克隆策略
In [15]:
# 本代码由可视化策略环境自动生成 2021年7月21日 19:51
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。

class conf:
    start_date = '2013-01-01'
    split_date = '2019-12-31'
    start_trade = '2020-01-01'
    end_date='2021-07-30'

    
    features1 = [
 'avg_turn_10',
'rank_return_40',
'ta_willr_28_0',
'avg_amount_5',
'fs_gross_profit_margin_0',
'fs_net_cash_flow_0',
'fs_free_cash_flow_0',
'avg_turn_40',
'fs_gross_profit_margin_ttm_0',
'(fs_current_liabilities_0+fs_non_current_liabilities_0)/ fs_common_equity_0',
'fs_roe_0',
'fs_common_equity_0',
'ta_sma_10_0',
'(high_0-low_0+high_1-low_1+high_2-low_2+high_3-low_3+high_4-low_4)/5',
'sh_holder_avg_pct_3m_chng_0',

    ]
    extra_fields = ['st_status_0',       
                    'price_limit_status_0',
                   ]
    
m1 = M.instruments.v2(
    start_date=conf.start_date,
    end_date=conf.split_date,
    market='CN_STOCK_A',
    instrument_list='',
    max_count=0
)

m2 = M.advanced_auto_labeler.v2(
    instruments=m1.data,
    label_expr="""# #号开始的表示注释
# 0. 每行一个,顺序执行,从第二个开始,可以使用label字段
# 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html
#   添加benchmark_前缀,可使用对应的benchmark数据
# 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_

# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
shift(close, -5) / shift(open, -1)

# 极值处理:用1%和99%分位的值做clip
clip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))

# 将分数映射到分类,这里使用20个分类
all_wbins(label, 20)

# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
where(shift(high, -1) == shift(low, -1), NaN, label)
""",
    start_date='',
    end_date='',
    benchmark='000300.SHA',
    drop_na_label=True,
    cast_label_int=True
)
m33 = M.input_features.v1(
    features=conf.features1
)

m3 = M.input_features.v1(
    features=conf.features1+conf.extra_fields
)



m4 = M.general_feature_extractor.v6(
    instruments=m1.data,
    features=m3.data,
    start_date='',
    end_date='',
    before_start_days=120
)

m5 = M.derived_feature_extractor.v2(
    input_data=m4.data,
    features=m3.data,
    date_col='date',
    instrument_col='instrument'
)

m7 = M.join.v3(
    data1=m2.data,
    data2=m5.data,
    on='date,instrument',
    how='inner',
    sort=False
)

# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m15_run_bigquant_run(input_1, input_2, input_3):
    # 示例代码如下。在这里编写您的代码

    df = input_1.read_df()
    ins= m1.data.read_pickle()['instruments']
    start= m1.data.read_pickle()['start_date']
    end= m1.data.read_pickle()['end_date']
    
    df1 = D.features(ins, start, end, fields=['mf_net_pct_main_0','market_cap_float_0'])#,'mf_net_amount_0'

    df_final=pd.merge(df,df1,on=['date','instrument'])
    df_final = df_final[df_final['mf_net_pct_main_0'] > 0.1]
    df_final = df_final[df_final['price_limit_status_0'] == 2]
    df_final = df_final[df_final['market_cap_float_0'] < 10000000000]

    
    print('-----------------------------------',len(df_final))
    data_1 = DataSource.write_df(df_final)  

    return Outputs(data_1=data_1, data_2=None, data_3=None)

m15 = M.cached.v3(
    input_1=m7.data,
    run=m15_run_bigquant_run
)

m13 = M.dropnan.v1(
    input_data=m15.data_1
)

m6 = M.stock_ranker_train.v5(
    training_ds=m13.data,
    features=m33.data,
    learning_algorithm='排序',
    number_of_leaves=30,
    minimum_docs_per_leaf=1000,
    number_of_trees=20,
    learning_rate=0.1,
    max_bins=1023,
    feature_fraction=1,
    m_lazy_run=False
)

m9 = M.instruments.v2(
    start_date=T.live_run_param('trading_date', conf.start_trade),
    end_date=T.live_run_param('trading_date', conf.end_date),
    market='CN_STOCK_A',
    instrument_list="""603700.SHA
603203.SHA
603757.SHA
002111.SZA
603277.SHA
300109.SZA
300406.SZA
002903.SZA
300441.SZA
002853.SZA
002940.SZA
601126.SHA
002614.SZA
300788.SZA
300396.SZA
300286.SZA
300778.SZA
603898.SHA
300695.SZA
603538.SHA
603697.SHA
300607.SZA
603607.SHA
300095.SZA
601566.SHA
603096.SHA
002832.SZA
300119.SZA
002833.SZA
002847.SZA
002322.SZA
300800.SZA
300206.SZA
300664.SZA
600285.SHA
002728.SZA
603258.SHA
603808.SHA
603777.SHA
002345.SZA
000582.SZA
603587.SHA
002492.SZA
603508.SHA
002818.SZA
603367.SHA
300639.SZA
600633.SHA
603297.SHA
300434.SZA
002293.SZA
300403.SZA

""",
    max_count=0
)

m10 = M.general_feature_extractor.v6(
    instruments=m9.data,
    features=m3.data,
    start_date='',
    end_date='',
    before_start_days=120
)

m11 = M.derived_feature_extractor.v2(
    input_data=m10.data,
    features=m3.data,
    date_col='date',
    instrument_col='instrument'
)

# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m16_run_bigquant_run(input_1, input_2, input_3):
    # 示例代码如下。在这里编写您的代码

    df = input_1.read_df()
    ins= m9.data.read_pickle()['instruments']
    start= m9.data.read_pickle()['start_date']
    end= m9.data.read_pickle()['end_date']
    df1 = D.features(ins, start, end, fields=['mf_net_pct_main_0','market_cap_float_0'])#,'mf_net_amount_0'

    
    df_final=pd.merge(df,df1,on=['date','instrument'])
    df_final = df_final[df_final['mf_net_pct_main_0'] > 0.1]
    df_final = df_final[df_final['price_limit_status_0'] == 2]
    df_final = df_final[df_final['market_cap_float_0'] < 10000000000]
    df_final = df_final[df_final['st_status_0'] == 0]
    print('-----------------------------------',len(df_final))
    data_1 = DataSource.write_df(df_final)


    return Outputs(data_1=data_1, data_2=None, data_3=None)
m16 = M.cached.v3(
    input_1=m11.data,
    run=m16_run_bigquant_run
)

m14 = M.dropnan.v2(
    input_data=m16.data_1
)

m8 = M.stock_ranker_predict.v5(
    model=m6.model,
    data=m14.data,
    m_lazy_run=False
)

# 回测引擎:每日数据处理函数,每天执行一次
def m12_handle_data_bigquant_run(context, data):
    
    # 按日期过滤得到今日的预测数据
    ranker_prediction = context.ranker_prediction[
        context.ranker_prediction.date == data.current_dt.strftime('%Y-%m-%d')]

    # 1. 资金分配
    # 平均持仓时间是hold_days,每日都将买入股票,每日预期使用 1/hold_days 的资金
    # 实际操作中,会存在一定的买入误差,所以在前hold_days天,等量使用资金;之后,尽量使用剩余资金(这里设置最多用等量的1.5倍)
    is_staging = context.trading_day_index < context.options['hold_days'] # 是否在建仓期间(前 hold_days 天)
    cash_avg = context.portfolio.portfolio_value / context.options['hold_days']
    cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)
    cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)
    positions = {e.symbol: p.amount * p.last_sale_price
                 for e, p in context.perf_tracker.position_tracker.positions.items()}

    # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰
    if not is_staging and cash_for_sell > 0:
        equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}
        instruments = []
        for x in equities :
            if not context.has_unfinished_sell_order(equities[x]):
                instruments.append(x)
                
        for instrument in instruments:
            context.order_target(context.symbol(instrument), 0)
            cash_for_sell -= positions[instrument]
            if cash_for_sell <= 0:
                break

    # 3. 生成买入订单:按机器学习算法预测的排序,买入前面的stock_count只股票
    buy_cash_weights = context.stock_weights
    buy_instruments = list(ranker_prediction.instrument[:len(buy_cash_weights)])
    max_cash_per_instrument = context.portfolio.portfolio_value * context.max_cash_per_instrument
    for i, instrument in enumerate(buy_instruments):
        cash = cash_for_buy * buy_cash_weights[i]
        if cash > max_cash_per_instrument - positions.get(instrument, 0):
            # 确保股票持仓量不会超过每次股票最大的占用资金量
            cash = max_cash_per_instrument - positions.get(instrument, 0)
        if cash > 0:
            current_price = data.current(context.symbol(instrument), 'price')
            amount = math.floor(cash / current_price - cash / current_price % 100)
            context.order(context.symbol(instrument), amount)

# 回测引擎:准备数据,只执行一次
def m12_prepare_bigquant_run(context):
    pass

# 回测引擎:初始化函数,只执行一次
def m12_initialize_bigquant_run(context):
    # 加载预测数据
    context.ranker_prediction = context.options['data'].read_df()

    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=3))
    # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
    # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只
    stock_count = 1
    # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[0.339160, 0.213986, 0.169580, ..]
    context.stock_weights = T.norm([1 / math.log(i + 2) for i in range(0, stock_count)])
    # 设置每只股票占用的最大资金比例
    context.max_cash_per_instrument = 0.9
    context.options['hold_days'] = 1

m12 = M.trade.v3(
    instruments=m9.data,
    options_data=m8.predictions,
    start_date='',
    end_date='',
    handle_data=m12_handle_data_bigquant_run,
    prepare=m12_prepare_bigquant_run,
    initialize=m12_initialize_bigquant_run,
    volume_limit=0.025,
    order_price_field_buy='open',
    order_price_field_sell='close',
    capital_base=50000, 
    benchmark='000300.SHA',
    auto_cancel_non_tradable_orders=True,
    data_frequency='daily',
    price_type='真实价格',
    plot_charts=True,
    backtest_only=False,
    amount_integer=False
)
设置测试数据集,查看训练迭代过程的NDCG
bigcharts-data-start/{"__type":"tabs","__id":"bigchart-5c1f0d79a40b4fdc933fb5263886a1dd"}/bigcharts-data-end
  • 收益率36.55%
  • 年化收益率22.75%
  • 基准收益率17.44%
  • 阿尔法0.2
  • 贝塔0.34
  • 夏普比率0.73
  • 胜率0.47
  • 盈亏比-1.49
  • 收益波动率30.11%
  • 信息比率0.02
  • 最大回撤20.49%
bigcharts-data-start/{"__type":"tabs","__id":"bigchart-f1400f5b5d444d6e8725d81e2e03c6b6"}/bigcharts-data-end