求大神帮我修改一下,想在事件驱动策略里加入止损机制

策略分享
标签: #<Tag:0x00007fc83cb3d1a0>

(rkr) #1
克隆策略

每股收益增长率策略

数据准备函数

In [46]:
def prepare(context):
    instruments = context.instruments
    start_date = context.start_date
    end_date = context.end_date
    # 获取数据
    data_1 = D.financial_statements(instruments, start_date, end_date, 
          fields=['instrument','fs_publish_date','fs_quarter_year',
          'fs_quarter_index','fs_net_profit','fs_eps_yoy'])
    # 选择归母公司净利率大于0,每股收益同比增长率大于35%的股票
    data_2 = data_1[data_1['fs_net_profit'] > 0]
    selected = data_2[data_2['fs_eps_yoy'] > 35] 

    # 获取交易日历
    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_eps_yoy',ascending=False ).instrument)
        else:
            event[dt] = []    
    context.event = event 

策略逻辑主体函数

In [47]:
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()}
    
    # 还允许建仓的股票数目
    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  
    
    for k in equities.keys():        
        # k的持仓时间大于10天开始
        if context.trading_day_index - context.hold_days[k] <= 10:
            return        
        # 每日获取k的当前价格和前10日最低价
        price = data.current(k,'price')
        low_point = data.history(k,'price',10,'1d').min()
        # 如果持仓时k的当前价格低于前10日最低价
        if price <= low_point and data.can_trade(context.symbol(k)):
            # 卖完
            context.order_target_percent(context.symbol(k),0)
        # 否则如果持仓时间大于40天
        elif 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)
   
 

策略回测接口

In [48]:
m=M.trade.v2( 
    instruments=D.instruments(market='CN_STOCK_A'),
    start_date='2010-01-01', 
    end_date='2019-12-15',
    prepare=prepare,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',
    order_price_field_sell='open',
    capital_base=1000000,
    benchmark='000300.INDX',
)
error_help error:  'NoneType' object has no attribute 'get'

Trade (回测/模拟)(trade)使用错误,你可以:

1.一键查看文档

2.一键搜索答案

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-48-327504a76342> in <module>()
      9     order_price_field_sell='open',
     10     capital_base=1000000,
---> 11     benchmark='000300.INDX',
     12 )

<ipython-input-47-0c6bd3522846> in handle_data(context, data)
     32             return
     33         # 每日获取k的当前价格和前10日最低价
---> 34         price = data.current(k,'price')
     35         low_point = data.history(k,'price',10,'1d').min()
     36         # 如果持仓时k的当前价格低于前10日最低价

AttributeError: 'str' object has no attribute 'start_date'

(达达) #2
克隆策略

每股收益增长率策略

数据准备函数

In [1]:
def prepare(context):
    instruments = context.instruments
    start_date = context.start_date
    end_date = context.end_date
    # 获取数据
    data_1 = D.financial_statements(instruments, start_date, end_date, 
          fields=['instrument','fs_publish_date','fs_quarter_year',
          'fs_quarter_index','fs_net_profit','fs_eps_yoy'])
    # 选择归母公司净利率大于0,每股收益同比增长率大于35%的股票
    data_2 = data_1[data_1['fs_net_profit'] > 0]
    selected = data_2[data_2['fs_eps_yoy'] > 35] 

    # 获取交易日历
    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_eps_yoy',ascending=False ).instrument)
        else:
            event[dt] = []    
    context.event = event 

策略逻辑主体函数

In [6]:
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()}
    
    # 还允许建仓的股票数目
    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  
    
    for k in equities.keys():        
        # k的持仓时间大于10天开始
        if context.trading_day_index - context.hold_days[k] <= 10:
            return        
        # 每日获取k的当前价格和前10日最低价
        price = data.current(context.symbol(k),'price')
        low_point = data.history(context.symbol(k),'price',10,'1d').min()
        # 如果持仓时k的当前价格低于前10日最低价
        if price <= low_point and data.can_trade(context.symbol(k)):
            # 卖完
            context.order_target_percent(context.symbol(k),0)
        # 否则如果持仓时间大于40天
        elif 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)
   
 

策略回测接口

In [7]:
m=M.trade.v2( 
    instruments=D.instruments(market='CN_STOCK_A'),
    start_date='2010-01-01', 
    end_date='2019-12-15',
    prepare=prepare,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',
    order_price_field_sell='open',
    capital_base=1000000,
    benchmark='000300.INDX',
)
  • 收益率53.26%
  • 年化收益率4.55%
  • 基准收益率10.98%
  • 阿尔法0.03
  • 贝塔0.33
  • 夏普比率0.17
  • 胜率0.45
  • 盈亏比1.55
  • 收益波动率16.5%
  • 信息比率0.01
  • 最大回撤34.53%
bigcharts-data-start/{"__type":"tabs","__id":"bigchart-e81279db9b6244cd9df2410ccfb5f2f3"}/bigcharts-data-end

(rkr) #3

多谢多谢,我昨天也弄出来了,重新又做了一个回测收益更高的策略