Skip to content

Commit

Permalink
Merge 86b72d3 into 5025eb1
Browse files Browse the repository at this point in the history
  • Loading branch information
johnbywater committed Sep 19, 2017
2 parents 5025eb1 + 86b72d3 commit 223bea9
Show file tree
Hide file tree
Showing 60 changed files with 1,629 additions and 1,683 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ omit =
*/python?.?/*
*/test_?.py
*/tests/*
*/quantdsl/lib/*
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"

before_install:
- travis_retry wget http://repo.continuum.io/miniconda/Miniconda-3.8.3-Linux-x86_64.sh -O miniconda.sh
Expand Down
262 changes: 143 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
## Install

Use pip to install the [latest distribution](https://pypi.python.org/pypi/quantdsl) from
the Python Package Index.
the Python Package Index. To avoid disturbing your system's site packages, it is recommended to install
into a new virtual Python environment, using [Virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/).

```
pip install --upgrade pip
Expand All @@ -17,40 +18,6 @@ pip install quantdsl

Please register any [issues on GitHub](https://github.com/johnbywater/quantdsl/issues).

To avoid disturbing your system's site packages, it is recommended to install
into a new virtual Python environment, using [Virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/).

If you are working on a corporate LAN, with an HTTP proxy that requires authentication, then pip may fail to find
the Python Package Index. In this case you may need to download the distribution (and dependencies) by hand, and
then use the path to the downloaded files instead of the package name in the `pip` command:

```
pip install ~/Downloads/quantdsl-X.X.X.tar.gz
```

### Trouble building NumPy and SciPy?

This package depends on [SciPy](https://www.scipy.org/), which depends on [NumPy](http://www.numpy.org/).

Both should be automatically installed as Python dependencies, however they depend on compilers being available on
your system.

On GNU/Linux systems you may need to install developer tools (e.g. ```build-essential``` on Debian). If
you don't want to build the binaries, you can just install NumPy and SciPy as system packages and create a Python
virtual environment that uses system site packages (`--system-site-packages`).

Similarly, OSX users may benefit from reading [this page](https://www.scipy.org/scipylib/building/macosx.html):
install Apple’s Developer Tools, then install the Fortran compiler binary. Then you should be able
to install NumPy and SciPy using pip.

Windows users may also not be able to install NumPy and SciPy because they do not have a
compiler installed. Obtaining one that works can be frustrating. If so, one solution would
be to install the [PythonXY](https://code.google.com/p/pythonxy/wiki/Downloads?tm=2)
distribution of Python, so that you have NumPy and SciPy - other distributions are available.
Then create a virtual environment with the `--system-site-packages` option of `virtualenv`
so that NumPy and SciPy will be available in your virtual environment. If you get bogged down,
the simpler alternative is to install *Quant DSL* directly into your PythonXY installation,
using `pip install quantdsl` or `easy_install quantdsl` if `pip` is not available.

## Overview

Expand All @@ -61,120 +28,177 @@ maths used in finance and trading. The elements of the language can be freely co
of value. User defined functions generate extensive dependency graphs that effectively model and evaluate exotic
derivatives.

## Definition and implementation

The syntax of Quant DSL expressions has been
[formally defined](http://www.appropriatesoftware.org/quant/docs/quant-dsl-definition-and-proof.pdf),
the semantic model is supported with mathematical proofs. The syntax is a strict subset of the Python language
syntax. This package is an implementation of the language in Python. At this time, we are not aware of any
other implementation of Quant DSL, in Python or in any other language.
the semantic model is supported with mathematical proofs.

This package is an implementation of the language in Python. Function definitions are also supported, to ease
construction of Quant DSL expressions. The import statement is also supported to allow function definitions to be
used from a library (see below).

## Usage
Steps for evaluating a contract include: specification of a model of a contract; calibration of a stochastic process
for the underlying prices; simulation using the price process of future prices underlying the contract; and evaluation
of the contract model against the simulation.

To create a working program, you can copy and paste the following code snippets into a single Python file. The code
snippets in this section have been tested. Please feel free to experiment by making variations.
The library provides an application class `QuantDslApplication` which
has methods that support these steps: `compile()`, `simulate()` and `evaluate()`.

If you are using a Python virtualenv, please check that your virtualenv is activated before installing the library
and running your program.
The library also provides a convenience function `calc()` uses those methods of that application to evaluate
contracts.

Let's jump in at the deep-end with a simple model of a gas-fired power station.

```python
source_code = """
PowerStation(Date('2012-01-01'), Date('2012-01-13'), Market('GAS'), Market('POWER'), Stopped(1))
def PowerStation(start, end, gas, power, duration_off):
if (start < end):
Wait(start,
Choice(
ProfitFromRunning(gas, power, duration_off) + PowerStation(
Tomorrow(start), end, gas, power, Running()
),
PowerStation(
Tomorrow(start), end, gas, power, Stopped(duration_off)
)
)
)
else:
return 0

@inline
def ProfitFromRunning(gas, power, duration_off):
if duration_off > 1:
return 0.75 * power - gas
elif duration_off == 1:
return 0.90 * power - gas
else:
return 1.00 * power - gas
## Example of usage

@inline
def Running():
return 0
The examples below use the library function `calc()` to evaluate contracts.

@inline
def Stopped(duration_off):
return duration_off + 1

@inline
def Tomorrow(today):
return today + TimeDelta('1d')
"""
```python
from quantdsl.interfaces.calcandplot import calc_and_plot
```

Construct a Quant DSL application object.
### Gas Storage

Here's an evaluation of a gas storage facility.

```python
from quantdsl.application.with_pythonobjects import QuantDslApplicationWithPythonObjects
calc_and_plot(
title="Gas Storage",

source_code="""
def GasStorage(start, end, commodity_name, quantity, target, limit, step, period):
if ((start < end) and (limit > 0)):
if quantity <= 0:
return Wait(start, Choice(
Continue(start, end, commodity_name, quantity, limit, step, period, target),
Inject(start, end, commodity_name, quantity, limit, step, period, target, 1),
))
elif quantity >= limit:
return Wait(start, Choice(
Continue(start, end, commodity_name, quantity, limit, step, period, target),
Inject(start, end, commodity_name, quantity, limit, step, period, target, -1),
))
else:
return Wait(start, Choice(
Continue(start, end, commodity_name, quantity, limit, step, period, target),
Inject(start, end, commodity_name, quantity, limit, step, period, target, 1),
Inject(start, end, commodity_name, quantity, limit, step, period, target, -1),
))
else:
if target < 0 or target == quantity:
return 0
else:
return BreachOfContract()
app = QuantDslApplicationWithPythonObjects()
```
Compile the module into a dependency graph.
@inline
def BreachOfContract():
-10000000000000000
```python
contract_specification = app.compile(source_code)
```
@inline
def Continue(start, end, commodity_name, quantity, limit, step, period, target):
GasStorage(start + step, end, commodity_name, quantity, target, limit, step, period)
Calibrate from historical data. In this example, we can just register some calibration parameters.
```python
price_process_name = 'quantdsl.priceprocess.blackscholes.BlackScholesPriceProcess'

calibration_params = {
'GAS-LAST-PRICE': 10,
'POWER-LAST-PRICE': 11,
'GAS-ACTUAL-HISTORICAL-VOLATILITY': 30,
'POWER-ACTUAL-HISTORICAL-VOLATILITY': 20,
'GAS-POWER-CORRELATION': 0.4,
}

market_calibration = app.register_market_calibration(
price_process_name,
calibration_params
)
```
@inline
def Inject(start, end, commodity_name, quantity, limit, step, period, target, vol):
Continue(start, end, commodity_name, quantity + vol, limit, step, period, target) - \
vol * Lift(commodity_name, period, Market(commodity_name))
Make a simulation from the calibration.
```python
import datetime
GasStorage(Date('2011-6-1'), Date('2011-9-1'), 'GAS', 0, 0, 50000, TimeDelta('1m'), 'monthly')
""",

market_simulation = app.simulate(
contract_specification,
market_calibration,
observation_date='2011-1-1',
interest_rate=2.5,
path_count=20000,
observation_date=datetime.datetime(2011, 1, 1)
perturbation_factor=0.01,
periodisation='monthly',

price_process={
'name': 'quantdsl.priceprocess.blackscholes.BlackScholesPriceProcess',
'market': ['GAS'],
'sigma': [0.5],
'alpha': [0.1],
'rho': [[1.0]],
'curve': {
'GAS': (
('2011-1-1', 13.5),
('2011-2-1', 11.0),
('2011-3-1', 10.0),
('2011-4-1', 9.0),
('2011-5-1', 7.5),
('2011-6-1', 7.0),
('2011-7-1', 6.5),
('2011-8-1', 7.5),
('2011-9-1', 8.5),
('2011-10-1', 10.0),
('2011-11-1', 11.5),
('2011-12-1', 12.0),
('2012-1-1', 13.5),
('2012-2-1', 11.0),
('2012-3-1', 10.0),
('2012-4-1', 9.0),
('2012-5-1', 7.5),
('2012-6-1', 7.0),
('2012-7-1', 6.5),
('2012-8-1', 7.5),
('2012-9-1', 8.5),
('2012-10-1', 10.0),
('2012-11-1', 11.5),
('2012-12-1', 12.0)
)
}
}
)

```

Make an evaluation using the simulation.
### Power Station

Here's an evaluation of a power station. This time, the source code imports a power station model from the library.

```python
valuation = app.evaluate(contract_specification, market_simulation)
```
calc_and_plot(
title="Power Station",

Inspect the estimated value.
source_code="""from quantdsl.lib.powerplant2 import PowerPlant, Running
PowerPlant(Date('2011-1-1'), Date('2011-1-6'), Running())
""",

observation_date='2011-1-1',
interest_rate=2.5,
path_count=20000,
perturbation_factor=0.01,
periodisation='monthly',

price_process={
'name': 'quantdsl.priceprocess.blackscholes.BlackScholesPriceProcess',
'market': ['GAS', 'POWER'],
'sigma': [0.5, 0.3],
'rho': [[1.0, 0.8], [0.8, 1.0]],
'curve': {
'GAS': [
('2011-1-1', 13.5),
('2011-2-1', 11.0),
('2011-3-1', 10.0),
('2011-4-1', 9.0),
('2011-5-1', 7.5),
('2011-6-1', 7.0),
],
'POWER': [
('2011-1-1', 13.5),
('2011-2-1', 11.0),
('2011-3-1', 10.0),
('2011-4-1', 9.0),
('2011-5-1', 7.5),
('2011-6-1', 7.0),
]
}
}
)

```python
estimated_value = app.get_result(valuation).result_value.mean()
assert 17 < estimated_value < 18, estimated_value
```
1 change: 0 additions & 1 deletion quantdsl/application/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
__author__ = 'john'
Loading

0 comments on commit 223bea9

Please sign in to comment.