# 本代码由可视化策略环境自动生成 2022年3月28日 10:34
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
# 回测引擎:初始化函数,只执行一次
def m6_initialize_bigquant_run(context):
# 加载股票指标数据,数据继承自m6模块
context.indicator_data = context.options['data'].read_df()
# 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
context.set_commission(PerOrder(buy_cost=0.0001, sell_cost=0.001, min_cost=5))
# 设置股票数量
context.stock_num = 30
#每月调仓:则需要将输入特征数据转换为月度数据
context.month_data = context.indicator_data.groupby('instrument').resample(rule='M', on='date')
context.month_data = context.month_data.agg({
'instrument': 'last',
'date':'last',
'list_days_0': 'last',
'market_cap_0': 'last',
'pe_ttm_0': 'last',
})
context.month_data = context.month_data.reset_index(drop=True)
#每月调仓,改用每月调用一次主处理函数
schedule_function(func=month_handle_data,
date_rule=date_rules.month_start(), # 例如每周开始时执行一次
time_rule=time_rules.market_open()) # 开盘执行
from datetime import timedelta
#每月初调用一次主处理函数,在本函数进行目标股票获取并进行买卖
def month_handle_data(context, data):
# 当前的日期
date = data.current_dt.strftime('%Y-%m-%d')
#根据当前时间获取上一个月的时间。当前月初往前偏移28天一定是上个月
last_month = str(pd.to_datetime(date) + timedelta(days=-28))[0:7]
#获取上个月末的股票池
df = context.month_data
tempdf = df[df['date'].astype(str).apply(lambda x:x[0:7])==last_month]
#对股票池根据因子值列进行排序,并取前30只股票
stocks = tempdf.sort_values('pe_ttm_0').iloc[:context.stock_num,:]
#把股票id转换成需要购买的股票列表
stock_to_buy = stocks['instrument'].values.tolist()
print("选股日期:",date,',选股数量:',len(stock_to_buy))
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')
# 亏10%就止损
if (stock_market_price - stock_cost) / stock_cost <= -0.10:
context.order_target_percent(context.symbol(i),0)
current_stoploss_stock.append(i)
# print('日期:',date,'股票:',i,'出现止损状况')
# 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
stock_hold_now = [equity.symbol for equity in context.portfolio.positions]
# 继续持有的股票:调仓时,如果买入的股票已经存在于目前的持仓里,那么应继续持有
no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]
# 需要卖出的股票
stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]
# 卖出
for stock in stock_to_sell:
# 如果该股票停牌,则没法成交。因此需要用can_trade方法检查下该股票的状态
# 如果返回真值,则可以正常下单,否则会出错
# 因为stock是字符串格式,我们用symbol方法将其转化成平台可以接受的形式:Equity格式
if data.can_trade(context.symbol(stock)):
context.order_target_percent(context.symbol(stock), 0)
# 如果当天没有买入的股票,就返回
if len(stock_to_buy) == 0:
return
# 等权重买入
weight = 1 / len(stock_to_buy)
# 买入
for stock in stock_to_buy:
if data.can_trade(context.symbol(stock)):
# 下单使得某只股票的持仓权重达到weight,因为
# weight大于0,因此是等权重买入
context.order_target_percent(context.symbol(stock), weight)
# 回测引擎:每日数据处理函数,每天执行一次
def m6_handle_data_bigquant_run(context, data):
pass
# 回测引擎:准备数据,只执行一次
def m6_prepare_bigquant_run(context):
pass
# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
def m6_before_trading_start_bigquant_run(context, data):
pass
m1 = M.instruments.v2(
start_date='2018-01-01',
end_date='2020-12-31',
market='CN_STOCK_A',
instrument_list='',
max_count=0
)
m2 = M.input_features.v1(
features="""
# #号开始的表示注释,注释需单独一行
# 多个特征,每行一个,可以包含基础特征和衍生特征,特征须为本平台特征
pe_ttm_0
market_cap_0
list_days_0"""
)
m15 = M.general_feature_extractor.v7(
instruments=m1.data,
features=m2.data,
start_date='',
end_date='',
before_start_days=0
)
m5 = M.chinaa_stock_filter.v1(
input_data=m15.data,
index_constituent_cond=['全部'],
board_cond=['全部'],
industry_cond=['全部'],
st_cond=['正常'],
delist_cond=['全部'],
output_left_data=False
)
m4 = M.filter.v3(
input_data=m5.data,
expr='(market_cap_0 < 5000000000) & (list_days_0 > 60) & (pe_ttm_0 > 0)',
output_left_data=False
)
m3 = M.sort.v5(
input_ds=m4.data,
sort_by='pe_ttm_0',
group_by='date',
keep_columns='--',
ascending=True
)
m6 = M.trade.v4(
instruments=m1.data,
options_data=m3.sorted_data,
start_date='',
end_date='',
initialize=m6_initialize_bigquant_run,
handle_data=m6_handle_data_bigquant_run,
prepare=m6_prepare_bigquant_run,
before_trading_start=m6_before_trading_start_bigquant_run,
volume_limit=0.025,
order_price_field_buy='open',
order_price_field_sell='open',
capital_base=100000000,
auto_cancel_non_tradable_orders=True,
data_frequency='daily',
price_type='后复权',
product_type='股票',
plot_charts=True,
backtest_only=False,
benchmark=''
)
[2022-03-28 12:15:39.455135] INFO: moduleinvoker: instruments.v2 开始运行..
[2022-03-28 12:15:39.463076] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.464451] INFO: moduleinvoker: instruments.v2 运行完成[0.009321s].
[2022-03-28 12:15:39.467950] INFO: moduleinvoker: input_features.v1 开始运行..
[2022-03-28 12:15:39.479779] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.480985] INFO: moduleinvoker: input_features.v1 运行完成[0.013033s].
[2022-03-28 12:15:39.495397] INFO: moduleinvoker: general_feature_extractor.v7 开始运行..
[2022-03-28 12:15:39.504550] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.505843] INFO: moduleinvoker: general_feature_extractor.v7 运行完成[0.010449s].
[2022-03-28 12:15:39.514957] INFO: moduleinvoker: chinaa_stock_filter.v1 开始运行..
[2022-03-28 12:15:39.532643] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.533815] INFO: moduleinvoker: chinaa_stock_filter.v1 运行完成[0.018855s].
[2022-03-28 12:15:39.541550] INFO: moduleinvoker: filter.v3 开始运行..
[2022-03-28 12:15:39.549753] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.551116] INFO: moduleinvoker: filter.v3 运行完成[0.009571s].
[2022-03-28 12:15:39.555873] INFO: moduleinvoker: sort.v5 开始运行..
[2022-03-28 12:15:39.569957] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.571177] INFO: moduleinvoker: sort.v5 运行完成[0.015302s].
[2022-03-28 12:15:39.628662] INFO: moduleinvoker: backtest.v8 开始运行..
[2022-03-28 12:15:39.633586] INFO: backtest: biglearning backtest:V8.6.2
[2022-03-28 12:15:39.634645] INFO: backtest: product_type:stock by specified
[2022-03-28 12:15:39.731001] INFO: moduleinvoker: cached.v2 开始运行..
[2022-03-28 12:15:39.738703] INFO: moduleinvoker: 命中缓存
[2022-03-28 12:15:39.740264] INFO: moduleinvoker: cached.v2 运行完成[0.009287s].
[2022-03-28 12:15:42.730160] INFO: algo: TradingAlgorithm V1.8.7
[2022-03-28 12:16:24.842928] INFO: algo: trading transform...
[2022-03-28 12:16:44.798723] INFO: Performance: Simulated 730 trading days out of 730.
[2022-03-28 12:16:44.800031] INFO: Performance: first open: 2018-01-02 09:30:00+00:00
[2022-03-28 12:16:44.801037] INFO: Performance: last close: 2020-12-31 15:00:00+00:00
[2022-03-28 12:16:49.617147] INFO: moduleinvoker: backtest.v8 运行完成[69.988473s].
[2022-03-28 12:16:49.618926] INFO: moduleinvoker: trade.v4 运行完成[70.042299s].