@openfinclaw/findoo-datahub-plugin 2026.3.10 → 2026.3.12

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/index.ts CHANGED
@@ -46,23 +46,28 @@ const findooDatahubPlugin = {
46
46
  // --- DataHub client ---
47
47
  if (!config.datahubApiKey) {
48
48
  api.log?.(
49
- "warn",
50
- "findoo-datahub-plugin: no API key configured. Set DATAHUB_API_KEY env var or plugins.findoo-datahub-plugin.datahubApiKey in config. Using built-in dev key.",
49
+ "error",
50
+ "findoo-datahub-plugin: API key is required. Set DATAHUB_API_KEY env var or configure in Control UI Plugins → Findoo DataHub.",
51
51
  );
52
52
  }
53
53
 
54
- const client = new DataHubClient(
55
- config.datahubApiUrl,
56
- config.datahubUsername,
57
- config.datahubApiKey ?? "98ffa5c5-1ec6-4735-8e0c-715a5eca1a8d",
58
- config.requestTimeoutMs,
59
- );
54
+ const client = config.datahubApiKey
55
+ ? new DataHubClient(
56
+ config.datahubApiUrl,
57
+ config.datahubUsername,
58
+ config.datahubApiKey,
59
+ config.requestTimeoutMs,
60
+ )
61
+ : null;
60
62
 
61
63
  // --- Local cache + regime detector ---
62
64
  const dbPath = api.resolvePath("state/findoo-ohlcv-cache.sqlite");
63
65
  const cache = new OHLCVCache(dbPath);
64
66
  const regimeDetector = new RegimeDetector();
65
67
 
68
+ const NO_KEY_ERROR =
69
+ "DataHub API key not configured. Set DATAHUB_API_KEY env var or configure in Control UI → Plugins → Findoo DataHub.";
70
+
66
71
  // --- Data provider service (exposed to other extensions) ---
67
72
  const dataProvider = {
68
73
  async getOHLCV(params: {
@@ -72,6 +77,8 @@ const findooDatahubPlugin = {
72
77
  since?: number;
73
78
  limit?: number;
74
79
  }) {
80
+ if (!client) throw new Error(NO_KEY_ERROR);
81
+
75
82
  // Check cache first
76
83
  const range = cache.getRange(params.symbol, params.market, params.timeframe);
77
84
  if (range && params.since != null && params.limit != null) {
@@ -92,6 +99,7 @@ const findooDatahubPlugin = {
92
99
  },
93
100
 
94
101
  async getTicker(symbol: string, market: MarketType) {
102
+ if (!client) throw new Error(NO_KEY_ERROR);
95
103
  return client.getTicker(symbol, market);
96
104
  },
97
105
 
@@ -233,6 +241,7 @@ const findooDatahubPlugin = {
233
241
  }),
234
242
  async execute(_toolCallId: string, params: Record<string, unknown>) {
235
243
  try {
244
+ if (!client) return json({ error: NO_KEY_ERROR });
236
245
  const endpoint = String(params.endpoint ?? "price/historical");
237
246
  const qp = buildParams(params);
238
247
  const results = await client.equity(endpoint, qp);
@@ -283,6 +292,7 @@ const findooDatahubPlugin = {
283
292
  }),
284
293
  async execute(_toolCallId: string, params: Record<string, unknown>) {
285
294
  try {
295
+ if (!client) return json({ error: NO_KEY_ERROR });
286
296
  const endpoint = String(params.endpoint ?? "price/historical");
287
297
  const qp = buildParams(params);
288
298
  const results = await client.index(endpoint, qp);
@@ -351,6 +361,7 @@ const findooDatahubPlugin = {
351
361
  }),
352
362
  async execute(_toolCallId: string, params: Record<string, unknown>) {
353
363
  try {
364
+ if (!client) return json({ error: NO_KEY_ERROR });
354
365
  const endpoint = String(params.endpoint ?? "cpi");
355
366
  const qp = buildParams(params);
356
367
  // Route currency/* and fixedincome/* endpoints to their categories
@@ -416,6 +427,7 @@ const findooDatahubPlugin = {
416
427
  }),
417
428
  async execute(_toolCallId: string, params: Record<string, unknown>) {
418
429
  try {
430
+ if (!client) return json({ error: NO_KEY_ERROR });
419
431
  const endpoint = String(params.endpoint ?? "futures/historical");
420
432
  const qp = buildParams(params);
421
433
  const results = await client.derivatives(endpoint, qp);
@@ -483,6 +495,7 @@ const findooDatahubPlugin = {
483
495
  }),
484
496
  async execute(_toolCallId: string, params: Record<string, unknown>) {
485
497
  try {
498
+ if (!client) return json({ error: NO_KEY_ERROR });
486
499
  const endpoint = String(params.endpoint ?? "coin/market");
487
500
  const qp = buildParams(params);
488
501
  // Endpoint-specific param mapping for crypto APIs
@@ -570,6 +583,7 @@ const findooDatahubPlugin = {
570
583
  }),
571
584
  async execute(_toolCallId: string, params: Record<string, unknown>) {
572
585
  try {
586
+ if (!client) return json({ error: NO_KEY_ERROR });
573
587
  const endpoint = String(params.endpoint ?? "market/top_list");
574
588
  const qp = buildParams(params);
575
589
  // Auto-alias: trade_date→date for endpoints that use 'date' param
@@ -618,6 +632,7 @@ const findooDatahubPlugin = {
618
632
  }),
619
633
  async execute(_toolCallId: string, params: Record<string, unknown>) {
620
634
  try {
635
+ if (!client) return json({ error: NO_KEY_ERROR });
621
636
  const path = String(params.path ?? "").trim();
622
637
  if (!path) throw new Error("path is required");
623
638
  const qp = (params.params ?? {}) as Record<string, string>;
@@ -766,6 +781,7 @@ const findooDatahubPlugin = {
766
781
  }),
767
782
  async execute(_toolCallId: string, params: Record<string, unknown>) {
768
783
  try {
784
+ if (!client) return json({ error: NO_KEY_ERROR });
769
785
  const indicator = String(params.indicator ?? "sma");
770
786
  const qp: Record<string, string> = {};
771
787
  if (params.symbol) qp.symbol = String(params.symbol);
@@ -830,6 +846,7 @@ const findooDatahubPlugin = {
830
846
  }),
831
847
  async execute(_toolCallId: string, params: Record<string, unknown>) {
832
848
  try {
849
+ if (!client) return json({ error: NO_KEY_ERROR });
833
850
  const endpoint = String(params.endpoint ?? "info");
834
851
  const qp = buildParams(params);
835
852
  const results = await client.etf(endpoint, qp);
@@ -871,6 +888,7 @@ const findooDatahubPlugin = {
871
888
  }),
872
889
  async execute(_toolCallId: string, params: Record<string, unknown>) {
873
890
  try {
891
+ if (!client) return json({ error: NO_KEY_ERROR });
874
892
  const endpoint = String(params.endpoint ?? "price/historical");
875
893
  const qp = buildParams(params);
876
894
  // Route news/* to the generic query path
@@ -902,7 +920,7 @@ const findooDatahubPlugin = {
902
920
  parameters: Type.Object({}),
903
921
  async execute() {
904
922
  return json({
905
- datahub: config.datahubApiUrl,
923
+ connected: !!client,
906
924
  markets: dataProvider.getSupportedMarkets(),
907
925
  categories: [
908
926
  "equity",
@@ -1,34 +1,27 @@
1
1
  {
2
2
  "id": "findoo-datahub-plugin",
3
3
  "name": "Findoo DataHub",
4
- "description": "Unified financial data source — 172 endpoints covering equity (A/HK/US), crypto, macro, derivatives, index, ETF via OpenBB DataHub. Works out of the box.",
4
+ "description": "Unified financial data source — 172 endpoints covering equity (A/HK/US), crypto, macro, derivatives, index, ETF. Works out of the box.",
5
5
  "kind": "financial",
6
6
  "version": "2026.3.2",
7
7
  "skills": ["./skills"],
8
8
  "configSchema": {
9
9
  "type": "object",
10
10
  "properties": {
11
- "datahubApiUrl": {
12
- "type": "string",
13
- "default": "http://43.134.61.136:8088",
14
- "description": "DataHub REST API base URL. Change only for self-hosted OpenBB instances"
15
- },
16
- "datahubUsername": {
17
- "type": "string",
18
- "default": "admin",
19
- "description": "DataHub HTTP Basic Auth username"
20
- },
21
11
  "datahubApiKey": {
22
12
  "type": "string",
23
- "description": "DataHub API key (required). Set via config or DATAHUB_API_KEY env var.",
13
+ "minLength": 1,
14
+ "description": "DataHub API key (required). Also accepted via DATAHUB_API_KEY env var.",
24
15
  "sensitive": true
25
- },
26
- "requestTimeoutMs": {
27
- "type": "number",
28
- "default": 30000,
29
- "minimum": 1000,
30
- "maximum": 120000
31
16
  }
32
17
  }
18
+ },
19
+ "uiHints": {
20
+ "datahubApiKey": {
21
+ "label": "API Key",
22
+ "help": "DataHub API 密钥(必填)。",
23
+ "sensitive": true,
24
+ "placeholder": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
25
+ }
33
26
  }
34
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfinclaw/findoo-datahub-plugin",
3
- "version": "2026.3.10",
3
+ "version": "2026.3.12",
4
4
  "description": "Unified financial data source — free mode (CCXT/CoinGecko/DefiLlama/Yahoo) + full mode (172 DataHub endpoints)",
5
5
  "keywords": [
6
6
  "crypto",
@@ -101,10 +101,10 @@ fin_derivatives(futures/holding) → 主力持仓方向
101
101
  - US: `fin_derivatives(endpoint="options/chains", symbol="SPY")` → 直接取返回的 IV 字段 → 与 VIX 历史对比
102
102
  - ⚠️ A 股标的有限 (50ETF/300ETF/科创50ETF 等),个股期权几乎不存在
103
103
 
104
- | IV 分位 | 看涨 | 看跌 | 无方向 |
105
- | ----------- | -------------------------- | -------------------------- | ----------------------- |
106
- | < 30th (低) | 买 Call / Bull Call Spread | 买 Put / Bear Put Spread | Long Straddle/Strangle |
107
- | 30-70th | Bull Call Spread | Bear Put Spread | Iron Condor |
104
+ | IV 分位 | 看涨 | 看跌 | 无方向 |
105
+ | ----------- | -------------------------- | -------------------------- | ------------------------------------- |
106
+ | < 30th (低) | 买 Call / Bull Call Spread | 买 Put / Bear Put Spread | Long Straddle/Strangle |
107
+ | 30-70th | Bull Call Spread | Bear Put Spread | Iron Condor |
108
108
  | > 70th (高) | 卖 Put / Bull Put Spread | 卖 Call / Bear Call Spread | Short Straddle/Strangle ⚠️ 必须设止损 |
109
109
 
110
110
  ### 常用策略参数
@@ -112,20 +112,20 @@ Credit_stress = 0.4*shibor_score + 0.3*curve_score + 0.3*margin_score
112
112
 
113
113
  ## 风险传导链模型
114
114
 
115
- | 路径 | 链路 | 频率 | 升级触发 |
116
- |------|------|------|---------|
117
- | **A 外部冲击** | 美债↑(`treasury_us`) → CNH贬(`USDCNH`) → 北向流出(`hsgt_flow`) → 大宗联动(AU/SC) → A股承压 | 日频 | 10Y日变>10bp |
118
- | **B 去杠杆** | 监管收紧 → 融资降(`margin/summary`) → 杠杆平仓(`margin/trading`) → 质押风险(`pledge/stat`) → 连锁跌停 | 周频 | 融资连降3日 |
119
- | **C 流动性危机** | Shibor飙升(`shibor`) → 债券抛售(`treasury_cn`) → 利差异常 → 股债双杀 | 日频 | O/N>3% |
115
+ | 路径 | 链路 | 频率 | 升级触发 |
116
+ | ---------------- | ----------------------------------------------------------------------------------------------------- | ---- | ------------ |
117
+ | **A 外部冲击** | 美债↑(`treasury_us`) → CNH贬(`USDCNH`) → 北向流出(`hsgt_flow`) → 大宗联动(AU/SC) → A股承压 | 日频 | 10Y日变>10bp |
118
+ | **B 去杠杆** | 监管收紧 → 融资降(`margin/summary`) → 杠杆平仓(`margin/trading`) → 质押风险(`pledge/stat`) → 连锁跌停 | 周频 | 融资连降3日 |
119
+ | **C 流动性危机** | Shibor飙升(`shibor`) → 债券抛售(`treasury_cn`) → 利差异常 → 股债双杀 | 日频 | O/N>3% |
120
120
 
121
121
  ## 风险情景预案
122
122
 
123
- | 情景 | 触发条件 | 行动 |
124
- |------|---------|------|
125
- | **A 美联储冲击** | 10Y 5日升>25bp + USDCNH周升>0.8% + 北向3日出>150亿 | 减成长至30%,增配高股息,IF空头对冲 |
126
- | **B 信用事件** | 融资10日降>8% + O/N>3.5% + 银行地产跌停>15 | 清仓金融地产,仓位<30%,增配国债ETF(511010.SH) |
127
- | **C 地缘冲突** | AU日涨>2% + SC日涨>5% + USDCNH 3日升>1% | 仓位30%,加配黄金/现金/短期国债 |
128
- | **D 钱荒** | O/N>5% + 大面积强平 + 跌停>200 + 10Y-1Y<10bp | 全清仓转现金。恢复: O/N<2.5% + 跌停<50 |
123
+ | 情景 | 触发条件 | 行动 |
124
+ | ---------------- | -------------------------------------------------- | ---------------------------------------------- |
125
+ | **A 美联储冲击** | 10Y 5日升>25bp + USDCNH周升>0.8% + 北向3日出>150亿 | 减成长至30%,增配高股息,IF空头对冲 |
126
+ | **B 信用事件** | 融资10日降>8% + O/N>3.5% + 银行地产跌停>15 | 清仓金融地产,仓位<30%,增配国债ETF(511010.SH) |
127
+ | **C 地缘冲突** | AU日涨>2% + SC日涨>5% + USDCNH 3日升>1% | 仓位30%,加配黄金/现金/短期国债 |
128
+ | **D 钱荒** | O/N>5% + 大面积强平 + 跌停>200 + 10Y-1Y<10bp | 全清仓转现金。恢复: O/N<2.5% + 跌停<50 |
129
129
 
130
130
  ## 尾部风险预警 (Perfect Storm)
131
131