请问为什么会报错?换成002049不会报错

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

(chidaye) #1
克隆策略
In [2]:
# 获取股票代码
instruments = ['600520.SHA']  
# 确定起始时间
start_date = '2014-01-01' 
# 确定结束时间
end_date = '2018-04-09' 
# 获取股票市净率数据,返回DataFrame数据格式

   #利用API获取数据
ey_data = D.history_data(instruments, start_date , end_date, fields=['close','high','low'],price_type='forward_adjusted')
ey_data['up_line'] = np.nan     #用于存放计算好的蓝线,下面类同
ey_data['min_line'] = np.nan
ey_data['down_line'] = np.nan
ey_data['(H+L)/2'] = (ey_data['high']+ey_data['low'])/2   #计算最高价和最低价的均值
#计算三条鳄鱼线
#计算三条鳄鱼线
for i in range(21,len(ey_data)):
    ey_data['down_line'][i] = ey_data['(H+L)/2'][i-21:i-8].mean()
    ey_data['min_line'][i] = ey_data['(H+L)/2'][i-13:i-5].mean()
    ey_data['up_line'][i] = ey_data['(H+L)/2'][i-8:i-3].mean()
    ey_data = ey_data.dropna()  #去掉缺省值

    ey_data['gold_cross_status'] = (ey_data['up_line'] > ey_data['min_line'])&(ey_data['min_line'] > ey_data['down_line'])
    ey_data['pos_percent'] = np.where(ey_data['gold_cross_status'],1,0)
    pos_df = ey_data[['date', 'pos_percent']].set_index('date')

#结合大盘指数卖出
bm_price = D.history_data(['000300.SHA'], start_date , end_date, fields=['close'])
bm_price['sma'] = bm_price['close'].rolling(5).mean()
bm_price['lma'] = bm_price['close'].rolling(30).mean()
bm_price['gold_cross_status'] = bm_price['sma'] > bm_price['lma']
bm_price['pos_percent'] = np.where(bm_price['gold_cross_status'],1,0)
bm_pos_df = bm_price[['date', 'pos_percent']].set_index('date')


# 2. 策略主体函数
# 回测参数设置,initialize函数只运行一次
def initialize(context):
    # 手续费设置
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) # 设置手续费,买入成本为万分之三,卖出为千分之1.3
    
    context.ins = context.instruments
    context.weights = 1/len(context.instruments)
    context.pos = pos_df
    context.bm_pos = bm_pos_df
def handle_data(context, data):
    date = data.current_dt.strftime('%Y-%m-%d')  
    #------------------------------------------止赢模块START--------------------------------------------
    positions = {e.symbol: p.cost_basis  for e, p in context.portfolio.positions.items()}
    # 新建当日止赢股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
    current_stopwin_stock = [] 
    if len(positions) > 0:
        for i in positions.keys():
            stock_cost = positions[i] 
            stock_market_price = data.current(context.symbol(i), 'price') 
            # 赚10%就止赢
            if (stock_market_price - stock_cost ) / stock_cost>= 0.75:   
                context.order_target_percent(context.symbol(i),0)     
                current_stopwin_stock.append(i)
                print('日期:',date,'股票:',i,'出现止盈状况')  
                
    #-------------------------------------------止赢模块END---------------------------------------------
  #------------------------------------------止损模块START--------------------------------------------
    positions = {e.symbol: p.cost_basis  for e, p in context.portfolio.positions.items()}
    # 新建当日止损股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
    current_stoploss_stock = [] 
    if len(positions) > 0:
        for i in positions.keys():
            stock_cost = positions[i] 
            stock_market_price = data.current(context.symbol(i), 'price') 
            # 亏5%就止损
            if (stock_market_price - stock_cost) / stock_cost <= -0.65:   
                context.order_target_percent(context.symbol(i),0)     
                current_stoploss_stock.append(i)
                print('日期:',date,'股票:',i,'出现止损状况')
    #-------------------------------------------止损模块END---------------------------------------------

    
   
     
    # 长期均线值要有意义,需要在60根k线之后
    if context.trading_day_index <  21:     
        return
    for k in context.instruments:
        if k in current_stoploss_stock or k in current_stopwin_stock:
             continue
        sid = context.symbol(k) # 将标的转化为equity格式
        price = data.current(sid, 'price') # 最新价格
        
        cash = context.portfolio.portfolio_value  # 现金
        cur_position = context.portfolio.positions[sid].amount # 持仓
             # 买入
        if context.pos.ix[date].pos_percent == 1:
            if  cur_position == 0 and data.can_trade(sid):  
                context.order_target_percent(sid, context.weights) # 买入
                     
             # 卖出
        if context.bm_pos.ix[date].pos_percent == 0:  
                 # 进行清仓
            if cur_position > 0 and data.can_trade(sid):
                context.order_target_value(sid, 0)    
           
                     
                

# 3. 启动回测

m = M.trade.v2( 
    instruments=instruments,
    start_date=start_date, 
    end_date=end_date,
    # 必须传入initialize,只在第一天运行
    initialize=initialize,
    #  必须传入handle_data,每个交易日都会运行
    handle_data=handle_data,
    # 买入以开盘价成交
    order_price_field_buy='open',
    # 卖出也以开盘价成交
    order_price_field_sell='open',
    # 策略本金
    capital_base=60000,
    # 比较基准:沪深300
    benchmark='000300.INDX',
    price_type='forward_adjusted'
)
[2018-04-17 09:35:15.647444] INFO: bigquant: backtest.v7 开始运行..
[2018-04-17 09:35:15.749836] INFO: algo: set price type:forward_adjusted
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: an integer is required

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: '2014-02-10'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
TypeError: an integer is required

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: '2014-02-10'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: 1391990400000000000

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: Timestamp('2014-02-10 00:00:00')

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: 1391990400000000000

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: Timestamp('2014-02-10 00:00:00')

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-2-0cd2e897b5ad> in <module>()
    123     # 比较基准:沪深300
    124     benchmark='000300.INDX',
--> 125     price_type='forward_adjusted'
    126 )
    127 

<ipython-input-2-0cd2e897b5ad> in handle_data(context, data)
     92         cur_position = context.portfolio.positions[sid].amount # 持仓
     93              # 买入
---> 94         if context.pos.ix[date].pos_percent == 1:
     95             if  cur_position == 0 and data.can_trade(sid):
     96                 context.order_target_percent(sid, context.weights) # 买入

KeyError: '2014-02-10'

(达达) #2

您好,建议您优化一下代码,按我的理解您需要的是计算指标然后结合风控做交易。
1、在计算指标时可以考虑采用rolling的方式计算来替代for循环可以大大提速 例如:
ey_data[‘down_line’] = ey_data[’(H+L)/2’].rolling(13).mean().shift(8)
2、您在做大盘风控时有个计算指标也是向前引用,这个引用日期如果超过股票指标引用周期的话可能在主函数中引用不到,可以把大盘指标向前引用一段时间保证风控的指标是完整的
strat_date=(datetime.datetime.strptime(start_date,"%Y-%m-%d")-datetime.timedelta(days = 10)).strftime("%Y-%m-%d")
bm_price = D.history_data([‘000300.SHA’], start_date , end_date, fields=[‘close’])
3、修改后的策略

克隆策略
In [120]:
# 获取股票代码
instruments = ['600520.SHA']  
# 确定起始时间
start_date = '2010-12-01' 
# 确定结束时间
end_date = '2018-04-09' 
# 获取股票市净率数据,返回DataFrame数据格式

   #利用API获取数据
ey_data = D.history_data(instruments, start_date , end_date, fields=['close','high','low'],price_type='forward_adjusted')
ey_data['up_line'] = np.nan     #用于存放计算好的蓝线,下面类同
ey_data['min_line'] = np.nan
ey_data['down_line'] = np.nan
ey_data['(H+L)/2'] = (ey_data['high']+ey_data['low'])/2   #计算最高价和最低价的均值
In [121]:
#计算三条鳄鱼线
#计算三条鳄鱼线 缺失的数据直接用(H+L)/2补全以免影响判断,也可以考虑在回测中计算,通过天数控制开始交易时间
ey_data['down_line'] = ey_data['(H+L)/2'].rolling(13).mean().shift(8)
ey_data['down_line']=ey_data['down_line'].fillna(ey_data['(H+L)/2'])
ey_data['min_line'] = ey_data['(H+L)/2'].rolling(8).mean().shift(5)
ey_data['min_line']=ey_data['min_line'].fillna(ey_data['(H+L)/2'])
ey_data['up_line'] = ey_data['(H+L)/2'].rolling(5).mean().shift(3)
ey_data['up_line']=ey_data['up_line'].fillna(ey_data['(H+L)/2'])
ey_data['gold_cross_status'] = (ey_data['up_line'] > ey_data['min_line'])&(ey_data['min_line'] > ey_data['down_line'])
ey_data['pos_percent'] = np.where(ey_data['gold_cross_status'],1,0)
pos_df = ey_data[['date', 'pos_percent']].set_index('date')
In [152]:
import datetime
import time 
#结合大盘指数卖出 这里最长引用了30天,为了不与个股的指标最长引用周期21冲突,可以把历史数据提前几天(这里提前10天),保证在21到30天之间的bm有数据
strat_date=(datetime.datetime.strptime(start_date,"%Y-%m-%d")-datetime.timedelta(days = 10)).strftime("%Y-%m-%d")
bm_price = D.history_data(['000300.SHA'], start_date , end_date, fields=['close'])
bm_price['sma'] = bm_price['close'].rolling(5).mean()
bm_price['lma'] = bm_price['close'].rolling(30).mean()
bm_price['gold_cross_status'] = bm_price['sma'] > bm_price['lma']
bm_price['pos_percent'] = np.where(bm_price['gold_cross_status'],1,0)
bm_pos_df = bm_price[['date', 'pos_percent']].set_index('date')
In [153]:
# 2. 策略主体函数
# 回测参数设置,initialize函数只运行一次
def initialize(context):
    # 手续费设置
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) # 设置手续费,买入成本为万分之三,卖出为千分之1.3
    
    context.ins = context.instruments
    context.weights = 1/len(context.instruments)
    context.pos = pos_df
    context.bm_pos = bm_pos_df
def handle_data(context, data):
    date = data.current_dt.strftime('%Y-%m-%d')  
    #------------------------------------------止赢模块START--------------------------------------------
    positions = {e.symbol: p.cost_basis  for e, p in context.portfolio.positions.items()}
    # 新建当日止赢股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
    current_stopwin_stock = [] 
    if len(positions) > 0:
        for i in positions.keys():
            stock_cost = positions[i] 
            stock_market_price = data.current(context.symbol(i), 'price') 
            # 赚10%就止赢
            if (stock_market_price - stock_cost ) / stock_cost>= 0.75:   
                context.order_target_percent(context.symbol(i),0)     
                current_stopwin_stock.append(i)
                print('日期:',date,'股票:',i,'出现止盈状况')  
                
    #-------------------------------------------止赢模块END---------------------------------------------
  #------------------------------------------止损模块START--------------------------------------------
    positions = {e.symbol: p.cost_basis  for e, p in context.portfolio.positions.items()}
    # 新建当日止损股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
    current_stoploss_stock = [] 
    if len(positions) > 0:
        for i in positions.keys():
            stock_cost = positions[i] 
            stock_market_price = data.current(context.symbol(i), 'price') 
            # 亏5%就止损
            if (stock_market_price - stock_cost) / stock_cost <= -0.65:   
                context.order_target_percent(context.symbol(i),0)     
                current_stoploss_stock.append(i)
                print('日期:',date,'股票:',i,'出现止损状况')
    #-------------------------------------------止损模块END---------------------------------------------

    
   
     
    # 长期均线值要有意义,需要在60根k线之后
    if context.trading_day_index <  30:     
        return
    for k in context.instruments:
        if k in current_stoploss_stock or k in current_stopwin_stock:
             continue
        sid = context.symbol(k) # 将标的转化为equity格式
        price = data.current(sid, 'price') # 最新价格
        
        cash = context.portfolio.portfolio_value  # 现金
        cur_position = context.portfolio.positions[sid].amount # 持仓
             # 买入
        if context.pos.ix[date].pos_percent == 1:
            if  cur_position == 0 and data.can_trade(sid):  
                context.order_target_percent(sid, context.weights) # 买入
                     
             # 卖出
        if context.bm_pos.ix[date].pos_percent == 0:  
                 # 进行清仓
            if cur_position > 0 and data.can_trade(sid):
                context.order_target_value(sid, 0)    
           
                     
                

# 3. 启动回测

m = M.trade.v2( 
    instruments=instruments,
    start_date=start_date, 
    end_date=end_date,
    # 必须传入initialize,只在第一天运行
    initialize=initialize,
    #  必须传入handle_data,每个交易日都会运行
    handle_data=handle_data,
    # 买入以开盘价成交
    order_price_field_buy='open',
    # 卖出也以开盘价成交
    order_price_field_sell='open',
    # 策略本金
    capital_base=60000,
    # 比较基准:沪深300
    benchmark='000300.INDX',
    price_type='forward_adjusted'
)
[2018-04-17 13:27:01.234203] INFO: bigquant: backtest.v7 开始运行..
[2018-04-17 13:27:01.242869] INFO: bigquant: 命中缓存
  • 收益率14.61%
  • 年化收益率1.94%
  • 基准收益率22.82%
  • 阿尔法-0.02
  • 贝塔0.34
  • 夏普比率-0.07
  • 胜率0.514
  • 盈亏比1.058
  • 收益波动率34.4%
  • 信息比率-0.03
  • 最大回撤75.61%
[2018-04-17 13:27:04.530801] INFO: bigquant: backtest.v7 运行完成[3.296591s].
In [ ]: