多品种策略
由qxiao创建,最终由qxiao 被浏览 3 用户
多品种回测使用指南
多品种回测的核心思路:**在单一回测框架内,同时持有并管理股票、基金、期货、期权等不同品种。**主框架入口不变,通过"品种声明 + 独立账户 + 指定下单账户"三步扩展到多品种。
核心规律
- 在
instruments里声明所有品种 这是多品种回测的数据入口。所有需要行情数据的品种,无论是 ETF、期货合约还是期权,都必须在 params["instruments"] 里提前声明。引擎只为声明过的品种加载数据。
# 股票 + ETF 基金
params = {
"instruments": list(df['instrument'].unique()) + ['518880.SH', '513100.SH', '513030.SH'],
...
}
# 股票 + 期货
params = {
"instruments": list(df_factors["instrument"].unique()) + ["IF2506.CFE"],
...
}
2. 在 initialize 里用 add_account 开独立账户
非股票品种(基金除外)需要独立账户来隔离资金和保证金。在 initialize 里调用 context.add_account,并将返回的 account_id 保存到 context 上供后续使用。
def initialize(context: bigtrader.IContext):
# 期货账户:独立保证金
_, context.future_account_id = context.add_account(
bigtrader.AccountType.FUTURE,
capital_base=500_000,
)
# 基金账户:与股票同类型,但资金独立
_, context.etf_account_id = context.add_account(
bigtrader.AccountType.STOCK,
capital_base=1_000_000,
)
| 品种 | AccountType | 是否需要独立账户 |
|---|---|---|
| 股票 | STOCK | 默认账户,无需 add_account |
| ETF 基金 | STOCK | 按需,资金需隔离时开 |
| 期货 | FUTURE | 必须独立账户 |
| 期权 | OPTION | 必须独立账户 |
3. 下单时通过 account_id 指定账户
多账户体系下,下单必须通过 account_id 告知引擎走哪个账户。不传则默认走主账户(股票账户)。
def handle_data(context, data):
# 期货下单 —— 指定期货账户
context.buy_open(
"IF2506.CFE",
1,
account_id=context.future_account_id,
)
# 股票下单 —— 走默认主账户,无需 account_id
context.order_target_percent("600519.SH", 0.1)
# ETF 下单 —— 指定 ETF 账户
context.order_target_percent(
"518880.SH",
0.25,
account_id=context.etf_account_id,
)
-
handle_data里各品种逻辑独立管理每类品种的信号生成和调仓节奏完全独立,写在同一个
handle_data里按顺序执行即可。
def handle_data(context, data):
# --- 期货:维持固定手数多头 ---
fut_pos = context.get_position("IF2506.CFE", direction="1",
account_id=context.future_account_id)
if fut_pos.current_qty < 1:
context.buy_open("IF2506.CFE", 1, account_id=context.future_account_id)
# --- 股票:因子选股,按周期调仓 ---
if context.stock_rebalance_period.is_signal_date(data.current_dt.date()):
# ... 选股逻辑 ...
context.order_target_percent(ins, weight)
# --- ETF:固定标的,等权持有 ---
if context.etf_rebalance_period.is_signal_date(data.current_dt.date()):
for ins in ['518880.SH', '513100.SH']:
context.order_target_percent(ins, 0.5, account_id=context.etf_account_id)
-
bigtrader.run入口保持不变无论组合了多少品种,顶层调用方式不变。
capital_base是主账户(股票账户)的初始资金,其他账户的资金在add_account时单独设置。
performance = bigtrader.run(
data=params,
market=bigtrader.Market.CN_STOCK, # 填主市场
frequency=bigtrader.Frequency.DAILY,
capital_base=1_000_000, # 主账户(股票)资金
initialize=initialize,
handle_data=handle_data,
)
完整结构一览
params["instruments"] ← 声明所有品种的行情数据
│
initialize()
├── add_account(FUTURE) ← 期货独立账户
├── add_account(STOCK) ← 基金独立账户(可选)
└── 调仓计划初始化
│
handle_data()
├── 期货逻辑 → buy_open(..., account_id=future_account_id)
├── 股票逻辑 → order_target_percent(ins, weight)
└── 基金逻辑 → order_target_percent(ins, weight, account_id=etf_account_id)
│
bigtrader.run() ← 入口不变
一句话记忆
instruments 声明品种 → add_account 开副账户 → 下单指定 account_id → handle_data 各管各的逻辑。