跳轉到

State 與 Broker JSON 規格

本頁整理回測執行期最重要的 JSON 結構,重點是讓重做系統的人知道:

  • state 外層長什麼樣
  • broker 保存哪些欄位
  • order_history 每筆紀錄格式為何
  • tradebot 在執行過程中另外維護哪些歷史陣列

整體 state 結構

GET /state 與內部 BacktestBot.get_state() 會回傳一個以四大區塊為主的物件:

{
  "strategy": {},
  "indicators": {},
  "broker": {},
  "data_feed": {},
  "analysis": {}
}

說明:

  • strategy: 策略本身序列化後的狀態
  • indicators: 指標容器目前的所有序列與游標
  • broker: 資金、部位、訂單歷史、保證金、損益
  • data_feed: 當前資料序列與 current_index
  • analysis: API 層補上的績效分析摘要,不一定直接來自 BacktestBot.get_state()

TradeBot 執行期結構

BacktestBot 另外維護三類「不一定直接出現在 GET /state,但會出現在儲存檔或圖表資料生成流程」的資料:

pending_orders

用途:策略先發訊號,等下一根 K 線開盤價才執行。

格式:

{
  "action": "buy",
  "symbol": "TXFR1",
  "size": 1,
  "message": "突破上軌,下一根開多",
  "signal_price": 22480.0
}

欄位說明:

  • action: buysellcover
  • symbol: 商品代號
  • size: 口數
  • message: 訊號說明
  • signal_price: 產生訊號當下價格,只用於記錄與除錯

broker_history

用途:每跑完一根 K 棒,記錄當下 broker 狀態快照。

陣列元素格式:

{
  "init_cash": 1000000,
  "cash": 982450.0,
  "contract_size": 200,
  "margin_rate": 0.1,
  "fee_per_contract": 50,
  "positions": {
    "TXFR1": {
      "long": 0,
      "short": 1
    }
  },
  "avg_cost": {
    "TXFR1": {
      "long": 0.0,
      "short": 22480.0
    }
  },
  "position_details": {
    "TXFR1": [
      {
        "direction": "short",
        "price": 22480.0,
        "size": 1
      }
    ]
  },
  "order_history": {
    "TXFR1": [
      {
        "type": "sell",
        "direction": "short",
        "price": 22480.0,
        "size": 1,
        "fee": 50,
        "timestamp": "2025-01-02 09:15:00",
        "message": "建立空倉"
      }
    ]
  },
  "realized_pnl": 3500.0,
  "unrealized_pnl": {
    "TXFR1": -1200.0
  },
  "margin": 449600.0
}

data_feed_history

用途:每根 K 棒都記錄一份簡化 OHLCV,供輸出圖表與歷史比對。

陣列元素格式:

{
  "datetime": "2025-01-02 09:15:00",
  "open": 22470.0,
  "high": 22490.0,
  "low": 22460.0,
  "close": 22480.0,
  "volume": 1822.0
}

Broker JSON 結構

專案內有兩種 broker:

  • Broker: 現貨式簡化 broker
  • FuturesBroker: 目前主回測比較常用的期貨 broker

重做系統時,應以 FuturesBroker 結構為主要相容目標。

FuturesBroker.to_json()

完整骨架:

{
  "init_cash": 1000000,
  "cash": 982450.0,
  "contract_size": 200,
  "margin_rate": 0.1,
  "fee_per_contract": 50,
  "positions": {
    "TXFR1": {
      "long": 1,
      "short": 0
    }
  },
  "avg_cost": {
    "TXFR1": {
      "long": 22410.0,
      "short": 0.0
    }
  },
  "position_details": {
    "TXFR1": [
      {
        "direction": "long",
        "price": 22410.0,
        "size": 1
      }
    ]
  },
  "order_history": {
    "TXFR1": [
      {
        "type": "buy",
        "direction": "long",
        "price": 22410.0,
        "size": 1,
        "fee": 50,
        "timestamp": "2025-01-02 09:20:00",
        "message": "突破進場"
      }
    ]
  },
  "realized_pnl": 0.0,
  "unrealized_pnl": {
    "TXFR1": 1200.0
  },
  "margin": 448200.0
}

欄位說明:

  • init_cash: 初始資金
  • cash: 目前可用現金
  • contract_size: 每口合約乘數
  • margin_rate: 保證金比率
  • fee_per_contract: 每口手續費
  • positions: 各商品多空口數
  • avg_cost: 各商品多空平均成本
  • position_details: lot-level 明細
  • order_history: 訂單/成交事件歷史
  • realized_pnl: 已實現損益累計
  • unrealized_pnl: 各商品未實現損益
  • margin: 當前占用保證金

positions 規格

格式:

{
  "TXFR1": {
    "long": 2,
    "short": 0
  },
  "MXFR1": {
    "long": 0,
    "short": 1
  }
}

注意:

  • 此 broker 允許同時存在 long / short 欄位
  • 但實際策略是否允許同商品同時雙向持倉,要看策略邏輯

avg_cost 規格

格式:

{
  "TXFR1": {
    "long": 22410.0,
    "short": 0.0
  }
}

position_details 規格

格式:

{
  "TXFR1": [
    {
      "direction": "long",
      "price": 22410.0,
      "size": 1
    },
    {
      "direction": "long",
      "price": 22425.0,
      "size": 1
    }
  ]
}

說明:

  • 這裡保留 lot 級別資料
  • 平倉時會依序扣減舊 lot
  • 可用於之後重做更精細的 FIFO / 持倉分析

order_history 規格

order_history 是一個以 symbol 為 key 的 map,每個 value 是事件陣列。

開多

{
  "type": "buy",
  "direction": "long",
  "price": 22410.0,
  "size": 1,
  "fee": 50,
  "timestamp": "2025-01-02 09:20:00",
  "message": "突破進場"
}

平多

{
  "type": "sell",
  "direction": "long",
  "price": 22480.0,
  "size": 1,
  "fee": 50,
  "pnl": 13950.0,
  "timestamp": "2025-01-02 10:05:00",
  "message": "停利出場"
}

開空

{
  "type": "sell",
  "direction": "short",
  "price": 22480.0,
  "size": 1,
  "fee": 50,
  "timestamp": "2025-01-02 10:10:00",
  "message": "跌破下軌做空"
}

平空

{
  "type": "cover",
  "direction": "short",
  "price": 22420.0,
  "size": 1,
  "fee": 50,
  "pnl": 11950.0,
  "timestamp": "2025-01-02 10:40:00",
  "message": "空單回補"
}

欄位差異:

  • 所有事件都有:typedirectionpricesizefeetimestampmessage
  • 只有平倉事件通常帶有:pnl

Strategy JSON

策略 to_json() 的實際欄位依策略類別而異,但重做系統時至少應保留:

{
  "class_name": "BollingerATRStrategyV4",
  "params": {
    "init_window": 25,
    "std": 2.0,
    "in_std": 0.5
  },
  "runtime": {
    "position": "short",
    "pattern_state": "await_breakout"
  }
}

注意:

  • 目前專案未建立正式的跨策略統一 schema
  • 所以文件只能保證「一定存在策略序列化物件」,不能保證每個欄位都一致
  • 若要把系統做成正式產品,建議後續定義統一的 StrategyStateSchema

Indicators JSON

指標容器同樣偏動態,但通常會長得像:

{
  "current_index": 1234,
  "series": {
    "MA": [null, null, 22455.2],
    "Upper": [null, null, 22488.1],
    "Lower": [null, null, 22422.3],
    "ATR": [null, null, 55.0]
  }
}

DataFeed JSON

典型結構:

{
  "symbol": "TXFR1",
  "interval": "5min",
  "current_index": 1234,
  "data": [
    {
      "datetime": "2025-01-02 09:00:00",
      "open": 22400.0,
      "high": 22420.0,
      "low": 22395.0,
      "close": 22410.0,
      "volume": 1523.0
    }
  ]
}

儲存檔 backtest_state_*.json

BacktestBot.save_state() 輸出的 JSON 骨架如下:

{
  "strategy": {},
  "data_feed": {},
  "indicators": {},
  "broker": {},
  "broker_history": [],
  "data_feed_history": []
}

這個檔案比 GET /state 更完整,因為它額外包含:

  • broker_history
  • data_feed_history

但目前不包含:

  • pending_orders
  • 明確版號
  • schema version
  • 序列化格式版本資訊

重做系統時建議補上的正式欄位

如果目標真的是「正式產品規格書等級」,下一步最值得補的 schema 欄位是:

  • schema_version
  • broker_type
  • strategy_name
  • timeframe_minutes
  • ticker
  • generated_at
  • timezone

這些欄位目前多半分散在 API 上下文,而不是完整嵌進 state/broker JSON 本身。