Skip to content

Commit 113a70a

Browse files
committed
Auto-deploy CI/CD + worker loads config from GitHub raw + developer standards doc
1 parent 6427254 commit 113a70a

4 files changed

Lines changed: 254 additions & 11 deletions

File tree

.github/workflows/deploy-strategy-switch-console.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
branches: [main]
66
paths:
77
- ".github/workflows/deploy-strategy-switch-console.yml"
8+
- "platform-config.json"
9+
- "scripts/build_config.py"
810
- "scripts/sync_strategy_switch_page_asset.py"
911
- "web/strategy-switch-console/**"
1012
workflow_dispatch:
@@ -49,6 +51,11 @@ jobs:
4951
with:
5052
node-version: "22"
5153

54+
- name: Build config from platform-config.json
55+
run: |
56+
set -euo pipefail
57+
python3 scripts/build_config.py
58+
5259
- name: Regenerate bundled assets
5360
run: |
5461
set -euo pipefail

.github/workflows/validate.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
else
3131
git diff-tree --check --no-commit-id --root -r HEAD
3232
fi
33+
- name: Validate platform config
34+
run: python3 scripts/build_config.py --check
3335
- name: Validate runtime targets
3436
run: python3 scripts/runtime_settings.py validate
3537
- name: Run unit tests
@@ -43,6 +45,8 @@ jobs:
4345
- name: Validate strategy switch web assets
4446
run: |
4547
set -euo pipefail
48+
python3 scripts/build_config.py --check
49+
python3 scripts/build_config.py
4650
python3 scripts/sync_strategy_switch_page_asset.py
4751
git diff --exit-code -- web/strategy-switch-console/page_asset.js web/strategy-switch-console/strategy_profiles_asset.js
4852
jq empty web/strategy-switch-console/strategy-profiles.example.json
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# QuantStrategyLab 开发者标准规范
2+
3+
## 架构总览
4+
5+
```
6+
QuantRuntimeSettings (配置 + 控制台)
7+
├── platform-config.json ← 单一配置源(唯一手动编辑)
8+
├── scripts/build_config.py ← 构建脚本(自动生成)
9+
├── web/strategy-switch-console/ ← 控制台 Worker
10+
└── .github/workflows/ ← CI/CD 自动部署
11+
12+
各域策略仓库(独立)
13+
├── CnEquityStrategies → cn_equity domain
14+
├── UsEquityStrategies → us_equity domain
15+
├── HkEquityStrategies → hk_equity domain
16+
├── CryptoStrategies → crypto domain
17+
18+
组合策略仓库(独立)
19+
├── QuantCnComboStrategies
20+
├── QuantUsComboStrategies
21+
├── QuantHkComboStrategies
22+
└── QuantCryptoComboStrategies
23+
24+
执行平台(独立)
25+
├── QmtPlatform → cn_equity
26+
├── BinancePlatform → crypto
27+
├── IB/Charles Schwab/FT/LB → us_equity, hk_equity
28+
```
29+
30+
---
31+
32+
## 操作手册
33+
34+
### 一、增加一个新平台
35+
36+
**只需改 1 个文件、加 ~10 行 JSON**
37+
38+
编辑 `platform-config.json``platforms` 段:
39+
40+
```json
41+
"new_platform_id": {
42+
"label": "New Platform",
43+
"code": "NP",
44+
"accent_color": "var(--np)",
45+
"css_var": "--np: #hexcolor",
46+
"repository": "QuantStrategyLab/NewPlatformRepo",
47+
"variable_scope": "repository",
48+
"supported_domains": ["us_equity"],
49+
"capabilities": {
50+
"margin_policy": true,
51+
"reserved_cash": true,
52+
"income_layer": true,
53+
"option_overlay": true,
54+
"dca": false
55+
},
56+
"default_account": {
57+
"key": "preview",
58+
"label": "New Platform",
59+
"target_name": "preview",
60+
"supported_domains": ["us_equity"]
61+
},
62+
"deployment": {
63+
"default_execution_mode": "live",
64+
"dry_run_only": false,
65+
"env_repo_key": ["STRATEGY_SWITCH_NP_REPO", "RUNTIME_SETTINGS_NP_REPO"]
66+
}
67+
}
68+
```
69+
70+
**capabilities 含义**
71+
72+
| 字段 | 作用 | 前端控制 |
73+
|------|------|---------|
74+
| `margin_policy` | 是否支持融资 | 显示现金策略控件 |
75+
| `reserved_cash` | 是否显示预留现金 | 显示预留现金控件 |
76+
| `income_layer` | 是否支持收入层 | 收入层下拉可选 |
77+
| `option_overlay` | 是否支持期权层 | 期权层下拉可选 |
78+
| `dca` | 是否支持定投 | 定投控件可见 |
79+
80+
**然后**
81+
```bash
82+
python3 scripts/build_config.py # 本地生成
83+
git add -A && git commit -m "Add platform: new_platform_id"
84+
git push origin main # CI/CD 自动部署
85+
```
86+
87+
---
88+
89+
### 二、增加一个新策略
90+
91+
**只需改 1 个文件、加 ~5 行 JSON**
92+
93+
编辑 `platform-config.json``strategies` 段:
94+
95+
```json
96+
"my_new_strategy": {
97+
"label": "策略中文名",
98+
"label_en": "Strategy English Name",
99+
"domain": "us_equity",
100+
"runtime_enabled": true,
101+
"features": {
102+
"income_layer": false,
103+
"option_overlay": false,
104+
"dca": false,
105+
"combo": false
106+
}
107+
}
108+
```
109+
110+
**若需要收入层**:加 `"income_layer": true` + `income_layer_defaults`
111+
**若需要期权层**:加 `"option_overlay": true` + `option_overlay_defaults`
112+
**若是定投策略**:加 `"dca": true` + `dca_defaults`
113+
**若是组合策略**:加 `"combo": true, "combo_mode": "dynamic"`
114+
115+
**然后**
116+
```bash
117+
python3 scripts/build_config.py
118+
git add -A && git commit -m "Add strategy: my_new_strategy"
119+
git push origin main
120+
```
121+
122+
---
123+
124+
### 三、增加一个新域(股票市场)
125+
126+
**只需改 1 个文件、加 ~3 行 JSON**
127+
128+
编辑 `platform-config.json``domains` 段:
129+
130+
```json
131+
"new_domain": {
132+
"label_zh": "新市场",
133+
"label_en": "New Market"
134+
}
135+
```
136+
137+
然后把域赋给需要支持该市场的平台的 `supported_domains` 数组。
138+
139+
---
140+
141+
### 四、修改已有策略/平台
142+
143+
只改 `platform-config.json` 对应段落后重新构建:
144+
145+
```bash
146+
python3 scripts/build_config.py
147+
```
148+
149+
CI/CD 自动检测差异并部署。
150+
151+
---
152+
153+
## 本地开发流程
154+
155+
```bash
156+
# 1. 修改配置
157+
vim platform-config.json
158+
159+
# 2. 验证并构建
160+
python3 scripts/build_config.py --check # 只验证
161+
python3 scripts/build_config.py # 构建
162+
163+
# 3. 预览(需要 wrangler)
164+
cd web/strategy-switch-console
165+
npx wrangler dev --port 8787
166+
```
167+
168+
## CI/CD 流程
169+
170+
```mermaid
171+
git push main
172+
173+
├─→ validate.yml(PR/推送触发)
174+
│ ├── build_config.py --check
175+
│ ├── runtime_settings.py validate
176+
│ ├── JavaScript 语法检查
177+
│ └── 回归验证(已生成文件 vs git HEAD)
178+
179+
└─→ deploy-strategy-switch-console.yml(platform-config.json 变更时触发)
180+
├── build_config.py(重新生成)
181+
├── sync_strategy_switch_page_asset.py(同步)
182+
├── validate(同上)
183+
└── wrangler deploy(Clouderflare Worker 部署)
184+
```
185+
186+
## 禁止事项
187+
188+
-**禁止**`index.html``worker.js` 中硬编码平台名称/颜色/仓库
189+
-**禁止**`index.html` 中硬编码 `defaultAccountOptions`/`defaultRepositories`/`platformMeta`
190+
-**禁止**手动编辑 `strategy_profiles_asset.js``page_asset.js`(由构建脚本生成)
191+
-**禁止**跳过 `build_config.py --check` 步骤直接部署
192+
- ✅ 所有平台/策略/域的新增和修改,必须在 `platform-config.json` 中完成
193+
194+
## 概念索引
195+
196+
| 概念 | 定义位置 | 前端消费 | 说明 |
197+
|------|---------|---------|------|
198+
| **Platform** | `platform-config.json > platforms` | 控制台 Tab、帐号下拉、策略过滤 | 交易所/券商等执行端 |
199+
| **Domain** | `platform-config.json > domains` | 策略分类标签、平台可选的域 | 股票市场类型 |
200+
| **Strategy** | `platform-config.json > strategies` | 策略下拉、控件显隐 | 交易策略 |
201+
| **Capability** | `platforms.*.capabilities` | `platformSupports*` 系列函数 | 平台能力声明 |
202+
| **Feature** | `strategies.*.features` | 收入层/期权层/DCA 控件显隐 | 策略特性声明 |

web/strategy-switch-console/worker.js

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -534,24 +534,54 @@ async function renderAdminPage(state) {
534534
</html>`;
535535
}
536536

537-
const PLATFORM_META = {
538-
longbridge: { label: "LongBridge", code: "LB", accent: "var(--lb)" },
539-
ibkr: { label: "IBKR", code: "IB", accent: "var(--ib)" },
540-
schwab: { label: "Schwab", code: "SW", accent: "var(--sw)" },
541-
firstrade: { label: "Firstrade", code: "FT", accent: "var(--ft)" },
542-
qmt: { label: "QMT", code: "QM", accent: "var(--qmt)" },
543-
binance: { label: "Binance", code: "BN", accent: "var(--bn)" },
544-
};
537+
let _cachedSharedConfig = null;
538+
let _cachedPlatformMeta = null;
539+
540+
async function loadSharedConfig() {
541+
if (_cachedSharedConfig) return _cachedSharedConfig;
542+
try {
543+
const url = "https://raw.githubusercontent.com/QuantStrategyLab/QuantRuntimeSettings/main/platform-config.json";
544+
const resp = await fetchWithTimeout(url, {}, 5000);
545+
if (resp.ok) _cachedSharedConfig = await resp.json();
546+
} catch { /* fallback to hardcoded */ }
547+
return _cachedSharedConfig;
548+
}
549+
550+
async function loadPlatformMeta() {
551+
const merged = {
552+
longbridge: { label: "LongBridge", code: "LB", accent: "var(--lb)" },
553+
ibkr: { label: "IBKR", code: "IB", accent: "var(--ib)" },
554+
schwab: { label: "Schwab", code: "SW", accent: "var(--sw)" },
555+
firstrade: { label: "Firstrade", code: "FT", accent: "var(--ft)" },
556+
qmt: { label: "QMT", code: "QM", accent: "var(--qmt)" },
557+
binance: { label: "Binance", code: "BN", accent: "var(--bn)" },
558+
};
559+
try {
560+
const config = await loadSharedConfig();
561+
if (config && config.platforms) {
562+
const raw = config.platforms;
563+
for (const pid of Object.keys(raw)) {
564+
merged[pid] = {
565+
label: raw[pid].label,
566+
code: raw[pid].code,
567+
accent: raw[pid].accent_color,
568+
};
569+
}
570+
}
571+
} catch { /* keep defaults */ }
572+
return merged;
573+
}
545574

546575
async function configPayload(request, env) {
547576
const session = await readSession(request, env);
548-
if (!session?.allowed) return { accountOptions: null, platformMeta: PLATFORM_META };
577+
const meta = await loadPlatformMeta();
578+
if (!session?.allowed) return { accountOptions: null, platformMeta: meta };
549579
const accountConfig = await loadAccountOptionsConfig(env);
550580
const strategyProfiles = await loadStrategyProfilesConfig(env);
551581
return {
552582
accountOptions: accountConfig.options,
553583
platformRepositories: platformRepositories(env),
554-
platformMeta: PLATFORM_META,
584+
platformMeta: meta,
555585
strategyProfiles,
556586
currentStrategies: await loadCurrentStrategiesSafely(accountConfig.options, env),
557587
};
@@ -560,7 +590,7 @@ async function configPayload(request, env) {
560590
async function strategyProfilesPayload(env) {
561591
return {
562592
strategyProfiles: await loadStrategyProfilesConfig(env),
563-
platformMeta: PLATFORM_META,
593+
platformMeta: await loadPlatformMeta(),
564594
};
565595
}
566596

0 commit comments

Comments
 (0)