Share Notes

chundev

View the Project on GitHub latteouka/share-notes

TSM Executor 自動下單系統建置紀錄

日期:2026-03-16 目的:為台積電期貨策略系統(TSM)建置自動下單模組,從訊號到執行全自動化


TL;DR

用 Python + Shioaji API 建了一個獨立的自動下單 worker,透過 TSM 的 HTTP API 讀取策略訊號,執行期貨下單,並同步發送 Telegram + Threads 通知。目前以模擬模式運行,每日 08:30 自動執行。


架構

TSM (Node.js, Docker)              tsm-executor (Python, Docker)
┌────────────────────────┐         ┌──────────────────────┐
│ 15:30 算訊號            │         │ 08:30 cron 觸發       │
│ GET /api/executor/     │◄────────│ 讀取訊號              │
│     signal             │ Bearer  │ Shioaji 下單(模擬)    │
│                        │ Token   │                      │
│ POST /api/executor/    │◄────────│ 回報執行結果           │
│      report            │         │                      │
│ → DB + Telegram        │         └──────────────────────┘
│ → Threads              │
└────────────────────────┘
         ↕
    PostgreSQL

兩個獨立 repo,共用同一個 docker-compose.prod.yml


建置步驟

1. 永豐 Shioaji API 申請

2. Python 專案初始化

tsm-executor/
├── Dockerfile
├── requirements.txt      # shioaji, python-dotenv, psycopg2-binary
├── .env                  # API Key、憑證路徑(不入版控)
├── cron/
│   └── executor-cron.sh  # server crontab 用
└── src/
    ├── config.py         # 環境變數
    ├── broker.py         # Shioaji 登入、買進、賣出
    └── executor.py       # 主流程:讀訊號 → 下單 → 回報

3. TSM 端新增 API

Endpoint 方法 用途
/api/executor/signal GET 回傳今日策略訊號(繞過 Free/Pro 限制)
/api/executor/report POST 接收執行結果 → 寫 DB + 發 Telegram + Threads

兩個 endpoint 都用 Bearer Token 保護,外部無法存取。

4. DB Schema 新增

model ExecutionOrder {
  // 每筆下單紀錄(買進/賣出各一筆)
  action         String     // "buy" | "sell"
  contracts      Int
  signalPrice    Float      // 回測引擎的理論價
  filledPrice    Float?     // 實際成交價
  status         String     // "simulated" | "filled" | "failed"
  mode           String     // "simulation" | "live"
}

model ExecutionPosition {
  // 一筆完整交易(進場 → 出場)
  status          String    // "open" | "closed"
  entryDate       String
  entryPrice      Float
  exitDate        String?
  exitPrice       Float?
  returnRate      Float?    // 報酬率 %
  mode            String    // "simulation" | "live"
}

5. Docker 部署

executor 用獨立 image,透過 compose profile 隔離:

# docker-compose.prod.yml
services:
  app:
    image: tsm:latest         # 676MB
  executor:
    image: tsm-executor:latest # 128MB
    profiles: ["executor"]     # 不隨 up -d 自動啟動
    environment:
      TSM_API_URL: http://app:3050/api/executor/signal
      TSM_REPORT_URL: http://app:3050/api/executor/report

6. Crontab 排程

# 每週一到週五 08:30(開盤前 15 分鐘)
30 8 * * 1-5 cd /home/deploy/tsm && \
  docker compose -f docker-compose.prod.yml --env-file .env.production \
  --profile executor run --rm executor python src/executor.py \
  >> /home/deploy/tsm-executor/logs/cron.log 2>&1

下單策略

項目 設定
商品 CDF(台積電期貨)近月合約 CDFR1
進場 市價單(MKT) — 隔夜跳空限價單容易掛不到
出場 市價單(MKT) — 儘快平倉
委託類型 ROD(當日有效)
時機 08:30 掛單,08:45 開盤成交

每日通知

executor 執行後會同時發送兩個通知:

Telegram:

[盤前執行] 2026-03-17(模擬)
P/C:158.9 | 期貨:1870
🟢 進場
買進 CDF 1 口 @ 1870
(模擬,未實際下單)

Threads: 同上內容,公開發佈。

透過 Threads 貼文可以驗證系統是否每天正確執行。


模擬 → 實盤切換

目前以模擬模式運行(SIMULATION=true),不實際下單。

切換實盤只需要改一個環境變數:

# server 上的 .env.production
EXECUTOR_SIMULATION=false

建議模擬跑至少 2-4 週,確認:


Makefile 指令

# 在 TSM 專案目錄下
make build-executor    # 本地 build executor image
make push-executor     # build + 傳送到 server
make deploy            # 部署 TSM 主應用(不含 executor)

測試驗證結果

測試項目 結果
Shioaji 登入
CDF 合約查詢(7 個合約)
模擬買進/賣出/查詢/取消 ✅ 全部 PendingSubmit
TSM signal API(本地) ✅ 回傳即時訊號
TSM signal API(server) ✅ Token 驗證正常
executor dry run(本地) ✅ 正確讀到持倉
executor dry run(server) ✅ Docker 內部網路正常
crontab 排程 ✅ 已設定

注意事項