初始策略运行成功,但是扩充股票池或者修改初始资金时运行出错

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

(xiaoxiao2017) #1
克隆策略
In [45]:
# 1. 策略基本参数

start_date = '2017-07-11'
end_date = '2017-8-11'
benchmark = '000300.INDX'
#instruments=['600000.SHA']
instruments=['600000.SHA','600519.SHA'] #第一次运行:股票池含2只股票,capital_base =1亿,运行成功
#instruments=['200725.SZA']#不是股票 是分级基金
#instruments=D.instruments(start_date,end_date) #第三次运行,股票池为所有股票,capital_base =1亿,结果:KeyError
capital_base = 100000000  
#capital_base = 1000000000 #第二次运行,股票池含2只股票,capital_base =10亿,结果:KeyError: '600000.SHA'

# 2. 策略主体函数
# 初始化虚拟账户状态,只在第一个交易日运行
def initialize(context):
    # 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    context.tr_all=list() #记录每天振幅
    context.tr_num=20 # 要几天的TR均值
    context.day_n=0 #数天数
    context.N=0.0
    context.stoped=list() #记录当日止*了什么
    context.in_price=dict()#在一个股票的版本里,用数值就够了,这里要变成字典

# 策略交易逻辑,每个交易日运行一次
def handle_data(context, data):
    context.day_n=context.day_n+1
    today = data.current_dt.strftime('%Y-%m-%d')
    cash_today=context.portfolio.cash
    cash_today_used=0
    #print(today,cash_now)
    in_days_num=20 # 55日进,20日出
    out_days_num=5
    for i in instruments:
        sid=context.symbol(i)
        try:
            last_in_price=context.in_price[i]#每次覆盖
        except KeyError:
            last_in_price=0
        cur_position=context.portfolio.positions[sid].amount#为啥这里的sid用[]?因为 是dict?
        price=data.current(sid,"price")
#=============================以下计算N============================================
        if context.day_n>=2:
            n_days=np.maximum(context.day_n,20)
            base_data=data.history(sid,['high','low','close'],int(n_days+1),'1d')
            context.tr_all=[]#清空
            for d in range(1,(n_days+1)):  
                price_h=base_data['high'][-d]#每次覆盖
                price_l=base_data['low'][-d]
                price_c2=base_data['close'][-d-1]
                h_l=np.array(price_h-price_l)
                P_l=np.array(price_c2-price_l)
                h_p=np.array(price_h-price_c2)
                temp=np.maximum(h_l,P_l,h_p)
                context.tr_all.append(temp)
            context.N=np.mean(np.array(context.tr_all))
 #===============================N计算完毕,开始计算unit========================================= 
            value=capital_base
            context.one_unit=int(value*0.01/(context.N*100))*100
  #==============================以下是止损模块============================================  
            context.stoped=[]#每天清空一下
            buy_stop_loss_price=last_in_price-(2*context.N)
           
            if price<buy_stop_loss_price and cur_position > 0 and data.can_trade(sid):
                context.order_target_percent(sid,0)
                context.stoped.append(i)
                del context.in_price[i]#去除键组
                cash_today_used=cash_today_used+context.one_unit*price*(1-0.0013)#如果碰到后面就差这些钱导致今天这个股票买不进去,也...没办法了...
       
  #=========================以下是开仓/加仓/退出 模块======================================  
            in_days_high=data.history(sid,'close',in_days_num,'1d').max()
            out_days_low=data.history(sid,'close',out_days_num,'1d').min()
            if context.one_unit*price*1.0003<(cash_today+cash_today_used):
                cash_enough=True
            else:
                cash_enough=False
    #先多开后空平
            if price > in_days_high and cur_position==0 and data.can_trade(sid) and cash_enough==True:
                #开仓
                context.order(sid,context.one_unit)
                context.in_price[i]=price
                cash_today_used=cash_today_used-context.one_unit*price*1.0003
            if price > last_in_price+0.5*context.N  and cur_position>0 and data.can_trade(sid) and cash_enough==True:
                #加仓
                context.order(sid,context.one_unit)
                context.in_price[i]=price
                cash_today_used=cash_today_used-context.one_unit*price*1.0003
            elif price < out_days_low and cur_position>0 and data.can_trade(sid) and i not in context.stoped:#退出
                context.order_target_percent(sid,0)
                del context.in_price[i] #去除键组
                cash_today_used=cash_today_used+context.one_unit*price*(1-0.0013)
#============================开仓模块结束========================================== 
 #=========================unit4模块,暂时用最新的N算

 
# 3. 启动回测

# 策略回测接口: https://bigquant.com/docs/module_trade.html
m = M.trade.v2(
    instruments=instruments,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize,
    handle_data=handle_data,
    # 买入订单以开盘价成交
    order_price_field_buy='open',
    # 卖出订单以开盘价成交
    order_price_field_sell='open',
    capital_base=capital_base,
    benchmark=benchmark,
)
[2017-11-21 12:27:49.854587] INFO: bigquant: backtest.v7 开始运行..
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-45-7e5bd03fa7d0> in <module>()
    109     order_price_field_sell='open',
    110     capital_base=capital_base,
--> 111     benchmark=benchmark,
    112 )

<ipython-input-45-7e5bd03fa7d0> in handle_data(context, data)
     89             elif price < out_days_low and cur_position>0 and data.can_trade(sid) and i not in context.stoped:#退出
     90                 context.order_target_percent(sid,0)
---> 91                 del context.in_price[i] #去除键组
     92                 cash_today_used=cash_today_used+context.one_unit*price*(1-0.0013)
     93 #============================开仓模块结束==========================================

KeyError: '600000.SHA'

编写了一个比较初级的策略,
有计算振幅,依据振幅计算每单下单量。有开仓,加仓,止损,退出模块。资金用完了就停止开仓。
开仓逻辑:价格大于20天最大值,开仓
退出逻辑:价格低于5天最低值,平仓
想实现每天把沪深所有股票算一遍,符合条件就开仓。
当股票池只有2只股票,初始资金1亿的时候策略能够运行。
但是扩充股票池到所有股票,或者修改初始资金时,运行出错,都是KeyError: 。
想请问是哪里出错了?谢谢。

instruments=[‘600000.SHA’,‘600519.SHA’] #第一次运行:股票池含2只股票,capital_base =1亿,运行成功

#instruments=D.instruments(start_date,end_date) #第三次运行,股票池为所有股票,capital_base =1亿,结果:KeyError(运行耗时较长)
capital_base = 100000000
#capital_base = 1000000000 #第二次运行,股票池含2只股票,capital_base =10亿,结果:KeyError: ‘600000.SHA’


(xiaoxiao2017) #2

刚又运行了一下#第三次运行,股票池为所有股票,capital_base =1亿,结果很快就出来了,不是KeyError
变成了ValueError: cannot convert float NaN to integer,出错的是计算unit的版块


(xiaoxiao2017) #3

更新最新情况:
这两个问题看上去都解决了。
优化了context.N的计算,比如跳过停牌的日子之后,能顺利运行代码,还未检验结果。
虽然原先的出错信息KeyError还是很奇怪。
不知道换几个参数能否顺利运行。