问答交流

【代码报错】PapermillExecutionError

由whisky创建,最终由whisky 被浏览 15 用户

策略代码运行时正常,但是提交模拟交易后就报下面的错

from bigmodule import M

# <aistudiograph>

# @param(id="m8", name="initialize")
# 交易引擎:初始化函数, 只执行一次
def m8_initialize_bigquant_run(context):
    import math
    import numpy as np

    from bigtrader.finance.commission import PerOrder

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

    # 设置每只股票占用的最大资金比例
    context.max_cash_per_instrument = 1
    context.options["hold_days"] = 5


# @param(id="m8", name="before_trading_start")
# 交易引擎:每个单位时间开盘前调用一次。
def m8_before_trading_start_bigquant_run(context, data):
    # 盘前处理,订阅行情等
    pass

# @param(id="m8", name="handle_tick")
# 交易引擎:tick数据处理函数,每个tick执行一次
def m8_handle_tick_bigquant_run(context, tick):
    pass

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

    
    # 1. 资金分配
    # 平均持仓时间是hold_days, 每日都将买入股票, 每日预期使用 1/hold_days 的资金
    # 实际操作中, 会存在一定的买入误差, 所以在前hold_days天, 等量使用资金;之后, 尽量使用剩余资金
    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 3) * cash_avg)
    cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)
    positions = {
        e: p.amount * p.last_sale_price for e, p in context.portfolio.positions.items()
    }

    # 使用stock_sell记录卖出的股票
    stock_sell = []
    # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票, 按机器学习算法预测的排序末位淘汰
    if not is_staging and cash_for_sell > 0:
        equities = {e: e for e, p in context.portfolio.positions.items()}
        instruments = list(
            reversed(
                list(
                    ranker_prediction.instrument[
                        ranker_prediction.instrument.apply(lambda x: x in equities)
                    ]
                )
            )
        )

        for instrument in instruments:
            context.order_target(instrument, 0)
            cash_for_sell -= positions[instrument]
            stock_sell.append(instrument)
            if cash_for_sell <= 0:
                break
        
    print(today,'卖出股票列表',stock_sell)

    # 使用stock_buy记录买入的股票
    stock_buy = []
    # 3. 生成买入订单:按机器学习算法预测的排序, 买入前面的stock_count只股票
    buy_cash_weights = context.stock_weights
    buy_instruments = list(ranker_prediction.instrument[: len(buy_cash_weights)])
    print(today,'买入股票列表',buy_instruments)
    max_cash_per_instrument = (
        context.portfolio.portfolio_value * context.max_cash_per_instrument
    )
    # 买入数量计算
    buynum_list = []
    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(instrument, cash)

# @param(id="m8", name="handle_trade")
# 交易引擎:成交回报处理函数,每个成交发生时执行一次
def m8_handle_trade_bigquant_run(context, trade):
    pass

# @param(id="m8", name="handle_order")
# 交易引擎:委托回报处理函数,每个委托变化时执行一次
def m8_handle_order_bigquant_run(context, order):
    pass

# @param(id="m8", name="after_trading")
# 交易引擎:盘后处理函数,每日盘后执行一次
def m8_after_trading_bigquant_run(context, data):
    pass

# @module(position="-324,-1022", comment="""""", comment_collapsed=True)
m7 = M.cn_stock_basic_selector.v7(
    exchanges=["""上交所""", """深交所"""],
    list_sectors=["""主板""", """创业板"""],
    st_statuses=["""正常"""],
    drop_suspended=True,
    m_name="""m7"""
)

# @module(position="-347,-910", comment="""因子特征,用表达式构建因子""")
m1 = M.input_features_dai.v30(
    input_1=m7.data,
    mode="""表达式""",
    expr="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home / cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
-- 数据使用: 表名.字段名, 对于没有指定表名的列,会从 expr_tables 推断

close / m_lag(close,6) AS return_5 
close / m_lag(close,11) AS return_10    
close / m_lag(close,21) AS return_20      
amount / m_avg(amount,6)    
m_avg(amount,6) / m_avg(amount,11)    
c_pct_rank(amount)/c_pct_rank(m_avg(amount,6))    
c_pct_rank(m_avg(amount,6))/c_pct_rank(m_avg(amount,21)) 
c_pct_rank(close / m_lag(close,1)) AS rank_return_0 
c_pct_rank(close / m_lag(close,6)) AS rank_return_5
c_pct_rank(close / m_lag(close,11)) AS rank_return_10
rank_return_0/rank_return_5  
rank_return_0/rank_return_10 
pe_ttm  
m_shift(close, 11)/m_shift(close, 41)
c_pct_rank(m_avg(turn*100,4)) AS rank_avg_turn_3
m_ta_bbands_l(close, timeperiod := 14) AS lowerbands_14
pb
c_pct_rank(m_lag(amount, 5)) AS rank_amount_5
c_pct_rank(close/m_lag(close, 4)) AS rank_return_3
m_avg(turn*100, 11) AS avg_turn_10
m_ta_sma(close,10) / m_ta_sma(close,30)
m_ta_cci(high, low, close, 14)
""",
    expr_filters="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
-- c_pct_rank(short_return) BETWEEN 0.4 AND 0.6
-- rank_returns <= 10
list_days > 260
st_status = 0
-- m_avg(turn, 5) BETWEEN 0.02 AND 0.05
""",
    expr_tables="""cn_stock_prefactors""",
    extra_fields="""date, instrument""",
    order_by="""date, instrument""",
    expr_drop_na=True,
    extract_data=False,
    m_name="""m1"""
)

# @module(position="-205,-667", comment="""抽取预测数据""")
m4 = M.extract_data_dai.v17(
    sql=m1.data,
    start_date="""2024-12-31""",
    start_date_bound_to_trading_date=True,
    end_date="""2025-01-08""",
    end_date_bound_to_trading_date=True,
    before_start_days=100,
    debug=False,
    m_cached=False,
    m_name="""m4"""
)

# @module(position="-517,-785", comment="""+ 数据标注""")
m2 = M.input_features_dai.v30(
    input_1=m1.data,
    mode="""表达式""",
    expr="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home / cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
-- 数据使用: 表名.字段名, 对于没有指定表名的列,会从 expr_tables 推断

input_1.* EXCLUDE(date, instrument)
m_lead(close, 5) / m_lead(open, 1) AS _future_return
aLL_quantile_cont(_future_return, 0.01) AS _future_return_1pct
all_quantile_cont(_future_return, 0.99) AS _future_return_99pct
clip(_future_return, _future_return_1pct, _future_return_99pct) AS _clipped_return
all_cbins(_clipped_return, 20) AS label
""",
    expr_filters="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
-- st_status = 0

-- 从训练数据中移除第二天涨停和跌停数据
m_lead(high, 1) != m_lead(low, 1)""",
    expr_tables="""cn_stock_bar1d""",
    extra_fields="""date, instrument""",
    order_by="""date, instrument""",
    expr_drop_na=True,
    sql="""-- 使用DAI SQL获取数据,构建因子等,如下是一个例子作为参考
-- DAI SQL 语法: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-sql%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B

SELECT

    -- 在这里输入因子表达式
    -- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
    -- 数据&字段: 数据文档 https://bigquant.com/data/home

    c_rank(volume) AS rank_volume,
    close / m_lag(close, 1) as return_0,

    -- 日期和股票代码
    date, instrument
FROM
    -- 预计算因子 cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
    cn_stock_prefactors
    -- 如果要使用输入数据源,需要在这里join进来
    -- JOIN input_1 USING(date, instrument)
WHERE
    -- WHERE 过滤,在窗口等计算算子之前执行
    -- 剔除ST股票
    st_status = 0
QUALIFY
    -- QUALIFY 过滤,在窗口等计算算子之后执行,比如 m_lag(close, 3) AS close_3,对于 close_3 的过滤需要放到这里
    -- 去掉有空值的行
    COLUMNS(*) IS NOT NULL
-- 按日期和股票代码排序,从小到大
ORDER BY date, instrument
""",
    extract_data=False,
    m_name="""m2"""
)

# @module(position="-535,-662", comment="""抽取训练数据""")
m3 = M.extract_data_dai.v17(
    sql=m2.data,
    start_date="""2016-01-01""",
    start_date_bound_to_trading_date=True,
    end_date="""2018-12-31""",
    end_date_bound_to_trading_date=True,
    before_start_days=100,
    debug=False,
    m_name="""m3"""
)

# @module(position="-449,-555", comment="""""", comment_collapsed=True)
m5 = M.stock_ranker_dai_train.v9(
    data=m3.data,
    learning_algorithm="""排序""",
    number_of_leaves=30,
    min_docs_per_leaf=1000,
    number_of_trees=25,
    learning_rate=0.1,
    max_bins=1023,
    feature_fraction=1,
    data_row_fraction=1,
    plot_charts=True,
    ndcg_discount_base=1,
    m_name="""m5"""
)

# @module(position="-345,-449", comment="""""", comment_collapsed=True)
m6 = M.stock_ranker_dai_predict.v12(
    model=m5.model,
    data=m4.data,
    m_name="""m6"""
)

# @module(position="-260,-353", comment="""""", comment_collapsed=True)
m8 = M.bigtrader.v30(
    data=m6.predictions,
    start_date="""""",
    end_date="""""",
    initialize=m8_initialize_bigquant_run,
    before_trading_start=m8_before_trading_start_bigquant_run,
    handle_tick=m8_handle_tick_bigquant_run,
    handle_data=m8_handle_data_bigquant_run,
    handle_trade=m8_handle_trade_bigquant_run,
    handle_order=m8_handle_order_bigquant_run,
    after_trading=m8_after_trading_bigquant_run,
    capital_base=200000,
    frequency="""daily""",
    product_type="""股票""",
    rebalance_period_type="""交易日""",
    rebalance_period_days="""5""",
    rebalance_period_roll_forward=True,
    backtest_engine_mode="""标准模式""",
    before_start_days=0,
    volume_limit=1,
    order_price_field_buy="""open""",
    order_price_field_sell="""close""",
    benchmark="""沪深300指数""",
    plot_charts=True,
    debug=False,
    backtest_only=False,
    m_cached=False,
    m_name="""m8"""
)
# </aistudiograph>

\

评论
  • 可是回测的时候能够正常运行,就有点搞不懂了,难道是回测跟模拟是两套数据?
  • 这个问题是你传入训练模块的数据是空的,这可能与你写的表达式条件有关,严格的表达式筛选会导致没有任何股票满足条件,或者你写了错误的表达式条件。
  • 您训练集开始日期是什么时候,然后向前取了多少天呢
  • 训练集开始日期是2016年1月1号,向前取100
  • 方便将敏感信息去掉然后分享一版代码出来吗
{link}