06 / 快速开始06 / QUICKSTART

先把一个样例日读对,再开始写策略。Read one sample day correctly before writing a strategy.

这是一条从 ZIP 到 Parquet、从字段关联到最小成交模拟的可复制路径,适用于 5分钟和15分钟市场。A copyable path from ZIP to Parquet, from schema joins to a minimal fill simulator for both 5-minute and 15-minute markets.

先下载真实样例START WITH REAL SAMPLES

免费、无需注册,先跑通读取流程。Free samples, no sign-up, no paywall.

网站提供 2026-08-10 UTC 的 5m 和15m 样例。完整历史数据免费发布在 Telegram。The site provides 2026-08-10 UTC samples for 5m and 15m markets. The complete historical archive is free on Telegram.

1. 解压并识别文件1. Extract and inventory the files

15m 样例是一个 ZIP。5m 样例分成 part1 和 part2,两个文件都下载后解压到同一个目录;分包只是传输层拆分。The 15m sample is one ZIP. The 5m sample is split into part 1 and part 2; download both and extract them into the same directory. The split is only for transport.

sample_15m/
├── ticks_20260810_00.parquet
├── depth_20260810_00.parquet
└── btc_15m_market_outcomes.parquet

实际文件可能按小时继续增加。不要仅凭文件名推断覆盖范围,先列出文件大小、Parquet schema、时间范围和 event_slug 数量。More hourly files may be present in a full archive. Do not infer coverage from filenames alone; inventory file sizes, Parquet schemas, time ranges, and event_slug counts first.

2. 安装最小读取依赖2. Install the minimal reader

python -m pip install pandas pyarrow
from pathlib import Path
import pandas as pd

root = Path("sample_15m")

ticks = pd.concat(
    [pd.read_parquet(path) for path in sorted(root.glob("ticks_*.parquet"))],
    ignore_index=True,
)
depth = pd.concat(
    [pd.read_parquet(path) for path in sorted(root.glob("depth_*.parquet"))],
    ignore_index=True,
)
outcomes = pd.read_parquet(root / "btc_15m_market_outcomes.parquet")

ticks = ticks.sort_values(["event_slug", "ts"])
depth = depth.sort_values(["event_slug", "ts", "outcome", "side", "level"])
data = ticks.merge(outcomes, on="event_slug", how="left")

3. 用 event_slug 关联3. Join with event_slug

ticks、depth、market_outcomes 和 seen_markets 都通过 event_slug 关联。需要核对 token 时,再从 seen_markets 补充 up_asset_id 和 down_asset_id。Join ticks, depth, market_outcomes, and seen_markets with event_slug. When token-level verification is needed, add up_asset_id and down_asset_id from seen_markets.

event_slug → market context → quotes / depth → resolved outcome

5m 市场窗口通常是 300 秒,15m 通常是 900 秒。回测边界使用文件中的 window_start_ts、window_end_ts 和 interval_min。A 5m window is normally 300 seconds and a 15m window 900 seconds. Use window_start_ts, window_end_ts, and interval_min from the files for backtest boundaries.

4. 先做最小成交模拟4. Start with a minimal fill simulator

买入从对应 outcome 的 ASK level 1 开始逐档消耗,卖出从 BID level 1 开始逐档消耗。展示数量不是成交保证。A buy consumes the selected outcome's ASK levels from level 1 upward; a sell consumes BID levels from level 1 downward. Displayed size is not a fill guarantee.

def consume_book(snapshot, outcome, side, quantity):
    levels = snapshot[
        (snapshot["outcome"] == outcome) &
        (snapshot["side"] == side)
    ].sort_values("level")

    remaining = quantity
    cost = 0.0
    filled = 0.0
    for row in levels.itertuples():
        amount = min(remaining, row.size)
        cost += amount * row.price
        filled += amount
        remaining -= amount
        if remaining <= 0:
            break

    return {
        "filled": filled,
        "average_price": cost / filled if filled else None,
        "unfilled": remaining,
    }

# buy -> side="ASK"; sell -> side="BID"
# Add latency, fees, slippage, and a fill-ratio assumption in the real backtest.

第一版回测至少显式设置延迟、部分成交比例、深度不足、手续费和滑点。不要用 mid 价代替真实买卖价,也不要把 winner_side 或 target 当成预测特征。The first backtest must state latency, partial-fill ratio, insufficient depth, fees, and slippage. Do not use mid as the buy/sell fill, and never use winner_side or target as a predictive feature.

接下来阅读Continue with