• Stars
    star
    159
  • Rank 235,916 (Top 5 %)
  • Language
    Jupyter Notebook
  • License
    MIT License
  • Created over 5 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple backtesting software for options

Build Status

Options Backtester

Simple backtester to evaluate and analyse options strategies over historical price data.

Requirements

  • Python >= 3.6
  • pipenv

Setup

Install pipenv

$> pip install pipenv

Create environment and download dependencies

$> make install

Activate environment

$> make env

Run Jupyter notebook

$> make notebook

Run tests

$> make test

Usage

Sample backtest

You can run this example by putting the code into a Jupyter Notebook/Lab file in this directory.

import os
import sys

BACKTESTER_DIR = os.getcwd()
TEST_DATA_DIR = os.path.join(BACKTESTER_DIR, 'backtester', 'test', 'test_data')
SAMPLE_STOCK_DATA = os.path.join(TEST_DATA_DIR, 'test_data_stocks.csv')
SAMPLE_OPTIONS_DATA = os.path.join(TEST_DATA_DIR, 'test_data_options.csv')
from backtester import Backtest, Stock, Type, Direction
from backtester.datahandler import HistoricalOptionsData, TiingoData
from backtester.strategy import Strategy, StrategyLeg

First we construct an options datahandler.

options_data = HistoricalOptionsData(SAMPLE_OPTIONS_DATA)
options_schema = options_data.schema

Next, we'll create a toy options strategy. It will simply buy a call and a put with dte between $80$ and $52$ and exit them a month later.

sample_strategy = Strategy(options_schema)

leg1 = StrategyLeg('leg_1', options_schema, option_type=Type.CALL, direction=Direction.BUY)
leg1.entry_filter = (options_schema.dte < 80) & (options_schema.dte > 52)

leg1.exit_filter = (options_schema.dte <= 52)

leg2 = StrategyLeg('leg_2', options_schema, option_type=Type.PUT, direction=Direction.BUY) 
leg2.entry_filter = (options_schema.dte < 80) & (options_schema.dte > 52)

leg2.exit_filter = (options_schema.dte <= 52)

sample_strategy.add_legs([leg1, leg2]);

We do the same for stocks: create a datahandler together with a list of the stocks we want in our inventory and their corresponding weights. In this case, we will hold VOO, TUR and RSX, with $0.4$, $0.1$ and $0.5$ weights respectively.

stocks_data = TiingoData(SAMPLE_STOCK_DATA)
stocks = [Stock('VOO', 0.4), Stock('TUR', 0.1), Stock('RSX', 0.5)]

We set our portfolio allocation, i.e. how much of our capital will be invested in stocks, options and cash. We'll allocate 50% of our capital to stocks and the rest to options.

allocation = {'stocks': 0.5, 'options': 0.5, 'cash': 0.0}

Finally, we create the Backtest object.

bt = Backtest(allocation, initial_capital=1_000_000)

bt.stocks = stocks
bt.stocks_data = stocks_data

bt.options_strategy = sample_strategy
bt.options_data = options_data

And run the backtest with a rebalancing period of one month.

bt.run(rebalance_freq=1)
0% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100% | ETA: 00:00:00
Total time elapsed: 00:00:00
leg_1 leg_2 totals
contract underlying expiration type strike cost order contract underlying expiration type strike cost order cost qty date
0 SPX170317C00300000 SPX 2017-03-17 call 300 195010.0 Order.BTO SPX170317P00300000 SPX 2017-03-17 put 300 5.0 Order.BTO 195015.0 2.0 2017-01-03
1 SPX170317C00300000 SPX 2017-03-17 call 300 -197060.0 Order.STC SPX170317P00300000 SPX 2017-03-17 put 300 -0.0 Order.STC -197060.0 2.0 2017-02-01
2 SPX170421C00500000 SPX 2017-04-21 call 500 177260.0 Order.BTO SPX170421P01375000 SPX 2017-04-21 put 1375 60.0 Order.BTO 177320.0 2.0 2017-02-01
3 SPX170421C00500000 SPX 2017-04-21 call 500 -188980.0 Order.STC SPX170421P01375000 SPX 2017-04-21 put 1375 -5.0 Order.STC -188985.0 2.0 2017-03-01
4 SPX170519C01000000 SPX 2017-05-19 call 1000 138940.0 Order.BTO SPX170519P01650000 SPX 2017-05-19 put 1650 100.0 Order.BTO 139040.0 3.0 2017-03-01
5 SPX170519C01000000 SPX 2017-05-19 call 1000 -135290.0 Order.STC SPX170519P01650000 SPX 2017-05-19 put 1650 -20.0 Order.STC -135310.0 3.0 2017-04-03

The trade log (bt.trade_log) shows we executed 6 trades: we bought one call and one put on 2017-01-03, 2017-02-01 and 2017-03-01, and exited those positions on 2017-02-01, 2017-03-01 and 2017-04-03 respectively.

The balance data structure shows how our positions evolved over time:

  • We started with $1000000 on 2017-01-02
  • total capital is the sum of cash, stocks capital and options capital
  • % change shows the inter day change in total capital
  • accumulated return gives the compounded return in total capital since the start of the backtest
bt.balance.head()
total capital cash VOO TUR RSX options qty calls capital puts capital stocks qty VOO qty TUR qty RSX qty options capital stocks capital % change accumulated return
2017-01-02 1.000000e+06 1000000.00000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.0 0.000000 NaN NaN
2017-01-03 9.990300e+05 110117.40592 199872.763320 49993.281167 249986.549593 2.0 389060.0 0.0 16186.0 1025.0 1758.0 13403.0 389060.0 499852.594080 -0.000970 0.999030
2017-01-04 1.004228e+06 110117.40592 201052.238851 50072.862958 251605.333911 2.0 391380.0 0.0 16186.0 1025.0 1758.0 13403.0 391380.0 502730.435720 0.005203 1.004228
2017-01-05 1.002706e+06 110117.40592 200897.553535 49865.950301 250564.686850 2.0 391260.0 0.0 16186.0 1025.0 1758.0 13403.0 391260.0 501328.190686 -0.001516 1.002706
2017-01-06 1.003201e+06 110117.40592 201680.647945 49372.543196 248830.275081 2.0 393200.0 0.0 16186.0 1025.0 1758.0 13403.0 393200.0 499883.466222 0.000494 1.003201

Evolution of our total capital over time:

bt.balance['total capital'].plot();

png

Evolution of our stock positions over time:

bt.balance[[stock.symbol for stock in stocks]].plot();

png

More plots and statistics are available in the backtester.statistics module.

Other strategies

The Strategy and StrategyLeg classes allow for more complex strategies; for instance, a long strangle could be implemented like so:

# Long strangle
leg_1 = StrategyLeg('leg_1', options_schema, option_type=Type.PUT, direction=Direction.BUY)
leg_1.entry_filter = (options_schema.underlying == 'SPX') & (options_schema.dte >= 60) & (options_schema.underlying_last <= 1.1 * options_schema.strike)
leg_1.exit_filter = (options_schema.dte <= 30)

leg_2 = StrategyLeg('leg_2', options_schema, option_type=Type.CALL, direction=Direction.BUY)
leg_2.entry_filter = (options_schema.underlying == 'SPX') & (options_schema.dte >= 60) & (options_schema.underlying_last >= 0.9 * options_schema.strike)
leg_2.exit_filter = (options_schema.dte <= 30)

strategy = Strategy(options_schema)
strategy.add_legs([leg_1, leg_2]);

You can explore more usage examples in the Jupyter notebooks.

Recommended reading

For complete novices in finance and economics, this post gives a comprehensive introduction.

Books

Introductory

  • Option Volatility and Pricing 2nd Ed. - Natemberg, 2014
  • Options, Futures, and Other Derivatives 10th Ed. - Hull 2017
  • Trading Options Greeks: How Time, Volatility, and Other Pricing Factors Drive Profits 2nd Ed. - Passarelli 2012

Intermediate

  • Trading Volatility - Bennet 2014
  • Volatility Trading 2nd Ed. - Sinclair 2013

Advanced

  • Dynamic Hedging - Taleb 1997
  • The Volatility Surface: A Practitioner's Guide - Gatheral 2006
  • The Volatility Smile - Derman & Miller 2016

Papers

Data sources

Exchanges

Historical Data

More Repositories

1

lambdaworks

lambdaworks offers implementations for both SNARKs and STARKs provers, along with the flexibility to leverage their individual components for constructing customized SNARKs.
Rust
607
star
2

cairo-vm

cairo-vm is a Rust implementation of the Cairo VM. Cairo (CPU Algebraic Intermediate Representation) is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly without the need for this party to re-execute the same program.
Rust
514
star
3

lambdaclass_hacking_learning_path

LambdaClass Hobby Club, hacking learning path handbook. The journey starts here!
224
star
4

starknet_in_rust

A Rust implementation of Starknet execution logic
Rust
171
star
5

erlings

Small exercises to get you used to reading and writing Erlang code
Erlang
164
star
6

merkle_patricia_tree

Patricia Merkle Tree implementation in Rust
Rust
154
star
7

riak_core_tutorial

An up to date riak_core tutorial, using basho's riak_core, Erlang/OTP 23-24-25 and rebar3.
Erlang
149
star
8

STARK101-rs

STARK 101 Workshop in Rust ๐Ÿบ๐Ÿฆ€
Jupyter Notebook
131
star
9

sparkling_water_bootcamp

Public repository for excersices, challenges and all the needs of the Sparkling Water Bootcamp
123
star
10

concrete

Concrete is a simple programming language specifically crafted for creating highly scalable systems that are reliable, efficient, and easy to maintain.
Rust
123
star
11

cairo_native

A compiler to convert Cairo's intermediate representation "Sierra" code to MLIR.
Rust
115
star
12

ethereum_rust

Lambda Ethereum Rust Execution client
Rust
113
star
13

lambda_ethereum_consensus

Elixir implementation of an Ethereum consensus client, which offers high reliance & fault tolerance
Elixir
97
star
14

finance_playground

Juypter notebooks playground to explore and analyse economy and finance ideas
Jupyter Notebook
95
star
15

webrtc-server

Signaling and ICE servers for WebRTC in Erlang
Erlang
91
star
16

lambdaworks_stark_platinum

STARK Cairo prover using lambdaworks. Cairo (CPU Algebraic Intermediate Representation) is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly. Cairo and similar proof systems can be used to provide scalability to blockchains.
77
star
17

mina_bridge

Bridge from Mina to Ethereum
Solidity
76
star
18

evm_mlir

An EVM written with MLIR
Rust
73
star
19

AES_zero_knowledge_proof_circuit

Rust
70
star
20

holiday_pinger

Erlang + ClojureScript app to send holiday reminders
Erlang
69
star
21

stark_compass_explorer

Stark Compass: the only open source explorer
Elixir
68
star
22

mirra_backend

Multiplayer 2D physics engine, matchmaking, market and leaderboard for 2D and 3D Games
Elixir
61
star
23

erlang-katana

๐Ÿ‘Œ erlang grab bag of useful functions. it should have been called swiss army knife but katanas are more deadlier ;)
Erlang
61
star
24

cairo-vm_in_go

cairo-vm_in_go is a Go implementation of the Cairo VM. Cairo (CPU Algebraic Intermediate Representation) is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly without the need for this party to re-execute the same program.
Go
56
star
25

libtorrent-rs

A Rust implementation of the BitTorrent V2 protocol
Rust
55
star
26

yet-another-swap

YAS is Yet Another Swap on Starknet but bringing the best prices and yield to Degens.
Cairo
54
star
27

starknet_tendermint_sequencer

Starknet sequencer built with Tendermint Core
Rust
53
star
28

zksync_era_precompiles

Yul precompile library to speedup elliptic curves operations.
Rust
51
star
29

champions_of_mirra

Champions of Mirra game codebase
C#
42
star
30

circom_export_to_cairo

Export Circom verifier to Cairo
Solidity
42
star
31

starknet_stack

Starknet Stack let's you easily create new Cairo Starknet chains with their own sequencers, provers and verifiers
Rust
42
star
32

throttle

Erlang/OTP application to rate limit resource access
Erlang
40
star
33

cairo-by-example

cairo-by-example.com
Shell
38
star
34

pinocchio_lambda_vm

Zero Knowledge Virtual Machine from scratch implementing Pinocchio
Rust
36
star
35

buzzconf

A conference by devs for devs. Functional Programming, Distributed Systems, Big Data and Machine Learning Conference in Buenos Aires, Argentina
HTML
34
star
36

zksync-web3-rs

Rust
33
star
37

julia_koans

Small exercises to get you used to reading and writing Julia code!
Julia
31
star
38

noir_backend_using_gnark

A Noir's backend implementation using Gnark
Go
31
star
39

cairo-vm-py

cairo-rs-py adds Python bindings to the cairo-rs Cairo VM
Rust
23
star
40

lambdaworks_kzg

An ABI compatible for KZG EIP-4844 in Rust
Rust
22
star
41

aleo_lambda_vm

Arkworks implementation of the VM of Aleo verifiable computing model built by LambdaClass
Rust
21
star
42

simpleworks

Arkworks made simple for us: the non cryptographer software plumbers
Rust
20
star
43

era_vm

EraVM implementation
Rust
19
star
44

cairo-vm.c

cairo-vm_in_C is a C implementation of the Cairo VM. Cairo (CPU Algebraic Intermediate Representation) is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly without the need for this party to re-execute the same program.
C++
19
star
45

programming_bitcoin_in_rust

Implementing the book "Programming Bitcoin" in Rust
Rust
17
star
46

tornado_cash_anonymity_tool

Anonymity Research Tools for TCash Users
Jupyter Notebook
17
star
47

aleo_lambda_blockchain

Tendermint implementation of the blockchain of Aleo verifiable computing model built by LambdaClass
Rust
16
star
48

starknet_prover

15
star
49

lambdaworks_exercises

Contains several examples and challenges to use Lambdaworks
Rust
14
star
50

austral.rs

An implementation of the Austral language compiler in Rust
Rust
14
star
51

aleo_minimum_anti_collusion_infrastructure

Aleo's Minimum Anti-Collusion Infrastructure / MACI
Rust
13
star
52

starknet_rollup_on_bitcoin

Soverign rollup based on Rollkit, Cairo VM for the application layer and Bitcoin as a DA layer
Rust
13
star
53

lambda_consensus

Ethereum Consensus Client
12
star
54

starknet_kraken

Kraken is a Starknet modular decentralized sequencer implementation.
Rust
11
star
55

cairo_karnak

Cairo bytecode compiler
10
star
56

data_etudes

LambdaClass statistics, machine learning and data science etudes
Jupyter Notebook
10
star
57

reconnections

We were tired of implementing a reconnection system for our database clients so we created this
Erlang
10
star
58

find_peers

Find other erlang peers in the same subnet
Erlang
9
star
59

PLONK101-rs

9
star
60

elephant_in_the_room

Simple wordpress replacement coded in Elixir + Phoenix + Ecto + PostgreSQL + Docker
CSS
9
star
61

zksync_local_stack

Makefile
9
star
62

game_of_life_wasm

Conway's Game of Life in Rust and WebAssembly
Rust
8
star
63

elixir_riak_core

Wrapper to Riak Core for Elixir
Elixir
8
star
64

cairo_codegen-rs

A Rust library providing a builder API to generate Cairo code
8
star
65

zkRust

Rust
8
star
66

lambda_msm_fpga

Low level (VHDL) hardware description for MSM acceleration over FPGA
Python
8
star
67

curse_of_mirra_assets

Open source game assets: 3D models, 2d concept art, lore, music and more!
8
star
68

pinpon

๐Ÿ“ lambdaclass ping pong tournament and player ranking
Python
7
star
69

ieeextreme

Course material for students who want to go from zero to participating in the IEEExtreme competence using Python
Jupyter Notebook
7
star
70

entropy_hacking_learning_path

Entropy1729's Learning path
7
star
71

metal_playground

A repo for learning how to parallelize computations in the GPU using Apple's Metal, in Rust.
Rust
7
star
72

aleo_roulette

Elixir
6
star
73

cairo_finance

Cairo finance utilities
Cairo
6
star
74

lager_logstash_backend

Send lager logs to logstash
Erlang
6
star
75

lambdaworks_plonk_prover

6
star
76

bonobot

accept the mystery
Python
6
star
77

beam_prometheus_exporter

Add this to your release to get standard erlang metrics in prometheus/grafana
Erlang
6
star
78

million_requests_per_second

Trying to achieve a few millions requests per second with different languages, libraries and protocol
Ruby
6
star
79

mithril-oxide

Bindings to MLIR using the full C++ API
Rust
6
star
80

fuzzing_examples

A collection of fuzzers built using Honggfuzz and Cargofuzz tools
Rust
5
star
81

data_science_exercise

Data science exercise
Jupyter Notebook
5
star
82

blockaderl

Blockade docker API wrapper written in Erlang
Erlang
5
star
83

starknet_orb

5
star
84

ethereum_war_game_tooling

We are slow while using the UI/UX of crypto wallets so we created our CLI version
Elixir
5
star
85

zk_stack_cli

CLI tool for ZKsync, built using zksync-ethers-rs SDK
Rust
5
star
86

erlang_log_to_kibana_example

Redirect Erlang shell output to kibana via logstash
Shell
5
star
87

cairo-rs-wasm

Rust
5
star
88

starknet-replay

Provides a way of reading a real Starknet State, so you can re-execute an existing transaction in any of the Starknet networks in an easy way
Rust
5
star
89

aggregation_aligned_layer

Rust
4
star
90

guidelines

Design and coding standards for LambdaClass
4
star
91

tendermint_consensus

Tendermint Consensus is a minimalistic implementation of the BFT consensus algorithm to securely replicate state machines on multiple machines.
4
star
92

go-http-ipfs

HTTP server in Go to interact with a local IPFS node
Go
4
star
93

cairo_wnn

Cairo Weightless Neural Network
4
star
94

chaos_monkey_ex

A Chaos Monkey for Elixir that kills random processes
Elixir
3
star
95

wasm2cairo

3
star
96

merkletree_leo

3
star
97

concrete-ml-fuzzer

A differential fuzzer for `concrete-ml` and `scikit-learn`
Python
3
star
98

consensus-workbench

Proof of concept Rust implementations for various distributed systems protocols
Rust
3
star
99

lambcast

A Farcaster client implementation in Elixir
Elixir
3
star
100

zksync_seaport

Seaport implementation on zkSync Era. Seaport is a marketplace protocol for safely and efficiently buying and selling NFTs.
Solidity
3
star