@openfinclaw/openfinclaw-strategy 2026.4.9 → 2026.4.11

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 CHANGED
@@ -14,7 +14,7 @@ openclaw plugins install @openfinclaw/openfinclaw-strategy
14
14
  ## 快速开始
15
15
 
16
16
  ```bash
17
- # 查看策略排行榜(无需 API Key)
17
+ # 查看策略排行榜
18
18
  openclaw strategy leaderboard
19
19
 
20
20
  # 查看收益榜 Top 10
@@ -45,24 +45,24 @@ openclaw strategy show <strategy-id> --remote
45
45
 
46
46
  ### 策略工具
47
47
 
48
- | 工具名 | 说明 | API Key |
49
- | ---------------------- | -------------------------- | -------- |
50
- | `skill_leaderboard` | 查询排行榜 | 不需要 |
51
- | `skill_get_info` | 获取 Hub 策略公开详情 | 不需要 |
52
- | `skill_validate` | 本地验证策略包(FEP v2.0) | 不需要 |
53
- | `skill_list_local` | 列出本地策略 | 不需要 |
54
- | `skill_fork` | 从 Hub 下载策略到本地 | **需要** |
55
- | `skill_publish` | 发布策略 ZIP 到 Hub | **需要** |
56
- | `skill_publish_verify` | 查询发布状态和回测报告 | **需要** |
48
+ | 工具名 | 说明 | API Key |
49
+ | ---------------------- | -------------------------- | ------- |
50
+ | `skill_leaderboard` | 查询排行榜 | 需要 |
51
+ | `skill_get_info` | 获取 Hub 策略公开详情 | 需要 |
52
+ | `skill_validate` | 本地验证策略包(FEP v2.0) | 需要 |
53
+ | `skill_list_local` | 列出本地策略 | 需要 |
54
+ | `skill_fork` | 从 Hub 下载策略到本地 | 需要 |
55
+ | `skill_publish` | 发布策略 ZIP 到 Hub | 需要 |
56
+ | `skill_publish_verify` | 查询发布状态和回测报告 | 需要 |
57
57
 
58
58
  ## CLI 命令
59
59
 
60
60
  ```bash
61
- # 查看排行榜(无需 API Key)
61
+ # 查看排行榜
62
62
  openclaw strategy leaderboard
63
63
  openclaw strategy leaderboard returns --limit 10
64
64
 
65
- # 从 Hub Fork 策略(需要 API Key)
65
+ # 从 Hub Fork 策略
66
66
  openclaw strategy fork <strategy-id>
67
67
 
68
68
  # 列出本地策略
package/SKILL.md CHANGED
@@ -54,13 +54,13 @@ Agent: 使用 fin_compare 对比收益
54
54
  ### 策略管理
55
55
 
56
56
  ```bash
57
- # 查看排行榜(无需 API Key)
57
+ # 查看排行榜
58
58
  openclaw strategy leaderboard
59
59
 
60
60
  # 查看收益榜 Top 10
61
61
  openclaw strategy leaderboard returns --limit 10
62
62
 
63
- # 查看策略详情(无需 API Key)
63
+ # 查看策略详情
64
64
  openclaw strategy show 550e8400-e29b-41d4-a716-446655440001 --remote
65
65
  ```
66
66
 
@@ -134,10 +134,10 @@ export OPENFINCLAW_API_KEY=YOUR_API_KEY
134
134
 
135
135
  | 工具名 | 用途 | 需要 API Key |
136
136
  | ---------------------- | -------------------------------------- | ------------ |
137
- | `skill_leaderboard` | 查询排行榜(综合/收益/风控/人气/新星) | |
138
- | `skill_get_info` | 获取 Hub 策略公开详情 | |
139
- | `skill_validate` | 本地验证策略包格式(FEP v2.0) | |
140
- | `skill_list_local` | 列出本地已下载的策略 | |
137
+ | `skill_leaderboard` | 查询排行榜(综合/收益/风控/人气/新星) | **是** |
138
+ | `skill_get_info` | 获取 Hub 策略公开详情 | **是** |
139
+ | `skill_validate` | 本地验证策略包格式(FEP v2.0) | **是** |
140
+ | `skill_list_local` | 列出本地已下载的策略 | **是** |
141
141
  | `skill_fork` | 从 Hub 下载公开策略到本地 | **是** |
142
142
  | `skill_publish` | 发布策略 ZIP 到 Hub,自动触发回测 | **是** |
143
143
  | `skill_publish_verify` | 查询发布状态和回测报告 | **是** |
@@ -172,7 +172,7 @@ export OPENFINCLAW_API_KEY=YOUR_API_KEY
172
172
 
173
173
  ### strategy leaderboard
174
174
 
175
- 查看 Hub 排行榜(无需 API Key):
175
+ 查看 Hub 排行榜:
176
176
 
177
177
  ```bash
178
178
  # 综合榜 Top 20(默认)
@@ -223,7 +223,7 @@ openclaw strategy list
223
223
  # 查看本地策略
224
224
  openclaw strategy show btc-adaptive-dca-34a5792f
225
225
 
226
- # 从 Hub 获取最新信息(无需 API Key)
226
+ # 从 Hub 获取最新信息
227
227
  openclaw strategy show 550e8400-e29b-41d4-a716-446655440001 --remote
228
228
  ```
229
229
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfinclaw/openfinclaw-strategy",
3
- "version": "2026.4.9",
3
+ "version": "2026.4.11",
4
4
  "description": "OpenFinClaw - Unified financial tools: market data (price/K-line/crypto/compare/search), strategy publishing, fork, and validation. Single API key for Hub and DataHub.",
5
5
  "keywords": [
6
6
  "backtest",
package/src/cli.ts CHANGED
@@ -50,7 +50,7 @@ export function registerStrategyCli(params: {
50
50
  // ── strategy leaderboard ──
51
51
  root
52
52
  .command("leaderboard [boardType]")
53
- .description("Query strategy leaderboard from Hub (no API key required)")
53
+ .description("Query strategy leaderboard from Hub")
54
54
  .option("-l, --limit <number>", "Number of results (max 100)", "20")
55
55
  .option("-o, --offset <number>", "Offset for pagination", "0")
56
56
  .action(
@@ -344,10 +344,18 @@ function printStrategyInfo(
344
344
  console.log("Hub:");
345
345
  console.log(` ID: ${hub.id}`);
346
346
  console.log(` 名称: ${hub.name}`);
347
- if (hub.version) console.log(` 版本: ${hub.version}`);
348
- if (hub.author?.displayName) console.log(` 作者: ${hub.author.displayName}`);
349
- if (hub.market) console.log(` 市场: ${hub.market}`);
350
- if (hub.description) console.log(` 描述: ${hub.description}`);
347
+ if (hub.version) {
348
+ console.log(` 版本: ${hub.version}`);
349
+ }
350
+ if (hub.author?.displayName) {
351
+ console.log(` 作者: ${hub.author.displayName}`);
352
+ }
353
+ if (hub.market) {
354
+ console.log(` 市场: ${hub.market}`);
355
+ }
356
+ if (hub.description) {
357
+ console.log(` 描述: ${hub.description}`);
358
+ }
351
359
 
352
360
  if (hub.backtestResult) {
353
361
  console.log("");
@@ -23,6 +23,9 @@ import type { AggregatedNewsProvider } from "./news-provider.js";
23
23
  import { formatPeriodicReportMarkdown } from "./periodic-report-builder.js";
24
24
  import { buildScanReport, formatScanReportMarkdown } from "./scan-report-builder.js";
25
25
 
26
+ const NO_API_KEY =
27
+ "API key not configured. Set apiKey in plugin config or OPENFINCLAW_API_KEY env var.";
28
+
26
29
  /** JSON tool result helper. */
27
30
  function json(payload: unknown) {
28
31
  return {
@@ -421,6 +424,7 @@ export function registerSchedulerTools(
421
424
  "strategy_scan_history",
422
425
  "scheduler",
423
426
  async (_toolCallId, params) => {
427
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
424
428
  try {
425
429
  const db = getDb();
426
430
  const entries = queryScanHistory(db, {
@@ -489,6 +493,7 @@ export function registerSchedulerTools(
489
493
  "strategy_periodic_report",
490
494
  "scheduler",
491
495
  async (_toolCallId, params) => {
496
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
492
497
  const period = params.period === "monthly" ? "monthly" : "weekly";
493
498
  const scanId = randomUUID();
494
499
  const now = new Date();
@@ -21,7 +21,9 @@ export async function hubApiRequest(
21
21
  }
22
22
 
23
23
  const headers: Record<string, string> = { "Content-Type": "application/json" };
24
- if (config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
24
+ if (config.apiKey) {
25
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
26
+ }
25
27
 
26
28
  const response = await fetch(url.toString(), {
27
29
  method,
@@ -346,6 +346,7 @@ export function registerStrategyTools(
346
346
  }),
347
347
  }),
348
348
  execute: withLogging(getDb, "skill_validate", "strategy", async (_toolCallId, params) => {
349
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
349
350
  try {
350
351
  const dirPath = String(params.dirPath ?? "").trim();
351
352
  if (!dirPath)
@@ -375,7 +376,7 @@ export function registerStrategyTools(
375
376
  {
376
377
  name: "skill_leaderboard",
377
378
  label: "Get Hub leaderboard",
378
- description: "Query strategy leaderboard from hub.openfinclaw.ai. No API key required.",
379
+ description: "Query strategy leaderboard from hub.openfinclaw.ai.",
379
380
  parameters: Type.Object({
380
381
  boardType: Type.Optional(
381
382
  Type.Unsafe<BoardType>({
@@ -390,6 +391,7 @@ export function registerStrategyTools(
390
391
  offset: Type.Optional(Type.Number({ description: "Offset for pagination" })),
391
392
  }),
392
393
  execute: withLogging(getDb, "skill_leaderboard", "strategy", async (_toolCallId, params) => {
394
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
393
395
  try {
394
396
  const boardType = (params.boardType as BoardType) || "composite";
395
397
  const limit = Math.min(Math.max(Number(params.limit) || 20, 1), 100);
@@ -401,7 +403,7 @@ export function registerStrategyTools(
401
403
 
402
404
  const response = await fetch(url.toString(), {
403
405
  method: "GET",
404
- headers: { Accept: "application/json" },
406
+ headers: { Accept: "application/json", Authorization: `Bearer ${config.apiKey}` },
405
407
  signal: AbortSignal.timeout(config.requestTimeoutMs),
406
408
  });
407
409
 
@@ -573,6 +575,7 @@ export function registerStrategyTools(
573
575
  description: "List all strategies downloaded or created locally, organized by date.",
574
576
  parameters: Type.Object({}),
575
577
  execute: withLogging(getDb, "skill_list_local", "strategy", async () => {
578
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
576
579
  try {
577
580
  const strategies = await listLocalStrategies();
578
581
 
@@ -622,7 +625,7 @@ export function registerStrategyTools(
622
625
  name: "skill_get_info",
623
626
  label: "Get strategy info from Hub",
624
627
  description:
625
- "Fetch detailed information about a strategy from hub.openfinclaw.ai. No API key required.",
628
+ "Fetch detailed information about a strategy from hub.openfinclaw.ai.",
626
629
  parameters: Type.Object({
627
630
  strategyId: Type.String({ description: "Strategy ID from Hub (UUID or Hub URL)" }),
628
631
  }),
@@ -631,6 +634,7 @@ export function registerStrategyTools(
631
634
  "skill_get_info",
632
635
  "strategy",
633
636
  async (_toolCallId, params) => {
637
+ if (!config.apiKey) return json({ success: false, error: NO_API_KEY });
634
638
  try {
635
639
  const strategyId = String(params.strategyId ?? "").trim();
636
640
  if (!strategyId) return json({ success: false, error: "strategyId is required" });