diff --git a/catalyst/constants.py b/catalyst/constants.py index 55ccce15..c5f8d4ef 100644 --- a/catalyst/constants.py +++ b/catalyst/constants.py @@ -1,3 +1,5 @@ # -*- coding: utf-8 -*- -LOG_LEVEL = 'ERROR' \ No newline at end of file +import logbook + +LOG_LEVEL = logbook.INFO \ No newline at end of file diff --git a/catalyst/examples/buy_btc_simple.py b/catalyst/examples/buy_btc_simple.py index f7eb8aa0..78888715 100644 --- a/catalyst/examples/buy_btc_simple.py +++ b/catalyst/examples/buy_btc_simple.py @@ -1,8 +1,8 @@ from catalyst.api import order, record, symbol def initialize(context): - context.asset = symbol('btc_usd') + context.asset = symbol('btc_usd') def handle_data(context, data): - order(asset, 1) - record(btc=data.current(context.asset, 'price')) \ No newline at end of file + order(context.asset, 1) + record(btc = data.current(context.asset, 'price')) \ No newline at end of file diff --git a/docs/source/beginner-tutorial.rst b/docs/source/beginner-tutorial.rst index b3b1b133..213087b5 100644 --- a/docs/source/beginner-tutorial.rst +++ b/docs/source/beginner-tutorial.rst @@ -52,7 +52,7 @@ My first algorithm ~~~~~~~~~~~~~~~~~~ Lets take a look at a very simple algorithm from the ``examples`` -directory, ``buy_btc.py``: +directory: `buy_btc_simple.py `_: .. code-block:: python @@ -225,16 +225,16 @@ Thus, to execute our algorithm from above and save the results to .. code-block:: python - catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2016-9-29 -o buy_simple_btc_out.pickle + catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle -.. -.. parsed-literal +.. parsed-literal:: -.. AAPL -.. [2015-11-04 22:45:32.820166] INFO: Performance: Simulated 3521 trading days out of 3521. -.. [2015-11-04 22:45:32.820314] INFO: Performance: first open: 2000-01-03 14:31:00+00:00 -.. [2015-11-04 22:45:32.820401] INFO: Performance: last close: 2013-12-31 21:00:00+00:00 + INFO: run_algo: running algo in backtest mode + INFO: exchange_algorithm: initialized trading algorithm in backtest mode + INFO: Performance: Simulated 639 trading days out of 639. + INFO: Performance: first open: 2016-01-01 00:00:00+00:00 + INFO: Performance: last close: 2017-09-30 23:59:00+00:00 ``run`` first calls the ``initialize()`` function, and then @@ -255,7 +255,7 @@ slippage model that ``catalyst`` uses). Let's take a quick look at the performance ``DataFrame``. For this, we use ``pandas`` from inside the IPython Notebook and print the first ten -rows. Note that ``catalyst`` makes heavy usage of +rows. and print the first ten rows. Note that ``catalyst`` makes heavy usage of `pandas `_, especially for data input and outputting so it's worth spending some time to learn it. @@ -265,17 +265,196 @@ outputting so it's worth spending some time to learn it. perf = pd.read_pickle('buy_btc_simple_out.pickle') # read in perf DataFrame perf.head() +.. raw:: html + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
algo_volatilityalgorithm_period_returnalphabenchmark_period_returnbenchmark_volatilitybetabtccapital_usedending_cashending_exposure...short_exposureshort_valueshorts_countsortinostarting_cashstarting_exposurestarting_valuetrading_daystransactionstreasury_period_return
2016-01-01 23:59:00+00:00NaN0.000000e+00NaN-0.010937NaNNaN433.9799990.0000001.000000e+070.00...000NaN1.000000e+070.000.001[]0.0227
2016-01-02 23:59:00+00:000.000011-9.536708e-07-0.000170-0.0064800.173338-0.000062432.700000-442.2367089.999558e+06432.70...000-11.2249721.000000e+070.000.002[{u'order_id': u'7869f7828fa140328eb40477bb7de...0.0227
2016-01-03 23:59:00+00:000.000011-2.328842e-06-0.000176-0.0265120.1978570.000009428.390000-437.8317169.999120e+06856.78...000-12.7542629.999558e+06432.70432.703[{u'order_id': u'be62ff77760c4599abaac43be9cc9...0.0227
2016-01-04 23:59:00+00:000.000011-2.380954e-06-0.000139-0.0086400.2697900.000020432.900000-442.4411169.998677e+061298.70...000-11.2872059.999120e+06856.78856.784[{u'order_id': u'd6dca79513214346a646079213526...0.0224
2016-01-05 23:59:00+00:000.000011-3.650729e-06-0.000158-0.0214260.2459890.000024431.840000-441.3577549.998236e+061727.36...000-12.3338479.998677e+061298.701298.705[{u'order_id': u'505275d6646a41f3856b22b16678d...0.0225
+
+ +| There is a row for each trading day, starting on the first day of our simulation Jan 1st, 2016. In the columns you can find various -information about the state of your algorithm. The very first column +information about the state of your algorithm. The column ``btc`` was placed there by the ``record()`` function mentioned earlier and allows us to plot the price of bitcoin. For example, we could easily examine now how our portfolio value changed over time compared to the bitcoin price. -Our algorithm performance as assessed by the -``portfolio_value`` closely matches that of the bitcoin price. This -is not surprising as our algorithm only bought bitcoin every chance it got. +.. code-block:: python + + %pylab inline + figsize(12, 12) + import matplotlib.pyplot as plt + + ax1 = plt.subplot(211) + perf.portfolio_value.plot(ax=ax1) + ax1.set_ylabel('portfolio value') + ax2 = plt.subplot(212, sharex=ax1) + perf.btc.plot(ax=ax2) + ax2.set_ylabel('bitcoin price') + +.. parsed-literal:: + + Populating the interactive namespace from numpy and matplotlib + +.. parsed-literal:: + + + +.. image:: https://s3.amazonaws.com/enigmaco-docs/github.io/buy_btc_simple_graph.png + +Our algorithm performance as assessed by the ``portfolio_value`` closely +matches that of the bitcoin price. This is not surprising as our algorithm +only bought bitcoin every chance it got. Access to previous prices using ``history`` @@ -305,13 +484,14 @@ a function we use in the ``handle_data()`` section: .. code-block:: python - from catalyst.api import order, record, symbol + %%catalyst --start 2016-1-1 --end 2017-9-30 -x bitfinex -o dma.pickle + from catalyst.api import order, record, symbol, order_target def initialize(context): context.i = 0 context.asset = symbol('btc_usd') - def handle_data(context, data): + def handle_data(context, data): # Skip first 300 days to get full windows context.i += 1 if context.i < 300: @@ -336,6 +516,46 @@ a function we use in the ``handle_data()`` section: short_mavg=short_mavg, long_mavg=long_mavg) + def analyze(context, perf): + import matplotlib as plt + fig = plt.figure() + ax1 = fig.add_subplot(211) + perf.portfolio_value.plot(ax=ax1) + ax1.set_ylabel('portfolio value in $') + + ax2 = fig.add_subplot(212) + perf['btc'].plot(ax=ax2) + perf[['short_mavg', 'long_mavg']].plot(ax=ax2) + + perf_trans = perf.ix[[t != [] for t in perf.transactions]] + buys = perf_trans.ix[[t[0]['amount'] > 0 for t in perf_trans.transactions]] + sells = perf_trans.ix[ + [t[0]['amount'] < 0 for t in perf_trans.transactions]] + ax2.plot(buys.index, perf.short_mavg.ix[buys.index], + '^', markersize=10, color='m') + ax2.plot(sells.index, perf.short_mavg.ix[sells.index], + 'v', markersize=10, color='k') + ax2.set_ylabel('price in $') + plt.legend(loc=0) + plt.show() + +Here we are explicitly defining an ``analyze()`` function that gets +automatically called once the backtest is done. + +Although it might not be directly apparent, the power of ``history()`` +(pun intended) can not be under-estimated as most algorithms make use of +prior market developments in one form or another. You could easily +devise a strategy that trains a classifier with +`scikit-learn `__ which tries to +predict future market movements based on past prices (note, that most of +the ``scikit-learn`` functions require ``numpy.ndarray``\ s rather than +``pandas.DataFrame``\ s, so you can simply pass the underlying +``ndarray`` of a ``DataFrame`` via ``.values``). + +We also used the ``order_target()`` function above. This and other +functions like it can make order management and portfolio rebalancing +much easier. + Conclusions ~~~~~~~~~~~