Skip to content

Instantly share code, notes, and snippets.

@AnthonyFJGarner
Created April 11, 2022 12:20
Show Gist options
  • Save AnthonyFJGarner/7f4bc9513b167dd2683794bb42e7ea8b to your computer and use it in GitHub Desktop.
Save AnthonyFJGarner/7f4bc9513b167dd2683794bb42e7ea8b to your computer and use it in GitHub Desktop.
Conquer High Frequency Backtesting
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "d9f93c61-d8de-4dc1-9c8a-15f4dcb0bf1a",
"metadata": {},
"source": [
"## Conquer High Frequency Backtesting\n",
"[Conquer High Frequency Backtesting](https://medium.com/open-crypto-market-data-initiative/conquer-high-frequency-backtesting-a-quantitative-journey-part-v-d6797c98996f)\n",
"\n",
"Crypto Chassis, Medium. \n",
"Published in Open Crypto Trading Initiative. \n",
"Conquer High Frequency Backtesting: A Quantitative Journey, Part V"
]
},
{
"cell_type": "code",
"execution_count": 99,
"id": "58a276a8-a012-46a4-b9ef-e0aa699850c8",
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"import json\n",
"import pandas as pd\n",
"import gzip\n",
"import pathlib\n",
"import dateutil\n",
"import numpy as np\n",
"import sys\n",
"import pip"
]
},
{
"cell_type": "code",
"execution_count": 84,
"id": "0ed62838-a15c-447e-96aa-92a628065206",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" mid_price\n",
"time_seconds \n",
"1611187200 35493.970\n",
"1611187201 35491.085\n",
"1611187202 35493.695\n",
"1611187203 35502.295\n",
"1611187204 35512.420\n"
]
}
],
"source": [
"local_csv_name_1 = 'order_book_snapshot.csv'\n",
"local_csv_1 = pathlib.Path(local_csv_name_1)\n",
"if not local_csv_1.is_file():\n",
" r = requests.get(f'https://api.cryptochassis.com/v1/market-depth/coinbase/btc-usd?depth=1&startTime=2021-01-21')\n",
" file_url = r.json()['urls'][0]['url']\n",
" csv_string = gzip.decompress(requests.get(file_url).content).decode('utf-8')\n",
" with open(local_csv_1, 'w') as f:\n",
" f.write(csv_string)\n",
"df_1 = pd.read_csv(local_csv_name_1, index_col='time_seconds')\n",
"df_1[['bid_price','bid_size']] = df_1['bid_price_bid_size'].str.split(pat='_',expand=True).astype(float)\n",
"df_1[['ask_price','ask_size']] = df_1['ask_price_ask_size'].str.split(pat='_',expand=True).astype(float)\n",
"df_1['mid_price'] = (df_1['ask_price']+df_1['bid_price'])/2\n",
"df_1 = df_1[['mid_price']]\n",
"print(df_1.head())"
]
},
{
"cell_type": "code",
"execution_count": 85,
"id": "daa0c00b-7c5b-47f1-97c3-b998551f4f6b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" price is_buyer_maker\n",
"time_seconds \n",
"1611187200 35498.85 0\n",
"1611187200 35498.83 0\n",
"1611187200 35498.31 0\n",
"1611187200 35494.23 0\n",
"1611187201 35493.70 0\n"
]
}
],
"source": [
"local_csv_name_2 = 'trade.csv'\n",
"local_csv_2 = pathlib.Path(local_csv_name_2)\n",
"if not local_csv_2.is_file():\n",
" r = requests.get(f'https://api.cryptochassis.com/v1/trade/coinbase/btc-usd?startTime=2021-01-21')\n",
" file_url = r.json()['urls'][0]['url']\n",
" csv_string = gzip.decompress(requests.get(file_url).content).decode('utf-8')\n",
" with open(local_csv_2, 'w') as f:\n",
" f.write(csv_string)\n",
"df_2 = pd.read_csv(local_csv_name_2, index_col='time_seconds')\n",
"df_2 = df_2[['price', 'is_buyer_maker']]\n",
"print(df_2.head())"
]
},
{
"cell_type": "code",
"execution_count": 90,
"id": "f4cc7f75-bbdb-4004-b11b-6b097f597d30",
"metadata": {},
"outputs": [],
"source": [
"start_time_iso = '2021-01-21'"
]
},
{
"cell_type": "code",
"execution_count": 101,
"id": "99676d27-6aec-42e8-9d4c-90638793a743",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" time_seconds btc usd total\n",
"2876 1611273480 0.122 2833.211335 6592.858495\n",
"2877 1611273510 0.121 2863.985842 6587.328872\n",
"2878 1611273540 0.121 2863.992021 6601.932491\n",
"2879 1611273570 0.121 2863.998170 6584.236340\n",
"2880 1611273600 0.121 2864.004334 6593.022264\n"
]
}
],
"source": [
"period_seconds = 30\n",
"initial_start_time_seconds = int(\n",
" dateutil.parser.parse(start_time_iso).timestamp())\n",
"end_time_seconds = initial_start_time_seconds + 24 * 3600\n",
"spread_percentage = 0.02\n",
"our_order_quantity = 0.001\n",
"balance = {\n",
" 'time_seconds': [],\n",
" 'btc': [],\n",
" 'usd': [],\n",
" 'total': [],\n",
"}\n",
"balance['time_seconds'].append(\n",
" initial_start_time_seconds)\n",
"initial_btc_balance = our_order_quantity * 100\n",
"balance['btc'].append(\n",
" initial_btc_balance)\n",
"initial_btc_usd_price = df_1.head(\n",
" n=1).iloc[0]['mid_price']\n",
"initial_usd_balance = initial_btc_balance * \\\n",
" initial_btc_usd_price\n",
"balance['usd'].append(\n",
" initial_usd_balance)\n",
"balance['total'].append(\n",
" initial_btc_balance *\n",
" initial_btc_usd_price +\n",
" initial_usd_balance)\n",
"start_time_seconds = initial_start_time_seconds\n",
"while start_time_seconds < end_time_seconds:\n",
" #print(\n",
" # f\"replaying {pd.Timestamp(start_time_seconds, unit='s')} (unix timestamp {start_time_seconds})\")\n",
" mid_price = df_1[df_1.index <= start_time_seconds].tail(\n",
" n=1).iloc[0]['mid_price']\n",
" our_buy_order_price = mid_price * \\\n",
" (1 - spread_percentage / 100 / 2)\n",
" our_sell_order_price = mid_price * \\\n",
" (1 + spread_percentage / 100 / 2)\n",
" df_trade_price = df_2[(df_2.index >= start_time_seconds) & (\n",
" df_2.index < (start_time_seconds + period_seconds))]\n",
" trade_price_buyer_is_maker_lowest = df_trade_price[df_trade_price.is_buyer_maker == 1]['price'].min(\n",
" )\n",
" trade_price_buyer_is_taker_highest = df_trade_price[df_trade_price.is_buyer_maker == 0]['price'].max(\n",
" )\n",
" balance_btc_change = 0\n",
" balance_usd_change = 0\n",
" if not np.isnan(\n",
" trade_price_buyer_is_maker_lowest) and trade_price_buyer_is_maker_lowest <= our_buy_order_price:\n",
" balance_btc_change += our_order_quantity\n",
" balance_usd_change -= our_buy_order_price * \\\n",
" our_order_quantity\n",
" #print(\n",
" #f'filled our buy order at price {our_buy_order_price}')\n",
" if not np.isnan(\n",
" trade_price_buyer_is_taker_highest) and trade_price_buyer_is_taker_highest >= our_sell_order_price:\n",
" balance_btc_change -= our_order_quantity\n",
" balance_usd_change += our_sell_order_price * \\\n",
" our_order_quantity\n",
" #print(\n",
" #f'filled our sell order at price {our_sell_order_price}')\n",
" start_time_seconds += period_seconds\n",
" balance['time_seconds'].append(\n",
" start_time_seconds)\n",
" btc_balance = balance['btc'][-1] + \\\n",
" balance_btc_change\n",
" usd_balance = balance['usd'][-1] + \\\n",
" balance_usd_change\n",
" balance['btc'].append(btc_balance)\n",
" balance['usd'].append(usd_balance)\n",
" balance['total'].append(\n",
" btc_balance *\n",
" mid_price +\n",
" usd_balance)\n",
"print(pd.DataFrame(balance).tail())"
]
},
{
"cell_type": "markdown",
"id": "3d1230be-5ab9-45f9-a45b-c51bcbdeb2f0",
"metadata": {},
"source": [
"## Python Version and Libraries with Versions"
]
},
{
"cell_type": "raw",
"id": "e262fcfb-6454-4cf6-838d-ecc6faece97c",
"metadata": {},
"source": [
"sys.version,sys.version_info\n",
"\n",
"('3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]', sys.version_info(major=3, minor=9, micro=12, releaselevel='final', serial=0))\n",
"\n",
"%pip list\n",
"Package Version\n",
"-------------------- ---------\n",
"anyio 3.5.0\n",
"argon2-cffi 21.3.0\n",
"argon2-cffi-bindings 21.2.0\n",
"Note: you may need to restart the kernel to use updated packages.\n",
"asttokens 2.0.5\n",
"attrs 21.4.0\n",
"Babel 2.9.1\n",
"backcall 0.2.0\n",
"beautifulsoup4 4.11.1\n",
"bleach 5.0.0\n",
"Bottleneck 1.3.4\n",
"brotlipy 0.7.0\n",
"certifi 2021.10.8\n",
"cffi 1.15.0\n",
"charset-normalizer 2.0.4\n",
"colorama 0.4.4\n",
"cryptography 36.0.0\n",
"debugpy 1.5.1\n",
"decorator 5.1.1\n",
"defusedxml 0.7.1\n",
"entrypoints 0.3\n",
"executing 0.8.3\n",
"fastjsonschema 2.15.3\n",
"flit_core 3.7.1\n",
"idna 3.3\n",
"importlib-metadata 4.11.3\n",
"importlib-resources 5.6.0\n",
"ipykernel 6.9.1\n",
"ipython 8.2.0\n",
"ipython-genutils 0.2.0\n",
"jedi 0.18.1\n",
"Jinja2 3.1.1\n",
"json5 0.9.5\n",
"jsonschema 4.4.0\n",
"jupyter-client 7.1.2\n",
"jupyter-core 4.9.2\n",
"jupyter-server 1.16.0\n",
"jupyterlab 3.3.3\n",
"jupyterlab-pygments 0.2.0\n",
"jupyterlab-server 2.12.0\n",
"MarkupSafe 2.1.1\n",
"matplotlib-inline 0.1.2\n",
"mistune 0.8.4\n",
"mkl-fft 1.3.1\n",
"mkl-random 1.2.2\n",
"mkl-service 2.4.0\n",
"nbclassic 0.3.7\n",
"nbclient 0.5.13\n",
"nbconvert 6.4.5\n",
"nbformat 5.3.0\n",
"nest-asyncio 1.5.1\n",
"notebook 6.4.10\n",
"notebook-shim 0.1.0\n",
"numexpr 2.8.1\n",
"numpy 1.21.5\n",
"packaging 21.3\n",
"pandas 1.4.1\n",
"pandocfilters 1.5.0\n",
"parso 0.8.3\n",
"pickleshare 0.7.5\n",
"pip 21.2.4\n",
"prometheus-client 0.14.1\n",
"prompt-toolkit 3.0.20\n",
"pure-eval 0.2.2\n",
"pycparser 2.21\n",
"Pygments 2.11.2\n",
"pyOpenSSL 22.0.0\n",
"pyparsing 3.0.4\n",
"pyrsistent 0.18.1\n",
"PySocks 1.7.1\n",
"python-dateutil 2.8.2\n",
"pytz 2021.3\n",
"pywin32 302\n",
"pywinpty 2.0.2\n",
"pyzmq 22.3.0\n",
"requests 2.27.1\n",
"Send2Trash 1.8.0\n",
"setuptools 58.0.4\n",
"six 1.16.0\n",
"sniffio 1.2.0\n",
"soupsieve 2.3.1\n",
"stack-data 0.2.0\n",
"terminado 0.13.1\n",
"testpath 0.6.0\n",
"tornado 6.1\n",
"traitlets 5.1.1\n",
"urllib3 1.26.8\n",
"wcwidth 0.2.5\n",
"webencodings 0.5.1\n",
"websocket-client 1.3.2\n",
"wheel 0.37.1\n",
"win-inet-pton 1.1.0\n",
"wincertstore 0.2\n",
"zipp 3.8.0​"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d3cf656-b370-49ff-a06f-8db486d82ecb",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "crypto-kernel",
"language": "python",
"name": "crypto-kernel"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@AnthonyFJGarner
Copy link
Author

sys.version,sys.version_info

('3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]', sys.version_info(major=3, minor=9, micro=12, releaselevel='final', serial=0))

%pip list
Package Version


anyio 3.5.0
argon2-cffi 21.3.0
argon2-cffi-bindings 21.2.0
Note: you may need to restart the kernel to use updated packages.
asttokens 2.0.5
attrs 21.4.0
Babel 2.9.1
backcall 0.2.0
beautifulsoup4 4.11.1
bleach 5.0.0
Bottleneck 1.3.4
brotlipy 0.7.0
certifi 2021.10.8
cffi 1.15.0
charset-normalizer 2.0.4
colorama 0.4.4
cryptography 36.0.0
debugpy 1.5.1
decorator 5.1.1
defusedxml 0.7.1
entrypoints 0.3
executing 0.8.3
fastjsonschema 2.15.3
flit_core 3.7.1
idna 3.3
importlib-metadata 4.11.3
importlib-resources 5.6.0
ipykernel 6.9.1
ipython 8.2.0
ipython-genutils 0.2.0
jedi 0.18.1
Jinja2 3.1.1
json5 0.9.5
jsonschema 4.4.0
jupyter-client 7.1.2
jupyter-core 4.9.2
jupyter-server 1.16.0
jupyterlab 3.3.3
jupyterlab-pygments 0.2.0
jupyterlab-server 2.12.0
MarkupSafe 2.1.1
matplotlib-inline 0.1.2
mistune 0.8.4
mkl-fft 1.3.1
mkl-random 1.2.2
mkl-service 2.4.0
nbclassic 0.3.7
nbclient 0.5.13
nbconvert 6.4.5
nbformat 5.3.0
nest-asyncio 1.5.1
notebook 6.4.10
notebook-shim 0.1.0
numexpr 2.8.1
numpy 1.21.5
packaging 21.3
pandas 1.4.1
pandocfilters 1.5.0
parso 0.8.3
pickleshare 0.7.5
pip 21.2.4
prometheus-client 0.14.1
prompt-toolkit 3.0.20
pure-eval 0.2.2
pycparser 2.21
Pygments 2.11.2
pyOpenSSL 22.0.0
pyparsing 3.0.4
pyrsistent 0.18.1
PySocks 1.7.1
python-dateutil 2.8.2
pytz 2021.3
pywin32 302
pywinpty 2.0.2
pyzmq 22.3.0
requests 2.27.1
Send2Trash 1.8.0
setuptools 58.0.4
six 1.16.0
sniffio 1.2.0
soupsieve 2.3.1
stack-data 0.2.0
terminado 0.13.1
testpath 0.6.0
tornado 6.1
traitlets 5.1.1
urllib3 1.26.8
wcwidth 0.2.5
webencodings 0.5.1
websocket-client 1.3.2
wheel 0.37.1
win-inet-pton 1.1.0
wincertstore 0.2
zipp 3.8.0​

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment