克隆策略

事件驱动策略:基于业绩快报

数据准备函数

In [1]:
def prepare(context):
    instruments = context.instruments
    start_date = context.start_date
    end_date = context.end_date
    # 获取数据
    data = D.financial_statements(instruments, start_date, end_date, 
          fields=['instrument','fs_publish_date','fs_quarter_year',
          'fs_quarter_index','fs_net_profit_yoy'])
    # 选择净利润同比增长率大于30%的股票
    selected = data[data['fs_net_profit_yoy'] > 30] 

    # 获取交易日历
    date = D.trading_days(start_date=start_date,end_date=end_date)
    # 将日期型格式转化为字符型格式
    date = date['date'].apply(lambda x : x.strftime('%Y-%m-%d'))
    # 为尽量接近实盘,事件日期应为财报公布日的前一天
    publish_date = date.shift(-1)
    shift = dict(zip(date, publish_date))

    # 建立事件表
    event = {}
    for dt in date:
        if type(shift[dt]) is str:
            event[dt] = list(selected[selected['fs_publish_date'] == shift[dt]].sort_values(
                'fs_net_profit_yoy',ascending=False ).instrument)
        else:
            event[dt] = []    
    context.event = event 

策略逻辑主体函数

In [2]:
def initialize(context):
   
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) 
    context.daily_buy_stock = context.event
    context.hold_periods = 40 # 持有40天,固定持仓期
    context.stock_max_num = 50 # 最大持仓数量为50只
    context.hold_days = {}
     
def handle_data(context,data):
  
    date = data.current_dt.strftime('%Y-%m-%d') # 日期
    
    # 目前仓位里面的股票列表
    equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}
    
    for k in equities.keys():
        # 如果持仓时间大于40天
        if context.trading_day_index - context.hold_days[k] >= context.hold_periods \
               and data.can_trade(context.symbol(k)):
            # 卖完
            context.order_target_percent(context.symbol(k),0)
   
    # 还允许建仓的股票数目
    stock_can_buy_num = context.stock_max_num - len(equities)
    # 获取当日买入股票的代码
    stock_to_buy = context.daily_buy_stock[date][:stock_can_buy_num]

    # 等权重买入 
    weight =  1 / context.stock_max_num
    
    # 买入
    for stock in stock_to_buy:
        if data.can_trade(context.symbol(stock)):
            context.order_target_percent(context.symbol(stock), weight)
            # 记录建仓时间的日期索引
            context.hold_days[stock] = context.trading_day_index  

策略回测接口

In [3]:
m=M.trade.v2( 
    instruments=D.instruments(market='CN_STOCK_A'),
    start_date='2010-01-01', 
    end_date='2017-08-01',
    prepare=prepare,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',
    order_price_field_sell='open',
    capital_base=1000000,
    benchmark='000300.INDX',
)
[2018-03-22 19:58:10.576019] INFO: bigquant: backtest.v7 开始运行..
[2018-03-22 19:58:24.447598] INFO: algo: set price type:backward_adjusted
[2018-03-22 20:00:02.144660] INFO: Blotter: 2011-03-01 cancel order Equity(3437 [000973.SZA]) 
[2018-03-22 20:00:02.186730] INFO: Blotter: 2011-03-02 cancel order Equity(1775 [000977.SZA]) 
[2018-03-22 20:00:02.451034] INFO: Blotter: 2011-03-04 cancel order Equity(2962 [000629.SZA]) 
[2018-03-22 20:00:02.512531] INFO: Blotter: 2011-03-07 cancel order Equity(2647 [002422.SZA]) 
[2018-03-22 20:00:02.574669] INFO: Blotter: 2011-03-08 cancel order Equity(2298 [600114.SHA]) 
[2018-03-22 20:00:02.641604] INFO: Blotter: 2011-03-09 cancel order Equity(1213 [600179.SHA]) 
[2018-03-22 20:00:02.667457] INFO: Blotter: 2011-03-10 cancel order Equity(3087 [600567.SHA]) 
[2018-03-22 20:00:02.696841] INFO: Blotter: 2011-03-11 cancel order Equity(617 [600728.SHA]) 
[2018-03-22 20:00:02.754833] INFO: Blotter: 2011-03-15 cancel order Equity(3354 [600221.SHA]) 
[2018-03-22 20:00:02.787623] INFO: Blotter: 2011-03-16 cancel order Equity(355 [002210.SZA]) 
[2018-03-22 20:00:02.857295] INFO: Blotter: 2011-03-17 cancel order Equity(1132 [002092.SZA]) 
[2018-03-22 20:00:02.908875] INFO: Blotter: 2011-03-18 cancel order Equity(2574 [600584.SHA]) 
[2018-03-22 20:00:02.943216] INFO: Blotter: 2011-03-21 cancel order Equity(773 [000902.SZA]) 
[2018-03-22 20:00:11.496672] INFO: Blotter: 2012-03-01 cancel order Equity(2922 [000799.SZA]) 
[2018-03-22 20:00:11.542353] INFO: Blotter: 2012-03-02 cancel order Equity(1863 [300105.SZA]) 
[2018-03-22 20:00:11.637673] INFO: Blotter: 2012-03-05 cancel order Equity(2656 [300127.SZA]) 
[2018-03-22 20:00:11.705130] INFO: Blotter: 2012-03-06 cancel order Equity(2992 [600702.SHA]) 
[2018-03-22 20:00:11.736938] INFO: Blotter: 2012-03-07 cancel order Equity(456 [002321.SZA]) 
[2018-03-22 20:00:11.767191] INFO: Blotter: 2012-03-08 cancel order Equity(3062 [000795.SZA]) 
[2018-03-22 20:00:11.811717] INFO: Blotter: 2012-03-09 cancel order Equity(3379 [000822.SZA]) 
[2018-03-22 20:00:11.848026] INFO: Blotter: 2012-03-12 cancel order Equity(3301 [300195.SZA]) 
[2018-03-22 20:00:11.909838] INFO: Blotter: 2012-03-13 cancel order Equity(1836 [600203.SHA]) 
[2018-03-22 20:00:11.947694] INFO: Blotter: 2012-03-14 cancel order Equity(3364 [300142.SZA]) 
[2018-03-22 20:00:11.995203] INFO: Blotter: 2012-03-16 cancel order Equity(3465 [000030.SZA]) 
[2018-03-22 20:09:49.689308] INFO: Performance: Simulated 1841 trading days out of 1841.
[2018-03-22 20:09:49.694649] INFO: Performance: first open: 2010-01-04 01:30:00+00:00
[2018-03-22 20:09:49.696548] INFO: Performance: last close: 2017-08-01 07:00:00+00:00
  • 收益率93.98%
  • 年化收益率9.49%
  • 基准收益率5.44%
  • 阿尔法0.07
  • 贝塔0.55
  • 夏普比率0.23
  • 胜率0.487
  • 盈亏比1.471
  • 收益波动率21.82%
  • 信息比率0.43
  • 最大回撤39.26%
[2018-03-22 20:10:18.296940] INFO: bigquant: backtest.v7 运行完成[727.720889s].