问答交流

【平台使用】order_target_percent函数问题

由bqfmyxm1创建,最终由bqfmyxm1 被浏览 2 用户

我正在使用标普500的数据写一个简单的动量因子策略,运行时一直打印以下日志:\n

日志 103 条 ▼
[2026-03-18 15:40:22] INFO: bigtrader.v35 开始运行 ..[2026-03-18 15:40:22] INFO: pybacktest run 2020-12-31 ~ 2024-12-31, , equity, instruments=501[2026-03-18 15:40:22] INFO: bigtrader module V2.2.0[2026-03-18 15:40:22] INFO: bigtrader engine v0.1.0.post9+g6d7300d 2026-02-10[2026-03-18 15:40:23] INFO: pybacktest read history data done, run backtest ...order_target_percent: price is null for 'NVDA.O' at '2020-12-31 15:00:00'
order_target_percent: price is null for 'BBWI.N' at '2020-12-31 15:00:00'
order_target_percent: price is null for 'MRNA.O' at '2020-12-31 15:00:00'
order_target_percent: price is null for 'ETSY.O' at '2020-12-31 15:00:00'
order_target_percent: price is null for 'ENPH.O' at '2020-12-31 15:00:00'
order_target_percent: price is null for 'NVDA.O' at '2021-01-04 15:00:00'
order_target_percent: price is null for 'MRNA.O' at '2021-01-04 15:00:00'
order_target_percent: price is null for 'ETSY.O' at '2021-01-04 15:00:00'
order_target_percent: price is null for 'GNRC.N' at '2021-01-04 15:00:00'
order_target_percent: price is null for 'ENPH.O' at '2021-01-04 15:00:00'
order_target_percent: price is null for 'NVDA.O' at '2021-01-05 15:00:00'
order_target_percent: price is null for 'BBWI.N' at '2021-01-05 15:00:00'
order_target_percent: price is null for 'MRNA.O' at '2021-01-05 15:00:00'
order_target_percent: price is null for 'ETSY.O' at '2021-01-05 15:00:00'
order_target_percent: price is null for 'ENPH.O' at '2021-01-05 15:00:00'
order_target_percent: price is null for 'BBWI.N' at '2021-01-06 15:00:00'
order_target_percent: price is null for 'MRNA.O' at '2021-01-06 15:00:00'
order_target_percent: price is null for 'ETSY.O' at '2021-01-06 15:00:00'
order_target_percent: price is null for 'GNRC.N' at '2021-01-06 15:00:00'
order_target_percent: price is null for 'ENPH.O' at '2021-01-06 15:00:00'

我的代码如下:\n

import os
from bigmodule import M
import dai

# ────────────────────────────────────────────────
# 计算经典 12-1 动量(过去252日收益 - 过去21日收益)
# ────────────────────────────────────────────────
df = dai.query("""
    WITH sp500_components AS (
        -- 历史标普500成分股 + 有效期 carry forward
        SELECT 
            member_code AS instrument,
            date AS start_date,
            LEAD(date, 1, '2099-12-31') OVER (PARTITION BY member_code ORDER BY date) AS end_date
        FROM us_stock_index_component
        WHERE name = '标准普尔500指数'
          AND date <= '2024-12-31'
    ),
    prices AS (
        SELECT 
            b.date,
            b.instrument,
            b.close,
            LAG(b.close, 21)  OVER (PARTITION BY b.instrument ORDER BY b.date) AS close_21d_ago,
            LAG(b.close, 252) OVER (PARTITION BY b.instrument ORDER BY b.date) AS close_252d_ago
        FROM us_stock_bar1d b
        INNER JOIN sp500_components c 
            ON b.instrument = c.instrument 
            AND b.date >= c.start_date 
            AND b.date < c.end_date
        WHERE b.date BETWEEN '2020-01-01' AND '2024-12-31'
    ),
    momentum AS (
        SELECT 
            date,
            instrument,
            CASE 
                WHEN close_21d_ago > 0 AND close_252d_ago > 0 
                     AND close_21d_ago IS NOT NULL 
                     AND close_252d_ago IS NOT NULL
                THEN (close / close_252d_ago - 1) - (close / close_21d_ago - 1)
                ELSE NULL
            END AS score  -- mom_12_1
        FROM prices
    )
    SELECT 
        date,
        instrument,
        score
    FROM momentum
    WHERE score IS NOT NULL
    ORDER BY date, score DESC, instrument
""").df()

def initialize(context):
    from bigtrader.finance.commission import PerOrder
    
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    
    context.hold_count = 5
    context.weight = 1.0 / context.hold_count

    context.df = df


def handle_data(context, data):
    # 当前日期字符串
    dt_str = data.current_dt.strftime("%Y-%m-%d")
    
    # 取出当天所有股票的 score,按降序已排好
    current_df = context.df[context.df["date"] == dt_str]
    
    if current_df.empty:
        return
    
    # 取前 hold_count 只(已按 score DESC 排序)
    to_hold_df = current_df.head(context.hold_count)
    to_hold_instruments = set(to_hold_df["instrument"])
    
    # -----------------------
    # 卖出:不在新列表里的全部清仓
    # -----------------------
    current_positions = context.get_account_positions()
    for instrument in list(current_positions.keys()):
        if instrument not in to_hold_instruments:
            context.order_target(instrument, 0)
    
    # -----------------------
    # 买入/调整:目标等权
    # -----------------------
    for instrument in to_hold_instruments:
        context.order_target_percent(instrument, context.weight)

# 回测引擎调用
m5 = M.bigtrader.v35(
    data=df,                    # 传入预计算好的 df
    initialize=initialize,
    handle_data=handle_data,
    capital_base=1000000,
    frequency="daily",
    order_price_field_buy="open",
    order_price_field_sell="close",
    m_cached=True,            
)

我理解order_target_percent这个函数就是按照order_price_field_buy设置的价格买入context.weight比例的指定标的。不太明白为啥会出现这个问题。烦请大家解答下,谢谢!\n顺便再问下打断点调试的功能为啥还是不可用啊?我这里只有运行按钮没有调试

{link}