mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-22 12:40:30 +08:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ade2989e8 | ||
|
|
b1d5acf2ad | ||
|
|
5d5ec6b9be | ||
|
|
1b84023c5d | ||
|
|
97f3329c1b | ||
|
|
bdeb344999 | ||
|
|
52e1de954f | ||
|
|
7b9eafef4e | ||
|
|
8b141a0c28 | ||
|
|
7f602d7fcc |
@@ -138,8 +138,9 @@ from catalyst.gens.sim_engine import MinuteSimulationClock
|
||||
from catalyst.sources.benchmark_source import BenchmarkSource
|
||||
from catalyst.catalyst_warnings import ZiplineDeprecationWarning
|
||||
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger("ZiplineLog")
|
||||
log = logbook.Logger("CatalystLog", level=LOG_LEVEL)
|
||||
|
||||
|
||||
class TradingAlgorithm(object):
|
||||
|
||||
@@ -76,7 +76,9 @@ from catalyst.utils.numpy_utils import as_column
|
||||
from catalyst.utils.preprocess import preprocess
|
||||
from catalyst.utils.sqlite_utils import group_into_chunks, coerce_string_to_eng
|
||||
|
||||
log = Logger('assets.py')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('assets.py', level=LOG_LEVEL)
|
||||
|
||||
# A set of fields that need to be converted to strings before building an
|
||||
# Asset to avoid unicode fields
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logbook
|
||||
|
||||
LOG_LEVEL = logbook.INFO
|
||||
@@ -215,7 +215,7 @@ cpdef _read_bcolz_data(ctable_t table,
|
||||
else:
|
||||
continue
|
||||
|
||||
if column_name in ['open', 'high', 'low', 'close']:
|
||||
if column_name in ['open', 'high', 'low', 'close', 'volume']:
|
||||
where_nan = (outbuf == 0)
|
||||
outbuf_as_float = outbuf.astype(float64) * .000000001
|
||||
outbuf_as_float[where_nan] = NAN
|
||||
|
||||
@@ -30,8 +30,10 @@ from catalyst.utils.cli import (
|
||||
)
|
||||
from catalyst.utils.memoize import lazyval
|
||||
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
logbook.StderrHandler().push_application()
|
||||
log = logbook.Logger(__name__)
|
||||
log = logbook.Logger(__name__, level=LOG_LEVEL)
|
||||
|
||||
DEFAULT_RETRIES = 5
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ from catalyst.utils.cli import maybe_show_progress
|
||||
|
||||
from . import core as bundles
|
||||
|
||||
log = Logger(__name__)
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger(__name__, level=LOG_LEVEL)
|
||||
seconds_per_call = (pd.Timedelta('10 minutes') / 2000).total_seconds()
|
||||
|
||||
class QuandlBundle(BaseEquityPricingBundle):
|
||||
|
||||
@@ -68,7 +68,9 @@ from catalyst.errors import (
|
||||
HistoryWindowStartsBeforeData,
|
||||
)
|
||||
|
||||
log = Logger('DataPortal')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('DataPortal', level=LOG_LEVEL)
|
||||
|
||||
BASE_FIELDS = frozenset([
|
||||
"open",
|
||||
|
||||
@@ -32,7 +32,9 @@ from ..utils.paths import (
|
||||
data_root,
|
||||
)
|
||||
|
||||
logger = logbook.Logger('Loader')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
logger = logbook.Logger('Loader', level=LOG_LEVEL)
|
||||
|
||||
# Mapping from index symbol to appropriate bond data
|
||||
INDEX_MAPPING = {
|
||||
|
||||
@@ -44,7 +44,9 @@ from catalyst.utils.calendars import get_calendar
|
||||
from catalyst.utils.cli import maybe_show_progress
|
||||
from catalyst.utils.memoize import lazyval
|
||||
|
||||
logger = logbook.Logger('MinuteBars')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
logger = logbook.Logger('MinuteBars', level=LOG_LEVEL)
|
||||
|
||||
US_EQUITIES_MINUTES_PER_DAY = 390
|
||||
FUTURES_MINUTES_PER_DAY = 1440
|
||||
|
||||
@@ -83,7 +83,9 @@ from catalyst.utils.cli import (
|
||||
from ._equities import _compute_row_slices, _read_bcolz_data
|
||||
from ._adjustments import load_adjustments_from_sqlite
|
||||
|
||||
logger = logbook.Logger('UsEquityPricing')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
logger = logbook.Logger('UsEquityPricing', level=LOG_LEVEL)
|
||||
|
||||
OHLC = frozenset(['open', 'high', 'low', 'close'])
|
||||
OHLCV = frozenset(['open', 'high', 'low', 'close', 'volume'])
|
||||
|
||||
@@ -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'))
|
||||
order(context.asset, 1)
|
||||
record(btc = data.current(context.asset, 'price'))
|
||||
@@ -1,6 +1,8 @@
|
||||
from logbook import Logger
|
||||
|
||||
log = Logger('AssetFinderExchange')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('AssetFinderExchange', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class AssetFinderExchange(object):
|
||||
@@ -41,9 +43,9 @@ class AssetFinderExchange(object):
|
||||
"""
|
||||
for sid in sids:
|
||||
if sid in self._asset_cache:
|
||||
log.info('got asset from cache: {}'.format(sid))
|
||||
log.debug('got asset from cache: {}'.format(sid))
|
||||
else:
|
||||
log.info('fetching asset: {}'.format(sid))
|
||||
log.debug('fetching asset: {}'.format(sid))
|
||||
return list()
|
||||
|
||||
def lookup_symbol(self, symbol, exchange, as_of_date=None, fuzzy=False):
|
||||
|
||||
@@ -33,7 +33,9 @@ requests.adapters.DEFAULT_RETRIES = 20
|
||||
|
||||
BITFINEX_URL = 'https://api.bitfinex.com'
|
||||
|
||||
log = Logger('Bitfinex')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Bitfinex', level=LOG_LEVEL)
|
||||
warning_logger = Logger('AlgoWarning')
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ from catalyst.finance.order import Order, ORDER_STATUS
|
||||
from catalyst.exchange.exchange_utils import get_exchange_symbols_filename, \
|
||||
download_exchange_symbols
|
||||
|
||||
log = Logger('Bittrex')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Bittrex', level=LOG_LEVEL)
|
||||
|
||||
URL2 = 'https://bittrex.com/Api/v2.0'
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ from catalyst.exchange.exchange_errors import (
|
||||
PricingDataNotLoadedError, InvalidHistoryFrequencyError,
|
||||
BundleNotFoundError)
|
||||
|
||||
log = Logger('DataPortalExchange')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('DataPortalExchange', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class DataPortalExchangeBase(DataPortal):
|
||||
|
||||
@@ -24,7 +24,9 @@ from catalyst.exchange.exchange_utils import get_exchange_symbols
|
||||
from catalyst.finance.order import ORDER_STATUS
|
||||
from catalyst.finance.transaction import Transaction
|
||||
|
||||
log = Logger('Exchange')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Exchange', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class Exchange:
|
||||
|
||||
@@ -54,7 +54,9 @@ from catalyst.utils.input_validation import error_keywords, ensure_upper_case, \
|
||||
from catalyst.utils.preprocess import preprocess
|
||||
from catalyst.utils.math_utils import round_nearest
|
||||
|
||||
log = logbook.Logger('exchange_algorithm')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('exchange_algorithm', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class ExchangeAlgorithmExecutor(AlgorithmSimulator):
|
||||
|
||||
@@ -6,7 +6,9 @@ from catalyst.finance.commission import CommissionModel
|
||||
from catalyst.finance.slippage import SlippageModel
|
||||
from catalyst.finance.transaction import Transaction
|
||||
|
||||
log = Logger('exchange_blotter')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('exchange_blotter', level=LOG_LEVEL)
|
||||
|
||||
# It seems like we need to accept greater slippage risk in cryptos
|
||||
# Orders won't often close at Equity levels.
|
||||
|
||||
@@ -21,16 +21,15 @@ from catalyst.exchange.exchange_utils import get_exchange_folder
|
||||
from catalyst.utils.cli import maybe_show_progress
|
||||
from catalyst.utils.paths import ensure_directory
|
||||
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('exchange_bundle', level=LOG_LEVEL)
|
||||
|
||||
BUNDLE_NAME_TEMPLATE = '{root}/{frequency}_bundle'
|
||||
|
||||
def _cachpath(symbol, type_):
|
||||
return '-'.join([symbol, type_])
|
||||
|
||||
|
||||
BUNDLE_NAME_TEMPLATE = '{root}/{frequency}_bundle'
|
||||
log = Logger('exchange_bundle')
|
||||
log.level = INFO
|
||||
|
||||
|
||||
class ExchangeBundle:
|
||||
def __init__(self, exchange):
|
||||
self.exchange = exchange
|
||||
|
||||
@@ -3,7 +3,9 @@ from logbook import Logger
|
||||
|
||||
from catalyst.protocol import Portfolio, Positions, Position
|
||||
|
||||
log = Logger('ExchangePortfolio')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('ExchangePortfolio', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class ExchangePortfolio(Portfolio):
|
||||
|
||||
@@ -22,8 +22,9 @@ from logbook import Logger
|
||||
from catalyst.exchange.exchange_errors import \
|
||||
MismatchingBaseCurrenciesExchanges
|
||||
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('LiveGraphClock')
|
||||
log = Logger('LiveGraphClock', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class LiveGraphClock(object):
|
||||
|
||||
@@ -33,7 +33,9 @@ from catalyst.exchange.exchange_utils import get_exchange_symbols_filename, \
|
||||
download_exchange_symbols
|
||||
from catalyst.finance.transaction import Transaction
|
||||
|
||||
log = Logger('Poloniex')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Poloniex', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class Poloniex(Exchange):
|
||||
|
||||
@@ -34,7 +34,9 @@ from catalyst.finance.commission import (
|
||||
from catalyst.finance.cancel_policy import NeverCancel
|
||||
from catalyst.utils.input_validation import expect_types
|
||||
|
||||
log = Logger('Blotter')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Blotter', level=LOG_LEVEL)
|
||||
warning_logger = Logger('AlgoWarning')
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ from catalyst.errors import (
|
||||
TradingControlViolation,
|
||||
)
|
||||
|
||||
log = logbook.Logger('TradingControl')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('TradingControl', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class TradingControl(with_metaclass(abc.ABCMeta)):
|
||||
|
||||
@@ -88,7 +88,10 @@ from six import itervalues, iteritems
|
||||
|
||||
import catalyst.protocol as zp
|
||||
|
||||
log = logbook.Logger('Performance')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Performance', level=LOG_LEVEL)
|
||||
|
||||
TRADE_TYPE = zp.DATASOURCE_TYPE.TRADE
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ import logbook
|
||||
from catalyst.assets import Future, Asset
|
||||
from catalyst.utils.input_validation import expect_types
|
||||
|
||||
log = logbook.Logger('Performance')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Performance', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class Position(object):
|
||||
|
||||
@@ -32,7 +32,9 @@ from catalyst.assets import (
|
||||
)
|
||||
from . position import positiondict
|
||||
|
||||
log = logbook.Logger('Performance')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Performance', level=LOG_LEVEL)
|
||||
|
||||
|
||||
PositionStats = namedtuple('PositionStats',
|
||||
|
||||
@@ -70,7 +70,9 @@ import catalyst.finance.risk as risk
|
||||
|
||||
from . position_tracker import PositionTracker
|
||||
|
||||
log = logbook.Logger('Performance')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Performance', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class PerformanceTracker(object):
|
||||
|
||||
@@ -38,7 +38,9 @@ from empyrical import (
|
||||
sortino_ratio,
|
||||
)
|
||||
|
||||
log = logbook.Logger('Risk Cumulative')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Risk Cumulative', level=LOG_LEVEL)
|
||||
|
||||
|
||||
choose_treasury = functools.partial(choose_treasury, lambda *args: '10year',
|
||||
|
||||
@@ -36,7 +36,9 @@ from empyrical import (
|
||||
sortino_ratio
|
||||
)
|
||||
|
||||
log = logbook.Logger('Risk Period')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Risk Period', level=LOG_LEVEL)
|
||||
|
||||
choose_treasury = functools.partial(risk.choose_treasury,
|
||||
risk.select_treasury_duration)
|
||||
|
||||
@@ -63,7 +63,9 @@ from dateutil.relativedelta import relativedelta
|
||||
|
||||
from . period import RiskMetricsPeriod
|
||||
|
||||
log = logbook.Logger('Risk Report')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Risk Report', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class RiskReport(object):
|
||||
|
||||
@@ -61,7 +61,9 @@ Risk Report
|
||||
import logbook
|
||||
import numpy as np
|
||||
|
||||
log = logbook.Logger('Risk')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Risk', level=LOG_LEVEL)
|
||||
|
||||
|
||||
TREASURY_DURATIONS = [
|
||||
|
||||
@@ -26,7 +26,9 @@ from catalyst.data.loader import load_market_data
|
||||
from catalyst.utils.calendars import get_calendar
|
||||
from catalyst.utils.memoize import remember_last
|
||||
|
||||
log = logbook.Logger('Trading')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = logbook.Logger('Trading', level=LOG_LEVEL)
|
||||
|
||||
|
||||
DEFAULT_CAPITAL_BASE = 1e5
|
||||
|
||||
@@ -27,7 +27,9 @@ from catalyst.gens.sim_engine import (
|
||||
BEFORE_TRADING_START_BAR
|
||||
)
|
||||
|
||||
log = Logger('Trade Simulation')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('Trade Simulation', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class AlgorithmSimulator(object):
|
||||
|
||||
@@ -23,7 +23,9 @@ from catalyst.protocol import (
|
||||
)
|
||||
from catalyst.assets import Equity
|
||||
|
||||
logger = Logger('Requests Source Logger')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
logger = Logger('Requests Source Logger', level=LOG_LEVEL)
|
||||
|
||||
|
||||
def roll_dts_to_midnight(dts, trading_day):
|
||||
|
||||
@@ -43,7 +43,9 @@ from catalyst.exchange.exchange_utils import get_exchange_auth, \
|
||||
get_algo_object
|
||||
from logbook import Logger
|
||||
|
||||
log = Logger('run_algo')
|
||||
from catalyst.constants import LOG_LEVEL
|
||||
|
||||
log = Logger('run_algo', level=LOG_LEVEL)
|
||||
|
||||
|
||||
class _RunAlgoError(click.ClickException, ValueError):
|
||||
|
||||
@@ -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 <https://github.com/enigmampc/catalyst/blob/master/catalyst/examples/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 <http://pandas.pydata.org/>`_, 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
|
||||
|
||||
<div style="max-height:1000px;max-width:1500px;overflow:auto;">
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>algo_volatility</th>
|
||||
<th>algorithm_period_return</th>
|
||||
<th>alpha</th>
|
||||
<th>benchmark_period_return</th>
|
||||
<th>benchmark_volatility</th>
|
||||
<th>beta</th>
|
||||
<th>btc</th>
|
||||
<th>capital_used</th>
|
||||
<th>ending_cash</th>
|
||||
<th>ending_exposure</th>
|
||||
<th>...</th>
|
||||
<th>short_exposure</th>
|
||||
<th>short_value</th>
|
||||
<th>shorts_count</th>
|
||||
<th>sortino</th>
|
||||
<th>starting_cash</th>
|
||||
<th>starting_exposure</th>
|
||||
<th>starting_value</th>
|
||||
<th>trading_days</th>
|
||||
<th>transactions</th>
|
||||
<th>treasury_period_return</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>2016-01-01 23:59:00+00:00</th>
|
||||
<td>NaN</td>
|
||||
<td>0.000000e+00</td>
|
||||
<td>NaN</td>
|
||||
<td>-0.010937</td>
|
||||
<td>NaN</td>
|
||||
<td>NaN</td>
|
||||
<td>433.979999</td>
|
||||
<td>0.000000</td>
|
||||
<td>1.000000e+07</td>
|
||||
<td>0.00</td>
|
||||
<td>...</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>NaN</td>
|
||||
<td>1.000000e+07</td>
|
||||
<td>0.00</td>
|
||||
<td>0.00</td>
|
||||
<td>1</td>
|
||||
<td>[]</td>
|
||||
<td>0.0227</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2016-01-02 23:59:00+00:00</th>
|
||||
<td>0.000011</td>
|
||||
<td>-9.536708e-07</td>
|
||||
<td>-0.000170</td>
|
||||
<td>-0.006480</td>
|
||||
<td>0.173338</td>
|
||||
<td>-0.000062</td>
|
||||
<td>432.700000</td>
|
||||
<td>-442.236708</td>
|
||||
<td>9.999558e+06</td>
|
||||
<td>432.70</td>
|
||||
<td>...</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>-11.224972</td>
|
||||
<td>1.000000e+07</td>
|
||||
<td>0.00</td>
|
||||
<td>0.00</td>
|
||||
<td>2</td>
|
||||
<td>[{u'order_id': u'7869f7828fa140328eb40477bb7de...</td>
|
||||
<td>0.0227</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2016-01-03 23:59:00+00:00</th>
|
||||
<td>0.000011</td>
|
||||
<td>-2.328842e-06</td>
|
||||
<td>-0.000176</td>
|
||||
<td>-0.026512</td>
|
||||
<td>0.197857</td>
|
||||
<td>0.000009</td>
|
||||
<td>428.390000</td>
|
||||
<td>-437.831716</td>
|
||||
<td>9.999120e+06</td>
|
||||
<td>856.78</td>
|
||||
<td>...</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>-12.754262</td>
|
||||
<td>9.999558e+06</td>
|
||||
<td>432.70</td>
|
||||
<td>432.70</td>
|
||||
<td>3</td>
|
||||
<td>[{u'order_id': u'be62ff77760c4599abaac43be9cc9...</td>
|
||||
<td>0.0227</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2016-01-04 23:59:00+00:00</th>
|
||||
<td>0.000011</td>
|
||||
<td>-2.380954e-06</td>
|
||||
<td>-0.000139</td>
|
||||
<td>-0.008640</td>
|
||||
<td>0.269790</td>
|
||||
<td>0.000020</td>
|
||||
<td>432.900000</td>
|
||||
<td>-442.441116</td>
|
||||
<td>9.998677e+06</td>
|
||||
<td>1298.70</td>
|
||||
<td>...</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>-11.287205</td>
|
||||
<td>9.999120e+06</td>
|
||||
<td>856.78</td>
|
||||
<td>856.78</td>
|
||||
<td>4</td>
|
||||
<td>[{u'order_id': u'd6dca79513214346a646079213526...</td>
|
||||
<td>0.0224</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2016-01-05 23:59:00+00:00</th>
|
||||
<td>0.000011</td>
|
||||
<td>-3.650729e-06</td>
|
||||
<td>-0.000158</td>
|
||||
<td>-0.021426</td>
|
||||
<td>0.245989</td>
|
||||
<td>0.000024</td>
|
||||
<td>431.840000</td>
|
||||
<td>-441.357754</td>
|
||||
<td>9.998236e+06</td>
|
||||
<td>1727.36</td>
|
||||
<td>...</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>0</td>
|
||||
<td>-12.333847</td>
|
||||
<td>9.998677e+06</td>
|
||||
<td>1298.70</td>
|
||||
<td>1298.70</td>
|
||||
<td>5</td>
|
||||
<td>[{u'order_id': u'505275d6646a41f3856b22b16678d...</td>
|
||||
<td>0.0225</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
|
||||
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::
|
||||
|
||||
<matplotlib.text.Text at 0x10eaeadd0>
|
||||
|
||||
.. 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.pyplot 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 <http://scikit-learn.org/stable/>`__ 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
|
||||
~~~~~~~~~~~
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Incompatible with earlier PIP versions
|
||||
pip>=7.1.0
|
||||
# bcolz fails to install if this is not in the build_requires.
|
||||
setuptools>18.0
|
||||
setuptools>36.0
|
||||
|
||||
# Logging
|
||||
Logbook==0.12.5
|
||||
|
||||
Reference in New Issue
Block a user