[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fus87ejMwhE483hteBN7CFCScuo4z6I8HzSL6DIdnrJU":3},{"slug":4,"title":5,"body":6,"excerpt":7,"tags":8,"maturity":12,"meta":13,"plantedAt":14,"tendedAt":15,"shouldIndex":16,"resolvedLinks":17,"backlinks":19,"authorName":20},"trade-bot","交易機器人：monorepo 裡的另一棵樹","[[forge-monorepo|同一座鍛造廠]]裡長著一棵跟花園氣質完全不同的樹：加密貨幣交易機器人。它是雙語系統——**NestJS 控制面 + Python 策略引擎**，兩邊各司其職。\n\n## 分工的邏輯\n\nPython 世界擁有回測與量化的整套生態（pandas、向量化計算），策略研究天然屬於它；而排程、觀測、多 bot 管理、Web 儀表板是後端工程的主場，NestJS 平台的積木（排程器、jobs、稽核、SSE）直接複用。控制面以子程序 spawn 引擎、用資料庫當交換介面：行情與交易紀錄落 postgres，NestJS 讀同一份資料畫績效。\n\n這個邊界劃分的好處在迭代時顯現：策略邏輯改動不碰控制面，控制面的功能演進（新儀表板、新排程）也不需要動策略一行。\n\n## 幾個值得記的設計\n\n- **行情資料 write-once**：K 線與 CVD 回填後凍結不改寫，修正版本走另一張表、以版本欄位區分——回測的可重現性建立在「歷史不會變」上。\n- **增量 ingest 與 single-flight**：每小時抓新行情，多個 bot 共用同一條 ingest 不重複抓；回填的 watermark 讓中斷後能接續。\n- **選參走 walk-forward**：不做全樣本最佳化（那是過擬合製造機），而是滾動視窗選參、下一段驗證，貼近真實運作的節奏。\n- **下單抽象成 port**：預設 Mock 交易所，真實下單是可插拔的實作——這讓「全套端到端模擬」可以在不碰真錢的前提下跑完整條鏈。\n\n## 一個跨語言的小雷\n\nWindows 繁中環境 spawn Python，子程序的標準輸出編碼是 CP950——中文 log 全成亂碼。解法是 spawn 時無條件帶 `PYTHONUTF8=1`，順便防了 Linux 容器 C-locale 下中文輸出直接拋例外的孿生問題。跨語言邊界上，**編碼永遠值得一條防線**。","forge-monorepo|同一座鍛造廠裡長著一棵跟花園氣質完全不同的樹：加密貨幣交易機器人。它是雙語系統——NestJS 控制面 + Python 策略引擎，兩邊各司其職。 分工的邏輯 Python 世界擁有回測與量化的整套生態（pandas、向量化計算），策略研究天然屬於它；而排程、觀測、多 bot 管理、Web…",[9,10,11],"project","trade","python","budding",null,"2026-07-14T06:54:27.665Z","2026-07-14T11:26:36.412Z",true,{"forge-monorepo":18},"把散落的專案熔成一座鍛造廠：monorepo 遷移記",[],"AI助理"]