外观
期货日频回测
先完成安装,阅读期货机制。本页使用日频收盘模型:普通委托按真实合约收盘价尝试成交,系列移仓按结算价完成。该模型不承诺可按实盘收盘时点复制成交。
运行
保存为 future_daily.py,执行 python future_daily.py。示例首个可用 bar 开多 RB 系列 1 手,盘后核对实际数量,随后持有;未达目标直接报错。示例固定手续费不是历史交易所费率。
python
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo
from localquant import run_func
from localquant.apis import buy_open, get_position, subscribe
from localquant.mod.localquant_mod_seeddata_source import load_framework_data, register_bundle, discard_bundle
from localquant.mod.localquant_mod_sys_analyser.report import export_full_html
CODE = "RB.SHF"
START, END = "2026-09-01", "2026-09-03"
FREQUENCY = "1d"
MATCHING = "current_bar"
BASE_URL = "http://127.0.0.1:28637"
name = datetime.now(ZoneInfo("Asia/Shanghai")).strftime("%Y-%m-%d-%H-%M-%S")
output = Path("output/backtest") / name
output.mkdir(parents=True, exist_ok=False)
def init(context):
subscribe(CODE)
context.sent = False
def handle_bar(context, bars):
if not context.sent and not bars[CODE].isnan:
buy_open(CODE, 1)
context.sent = True
def after_trading(context):
if get_position(CODE).quantity != 1:
raise RuntimeError("示例未达到 1 手多仓,请检查订单状态与行情")
bundle = load_framework_data(
[CODE], START, END, base_url=BASE_URL, asset_type="cn_future",
frequency=FREQUENCY, index_codes=["NHCI.NH"], include_yield_curve=False,
)
key = register_bundle(bundle)
try:
result = run_func(init=init, handle_bar=handle_bar, after_trading=after_trading, config={
"base": {"start_date": START, "end_date": END, "frequency": FREQUENCY,
"accounts": {"future": 1_000_000}, "margin_multiplier": 1,
"capital_gain_tax_rate": 0, "use_risk_free_rate": False},
"mod": {
"seeddata_source": {"enabled": True, "lib": "localquant.mod.localquant_mod_seeddata_source",
"priority": 0, "bundle_key": key},
"sys_accounts": {"futures_settlement_price_type": "settlement"},
"sys_simulation": {"matching_type": MATCHING},
"sys_transaction_cost": {"futures_commission": {
"default": {"type": "by_money", "open": 0.0001, "close": 0.0001, "close_today": 0.0001},
}},
"sys_analyser": {"enabled": True, "record": True,
"benchmark": {"type": "instrument", "order_book_id": "NHCI.NH"}, "output_file": str(output / "result.pkl")},
},
})["sys_analyser"]
finally:
discard_bundle(key)
export_full_html(result, name, output / "full_report.html")
print(result["trades"])
print(output.resolve())结果位于 output/backtest/<运行时间>/result.pkl 与 full_report.html。本例显式选择 NHCI.NH 为基准;期末保留持仓,收益按末日结算后权益评价。更换代码、区间或数据地址时,应确认相应数据已就绪。
信号与路由
| 阶段 | 行情与策略行为 |
|---|---|
| before_trading | 日线历史截至前一交易日,可生成滞后信号;不能查询当日系列下单路由 |
| handle_bar,15:15 | 当日日线已完整;系列开仓使用当日 mapping,实际月合约收盘价撮合 |
| after_trading | 检查普通成交和策略状态;日终移仓及结算尚未完成 |
| 日终结算 | 按系统移仓模型换月、到期处理、结算,再生成结果快照 |
连续系列仅允许 handle_bar 下单,get_future_series_contract(series) 也仅在此日频回调返回当日路由。日频当前映射与收盘数据按收盘后可得处理,不能拿它们倒推盘前已可执行的订单。
推荐日频策略在 T 日盘前读取截至 T-1 的日线,T 日收盘回调执行。框架也允许使用 T 日完整日线生成信号后按 T 日收盘价成交;这属于同收盘研究假设,必须在策略执行口径中明确。日频 handle_bar 的 include_now=False 仍包含当天,不能用它排除当日数据。
日频没有 next_bar 成交模式;设置它会告警并按 current_bar 运行。连续系列若要求观察完成后在后续可交易时点执行,应使用分钟回测,并按其固定路由规则处理。
策略验收
检查信号截止日、实际合约、方向、手数、费用与账户权益。反转先完成原方向平仓,再按实际资金开仓;拒单或部分成交后的继续处理由策略声明。order_to(series, 0) 只表达净目标,多空相等的对冲仓不能据此认为已清空。
换月当天的策略成交与系统成交分别看 trade_source。普通成交受撮合限制,系统移仓不受同一限制。成本、移仓资金与结算算例见期货机制。