def prepare(context):
# 加载原始数据
stock_raw_data = D.history_data(context.instruments, context.start_date, context.end_date, ['close','low'])
# 包含多个周期均线值的股票数据
stock_ma_data = stock_raw_data.groupby('instrument').apply(ma_calculate)
# 每日买入股票的数据框
context.daily_stock_to_buy= stock_ma_data.groupby('date').apply(open_pos_con)
# 每日卖出股票的数据框
context.daily_stock_to_sell= stock_ma_data.groupby('date').apply(close_pos_con)
# 计算多个周期均线的函数
def ma_calculate(df):
ma_list = [5,10,20,40,120]
for ma_len in ma_list:
df['ma_'+str(ma_len)] = df['close'].rolling( ma_len).mean()
return df
# 函数:求满足开仓条件的股票列表
def open_pos_con(df):
return list(df[(df['ma_5']>df['ma_10'])&(df['ma_10']>df['ma_20'])&(df['ma_20']>df['ma_40'])&(df['ma_40']>df['ma_120'])&(df['low']<df['ma_10'])].instrument)
# 函数:求满足平仓条件的股票列表
def close_pos_con(df):
return list(df[df['ma_5']<df['ma_40']].instrument)
# 初始化虚拟账户状态,只在第一个交易日运行
def initialize(context):
# 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
context.num_stock = 100 # 最多同时持有100只股票
# 策略交易逻辑,每个交易日运行一次
def handle_data(context, data):
date = data.current_dt.strftime('%Y-%m-%d') # 日期
buy_stock = context.daily_stock_to_buy[date] # 当日符合买入条件的股票
sell_stock = context.daily_stock_to_sell[date] # 当日符合卖出条件的股票
weight = 1/context.num_stock # 等权重配置
stock_hold_num = len(context.portfolio.positions) # 目前持有的股票数量
remain_num = context.num_stock - stock_hold_num # 还可以买入的股票数量,需要把卖出的股票加回来
# 初始化当日买入订单的数量为0
order_count = 0
# 买入股票
for i in buy_stock:
# 如果发送买入订单的股票数量已经超过了还可以买入的股票数量,那么应退出for循环
if order_count >= remain_num:
break
# 对于没有买入的股票且可以交易的股票,应买入
if context.portfolio.positions[context.symbol(i)].amount == 0 and data.can_trade(context.symbol(i)):
order_target_percent(context.symbol(i), weight)
order_count += 1 # 统计一下当天股票买入数量
# 卖出股票
for j in sell_stock:
if context.portfolio.positions[context.symbol(j)].amount > 0 and data.can_trade(context.symbol(j)):
order_target_percent(context.symbol(j), 0)
# 策略回测接口: https://bigquant.com/docs/strategy_backtest.html
m = M.trade.v3(
instruments=D.instruments(market='CN_STOCK_A'),
start_date='2013-01-01',
end_date='2015-01-21',
prepare=prepare, # 数据准备函数
initialize=initialize, # 初始化函数
handle_data=handle_data, # 策略主体函数
# 买入订单以开盘价成交
order_price_field_buy='open',
# 卖出订单以开盘价成交
order_price_field_sell='open',
capital_base=1000000,
benchmark='000300.INDX',
)
[2021-12-02 09:51:20.398349] INFO: moduleinvoker: backtest.v7 开始运行..
[2021-12-02 09:51:20.403487] INFO: backtest: biglearning backtest:V7.3.0
[2021-12-02 09:51:36.537527] INFO: moduleinvoker: cached.v2 开始运行..
[2021-12-02 09:51:36.544906] WARNING: bigdatasource: cannot find filed [settle] table in field_table_map!
[2021-12-02 09:51:43.754365] INFO: moduleinvoker: cached.v2 运行完成[7.216852s].
[2021-12-02 09:51:44.557881] INFO: algo: TradingAlgorithm V1.8.5
[2021-12-02 09:51:52.825007] INFO: algo: trading transform...
[2021-12-02 09:52:10.517311] INFO: Performance: Simulated 496 trading days out of 496.
[2021-12-02 09:52:10.520490] INFO: Performance: first open: 2013-01-04 09:30:00+00:00
[2021-12-02 09:52:10.523909] INFO: Performance: last close: 2015-01-21 15:00:00+00:00
[2021-12-02 09:52:13.418314] INFO: moduleinvoker: backtest.v7 运行完成[53.019934s].
[2021-12-02 09:52:13.421942] INFO: moduleinvoker: trade.v3 运行完成[53.032784s].