Skip to main content

国内期货事件驱动回测框架(L1/L5 Tick + Bar,多合约,可配置撮合策略)

Project description

KestrelFBT — 国内期货回测框架

基于 Python 的事件驱动期货回测系统,支持 L1(普通行情)和 L5(五档深度)数据, 覆盖国内全交易所(SHFE / DCE / CZCE / CFFEX / INE / GFEX)。


快速开始

安装依赖

pip install -r requirements.txt

运行示例

# Bar 策略(双均线)
python examples/demo_strategy.py

# Tick 策略(L1 ask1 动量)
python examples/demo_tick_strategy.py

# 完整仓位管理(止盈/止损/移动止损)
python examples/example_position_mgmt.py

# 多合约价差策略(rb + hc)
python examples/example_multi_contract.py

# L5 walk_book 冲击成本对比
python examples/example_l5_walkbook.py

数据源

目录结构

{data_root}/
├── FUTURES_L1_TICK_ALL/              # L1 行情,覆盖全交易所
│   └── {YYYYMMDD}/
│       ├── DAY/{instrument}_day.csv
│       └── NIGHT/{instrument}_night.csv
├── FUTURES_L5_TICK_SHFE/             # L5 深度行情,按交易所分目录
├── FUTURES_L5_TICK_DCE/
├── FUTURES_L5_TICK_CZCE/
├── FUTURES_L5_TICK_CFFEX/
├── FUTURES_L5_TICK_INE/
└── FUTURES_L5_TICK_GFEX/

CSV 格式(30 列,无表头)

字段 说明
0 instrument 合约代码
1 date 自然日 YYYYMMDD
2 time HHMMSSMMM(如 090000000)
3 turnover 当日累计成交额
4 volume 当日累计成交量(session 内重置)
5 last_price 最新价
6 open_interest 持仓量
7 high_price 当日最高
8 low_price 当日最低
9 timestamp Unix 微秒时间戳
10-14 bid1-5 买一到买五价格
15-19 ask1-5 卖一到卖五价格
20-24 bid1-5_vol 买一到买五挂量
25-29 ask1-5_vol 卖一到卖五挂量

L1 文件中 bid2-5 / ask2-5 列恒为 0

日期约定

文件夹日期 = 自然日(数据物理发生的日期)

交易日 T 的数据 =
  夜盘:{T 的上一个自然日}/NIGHT/   ← 物理发生在上一自然日晚
  日盘:{T}/DAY/

示例:交易日 20250103 = 20250102/NIGHT/ + 20250103/DAY/

基本用法

1. 编写策略

继承 BaseStrategy,重写需要的回调:

from kestrel.strategy.base import BaseStrategy
from kestrel.data.schema import TickData, BarData

class MyStrategy(BaseStrategy):
    name = "MyStrategy"

    def on_start(self): ...              # 回测开始,初始化
    def on_day_start(self, date): ...    # 每日开始
    def on_tick(self, tick: TickData): ... # 每条 tick
    def on_bar(self, bar: BarData): ...  # 每根 K 线(需配置 bar_periods)
    def on_fill(self, fill_data): ...    # 成交回报
    def on_reject(self, reject_data): ...# 拒单通知
    def on_day_end(self, date): ...      # 每日结束
    def on_stop(self): ...               # 回测结束

2. 下单接口

# 开仓(均返回 order_id)
order_id = self.buy_open(instrument, price, volume, order_type="LIMIT")
order_id = self.sell_open(instrument, price, volume, order_type="MARKET")

# 平仓
order_id = self.sell_close(instrument, price, volume, order_type="LIMIT")
order_id = self.buy_close(instrument, price, volume, close_today=False)

# 撤单
self.cancel(order_id)

# order_type: "LIMIT"(限价)或 "MARKET"(市价/对手价)

3. 查询接口

tick  = self.get_last_tick("rb2501")   # 最新 tick
pos   = self.get_position("rb2501")    # 持仓(含多空手数、均价)
eq    = self.get_equity()              # 总权益
cash  = self.get_cash()                # 可用资金

4. 配置回测

from kestrel.engine.backtest import BacktestEngine, BacktestConfig
from kestrel.engine.matching import ContractInfo, FillPolicy

config = BacktestConfig(
    instruments     = ["rb2501"],           # 订阅合约列表
    start_date      = 20250102,             # 回测起始交易日
    end_date        = 20250228,             # 回测结束交易日
    initial_capital = 500_000.0,            # 初始资金(元)
    contracts       = [ContractInfo(...)],  # 合约规格(见下方)
    use_l5          = False,                # True=L5数据,False=L1数据
    fill_policy     = FillPolicy(...),      # 撮合策略(见下方)
    bar_periods     = [1, 5],              # K线周期(分钟),None=不合成K线
    data_root       = "/mnt/nvme1n1",       # 数据根目录
    output_path     = "./results/out.json", # 结果输出路径(None=不输出)
)

engine = BacktestEngine(config, MyStrategy())
report = engine.run()

5. 合约规格

ContractInfo(
    instrument        = "rb2501",   # 合约代码
    exchange          = "SHFE",     # 交易所
    multiplier        = 10,         # 合约乘数(元/点)
    price_tick        = 1.0,        # 最小变动价位
    margin_rate       = 0.08,       # 保证金率(按合约价值比例)
    commission_per_lot = 10.0,      # 手续费(元/手),与 commission_rate 二选一
    commission_rate   = 0.0,        # 手续费率(按成交额比例)
)

常见合约规格参考 config/contract_specs.json(含乘数和最小变动价,不含保证金/手续费)。

6. 撮合策略

FillPolicy(
    # 限价单成交模式
    limit_fill_mode           = "next_tick",  # 默认:下一tick才成交(最保守)
                                              # "price_cross":价格穿越即成交
                                              # "volume_participation":按成交量参与比例

    volume_participation_rate = 0.3,          # 仅 volume_participation 模式有效

    # 市价单 / 对手价成交模式
    market_fill_mode          = "next_tick",  # 默认:下一tick对手盘价格成交
                                              # "current_tick":当前快照价格(有预见性偏差)

    market_slippage_ticks     = 1,            # 额外滑点跳数(>=0)

    # L5 模式:按五档深度逐档消耗,量化市场冲击成本
    # L1 模式下此参数自动忽略
    walk_book                 = True,
)

数据模型

TickData

tick.instrument     # 合约代码
tick.trading_date   # 交易日 YYYYMMDD
tick.time           # HHMMSSMMM
tick.timestamp      # Unix 微秒
tick.last_price     # 最新价
tick.delta_volume   # 本 tick 新增成交量(差分后)
tick.bid1           # 买一价(L1/L5 均有)
tick.ask1           # 卖一价
tick.bid1_vol       # 买一量
tick.ask1_vol       # 卖一量
tick.bid2-5         # 买二到买五(仅 L5 有效)
tick.ask2-5         # 卖二到卖五(仅 L5 有效)
tick.is_l5()        # 是否包含五档深度
tick.ask_prices()   # [ask1, ask2, ..., ask5]
tick.ask_vols()     # [ask1_vol, ..., ask5_vol]

BarData

bar.instrument      # 合约代码
bar.trading_date    # 交易日
bar.bar_time        # Bar 开始时间 HHMMSSMMM
bar.period_min      # K 线周期(分钟)
bar.open / high / low / close
bar.volume          # 该 Bar 内成交量

InstrumentPosition

pos = self.get_position("rb2501")
pos.long_volume     # 多头持仓手数
pos.short_volume    # 空头持仓手数
pos.long_avg_price() # 多头均价
pos.short_avg_price()# 空头均价
pos.floating_pnl()  # 浮动盈亏

回测报告

engine.run() 返回 dict,同时(若配置了 output_path)写入 JSON 文件:

{
  "config": { "instruments": [...], "start_date": ..., ... },
  "metrics": {
    "total_return": 0.0512,
    "annual_return": 0.1823,
    "sharpe_ratio": 1.42,
    "calmar_ratio": 2.31,
    "max_drawdown": 12500.0,
    "max_drawdown_pct": 0.025,
    "win_rate": 0.54,
    "profit_factor": 1.8,
    "total_commission": 1200.0,
    "total_trades": 120,
    "total_turnover": 8500000.0
  },
  "equity_curve": [
    { "date": 20250102, "equity": 502000, "daily_pnl": 2000, ... },
    ...
  ]
}

控制台打印摘要:

from kestrel.analytics.report import print_summary
print_summary(report)

架构概览

BacktestConfig
    └─ BacktestEngine
          ├─ DataFeed          ← 多合约 tick 归并回放 + Bar 合成
          ├─ EventEngine        ← 同步事件总线
          ├─ MatchingEngine     ← 撮合引擎(FillPolicy 可配置)
          │    └─ ContractInfo  ← 合约规格
          ├─ Portfolio          ← 持仓 + 逐日盯市结算
          └─ BaseStrategy       ← 用户策略(可插拔)
                                   ↑ on_tick / on_bar / on_fill

事件流(每个 tick)

DataFeed → TickData
  → MatchingEngine.on_tick()    先撮合上一 tick 的挂单
  → Portfolio.on_tick()         更新浮动盈亏
  → Strategy.on_tick()          触发策略逻辑
  → Strategy.on_bar()           触发已完成的 Bar
  → EventEngine.process_all()   处理 ORDER / FILL / REJECT

注意事项

  1. L1 vs L5 互斥:两者代表不同的实盘账户类型,不可混用。 用 L5 数据回测但实盘只有 L1 会高估信息优势。

  2. 撮合近似性:所有基于快照数据的成交模拟都是近似。 FillPolicy 的默认参数(next_tick + 1 跳滑点)偏保守。 建议用实盘成交数据校准滑点参数。

  3. 成交量累计:CSV 中的 volume 是 session 内累计值。 框架内部已自动做差分,tick.delta_volume 即为本 tick 新增成交量。 DAY/NIGHT session 切换时差分基准自动重置。

  4. 交易日归属:夜盘数据文件夹日期为自然日,但在框架内已映射为下一交易日。 策略代码中的 tick.trading_dateon_day_start(date) 始终是交易日。

  5. 多合约时间对齐:多合约 tick 按 timestamp(微秒)全局排序后串行回放, 保证跨合约策略(套利)的时间一致性和结果确定性。

  6. 参数优化:如需跑多组参数,使用 multiprocessing.Pool 在多进程中 各自创建独立的 BacktestEngine,不要在引擎内部使用多线程。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kestrel_fbt-0.1.0.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kestrel_fbt-0.1.0-py3-none-any.whl (37.1 kB view details)

Uploaded Python 3

File details

Details for the file kestrel_fbt-0.1.0.tar.gz.

File metadata

  • Download URL: kestrel_fbt-0.1.0.tar.gz
  • Upload date:
  • Size: 34.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for kestrel_fbt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3076ceeb98d1959c8c495fbc9029a279e305b227512574ab04732e46e8c9ce96
MD5 3061c5010c4cbc1f6181fa95413327fb
BLAKE2b-256 b2c06880b65242021b28321e6d33875d8dc8ef965196ff0309d272f2d58c0d5a

See more details on using hashes here.

File details

Details for the file kestrel_fbt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: kestrel_fbt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for kestrel_fbt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 51bb1dc2e51ce750093e4ea274c4b428cbecca3b7965a91df29e950dd5673ce9
MD5 9ea422d188e9bb1ccd2ca27f1a84d25b
BLAKE2b-256 c3974ec69338c7fdcf1d83585bab6046ce67b1c8de345cecce75163cbad3ae77

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page