版本 v1.0
### 事件驱动策略的交易规则
### 策略构建步骤
### 策略的实现
可视化策略实现如下:
# 本代码由可视化策略环境自动生成 2021年12月6日 22:16
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m4_run_bigquant_run(input_1, input_2, input_3):
# 示例代码如下。在这里编写您的代码
#start_date=input_1.read_pickle()['start_date']
start_date=(pd.to_datetime(input_1.read_pickle()['start_date']) - datetime.timedelta(days=100)).strftime('%Y-%m-%d')
end_date=input_1.read_pickle()['end_date']
instruments=input_1.read_pickle()['instruments']
df = DataSource('financial_statement_CN_STOCK_A').read(instruments,start_date,end_date,\
['fs_publish_date','fs_quarter_year','fs_quarter_index','fs_net_profit_yoy'])
data_1 = DataSource.write_df(df)
return Outputs(data_1=data_1, data_2=None, data_3=None)
# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
def m4_post_run_bigquant_run(outputs):
return outputs
# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m9_run_bigquant_run(input_1, input_2, input_3):
# 示例代码如下。在这里编写您的代码
# 获取交易日历
start_date=(pd.to_datetime(input_1.read_pickle()['start_date']) - datetime.timedelta(days=100)).strftime('%Y-%m-%d')
end_date=input_1.read_pickle()['end_date']
df = D.trading_days(start_date=start_date,end_date=end_date)
# 为尽量接近实盘,事件日期应为财报公布日的前一天
df['shift_date']=df.shift(1)
data_1 = DataSource.write_df(df)
return Outputs(data_1=data_1, data_2=None, data_3=None)
# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
def m9_post_run_bigquant_run(outputs):
return outputs
# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m7_run_bigquant_run(input_1, input_2, input_3):
# 示例代码如下。在这里编写您的代码
df1 = input_1.read_df()
df2 = input_2.read_df()
df_merge=pd.merge(df1,df2,on='date',how='left')#.drop(['date'],axis=1).rename(columns={'shift_date':'date'})
data_1 = DataSource.write_df(df_merge)
return Outputs(data_1=data_1, data_2=None, data_3=None)
# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
def m7_post_run_bigquant_run(outputs):
return outputs
# 回测引擎:初始化函数,只执行一次
def m3_initialize_bigquant_run(context):
context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
context.hold_periods = 40 # 持有40天,固定持仓期
context.stock_max_num = 50 # 最大持仓数量为50只
# 回测引擎:每日数据处理函数,每天执行一次
def m3_handle_data_bigquant_run(context, data):
today = data.current_dt.strftime('%Y-%m-%d') # 日期
# 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表和对应的最新市值
equities = {e.symbol: p for e, p in context.portfolio.positions.items() if p.amount>0}
# 记录持仓股票数量
hold_num = len(equities)
# 记录用于买入股票的可用现金
cash_for_buy = context.portfolio.cash
for instrument in equities.keys():
# 如果持仓时间大于40天
sid = equities[instrument].sid # 交易标的
# 今天和上次交易的时间相隔hold_days就全部卖出
dt = pd.to_datetime(D.trading_days(end_date = today).iloc[-context.hold_periods].values[0])
if pd.to_datetime(equities[instrument].last_sale_date.strftime('%Y-%m-%d')) <= dt and data.can_trade(context.symbol(instrument)):
# 卖出股票并更新持股数量
context.order_target_percent(sid, 0)
hold_num -= 1
# 因为是早盘卖股票早盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;
# 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用
cash_for_buy += equities[instrument].amount * equities[instrument].last_sale_price
# 当日还允许买入建仓的股票数目
stock_can_buy_num = context.stock_max_num - hold_num
try:
daily_stock_buy = context.daily_stock_buy[today] # 当日符合买入条件的股票
except:
daily_stock_buy = [] # 如果没有符合条件的股票,就设置为空
stock_to_buy = [k for k in daily_stock_buy if k not in equities]
stock_to_buy_num = min(stock_can_buy_num,len(stock_to_buy))
# 如果不需要买入股票就返回,当日不执行买入操作
if stock_to_buy_num > 0:
buy_num = 0
# 买入满足条件的股票,使用可用现金等额买入
for stock in stock_to_buy:
cash = cash_for_buy / stock_to_buy_num
if data.can_trade(context.symbol(stock)) and buy_num<stock_to_buy_num:
context.order_target_value(context.symbol(stock), cash)
buy_num += 1
# 回测引擎:准备数据,只执行一次
def m3_prepare_bigquant_run(context):
# 加载预测数据
df = context.options['data'].read_df()
df['date']=df['date'].apply(lambda x:x.strftime('%Y-%m-%d'))
# 函数:求满足开仓条件的股票列表
def open_pos_con(df):
return list(df.instrument)
# 每日买入股票的数据框
context.daily_stock_buy= df.groupby('date').apply(open_pos_con)
m1 = M.instruments.v2(
start_date=T.live_run_param('trading_date', '2017-07-01'),
end_date=T.live_run_param('trading_date', '2017-12-18'),
market='CN_STOCK_A',
instrument_list='',
max_count=0
)
m4 = M.cached.v3(
input_1=m1.data,
run=m4_run_bigquant_run,
post_run=m4_post_run_bigquant_run,
input_ports='',
params='{}',
output_ports=''
)
m9 = M.cached.v3(
input_1=m1.data,
run=m9_run_bigquant_run,
post_run=m9_post_run_bigquant_run,
input_ports='',
params='{}',
output_ports='',
m_cached=False
)
m7 = M.cached.v3(
input_1=m4.data_1,
input_2=m9.data_1,
run=m7_run_bigquant_run,
post_run=m7_post_run_bigquant_run,
input_ports='',
params='{}',
output_ports='',
m_cached=False
)
m6 = M.filter.v3(
input_data=m7.data_1,
expr='fs_net_profit_yoy>30',
output_left_data=False
)
m5 = M.sort.v4(
input_ds=m6.data,
sort_by='fs_net_profit_yoy',
group_by='date',
keep_columns='--',
ascending=False
)
m3 = M.trade.v4(
instruments=m1.data,
options_data=m5.sorted_data,
start_date='',
end_date='',
initialize=m3_initialize_bigquant_run,
handle_data=m3_handle_data_bigquant_run,
prepare=m3_prepare_bigquant_run,
volume_limit=0.025,
order_price_field_buy='open',
order_price_field_sell='open',
capital_base=1000000,
auto_cancel_non_tradable_orders=True,
data_frequency='daily',
price_type='后复权',
product_type='股票',
plot_charts=True,
backtest_only=False,
benchmark='000300.HIX'
)
[2021-03-25 15:17:25.386599] INFO: moduleinvoker: instruments.v2 开始运行..
[2021-03-25 15:17:25.510937] INFO: moduleinvoker: instruments.v2 运行完成[0.124326s].
[2021-03-25 15:17:25.527928] INFO: moduleinvoker: cached.v3 开始运行..
[2021-03-25 15:17:25.789331] INFO: moduleinvoker: cached.v3 运行完成[0.261402s].
[2021-03-25 15:17:25.792873] INFO: moduleinvoker: cached.v3 开始运行..
[2021-03-25 15:17:25.884038] INFO: moduleinvoker: cached.v3 运行完成[0.091142s].
[2021-03-25 15:17:25.889139] INFO: moduleinvoker: cached.v3 开始运行..
[2021-03-25 15:17:26.017452] INFO: moduleinvoker: cached.v3 运行完成[0.128308s].
[2021-03-25 15:17:26.027514] INFO: moduleinvoker: filter.v3 开始运行..
[2021-03-25 15:17:26.040515] INFO: filter: 使用表达式 fs_net_profit_yoy>30 过滤
[2021-03-25 15:17:26.126421] INFO: filter: 过滤 /data, 5120/0/12661
[2021-03-25 15:17:26.194438] INFO: moduleinvoker: filter.v3 运行完成[0.166896s].
[2021-03-25 15:17:26.202879] INFO: moduleinvoker: sort.v4 开始运行..
[2021-03-25 15:17:26.626713] INFO: moduleinvoker: sort.v4 运行完成[0.423828s].
[2021-03-25 15:17:28.454118] INFO: moduleinvoker: backtest.v8 开始运行..
[2021-03-25 15:17:28.467349] INFO: backtest: biglearning backtest:V8.5.0
[2021-03-25 15:17:28.563464] INFO: backtest: product_type:stock by specified
[2021-03-25 15:17:28.682567] INFO: moduleinvoker: cached.v2 开始运行..
[2021-03-25 15:17:38.780127] INFO: backtest: 读取股票行情完成:1240722
[2021-03-25 15:17:41.273240] INFO: moduleinvoker: cached.v2 运行完成[12.590676s].
[2021-03-25 15:17:42.696518] INFO: algo: TradingAlgorithm V1.8.1
[2021-03-25 15:17:42.991644] INFO: algo: trading transform...
[2021-03-25 15:17:55.437481] INFO: Performance: Simulated 116 trading days out of 116.
[2021-03-25 15:17:55.438905] INFO: Performance: first open: 2017-07-03 09:30:00+00:00
[2021-03-25 15:17:55.439861] INFO: Performance: last close: 2017-12-18 15:00:00+00:00
[2021-03-25 15:17:58.843906] INFO: moduleinvoker: backtest.v8 运行完成[30.389829s].
[2021-03-25 15:17:58.845450] INFO: moduleinvoker: trade.v4 运行完成[32.148798s].