复制链接
克隆策略

    {"description":"实验创建于2017/8/26","graph":{"edges":[{"to_node_id":"-513:model","from_node_id":"-134:model"},{"to_node_id":"-893:options_data","from_node_id":"-513:predictions"},{"to_node_id":"-134:training_ds","from_node_id":"-100:data"},{"to_node_id":"-134:features","from_node_id":"-100:features"},{"to_node_id":"-513:data","from_node_id":"-109:data"},{"to_node_id":"-893:instruments","from_node_id":"-109:instruments"}],"nodes":[{"node_id":"-134","module_id":"BigQuantSpace.dai_stock_ranker_train.dai_stock_ranker_train-v1","parameters":[{"name":"learning_algorithm","value":"排序","type":"Literal","bound_global_parameter":null},{"name":"number_of_leaves","value":30,"type":"Literal","bound_global_parameter":null},{"name":"minimum_docs_per_leaf","value":1000,"type":"Literal","bound_global_parameter":null},{"name":"number_of_trees","value":20,"type":"Literal","bound_global_parameter":null},{"name":"learning_rate","value":0.1,"type":"Literal","bound_global_parameter":null},{"name":"max_bins","value":1023,"type":"Literal","bound_global_parameter":null},{"name":"feature_fraction","value":1,"type":"Literal","bound_global_parameter":null},{"name":"data_row_fraction","value":1,"type":"Literal","bound_global_parameter":null},{"name":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"ndcg_discount_base","value":1,"type":"Literal","bound_global_parameter":null},{"name":"m_lazy_run","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"training_ds","node_id":"-134"},{"name":"features","node_id":"-134"},{"name":"test_ds","node_id":"-134"},{"name":"base_model","node_id":"-134"}],"output_ports":[{"name":"model","node_id":"-134"},{"name":"feature_gains","node_id":"-134"},{"name":"m_lazy_run","node_id":"-134"}],"cacheable":true,"seq_num":9,"comment":"","comment_collapsed":true},{"node_id":"-513","module_id":"BigQuantSpace.dai_stock_ranker_predict.dai_stock_ranker_predict-v1","parameters":[{"name":"m_lazy_run","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"model","node_id":"-513"},{"name":"data","node_id":"-513"}],"output_ports":[{"name":"predictions","node_id":"-513"},{"name":"m_lazy_run","node_id":"-513"}],"cacheable":true,"seq_num":11,"comment":"","comment_collapsed":true},{"node_id":"-893","module_id":"BigQuantSpace.dai_trade.dai_trade-v1","parameters":[{"name":"start_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"initialize","value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n import math\n from zipline.finance.commission import PerOrder\n # 加载预测数据\n context.ranker_prediction = context.options['data'].read_df()\n\n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))\n # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)\n # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只\n stock_count = 5\n # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[0.339160, 0.213986, 0.169580, ..]\n context.stock_weights = T.norm([1 / math.log(i + 2) for i in range(0, stock_count)])\n # 设置每只股票占用的最大资金比例\n context.max_cash_per_instrument = 0.2\n context.hold_days = 5\n","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n # 按日期过滤得到今日的预测数据\n ranker_prediction = context.ranker_prediction[\n context.ranker_prediction.date == data.current_dt.strftime('%Y-%m-%d')]\n\n # 1. 资金分配\n # 平均持仓时间是hold_days,每日都将买入股票,每日预期使用 1/hold_days 的资金\n # 实际操作中,会存在一定的买入误差,所以在前hold_days天,等量使用资金;之后,尽量使用剩余资金(这里设置最多用等量的1.5倍)\n is_staging = context.trading_day_index < context.hold_days # 是否在建仓期间(前 hold_days 天)\n cash_avg = context.portfolio.portfolio_value / context.hold_days\n cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)\n cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)\n positions = {e.symbol: p.amount * p.last_sale_price\n for e, p in context.perf_tracker.position_tracker.positions.items()}\n\n # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按StockRanker预测的排序末位淘汰\n if not is_staging and cash_for_sell > 0:\n equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}\n instruments = list(reversed(list(ranker_prediction.instrument[ranker_prediction.instrument.apply(\n lambda x: x in equities and not context.has_unfinished_sell_order(equities[x]))])))\n # print('rank order for sell %s' % instruments)\n for instrument in instruments:\n context.order_target(context.symbol(instrument), 0)\n cash_for_sell -= positions[instrument]\n if cash_for_sell <= 0:\n break\n\n # 3. 生成买入订单:按StockRanker预测的排序,买入前面的stock_count只股票\n buy_cash_weights = context.stock_weights\n buy_instruments = list(ranker_prediction.instrument[:len(buy_cash_weights)])\n max_cash_per_instrument = context.portfolio.portfolio_value * context.max_cash_per_instrument\n for i, instrument in enumerate(buy_instruments):\n cash = cash_for_buy * buy_cash_weights[i]\n if cash > max_cash_per_instrument - positions.get(instrument, 0):\n # 确保股票持仓量不会超过每次股票最大的占用资金量\n cash = max_cash_per_instrument - positions.get(instrument, 0)\n if cash > 0:\n context.order_value(context.symbol(instrument), cash)\n","type":"Literal","bound_global_parameter":null},{"name":"prepare","value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"before_trading_start","value":"# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"volume_limit","value":0.025,"type":"Literal","bound_global_parameter":null},{"name":"order_price_field_buy","value":"open","type":"Literal","bound_global_parameter":null},{"name":"order_price_field_sell","value":"close","type":"Literal","bound_global_parameter":null},{"name":"capital_base","value":1000000,"type":"Literal","bound_global_parameter":null},{"name":"auto_cancel_non_tradable_orders","value":"True","type":"Literal","bound_global_parameter":null},{"name":"data_frequency","value":"daily","type":"Literal","bound_global_parameter":null},{"name":"price_type","value":"真实价格","type":"Literal","bound_global_parameter":null},{"name":"product_type","value":"股票","type":"Literal","bound_global_parameter":null},{"name":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"backtest_only","value":"False","type":"Literal","bound_global_parameter":null},{"name":"benchmark","value":"000300.HIX","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-893"},{"name":"options_data","node_id":"-893"},{"name":"history_ds","node_id":"-893"},{"name":"benchmark_ds","node_id":"-893"},{"name":"trading_calendar","node_id":"-893"}],"output_ports":[{"name":"raw_perf","node_id":"-893"}],"cacheable":false,"seq_num":12,"comment":"","comment_collapsed":true},{"node_id":"-100","module_id":"BigQuantSpace.dai_extract_data.dai_extract_data-v1","parameters":[{"name":"start_date","value":"2018-01-01","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2020-12-31","type":"Literal","bound_global_parameter":null},{"name":"sql","value":"# #号开始的表示注释,注释需单独一行\n# 抽取原始表数据,这里向前抽取90天的数据以方便因子计算\ncreate table source as\nselect\nbar1d_CN_STOCK_A_all.date, bar1d_CN_STOCK_A_all.instrument,\nbar1d_CN_STOCK_A_all.close, bar1d_CN_STOCK_A_all.amount,\nbar1d_CN_STOCK_A_all.open, bar1d_CN_STOCK_A_all.high,\nbar1d_CN_STOCK_A_all.low, market_value_CN_STOCK_A.pe_ttm\nfrom bar1d_CN_STOCK_A_all left join market_value_CN_STOCK_A\nusing (instrument, date)\nwhere bar1d_CN_STOCK_A_all.date between DATE '{start_date}' - INTERVAL 90 DAY and '{end_date}' and amount > 0\nand bar1d_CN_STOCK_A_all.instrument in (\nSELECT instrument FROM basic_info_CI_CN_STOCK where (delist_date is NULL or delist_date >= '{start_date}') and list_date <= '{end_date}'\n);\n\n# 数据标注部分,抽取预测数据不需要该部分\ncreate table labels as\nwith cte1 as\n# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)\n (select *, m_lead(close, 6) / m_lead(open, 2) as label FROM source\n where date between '{start_date}' and '{end_date}' and amount > 0),\ncte2 as\n# 极值处理:用1%和99%分位的值做clip\n (select *, quantile_cont(label, 0.01) over() as lower, quantile_cont(label, 0.99) over() as upper from cte1),\ncte3 as\n (select * replace (case when label < lower then lower when label > upper then upper else label end as label) from cte2),\n# 将分数映射到分类,这里使用20个分类\ncte4 as\n (select min(label) as min, max(label) as max, (max(label) - min(label)) / 20 as interval from cte3),\ncte5 as\n (select list_append(\n list_prepend('-inf'::DOUBLE, list_transform(range(1, 20), x -> min + x * interval)),\n 'inf'::DOUBLE\n ) as bins_list from cte4),\ncte6 as\n (select * replace (cut(label, (select bins_list from cte5)) as label) from cte3)\n\n# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)\nselect date, instrument, iif(m_lead(high, 2) = m_lead(low, 2), NULL, label) as label from cte6;\n\n# 因子抽取部分\ncreate table features as\nwith cte1 as\n (select\n close / m_lag(close, 2) as return_0,\n close / m_lag(close, 7) as return_5,\n close / m_lag(close, 12) as return_10,\n close / m_lag(close, 22) as return_20,\n m_avg(amount, 6) as avg_amount_5,\n m_avg(amount, 11) as avg_amount_10,\n m_avg(amount, 21) as avg_amount_20, *\n from source)\n\nselect date, instrument, return_5, return_10, return_20,\n amount/avg_amount_5 as 'avg_amount_0/avg_amount_5',\n avg_amount_5/avg_amount_20 as 'avg_amount_5/avg_amount_20',\n pct_rank2(amount, date)/pct_rank2(avg_amount_5, date) as 'rank_avg_amount_0/rank_avg_amount_5',\n pct_rank2(avg_amount_5, date)/pct_rank2(avg_amount_10, date) as 'rank_avg_amount_5/rank_avg_amount_10',\n pct_rank2(return_0, date) as rank_return_0,\n pct_rank2(return_5, date) as rank_return_5,\n pct_rank2(return_10, date) as rank_return_10,\n pct_rank2(return_0, date)/pct_rank2(return_5, date) as 'rank_return_0/rank_return_5',\n pct_rank2(return_5, date)/pct_rank2(return_10, date) as 'rank_return_5/rank_return_10',\n pe_ttm as pe_ttm_0\n from cte1;\n\nselect features.*, labels.label\nfrom labels inner join features\nusing (instrument, date)\norder by labels.instrument, labels.date\n","type":"Literal","bound_global_parameter":null},{"name":"drop_na","value":"True","type":"Literal","bound_global_parameter":null},{"name":"cast_label_int","value":"True","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"rolling_conf","node_id":"-100"}],"output_ports":[{"name":"data","node_id":"-100"},{"name":"features","node_id":"-100"},{"name":"instruments","node_id":"-100"}],"cacheable":true,"seq_num":10,"comment":"训练数据","comment_collapsed":false},{"node_id":"-109","module_id":"BigQuantSpace.dai_extract_data.dai_extract_data-v1","parameters":[{"name":"start_date","value":"2021-01-01","type":"Literal","bound_global_parameter":"交易日期"},{"name":"end_date","value":"2021-12-31","type":"Literal","bound_global_parameter":"交易日期"},{"name":"sql","value":"# #号开始的表示注释,注释需单独一行\n# 抽取原始表数据,这里向前抽取90天的数据以方便因子计算\ncreate table source as\nselect\nbar1d_CN_STOCK_A_all.date, bar1d_CN_STOCK_A_all.instrument,\nbar1d_CN_STOCK_A_all.close, bar1d_CN_STOCK_A_all.amount,\nmarket_value_CN_STOCK_A.pe_ttm\nfrom bar1d_CN_STOCK_A_all left join market_value_CN_STOCK_A\nusing (instrument, date)\nwhere bar1d_CN_STOCK_A_all.date between DATE '{start_date}' - INTERVAL 90 DAY and '{end_date}' and amount > 0\nand bar1d_CN_STOCK_A_all.instrument in (\nSELECT instrument FROM basic_info_CI_CN_STOCK where (delist_date is NULL or delist_date >= '{start_date}') and list_date <= '{end_date}'\n);\n\n# 因子抽取部分\nwith cte1 as\n(select\n close / m_lag(close, 2) as return_0,\n close / m_lag(close, 7) as return_5,\n close / m_lag(close, 12) as return_10,\n close / m_lag(close, 22) as return_20,\n m_avg(amount, 6) as avg_amount_5,\n m_avg(amount, 11) as avg_amount_10,\n m_avg(amount, 21) as avg_amount_20, *\n from source)\nselect date, instrument, return_5, return_10, return_20,\n amount/avg_amount_5 as 'avg_amount_0/avg_amount_5',\n avg_amount_5/avg_amount_20 as 'avg_amount_5/avg_amount_20',\n pct_rank2(amount, date)/pct_rank2(avg_amount_5, date) as 'rank_avg_amount_0/rank_avg_amount_5',\n pct_rank2(avg_amount_5, date)/pct_rank2(avg_amount_10, date) as 'rank_avg_amount_5/rank_avg_amount_10',\n pct_rank2(return_0, date) as rank_return_0,\n pct_rank2(return_5, date) as rank_return_5,\n pct_rank2(return_10, date) as rank_return_10,\n pct_rank2(return_0, date)/pct_rank2(return_5, date) as 'rank_return_0/rank_return_5',\n pct_rank2(return_5, date)/pct_rank2(return_10, date) as 'rank_return_5/rank_return_10',\n pe_ttm as pe_ttm_0\n from cte1;\n","type":"Literal","bound_global_parameter":null},{"name":"drop_na","value":"True","type":"Literal","bound_global_parameter":null},{"name":"cast_label_int","value":"True","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"rolling_conf","node_id":"-109"}],"output_ports":[{"name":"data","node_id":"-109"},{"name":"features","node_id":"-109"},{"name":"instruments","node_id":"-109"}],"cacheable":true,"seq_num":1,"comment":"预测数据","comment_collapsed":false}],"node_layout":"<node_postions><node_position Node='-134' Position='180,-298,200,200'/><node_position Node='-513' Position='358,-210,200,200'/><node_position Node='-893' Position='275,-118,200,200'/><node_position Node='-100' Position='97,-405,200,200'/><node_position Node='-109' Position='500,-404,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [1]:
    # 本代码由可视化策略环境自动生成 2023年4月8日 17:58
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
     
    # 显式导入 BigQuant 相关 SDK 模块
    from bigdatasource.api import DataSource
    from biglearning.api import M
    from biglearning.api import tools as T
    from biglearning.module2.common.data import Outputs
    
    # 回测引擎:初始化函数,只执行一次
    def m12_initialize_bigquant_run(context):
        import math
        from zipline.finance.commission import PerOrder
        # 加载预测数据
        context.ranker_prediction = context.options['data'].read_df()
    
        # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
        # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
        # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只
        stock_count = 5
        # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[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.2
        context.hold_days = 5
    
    # 回测引擎:每日数据处理函数,每天执行一次
    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.hold_days # 是否在建仓期间(前 hold_days 天)
        cash_avg = context.portfolio.portfolio_value / context.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天之后才开始卖出;对持仓的股票,按StockRanker预测的排序末位淘汰
        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 = list(reversed(list(ranker_prediction.instrument[ranker_prediction.instrument.apply(
                    lambda x: x in equities and not context.has_unfinished_sell_order(equities[x]))])))
            # print('rank order for sell %s' % instruments)
            for instrument in instruments:
                context.order_target(context.symbol(instrument), 0)
                cash_for_sell -= positions[instrument]
                if cash_for_sell <= 0:
                    break
    
        # 3. 生成买入订单:按StockRanker预测的排序,买入前面的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:
                context.order_value(context.symbol(instrument), cash)
    
    # 回测引擎:准备数据,只执行一次
    def m12_prepare_bigquant_run(context):
        pass
    
    # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
    def m12_before_trading_start_bigquant_run(context, data):
        pass
    
    
    m10 = M.dai_extract_data.v1(
        start_date='2018-01-01',
        end_date='2020-12-31',
        sql="""# #号开始的表示注释,注释需单独一行
    # 抽取原始表数据,这里向前抽取90天的数据以方便因子计算
    create table source as
    select
    bar1d_CN_STOCK_A_all.date, bar1d_CN_STOCK_A_all.instrument,
    bar1d_CN_STOCK_A_all.close, bar1d_CN_STOCK_A_all.amount,
    bar1d_CN_STOCK_A_all.open, bar1d_CN_STOCK_A_all.high,
    bar1d_CN_STOCK_A_all.low, market_value_CN_STOCK_A.pe_ttm
    from bar1d_CN_STOCK_A_all left join market_value_CN_STOCK_A
    using (instrument, date)
    where bar1d_CN_STOCK_A_all.date between DATE '{start_date}' - INTERVAL 90 DAY and '{end_date}' and amount > 0
    and bar1d_CN_STOCK_A_all.instrument in (
    SELECT instrument FROM basic_info_CI_CN_STOCK where (delist_date is NULL or delist_date >= '{start_date}') and list_date <= '{end_date}'
    );
    
    # 数据标注部分,抽取预测数据不需要该部分
    create table labels as
    with cte1 as
    # 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
        (select *, m_lead(close, 6) / m_lead(open, 2) as label FROM source
        where date between '{start_date}' and '{end_date}' and amount > 0),
    cte2 as
    # 极值处理:用1%和99%分位的值做clip
        (select *, quantile_cont(label, 0.01) over() as lower, quantile_cont(label, 0.99) over() as upper from cte1),
    cte3 as
        (select * replace (case when label < lower then lower when label > upper then upper else label end as label) from cte2),
    # 将分数映射到分类,这里使用20个分类
    cte4 as
        (select min(label) as min, max(label) as max, (max(label) - min(label)) / 20 as interval from cte3),
    cte5 as
        (select list_append(
            list_prepend('-inf'::DOUBLE, list_transform(range(1, 20), x -> min + x * interval)),
            'inf'::DOUBLE
        ) as bins_list from cte4),
    cte6 as
        (select * replace (cut(label, (select bins_list from cte5)) as label) from cte3)
    
    # 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
    select date, instrument, iif(m_lead(high, 2) = m_lead(low, 2), NULL, label) as label from cte6;
    
    # 因子抽取部分
    create table features as
    with cte1 as
        (select
            close / m_lag(close, 2) as return_0,
            close / m_lag(close, 7) as return_5,
            close / m_lag(close, 12) as return_10,
            close / m_lag(close, 22) as return_20,
            m_avg(amount, 6) as avg_amount_5,
            m_avg(amount, 11) as avg_amount_10,
            m_avg(amount, 21) as avg_amount_20, *
            from source)
    
    select date, instrument, return_5, return_10, return_20,
        amount/avg_amount_5 as 'avg_amount_0/avg_amount_5',
        avg_amount_5/avg_amount_20 as 'avg_amount_5/avg_amount_20',
        pct_rank2(amount, date)/pct_rank2(avg_amount_5, date) as 'rank_avg_amount_0/rank_avg_amount_5',
        pct_rank2(avg_amount_5, date)/pct_rank2(avg_amount_10, date) as 'rank_avg_amount_5/rank_avg_amount_10',
        pct_rank2(return_0, date) as rank_return_0,
        pct_rank2(return_5, date) as rank_return_5,
        pct_rank2(return_10, date) as rank_return_10,
        pct_rank2(return_0, date)/pct_rank2(return_5, date) as 'rank_return_0/rank_return_5',
        pct_rank2(return_5, date)/pct_rank2(return_10, date) as 'rank_return_5/rank_return_10',
        pe_ttm as pe_ttm_0
        from cte1;
    
    select features.*, labels.label
    from labels inner join features
    using (instrument, date)
    order by labels.instrument, labels.date
    """,
        drop_na=True,
        cast_label_int=True
    )
    
    m9 = M.dai_stock_ranker_train.v1(
        training_ds=m10.data,
        features=m10.features,
        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,
        data_row_fraction=1,
        plot_charts=True,
        ndcg_discount_base=1,
        m_lazy_run=False
    )
    
    m1 = M.dai_extract_data.v1(
        start_date=T.live_run_param('trading_date', '2021-01-01'),
        end_date=T.live_run_param('trading_date', '2021-12-31'),
        sql="""# #号开始的表示注释,注释需单独一行
    # 抽取原始表数据,这里向前抽取90天的数据以方便因子计算
    create table source as
    select
    bar1d_CN_STOCK_A_all.date, bar1d_CN_STOCK_A_all.instrument,
    bar1d_CN_STOCK_A_all.close, bar1d_CN_STOCK_A_all.amount,
    market_value_CN_STOCK_A.pe_ttm
    from bar1d_CN_STOCK_A_all left join market_value_CN_STOCK_A
    using (instrument, date)
    where bar1d_CN_STOCK_A_all.date between DATE '{start_date}' - INTERVAL 90 DAY and '{end_date}' and amount > 0
    and bar1d_CN_STOCK_A_all.instrument in (
    SELECT instrument FROM basic_info_CI_CN_STOCK where (delist_date is NULL or delist_date >= '{start_date}') and list_date <= '{end_date}'
    );
    
    # 因子抽取部分
    with cte1 as
    (select
        close / m_lag(close, 2) as return_0,
        close / m_lag(close, 7) as return_5,
        close / m_lag(close, 12) as return_10,
        close / m_lag(close, 22) as return_20,
        m_avg(amount, 6) as avg_amount_5,
        m_avg(amount, 11) as avg_amount_10,
        m_avg(amount, 21) as avg_amount_20, *
        from source)
    select date, instrument, return_5, return_10, return_20,
        amount/avg_amount_5 as 'avg_amount_0/avg_amount_5',
        avg_amount_5/avg_amount_20 as 'avg_amount_5/avg_amount_20',
        pct_rank2(amount, date)/pct_rank2(avg_amount_5, date) as 'rank_avg_amount_0/rank_avg_amount_5',
        pct_rank2(avg_amount_5, date)/pct_rank2(avg_amount_10, date) as 'rank_avg_amount_5/rank_avg_amount_10',
        pct_rank2(return_0, date) as rank_return_0,
        pct_rank2(return_5, date) as rank_return_5,
        pct_rank2(return_10, date) as rank_return_10,
        pct_rank2(return_0, date)/pct_rank2(return_5, date) as 'rank_return_0/rank_return_5',
        pct_rank2(return_5, date)/pct_rank2(return_10, date) as 'rank_return_5/rank_return_10',
        pe_ttm as pe_ttm_0
        from cte1;
    """,
        drop_na=True,
        cast_label_int=True
    )
    
    m11 = M.dai_stock_ranker_predict.v1(
        model=m9.model,
        data=m1.data,
        m_lazy_run=False
    )
    
    m12 = M.dai_trade.v1(
        instruments=m1.instruments,
        options_data=m11.predictions,
        start_date='',
        end_date='',
        initialize=m12_initialize_bigquant_run,
        handle_data=m12_handle_data_bigquant_run,
        prepare=m12_prepare_bigquant_run,
        before_trading_start=m12_before_trading_start_bigquant_run,
        volume_limit=0.025,
        order_price_field_buy='open',
        order_price_field_sell='close',
        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'
    )
    
    [2023-04-13 10:33:55.316284] INFO moduleinvoker: dai_extract_data.v1 开始运行..
    [2023-04-13 10:33:56.455355] INFO 数据处理-数据抽取: 开始数据抽取 ..
    [2023-04-13 10:34:44.680676] INFO 数据处理-数据抽取: 总行数: 2598987
    [2023-04-13 10:34:48.060632] INFO moduleinvoker: dai_extract_data.v1 运行完成[52.744253s].
    [2023-04-13 10:34:48.343610] INFO moduleinvoker: dai_stock_ranker_train.v1 开始运行..
    [2023-04-13 10:35:04.237163] INFO StockRanker: 特征预处理 ..
    [2023-04-13 10:35:09.649312] INFO StockRanker: prepare data: training ..
    [2023-04-13 10:35:17.224650] INFO StockRanker: sort ..
    [2023-04-13 10:36:02.769829] INFO 机器学习-排序-StockRanker训练: c2810978 准备训练: 2598987 行数
    [2023-04-13 10:36:02.772148] INFO 机器学习-排序-StockRanker训练: AI模型训练,将在2598987*13=3378.68万数据上对模型训练进行20轮迭代训练。预计将需要11~21分钟。请耐心等待。
    [2023-04-13 10:36:03.053837] INFO 机器学习-排序-StockRanker训练: 正在训练 ..
    [2023-04-13 10:36:03.139660] INFO 机器学习-排序-StockRanker训练: 任务状态: Pending
    [2023-04-13 10:36:13.206579] INFO 机器学习-排序-StockRanker训练: 任务状态: Running
    [2023-04-13 10:37:33.702561] INFO 机器学习-排序-StockRanker训练: 00:01:24.0583322, finished iteration 1
    [2023-04-13 10:38:03.881259] INFO 机器学习-排序-StockRanker训练: 00:01:49.6597125, finished iteration 2
    [2023-04-13 10:38:24.002246] INFO 机器学习-排序-StockRanker训练: 00:02:16.4982449, finished iteration 3
    [2023-04-13 10:38:54.181017] INFO 机器学习-排序-StockRanker训练: 00:02:44.6546365, finished iteration 4
    [2023-04-13 10:39:24.325822] INFO 机器学习-排序-StockRanker训练: 00:03:15.1669484, finished iteration 5
    [2023-04-13 10:39:54.499075] INFO 机器学习-排序-StockRanker训练: 00:03:46.5763493, finished iteration 6
    [2023-04-13 10:40:24.637888] INFO 机器学习-排序-StockRanker训练: 00:04:17.4671857, finished iteration 7
    [2023-04-13 10:41:04.847158] INFO 机器学习-排序-StockRanker训练: 00:04:49.8584603, finished iteration 8
    [2023-04-13 10:41:35.033364] INFO 机器学习-排序-StockRanker训练: 00:05:24.0105459, finished iteration 9
    [2023-04-13 10:42:05.207333] INFO 机器学习-排序-StockRanker训练: 00:05:55.1008849, finished iteration 10
    [2023-04-13 10:42:35.360228] INFO 机器学习-排序-StockRanker训练: 00:06:25.1910062, finished iteration 11
    [2023-04-13 10:43:05.507656] INFO 机器学习-排序-StockRanker训练: 00:06:53.6239072, finished iteration 12
    [2023-04-13 10:43:35.650719] INFO 机器学习-排序-StockRanker训练: 00:07:21.6537339, finished iteration 13
    [2023-04-13 10:44:05.796452] INFO 机器学习-排序-StockRanker训练: 00:07:50.0419408, finished iteration 14
    [2023-04-13 10:44:25.901560] INFO 机器学习-排序-StockRanker训练: 00:08:18.6441793, finished iteration 15
    [2023-04-13 10:44:56.089014] INFO 机器学习-排序-StockRanker训练: 00:08:47.6143761, finished iteration 16
    [2023-04-13 10:45:26.258710] INFO 机器学习-排序-StockRanker训练: 00:09:16.6044937, finished iteration 17
    [2023-04-13 10:45:56.496628] INFO 机器学习-排序-StockRanker训练: 00:09:45.7971025, finished iteration 18
    [2023-04-13 10:46:26.669891] INFO 机器学习-排序-StockRanker训练: 00:10:14.7365279, finished iteration 19
    [2023-04-13 10:46:56.831136] INFO 机器学习-排序-StockRanker训练: 00:10:44.2155485, finished iteration 20
    [2023-04-13 10:46:56.837551] INFO 机器学习-排序-StockRanker训练: 任务状态: Succeeded
    
    [2023-04-13 10:46:57.434878] INFO: bigcharts.impl.render:render.py:404:render_chart Data is None, skip loading it to chart.
    
    [2023-04-13 10:46:57.662937] INFO moduleinvoker: dai_stock_ranker_train.v1 运行完成[729.319314s].
    
    INFO:moduleinvoker:dai_stock_ranker_train.v1 运行完成[729.319314s].
    
    [2023-04-13 10:46:57.704363] INFO moduleinvoker: dai_extract_data.v1 开始运行..
    
    INFO:moduleinvoker:dai_extract_data.v1 开始运行..
    
    [2023-04-13 10:46:57.717331] INFO 数据处理-数据抽取: 开始数据抽取 ..
    
    INFO:数据处理-数据抽取:开始数据抽取 ..
    
    [2023-04-13 10:47:11.144547] INFO 数据处理-数据抽取: 总行数: 1205477
    
    INFO:数据处理-数据抽取:总行数: 1205477
    
    [2023-04-13 10:47:12.651397] INFO moduleinvoker: dai_extract_data.v1 运行完成[14.946957s].
    
    INFO:moduleinvoker:dai_extract_data.v1 运行完成[14.946957s].
    
    [2023-04-13 10:47:12.667989] INFO moduleinvoker: dai_stock_ranker_predict.v1 开始运行..
    
    INFO:moduleinvoker:dai_stock_ranker_predict.v1 开始运行..
    
    [2023-04-13 10:47:18.516245] INFO 机器学习-排序-StockRanker预测: /data ..
    
    INFO:机器学习-排序-StockRanker预测:/data ..
    /var/app/enabled/biglearning/module2/modules/dai_stock_ranker_predict/v1/__init__.py:64: SettingWithCopyWarning: 
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead
    
    See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
    
    [2023-04-13 10:47:23.604773] INFO moduleinvoker: dai_stock_ranker_predict.v1 运行完成[10.936815s].
    
    INFO:moduleinvoker:dai_stock_ranker_predict.v1 运行完成[10.936815s].
    
    [2023-04-13 10:47:28.205242] INFO moduleinvoker: dai_backtest.v1 开始运行..
    
    INFO:moduleinvoker:dai_backtest.v1 开始运行..
    
    [2023-04-13 10:47:28.214863] INFO backtest: biglearning backtest:V8.6.3
    
    INFO:backtest:biglearning backtest:V8.6.3
    
    [2023-04-13 10:47:28.219807] INFO backtest: product_type:stock by specified
    
    INFO:backtest:product_type:stock by specified
    
    [2023-04-13 10:47:28.307128] INFO moduleinvoker: cached.v2 开始运行..
    
    INFO:moduleinvoker:cached.v2 开始运行..
    
    [2023-04-13 10:47:37.878364] INFO backtest: 读取股票行情完成:2249821
    
    INFO:backtest:读取股票行情完成:2249821
    /usr/local/python3/lib/python3.8/site-packages/pandas/core/generic.py:2605: PerformanceWarning: 
    your performance may suffer as PyTables will pickle object types that it cannot
    map directly to c-types [inferred_type->mixed,key->block3_values] [items->Index(['instrument', 'suspended', 'name'], dtype='object')]
    
      pytables.to_hdf(
    
    [2023-04-13 10:47:40.772160] INFO moduleinvoker: cached.v2 运行完成[12.465053s].
    
    INFO:moduleinvoker:cached.v2 运行完成[12.465053s].
    
    [2023-04-13 10:47:53.366618] INFO backtest: algo history_data=DataSource(afdd5bfab3d344beb967554e22cceb51T)
    
    INFO:backtest:algo history_data=DataSource(afdd5bfab3d344beb967554e22cceb51T)
    
    [2023-04-13 10:47:53.371976] INFO algo: TradingAlgorithm V1.8.9
    
    INFO:algo:TradingAlgorithm V1.8.9
    
    [2023-04-13 10:47:59.414684] INFO algo: trading transform...
    
    INFO:algo:trading transform...
    /usr/local/python3/lib/python3.8/site-packages/pandas/core/indexing.py:1124: FutureWarning: Indexing a timezone-naive DatetimeIndex with a timezone-aware datetime is deprecated and will raise KeyError in a future version.  Use a timezone-naive object instead.
      return self._get_label(key, axis=axis)
    /var/app/enabled/bigline/zipline/data/us_equity_pricing.py:990: FutureWarning: Indexing a timezone-naive DatetimeIndex with a timezone-aware datetime is deprecated and will raise KeyError in a future version.  Use a timezone-naive object instead.
      return df.loc[dt, field]
    
    [2023-04-13 10:48:06.369952] WARNING Performance: maybe_close_position no price for asset:Equity(174 [000760.SZA]), field:price, dt:2021-07-23 15:00:00+00:00
    
    WARNING:Performance:maybe_close_position no price for asset:Equity(174 [000760.SZA]), field:price, dt:2021-07-23 15:00:00+00:00
    
    [2023-04-13 10:48:11.116743] INFO Performance: Simulated 243 trading days out of 243.
    
    INFO:Performance:Simulated 243 trading days out of 243.
    
    [2023-04-13 10:48:11.122817] INFO Performance: first open: 2021-01-04 09:30:00+00:00
    
    INFO:Performance:first open: 2021-01-04 09:30:00+00:00
    
    [2023-04-13 10:48:11.141376] INFO Performance: last close: 2021-12-31 15:00:00+00:00
    
    INFO:Performance:last close: 2021-12-31 15:00:00+00:00
    /usr/local/python3/lib/python3.8/site-packages/pandas/core/generic.py:2605: PerformanceWarning: 
    your performance may suffer as PyTables will pickle object types that it cannot
    map directly to c-types [inferred_type->mixed,key->block5_values] [items->Index(['positions', 'transactions', 'orders', 'LOG', 'TRA_FAC', 'POS_FAC',
           'period_label'],
          dtype='object')]
    
      pytables.to_hdf(
    /usr/local/python3/lib/python3.8/site-packages/pandas/core/generic.py:2605: PerformanceWarning: 
    your performance may suffer as PyTables will pickle object types that it cannot
    map directly to c-types [inferred_type->mixed,key->block2_values] [items->Index(['instrument', 'suspended', 'name'], dtype='object')]
    
      pytables.to_hdf(
    /usr/local/python3/lib/python3.8/site-packages/pandas/core/indexing.py:1637: SettingWithCopyWarning: 
    A value is trying to be set on a copy of a slice from a DataFrame
    
    See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
      self._setitem_single_block(indexer, value, name)
    [2023-04-13 10:48:16.565740] INFO: bigcharts.impl.render:render.py:404:render_chart Data is None, skip loading it to chart.
    
    • 收益率90.76%
    • 年化收益率95.38%
    • 基准收益率-5.2%
    • 阿尔法1.02
    • 贝塔0.4
    • 夏普比率2.6
    • 胜率0.55
    • 盈亏比1.48
    • 收益波动率25.91%
    • 信息比率0.17
    • 最大回撤16.42%
    日期 时间 股票代码 股票名称 买/卖 数量 成交价 总成本 交易佣金
    Loading... (need help?)
    日期 股票代码 股票名称 持仓均价 收盘价 股数 持仓价值 收益
    Loading... (need help?)
    时间 级别 内容
    Loading... (need help?)
    [2023-04-13 10:48:17.268972] INFO moduleinvoker: dai_backtest.v1 运行完成[49.063689s].
    
    INFO:moduleinvoker:dai_backtest.v1 运行完成[49.063689s].
    
    [2023-04-13 10:48:17.274181] INFO moduleinvoker: dai_trade.v1 运行完成[53.655325s].
    
    INFO:moduleinvoker:dai_trade.v1 运行完成[53.655325s].