Skip to content

Instantly share code, notes, and snippets.

@hsm207
Created November 14, 2020 08:08
Show Gist options
  • Save hsm207/db00a8102889dfce269c2d66a118071b to your computer and use it in GitHub Desktop.
Save hsm207/db00a8102889dfce269c2d66a118071b to your computer and use it in GitHub Desktop.
Zipline futures bug
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"<string>:13: UserWarning: Overwriting bundle with name 'random_futures'\n"
]
},
{
"ename": "KeyError",
"evalue": "<class 'zipline.assets.continuous_futures.ContinuousFuture'>",
"output_type": "error",
"traceback": [
"\u001b[0;31m-----------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0mTraceback (most recent call last)",
"\u001b[0;32m<ipython-input-3-99c44213dbe4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[0mcapital_base\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstarting_portfolio\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 210\u001b[0m \u001b[0mdata_frequency\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"daily\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 211\u001b[0;31m \u001b[0mbundle\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"random_futures\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 212\u001b[0m )\n",
"\u001b[0;32m/zipline/zipline/utils/run_algo.py\u001b[0m in \u001b[0;36mrun_algorithm\u001b[0;34m(start, end, initialize, capital_base, handle_data, before_trading_start, analyze, data_frequency, bundle, bundle_timestamp, trading_calendar, metrics_set, benchmark_returns, default_extension, extensions, strict_extensions, environ, blotter)\u001b[0m\n\u001b[1;32m 407\u001b[0m \u001b[0menviron\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0menviron\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 408\u001b[0m \u001b[0mblotter\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mblotter\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 409\u001b[0;31m \u001b[0mbenchmark_spec\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbenchmark_spec\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 410\u001b[0m )\n\u001b[1;32m 411\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/utils/run_algo.py\u001b[0m in \u001b[0;36m_run\u001b[0;34m(handle_data, initialize, before_trading_start, analyze, algofile, algotext, defines, data_frequency, capital_base, bundle, bundle_timestamp, start, end, output, trading_calendar, print_algo, metrics_set, local_namespace, environ, blotter, benchmark_spec)\u001b[0m\n\u001b[1;32m 214\u001b[0m \u001b[0;34m}\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0malgotext\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 215\u001b[0m \u001b[0;34m'algo_filename'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0malgofile\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'name'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'<algorithm>'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 216\u001b[0;31m \u001b[0;34m'script'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0malgotext\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 217\u001b[0m }\n\u001b[1;32m 218\u001b[0m ).run()\n",
"\u001b[0;32m/zipline/zipline/algorithm.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, data_portal)\u001b[0m\n\u001b[1;32m 641\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 642\u001b[0m \u001b[0mperfs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 643\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mperf\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_generator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 644\u001b[0m \u001b[0mperfs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 645\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/gens/tradesimulation.py\u001b[0m in \u001b[0;36mtransform\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 203\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maction\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclock\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0maction\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mBAR\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 205\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mcapital_change_packet\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mevery_bar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 206\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mcapital_change_packet\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 207\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0maction\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mSESSION_START\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/gens/tradesimulation.py\u001b[0m in \u001b[0;36mevery_bar\u001b[0;34m(dt_to_use, current_data, handle_data)\u001b[0m\n\u001b[1;32m 131\u001b[0m \u001b[0mmetrics_tracker\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprocess_commission\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcommission\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 132\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 133\u001b[0;31m \u001b[0mhandle_data\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0malgo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcurrent_data\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdt_to_use\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 134\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 135\u001b[0m \u001b[0;31m# grab any new orders from the blotter, then clear the list.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/utils/events.py\u001b[0m in \u001b[0;36mhandle_data\u001b[0;34m(self, context, data, dt)\u001b[0m\n\u001b[1;32m 216\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 217\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 218\u001b[0;31m \u001b[0mdt\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 219\u001b[0m )\n\u001b[1;32m 220\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/utils/events.py\u001b[0m in \u001b[0;36mhandle_data\u001b[0;34m(self, context, data, dt)\u001b[0m\n\u001b[1;32m 235\u001b[0m \"\"\"\n\u001b[1;32m 236\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrule\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshould_trigger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 237\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcontext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 238\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 239\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-3-99c44213dbe4>\u001b[0m in \u001b[0;36mrebalance\u001b[0;34m(context, data)\u001b[0m\n\u001b[1;32m 138\u001b[0m \u001b[0mfields\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"close\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"volume\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 139\u001b[0m \u001b[0mfrequency\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"1d\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 140\u001b[0;31m \u001b[0mbar_count\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlong_trend_window\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 141\u001b[0m )\n\u001b[1;32m 142\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/_protocol.pyx\u001b[0m in \u001b[0;36mzipline._protocol.check_parameters.__call__.assert_keywords_and_call\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/_protocol.pyx\u001b[0m in \u001b[0;36mzipline._protocol.BarData.history\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/data_portal.py\u001b[0m in \u001b[0;36mget_history_window\u001b[0;34m(self, assets, end_dt, bar_count, frequency, field, data_frequency, ffill)\u001b[0m\n\u001b[1;32m 965\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 966\u001b[0m df = self._get_history_daily_window(assets, end_dt, bar_count,\n\u001b[0;32m--> 967\u001b[0;31m field, data_frequency)\n\u001b[0m\u001b[1;32m 968\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mfrequency\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"1m\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 969\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mfield\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"price\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/data_portal.py\u001b[0m in \u001b[0;36m_get_history_daily_window\u001b[0;34m(self, assets, end_dt, bar_count, field_to_use, data_frequency)\u001b[0m\n\u001b[1;32m 804\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 805\u001b[0m data = self._get_history_daily_window_data(\n\u001b[0;32m--> 806\u001b[0;31m \u001b[0massets\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdays_for_window\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_dt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfield_to_use\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata_frequency\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 807\u001b[0m )\n\u001b[1;32m 808\u001b[0m return pd.DataFrame(\n",
"\u001b[0;32m/zipline/zipline/data/data_portal.py\u001b[0m in \u001b[0;36m_get_history_daily_window_data\u001b[0;34m(self, assets, days_for_window, end_dt, field_to_use, data_frequency)\u001b[0m\n\u001b[1;32m 827\u001b[0m \u001b[0mfield_to_use\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 828\u001b[0m \u001b[0mdays_for_window\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 829\u001b[0;31m \u001b[0mextra_slot\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 830\u001b[0m )\n\u001b[1;32m 831\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/data_portal.py\u001b[0m in \u001b[0;36m_get_daily_window_data\u001b[0;34m(self, assets, field, days_in_window, extra_slot)\u001b[0m\n\u001b[1;32m 1115\u001b[0m \u001b[0mdays_in_window\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1116\u001b[0m \u001b[0mfield\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1117\u001b[0;31m extra_slot)\n\u001b[0m\u001b[1;32m 1118\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mextra_slot\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1119\u001b[0m \u001b[0mreturn_array\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreturn_array\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/history_loader.py\u001b[0m in \u001b[0;36mhistory\u001b[0;34m(self, assets, dts, field, is_perspective_after)\u001b[0m\n\u001b[1;32m 547\u001b[0m \u001b[0mdts\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 548\u001b[0m \u001b[0mfield\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 549\u001b[0;31m is_perspective_after)\n\u001b[0m\u001b[1;32m 550\u001b[0m \u001b[0mend_ix\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_calendar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msearchsorted\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdts\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 551\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/history_loader.py\u001b[0m in \u001b[0;36m_ensure_sliding_windows\u001b[0;34m(self, assets, dts, field, is_perspective_after)\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0madj_dts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mprefetch_dts\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 430\u001b[0m \u001b[0mprefetch_len\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprefetch_dts\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 431\u001b[0;31m \u001b[0marray\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprefetch_dts\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mneeded_assets\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfield\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 432\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 433\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mfield\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'sid'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/history_loader.py\u001b[0m in \u001b[0;36m_array\u001b[0;34m(self, dts, assets, field)\u001b[0m\n\u001b[1;32m 571\u001b[0m \u001b[0mdts\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 572\u001b[0m \u001b[0mdts\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 573\u001b[0;31m \u001b[0massets\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 574\u001b[0m )[0]\n\u001b[1;32m 575\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/zipline/zipline/data/dispatch_bar_reader.py\u001b[0m in \u001b[0;36mload_raw_arrays\u001b[0;34m(self, fields, start_dt, end_dt, sids)\u001b[0m\n\u001b[1;32m 110\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0masset\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0massets\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0masset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 112\u001b[0;31m \u001b[0msid_groups\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0masset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 113\u001b[0m \u001b[0mout_pos\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyError\u001b[0m: <class 'zipline.assets.continuous_futures.ContinuousFuture'>"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x432 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import zipline\n",
"from zipline.api import (\n",
" future_symbol,\n",
" set_commission,\n",
" set_slippage,\n",
" schedule_function,\n",
" date_rules,\n",
" time_rules,\n",
" continuous_future,\n",
" order_target,\n",
")\n",
"from datetime import datetime\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib\n",
"import pyfolio as pf\n",
"import pandas as pd\n",
"import numpy as np\n",
"from zipline.finance.commission import PerShare, PerTrade, PerContract\n",
"from zipline.finance.slippage import (\n",
" VolumeShareSlippage,\n",
" FixedSlippage,\n",
" VolatilityVolumeShare,\n",
")\n",
"\n",
"\"\"\"\n",
"Model Settings\n",
"\"\"\"\n",
"starting_portfolio = 10000000\n",
"risk_factor = 0.001\n",
"vola_window = 60\n",
"# short_trend_window = 125\n",
"# long_trend_window = 250\n",
"short_trend_window = 5\n",
"long_trend_window = 10\n",
"\n",
"\"\"\"\n",
"Prepare for dynamic chart\n",
"\"\"\"\n",
"dynamic_results = pd.DataFrame()\n",
"fig = plt.figure(figsize=(10, 6))\n",
"ax = fig.add_subplot(111)\n",
"ax.set_title(\"Time Return Performance\")\n",
"\n",
"\n",
"def initialize(context):\n",
" \"\"\"\n",
" Cost Settings\n",
" \"\"\"\n",
" context.enable_commission = True\n",
" context.enable_slippage = True\n",
"\n",
" if context.enable_commission:\n",
" comm_model = PerContract(cost=0.85, exchange_fee=1.5)\n",
" else:\n",
" comm_model = PerTrade(cost=0.0)\n",
"\n",
" set_commission(us_futures=comm_model)\n",
"\n",
" if context.enable_slippage:\n",
" slippage_model = VolatilityVolumeShare(volume_limit=0.2)\n",
" else:\n",
" slippage_model = FixedSlippage(spread=0.0)\n",
"\n",
" set_slippage(us_futures=slippage_model)\n",
"\n",
" markets = [\"AD\"]\n",
"\n",
" # Make a list of all continuations\n",
" context.universe = [\n",
" continuous_future(market, offset=0, roll=\"volume\", adjustment=\"mul\")\n",
" for market in markets\n",
" ]\n",
"\n",
" # Schedule daily trading\n",
" schedule_function(rebalance, date_rules.month_start(), time_rules.market_close())\n",
"\n",
" # Schedule daily roll check\n",
" schedule_function(roll_futures, date_rules.every_day(), time_rules.market_close())\n",
"\n",
" # Schedule monthly chart update\n",
" schedule_function(update_chart, date_rules.month_start(), time_rules.market_close())\n",
"\n",
"\n",
"def update_chart(context, data):\n",
" # This function continuously update the graph during the backtest\n",
" today = data.current_session.date()\n",
" dynamic_results.loc[today, \"PortfolioValue\"] = context.portfolio.portfolio_value\n",
"\n",
" if ax.lines: # Update existing line\n",
" ax.lines[0].set_xdata(dynamic_results.index)\n",
" ax.lines[0].set_ydata(dynamic_results.PortfolioValue)\n",
" else: # Create new line\n",
" ax.semilogy(dynamic_results)\n",
"\n",
" # Update scales min/max\n",
" ax.set_ylim(\n",
" dynamic_results.PortfolioValue.min(), dynamic_results.PortfolioValue.max()\n",
" )\n",
" ax.set_xlim(dynamic_results.index.min(), dynamic_results.index.max())\n",
"\n",
" # Redraw the graph\n",
" fig.canvas.draw()\n",
"\n",
"\n",
"def roll_futures(context, data):\n",
" today = data.current_session.date()\n",
" open_orders = zipline.api.get_open_orders()\n",
" for held_contract in context.portfolio.positions:\n",
" if held_contract in open_orders:\n",
" continue\n",
" days_to_auto_close = (held_contract.auto_close_date.date() - today).days\n",
" if days_to_auto_close > 10:\n",
" continue\n",
"\n",
" # Make a continuation\n",
" continuation = continuous_future(\n",
" held_contract.root_symbol, offset=0, roll=\"volume\", adjustment=\"mul\"\n",
" )\n",
" continuation_contract = data.current(continuation, \"contract\")\n",
"\n",
" if continuation_contract != held_contract:\n",
" pos_size = context.portfolio.positions[held_contract].amount\n",
" order_target(held_contract, 0)\n",
" order_target(continuation_contract, pos_size)\n",
"\n",
"\n",
"def position_size(portfolio_value, std, pv, avg_volume):\n",
" target_variation = portfolio_value * risk_factor\n",
" contract_variation = std * pv\n",
" contracts = target_variation / contract_variation\n",
" return int(np.nan_to_num(contracts))\n",
"\n",
"\n",
"def rebalance(context, data):\n",
" # Get the history\n",
" hist = data.history(\n",
" context.universe,\n",
" fields=[\"close\", \"volume\"],\n",
" frequency=\"1d\",\n",
" bar_count=long_trend_window,\n",
" )\n",
"\n",
" # Make a dictionary of open positions\n",
" open_pos = {pos.root_symbol: pos for pos in context.portfolio.positions}\n",
"\n",
" # Loop all markets\n",
" for continuation in context.universe:\n",
" # Slice off history for this market\n",
" h = hist.xs(continuation, 2)\n",
" root = continuation.root_symbol\n",
"\n",
" # Calculate volatility\n",
" std = h.close.diff()[-vola_window:].std()\n",
"\n",
" if root in open_pos: # Position is already open\n",
" p = context.portfolio.positions[open_pos[root]]\n",
" if p.amount > 0: # Long position\n",
" if h.close[-1] < h.close[-long_trend_window]:\n",
" # Lost slow trend, close position\n",
" order_target(open_pos[root], 0)\n",
" elif h.close[-1] < h.close[-short_trend_window]:\n",
" # Lost fast trend, close position\n",
" order_target(open_pos[root], 0)\n",
" else: # Short position\n",
" if h.close[-1] > h.close[-long_trend_window]:\n",
" # Lost slow trend, close position\n",
" order_target(open_pos[root], 0)\n",
" elif h.close[-1] > h.close[-short_trend_window]:\n",
" # Lost fast trend, close position\n",
" order_target(open_pos[root], 0)\n",
"\n",
" else: # No position open yet.\n",
" if (h.close[-1] > h.close[-long_trend_window]) and (\n",
" h.close[-1] > h.close[-short_trend_window]\n",
" ):\n",
" # Buy new position\n",
" contract = data.current(continuation, \"contract\")\n",
" contracts_to_trade = position_size(\n",
" context.portfolio.portfolio_value,\n",
" std,\n",
" contract.price_multiplier,\n",
" h[\"volume\"][-20:].mean(),\n",
" )\n",
"\n",
" order_target(contract, contracts_to_trade)\n",
" elif (h.close[-1] < h.close[-long_trend_window]) and (\n",
" h.close[-1] < h.close[-short_trend_window]\n",
" ):\n",
" # New short position\n",
" contract = data.current(continuation, \"contract\")\n",
" contracts_to_trade = position_size(\n",
" context.portfolio.portfolio_value,\n",
" std,\n",
" contract.price_multiplier,\n",
" h[\"volume\"][-20:].mean(),\n",
" )\n",
"\n",
" order_target(contract, contracts_to_trade * -1)\n",
"\n",
"\n",
"start = pd.Timestamp(\"2018-01-01 08:15:12\", tz=\"utc\")\n",
"end = pd.Timestamp(\"2018-12-31 08:15:12\", tz=\"utc\")\n",
"\n",
"\n",
"perf = zipline.run_algorithm(\n",
" start=start,\n",
" end=end,\n",
" initialize=initialize,\n",
" capital_base=starting_portfolio,\n",
" data_frequency=\"daily\",\n",
" bundle=\"random_futures\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"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.6.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment