跳轉到

大盤半年線(MA120)/年線(MA240)乖離率 Integration Guide — Frontend

Backend branch: feat/daily-market-ma120-ma240-bias → cortex/dev API base: 公開端點(與既有 /api/daily-market/* 同) 生效時間:merge 後 cortex-api 自動 reload 即生效;無 migration、無資料回補(快照表已有全歷史值)

Consumer:cortex-web 大盤儀表板(讀 /latest 的 index.moving_averages 與 /range、/index-range 的 daily[])。


1. 欄位改名對照表(Breaking)

無。純 additive;既有 5/20/60 日欄位的名稱、值、null 規則一律不變。

2. 新增欄位

端點 位置 新欄位 型別
GET /api/daily-market/range daily[] bias_rate_ma120_pct、bias_rate_ma240_pct number \| null
GET /api/daily-market/index-range daily[] bias_rate_ma120_pct、bias_rate_ma240_pct number \| null
GET /api/daily-market/latest(及 /{trade_date}) index.moving_averages ma120、ma240、distance_to_ma120_pct、distance_to_ma240_pct、bias_rate_ma120_pct、bias_rate_ma240_pct number \| null

bias_rate_ma{N}_pct 與 distance_to_ma{N}_pct 同值(與既有 5/20/60 一樣,兩個名字並存)。/range 與 /index-range 同一交易日的兩欄逐欄相等。

3. 計算與 null 規則

  • bias_rate_maN_pct = (收盤 − MAN) ÷ MAN × 100,四位小數。
  • 收盤與均線都取同一交易日的 ^TWII 技術快照(daily_technical_snapshot),和 5/20/60 日乖離率出自同一個收盤價。
  • 下列情況回 null,不以前一日均線補值:同日快照不存在、該均線仍在暖機期(MA120 需 120 根、MA240 需 240 根 K 棒;目前資料 MA120 自 2018-07-03、MA240 自 2018-12-21 起有值)、MAN = 0。
  • 前端不可把 null 當 0 顯示。
  • 收盤價來源差異:同一列的 market_index_close 來自官方大盤日資料,乖離率用的是技術快照收盤。2021 年起兩者逐日相同;2018-07-24~2020-01-14 有 53 天不同(多數為官方資料 source_error,market_index_close 為 null 但 5/20/60/120 日乖離率有值,MA240 乖離率在 2018-12-21 前仍因暖機為 null;其餘差 0.01–0.04 點)。請直接使用乖離率欄位,不要用 market_index_close 自行重算。

4. 範例(本 branch 程式碼打 live DB 實測輸出)

GET /api/daily-market/index-range?start_date=2026-11-03&end_date=2026-11-03

{
  "market": "taiwan",
  "start_date": "2026-11-03",
  "end_date": "2026-11-03",
  "count": 1,
  "daily": [
    {
      "trade_date": "2026-11-03",
      "market_index_close": 43307.54,
      "market_trade_value_amount": 1002035660990,
      "bias_rate_ma5_pct": -4.5431,
      "bias_rate_ma20_pct": -8.4856,
      "bias_rate_ma60_pct": -6.9963,
      "bias_rate_ma120_pct": -4.5121,
      "bias_rate_ma240_pct": 12.0097
    }
  ]
}

GET /api/daily-market/latest → index.moving_averages(2026-11-03)

{
  "ma5": 45368.684,
  "ma20": 47323.2115,
  "ma60": 46565.3745,
  "ma120": 45353.972,
  "ma240": 38664.0883,
  "distance_to_ma5_pct": -4.5431,
  "distance_to_ma20_pct": -8.4856,
  "distance_to_ma60_pct": -6.9963,
  "distance_to_ma120_pct": -4.5121,
  "distance_to_ma240_pct": 12.0097,
  "bias_rate_ma5_pct": -4.5431,
  "bias_rate_ma20_pct": -8.4856,
  "bias_rate_ma60_pct": -6.9963,
  "bias_rate_ma120_pct": -4.5121,
  "bias_rate_ma240_pct": 12.0097,
  "benchmark_ticker": "^TWII",
  "source": "daily_technical_snapshot",
  "date": "2026-11-03",
  "status": "available"
}

暖機期範例(index-range,2018-12-20):"bias_rate_ma120_pct": -7.2016, "bias_rate_ma240_pct": null。

與需求範例的差異:需求範例寫 2026-11-03 bias_rate_ma120_pct = -4.5110,以同範例的 ma120 = 45353.972、收盤 43307.54 代公式為 -4.5121;後端以公式值為準(2026-11-03 使用者確認)。前端若有寫死 -4.5110 的測試請改成 -4.5121。

5. 前端改法(cortex-web)

  1. src/types/daily-market.ts:/range 與 /index-range 的 daily[] 型別加 bias_rate_ma120_pct: number | null、bias_rate_ma240_pct: number | null;moving_averages 型別加上表六欄(皆 number | null)。
  2. 讀取端照既有 5/20/60 的寫法並列 120/240,null 顯示為無資料。

6. 驗證

curl -s "http://localhost:8000/api/daily-market/index-range?start_date=2026-11-03&end_date=2026-11-03" | jq '.daily[0] | {bias_rate_ma120_pct, bias_rate_ma240_pct}'

預期:{"bias_rate_ma120_pct": -4.5121, "bias_rate_ma240_pct": 12.0097}。