Skip to main content

Composable financial contracts with Monte Carlo valuation

Project description

Monte Carlo Contracts

PyPI package Build status

A Python library to compose complex fincancial products from elementary contracts.

This is what it looks like (see Minimal.ipynb for the full example):

ko_option = Until(
    Stock("ABC Eqty") > 70,
    When(
        At(np.datetime64("2024-06-01")),
        Or(Stock("ABC Eqty") * One("USD") - 55 * One("USD"), Zero()),
    ),
)

evaluate(model, ko_option)
# 3.2316051920219797

Minimal example plots

This library employs ideas from How to Write a Financial Contract by S. L. Peyton Jones and J-M. Eber. However, the implementation is not based on functional programming but rather using an object oriented approach. Also, this implementation is tailored towards Monte Carlo based cashflow generation whereas the paper favours more general methods.

For an introduction to the concepts of composable contracts and usage instructions of this library, see the Introduction notebook.

Features

  • Composition of financial contracts using elementary contracts Zero, One, Give, Scale, And, When, Cond, Anytime, Until, Delay and Exchange.
  • Boolean and real valued observables (stochastic processes) to be referenced by contracts.
  • Cashflow generation for composed contracts given simulation models on fixed dategrids.

Non-Features

  • Financial products description language. This library provides classes to describe financial contracts at a low level; a high level description language could be translated into this low level language, but not the other way round.
  • Lifecycle management. Capturing past lifecycle events of financial products such as call rights, knockouts or even fixings is left to a high level description. Doing it here would be very hard due to the nature of the acquisition date free variable and the lack of mandatory start / end dates in particular. Just think about a simple contract such as When(Stock("ABC") > 100, One("EUR")). Which fixings would you require? Up to which point would you perform model simulation?
  • Pricing methods other than Monte Carlo Simulation. While composable contract representations do not force Monte Carlo methods, this library is designed exclusively for them. Supporting other methods would likely require a separation of contracts and the operations defined on them, e.g. by means of the visitor pattern. In How to Write a Financial Contract, Peyton Jones and Eber favour implementation in functional programming languages where this separation is achieved more naturally.

Examples

Install

With Python 3.8+ on your machine, you can install monte-carlo-contracts using pip by running (ideally in a virtual environment)

pip install monte-carlo-contracts

which will automatically install the hard dependencies numpy and pandas.

For development or running the examples, you may instead want to run

pip install -e .

and then

pip install -r requirements_dev.txt

from the root directory of this repository.

Available Contracts and Observables

Contract Description
Contract Abstract base class for all contracts
Zero Neither receive nor pay anything
One Receive one unit of currency at acquisition
Give Receive all obligations of the underlying contract and pay all rights, i.e. invert the underlying contract
And Obtain rights and obligations of all underlying contracts
Or Choose at acquisition between the underlying contracts
Cond If observable is True at acquisition, obtain contract1, otherwise contract2
Scale Same as the underling contract, but all payments scaled by the value of observable at acquisition
When Obtain the underlying contract as soon as observable becomes True after acquisition
Delay Obtain the underlying contract and delay all payments to first occurence of observable.
Anytime At any point in time after acquisition when observable is True, choose whether to obtain the underlying contract or not; can be exercised only once
Until Obtain the underlying contract, but as soon as observable becomes True after acquisition all following payments are nullified
Exchange Exchange cashflows resulting from contract to currency at the current spot rate
Boolean Observable Description
ObservableBool Abstract base class for all observables of underlying type bool
Not True if observable is False and vice versa
AndObservable True if and only if both observables are True
OrObservable True if either or both observable are True
GreaterOrEqualThan True if and only if observable1 is greater or equal than observable2
GreaterThan True if and only if observable1 is strictly greater than observable2
At True only at date
Float Observable Description
ObservableFloat Abstract base class for all observables of underlying type float, essentially a real-valued stochastic process
Sum Equal to the sum of two observables
Minus Negative value of observable
Product Equal to the product (multiplication) of two observables
Quotient Equal to the quotient (division) of two observables
Power Equal to observable1 to the power of observable2
Maximum Equal to the maximum of two observables
Minimum Equal to the minimum of two observables
RunningMax Running maximum of observable over time, seen from first_observation_idx.
RunningMin Running minimum of observable over time, seen from first_observation_idx.
FixedAfter Equal to observable, but remains constant as soon as fixing_condition becomes true after (including) first_observation_idx.
Stock Value of the stock identified by identifier
FX Value of the currency spot between base_currency and counter_currency, i.e. 'one unit counter_currency' / 'one unit of base_currency'
LinearRate Value of the linear rate (e.g. a LIBOR) with payment frequency in currency
KonstFloat Always equal to constant

History

See HISTORY.md.

Credits

Main developer is luphord luphord@protonmail.com.

cookiecutter-pyscript was used as project template, but the repository structure has evolved considerably.

History

Some future version (not yet)

  • ToDo: Observables Sum, Product, Maximum, Minimum, AndObservable and OrObservable accept more than two contracts to be combined
  • ToDo: Add JSON (de)serialization for contracts and observables
  • ToDo: Add Jupyter based treeview for contracts and observables
  • ToDo: Implement cashflow generation for Or contract with future payment dates
  • ToDo: Implement cashflow generation for Anytime contract (using Longstaff-Schwartz approach)
  • ToDo: Implement get_model_requirements for all observables and contracts
  • ToDo: Add a "test model" working for arbitrary underlyings to analyze contracts
  • ToDO: fix Ho-Lee-Model
  • ToDo: Use instances of a Currency class instead of strings to describe currencies
  • ToDo: Add documentation about the concepts of contracts, observables and acquisition dates
  • ToDo: Document financial products lifecycle aspects and their relationship to composable contracts
  • ToDo: Add labels to contracts which are forwarded to simulated cashflows
  • ToDo: Add documentation about models in Introduction notebook

0.10.0 (2022-04-03)

  • Add new Exchange(currency, contract) contract
  • Modify FX options examples to use Exchange for cash settlement
  • Add observables and contracts overview to package doc, as well as to Introduction notebook

0.9.0 (2023-03-26)

  • BREAKING CHANGE Convenvience methods generate_cashflows, generate_simple_cashflows, generate_simple_cashflows_in_currency, generate_simple_cashflows_in_numeraire_currency and evaluate that used to be defined on Model are now standalone functions that accept a model instance as first argument; i.e. instead of model.evaluate(contract) you now do evaluate(model, contract)
  • BREAKING CHANGE Pricing model implementations (at the moment HoLee and simulate_equity_black_scholes_model) now need to be imported from mcc.pricing_models; stochastic processes (at the moment BrownianMotion and GeometricBrownianMotion) need to be imported from mcc.pricing_models.stochastic_processes
  • Split mcc.py into multiple modules forming package mcc; imports will continue to work as before except for the exceptions listed above
  • Split tests into multiple smaller modules with more specific focus
  • Support Python 3.11
  • Upgrade (dev) dependencies
  • Development Status :: 3 - Alpha
  • BREAKING CHANGE: Remove CLI stub (there was no real CLI functionality anyway)

0.8.0 (2023-03-20)

  • BREAKING CHANGE: Contract now inherits from ResolvableContract instead of the other way round
  • BREAKING CHANGE: And and Or contracts now accept more than two contracts to be combined; these have equivalent semantics to nested And or Or contracts and allow for flat structures to improve readability
  • Add Delay(observableBool, contract) contract to delay cashflows to a later point in time (main use case is FX payment offset)
  • First steps towards model requirements (yet incomplete)
  • Fix cashflow generation for nested contracts

0.7.0 (2022-03-13)

  • BREAKING CHANGE: ObservableFloat.simulate and ObservableBool.simulate now accept a DateIndex first_observation_idx as first argument, Contract classes will pass acquisition_idx; this allows observations to depend on the time of entering a contract, e.g. "maximum spot since acquisition"
  • BREAKING CHANGE: FixedAfter fixes composed observable after (including) first_observation_idx, not from the beginning
  • Add operator overloading for Contract classes, i.e. you can now do One("USD") - One("EUR") | 1.2 * One("GBP") instead of Or(And(One("USD"), Give(One("EUR"))), Scale(1.2, One("GBP")))
  • Maximum and Minimum observables to observe the larger and smaller value of two observables at the same time on the same path
  • RunningMax and RunningMin observables to observe running extreme values from first_observation_idx onwards
  • Support Python 3.10
  • Make use of type annotations added to numpy

0.6.0 (2022-03-04)

  • BREAKING CHANGE: Make SimpleCashflows a pandas.DataFrame
  • Run notebooks in automated tests using nbval
  • Migrate from travis-ci to GitHub Actions
  • Explicitly support Python 3.8 and 3.9
  • Move history to HISTORY.md

0.5.0 (2020-11-08)

  • BREAKING CHANGE: Add simulated_rates to Model (included in constructor); pass an empty dict for simulated_rates to adapt your code
  • BREAKING CHANGE: BrownianMotion and GeometricBrownianMotion generalized to dynamic mean/drift; pass mu_t = lambda t: mu * t to adapt your code
  • LinearRate observable supported by TermStructureModel
  • First steps towards term structure models
  • FixedAfter observable to keep an observable fixed after a condition is true
  • Observables support arithmetic operations (binary +, -, *, /, ** and unary -) with other observables as well as constants (also right operators work)
  • Working with Observables example notebook

0.4.0 (2020-11-04)

  • Discounting (Model.discount)
  • Evaluation (Model.evaluate)
  • String representations for contracts and observables

0.3.0 (2020-10-23)

  • Simulation of basic contract Until
  • Currency conversion of IndexedCashflows
  • Or contract supports multiple currencies
  • ObservableFloat supports <, <=, > and >= operators with float or other ObservableFloat instances
  • ObservableBool supports ~, & and | operators for combined conditions
  • Equity Options and FX Options examples

0.2.0 (2020-10-11)

  • Simulation of basic contracts Zero, One, Give, Scale, And, When and Cond
  • Partial simulation of Or contract
  • Float observables Stock and FX
  • Boolean observables At
  • SimulatedCashflows and model-bound IndexedCashflows to represent cashflows
  • Basic Model allowing the generation of cashflows for the contracts above

0.1.0 (2020-09-22)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

monte-carlo-contracts-0.10.0.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

monte_carlo_contracts-0.10.0-py2.py3-none-any.whl (26.8 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file monte-carlo-contracts-0.10.0.tar.gz.

File metadata

File hashes

Hashes for monte-carlo-contracts-0.10.0.tar.gz
Algorithm Hash digest
SHA256 9c60ee42bd20f91927db5c0673534c72753799b79f1a25ef66e9f929479215c9
MD5 5dc7cc2ff010cfcf0935ea59902dd655
BLAKE2b-256 e133c6ee473ef1400772bd7ab35bef402dad58341505085c0348d76c08937165

See more details on using hashes here.

File details

Details for the file monte_carlo_contracts-0.10.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for monte_carlo_contracts-0.10.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 63da74cbebb26c13a287ab2c756108018bc64397916b0cb95f43aca841b69790
MD5 488078eb77b708c9aa4bf26ad2f2884e
BLAKE2b-256 77dd5f0a0d0a5a2031b9f6e2f695e17d7895d1a1a4ea87603d47e8e6a5d6c072

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page