@openfinclaw/openfinclaw-strategy 0.0.11 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -93
- package/index.test.ts +11 -11
- package/index.ts +18 -979
- package/openclaw.plugin.json +25 -8
- package/package.json +10 -4
- package/skills/openfinclaw/SKILL.md +78 -78
- package/skills/price-check/SKILL.md +118 -0
- package/skills/skill-publish/SKILL.md +4 -4
- package/skills/strategy-builder/SKILL.md +124 -399
- package/skills/strategy-fork/SKILL.md +2 -2
- package/skills/strategy-pack/SKILL.md +12 -12
- package/src/cli.ts +5 -5
- package/src/config.ts +57 -0
- package/src/datahub/client.ts +150 -0
- package/src/datahub/tools.ts +349 -0
- package/src/strategy/client.ts +44 -0
- package/src/{fork.ts → strategy/fork.ts} +12 -11
- package/src/{strategy-storage.ts → strategy/storage.ts} +6 -7
- package/src/strategy/tools.ts +524 -0
- package/src/{validate.ts → strategy/validate.ts} +3 -35
- package/src/types.ts +42 -0
- package/LICENSE +0 -21
- package/src/strategy-storage.test.ts +0 -109
- package/src/validate.test.ts +0 -841
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: strategy-builder
|
|
3
|
-
description: "Strategy builder — turn natural language trading ideas into compliant FEP v2.0 strategy packages
|
|
3
|
+
description: "Strategy builder — turn natural language trading ideas into compliant FEP v2.0 strategy packages (fep.yaml + scripts/strategy.py), with validation and L1/L2 routing."
|
|
4
4
|
metadata:
|
|
5
5
|
openclaw:
|
|
6
6
|
emoji: "🏗️"
|
|
@@ -8,13 +8,13 @@ metadata:
|
|
|
8
8
|
|
|
9
9
|
# Strategy Builder (FEP v2.0)
|
|
10
10
|
|
|
11
|
-
Turn natural language trading ideas into **FEP v2.0** strategy packages
|
|
11
|
+
Turn natural language trading ideas into **FEP v2.0** strategy packages. Generates `fep.yaml` + `scripts/strategy.py` (and optional `risk_manager.py`, `indicators.py`), validates against the spec.
|
|
12
12
|
|
|
13
13
|
## Prerequisites (tool profile)
|
|
14
14
|
|
|
15
|
-
This skill needs **read** (read files) and **exec** (run shell commands). Ensure the agent has the **coding** tool profile: set `tools.profile: "coding"` or `tools.alsoAllow: ["read", "exec", "write", "edit"]`.
|
|
15
|
+
This skill needs **read** (read files) and **exec** (run shell commands). Ensure the agent has the **coding** tool profile: set `tools.profile: "coding"` or `tools.alsoAllow: ["read", "exec", "write", "edit"]`.
|
|
16
16
|
|
|
17
|
-
**No subagent required.** Do strategy creation in the **current session**: use read/write/edit to create `fep.yaml` and `scripts/strategy.py`, and exec for zip/validate.
|
|
17
|
+
**No subagent required.** Do strategy creation in the **current session**: use read/write/edit to create `fep.yaml` and `scripts/strategy.py`, and exec for zip/validate.
|
|
18
18
|
|
|
19
19
|
## When to Use
|
|
20
20
|
|
|
@@ -27,40 +27,32 @@ This skill needs **read** (read files) and **exec** (run shell commands). Ensure
|
|
|
27
27
|
- "I have a trading idea but don't know how to code it"
|
|
28
28
|
- "create a strategy for sideways crypto markets"
|
|
29
29
|
- "turn this idea into a backtest-ready package"
|
|
30
|
-
- "build a grid trading strategy for SOL"
|
|
31
30
|
|
|
32
31
|
## When NOT to Use
|
|
33
32
|
|
|
34
33
|
**DON'T use this skill when:**
|
|
35
34
|
|
|
36
|
-
- User wants to backtest an existing strategy — use
|
|
37
|
-
- User wants to
|
|
38
|
-
- User wants
|
|
39
|
-
- User wants
|
|
40
|
-
- User wants portfolio analysis — use fin-portfolio
|
|
35
|
+
- User wants to backtest an existing strategy — use skill_publish
|
|
36
|
+
- User wants to Fork/download a strategy from Hub — use skill_fork
|
|
37
|
+
- User wants to execute a live trade — use trading tools
|
|
38
|
+
- User wants portfolio analysis — use portfolio tools
|
|
41
39
|
|
|
42
40
|
## Tools
|
|
43
41
|
|
|
44
|
-
###
|
|
42
|
+
### Strategy Tools (from this plugin)
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
| Tool | Purpose |
|
|
45
|
+
| ---------------------- | ---------------------------------------------- |
|
|
46
|
+
| `skill_validate` | Validate strategy package directory (FEP v2.0) |
|
|
47
|
+
| `skill_publish` | Publish strategy ZIP to Hub |
|
|
48
|
+
| `skill_publish_verify` | Query publish status and backtest report |
|
|
49
49
|
|
|
50
|
-
###
|
|
50
|
+
### Market Data Tools (for symbol validation)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- `backtest_remote_validate` — Validate strategy package directory (fep v2.0) before zip/submit; **use first** when dir is ready
|
|
58
|
-
- `backtest_remote_submit` — Submit strategy ZIP to Findoo Backtest API (after validate + zip)
|
|
59
|
-
- `backtest_remote_status` / `backtest_remote_report` — Query task status and full report
|
|
60
|
-
|
|
61
|
-
### Supporting
|
|
62
|
-
|
|
63
|
-
- `fin_paper_create` — Deploy validated strategy to paper trading (optional follow-up)
|
|
52
|
+
| Tool | Purpose |
|
|
53
|
+
| ----------- | ------------------------------------ |
|
|
54
|
+
| `fin_price` | Check current price, validate symbol |
|
|
55
|
+
| `fin_kline` | Get historical K-line data |
|
|
64
56
|
|
|
65
57
|
---
|
|
66
58
|
|
|
@@ -72,8 +64,8 @@ This skill needs **read** (read files) and **exec** (run shell commands). Ensure
|
|
|
72
64
|
<strategy-dir>/
|
|
73
65
|
├── fep.yaml # 策略配置 (必需)
|
|
74
66
|
├── scripts/
|
|
75
|
-
│ └── strategy.py # 策略入口 (必需)
|
|
76
|
-
└── .created-meta.json # 本地元数据 (
|
|
67
|
+
│ └── strategy.py # 策略入口 (必需)
|
|
68
|
+
└── .created-meta.json # 本地元数据 (必需)
|
|
77
69
|
```
|
|
78
70
|
|
|
79
71
|
**Optional:**
|
|
@@ -85,43 +77,35 @@ This skill needs **read** (read files) and **exec** (run shell commands). Ensure
|
|
|
85
77
|
└── data/ # 自定义数据
|
|
86
78
|
```
|
|
87
79
|
|
|
88
|
-
**Packaging:** `cd <strategy-dir> && zip -r ../<id>-<version>.zip fep.yaml scripts/`
|
|
80
|
+
**Packaging:** `cd <strategy-dir> && zip -r ../<id>-<version>.zip fep.yaml scripts/`
|
|
89
81
|
|
|
90
82
|
---
|
|
91
83
|
|
|
92
84
|
## fep.yaml (FEP v2.0)
|
|
93
85
|
|
|
94
|
-
### Minimal
|
|
86
|
+
### Minimal Example
|
|
95
87
|
|
|
96
88
|
```yaml
|
|
97
89
|
fep: "2.0"
|
|
98
90
|
|
|
99
|
-
# ── 身份标识 (必填) ───────────────────────────────────────
|
|
100
91
|
identity:
|
|
101
|
-
id: fin-dca-basic-test
|
|
102
|
-
type: strategy
|
|
103
|
-
name: "DCA Basic Test Strategy"
|
|
104
|
-
version: "1.0.0"
|
|
105
|
-
style: dca
|
|
106
|
-
visibility: public
|
|
107
|
-
summary: "Simple DCA strategy for BTC"
|
|
108
|
-
description: "A simple DCA strategy that buys BTC periodically"
|
|
109
|
-
license: MIT
|
|
110
|
-
tags: [dca, btc, crypto]
|
|
92
|
+
id: fin-dca-basic-test
|
|
93
|
+
type: strategy
|
|
94
|
+
name: "DCA Basic Test Strategy"
|
|
95
|
+
version: "1.0.0"
|
|
96
|
+
style: dca
|
|
97
|
+
visibility: public
|
|
98
|
+
summary: "Simple DCA strategy for BTC"
|
|
99
|
+
description: "A simple DCA strategy that buys BTC periodically"
|
|
100
|
+
license: MIT
|
|
101
|
+
tags: [dca, btc, crypto]
|
|
111
102
|
author:
|
|
112
|
-
name: "OpenFinClaw"
|
|
113
|
-
wallet: "0x..." # 可选:收益分配地址
|
|
103
|
+
name: "OpenFinClaw"
|
|
114
104
|
changelog:
|
|
115
105
|
- version: "1.0.0"
|
|
116
|
-
date: "
|
|
106
|
+
date: "2026-01-01"
|
|
117
107
|
changes: "Initial release"
|
|
118
108
|
|
|
119
|
-
# ── 技术配置 (可选,有默认值) ───────────────────────────────
|
|
120
|
-
technical:
|
|
121
|
-
language: python # 默认 python
|
|
122
|
-
entryPoint: strategy.py # 默认 strategy.py
|
|
123
|
-
|
|
124
|
-
# ── 策略参数 (可选) ───────────────────────────────────────
|
|
125
109
|
parameters:
|
|
126
110
|
- name: base_amount
|
|
127
111
|
default: 100
|
|
@@ -129,147 +113,55 @@ parameters:
|
|
|
129
113
|
label: "基础定投金额"
|
|
130
114
|
range: { min: 10, max: 10000 }
|
|
131
115
|
|
|
132
|
-
# ── 回测配置 (必填) ───────────────────────────────────────
|
|
133
116
|
backtest:
|
|
134
|
-
symbol: "BTC/USDT"
|
|
135
|
-
timeframe: 1d
|
|
117
|
+
symbol: "BTC/USDT"
|
|
118
|
+
timeframe: 1d
|
|
136
119
|
defaultPeriod:
|
|
137
120
|
startDate: "2025-01-01"
|
|
138
121
|
endDate: "2026-01-01"
|
|
139
|
-
initialCapital: 10000
|
|
122
|
+
initialCapital: 10000
|
|
140
123
|
|
|
141
|
-
# ── 风控配置 (可选) ───────────────────────────────────────
|
|
142
|
-
risk:
|
|
143
|
-
maxDrawdownThreshold: 25 # 最大回撤限制 (%)
|
|
144
|
-
dailyLossLimitPct: 5 # 日亏损限制 (%)
|
|
145
|
-
maxTradesPerDay: 10 # 日最大交易笔数
|
|
146
|
-
|
|
147
|
-
# ── 分类 (必填) ───────────────────────────────────────
|
|
148
124
|
classification:
|
|
149
|
-
archetype: systematic
|
|
150
|
-
market: Crypto
|
|
151
|
-
assetClasses: [crypto]
|
|
152
|
-
frequency: daily
|
|
153
|
-
riskProfile: medium
|
|
125
|
+
archetype: systematic
|
|
126
|
+
market: Crypto
|
|
127
|
+
assetClasses: [crypto]
|
|
128
|
+
frequency: daily
|
|
129
|
+
riskProfile: medium
|
|
154
130
|
```
|
|
155
131
|
|
|
156
|
-
###
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
author:
|
|
181
|
-
name: "OpenFinClaw" # 必填:作者名
|
|
182
|
-
wallet: "0x..." # 可选:收益分配地址
|
|
183
|
-
```
|
|
184
|
-
- `changelog`: 变更日志数组(至少包含一条初始版本记录)
|
|
185
|
-
```yaml
|
|
186
|
-
changelog:
|
|
187
|
-
- version: "1.0.0"
|
|
188
|
-
date: "2026-01-01"
|
|
189
|
-
changes: "Initial release"
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**可选字段:**
|
|
193
|
-
|
|
194
|
-
- `createdAt`: `"2025-01-01"` (YYYY-MM-DD)
|
|
195
|
-
- `updatedAt`: `"2025-06-01"` (YYYY-MM-DD)
|
|
196
|
-
|
|
197
|
-
### Backtest Fields (FEP v2.0)
|
|
198
|
-
|
|
199
|
-
**必填字段:**
|
|
200
|
-
|
|
201
|
-
- `symbol`: 交易品种(服务端根据 symbol 自动推断市场类型、数据源、货币、手续费和结算规则)
|
|
202
|
-
- `defaultPeriod.startDate`: 回测开始日期
|
|
203
|
-
- `defaultPeriod.endDate`: 回测结束日期
|
|
204
|
-
- `initialCapital`: 初始资金
|
|
205
|
-
|
|
206
|
-
**可选字段:**
|
|
207
|
-
|
|
208
|
-
- `timeframe`: K线周期,`1m` | `5m` | `15m` | `30m` | `1h` | `4h` | `1d` | `1w`(默认 `1d`)
|
|
209
|
-
- `universe`: 多标的配置(轮动策略用)
|
|
210
|
-
```yaml
|
|
211
|
-
universe:
|
|
212
|
-
symbols: ["000001.SZ", "000002.SZ", "600519.SH"]
|
|
213
|
-
```
|
|
214
|
-
- `rebalance`: 再平衡配置(多标的用)
|
|
215
|
-
```yaml
|
|
216
|
-
rebalance:
|
|
217
|
-
frequency: monthly # daily | weekly | monthly
|
|
218
|
-
maxHoldings: 2 # 最大同时持仓数
|
|
219
|
-
weightMethod: equal # equal | market_cap
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
**服务端自动推断(用户无需指定):**
|
|
223
|
-
|
|
224
|
-
| 配置项 | 推断规则 |
|
|
225
|
-
| -------- | --------------------------------------------------------------------------------- |
|
|
226
|
-
| 市场类型 | `000001.SZ` → A股, `AAPL` → 美股, `BTC/USDT` → Crypto, `00700.HK` → 港股 |
|
|
227
|
-
| 数据源 | 可识别 symbol → DataHub 真实数据, 未知 → 合成数据 |
|
|
228
|
-
| 货币 | A股 → CNY, 美股 → USD, 港股 → HKD, Crypto → USDT |
|
|
229
|
-
| 手续费 | A股: 佣金+印花税+过户费, 港股: 佣金+印花税+征费, 美股: 零佣金, Crypto: MakerTaker |
|
|
230
|
-
| 结算规则 | A股/ETF → T+1, 其余 → T+0 |
|
|
132
|
+
### Identity Fields (必填)
|
|
133
|
+
|
|
134
|
+
| Field | Description |
|
|
135
|
+
| ------------- | --------------------------------- | ---------------- | ------------- | ----- | -------- |
|
|
136
|
+
| `id` | 策略唯一标识(英文 + 连字符) |
|
|
137
|
+
| `name` | 策略显示名称 |
|
|
138
|
+
| `version` | 语义化版本号(如 `"1.0.0"`) |
|
|
139
|
+
| `style` | `trend` | `mean-reversion` | `momentum` | `dca` | `hybrid` |
|
|
140
|
+
| `visibility` | `public` | `private` | `unlisted` |
|
|
141
|
+
| `summary` | 一句话策略描述 |
|
|
142
|
+
| `description` | 详细策略说明 |
|
|
143
|
+
| `license` | `MIT` | `CC-BY-4.0` | `proprietary` |
|
|
144
|
+
| `tags` | 标签数组,如 `[dca, btc, crypto]` |
|
|
145
|
+
| `author` | 对象,必须包含 `name` 字段 |
|
|
146
|
+
| `changelog` | 变更日志数组 |
|
|
147
|
+
|
|
148
|
+
### Backtest Fields (必填)
|
|
149
|
+
|
|
150
|
+
| Field | Description |
|
|
151
|
+
| ------------------------- | ------------------------ |
|
|
152
|
+
| `symbol` | 交易品种(自动推断市场) |
|
|
153
|
+
| `defaultPeriod.startDate` | 回测开始日期 |
|
|
154
|
+
| `defaultPeriod.endDate` | 回测结束日期 |
|
|
155
|
+
| `initialCapital` | 初始资金 |
|
|
231
156
|
|
|
232
157
|
### Symbol 格式
|
|
233
158
|
|
|
234
|
-
| 格式
|
|
235
|
-
|
|
|
236
|
-
| `XXX/YYY`
|
|
237
|
-
| `6位数.SZ/SH`
|
|
238
|
-
| `5位数.
|
|
239
|
-
| `
|
|
240
|
-
| `4-5位数.HK` | 港股 | `00700.HK` |
|
|
241
|
-
| `1-5大写字母` | 美股 | `AAPL`, `NVDA` |
|
|
242
|
-
| `字母+数字.交易所` | 期货 | `IF2503.CFX` |
|
|
243
|
-
|
|
244
|
-
### Classification (必填)
|
|
245
|
-
|
|
246
|
-
```yaml
|
|
247
|
-
classification:
|
|
248
|
-
archetype: systematic # 必填: systematic | discretionary | hybrid
|
|
249
|
-
market: Crypto # 必填: Crypto | US | CN | HK | Forex | Commodity
|
|
250
|
-
assetClasses: [crypto] # 必填: 资产类别数组
|
|
251
|
-
frequency: daily # 必填: daily | weekly | monthly
|
|
252
|
-
riskProfile: medium # 必填: low | medium | high
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Risk (可选)
|
|
256
|
-
|
|
257
|
-
```yaml
|
|
258
|
-
risk:
|
|
259
|
-
maxDrawdownThreshold: 25 # 最大回撤限制 (%),默认 25
|
|
260
|
-
dailyLossLimitPct: 5 # 日亏损限制 (%),默认 5
|
|
261
|
-
maxTradesPerDay: 10 # 日最大交易笔数,默认 10
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### Paper (可选)
|
|
265
|
-
|
|
266
|
-
```yaml
|
|
267
|
-
paper:
|
|
268
|
-
barIntervalSeconds: 60 # 行情轮询间隔(秒),默认 60
|
|
269
|
-
maxDurationHours: 24 # 最大运行时长,默认 24
|
|
270
|
-
warmupBars: 100 # 预热 K 线数,默认 100
|
|
271
|
-
timeframe: 1d # 模拟盘 K 线周期
|
|
272
|
-
```
|
|
159
|
+
| 格式 | 市场 | 示例 |
|
|
160
|
+
| ------------- | ------ | ------------------------ |
|
|
161
|
+
| `XXX/YYY` | Crypto | `BTC/USDT`, `ETH/BTC` |
|
|
162
|
+
| `6位数.SZ/SH` | A股 | `000001.SZ`, `600519.SH` |
|
|
163
|
+
| `5位数.HK` | 港股 | `00700.HK` |
|
|
164
|
+
| `1-5大写字母` | 美股 | `AAPL`, `NVDA` |
|
|
273
165
|
|
|
274
166
|
---
|
|
275
167
|
|
|
@@ -277,279 +169,112 @@ paper:
|
|
|
277
169
|
|
|
278
170
|
### 单标的策略:compute() 函数
|
|
279
171
|
|
|
280
|
-
**Must** implement a single entry function:
|
|
281
|
-
|
|
282
172
|
```python
|
|
283
|
-
|
|
284
|
-
def compute(data):
|
|
173
|
+
def compute(data, context=None):
|
|
285
174
|
"""
|
|
286
175
|
Args:
|
|
287
|
-
data: pandas DataFrame, 包含 OHLCV 列
|
|
176
|
+
data: pandas DataFrame, 包含 OHLCV 列
|
|
177
|
+
context: dict with equity, cash, position, bar_index
|
|
288
178
|
Returns:
|
|
289
|
-
dict: {"action": "buy"|"sell"|"hold"
|
|
179
|
+
dict: {"action": "buy"|"sell"|"hold", ...}
|
|
290
180
|
"""
|
|
291
181
|
close = data["close"].values
|
|
292
182
|
current_price = float(close[-1])
|
|
183
|
+
|
|
293
184
|
return {
|
|
294
185
|
"action": "buy",
|
|
295
186
|
"amount": 100.0,
|
|
296
187
|
"price": current_price,
|
|
297
188
|
"reason": f"Buy at ${current_price:.2f}",
|
|
298
189
|
}
|
|
299
|
-
|
|
300
|
-
# 模式 B: 带 context(推荐,可获取仓位和资金信息)
|
|
301
|
-
def compute(data, context=None):
|
|
302
|
-
"""
|
|
303
|
-
Args:
|
|
304
|
-
data: pandas DataFrame
|
|
305
|
-
context: dict with equity, cash, position, bar_index
|
|
306
|
-
"""
|
|
307
|
-
position = context.get("position") if context else None
|
|
308
|
-
# ...
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
**context 结构:**
|
|
312
|
-
|
|
313
|
-
```python
|
|
314
|
-
{
|
|
315
|
-
"equity": 95000.0, # 当前账户净值
|
|
316
|
-
"cash": 45000.0, # 可用现金
|
|
317
|
-
"initial_capital": 100000.0, # 初始资金
|
|
318
|
-
"position": { # 有持仓时
|
|
319
|
-
"side": "long",
|
|
320
|
-
"quantity": 100.0,
|
|
321
|
-
"market_value": 50000.0
|
|
322
|
-
} or None, # 无持仓时
|
|
323
|
-
"bar_index": 150 # 全局 K 线索引
|
|
324
|
-
}
|
|
325
190
|
```
|
|
326
191
|
|
|
327
|
-
|
|
192
|
+
### 信号返回格式
|
|
328
193
|
|
|
329
|
-
| action
|
|
330
|
-
|
|
|
331
|
-
| `buy`
|
|
332
|
-
| `sell`
|
|
333
|
-
| `hold`
|
|
334
|
-
| `target` | target_pct 或 target_value | reason | 调仓到目标权重/金额 |
|
|
194
|
+
| action | 必填字段 | 说明 |
|
|
195
|
+
| ------ | ------------- | ------------- |
|
|
196
|
+
| `buy` | amount, price | 按金额买入 |
|
|
197
|
+
| `sell` | — | 无参数=全仓卖 |
|
|
198
|
+
| `hold` | — | 不操作 |
|
|
335
199
|
|
|
336
|
-
###
|
|
200
|
+
### Allowed Imports
|
|
337
201
|
|
|
338
|
-
|
|
202
|
+
`numpy`, `pandas`, `math`, `statistics`, `datetime`, `collections`, `ta`
|
|
339
203
|
|
|
340
|
-
|
|
341
|
-
def select(universe):
|
|
342
|
-
"""
|
|
343
|
-
Args:
|
|
344
|
-
universe: dict[str, pd.DataFrame] - {symbol: DataFrame}
|
|
345
|
-
Returns:
|
|
346
|
-
list[str]: 选中标的列表(按优先级排序)
|
|
347
|
-
"""
|
|
348
|
-
scores = []
|
|
349
|
-
for symbol, df in universe.items():
|
|
350
|
-
close = df["close"].values
|
|
351
|
-
if len(close) < 20:
|
|
352
|
-
continue
|
|
353
|
-
momentum = (close[-1] / close[-20]) - 1
|
|
354
|
-
scores.append((symbol, momentum))
|
|
355
|
-
|
|
356
|
-
scores.sort(key=lambda x: x[1], reverse=True)
|
|
357
|
-
return [s[0] for s in scores] # 引擎自动截取 maxHoldings 个
|
|
358
|
-
```
|
|
204
|
+
### Forbidden
|
|
359
205
|
|
|
360
|
-
|
|
361
|
-
- **Forbidden (server will reject):** `import os/subprocess/sys/socket/shutil/ctypes/importlib/signal/threading/multiprocessing/pathlib/tempfile/requests/urllib/http/ftplib/smtplib/xmlrpc/pickle/shelve/marshal/concurrent/asyncio/io`, `eval()`, `exec()`, `compile()`, `open()`, `__import__()`, `getattr()`, `setattr()`, `delattr()`, `vars()`, `dir()`, `breakpoint()`, `exit()`, `quit()`, `input()`, `globals()`, `locals()`
|
|
362
|
-
- **Forbidden (breaks backtest):** `datetime.now()`, `date.today()`
|
|
206
|
+
`import os/subprocess/sys/socket/shutil/ctypes/...`, `eval()`, `exec()`, `open()`, `datetime.now()`
|
|
363
207
|
|
|
364
208
|
---
|
|
365
209
|
|
|
366
210
|
## Builder Pipeline
|
|
367
211
|
|
|
368
|
-
### Step 1: Intent Collection
|
|
212
|
+
### Step 1: Intent Collection
|
|
369
213
|
|
|
370
214
|
Extract key dimensions:
|
|
371
215
|
|
|
372
|
-
| Dimension | Example
|
|
373
|
-
| -------------- |
|
|
374
|
-
| Asset | BTC, ETH, AAPL
|
|
375
|
-
| Frequency | daily, weekly
|
|
376
|
-
| Core idea | buy dips, trend follow,
|
|
377
|
-
| Capital | $10,000
|
|
378
|
-
| Risk tolerance | 25% max drawdown
|
|
379
|
-
| Time horizon |
|
|
380
|
-
| Market | Crypto, US, CN, HK |
|
|
216
|
+
| Dimension | Example |
|
|
217
|
+
| -------------- | --------------------------- |
|
|
218
|
+
| Asset | BTC, ETH, AAPL |
|
|
219
|
+
| Frequency | daily, weekly |
|
|
220
|
+
| Core idea | buy dips, trend follow, DCA |
|
|
221
|
+
| Capital | $10,000 |
|
|
222
|
+
| Risk tolerance | 25% max drawdown |
|
|
223
|
+
| Time horizon | 2025-01-01 to 2026-01-01 |
|
|
381
224
|
|
|
382
|
-
|
|
225
|
+
### Step 2: Technical Design
|
|
383
226
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
Propose: strategy archetype (DCA, trend, mean-reversion, momentum, grid), indicators (RSI, EMA, MACD, etc.), entry/exit logic, position sizing, risk controls, market adaptations. **Wait for user confirmation** before generating code.
|
|
227
|
+
Propose: strategy archetype, indicators, entry/exit logic, position sizing, risk controls. **Wait for user confirmation** before generating code.
|
|
387
228
|
|
|
388
229
|
### Step 2.5: Determine Target Directory
|
|
389
230
|
|
|
390
|
-
**
|
|
231
|
+
**Standard path:**
|
|
391
232
|
|
|
392
233
|
```
|
|
393
234
|
~/.openfinclaw/workspace/strategies/{YYYY-MM-DD}/{slugified-name}/
|
|
394
235
|
```
|
|
395
236
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
- `{YYYY-MM-DD}`: Current date (e.g., `2026-03-19`), organizes strategies by creation date
|
|
399
|
-
- `{slugified-name}`: Lowercase, spaces/underscores to hyphens, max 40 chars (e.g., `btc-adaptive-dca`)
|
|
400
|
-
- **ALWAYS** create the date directory if it does not exist
|
|
401
|
-
- **NEVER** save strategies to arbitrary directories like `~/clawd`, `~/projects`, etc.
|
|
402
|
-
|
|
403
|
-
**Directory creation sequence:**
|
|
404
|
-
|
|
405
|
-
1. Compute `dateStr = formatDate(new Date())` → `"YYYY-MM-DD"`
|
|
406
|
-
2. Compute `slug = slugifyName(strategyName)` → lowercase-hyphenated
|
|
407
|
-
3. `rootDir = path.join(homedir(), ".openfinclaw", "workspace", "strategies")`
|
|
408
|
-
4. `dateDir = path.join(rootDir, dateStr)` — create if not exists
|
|
409
|
-
5. `targetDir = path.join(dateDir, slug)` — final strategy directory
|
|
410
|
-
|
|
411
|
-
**Example:**
|
|
412
|
-
|
|
413
|
-
```
|
|
414
|
-
Strategy name: "BTC Adaptive DCA"
|
|
415
|
-
Date: 2026-03-19
|
|
416
|
-
Target dir: ~/.openfinclaw/workspace/strategies/2026-03-19/btc-adaptive-dca/
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**Metadata file (.created-meta.json):** After creating the strategy files, also generate this metadata file in the strategy directory:
|
|
237
|
+
Example: `~/.openfinclaw/workspace/strategies/2026-03-19/btc-adaptive-dca/`
|
|
420
238
|
|
|
421
|
-
|
|
422
|
-
{
|
|
423
|
-
"name": "fin-btc-adaptive-dca",
|
|
424
|
-
"displayName": "BTC Adaptive DCA",
|
|
425
|
-
"createdAt": "2026-03-19T10:30:00.000Z",
|
|
426
|
-
"version": "1.0.0"
|
|
427
|
-
}
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
### Step 3: Code Generation (FEP v2.0)
|
|
239
|
+
### Step 3: Code Generation
|
|
431
240
|
|
|
432
241
|
Generate:
|
|
433
242
|
|
|
434
|
-
1. **fep.yaml** —
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
- **parameters** (可选): 策略参数数组
|
|
438
|
-
- **backtest** (必填): symbol, defaultPeriod, initialCapital; 可选 timeframe, universe, rebalance
|
|
439
|
-
- **classification** (必填): archetype, market, assetClasses, frequency, riskProfile
|
|
440
|
-
- **risk** (可选): 风控配置
|
|
441
|
-
|
|
442
|
-
**生成规则:**
|
|
443
|
-
- `fep` 版本必须是 `"2.0"`
|
|
444
|
-
- `backtest.defaultPeriod.endDate` 默认使用当前日期(格式 `YYYY-MM-DD`)
|
|
445
|
-
- `backtest.defaultPeriod.startDate` 根据用户描述选择合理区间(例如最近 6–12 个月)
|
|
446
|
-
- `backtest.symbol` 必填,服务端自动推断市场和手续费
|
|
447
|
-
- **classification 必填字段及默认值:**
|
|
448
|
-
- `archetype`: 默认 `systematic`(除非用户明确需要主观判断)
|
|
449
|
-
- `market`: 根据标的自动推断(BTC/ETH → `Crypto`,AAPL → `US` 等)
|
|
450
|
-
- `assetClasses`: 根据标的自动推断(BTC/ETH → `[crypto]`,AAPL → `[equity]`)
|
|
451
|
-
- `frequency`: 默认 `daily`(日频)
|
|
452
|
-
- `riskProfile`: 默认 `medium`
|
|
453
|
-
- **版本递增规则:** 如果策略 `id` 已存在(用户修改现有策略),必须递增 `identity.version`
|
|
454
|
-
- **默认作者:** `identity.author.name` 默认为 `"OpenFinClaw"`,除非用户指定其他作者
|
|
455
|
-
- **默认可见性:** `identity.visibility` 默认为 `"public"`(公开策略)
|
|
456
|
-
- **默认许可证:** `identity.license` 默认为 `"MIT"`
|
|
457
|
-
- **默认风格:** `identity.style` 根据策略类型自动选择
|
|
458
|
-
- **tags 格式:** 必须使用行内数组 `tags: [dca, btc, crypto]`
|
|
459
|
-
|
|
460
|
-
2. **scripts/strategy.py** — Must define `compute(data)` or `compute(data, context=None)` returning signal dict, or `select(universe)` for multi-asset strategies. Use only allowed imports; no forbidden patterns.
|
|
461
|
-
|
|
462
|
-
3. **.created-meta.json** — Metadata file for local strategy tracking (required for all locally created strategies):
|
|
463
|
-
|
|
464
|
-
```json
|
|
465
|
-
{
|
|
466
|
-
"name": "fin-btc-adaptive-dca",
|
|
467
|
-
"displayName": "BTC Adaptive DCA",
|
|
468
|
-
"createdAt": "2026-03-19T10:30:00.000Z",
|
|
469
|
-
"version": "1.0.0"
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
4. **Optional:** scripts/indicators.py, scripts/risk_manager.py (if design needs them; entry contract remains `compute(data)` in strategy.py).
|
|
474
|
-
|
|
475
|
-
Present the package structure and wait for confirmation before validation.
|
|
243
|
+
1. **fep.yaml** — 完整的 FEP v2.0 配置
|
|
244
|
+
2. **scripts/strategy.py** — 实现 `compute(data)` 函数
|
|
245
|
+
3. **.created-meta.json** — 本地元数据
|
|
476
246
|
|
|
477
247
|
### Step 4: Self-Validation
|
|
478
248
|
|
|
479
|
-
1. **Structure:**
|
|
480
|
-
2. **fep.yaml:**
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
- `backtest`: symbol, defaultPeriod (startDate/endDate), initialCapital (全部必填)
|
|
484
|
-
- `classification`: archetype, market, assetClasses, frequency, riskProfile (全部必填)
|
|
485
|
-
3. **strategy.py:** Defines `compute(data)` or `select(universe)`; return dict has required fields; no forbidden imports/calls.
|
|
486
|
-
4. **.created-meta.json:** Valid JSON with `name`, `displayName`, `createdAt`, `version` fields.
|
|
487
|
-
5. **Target directory:** Must be under `~/.openfinclaw/workspace/strategies/{YYYY-MM-DD}/`.
|
|
488
|
-
6. If **fin-backtest-remote** is available: call `backtest_remote_validate` with the strategy directory path; if `valid: false`, fix `errors` and re-validate. Do not zip/submit until validation passes.
|
|
489
|
-
7. **Sanity run:** If local backtest is available (`fin_backtest_run`), run on a short period to confirm code executes.
|
|
490
|
-
|
|
491
|
-
Auto-fix and re-validate up to 3 iterations; if still failing, explain clearly to the user.
|
|
249
|
+
1. **Structure:** 检查必需文件
|
|
250
|
+
2. **fep.yaml:** 验证必填字段
|
|
251
|
+
3. **strategy.py:** 检查函数签名和禁止的导入
|
|
252
|
+
4. 调用 `skill_validate(dirPath)` 验证
|
|
492
253
|
|
|
493
|
-
### Step 5:
|
|
494
|
-
|
|
495
|
-
| Signal | L1 (script) | L2 (agent) |
|
|
496
|
-
| ----------------- | ------------------------- | ------------------------------------- |
|
|
497
|
-
| Decision logic | Fully deterministic rules | Requires judgment, context |
|
|
498
|
-
| Engine in fep/API | `engine: script` or omit | `engine: agent`, `agent.budgetCapUsd` |
|
|
499
|
-
| Cost | No LLM cost | LLM budget cap |
|
|
500
|
-
|
|
501
|
-
**Default: L1.** Only set L2 (agent section in fep.yaml, engine=agent on submit) when the user explicitly wants agent involvement or strategy benefits from LLM analysis.
|
|
502
|
-
|
|
503
|
-
### Step 6: Delivery & Optional Remote Backtest
|
|
254
|
+
### Step 5: Delivery
|
|
504
255
|
|
|
505
256
|
Present the package and next steps:
|
|
506
257
|
|
|
507
|
-
-
|
|
508
|
-
-
|
|
509
|
-
1. Ensure directory is validated (`backtest_remote_validate`)
|
|
510
|
-
2. Zip: `zip -r ../<id>-<version>.zip fep.yaml scripts/` (e.g. `fin-dca-basic-test-1.0.0.zip`)
|
|
511
|
-
3. Submit with `backtest_remote_submit` (filePath, optional engine, budget_cap_usd)
|
|
512
|
-
4. Poll with `backtest_remote_status`, fetch report with `backtest_remote_report` when status is completed
|
|
513
|
-
|
|
514
|
-
---
|
|
515
|
-
|
|
516
|
-
## Strategy Template Library
|
|
517
|
-
|
|
518
|
-
| Template | style | market | Entry Function |
|
|
519
|
-
| -------------------- | -------------- | ------ | -------------- |
|
|
520
|
-
| Simple DCA | dca | Crypto | compute() |
|
|
521
|
-
| Adaptive DCA | dca | Crypto | compute() |
|
|
522
|
-
| EMA Crossover | trend | Crypto | compute() |
|
|
523
|
-
| RSI Bounce | mean-reversion | Crypto | compute() |
|
|
524
|
-
| MACD Momentum | momentum | Crypto | compute() |
|
|
525
|
-
| Grid Trading | hybrid | Crypto | compute() |
|
|
526
|
-
| Multi-Asset Rotation | rotation | CN | select() |
|
|
527
|
-
| Multi-Factor | hybrid | Crypto | compute() |
|
|
258
|
+
- 本地验证通过后,可用 `skill_publish` 发布到 Hub
|
|
259
|
+
- 发布后用 `skill_publish_verify` 查询回测结果
|
|
528
260
|
|
|
529
261
|
---
|
|
530
262
|
|
|
531
|
-
##
|
|
532
|
-
|
|
533
|
-
| Market | Fee / Settlement | Lot / Limits | Special |
|
|
534
|
-
| ------------ | ---------------- | -------------- | ---------------------------------- |
|
|
535
|
-
| Crypto | ~0.1%, T+0 | 0.001+ | 24/7 |
|
|
536
|
-
| US Stock | ~0.1%, T+0 | 1 share | Pre/post hours |
|
|
537
|
-
| A-Share (CN) | ~0.154%, **T+1** | **100 shares** | **±10%/±20%**, stamp tax sell-only |
|
|
538
|
-
| HK | ~0.24%, T+0/T+2 | Variable | Lunch break |
|
|
263
|
+
## Strategy Templates
|
|
539
264
|
|
|
540
|
-
|
|
265
|
+
| Template | style | market |
|
|
266
|
+
| ------------- | -------------- | ------ |
|
|
267
|
+
| Simple DCA | dca | Crypto |
|
|
268
|
+
| EMA Crossover | trend | Crypto |
|
|
269
|
+
| RSI Bounce | mean-reversion | Crypto |
|
|
270
|
+
| Grid Trading | hybrid | Crypto |
|
|
541
271
|
|
|
542
272
|
---
|
|
543
273
|
|
|
544
274
|
## Response Guidelines
|
|
545
275
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
- End with clear next steps (backtest, paper, remote submit, or iterate).
|
|
552
|
-
|
|
553
|
-
## Risk Disclosures
|
|
554
|
-
|
|
555
|
-
> Generated strategies are based on historical patterns and user ideas. They require backtesting and paper trading before real capital. The builder produces code from rules and does not guarantee profitability. Validate with backtest and paper trading before going live.
|
|
276
|
+
1. Understand the user's idea; ask questions if vague
|
|
277
|
+
2. Present technical design and wait for confirmation
|
|
278
|
+
3. Show generated package structure
|
|
279
|
+
4. Run validation and report pass/fail
|
|
280
|
+
5. End with clear next steps (publish, iterate)
|