@dshtrading/client-ui-indicators 0.6.1 → 0.6.2
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/lib/client.js +426 -72
- package/lib/client.js.map +1 -1
- package/package.json +2 -3
package/lib/client.js
CHANGED
|
@@ -4,77 +4,51 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
//#region ../indicators/lib/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
sanitizeInstances(instances) {
|
|
53
|
-
if (!Array.isArray(instances)) return [];
|
|
54
|
-
const seen = /* @__PURE__ */ new Set();
|
|
55
|
-
const out = [];
|
|
56
|
-
for (const raw of instances) {
|
|
57
|
-
if (typeof raw !== "object" || raw === null) continue;
|
|
58
|
-
const { id, params } = raw;
|
|
59
|
-
if (typeof id !== "string" || seen.has(id)) continue;
|
|
60
|
-
const definition = registry.get(id);
|
|
61
|
-
if (definition === void 0) continue;
|
|
62
|
-
seen.add(id);
|
|
63
|
-
out.push({
|
|
64
|
-
id,
|
|
65
|
-
params: this.clampParams(definition, typeof params === "object" && params !== null ? params : {})
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return out;
|
|
69
|
-
},
|
|
70
|
-
subscribe(listener) {
|
|
71
|
-
listeners.add(listener);
|
|
72
|
-
return () => {
|
|
73
|
-
listeners.delete(listener);
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
getVersion: () => version
|
|
77
|
-
};
|
|
7
|
+
//#region ../indicators/lib/aux-series.js
|
|
8
|
+
/**
|
|
9
|
+
* 逐根序列的值不变量(宿主注入方的契约,消费方按此写纯函数):
|
|
10
|
+
* - 值数组长度**严格等于** bars.length(逐根对齐,不做前向填充、不做区间匹配);
|
|
11
|
+
* - `undefined` = 该根无值(指标据此留空,不是 0);
|
|
12
|
+
* - 数组元素只可能是有限数或 undefined,绝不出现 NaN/Infinity。
|
|
13
|
+
*/
|
|
14
|
+
/** 五日成交量档位通道键(冻结字面量)。 */
|
|
15
|
+
const FIVE_DAY_VOLUME_TIER_AUX_KEY = "five-day-volume-tiers";
|
|
16
|
+
/**
|
|
17
|
+
* 把日频外部序列对齐到 K 线序列:对每根 K 线取「date ≤ 该 K 线所属交易日」的
|
|
18
|
+
* 最新一条外部值(前向填充,反映「该交易日收盘时已知的最新持股比例」)。
|
|
19
|
+
* 早于首条外部数据的 K 线填 undefined。返回数组长度严格等于 bars.length。
|
|
20
|
+
* dayOfKline: 由宿主传入的「K 线 → 交易日(UTC 00:00)」取值函数,避免本纯库
|
|
21
|
+
* 依赖行情周期词汇。
|
|
22
|
+
*
|
|
23
|
+
* 前向填充的理由:港股通持股日频公布,K 线级别 ≥ 1d 时一个交易日一个点;但周 K/
|
|
24
|
+
* 月 K 上一个 bar 覆盖多日,必须取区间内最新已知值,否则会用到未来数据。
|
|
25
|
+
*
|
|
26
|
+
* 每根 K 线独立二分取值:只依赖 points 升序(契约要求),不假设 bars 升序——
|
|
27
|
+
* 宿主倒序传入或周期混排时每根 K 线拿到的仍是同一条值。
|
|
28
|
+
*/
|
|
29
|
+
function alignAuxToBars(bars, points, dayOfKline) {
|
|
30
|
+
const aligned = new Array(bars.length);
|
|
31
|
+
for (let index = 0; index < bars.length; index += 1) {
|
|
32
|
+
const bar = bars[index];
|
|
33
|
+
aligned[index] = bar === void 0 ? void 0 : valueAtOrBefore(points, dayOfKline(bar));
|
|
34
|
+
}
|
|
35
|
+
return aligned;
|
|
36
|
+
}
|
|
37
|
+
/** 升序序列里 date ≤ day 的最后一条值;无命中(早于首条数据 / 空序列)返回 undefined。 */
|
|
38
|
+
function valueAtOrBefore(points, day) {
|
|
39
|
+
let low = 0;
|
|
40
|
+
let high = points.length - 1;
|
|
41
|
+
let hit = -1;
|
|
42
|
+
while (low <= high) {
|
|
43
|
+
const mid = low + high >> 1;
|
|
44
|
+
const point = points[mid];
|
|
45
|
+
if (point === void 0) break;
|
|
46
|
+
if (point.date <= day) {
|
|
47
|
+
hit = mid;
|
|
48
|
+
low = mid + 1;
|
|
49
|
+
} else high = mid - 1;
|
|
50
|
+
}
|
|
51
|
+
return hit < 0 ? void 0 : points[hit]?.value;
|
|
78
52
|
}
|
|
79
53
|
//#endregion
|
|
80
54
|
//#region ../indicators/lib/math.js
|
|
@@ -281,7 +255,152 @@ window.__ModuleLoader__.load({
|
|
|
281
255
|
return EMA_COLORS[`EMA${period}`] ?? FALLBACK_PALETTE[index % FALLBACK_PALETTE.length] ?? "#8a8f99";
|
|
282
256
|
}
|
|
283
257
|
const closesOf = (bars) => bars.map((bar) => bar.close);
|
|
284
|
-
/**
|
|
258
|
+
/** 港股通持股比例副图消费的外部序列键(宿主按此键 prefetch 并按同名键注入)。 */
|
|
259
|
+
const HK_CONNECT_HOLDING_AUX_KEY = "hk-connect-holding";
|
|
260
|
+
/** 主动买盘副图消费的外部序列键(与桥端点同名,宿主按此键 prefetch 并注入)。 */
|
|
261
|
+
const ACTIVE_BUY_AUX_KEY = "cn-active-buy";
|
|
262
|
+
/** 一天的毫秒数(K 线交易日归一到 UTC 00:00 用)。 */
|
|
263
|
+
const MS_PER_DAY = 864e5;
|
|
264
|
+
/**
|
|
265
|
+
* K 线 → 交易日(UTC 00:00),供日频外部序列对齐。日线及更细周期取 openTime
|
|
266
|
+
* 当日(本仓日频 openTime 即 UTC 00:00,与外部序列一字对齐):这时不用 closeTime,
|
|
267
|
+
* 它是当日 23:59:59.999,一旦 openTime 带盘中偏移(如 09:30)向下取整就会进位到
|
|
268
|
+
* 次日、吃到未来一天的值。周 K/月 K 则取 closeTime 当日——周期末,从而对齐到区间内
|
|
269
|
+
* 最新已知值,而不是周期起点的旧值。
|
|
270
|
+
*/
|
|
271
|
+
function klineTradingDay(bar) {
|
|
272
|
+
const closeTime = bar.closeTime;
|
|
273
|
+
const periodEnd = typeof closeTime === "number" && Number.isFinite(closeTime) ? closeTime : bar.openTime;
|
|
274
|
+
const tradingDay = periodEnd - bar.openTime >= 2 * MS_PER_DAY ? periodEnd : bar.openTime;
|
|
275
|
+
return Math.floor(tradingDay / MS_PER_DAY) * MS_PER_DAY;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* K 线覆盖的 UTC 日区间 [首日 00:00, 末日 00:00](含首尾)。日线开收盘同日 ⇒ 单日
|
|
279
|
+
* 区间(等价于精确当日匹配);周 K/月 K 跨多日 ⇒ 多日区间。closeTime 非有限或早于
|
|
280
|
+
* openTime(脏数据)时退化为 openTime 当日。
|
|
281
|
+
*/
|
|
282
|
+
function klineCoverageRange(bar) {
|
|
283
|
+
const start = Math.floor(bar.openTime / MS_PER_DAY) * MS_PER_DAY;
|
|
284
|
+
const closeTime = bar.closeTime;
|
|
285
|
+
const closeDay = typeof closeTime === "number" && Number.isFinite(closeTime) ? Math.floor(closeTime / MS_PER_DAY) * MS_PER_DAY : start;
|
|
286
|
+
return closeDay > start ? [start, closeDay] : [start, start];
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* 把日频外部序列对齐到 K 线:每根只取**落在该 K 线覆盖区间内**的最新一条值,区间内
|
|
290
|
+
* 无点 ⇒ undefined,绝不沿用区间之前的点(无前向填充)。返回数组长度严格等于
|
|
291
|
+
* bars.length。只依赖 points 升序(契约要求)且每根 K 线独立二分,不假设 bars 升序。
|
|
292
|
+
*/
|
|
293
|
+
function alignAuxToBarCoverage(bars, points) {
|
|
294
|
+
const aligned = new Array(bars.length);
|
|
295
|
+
for (let index = 0; index < bars.length; index += 1) {
|
|
296
|
+
const bar = bars[index];
|
|
297
|
+
if (bar === void 0) {
|
|
298
|
+
aligned[index] = void 0;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
const [start, end] = klineCoverageRange(bar);
|
|
302
|
+
aligned[index] = valueWithinRange(points, start, end);
|
|
303
|
+
}
|
|
304
|
+
return aligned;
|
|
305
|
+
}
|
|
306
|
+
/** 升序序列里 date ∈ [start, end] 的最后一条值;区间内无点(或序列为空)返回 undefined。 */
|
|
307
|
+
function valueWithinRange(points, start, end) {
|
|
308
|
+
let low = 0;
|
|
309
|
+
let high = points.length - 1;
|
|
310
|
+
let hit = -1;
|
|
311
|
+
while (low <= high) {
|
|
312
|
+
const mid = low + high >> 1;
|
|
313
|
+
const point = points[mid];
|
|
314
|
+
if (point === void 0) break;
|
|
315
|
+
if (point.date <= end) {
|
|
316
|
+
hit = mid;
|
|
317
|
+
low = mid + 1;
|
|
318
|
+
} else high = mid - 1;
|
|
319
|
+
}
|
|
320
|
+
const point = hit < 0 ? void 0 : points[hit];
|
|
321
|
+
return point !== void 0 && point.date >= start ? point.value : void 0;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 档位色(亮/暗):镜像 `packages/client-ui-trading/src/client/five-day-series.ts`
|
|
325
|
+
* 的 TIER_COLORS_LIGHT / TIER_COLORS_DARK——「行情·5日」成交量档位色是这组色值的
|
|
326
|
+
* 唯一事实来源,本表是逐档同值的副本(本包不能反向依赖 UI 包),改色必须两处同步。
|
|
327
|
+
*/
|
|
328
|
+
const VOLUME_TIER_THEME_COLORS = {
|
|
329
|
+
无前值: {
|
|
330
|
+
light: "#a8adb8",
|
|
331
|
+
dark: "#6b7280"
|
|
332
|
+
},
|
|
333
|
+
"量比<1": {
|
|
334
|
+
light: "#d9a01f",
|
|
335
|
+
dark: "#e8c552"
|
|
336
|
+
},
|
|
337
|
+
"量比1-2": {
|
|
338
|
+
light: "#ee7f72",
|
|
339
|
+
dark: "#f0958b"
|
|
340
|
+
},
|
|
341
|
+
"量比2-3": {
|
|
342
|
+
light: "#c62828",
|
|
343
|
+
dark: "#e5484d"
|
|
344
|
+
},
|
|
345
|
+
"量比≥3": {
|
|
346
|
+
light: "#1c1c1e",
|
|
347
|
+
dark: "#f2f4f8"
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
/** 档位顺序 = 输出顺序 = 图例顺序(灰档在前,其后按量比递增)。 */
|
|
351
|
+
const VOLUME_TIERS = [
|
|
352
|
+
"无前值",
|
|
353
|
+
"量比<1",
|
|
354
|
+
"量比1-2",
|
|
355
|
+
"量比2-3",
|
|
356
|
+
"量比≥3"
|
|
357
|
+
];
|
|
358
|
+
/** 量比分档量能的前值窗口默认周期(params schema 与 compute 的缺参兜底共用一处)。 */
|
|
359
|
+
const VOLUME_TIER_DEFAULT_PERIOD = 4;
|
|
360
|
+
/**
|
|
361
|
+
* 量比 → 档位:阈值 1/2/3 分四档(比值恰好等于阈值时落**较高**一档,与五日图例
|
|
362
|
+
* 「1 ≤ 量比 < 2」的区间语义一致);undefined(无前值 / 不可判)落中性灰档。
|
|
363
|
+
* `Number.POSITIVE_INFINITY`(前值无量但本周期有量)落最高档。
|
|
364
|
+
*/
|
|
365
|
+
function volumeTierOf(ratio) {
|
|
366
|
+
if (ratio === void 0) return "无前值";
|
|
367
|
+
if (ratio < 1) return "量比<1";
|
|
368
|
+
if (ratio < 2) return "量比1-2";
|
|
369
|
+
if (ratio < 3) return "量比2-3";
|
|
370
|
+
return "量比≥3";
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* 量比序列:本周期量 ÷ 前 N 个周期量均值(不含本周期,等价 REF(MA(volume, N), 1))。
|
|
374
|
+
* 长度严格等于 bars.length。判定顺序(前值无量那两条与「行情·5日」现行分支同口径,
|
|
375
|
+
* 见 `packages/client-ui-trading/src/client/five-day-series.ts:220-225`):
|
|
376
|
+
* 1. 本周期量非有限(脏数据)→ undefined(灰);
|
|
377
|
+
* 2. 前值窗口不可用(前 N 根之内)或均值非有限(窗口含脏值)→ undefined(灰);
|
|
378
|
+
* 3. 前值均值 ≤ 0 且本周期有量 → `Number.POSITIVE_INFINITY`(比值发散,按最高档处理);
|
|
379
|
+
* 4. 前值均值 ≤ 0 且本周期量为 0 → undefined(比值无定义,灰);
|
|
380
|
+
* 5. 其余 → 本周期量 ÷ 前值均值(溢出的极端值照样发散,落最高档)。
|
|
381
|
+
*/
|
|
382
|
+
function volumeRatios(bars, period) {
|
|
383
|
+
const volumes = bars.map((bar) => bar.volume);
|
|
384
|
+
const priorMeans = sma(volumes, period);
|
|
385
|
+
return bars.map((_bar, index) => {
|
|
386
|
+
const volume = volumes[index];
|
|
387
|
+
if (volume === void 0 || !Number.isFinite(volume)) return void 0;
|
|
388
|
+
const mean = index >= 1 ? priorMeans[index - 1] : void 0;
|
|
389
|
+
if (mean === void 0 || !Number.isFinite(mean)) return void 0;
|
|
390
|
+
if (mean <= 0) return volume > 0 ? Number.POSITIVE_INFINITY : void 0;
|
|
391
|
+
return volume / mean;
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* 成交量柱的两条语义色(红涨绿跌缺省档 red-up 的 up/down,不透明度 0.55):
|
|
396
|
+
* 镜像 `packages/client-ui-trading/src/client/color-mode.ts` 的
|
|
397
|
+
* `PALETTES['red-up'].upAlpha(0.55)` / `downAlpha(0.55)`(本包不能反向依赖 UI 包)。
|
|
398
|
+
* 成交量柱有意的口径:只按涨跌语义配色,**不读**红涨绿跌设置——与五日档位色同款,
|
|
399
|
+
* 换绿涨红跌不会把成交量柱的涨跌语义翻过来。
|
|
400
|
+
*/
|
|
401
|
+
const VOLUME_UP_COLOR = "rgba(230, 69, 69, 0.55)";
|
|
402
|
+
const VOLUME_DOWN_COLOR = "rgba(43, 164, 113, 0.55)";
|
|
403
|
+
/** 十个预置 definition(纯数据,注册时机归消费方)。 */
|
|
285
404
|
function presetDefinitions() {
|
|
286
405
|
return [
|
|
287
406
|
{
|
|
@@ -561,10 +680,245 @@ window.__ModuleLoader__.load({
|
|
|
561
680
|
}
|
|
562
681
|
];
|
|
563
682
|
}
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
id: "vol",
|
|
686
|
+
pane: "sub",
|
|
687
|
+
title: "成交量",
|
|
688
|
+
params: [],
|
|
689
|
+
description: "柱高是本周期成交量;上涨(收盘 ≥ 开盘,等号归上涨)用红色、下跌用绿色,与 K 线方向判据同口径。颜色是固定的涨跌语义色,不随红涨绿跌配色设置翻转。当前级别能取到五日同分钟档位序列时(五日级别),柱色改用档位色(「行情·5日」的五档口径,见量比分档量能);取不到时回落涨跌色照常出柱。全市场、全 K 线级别通用。",
|
|
690
|
+
defaultActive: true,
|
|
691
|
+
barAux: [FIVE_DAY_VOLUME_TIER_AUX_KEY],
|
|
692
|
+
compute(bars) {
|
|
693
|
+
return [{
|
|
694
|
+
key: "上涨量",
|
|
695
|
+
kind: "histogram",
|
|
696
|
+
color: VOLUME_UP_COLOR,
|
|
697
|
+
values: bars.map((bar) => Number.isFinite(bar.volume) && bar.close >= bar.open ? bar.volume : void 0),
|
|
698
|
+
priceFormat: "volume"
|
|
699
|
+
}, {
|
|
700
|
+
key: "下跌量",
|
|
701
|
+
kind: "histogram",
|
|
702
|
+
color: VOLUME_DOWN_COLOR,
|
|
703
|
+
values: bars.map((bar) => Number.isFinite(bar.volume) && bar.close < bar.open ? bar.volume : void 0),
|
|
704
|
+
priceFormat: "volume"
|
|
705
|
+
}];
|
|
706
|
+
},
|
|
707
|
+
computeBarAux(bars, _params, barAux) {
|
|
708
|
+
const tiers = barAux[FIVE_DAY_VOLUME_TIER_AUX_KEY];
|
|
709
|
+
return VOLUME_TIERS.map((tier, tierIndex) => ({
|
|
710
|
+
key: tier,
|
|
711
|
+
kind: "histogram",
|
|
712
|
+
color: VOLUME_TIER_THEME_COLORS[tier].light,
|
|
713
|
+
themeColor: VOLUME_TIER_THEME_COLORS[tier],
|
|
714
|
+
values: bars.map((bar, index) => tiers?.[index] === tierIndex && Number.isFinite(bar.volume) ? bar.volume : void 0),
|
|
715
|
+
priceFormat: "volume"
|
|
716
|
+
}));
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
id: "vol-tier",
|
|
721
|
+
pane: "sub",
|
|
722
|
+
title: "量比分档量能",
|
|
723
|
+
params: [{
|
|
724
|
+
key: "n",
|
|
725
|
+
label: "周期",
|
|
726
|
+
default: VOLUME_TIER_DEFAULT_PERIOD,
|
|
727
|
+
min: 2,
|
|
728
|
+
max: 250
|
|
729
|
+
}],
|
|
730
|
+
description: "成交量按量比分档着色:量比 = 本周期成交量 ÷ 前 N 个周期成交量均值(不含本周期,等价 REF(MA(volume, N), 1)),阈值 1 / 2 / 3 分四档(量比 < 1、1 ≤ 量比 < 2、2 ≤ 量比 < 3、量比 ≥ 3)。前值窗口不可用(前 N 个周期之内,或前值含脏数据)走中性灰档;前值无量(前值均值为 0)时,本周期也无量走中性灰档,本周期有量则比值发散、按最高档处理(与「行情·5日」同口径)。柱高是本周期成交量,档位只决定颜色;全市场、全 K 线级别通用。着色读的是量比而不是涨跌,因此不受红涨绿跌配色设置影响。",
|
|
731
|
+
defaultActive: true,
|
|
732
|
+
compute(bars, params) {
|
|
733
|
+
const ratios = volumeRatios(bars, Math.round(params.n ?? VOLUME_TIER_DEFAULT_PERIOD));
|
|
734
|
+
return VOLUME_TIERS.map((tier) => ({
|
|
735
|
+
key: tier,
|
|
736
|
+
kind: "histogram",
|
|
737
|
+
color: VOLUME_TIER_THEME_COLORS[tier].light,
|
|
738
|
+
themeColor: VOLUME_TIER_THEME_COLORS[tier],
|
|
739
|
+
values: bars.map((bar, index) => volumeTierOf(ratios[index]) === tier && Number.isFinite(bar.volume) ? bar.volume : void 0)
|
|
740
|
+
}));
|
|
741
|
+
}
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
id: "hk-connect-holding",
|
|
745
|
+
pane: "sub",
|
|
746
|
+
title: "港股通持股比例",
|
|
747
|
+
params: [],
|
|
748
|
+
markets: ["hk"],
|
|
749
|
+
defaultApplyScope: { hk: {
|
|
750
|
+
enabled: true,
|
|
751
|
+
intervals: [
|
|
752
|
+
"1d",
|
|
753
|
+
"1w",
|
|
754
|
+
"1M"
|
|
755
|
+
]
|
|
756
|
+
} },
|
|
757
|
+
aux: [HK_CONNECT_HOLDING_AUX_KEY],
|
|
758
|
+
compute() {
|
|
759
|
+
return [];
|
|
760
|
+
},
|
|
761
|
+
computeAux(bars, _params, aux) {
|
|
762
|
+
const points = aux[HK_CONNECT_HOLDING_AUX_KEY];
|
|
763
|
+
if (points === void 0 || points.length === 0) return [];
|
|
764
|
+
return [{
|
|
765
|
+
key: "HK_CONNECT_HOLDING",
|
|
766
|
+
kind: "line",
|
|
767
|
+
color: "#7c5cff",
|
|
768
|
+
values: alignAuxToBars(bars, points, klineTradingDay).map((value) => typeof value === "number" && Number.isFinite(value) ? value : void 0),
|
|
769
|
+
precision: 2
|
|
770
|
+
}];
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
id: "active-buy",
|
|
775
|
+
pane: "sub",
|
|
776
|
+
title: "主动买盘",
|
|
777
|
+
params: [],
|
|
778
|
+
markets: ["cn"],
|
|
779
|
+
description: "数据源:本地累积的腾讯盘口快照推断的内外盘(非交易所官方逐笔方向,涨跌停/对倒日失真)。红柱为净主动买占当日总量百分比,蓝线为主动买占比 ((100 + 净买占比) / 2,前提是外盘 + 内盘 ≈ 当日总量,两者的差值是未归向成交、量级不固定)。当日柱为盘中累计到最新取数时刻,收盘后收敛为当日终值;某交易日没有采集到读数就是空的,不插值、不沿用前一交易日。",
|
|
780
|
+
defaultApplyScope: { cn: {
|
|
781
|
+
enabled: true,
|
|
782
|
+
intervals: [
|
|
783
|
+
"1d",
|
|
784
|
+
"1w",
|
|
785
|
+
"1M"
|
|
786
|
+
]
|
|
787
|
+
} },
|
|
788
|
+
aux: [ACTIVE_BUY_AUX_KEY],
|
|
789
|
+
compute() {
|
|
790
|
+
return [];
|
|
791
|
+
},
|
|
792
|
+
computeAux(bars, _params, aux) {
|
|
793
|
+
const points = aux[ACTIVE_BUY_AUX_KEY];
|
|
794
|
+
if (points === void 0 || points.length === 0) return [];
|
|
795
|
+
const net = alignAuxToBarCoverage(bars, points).map((value) => typeof value === "number" && Number.isFinite(value) ? value : void 0);
|
|
796
|
+
return [{
|
|
797
|
+
key: "净买",
|
|
798
|
+
kind: "histogram",
|
|
799
|
+
histogramBySign: true,
|
|
800
|
+
color: "#e64545",
|
|
801
|
+
values: net,
|
|
802
|
+
precision: 2
|
|
803
|
+
}, {
|
|
804
|
+
key: "买占",
|
|
805
|
+
kind: "line",
|
|
806
|
+
color: "#3b82f6",
|
|
807
|
+
values: net.map((value) => value === void 0 ? void 0 : (100 + value) / 2),
|
|
808
|
+
precision: 2
|
|
809
|
+
}];
|
|
810
|
+
}
|
|
564
811
|
}
|
|
565
812
|
];
|
|
566
813
|
}
|
|
567
814
|
//#endregion
|
|
815
|
+
//#region ../indicators/lib/chart-activations.js
|
|
816
|
+
/**
|
|
817
|
+
* 参数按 schema clamp 的**单一实现**(registry.clampParams 与 clampActivationParams 共用):
|
|
818
|
+
* 有限数字 → min/max 收敛 + 取整;缺失/非法 → schema 默认值;schema 外的键丢弃。
|
|
819
|
+
*/
|
|
820
|
+
function clampParamsBySpecs(specs, params) {
|
|
821
|
+
const out = {};
|
|
822
|
+
for (const spec of specs) {
|
|
823
|
+
const raw = params[spec.key];
|
|
824
|
+
out[spec.key] = typeof raw === "number" && Number.isFinite(raw) ? Math.min(spec.max, Math.max(spec.min, Math.round(raw))) : spec.default;
|
|
825
|
+
}
|
|
826
|
+
return out;
|
|
827
|
+
}
|
|
828
|
+
/** 定义侧默认适用范围的脱引用深拷贝(definition 是模块级常量,实例不得与之共享)。 */
|
|
829
|
+
function cloneApplyScope(scope) {
|
|
830
|
+
const out = {};
|
|
831
|
+
for (const [market, scene] of Object.entries(scope)) out[market] = {
|
|
832
|
+
enabled: scene.enabled,
|
|
833
|
+
intervals: [...scene.intervals]
|
|
834
|
+
};
|
|
835
|
+
return out;
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* 按 schema 生成默认参数实例(definition 缺席 → 空 params,UI 不可见兜底)。
|
|
839
|
+
* 这是「造新实例」的唯一入口:definition 声明了 defaultApplyScope 时随实例落地
|
|
840
|
+
* (决策 7 的默认适用范围由此进入三条创建路径),未声明的指标不长出 applyScope
|
|
841
|
+
* ——存量指标的新实例仍是「全部市场、全部级别应用」,零迁移。
|
|
842
|
+
*/
|
|
843
|
+
function defaultActivationInstance(spec) {
|
|
844
|
+
const params = {};
|
|
845
|
+
for (const p of spec.params) params[p.key] = p.default;
|
|
846
|
+
const instance = {
|
|
847
|
+
id: spec.id,
|
|
848
|
+
params
|
|
849
|
+
};
|
|
850
|
+
if (spec.defaultApplyScope === void 0) return instance;
|
|
851
|
+
return {
|
|
852
|
+
...instance,
|
|
853
|
+
applyScope: cloneApplyScope(spec.defaultApplyScope)
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
//#endregion
|
|
857
|
+
//#region ../indicators/lib/registry.js
|
|
858
|
+
function createIndicatorRegistry() {
|
|
859
|
+
const registry = /* @__PURE__ */ new Map();
|
|
860
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
861
|
+
let version = 0;
|
|
862
|
+
const register = (definition) => {
|
|
863
|
+
registry.set(definition.id, definition);
|
|
864
|
+
version += 1;
|
|
865
|
+
for (const listener of listeners) listener();
|
|
866
|
+
};
|
|
867
|
+
const definitionParams = (id) => registry.get(id)?.params ?? [];
|
|
868
|
+
return {
|
|
869
|
+
register,
|
|
870
|
+
unregister(id) {
|
|
871
|
+
if (!registry.delete(id)) return;
|
|
872
|
+
version += 1;
|
|
873
|
+
for (const listener of listeners) listener();
|
|
874
|
+
},
|
|
875
|
+
get: (id) => registry.get(id),
|
|
876
|
+
list: () => [...registry.values()],
|
|
877
|
+
defaultParams(definition) {
|
|
878
|
+
const params = {};
|
|
879
|
+
for (const spec of definition.params) params[spec.key] = spec.default;
|
|
880
|
+
return params;
|
|
881
|
+
},
|
|
882
|
+
defaultInstance(id) {
|
|
883
|
+
const definition = registry.get(id);
|
|
884
|
+
if (definition === void 0) return void 0;
|
|
885
|
+
return defaultActivationInstance(definition);
|
|
886
|
+
},
|
|
887
|
+
instanceKey(instance) {
|
|
888
|
+
const values = definitionParams(instance.id).map((spec) => instance.params[spec.key] ?? spec.default);
|
|
889
|
+
return `${instance.id}:${values.join(",")}`;
|
|
890
|
+
},
|
|
891
|
+
clampParams(definition, params) {
|
|
892
|
+
return clampParamsBySpecs(definition.params, params);
|
|
893
|
+
},
|
|
894
|
+
sanitizeInstances(instances) {
|
|
895
|
+
if (!Array.isArray(instances)) return [];
|
|
896
|
+
const seen = /* @__PURE__ */ new Set();
|
|
897
|
+
const out = [];
|
|
898
|
+
for (const raw of instances) {
|
|
899
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
900
|
+
const { id, params } = raw;
|
|
901
|
+
if (typeof id !== "string" || seen.has(id)) continue;
|
|
902
|
+
const definition = registry.get(id);
|
|
903
|
+
if (definition === void 0) continue;
|
|
904
|
+
seen.add(id);
|
|
905
|
+
out.push({
|
|
906
|
+
id,
|
|
907
|
+
params: this.clampParams(definition, typeof params === "object" && params !== null ? params : {})
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
return out;
|
|
911
|
+
},
|
|
912
|
+
subscribe(listener) {
|
|
913
|
+
listeners.add(listener);
|
|
914
|
+
return () => {
|
|
915
|
+
listeners.delete(listener);
|
|
916
|
+
};
|
|
917
|
+
},
|
|
918
|
+
getVersion: () => version
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
//#endregion
|
|
568
922
|
//#region src/client/index.ts
|
|
569
923
|
function apply(ctx) {
|
|
570
924
|
const registry = createIndicatorRegistry();
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../../indicators/lib/registry.js","../../indicators/lib/math.js","../../indicators/lib/presets.js","../src/client/index.ts"],"sourcesContent":["//#region src/registry.ts\nfunction createIndicatorRegistry() {\n\tconst registry = /* @__PURE__ */ new Map();\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet version = 0;\n\tconst register = (definition) => {\n\t\tregistry.set(definition.id, definition);\n\t\tversion += 1;\n\t\tfor (const listener of listeners) listener();\n\t};\n\tconst definitionParams = (id) => registry.get(id)?.params ?? [];\n\treturn {\n\t\tregister,\n\t\tunregister(id) {\n\t\t\tif (!registry.delete(id)) return;\n\t\t\tversion += 1;\n\t\t\tfor (const listener of listeners) listener();\n\t\t},\n\t\tget: (id) => registry.get(id),\n\t\tlist: () => [...registry.values()],\n\t\tdefaultParams(definition) {\n\t\t\tconst params = {};\n\t\t\tfor (const spec of definition.params) params[spec.key] = spec.default;\n\t\t\treturn params;\n\t\t},\n\t\tdefaultInstance(id) {\n\t\t\tconst definition = registry.get(id);\n\t\t\tif (definition === void 0) return void 0;\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tparams: this.defaultParams(definition)\n\t\t\t};\n\t\t},\n\t\tinstanceKey(instance) {\n\t\t\tconst values = definitionParams(instance.id).map((spec) => instance.params[spec.key] ?? spec.default);\n\t\t\treturn `${instance.id}:${values.join(\",\")}`;\n\t\t},\n\t\tclampParams(definition, params) {\n\t\t\tconst out = {};\n\t\t\tfor (const spec of definition.params) {\n\t\t\t\tconst raw = params[spec.key];\n\t\t\t\tout[spec.key] = typeof raw === \"number\" && Number.isFinite(raw) ? Math.min(spec.max, Math.max(spec.min, Math.round(raw))) : spec.default;\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\tsanitizeInstances(instances) {\n\t\t\tif (!Array.isArray(instances)) return [];\n\t\t\tconst seen = /* @__PURE__ */ new Set();\n\t\t\tconst out = [];\n\t\t\tfor (const raw of instances) {\n\t\t\t\tif (typeof raw !== \"object\" || raw === null) continue;\n\t\t\t\tconst { id, params } = raw;\n\t\t\t\tif (typeof id !== \"string\" || seen.has(id)) continue;\n\t\t\t\tconst definition = registry.get(id);\n\t\t\t\tif (definition === void 0) continue;\n\t\t\t\tseen.add(id);\n\t\t\t\tout.push({\n\t\t\t\t\tid,\n\t\t\t\t\tparams: this.clampParams(definition, typeof params === \"object\" && params !== null ? params : {})\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tgetVersion: () => version\n\t};\n}\n//#endregion\nexport { createIndicatorRegistry };\n","//#region src/math.ts\n/** 简单移动平均(滚动和,O(n))。 */\nfunction sma(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tlet sum = 0;\n\tfor (let index = 0; index < values.length; index++) {\n\t\tsum += values[index];\n\t\tif (index >= period) sum -= values[index - period];\n\t\tif (index >= period - 1) out[index] = sum / period;\n\t}\n\treturn out;\n}\n/** 指数移动平均(标准 EMA:种子 = 前 period 个的 SMA)。 */\nfunction ema(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tconst k = 2 / (period + 1);\n\tlet seed = 0;\n\tfor (let index = 0; index < period; index++) seed += values[index];\n\tlet prev = seed / period;\n\tout[period - 1] = prev;\n\tfor (let index = period; index < values.length; index++) {\n\t\tprev = values[index] * k + prev * (1 - k);\n\t\tout[index] = prev;\n\t}\n\treturn out;\n}\n/** 滚动样本标准差(无偏校正关——与主流行情软件一致用总体口径)。 */\nfunction stdev(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tfor (let index = period - 1; index < values.length; index++) {\n\t\tlet mean = 0;\n\t\tfor (let offset = 0; offset < period; offset++) mean += values[index - offset];\n\t\tmean /= period;\n\t\tlet variance = 0;\n\t\tfor (let offset = 0; offset < period; offset++) {\n\t\t\tconst delta = values[index - offset] - mean;\n\t\t\tvariance += delta * delta;\n\t\t}\n\t\tout[index] = Math.sqrt(variance / period);\n\t}\n\treturn out;\n}\n/**\n* 布林带:返回中轨(SMA)与上下轨(中轨 ± N 倍标准差)。\n* 主图叠加指标,三条线共享 warm-up。\n*/\nfunction bollinger(values, period, mult) {\n\tconst mid = sma(values, period);\n\tconst sd = stdev(values, period);\n\tconst upper = new Array(values.length).fill(void 0);\n\tconst lower = new Array(values.length).fill(void 0);\n\tfor (let index = 0; index < values.length; index++) {\n\t\tconst base = mid[index];\n\t\tconst dev = sd[index];\n\t\tif (base === void 0 || dev === void 0) continue;\n\t\tupper[index] = base + mult * dev;\n\t\tlower[index] = base - mult * dev;\n\t}\n\treturn {\n\t\tmid,\n\t\tupper,\n\t\tlower\n\t};\n}\n/**\n* MACD:DIF = EMA(fast) - EMA(slow);DEA = DIF 的 EMA(signal);\n* 柱 = (DIF - DEA) × 2。warm-up 取两者较大者(EMA 串联)。\n*/\nfunction macd(values, fast, slow, signal) {\n\tconst emaFast = ema(values, fast);\n\tconst emaSlow = ema(values, slow);\n\tconst dif = values.map((_, index) => {\n\t\tconst a = emaFast[index];\n\t\tconst b = emaSlow[index];\n\t\treturn a === void 0 || b === void 0 ? void 0 : a - b;\n\t});\n\tconst deaCompact = ema(dif.filter((value) => value !== void 0), signal);\n\tconst dea = new Array(values.length).fill(void 0);\n\tlet cursor = 0;\n\tfor (let index = 0; index < values.length; index++) {\n\t\tif (dif[index] === void 0) continue;\n\t\tdea[index] = deaCompact[cursor];\n\t\tcursor++;\n\t}\n\treturn {\n\t\tdif,\n\t\tdea,\n\t\thist: values.map((_, index) => {\n\t\t\tconst d = dif[index];\n\t\t\tconst e = dea[index];\n\t\t\treturn d === void 0 || e === void 0 ? void 0 : (d - e) * 2;\n\t\t})\n\t};\n}\n/**\n* RSI(Wilder 平滑)。种子 = 前 period 个涨跌均值,其后\n* avgGain/avgLoss 递推;前 period 位为 undefined。\n*/\nfunction rsi(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tlet gain = 0;\n\tlet loss = 0;\n\tfor (let index = 1; index <= period; index++) {\n\t\tconst delta = values[index] - values[index - 1];\n\t\tif (delta >= 0) gain += delta;\n\t\telse loss -= delta;\n\t}\n\tgain /= period;\n\tloss /= period;\n\tout[period] = loss === 0 ? 100 : 100 - 100 / (1 + gain / loss);\n\tfor (let index = period + 1; index < values.length; index++) {\n\t\tconst delta = values[index] - values[index - 1];\n\t\tgain = (gain * (period - 1) + Math.max(delta, 0)) / period;\n\t\tloss = (loss * (period - 1) + Math.max(-delta, 0)) / period;\n\t\tout[index] = loss === 0 ? 100 : 100 - 100 / (1 + gain / loss);\n\t}\n\treturn out;\n}\n/**\n* KDJ(RSV 的 SMA[Wilder] 平滑,初始值 50)。\n* 返回 k/d/j 三条序列;warm-up = N-1。\n*/\nfunction kdj(highs, lows, closes, n) {\n\tconst length = closes.length;\n\tconst k = new Array(length).fill(void 0);\n\tconst d = new Array(length).fill(void 0);\n\tconst j = new Array(length).fill(void 0);\n\tif (!valid(n, length)) return {\n\t\tk,\n\t\td,\n\t\tj\n\t};\n\tlet prevK = 50;\n\tlet prevD = 50;\n\tfor (let index = n - 1; index < length; index++) {\n\t\tlet hh = -Infinity;\n\t\tlet ll = Infinity;\n\t\tfor (let offset = 0; offset < n; offset++) {\n\t\t\thh = Math.max(hh, highs[index - offset]);\n\t\t\tll = Math.min(ll, lows[index - offset]);\n\t\t}\n\t\tconst rsvValue = hh === ll ? 50 : (closes[index] - ll) / (hh - ll) * 100;\n\t\tprevK = prevK + (rsvValue - prevK) / 3;\n\t\tprevD = prevD + (prevK - prevD) / 3;\n\t\tk[index] = prevK;\n\t\td[index] = prevD;\n\t\tj[index] = 3 * prevK - 2 * prevD;\n\t}\n\treturn {\n\t\tk,\n\t\td,\n\t\tj\n\t};\n}\nfunction valid(period, length) {\n\treturn Number.isFinite(period) && period >= 1 && length >= period;\n}\n//#endregion\nexport { bollinger, ema, kdj, macd, rsi, sma, stdev };\n","import { bollinger, ema, kdj, macd, rsi, sma } from \"./math.js\";\n//#region src/presets.ts\n/** MA 线配色(富途系配色 + 扩展周期轮换调色板)。 */\nconst MA_COLORS = {\n\tMA5: \"#e6b800\",\n\tMA10: \"#4a90e2\",\n\tMA20: \"#c05fd8\",\n\tMA30: \"#2ba471\",\n\tMA60: \"#f97316\",\n\tMA120: \"#0ea5e9\",\n\tMA250: \"#8a8f99\"\n};\n/** EMA 线配色。 */\nconst EMA_COLORS = {\n\tEMA5: \"#e6b800\",\n\tEMA6: \"#e6b800\",\n\tEMA10: \"#4a90e2\",\n\tEMA12: \"#ff9800\",\n\tEMA20: \"#c05fd8\",\n\tEMA26: \"#00bcd4\",\n\tEMA30: \"#2ba471\",\n\tEMA50: \"#2ba471\",\n\tEMA60: \"#f97316\",\n\tEMA120: \"#0ea5e9\",\n\tEMA200: \"#8a8f99\",\n\tEMA250: \"#8a8f99\"\n};\n/** 均线 6 色备用调色板(富途黄/蓝/紫/绿/橙/青)。 */\nconst FALLBACK_PALETTE = [\n\t\"#e6b800\",\n\t\"#4a90e2\",\n\t\"#c05fd8\",\n\t\"#2ba471\",\n\t\"#f97316\",\n\t\"#0ea5e9\"\n];\nfunction maColor(period, index) {\n\treturn MA_COLORS[`MA${period}`] ?? FALLBACK_PALETTE[index % FALLBACK_PALETTE.length] ?? \"#8a8f99\";\n}\nfunction emaColor(period, index) {\n\treturn EMA_COLORS[`EMA${period}`] ?? FALLBACK_PALETTE[index % FALLBACK_PALETTE.length] ?? \"#8a8f99\";\n}\nconst closesOf = (bars) => bars.map((bar) => bar.close);\n/** 六个预置 definition(纯数据,注册时机归消费方)。 */\nfunction presetDefinitions() {\n\treturn [\n\t\t{\n\t\t\tid: \"ma\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"MA\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"n1\",\n\t\t\t\t\tlabel: \"周期1\",\n\t\t\t\t\tdefault: 5,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n2\",\n\t\t\t\t\tlabel: \"周期2\",\n\t\t\t\t\tdefault: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n3\",\n\t\t\t\t\tlabel: \"周期3\",\n\t\t\t\t\tdefault: 20,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n4\",\n\t\t\t\t\tlabel: \"周期4\",\n\t\t\t\t\tdefault: 30,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n5\",\n\t\t\t\t\tlabel: \"周期5\",\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n6\",\n\t\t\t\t\tlabel: \"周期6\",\n\t\t\t\t\tdefault: 120,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst closes = closesOf(bars);\n\t\t\t\treturn [\n\t\t\t\t\tparams.n1,\n\t\t\t\t\tparams.n2,\n\t\t\t\t\tparams.n3,\n\t\t\t\t\tparams.n4,\n\t\t\t\t\tparams.n5,\n\t\t\t\t\tparams.n6\n\t\t\t\t].filter((period) => typeof period === \"number\" && Number.isFinite(period) && period > 0).map((period, index) => ({\n\t\t\t\t\tkey: `MA${period}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: maColor(period, index),\n\t\t\t\t\tvalues: sma(closes, period)\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"ema\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"EMA\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"n1\",\n\t\t\t\t\tlabel: \"周期1\",\n\t\t\t\t\tdefault: 5,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n2\",\n\t\t\t\t\tlabel: \"周期2\",\n\t\t\t\t\tdefault: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n3\",\n\t\t\t\t\tlabel: \"周期3\",\n\t\t\t\t\tdefault: 20,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n4\",\n\t\t\t\t\tlabel: \"周期4\",\n\t\t\t\t\tdefault: 30,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n5\",\n\t\t\t\t\tlabel: \"周期5\",\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n6\",\n\t\t\t\t\tlabel: \"周期6\",\n\t\t\t\t\tdefault: 120,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst closes = closesOf(bars);\n\t\t\t\treturn [\n\t\t\t\t\tparams.n1,\n\t\t\t\t\tparams.n2,\n\t\t\t\t\tparams.n3,\n\t\t\t\t\tparams.n4,\n\t\t\t\t\tparams.n5,\n\t\t\t\t\tparams.n6\n\t\t\t\t].filter((period) => typeof period === \"number\" && Number.isFinite(period) && period > 0).map((period, index) => ({\n\t\t\t\t\tkey: `EMA${period}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: emaColor(period, index),\n\t\t\t\t\tvalues: ema(closes, period)\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"boll\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"BOLL\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 20,\n\t\t\t\tmin: 2,\n\t\t\t\tmax: 250\n\t\t\t}, {\n\t\t\t\tkey: \"k\",\n\t\t\t\tlabel: \"倍数\",\n\t\t\t\tdefault: 2,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 5\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst { mid, upper, lower } = bollinger(closesOf(bars), params.n, params.k);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"MID\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#8a8f99\",\n\t\t\t\t\t\tvalues: mid\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"UP\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: upper\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"LOW\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: lower\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"macd\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"MACD\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"fast\",\n\t\t\t\t\tlabel: \"快线\",\n\t\t\t\t\tdefault: 12,\n\t\t\t\t\tmin: 2,\n\t\t\t\t\tmax: 100\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"slow\",\n\t\t\t\t\tlabel: \"慢线\",\n\t\t\t\t\tdefault: 26,\n\t\t\t\t\tmin: 2,\n\t\t\t\t\tmax: 200\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"signal\",\n\t\t\t\t\tlabel: \"信号\",\n\t\t\t\t\tdefault: 9,\n\t\t\t\t\tmin: 1,\n\t\t\t\t\tmax: 60\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst { dif, dea, hist } = macd(closesOf(bars), params.fast, params.slow, params.signal);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"DIF\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#e6b800\",\n\t\t\t\t\t\tvalues: dif\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"DEA\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: dea\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"HIST\",\n\t\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\t\tcolor: \"#8a8f99\",\n\t\t\t\t\t\tvalues: hist,\n\t\t\t\t\t\thistogramBySign: true\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"rsi\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"RSI\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 14,\n\t\t\t\tmin: 2,\n\t\t\t\tmax: 120\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\treturn [{\n\t\t\t\t\tkey: `RSI${params.n}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: \"#c05fd8\",\n\t\t\t\t\tvalues: rsi(closesOf(bars), params.n)\n\t\t\t\t}];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"kdj\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"KDJ\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 9,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 120\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst highs = bars.map((bar) => bar.high);\n\t\t\t\tconst lows = bars.map((bar) => bar.low);\n\t\t\t\tconst { k, d, j } = kdj(highs, lows, closesOf(bars), params.n);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"K\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#e6b800\",\n\t\t\t\t\t\tvalues: k\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"D\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: d\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"J\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#c05fd8\",\n\t\t\t\t\t\tvalues: j\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\t];\n}\n//#endregion\nexport { EMA_COLORS, MA_COLORS, presetDefinitions };\n","/**\n * 预置指标提供插件(client 半):在 client 上下文提供 tradingIndicators\n * 服务 = IndicatorRegistry 单例(注册六个预置指标)。机制先例 =\n * session-controller 的 `reflect.provide('sessions')`(dsh\n * packages/api/session-controller/src/client/sessions/service.ts:263)。\n *\n * 社区指标插件的接入方式:client 半 `ctx.inject(['tradingIndicators'],\n * scope => scope.tradingIndicators.register(definition))` —— 服务可用时\n * 回调才触发,加载顺序由 cordis 依赖解析保证;与本插件零耦合。\n *\n * 消费方 client-ui-trading 以可选依赖桥接(同样 ctx.inject),插件未\n * 安装时行情视图零指标正常工作。\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createIndicatorRegistry, presetDefinitions } from '@dshtrading/indicators'\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n /** dsh-trading 技术指标注册表(社区指标经 ctx.inject 消费后 register)。 */\n tradingIndicators: import('@dshtrading/indicators').IndicatorRegistry\n }\n}\n\nexport function apply(ctx: Context): void {\n const registry = createIndicatorRegistry()\n for (const definition of presetDefinitions()) registry.register(definition)\n // provide 由插件 fiber 持有:插件卸载/重载时服务随之注销/重建。\n ctx.reflect.provide('tradingIndicators', registry)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../../indicators/lib/aux-series.js","../../indicators/lib/math.js","../../indicators/lib/presets.js","../../indicators/lib/chart-activations.js","../../indicators/lib/registry.js","../src/client/index.ts"],"sourcesContent":["//#region src/aux-series.ts\n/**\n* 逐根序列的值不变量(宿主注入方的契约,消费方按此写纯函数):\n* - 值数组长度**严格等于** bars.length(逐根对齐,不做前向填充、不做区间匹配);\n* - `undefined` = 该根无值(指标据此留空,不是 0);\n* - 数组元素只可能是有限数或 undefined,绝不出现 NaN/Infinity。\n*/\n/** 五日成交量档位通道键(冻结字面量)。 */\nconst FIVE_DAY_VOLUME_TIER_AUX_KEY = \"five-day-volume-tiers\";\n/** 逐根档位编码词汇:下标即编码值。0 = 不可判(无前值/基准日/前值无量),1..4 = 量比四档。 */\nconst FIVE_DAY_VOLUME_TIER_CODES = [\n\t\"noPrior\",\n\t\"lt1\",\n\t\"lt2\",\n\t\"lt3\",\n\t\"gte3\"\n];\n/**\n* 把日频外部序列对齐到 K 线序列:对每根 K 线取「date ≤ 该 K 线所属交易日」的\n* 最新一条外部值(前向填充,反映「该交易日收盘时已知的最新持股比例」)。\n* 早于首条外部数据的 K 线填 undefined。返回数组长度严格等于 bars.length。\n* dayOfKline: 由宿主传入的「K 线 → 交易日(UTC 00:00)」取值函数,避免本纯库\n* 依赖行情周期词汇。\n*\n* 前向填充的理由:港股通持股日频公布,K 线级别 ≥ 1d 时一个交易日一个点;但周 K/\n* 月 K 上一个 bar 覆盖多日,必须取区间内最新已知值,否则会用到未来数据。\n*\n* 每根 K 线独立二分取值:只依赖 points 升序(契约要求),不假设 bars 升序——\n* 宿主倒序传入或周期混排时每根 K 线拿到的仍是同一条值。\n*/\nfunction alignAuxToBars(bars, points, dayOfKline) {\n\tconst aligned = new Array(bars.length);\n\tfor (let index = 0; index < bars.length; index += 1) {\n\t\tconst bar = bars[index];\n\t\taligned[index] = bar === void 0 ? void 0 : valueAtOrBefore(points, dayOfKline(bar));\n\t}\n\treturn aligned;\n}\n/** 升序序列里 date ≤ day 的最后一条值;无命中(早于首条数据 / 空序列)返回 undefined。 */\nfunction valueAtOrBefore(points, day) {\n\tlet low = 0;\n\tlet high = points.length - 1;\n\tlet hit = -1;\n\twhile (low <= high) {\n\t\tconst mid = low + high >> 1;\n\t\tconst point = points[mid];\n\t\tif (point === void 0) break;\n\t\tif (point.date <= day) {\n\t\t\thit = mid;\n\t\t\tlow = mid + 1;\n\t\t} else high = mid - 1;\n\t}\n\treturn hit < 0 ? void 0 : points[hit]?.value;\n}\n//#endregion\nexport { FIVE_DAY_VOLUME_TIER_AUX_KEY, FIVE_DAY_VOLUME_TIER_CODES, alignAuxToBars };\n","//#region src/math.ts\n/** 简单移动平均(滚动和,O(n))。 */\nfunction sma(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tlet sum = 0;\n\tfor (let index = 0; index < values.length; index++) {\n\t\tsum += values[index];\n\t\tif (index >= period) sum -= values[index - period];\n\t\tif (index >= period - 1) out[index] = sum / period;\n\t}\n\treturn out;\n}\n/** 指数移动平均(标准 EMA:种子 = 前 period 个的 SMA)。 */\nfunction ema(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tconst k = 2 / (period + 1);\n\tlet seed = 0;\n\tfor (let index = 0; index < period; index++) seed += values[index];\n\tlet prev = seed / period;\n\tout[period - 1] = prev;\n\tfor (let index = period; index < values.length; index++) {\n\t\tprev = values[index] * k + prev * (1 - k);\n\t\tout[index] = prev;\n\t}\n\treturn out;\n}\n/** 滚动样本标准差(无偏校正关——与主流行情软件一致用总体口径)。 */\nfunction stdev(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tfor (let index = period - 1; index < values.length; index++) {\n\t\tlet mean = 0;\n\t\tfor (let offset = 0; offset < period; offset++) mean += values[index - offset];\n\t\tmean /= period;\n\t\tlet variance = 0;\n\t\tfor (let offset = 0; offset < period; offset++) {\n\t\t\tconst delta = values[index - offset] - mean;\n\t\t\tvariance += delta * delta;\n\t\t}\n\t\tout[index] = Math.sqrt(variance / period);\n\t}\n\treturn out;\n}\n/**\n* 布林带:返回中轨(SMA)与上下轨(中轨 ± N 倍标准差)。\n* 主图叠加指标,三条线共享 warm-up。\n*/\nfunction bollinger(values, period, mult) {\n\tconst mid = sma(values, period);\n\tconst sd = stdev(values, period);\n\tconst upper = new Array(values.length).fill(void 0);\n\tconst lower = new Array(values.length).fill(void 0);\n\tfor (let index = 0; index < values.length; index++) {\n\t\tconst base = mid[index];\n\t\tconst dev = sd[index];\n\t\tif (base === void 0 || dev === void 0) continue;\n\t\tupper[index] = base + mult * dev;\n\t\tlower[index] = base - mult * dev;\n\t}\n\treturn {\n\t\tmid,\n\t\tupper,\n\t\tlower\n\t};\n}\n/**\n* MACD:DIF = EMA(fast) - EMA(slow);DEA = DIF 的 EMA(signal);\n* 柱 = (DIF - DEA) × 2。warm-up 取两者较大者(EMA 串联)。\n*/\nfunction macd(values, fast, slow, signal) {\n\tconst emaFast = ema(values, fast);\n\tconst emaSlow = ema(values, slow);\n\tconst dif = values.map((_, index) => {\n\t\tconst a = emaFast[index];\n\t\tconst b = emaSlow[index];\n\t\treturn a === void 0 || b === void 0 ? void 0 : a - b;\n\t});\n\tconst deaCompact = ema(dif.filter((value) => value !== void 0), signal);\n\tconst dea = new Array(values.length).fill(void 0);\n\tlet cursor = 0;\n\tfor (let index = 0; index < values.length; index++) {\n\t\tif (dif[index] === void 0) continue;\n\t\tdea[index] = deaCompact[cursor];\n\t\tcursor++;\n\t}\n\treturn {\n\t\tdif,\n\t\tdea,\n\t\thist: values.map((_, index) => {\n\t\t\tconst d = dif[index];\n\t\t\tconst e = dea[index];\n\t\t\treturn d === void 0 || e === void 0 ? void 0 : (d - e) * 2;\n\t\t})\n\t};\n}\n/**\n* RSI(Wilder 平滑)。种子 = 前 period 个涨跌均值,其后\n* avgGain/avgLoss 递推;前 period 位为 undefined。\n*/\nfunction rsi(values, period) {\n\tconst out = new Array(values.length).fill(void 0);\n\tif (!valid(period, values.length)) return out;\n\tlet gain = 0;\n\tlet loss = 0;\n\tfor (let index = 1; index <= period; index++) {\n\t\tconst delta = values[index] - values[index - 1];\n\t\tif (delta >= 0) gain += delta;\n\t\telse loss -= delta;\n\t}\n\tgain /= period;\n\tloss /= period;\n\tout[period] = loss === 0 ? 100 : 100 - 100 / (1 + gain / loss);\n\tfor (let index = period + 1; index < values.length; index++) {\n\t\tconst delta = values[index] - values[index - 1];\n\t\tgain = (gain * (period - 1) + Math.max(delta, 0)) / period;\n\t\tloss = (loss * (period - 1) + Math.max(-delta, 0)) / period;\n\t\tout[index] = loss === 0 ? 100 : 100 - 100 / (1 + gain / loss);\n\t}\n\treturn out;\n}\n/**\n* KDJ(RSV 的 SMA[Wilder] 平滑,初始值 50)。\n* 返回 k/d/j 三条序列;warm-up = N-1。\n*/\nfunction kdj(highs, lows, closes, n) {\n\tconst length = closes.length;\n\tconst k = new Array(length).fill(void 0);\n\tconst d = new Array(length).fill(void 0);\n\tconst j = new Array(length).fill(void 0);\n\tif (!valid(n, length)) return {\n\t\tk,\n\t\td,\n\t\tj\n\t};\n\tlet prevK = 50;\n\tlet prevD = 50;\n\tfor (let index = n - 1; index < length; index++) {\n\t\tlet hh = -Infinity;\n\t\tlet ll = Infinity;\n\t\tfor (let offset = 0; offset < n; offset++) {\n\t\t\thh = Math.max(hh, highs[index - offset]);\n\t\t\tll = Math.min(ll, lows[index - offset]);\n\t\t}\n\t\tconst rsvValue = hh === ll ? 50 : (closes[index] - ll) / (hh - ll) * 100;\n\t\tprevK = prevK + (rsvValue - prevK) / 3;\n\t\tprevD = prevD + (prevK - prevD) / 3;\n\t\tk[index] = prevK;\n\t\td[index] = prevD;\n\t\tj[index] = 3 * prevK - 2 * prevD;\n\t}\n\treturn {\n\t\tk,\n\t\td,\n\t\tj\n\t};\n}\nfunction valid(period, length) {\n\treturn Number.isFinite(period) && period >= 1 && length >= period;\n}\n//#endregion\nexport { bollinger, ema, kdj, macd, rsi, sma, stdev };\n","import { FIVE_DAY_VOLUME_TIER_AUX_KEY, alignAuxToBars } from \"./aux-series.js\";\nimport { bollinger, ema, kdj, macd, rsi, sma } from \"./math.js\";\n//#region src/presets.ts\n/** MA 线配色(富途系配色 + 扩展周期轮换调色板)。 */\nconst MA_COLORS = {\n\tMA5: \"#e6b800\",\n\tMA10: \"#4a90e2\",\n\tMA20: \"#c05fd8\",\n\tMA30: \"#2ba471\",\n\tMA60: \"#f97316\",\n\tMA120: \"#0ea5e9\",\n\tMA250: \"#8a8f99\"\n};\n/** EMA 线配色。 */\nconst EMA_COLORS = {\n\tEMA5: \"#e6b800\",\n\tEMA6: \"#e6b800\",\n\tEMA10: \"#4a90e2\",\n\tEMA12: \"#ff9800\",\n\tEMA20: \"#c05fd8\",\n\tEMA26: \"#00bcd4\",\n\tEMA30: \"#2ba471\",\n\tEMA50: \"#2ba471\",\n\tEMA60: \"#f97316\",\n\tEMA120: \"#0ea5e9\",\n\tEMA200: \"#8a8f99\",\n\tEMA250: \"#8a8f99\"\n};\n/** 均线 6 色备用调色板(富途黄/蓝/紫/绿/橙/青)。 */\nconst FALLBACK_PALETTE = [\n\t\"#e6b800\",\n\t\"#4a90e2\",\n\t\"#c05fd8\",\n\t\"#2ba471\",\n\t\"#f97316\",\n\t\"#0ea5e9\"\n];\nfunction maColor(period, index) {\n\treturn MA_COLORS[`MA${period}`] ?? FALLBACK_PALETTE[index % FALLBACK_PALETTE.length] ?? \"#8a8f99\";\n}\nfunction emaColor(period, index) {\n\treturn EMA_COLORS[`EMA${period}`] ?? FALLBACK_PALETTE[index % FALLBACK_PALETTE.length] ?? \"#8a8f99\";\n}\nconst closesOf = (bars) => bars.map((bar) => bar.close);\n/** 港股通持股比例副图消费的外部序列键(宿主按此键 prefetch 并按同名键注入)。 */\nconst HK_CONNECT_HOLDING_AUX_KEY = \"hk-connect-holding\";\n/** 主动买盘副图消费的外部序列键(与桥端点同名,宿主按此键 prefetch 并注入)。 */\nconst ACTIVE_BUY_AUX_KEY = \"cn-active-buy\";\n/** 一天的毫秒数(K 线交易日归一到 UTC 00:00 用)。 */\nconst MS_PER_DAY = 864e5;\n/**\n* K 线 → 交易日(UTC 00:00),供日频外部序列对齐。日线及更细周期取 openTime\n* 当日(本仓日频 openTime 即 UTC 00:00,与外部序列一字对齐):这时不用 closeTime,\n* 它是当日 23:59:59.999,一旦 openTime 带盘中偏移(如 09:30)向下取整就会进位到\n* 次日、吃到未来一天的值。周 K/月 K 则取 closeTime 当日——周期末,从而对齐到区间内\n* 最新已知值,而不是周期起点的旧值。\n*/\nfunction klineTradingDay(bar) {\n\tconst closeTime = bar.closeTime;\n\tconst periodEnd = typeof closeTime === \"number\" && Number.isFinite(closeTime) ? closeTime : bar.openTime;\n\tconst tradingDay = periodEnd - bar.openTime >= 2 * MS_PER_DAY ? periodEnd : bar.openTime;\n\treturn Math.floor(tradingDay / MS_PER_DAY) * MS_PER_DAY;\n}\n/**\n* K 线覆盖的 UTC 日区间 [首日 00:00, 末日 00:00](含首尾)。日线开收盘同日 ⇒ 单日\n* 区间(等价于精确当日匹配);周 K/月 K 跨多日 ⇒ 多日区间。closeTime 非有限或早于\n* openTime(脏数据)时退化为 openTime 当日。\n*/\nfunction klineCoverageRange(bar) {\n\tconst start = Math.floor(bar.openTime / MS_PER_DAY) * MS_PER_DAY;\n\tconst closeTime = bar.closeTime;\n\tconst closeDay = typeof closeTime === \"number\" && Number.isFinite(closeTime) ? Math.floor(closeTime / MS_PER_DAY) * MS_PER_DAY : start;\n\treturn closeDay > start ? [start, closeDay] : [start, start];\n}\n/**\n* 把日频外部序列对齐到 K 线:每根只取**落在该 K 线覆盖区间内**的最新一条值,区间内\n* 无点 ⇒ undefined,绝不沿用区间之前的点(无前向填充)。返回数组长度严格等于\n* bars.length。只依赖 points 升序(契约要求)且每根 K 线独立二分,不假设 bars 升序。\n*/\nfunction alignAuxToBarCoverage(bars, points) {\n\tconst aligned = new Array(bars.length);\n\tfor (let index = 0; index < bars.length; index += 1) {\n\t\tconst bar = bars[index];\n\t\tif (bar === void 0) {\n\t\t\taligned[index] = void 0;\n\t\t\tcontinue;\n\t\t}\n\t\tconst [start, end] = klineCoverageRange(bar);\n\t\taligned[index] = valueWithinRange(points, start, end);\n\t}\n\treturn aligned;\n}\n/** 升序序列里 date ∈ [start, end] 的最后一条值;区间内无点(或序列为空)返回 undefined。 */\nfunction valueWithinRange(points, start, end) {\n\tlet low = 0;\n\tlet high = points.length - 1;\n\tlet hit = -1;\n\twhile (low <= high) {\n\t\tconst mid = low + high >> 1;\n\t\tconst point = points[mid];\n\t\tif (point === void 0) break;\n\t\tif (point.date <= end) {\n\t\t\thit = mid;\n\t\t\tlow = mid + 1;\n\t\t} else high = mid - 1;\n\t}\n\tconst point = hit < 0 ? void 0 : points[hit];\n\treturn point !== void 0 && point.date >= start ? point.value : void 0;\n}\n/**\n* 档位色(亮/暗):镜像 `packages/client-ui-trading/src/client/five-day-series.ts`\n* 的 TIER_COLORS_LIGHT / TIER_COLORS_DARK——「行情·5日」成交量档位色是这组色值的\n* 唯一事实来源,本表是逐档同值的副本(本包不能反向依赖 UI 包),改色必须两处同步。\n*/\nconst VOLUME_TIER_THEME_COLORS = {\n\t无前值: {\n\t\tlight: \"#a8adb8\",\n\t\tdark: \"#6b7280\"\n\t},\n\t\"量比<1\": {\n\t\tlight: \"#d9a01f\",\n\t\tdark: \"#e8c552\"\n\t},\n\t\"量比1-2\": {\n\t\tlight: \"#ee7f72\",\n\t\tdark: \"#f0958b\"\n\t},\n\t\"量比2-3\": {\n\t\tlight: \"#c62828\",\n\t\tdark: \"#e5484d\"\n\t},\n\t\"量比≥3\": {\n\t\tlight: \"#1c1c1e\",\n\t\tdark: \"#f2f4f8\"\n\t}\n};\n/** 档位顺序 = 输出顺序 = 图例顺序(灰档在前,其后按量比递增)。 */\nconst VOLUME_TIERS = [\n\t\"无前值\",\n\t\"量比<1\",\n\t\"量比1-2\",\n\t\"量比2-3\",\n\t\"量比≥3\"\n];\n/** 量比分档量能的前值窗口默认周期(params schema 与 compute 的缺参兜底共用一处)。 */\nconst VOLUME_TIER_DEFAULT_PERIOD = 4;\n/**\n* 量比 → 档位:阈值 1/2/3 分四档(比值恰好等于阈值时落**较高**一档,与五日图例\n* 「1 ≤ 量比 < 2」的区间语义一致);undefined(无前值 / 不可判)落中性灰档。\n* `Number.POSITIVE_INFINITY`(前值无量但本周期有量)落最高档。\n*/\nfunction volumeTierOf(ratio) {\n\tif (ratio === void 0) return \"无前值\";\n\tif (ratio < 1) return \"量比<1\";\n\tif (ratio < 2) return \"量比1-2\";\n\tif (ratio < 3) return \"量比2-3\";\n\treturn \"量比≥3\";\n}\n/**\n* 量比序列:本周期量 ÷ 前 N 个周期量均值(不含本周期,等价 REF(MA(volume, N), 1))。\n* 长度严格等于 bars.length。判定顺序(前值无量那两条与「行情·5日」现行分支同口径,\n* 见 `packages/client-ui-trading/src/client/five-day-series.ts:220-225`):\n* 1. 本周期量非有限(脏数据)→ undefined(灰);\n* 2. 前值窗口不可用(前 N 根之内)或均值非有限(窗口含脏值)→ undefined(灰);\n* 3. 前值均值 ≤ 0 且本周期有量 → `Number.POSITIVE_INFINITY`(比值发散,按最高档处理);\n* 4. 前值均值 ≤ 0 且本周期量为 0 → undefined(比值无定义,灰);\n* 5. 其余 → 本周期量 ÷ 前值均值(溢出的极端值照样发散,落最高档)。\n*/\nfunction volumeRatios(bars, period) {\n\tconst volumes = bars.map((bar) => bar.volume);\n\tconst priorMeans = sma(volumes, period);\n\treturn bars.map((_bar, index) => {\n\t\tconst volume = volumes[index];\n\t\tif (volume === void 0 || !Number.isFinite(volume)) return void 0;\n\t\tconst mean = index >= 1 ? priorMeans[index - 1] : void 0;\n\t\tif (mean === void 0 || !Number.isFinite(mean)) return void 0;\n\t\tif (mean <= 0) return volume > 0 ? Number.POSITIVE_INFINITY : void 0;\n\t\treturn volume / mean;\n\t});\n}\n/**\n* 成交量柱的两条语义色(红涨绿跌缺省档 red-up 的 up/down,不透明度 0.55):\n* 镜像 `packages/client-ui-trading/src/client/color-mode.ts` 的\n* `PALETTES['red-up'].upAlpha(0.55)` / `downAlpha(0.55)`(本包不能反向依赖 UI 包)。\n* 成交量柱有意的口径:只按涨跌语义配色,**不读**红涨绿跌设置——与五日档位色同款,\n* 换绿涨红跌不会把成交量柱的涨跌语义翻过来。\n*/\nconst VOLUME_UP_COLOR = \"rgba(230, 69, 69, 0.55)\";\nconst VOLUME_DOWN_COLOR = \"rgba(43, 164, 113, 0.55)\";\n/** 十个预置 definition(纯数据,注册时机归消费方)。 */\nfunction presetDefinitions() {\n\treturn [\n\t\t{\n\t\t\tid: \"ma\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"MA\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"n1\",\n\t\t\t\t\tlabel: \"周期1\",\n\t\t\t\t\tdefault: 5,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n2\",\n\t\t\t\t\tlabel: \"周期2\",\n\t\t\t\t\tdefault: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n3\",\n\t\t\t\t\tlabel: \"周期3\",\n\t\t\t\t\tdefault: 20,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n4\",\n\t\t\t\t\tlabel: \"周期4\",\n\t\t\t\t\tdefault: 30,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n5\",\n\t\t\t\t\tlabel: \"周期5\",\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n6\",\n\t\t\t\t\tlabel: \"周期6\",\n\t\t\t\t\tdefault: 120,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst closes = closesOf(bars);\n\t\t\t\treturn [\n\t\t\t\t\tparams.n1,\n\t\t\t\t\tparams.n2,\n\t\t\t\t\tparams.n3,\n\t\t\t\t\tparams.n4,\n\t\t\t\t\tparams.n5,\n\t\t\t\t\tparams.n6\n\t\t\t\t].filter((period) => typeof period === \"number\" && Number.isFinite(period) && period > 0).map((period, index) => ({\n\t\t\t\t\tkey: `MA${period}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: maColor(period, index),\n\t\t\t\t\tvalues: sma(closes, period)\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"ema\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"EMA\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"n1\",\n\t\t\t\t\tlabel: \"周期1\",\n\t\t\t\t\tdefault: 5,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n2\",\n\t\t\t\t\tlabel: \"周期2\",\n\t\t\t\t\tdefault: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n3\",\n\t\t\t\t\tlabel: \"周期3\",\n\t\t\t\t\tdefault: 20,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n4\",\n\t\t\t\t\tlabel: \"周期4\",\n\t\t\t\t\tdefault: 30,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n5\",\n\t\t\t\t\tlabel: \"周期5\",\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"n6\",\n\t\t\t\t\tlabel: \"周期6\",\n\t\t\t\t\tdefault: 120,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 250\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst closes = closesOf(bars);\n\t\t\t\treturn [\n\t\t\t\t\tparams.n1,\n\t\t\t\t\tparams.n2,\n\t\t\t\t\tparams.n3,\n\t\t\t\t\tparams.n4,\n\t\t\t\t\tparams.n5,\n\t\t\t\t\tparams.n6\n\t\t\t\t].filter((period) => typeof period === \"number\" && Number.isFinite(period) && period > 0).map((period, index) => ({\n\t\t\t\t\tkey: `EMA${period}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: emaColor(period, index),\n\t\t\t\t\tvalues: ema(closes, period)\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"boll\",\n\t\t\tpane: \"main\",\n\t\t\ttitle: \"BOLL\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 20,\n\t\t\t\tmin: 2,\n\t\t\t\tmax: 250\n\t\t\t}, {\n\t\t\t\tkey: \"k\",\n\t\t\t\tlabel: \"倍数\",\n\t\t\t\tdefault: 2,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 5\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst { mid, upper, lower } = bollinger(closesOf(bars), params.n, params.k);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"MID\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#8a8f99\",\n\t\t\t\t\t\tvalues: mid\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"UP\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: upper\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"LOW\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: lower\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"macd\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"MACD\",\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\tkey: \"fast\",\n\t\t\t\t\tlabel: \"快线\",\n\t\t\t\t\tdefault: 12,\n\t\t\t\t\tmin: 2,\n\t\t\t\t\tmax: 100\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"slow\",\n\t\t\t\t\tlabel: \"慢线\",\n\t\t\t\t\tdefault: 26,\n\t\t\t\t\tmin: 2,\n\t\t\t\t\tmax: 200\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"signal\",\n\t\t\t\t\tlabel: \"信号\",\n\t\t\t\t\tdefault: 9,\n\t\t\t\t\tmin: 1,\n\t\t\t\t\tmax: 60\n\t\t\t\t}\n\t\t\t],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst { dif, dea, hist } = macd(closesOf(bars), params.fast, params.slow, params.signal);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"DIF\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#e6b800\",\n\t\t\t\t\t\tvalues: dif\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"DEA\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: dea\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"HIST\",\n\t\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\t\tcolor: \"#8a8f99\",\n\t\t\t\t\t\tvalues: hist,\n\t\t\t\t\t\thistogramBySign: true\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"rsi\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"RSI\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 14,\n\t\t\t\tmin: 2,\n\t\t\t\tmax: 120\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\treturn [{\n\t\t\t\t\tkey: `RSI${params.n}`,\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: \"#c05fd8\",\n\t\t\t\t\tvalues: rsi(closesOf(bars), params.n)\n\t\t\t\t}];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"kdj\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"KDJ\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: 9,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 120\n\t\t\t}],\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst highs = bars.map((bar) => bar.high);\n\t\t\t\tconst lows = bars.map((bar) => bar.low);\n\t\t\t\tconst { k, d, j } = kdj(highs, lows, closesOf(bars), params.n);\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"K\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#e6b800\",\n\t\t\t\t\t\tvalues: k\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"D\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#4a90e2\",\n\t\t\t\t\t\tvalues: d\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"J\",\n\t\t\t\t\t\tkind: \"line\",\n\t\t\t\t\t\tcolor: \"#c05fd8\",\n\t\t\t\t\t\tvalues: j\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"vol\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"成交量\",\n\t\t\tparams: [],\n\t\t\tdescription: \"柱高是本周期成交量;上涨(收盘 ≥ 开盘,等号归上涨)用红色、下跌用绿色,与 K 线方向判据同口径。颜色是固定的涨跌语义色,不随红涨绿跌配色设置翻转。当前级别能取到五日同分钟档位序列时(五日级别),柱色改用档位色(「行情·5日」的五档口径,见量比分档量能);取不到时回落涨跌色照常出柱。全市场、全 K 线级别通用。\",\n\t\t\tdefaultActive: true,\n\t\t\tbarAux: [FIVE_DAY_VOLUME_TIER_AUX_KEY],\n\t\t\tcompute(bars) {\n\t\t\t\treturn [{\n\t\t\t\t\tkey: \"上涨量\",\n\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\tcolor: VOLUME_UP_COLOR,\n\t\t\t\t\tvalues: bars.map((bar) => Number.isFinite(bar.volume) && bar.close >= bar.open ? bar.volume : void 0),\n\t\t\t\t\tpriceFormat: \"volume\"\n\t\t\t\t}, {\n\t\t\t\t\tkey: \"下跌量\",\n\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\tcolor: VOLUME_DOWN_COLOR,\n\t\t\t\t\tvalues: bars.map((bar) => Number.isFinite(bar.volume) && bar.close < bar.open ? bar.volume : void 0),\n\t\t\t\t\tpriceFormat: \"volume\"\n\t\t\t\t}];\n\t\t\t},\n\t\t\tcomputeBarAux(bars, _params, barAux) {\n\t\t\t\tconst tiers = barAux[FIVE_DAY_VOLUME_TIER_AUX_KEY];\n\t\t\t\treturn VOLUME_TIERS.map((tier, tierIndex) => ({\n\t\t\t\t\tkey: tier,\n\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\tcolor: VOLUME_TIER_THEME_COLORS[tier].light,\n\t\t\t\t\tthemeColor: VOLUME_TIER_THEME_COLORS[tier],\n\t\t\t\t\tvalues: bars.map((bar, index) => tiers?.[index] === tierIndex && Number.isFinite(bar.volume) ? bar.volume : void 0),\n\t\t\t\t\tpriceFormat: \"volume\"\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"vol-tier\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"量比分档量能\",\n\t\t\tparams: [{\n\t\t\t\tkey: \"n\",\n\t\t\t\tlabel: \"周期\",\n\t\t\t\tdefault: VOLUME_TIER_DEFAULT_PERIOD,\n\t\t\t\tmin: 2,\n\t\t\t\tmax: 250\n\t\t\t}],\n\t\t\tdescription: \"成交量按量比分档着色:量比 = 本周期成交量 ÷ 前 N 个周期成交量均值(不含本周期,等价 REF(MA(volume, N), 1)),阈值 1 / 2 / 3 分四档(量比 < 1、1 ≤ 量比 < 2、2 ≤ 量比 < 3、量比 ≥ 3)。前值窗口不可用(前 N 个周期之内,或前值含脏数据)走中性灰档;前值无量(前值均值为 0)时,本周期也无量走中性灰档,本周期有量则比值发散、按最高档处理(与「行情·5日」同口径)。柱高是本周期成交量,档位只决定颜色;全市场、全 K 线级别通用。着色读的是量比而不是涨跌,因此不受红涨绿跌配色设置影响。\",\n\t\t\tdefaultActive: true,\n\t\t\tcompute(bars, params) {\n\t\t\t\tconst ratios = volumeRatios(bars, Math.round(params.n ?? VOLUME_TIER_DEFAULT_PERIOD));\n\t\t\t\treturn VOLUME_TIERS.map((tier) => ({\n\t\t\t\t\tkey: tier,\n\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\tcolor: VOLUME_TIER_THEME_COLORS[tier].light,\n\t\t\t\t\tthemeColor: VOLUME_TIER_THEME_COLORS[tier],\n\t\t\t\t\tvalues: bars.map((bar, index) => volumeTierOf(ratios[index]) === tier && Number.isFinite(bar.volume) ? bar.volume : void 0)\n\t\t\t\t}));\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"hk-connect-holding\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"港股通持股比例\",\n\t\t\tparams: [],\n\t\t\tmarkets: [\"hk\"],\n\t\t\tdefaultApplyScope: { hk: {\n\t\t\t\tenabled: true,\n\t\t\t\tintervals: [\n\t\t\t\t\t\"1d\",\n\t\t\t\t\t\"1w\",\n\t\t\t\t\t\"1M\"\n\t\t\t\t]\n\t\t\t} },\n\t\t\taux: [HK_CONNECT_HOLDING_AUX_KEY],\n\t\t\tcompute() {\n\t\t\t\treturn [];\n\t\t\t},\n\t\t\tcomputeAux(bars, _params, aux) {\n\t\t\t\tconst points = aux[HK_CONNECT_HOLDING_AUX_KEY];\n\t\t\t\tif (points === void 0 || points.length === 0) return [];\n\t\t\t\treturn [{\n\t\t\t\t\tkey: \"HK_CONNECT_HOLDING\",\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: \"#7c5cff\",\n\t\t\t\t\tvalues: alignAuxToBars(bars, points, klineTradingDay).map((value) => typeof value === \"number\" && Number.isFinite(value) ? value : void 0),\n\t\t\t\t\tprecision: 2\n\t\t\t\t}];\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tid: \"active-buy\",\n\t\t\tpane: \"sub\",\n\t\t\ttitle: \"主动买盘\",\n\t\t\tparams: [],\n\t\t\tmarkets: [\"cn\"],\n\t\t\tdescription: \"数据源:本地累积的腾讯盘口快照推断的内外盘(非交易所官方逐笔方向,涨跌停/对倒日失真)。红柱为净主动买占当日总量百分比,蓝线为主动买占比 ((100 + 净买占比) / 2,前提是外盘 + 内盘 ≈ 当日总量,两者的差值是未归向成交、量级不固定)。当日柱为盘中累计到最新取数时刻,收盘后收敛为当日终值;某交易日没有采集到读数就是空的,不插值、不沿用前一交易日。\",\n\t\t\tdefaultApplyScope: { cn: {\n\t\t\t\tenabled: true,\n\t\t\t\tintervals: [\n\t\t\t\t\t\"1d\",\n\t\t\t\t\t\"1w\",\n\t\t\t\t\t\"1M\"\n\t\t\t\t]\n\t\t\t} },\n\t\t\taux: [ACTIVE_BUY_AUX_KEY],\n\t\t\tcompute() {\n\t\t\t\treturn [];\n\t\t\t},\n\t\t\tcomputeAux(bars, _params, aux) {\n\t\t\t\tconst points = aux[ACTIVE_BUY_AUX_KEY];\n\t\t\t\tif (points === void 0 || points.length === 0) return [];\n\t\t\t\tconst net = alignAuxToBarCoverage(bars, points).map((value) => typeof value === \"number\" && Number.isFinite(value) ? value : void 0);\n\t\t\t\treturn [{\n\t\t\t\t\tkey: \"净买\",\n\t\t\t\t\tkind: \"histogram\",\n\t\t\t\t\thistogramBySign: true,\n\t\t\t\t\tcolor: \"#e64545\",\n\t\t\t\t\tvalues: net,\n\t\t\t\t\tprecision: 2\n\t\t\t\t}, {\n\t\t\t\t\tkey: \"买占\",\n\t\t\t\t\tkind: \"line\",\n\t\t\t\t\tcolor: \"#3b82f6\",\n\t\t\t\t\tvalues: net.map((value) => value === void 0 ? void 0 : (100 + value) / 2),\n\t\t\t\t\tprecision: 2\n\t\t\t\t}];\n\t\t\t}\n\t\t}\n\t];\n}\n//#endregion\nexport { EMA_COLORS, MA_COLORS, presetDefinitions };\n","import { presetDefinitions } from \"./presets.js\";\n//#region src/chart-activations.ts\n/** 实例形状防御:id 非空字符串 + params 纯有限数字对象(坏形丢弃,SSOT 不收脏数据)。 */\nfunction isValidInstance(raw) {\n\tif (typeof raw !== \"object\" || raw === null) return false;\n\tconst id = raw.id;\n\tconst params = raw.params;\n\tif (typeof id !== \"string\" || id.trim() === \"\") return false;\n\tif (typeof params !== \"object\" || params === null) return false;\n\treturn Object.values(params).every((v) => typeof v === \"number\" && Number.isFinite(v));\n}\n/** 按标的覆盖表防御性清洗(issue #72):非法键/值整体丢弃该字段,不连累实例本体。 */\nfunction sanitizeSymbolParams(raw) {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return void 0;\n\tconst out = {};\n\tfor (const [scope, params] of Object.entries(raw)) {\n\t\tif (scope.trim() === \"\" || typeof params !== \"object\" || params === null || Array.isArray(params)) continue;\n\t\tconst clean = {};\n\t\tfor (const [key, value] of Object.entries(params)) if (typeof value === \"number\" && Number.isFinite(value)) clean[key] = value;\n\t\tif (Object.keys(clean).length > 0) out[scope] = clean;\n\t}\n\treturn Object.keys(out).length > 0 ? out : void 0;\n}\n/** 按标的隐藏表防御性清洗:只留非空字符串并去重;空表返回 undefined(字段整体消失)。 */\nfunction sanitizeHiddenScopes(raw) {\n\tif (!Array.isArray(raw)) return void 0;\n\tconst out = [];\n\tfor (const item of raw) {\n\t\tif (typeof item !== \"string\") continue;\n\t\tconst key = item.trim();\n\t\tif (key !== \"\" && !out.includes(key)) out.push(key);\n\t}\n\treturn out.length > 0 ? out : void 0;\n}\n/**\n* 适用范围防御性清洗:市场键须非空字符串,值须为 { enabled: boolean, intervals: string[] }\n* 形状;级别去空白、去重、丢非字符串。**形状不合格的整个市场条目丢弃**(而不是补默认\n* 值)——否则一条手写/损坏的条目会被读成「该市场未选级别」而静默停用;丢弃后该市场\n* 落回「缺席 = 全部级别应用」,与存量配置同语义。全部条目被丢弃时字段整体消失。\n*/\nfunction sanitizeApplyScope(raw) {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return void 0;\n\tconst out = {};\n\tfor (const [market, value] of Object.entries(raw)) {\n\t\tconst key = market.trim();\n\t\tif (key === \"\" || typeof value !== \"object\" || value === null || Array.isArray(value)) continue;\n\t\tconst scene = value;\n\t\tif (typeof scene.enabled !== \"boolean\" || !Array.isArray(scene.intervals)) continue;\n\t\tconst intervals = [];\n\t\tfor (const item of scene.intervals) {\n\t\t\tif (typeof item !== \"string\") continue;\n\t\t\tconst level = item.trim();\n\t\t\tif (level !== \"\" && !intervals.includes(level)) intervals.push(level);\n\t\t}\n\t\tout[key] = {\n\t\t\tenabled: scene.enabled,\n\t\t\tintervals\n\t\t};\n\t}\n\treturn Object.keys(out).length > 0 ? out : void 0;\n}\n/** 深拷贝规范化一个实例(params/symbolParams/hiddenScopes/applyScope 均脱引用);坏形返回 undefined。 */\nfunction sanitizeInstance(raw) {\n\tif (!isValidInstance(raw)) return void 0;\n\tconst params = { ...raw.params };\n\tconst symbolParams = sanitizeSymbolParams(raw.symbolParams);\n\tconst hiddenScopes = sanitizeHiddenScopes(raw.hiddenScopes);\n\tconst applyScope = sanitizeApplyScope(raw.applyScope);\n\tlet clean = {\n\t\tid: raw.id,\n\t\tparams\n\t};\n\tif (symbolParams !== void 0) clean = {\n\t\t...clean,\n\t\tsymbolParams\n\t};\n\tif (hiddenScopes !== void 0) clean = {\n\t\t...clean,\n\t\thiddenScopes\n\t};\n\tif (applyScope !== void 0) clean = {\n\t\t...clean,\n\t\tapplyScope\n\t};\n\treturn clean;\n}\n/** 按标的覆盖的 scope 键:`${market}:${symbol}`(与 client QuoteStage 的 market/symbol 同源)。 */\nfunction symbolScopeKey(market, symbol) {\n\treturn market + \":\" + symbol;\n}\n/**\n* 实例对某标的的生效参数(issue #72):symbolParams 命中 `${market}:${symbol}`\n* 时整体替代全局 params;market/symbol 缺失或无覆盖 → 全局 params。\n*/\nfunction effectiveInstanceParams(instance, market, symbol) {\n\tif (market !== void 0 && symbol !== void 0 && instance.symbolParams !== void 0) {\n\t\tconst scoped = instance.symbolParams[symbolScopeKey(market, symbol)];\n\t\tif (scoped !== void 0) return scoped;\n\t}\n\treturn instance.params;\n}\n/**\n* 实例对某标的的可见性:hiddenScopes 命中「market」或「${market}:${symbol}」任一\n* 作用域即隐藏;无隐藏记录默认可见(存量名册零迁移)。market 缺失(GUI 无聚焦\n* 标的)按可见处理——调用方此时走全局开关语义。\n*/\nfunction isInstanceVisibleOn(instance, market, symbol) {\n\tconst scopes = instance.hiddenScopes;\n\tif (scopes === void 0 || scopes.length === 0 || market === void 0) return true;\n\tif (scopes.includes(market)) return false;\n\tif (symbol !== void 0 && scopes.includes(symbolScopeKey(market, symbol))) return false;\n\treturn true;\n}\n/**\n* 指标定义在给定市场是否可用(definition.markets 缺席 = 所有市场可用)。\n*\n* 与实例级 isInstanceApplicableOn 正交:本函数管「这个指标在该市场是否该出现」\n* (定义侧白名单,如「港股通持股比例」只对港股有意义),后者管「已挂载实例在当前\n* 市场/级别是否应用」(用户侧设置)。market 缺失(无聚焦标的)不过滤,与\n* isInstanceApplicableOn 同款兜底;markets 空数组按「未限定」解释,**不**等于全禁用\n* ——「全禁用」不是有意义的意图表达,而空数组更可能是清洗后的残形。\n*/\nfunction isDefinitionAvailableOn(definition, market) {\n\tconst markets = definition.markets;\n\tif (markets === void 0 || markets.length === 0 || market === void 0) return true;\n\treturn markets.includes(market);\n}\n/**\n* 纯函数切换实例对一个作用域(「market」或「${market}:${symbol}」)的可见性:\n* visible=false 记隐藏(已记录则原引用返回),visible=true 清隐藏(清空后字段\n* 整体消失;本就无记录则原引用返回)。不触碰 params/symbolParams。\n*/\nfunction withHiddenScopes(instance, scope, visible) {\n\tconst scopes = instance.hiddenScopes ?? [];\n\tif (!visible) return scopes.includes(scope) ? instance : {\n\t\t...instance,\n\t\thiddenScopes: [...scopes, scope]\n\t};\n\tconst next = scopes.filter((key) => key !== scope);\n\tif (next.length === scopes.length) return instance;\n\tif (next.length === 0) {\n\t\tconst rest = { ...instance };\n\t\tdelete rest.hiddenScopes;\n\t\treturn rest;\n\t}\n\treturn {\n\t\t...instance,\n\t\thiddenScopes: next\n\t};\n}\n/**\n* 实例对「某市场 + 某 K 线级别」的适用性(适用范围设置的唯一读侧判据)。\n*\n* - 实例没有该市场条目(含 applyScope 字段整体缺失)→ 适用:新建指标与存量\n* 配置都是「全部市场、全部级别应用」,零迁移。\n* - 条目存在但 `enabled: false` → 不适用(市场关闭;已选级别保留不动)。\n* - 条目存在且启用、`intervals` 为空 → 不适用(「未选择级别」;空选择绝不解释\n* 为全部级别)。\n* - 条目存在且启用、选中级别不含当前级别 → 不适用。\n*\n* market 缺失(GUI 无聚焦标的)按适用处理——调用方此时无市场上下文可判。\n*/\nfunction isInstanceApplicableOn(instance, market, interval) {\n\tif (market === void 0) return true;\n\tconst scene = instance.applyScope?.[market];\n\tif (scene === void 0) return true;\n\tif (!scene.enabled) return false;\n\tif (scene.intervals.length === 0) return false;\n\tif (interval === void 0) return true;\n\treturn scene.intervals.includes(interval);\n}\n/**\n* 纯函数设置某市场的适用范围条目:`scene === undefined` 表示删除该市场条目\n* (落回「缺席 = 全部级别应用」)。条目删空后字段整体消失;市场键保持既有插入序,\n* 新键追加。与既有条目完全一致时返回原引用(不触发无意义持久化)。不触碰\n* params/symbolParams/hiddenScopes。\n*/\nfunction withMarketScope(instance, market, scene) {\n\tconst current = instance.applyScope;\n\tif (scene === void 0) {\n\t\tif (current === void 0 || current[market] === void 0) return instance;\n\t\tconst rest = {};\n\t\tfor (const [key, value] of Object.entries(current)) if (key !== market) rest[key] = value;\n\t\tif (Object.keys(rest).length === 0) {\n\t\t\tconst next = { ...instance };\n\t\t\tdelete next.applyScope;\n\t\t\treturn next;\n\t\t}\n\t\treturn {\n\t\t\t...instance,\n\t\t\tapplyScope: rest\n\t\t};\n\t}\n\tif (current?.[market] !== void 0 && current[market]?.enabled === scene.enabled && current[market]?.intervals.length === scene.intervals.length && scene.intervals.every((level, index) => current[market]?.intervals[index] === level)) return instance;\n\treturn {\n\t\t...instance,\n\t\tapplyScope: {\n\t\t\t...current ?? {},\n\t\t\t[market]: {\n\t\t\t\tenabled: scene.enabled,\n\t\t\t\tintervals: [...scene.intervals]\n\t\t\t}\n\t\t}\n\t};\n}\n/**\n* 全局 params 写的共用保留规则:按标的覆盖表(symbolParams)、隐藏表\n* (hiddenScopes)与适用范围(applyScope)三者都与 params 正交,全局调参一次\n* 不得静默清掉它们。桥、indicator_activate 与 indicator_author 的全局写共用本函数\n*(一个事实只有一个家)。\n*\n* 语义边界:只用于「写全局 params,其它三者保持不动」的写入。按标的覆盖写\n*(clearSymbol 要真的删除覆盖、activate 要真的清该标的隐藏)语义不同,由各写入口\n* 显式构造,不走本函数——否则「清空覆盖」会被继承规则反向补回。\n*/\nfunction carryInstanceExtras(base, next) {\n\tconst merged = { ...next };\n\tif (merged.symbolParams === void 0 && base?.symbolParams !== void 0) merged.symbolParams = base.symbolParams;\n\tif (merged.hiddenScopes === void 0 && base?.hiddenScopes !== void 0) merged.hiddenScopes = base.hiddenScopes;\n\tif (merged.applyScope === void 0 && base?.applyScope !== void 0) merged.applyScope = base.applyScope;\n\treturn merged;\n}\n/**\n* 某市场在适用范围里的「有效选择」(GUI 呈现实值):条目缺席即「全部级别应用」,\n* 返回 enabled=true + 传入的该市场全部支持级别。条目存在则原样返回其选择\n*(选择为空即空——「未选择级别」)。\n*/\nfunction effectiveMarketScope(instance, market, supportedIntervals) {\n\tconst scene = instance.applyScope?.[market];\n\tif (scene === void 0) return {\n\t\tenabled: true,\n\t\tintervals: [...supportedIntervals]\n\t};\n\treturn {\n\t\tenabled: scene.enabled,\n\t\tintervals: [...scene.intervals]\n\t};\n}\n/** 内存版激活名册存储(纯浏览器与单测用)。 */\nfunction createMemoryChartActivationStore(initial = []) {\n\tconst map = /* @__PURE__ */ new Map();\n\tfor (const item of initial) {\n\t\tconst clean = sanitizeInstance(item);\n\t\tif (clean !== void 0) map.set(clean.id, clean);\n\t}\n\treturn {\n\t\tlist: async () => [...map.values()].map((instance) => sanitizeInstance(instance)),\n\t\tactivate: async (instance) => {\n\t\t\tconst clean = sanitizeInstance(instance);\n\t\t\tif (clean === void 0) {\n\t\t\t\tconst id = instance?.id;\n\t\t\t\tthrow new Error(\"chart activation: invalid instance shape for id \" + JSON.stringify(id));\n\t\t\t}\n\t\t\tmap.set(clean.id, clean);\n\t\t},\n\t\tdeactivate: async (id) => map.delete(id),\n\t\treplaceAll: async (instances) => {\n\t\t\tmap.clear();\n\t\t\tfor (const item of instances) {\n\t\t\t\tconst clean = sanitizeInstance(item);\n\t\t\t\tif (clean !== void 0) map.set(clean.id, clean);\n\t\t\t}\n\t\t}\n\t};\n}\n/**\n* 解析指标定义(预置优先,其次自定义 store):未知 id 返回 undefined。\n* 工具与桥的写入边界共用,保证「能挂上图的 id」与「GUI 能渲染的 id」同源。\n*/\nasync function resolveIndicatorSpec(id, customStore) {\n\tconst preset = presetDefinitions().find((d) => d.id === id);\n\tif (preset !== void 0) return {\n\t\tid: preset.id,\n\t\ttitle: preset.title,\n\t\tpane: preset.pane,\n\t\tparams: preset.params,\n\t\t...preset.description !== void 0 ? { description: preset.description } : {},\n\t\t...preset.defaultApplyScope !== void 0 ? { defaultApplyScope: preset.defaultApplyScope } : {}\n\t};\n\tif (customStore !== void 0) {\n\t\tconst record = await customStore.get(id);\n\t\tif (record !== void 0) return {\n\t\t\tid: record.id,\n\t\t\ttitle: record.title,\n\t\t\tpane: record.pane,\n\t\t\tparams: record.params,\n\t\t\t...record.description !== void 0 ? { description: record.description } : {}\n\t\t};\n\t}\n}\n/**\n* 参数按 schema clamp 的**单一实现**(registry.clampParams 与 clampActivationParams 共用):\n* 有限数字 → min/max 收敛 + 取整;缺失/非法 → schema 默认值;schema 外的键丢弃。\n*/\nfunction clampParamsBySpecs(specs, params) {\n\tconst out = {};\n\tfor (const spec of specs) {\n\t\tconst raw = params[spec.key];\n\t\tout[spec.key] = typeof raw === \"number\" && Number.isFinite(raw) ? Math.min(spec.max, Math.max(spec.min, Math.round(raw))) : spec.default;\n\t}\n\treturn out;\n}\n/**\n* 写入边界用的 clamp(host 平面没有注册表实例,故不依赖 registry):规则同上,\n* 多一条 definition 未知(specs 为 undefined)时原样透传有限数字键的分支 —— 预置/\n* 自定义尚未就位的实例仍可落盘,UI 对未知 id 天然不可见。\n*/\nfunction clampActivationParams(specs, params) {\n\tif (specs === void 0) {\n\t\tconst out = {};\n\t\tfor (const [key, value] of Object.entries(params)) if (typeof value === \"number\" && Number.isFinite(value)) out[key] = value;\n\t\treturn out;\n\t}\n\treturn clampParamsBySpecs(specs, params);\n}\n/** 定义侧默认适用范围的脱引用深拷贝(definition 是模块级常量,实例不得与之共享)。 */\nfunction cloneApplyScope(scope) {\n\tconst out = {};\n\tfor (const [market, scene] of Object.entries(scope)) out[market] = {\n\t\tenabled: scene.enabled,\n\t\tintervals: [...scene.intervals]\n\t};\n\treturn out;\n}\n/**\n* 按 schema 生成默认参数实例(definition 缺席 → 空 params,UI 不可见兜底)。\n* 这是「造新实例」的唯一入口:definition 声明了 defaultApplyScope 时随实例落地\n* (决策 7 的默认适用范围由此进入三条创建路径),未声明的指标不长出 applyScope\n* ——存量指标的新实例仍是「全部市场、全部级别应用」,零迁移。\n*/\nfunction defaultActivationInstance(spec) {\n\tconst params = {};\n\tfor (const p of spec.params) params[p.key] = p.default;\n\tconst instance = {\n\t\tid: spec.id,\n\t\tparams\n\t};\n\tif (spec.defaultApplyScope === void 0) return instance;\n\treturn {\n\t\t...instance,\n\t\tapplyScope: cloneApplyScope(spec.defaultApplyScope)\n\t};\n}\n//#endregion\nexport { carryInstanceExtras, clampActivationParams, clampParamsBySpecs, createMemoryChartActivationStore, defaultActivationInstance, effectiveInstanceParams, effectiveMarketScope, isDefinitionAvailableOn, isInstanceApplicableOn, isInstanceVisibleOn, resolveIndicatorSpec, sanitizeApplyScope, sanitizeInstance, symbolScopeKey, withHiddenScopes, withMarketScope };\n","import { clampParamsBySpecs, defaultActivationInstance } from \"./chart-activations.js\";\n//#region src/registry.ts\nfunction createIndicatorRegistry() {\n\tconst registry = /* @__PURE__ */ new Map();\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet version = 0;\n\tconst register = (definition) => {\n\t\tregistry.set(definition.id, definition);\n\t\tversion += 1;\n\t\tfor (const listener of listeners) listener();\n\t};\n\tconst definitionParams = (id) => registry.get(id)?.params ?? [];\n\treturn {\n\t\tregister,\n\t\tunregister(id) {\n\t\t\tif (!registry.delete(id)) return;\n\t\t\tversion += 1;\n\t\t\tfor (const listener of listeners) listener();\n\t\t},\n\t\tget: (id) => registry.get(id),\n\t\tlist: () => [...registry.values()],\n\t\tdefaultParams(definition) {\n\t\t\tconst params = {};\n\t\t\tfor (const spec of definition.params) params[spec.key] = spec.default;\n\t\t\treturn params;\n\t\t},\n\t\tdefaultInstance(id) {\n\t\t\tconst definition = registry.get(id);\n\t\t\tif (definition === void 0) return void 0;\n\t\t\treturn defaultActivationInstance(definition);\n\t\t},\n\t\tinstanceKey(instance) {\n\t\t\tconst values = definitionParams(instance.id).map((spec) => instance.params[spec.key] ?? spec.default);\n\t\t\treturn `${instance.id}:${values.join(\",\")}`;\n\t\t},\n\t\tclampParams(definition, params) {\n\t\t\treturn clampParamsBySpecs(definition.params, params);\n\t\t},\n\t\tsanitizeInstances(instances) {\n\t\t\tif (!Array.isArray(instances)) return [];\n\t\t\tconst seen = /* @__PURE__ */ new Set();\n\t\t\tconst out = [];\n\t\t\tfor (const raw of instances) {\n\t\t\t\tif (typeof raw !== \"object\" || raw === null) continue;\n\t\t\t\tconst { id, params } = raw;\n\t\t\t\tif (typeof id !== \"string\" || seen.has(id)) continue;\n\t\t\t\tconst definition = registry.get(id);\n\t\t\t\tif (definition === void 0) continue;\n\t\t\t\tseen.add(id);\n\t\t\t\tout.push({\n\t\t\t\t\tid,\n\t\t\t\t\tparams: this.clampParams(definition, typeof params === \"object\" && params !== null ? params : {})\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tgetVersion: () => version\n\t};\n}\n//#endregion\nexport { createIndicatorRegistry };\n","/**\n * 预置指标提供插件(client 半):在 client 上下文提供 tradingIndicators\n * 服务 = IndicatorRegistry 单例(注册六个预置指标)。机制先例 =\n * session-controller 的 `reflect.provide('sessions')`(dsh\n * packages/api/session-controller/src/client/sessions/service.ts:263)。\n *\n * 社区指标插件的接入方式:client 半 `ctx.inject(['tradingIndicators'],\n * scope => scope.tradingIndicators.register(definition))` —— 服务可用时\n * 回调才触发,加载顺序由 cordis 依赖解析保证;与本插件零耦合。\n *\n * 消费方 client-ui-trading 以可选依赖桥接(同样 ctx.inject),插件未\n * 安装时行情视图零指标正常工作。\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createIndicatorRegistry, presetDefinitions } from '@dshtrading/indicators'\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n /** dsh-trading 技术指标注册表(社区指标经 ctx.inject 消费后 register)。 */\n tradingIndicators: import('@dshtrading/indicators').IndicatorRegistry\n }\n}\n\nexport function apply(ctx: Context): void {\n const registry = createIndicatorRegistry()\n for (const definition of presetDefinitions()) registry.register(definition)\n // provide 由插件 fiber 持有:插件卸载/重载时服务随之注销/重建。\n ctx.reflect.provide('tradingIndicators', registry)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dshtrading/client-ui-indicators",
|
|
3
3
|
"description": "Technical indicator provider plugin for dsh-trading: provides the tradingIndicators service (IndicatorRegistry with six presets MA/EMA/BOLL/MACD/RSI/KDJ) on the client context. Community indicators consume the same service via ctx.inject. Node half is a host loader placeholder; the browser half owns the service.",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"default": "./lib/index.js"
|
|
12
12
|
},
|
|
13
13
|
"./client": {
|
|
14
|
-
"types": "./lib/types/client/index.d.ts",
|
|
15
14
|
"default": "./lib/client.js"
|
|
16
15
|
},
|
|
17
16
|
"./package.json": "./package.json"
|
|
@@ -21,7 +20,7 @@
|
|
|
21
20
|
],
|
|
22
21
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
23
22
|
"dependencies": {
|
|
24
|
-
"@dshtrading/indicators": "^0.6.
|
|
23
|
+
"@dshtrading/indicators": "^0.6.2"
|
|
25
24
|
},
|
|
26
25
|
"peerDependencies": {
|
|
27
26
|
"@deepseek-ai/cordis": ">=4.0.0"
|