跳轉到

最佳化 API 詳細

這一頁專門說明參數最佳化任務系統。

系統定位

最佳化不是直接改一般回測的全域狀態,而是:

  1. 建立一個任務
  2. 固定商品 / 週期 / 時間範圍 / 策略
  3. 給一組 base_params
  4. 定義要枚舉的 param_ranges
  5. 批次跑所有組合
  6. 保存結果、排序、查詢、收藏

任務資料模型

一個最佳化任務核心包含:

  • ticker
  • timeframe_minutes
  • start_time
  • end_time
  • strategy_name
  • base_params
  • param_ranges
  • status
  • progress
  • total_combinations
  • completed_combinations
  • results

1. 建立任務

POST /optimization/tasks

Request body 範例:

{
  "ticker": "TXFR1",
  "timeframe_minutes": 5,
  "start_time": "2025-01-01 00:00:00",
  "end_time": "2025-06-30 23:59:59",
  "strategy_name": "BollingerATRStrategyV4",
  "base_params": {
    "init_window": 25,
    "std": 2.0,
    "in_std": 0.5,
    "atr_window": 10,
    "k": 3,
    "entry_type": "CLOSE",
    "calc_timing": "CLOSE",
    "price_offset_long": 10,
    "price_offset_short": 10,
    "stop_loss_offset_long": 10,
    "stop_loss_offset_short": 10
  },
  "param_ranges": {
    "init_window": { "start": 15, "end": 35, "step": 5 },
    "std": { "start": 1.5, "end": 2.5, "step": 0.25 }
  }
}

重要行為

  • strategy_name 可帶可不帶
  • 若未帶,後端會 fallback
  • 但若你是前端,建議永遠明傳
  • 建立時會檢查策略是否屬於可見策略

2. 任務列表

GET /optimization/tasks

Query:

  • ticker
  • status
  • limit
  • offset
  • include_params,預設 false

為什麼有 include_params

最佳化列表頁若只是顯示任務摘要,不需要每次都把:

  • base_params
  • param_ranges
  • results

全撈回來。
因此目前列表 API 預設是輕量化的。

建議前端

一般列表頁使用:

GET /optimization/tasks?limit=50&offset=0

只有真的要在列表直接展示參數摘要時,才使用:

GET /optimization/tasks?include_params=true

3. 單一任務詳情

GET /optimization/tasks/{task_id}

Query:

  • include_results,預設 false
  • include_params,預設 true

建議

輪詢或一般任務資訊頁:

  • 不要開 include_results

只有真的要完整看原始任務資料,才取完整內容。

4. 任務進度

GET /optimization/tasks/{task_id}/progress

這是專門為輪詢設計的輕量端點。

回傳大致包含:

  • id
  • status
  • progress
  • completed_combinations
  • total_combinations
  • error_message
  • updated_at

前端最佳實踐

執行任務後,不要一直輪詢完整 task 詳情,請輪詢:

GET /optimization/tasks/{task_id}/progress

5. 執行任務

POST /optimization/tasks/{task_id}/run

注意:

  • 目前是同步執行
  • request 會一路等到整個最佳化跑完才回來

也就是說,它不是:

  • 建背景 job 後立即返回

而是:

  • 真正把所有組合都跑完才回

內部流程

  1. 讀 task
  2. 產生所有參數組合
  3. 預載一次歷史資料
  4. ProcessPoolExecutor
  5. 每組參數交給 optimization_worker.run_one_combination()
  6. 不斷更新進度
  7. 結束後把結果排序並存回 DB

6. 更新任務

PATCH /optimization/tasks/{task_id}

限制:

  • 只能更新 pending 任務

可更新欄位:

  • ticker
  • timeframe_minutes
  • start_time
  • end_time
  • base_params
  • param_ranges

更新後系統會重新計算:

  • total_combinations

7. 複製任務

POST /optimization/tasks/{task_id}/clone

用途:

  • 把現有任務複製成新的 pending 任務

適合:

  • 用既有任務當模板
  • 只小改少量參數

8. 查看結果

GET /optimization/tasks/{task_id}/results

Query:

  • sort_by
  • sort_order
  • limit
  • offset

目前支援的排序欄位

  • total_pnl
  • win_rate
  • profit_factor
  • total_trades
  • max_drawdown_pct

已支援分頁

目前回傳中會包含:

  • results
  • total
  • limit
  • offset
  • has_more

前端建議

不要一次取全部結果。
建議:

  • 第一頁:limit=50&offset=0
  • 下一頁:offset=50

9. 收藏結果

相關 API

  • POST /optimization/records/toggle
  • GET /optimization/records
  • DELETE /optimization/records/{record_id}
  • DELETE /optimization/records

用途:

  • 把最佳化結果中挑中的組合保存下來
  • 作為人工篩選後的候選策略配置

10. 前端完整流程建議

1. GET /strategy_list
2. GET /get_params_for_combination
3. POST /optimization/tasks
4. POST /optimization/tasks/{task_id}/run
5. 輪詢 GET /optimization/tasks/{task_id}/progress
6. 完成後 GET /optimization/tasks/{task_id}/results?limit=50&offset=0
7. 若使用者收藏,呼叫 POST /optimization/records/toggle

11. 常見誤區

誤區 A:任務列表已經很快,所以詳情也可以拿來輪詢

不建議。
輪詢應使用 /progress

誤區 B:run 是背景任務

不是。
它目前是同步執行。

誤區 C:最佳化結果排序只在前端做

不是。
後端已有排序與分頁能力。

誤區 D:舊文件中的參數欄位名都還適用

不一定。
舊文件中曾使用:

  • price_offset
  • stop_loss_offset

但目前新策略與新 API 實際常見欄位為:

  • price_offset_long
  • price_offset_short
  • stop_loss_offset_long
  • stop_loss_offset_short

因此整合時應以目前實作與 Swagger 為準。