ml-finance-python

python scripts for finance machine learning

git clone https://9o.is/git/ml-finance-python.git

alpha_factor_zipline_with_trades.py

(4244B)


      1 #!/usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 __author__ = 'Stefan Jansen'
      4 
      5 import sys
      6 from pathlib import Path
      7 import pandas as pd
      8 from pytz import UTC
      9 from zipline import run_algorithm
     10 from zipline.api import (attach_pipeline, date_rules, time_rules, order_target_percent,
     11                          pipeline_output, record, schedule_function, get_open_orders, calendars,
     12                          set_commission, set_slippage)
     13 from zipline.finance import commission, slippage
     14 from zipline.pipeline import Pipeline, CustomFactor
     15 from zipline.pipeline.factors import Returns, AverageDollarVolume
     16 import logbook
     17 
     18 from pyfolio.utils import extract_rets_pos_txn_from_zipline
     19 
     20 # setup stdout logging
     21 zipline_logging = logbook.NestedSetup([
     22     logbook.NullHandler(level=logbook.DEBUG),
     23     logbook.StreamHandler(sys.stdout, level=logbook.INFO),
     24     logbook.StreamHandler(sys.stderr, level=logbook.ERROR),
     25 ])
     26 zipline_logging.push_application()
     27 
     28 # Settings
     29 MONTH = 21
     30 YEAR = 12 * MONTH
     31 N_LONGS = 200
     32 N_SHORTS = 0
     33 VOL_SCREEN = 1000
     34 
     35 start = pd.Timestamp('2010-01-01', tz=UTC)
     36 end = pd.Timestamp('2018-01-01', tz=UTC)
     37 capital_base = 1e7
     38 
     39 
     40 class MeanReversion(CustomFactor):
     41     """Compute ratio of latest monthly return to 12m average,
     42        normalized by std dev of monthly returns"""
     43     inputs = [Returns(window_length=MONTH)]
     44     window_length = YEAR
     45 
     46     def compute(self, today, assets, out, monthly_returns):
     47         df = pd.DataFrame(monthly_returns)
     48         out[:] = df.iloc[-1].sub(df.mean()).div(df.std())
     49 
     50 
     51 def compute_factors():
     52     """Create factor pipeline incl. mean reversion,
     53         filtered by 30d Dollar Volume; capture factor ranks"""
     54     mean_reversion = MeanReversion()
     55     dollar_volume = AverageDollarVolume(window_length=30)
     56     return Pipeline(columns={'longs'  : mean_reversion.bottom(N_LONGS),
     57                              'shorts' : mean_reversion.top(N_SHORTS),
     58                              'ranking': mean_reversion.rank(ascending=False)},
     59                     screen=dollar_volume.top(VOL_SCREEN))
     60 
     61 
     62 def exec_trades(data, assets, target_percent):
     63     """Place orders for assets using target portfolio percentage"""
     64     for asset in assets:
     65         if data.can_trade(asset) and not get_open_orders(asset):
     66             order_target_percent(asset, target_percent)
     67 
     68 
     69 def rebalance(context, data):
     70     """Compute long, short and obsolete holdings; place trade orders"""
     71     factor_data = context.factor_data
     72     assets = factor_data.index
     73 
     74     longs = assets[factor_data.longs]
     75     shorts = assets[factor_data.shorts]
     76     divest = context.portfolio.positions.keys() - longs.union(shorts)
     77 
     78     exec_trades(data, assets=divest, target_percent=0)
     79     exec_trades(data, assets=longs, target_percent=1 / N_LONGS if N_LONGS else 0)
     80     exec_trades(data, assets=shorts, target_percent=-1 / N_SHORTS if N_SHORTS else 0)
     81 
     82 
     83 def initialize(context):
     84     """Setup: register pipeline, schedule rebalancing,
     85         and set trading params"""
     86     attach_pipeline(compute_factors(), 'factor_pipeline')
     87     schedule_function(rebalance,
     88                       date_rules.week_start(),
     89                       time_rules.market_open(),
     90                       calendar=calendars.US_EQUITIES)
     91 
     92     set_commission(us_equities=commission.PerShare(cost=0.00075, min_trade_cost=.01))
     93     set_slippage(us_equities=slippage.VolumeShareSlippage(volume_limit=0.0025, price_impact=0.01))
     94 
     95 
     96 def before_trading_start(context, data):
     97     """Run factor pipeline"""
     98     context.factor_data = pipeline_output('factor_pipeline')
     99     record(factor_data=context.factor_data.ranking)
    100     assets = context.factor_data.index
    101     record(prices=data.current(assets, 'price'))
    102 
    103 
    104 backtest = run_algorithm(start=start,
    105                          end=end,
    106                          initialize=initialize,
    107                          before_trading_start=before_trading_start,
    108                          capital_base=capital_base)
    109 
    110 # depending on the pyfolio version, gross_leverage may also be returned
    111 returns, positions, transactions = extract_rets_pos_txn_from_zipline(backtest)
    112 
    113 
    114 print(returns.head())
    115 print(returns.info())
    116 
    117 # print(gross_lev.info())
    118 # print(gross_lev.head())
    119 
    120 print(positions.info())
    121 print(positions.head())
    122 
    123 print(transactions.info())
    124 print(transactions.head())