@continuumdao/continuum-node-sdk 1.3.23 → 1.3.24
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/dist/core/chart/apply-chart-drawings.d.ts +25 -0
- package/dist/core/chart/apply-chart-drawings.d.ts.map +1 -0
- package/dist/core/chart/apply-chart-drawings.js +82 -0
- package/dist/core/chart/apply-chart-drawings.js.map +1 -0
- package/dist/core/chart/customization-catalog.d.ts +29 -0
- package/dist/core/chart/customization-catalog.d.ts.map +1 -0
- package/dist/core/chart/customization-catalog.js +61 -0
- package/dist/core/chart/customization-catalog.js.map +1 -0
- package/dist/core/chart/day-range.d.ts +14 -0
- package/dist/core/chart/day-range.d.ts.map +1 -0
- package/dist/core/chart/day-range.js +72 -0
- package/dist/core/chart/day-range.js.map +1 -0
- package/dist/core/chart/levels/calculate-tools.d.ts +53 -0
- package/dist/core/chart/levels/calculate-tools.d.ts.map +1 -0
- package/dist/core/chart/levels/calculate-tools.js +96 -0
- package/dist/core/chart/levels/calculate-tools.js.map +1 -0
- package/dist/core/chart/levels/key-levels.d.ts +20 -0
- package/dist/core/chart/levels/key-levels.d.ts.map +1 -0
- package/dist/core/chart/levels/key-levels.js +133 -0
- package/dist/core/chart/levels/key-levels.js.map +1 -0
- package/dist/core/chart/levels/pivot-points.d.ts +16 -0
- package/dist/core/chart/levels/pivot-points.d.ts.map +1 -0
- package/dist/core/chart/levels/pivot-points.js +47 -0
- package/dist/core/chart/levels/pivot-points.js.map +1 -0
- package/dist/core/chart/live/refresh.d.ts +4 -2
- package/dist/core/chart/live/refresh.d.ts.map +1 -1
- package/dist/core/chart/live/refresh.js +6 -3
- package/dist/core/chart/live/refresh.js.map +1 -1
- package/dist/core/chart/overlay-schemas.d.ts +258 -0
- package/dist/core/chart/overlay-schemas.d.ts.map +1 -1
- package/dist/core/chart/overlay-schemas.js +46 -1
- package/dist/core/chart/overlay-schemas.js.map +1 -1
- package/dist/core/chart/overlays.d.ts.map +1 -1
- package/dist/core/chart/overlays.js +96 -4
- package/dist/core/chart/overlays.js.map +1 -1
- package/dist/core/chart/prepare-from-rows.d.ts +183 -0
- package/dist/core/chart/prepare-from-rows.d.ts.map +1 -1
- package/dist/core/chart/prepare-replay.d.ts +6 -0
- package/dist/core/chart/prepare-replay.d.ts.map +1 -0
- package/dist/core/chart/prepare-replay.js +60 -0
- package/dist/core/chart/prepare-replay.js.map +1 -0
- package/dist/core/chart/prepare.d.ts.map +1 -1
- package/dist/core/chart/prepare.js +16 -5
- package/dist/core/chart/prepare.js.map +1 -1
- package/dist/core/chart/schemas.d.ts +512 -1
- package/dist/core/chart/schemas.d.ts.map +1 -1
- package/dist/core/chart/schemas.js +11 -2
- package/dist/core/chart/schemas.js.map +1 -1
- package/dist/mcp/chart.d.ts.map +1 -1
- package/dist/mcp/chart.js +64 -1
- package/dist/mcp/chart.js.map +1 -1
- package/dist/mcp/resources/chart.md +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SdkResult } from '../result.js';
|
|
2
|
+
import type { ChartOverlayInput } from './overlay-schemas.js';
|
|
3
|
+
import type { ChartPrepareReplay, PrepareChartOutput } from './schemas.js';
|
|
4
|
+
export type ApplyChartDrawingsInput = {
|
|
5
|
+
title?: string;
|
|
6
|
+
toolResult?: unknown;
|
|
7
|
+
rows?: unknown[];
|
|
8
|
+
prepareReplay?: ChartPrepareReplay;
|
|
9
|
+
horizontalLevels?: Array<{
|
|
10
|
+
price: number;
|
|
11
|
+
label?: string;
|
|
12
|
+
kind?: 'support' | 'resistance' | 'level';
|
|
13
|
+
}>;
|
|
14
|
+
pivotLevels?: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
price: number;
|
|
17
|
+
}>;
|
|
18
|
+
fibonacci?: Extract<ChartOverlayInput, {
|
|
19
|
+
type: 'fibonacci';
|
|
20
|
+
}>;
|
|
21
|
+
removeDrawings?: boolean;
|
|
22
|
+
};
|
|
23
|
+
/** Re-prepare chart with drawing overlays merged into prepareReplay. */
|
|
24
|
+
export declare function applyChartDrawings(input: ApplyChartDrawingsInput): SdkResult<PrepareChartOutput>;
|
|
25
|
+
//# sourceMappingURL=apply-chart-drawings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-chart-drawings.d.ts","sourceRoot":"","sources":["../../../src/core/chart/apply-chart-drawings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAI5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAC,kBAAkB,EAAE,kBAAkB,EAAC,MAAM,cAAc,CAAC;AAEzE,MAAM,MAAM,uBAAuB,GAAG;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,OAAO,CAAA;KAAC,CAAC,CAAC;IACrG,WAAW,CAAC,EAAE,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE;QAAC,IAAI,EAAE,WAAW,CAAA;KAAC,CAAC,CAAC;IAC5D,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AA0CF,wEAAwE;AACxE,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,uBAAuB,GAC5B,SAAS,CAAC,kBAAkB,CAAC,CAoD/B"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { extractOhlcvBarsFromUnknown } from './fetch-result.js';
|
|
2
|
+
import { prepareChartFromRows } from './prepare-from-rows.js';
|
|
3
|
+
import { prepareChart } from './prepare.js';
|
|
4
|
+
function barsFromInput(input) {
|
|
5
|
+
if (input.rows?.length) {
|
|
6
|
+
return input.rows;
|
|
7
|
+
}
|
|
8
|
+
if (input.toolResult != null) {
|
|
9
|
+
return (extractOhlcvBarsFromUnknown(input.toolResult) ?? []);
|
|
10
|
+
}
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
function drawingOverlaysFromInput(input) {
|
|
14
|
+
if (input.removeDrawings) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const out = [];
|
|
18
|
+
if (input.horizontalLevels?.length) {
|
|
19
|
+
out.push({ type: 'horizontal_levels', levels: input.horizontalLevels });
|
|
20
|
+
}
|
|
21
|
+
if (input.pivotLevels?.length) {
|
|
22
|
+
out.push({ type: 'pivot_levels', levels: input.pivotLevels });
|
|
23
|
+
}
|
|
24
|
+
if (input.fibonacci) {
|
|
25
|
+
out.push(input.fibonacci);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function stripDrawingOverlays(replay) {
|
|
30
|
+
if (!replay.overlays?.length) {
|
|
31
|
+
return replay;
|
|
32
|
+
}
|
|
33
|
+
const kept = replay.overlays.filter(o => o.type !== 'horizontal_levels' &&
|
|
34
|
+
o.type !== 'pivot_levels' &&
|
|
35
|
+
o.type !== 'fibonacci');
|
|
36
|
+
return { ...replay, overlays: kept };
|
|
37
|
+
}
|
|
38
|
+
/** Re-prepare chart with drawing overlays merged into prepareReplay. */
|
|
39
|
+
export function applyChartDrawings(input) {
|
|
40
|
+
const bars = barsFromInput(input);
|
|
41
|
+
if (!bars.length) {
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
reason: 'Provide `rows` or `toolResult` with OHLCV bars to apply chart drawings.',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const title = input.title?.trim() || 'Chart';
|
|
48
|
+
const newDrawings = drawingOverlaysFromInput(input);
|
|
49
|
+
let baseReplay = input.prepareReplay ?? {};
|
|
50
|
+
if (input.removeDrawings) {
|
|
51
|
+
baseReplay = stripDrawingOverlays(baseReplay);
|
|
52
|
+
}
|
|
53
|
+
const indicatorOverlays = baseReplay.overlays?.filter(o => o.type !== 'horizontal_levels' &&
|
|
54
|
+
o.type !== 'pivot_levels' &&
|
|
55
|
+
o.type !== 'fibonacci') ?? [];
|
|
56
|
+
const mergedOverlays = [...indicatorOverlays, ...newDrawings];
|
|
57
|
+
if (input.toolResult != null) {
|
|
58
|
+
const fromRows = prepareChartFromRows({
|
|
59
|
+
title,
|
|
60
|
+
toolResult: input.toolResult,
|
|
61
|
+
});
|
|
62
|
+
if (!fromRows.ok) {
|
|
63
|
+
return fromRows;
|
|
64
|
+
}
|
|
65
|
+
if (!mergedOverlays.length && !baseReplay.skipDefaultOverlays) {
|
|
66
|
+
return fromRows;
|
|
67
|
+
}
|
|
68
|
+
return prepareChart({
|
|
69
|
+
title,
|
|
70
|
+
bars,
|
|
71
|
+
overlays: mergedOverlays.length ? mergedOverlays : [],
|
|
72
|
+
...(baseReplay.skipDefaultOverlays ? { options: { skipDefaultOverlays: true } } : {}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return prepareChart({
|
|
76
|
+
title,
|
|
77
|
+
bars,
|
|
78
|
+
...(mergedOverlays.length ? { overlays: mergedOverlays } : {}),
|
|
79
|
+
...(baseReplay.skipDefaultOverlays ? { options: { skipDefaultOverlays: true } } : {}),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=apply-chart-drawings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-chart-drawings.js","sourceRoot":"","sources":["../../../src/core/chart/apply-chart-drawings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ChartOverlayInput } from './overlay-schemas.js';
|
|
2
|
+
export type ChartCustomizationCatalog = {
|
|
3
|
+
indicators: Array<{
|
|
4
|
+
type: string;
|
|
5
|
+
label: string;
|
|
6
|
+
pane: 'main' | 'oscillator';
|
|
7
|
+
params: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
default?: number | string;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
12
|
+
drawings: Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
calculateTool: string;
|
|
16
|
+
applyField: string;
|
|
17
|
+
}>;
|
|
18
|
+
removeActions: string[];
|
|
19
|
+
currentDefaults: {
|
|
20
|
+
emaPeriod: number;
|
|
21
|
+
rsiPeriod: number;
|
|
22
|
+
};
|
|
23
|
+
exampleUserPhrases: string[];
|
|
24
|
+
};
|
|
25
|
+
export declare function listChartCustomizationOptions(): ChartCustomizationCatalog;
|
|
26
|
+
export type ChartDrawingInput = Extract<ChartOverlayInput, {
|
|
27
|
+
type: 'horizontal_levels' | 'pivot_levels' | 'fibonacci';
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=customization-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customization-catalog.d.ts","sourceRoot":"","sources":["../../../src/core/chart/customization-catalog.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAE5D,MAAM,MAAM,yBAAyB,GAAG;IACvC,UAAU,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;QAC5B,MAAM,EAAE,KAAK,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;SAAC,CAAC,CAAC;KACzD,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,CAAC;IACxD,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,wBAAgB,6BAA6B,IAAI,yBAAyB,CA0DzE;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CACtC,iBAAiB,EACjB;IAAC,IAAI,EAAE,mBAAmB,GAAG,cAAc,GAAG,WAAW,CAAA;CAAC,CAC1D,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DEFAULT_CHART_EMA_PERIOD, DEFAULT_CHART_RSI_PERIOD, } from './chart-defaults.js';
|
|
2
|
+
export function listChartCustomizationOptions() {
|
|
3
|
+
return {
|
|
4
|
+
indicators: [
|
|
5
|
+
{ type: 'sma', label: 'Simple moving average', pane: 'main', params: [{ name: 'period', default: 20 }] },
|
|
6
|
+
{ type: 'ema', label: 'Exponential moving average', pane: 'main', params: [{ name: 'period', default: 20 }] },
|
|
7
|
+
{
|
|
8
|
+
type: 'bollinger',
|
|
9
|
+
label: 'Bollinger bands',
|
|
10
|
+
pane: 'main',
|
|
11
|
+
params: [
|
|
12
|
+
{ name: 'period', default: 20 },
|
|
13
|
+
{ name: 'stdDev', default: 2 },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
{ type: 'fibonacci', label: 'Fibonacci retracements', pane: 'main', params: [{ name: 'range or sourceSeriesId' }] },
|
|
17
|
+
{ type: 'rsi', label: 'RSI', pane: 'oscillator', params: [{ name: 'period', default: 14 }] },
|
|
18
|
+
{ type: 'macd', label: 'MACD', pane: 'oscillator', params: [] },
|
|
19
|
+
{ type: 'stochasticrsi', label: 'Stochastic RSI', pane: 'oscillator', params: [] },
|
|
20
|
+
],
|
|
21
|
+
drawings: [
|
|
22
|
+
{
|
|
23
|
+
id: 'key_levels',
|
|
24
|
+
label: 'Key support/resistance (swing levels)',
|
|
25
|
+
calculateTool: 'calculate_key_levels',
|
|
26
|
+
applyField: 'horizontalLevels',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'pivot_points',
|
|
30
|
+
label: 'Pivot points (PP, R1, S1, …)',
|
|
31
|
+
calculateTool: 'calculate_pivot_points',
|
|
32
|
+
applyField: 'pivotLevels',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'fibonacci',
|
|
36
|
+
label: 'Fibonacci retracements (61.8% highlighted)',
|
|
37
|
+
calculateTool: 'calculate_fibonacci_range',
|
|
38
|
+
applyField: 'fibonacci',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
removeActions: [
|
|
42
|
+
'Remove all indicators (candles + volume only)',
|
|
43
|
+
'Remove drawing overlays (levels, pivots, Fibonacci lines)',
|
|
44
|
+
'Replace indicator set (pass full overlays array to prepare_chart)',
|
|
45
|
+
],
|
|
46
|
+
currentDefaults: {
|
|
47
|
+
emaPeriod: DEFAULT_CHART_EMA_PERIOD,
|
|
48
|
+
rsiPeriod: DEFAULT_CHART_RSI_PERIOD,
|
|
49
|
+
},
|
|
50
|
+
exampleUserPhrases: [
|
|
51
|
+
'what can I do to this chart',
|
|
52
|
+
'chart options',
|
|
53
|
+
'what indicators can you add',
|
|
54
|
+
'help with the chart',
|
|
55
|
+
'show me support and resistance',
|
|
56
|
+
'add pivot points',
|
|
57
|
+
'draw fibonacci',
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=customization-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customization-catalog.js","sourceRoot":"","sources":["../../../src/core/chart/customization-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GACxB,MAAM,qBAAqB,CAAC;AAqB7B,MAAM,UAAU,6BAA6B;IAC5C,OAAO;QACN,UAAU,EAAE;YACX,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAC,CAAC,EAAC;YACpG,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAC,CAAC,EAAC;YACzG;gBACC,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,iBAAiB;gBACxB,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE;oBACP,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAC;oBAC7B,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAC;iBAC5B;aACD;YACD,EAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,wBAAwB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAC,IAAI,EAAE,yBAAyB,EAAC,CAAC,EAAC;YAC/G,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAC,CAAC,EAAC;YACxF,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAC;YAC7D,EAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAC;SAChF;QACD,QAAQ,EAAE;YACT;gBACC,EAAE,EAAE,YAAY;gBAChB,KAAK,EAAE,uCAAuC;gBAC9C,aAAa,EAAE,sBAAsB;gBACrC,UAAU,EAAE,kBAAkB;aAC9B;YACD;gBACC,EAAE,EAAE,cAAc;gBAClB,KAAK,EAAE,8BAA8B;gBACrC,aAAa,EAAE,wBAAwB;gBACvC,UAAU,EAAE,aAAa;aACzB;YACD;gBACC,EAAE,EAAE,WAAW;gBACf,KAAK,EAAE,4CAA4C;gBACnD,aAAa,EAAE,2BAA2B;gBAC1C,UAAU,EAAE,WAAW;aACvB;SACD;QACD,aAAa,EAAE;YACd,+CAA+C;YAC/C,2DAA2D;YAC3D,mEAAmE;SACnE;QACD,eAAe,EAAE;YAChB,SAAS,EAAE,wBAAwB;YACnC,SAAS,EAAE,wBAAwB;SACnC;QACD,kBAAkB,EAAE;YACnB,6BAA6B;YAC7B,eAAe;YACf,6BAA6B;YAC7B,qBAAqB;YACrB,gCAAgC;YAChC,kBAAkB;YAClB,gBAAgB;SAChB;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DayHighLow = {
|
|
2
|
+
dayHigh: number;
|
|
3
|
+
dayLow: number;
|
|
4
|
+
dayLabelUtc: string;
|
|
5
|
+
barCount: number;
|
|
6
|
+
};
|
|
7
|
+
/** UTC calendar-day high/low for the day containing the latest candlestick bar. */
|
|
8
|
+
export declare function computeDayHighLowFromBars(bars: Record<string, unknown>[]): DayHighLow | null;
|
|
9
|
+
/** From a prepared chart's primary candlestick series rows. */
|
|
10
|
+
export declare function computeDayHighLowFromCandlestickSeries(series: Array<{
|
|
11
|
+
type: string;
|
|
12
|
+
data: Record<string, unknown>[];
|
|
13
|
+
}>): DayHighLow | null;
|
|
14
|
+
//# sourceMappingURL=day-range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"day-range.d.ts","sourceRoot":"","sources":["../../../src/core/chart/day-range.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AAoBF,mFAAmF;AACnF,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAC7B,UAAU,GAAG,IAAI,CAgDnB;AAED,+DAA+D;AAC/D,wBAAgB,sCAAsC,CACrD,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;CAAC,CAAC,GAC5D,UAAU,GAAG,IAAI,CAMnB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { coerceFiniteNumber, parseChartTimeFromRow } from './point-normalize.js';
|
|
2
|
+
function timeToUtcSec(time) {
|
|
3
|
+
if (typeof time === 'number') {
|
|
4
|
+
return time;
|
|
5
|
+
}
|
|
6
|
+
return Math.floor(Date.UTC(time.year, time.month - 1, time.day) / 1000);
|
|
7
|
+
}
|
|
8
|
+
function utcDayBoundsFromSec(sec) {
|
|
9
|
+
const d = new Date(sec * 1000);
|
|
10
|
+
const y = d.getUTCFullYear();
|
|
11
|
+
const m = d.getUTCMonth();
|
|
12
|
+
const day = d.getUTCDate();
|
|
13
|
+
const startSec = Math.floor(Date.UTC(y, m, day) / 1000);
|
|
14
|
+
const endSec = startSec + 86_400;
|
|
15
|
+
const label = `${y}-${String(m + 1).padStart(2, '0')}-${String(day).padStart(2, '0')} UTC`;
|
|
16
|
+
return { startSec, endSec, label };
|
|
17
|
+
}
|
|
18
|
+
/** UTC calendar-day high/low for the day containing the latest candlestick bar. */
|
|
19
|
+
export function computeDayHighLowFromBars(bars) {
|
|
20
|
+
if (!bars.length) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
let latestSec = null;
|
|
24
|
+
for (const bar of bars) {
|
|
25
|
+
const time = parseChartTimeFromRow(bar);
|
|
26
|
+
if (time == null) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const sec = timeToUtcSec(time);
|
|
30
|
+
if (sec != null && (latestSec == null || sec > latestSec)) {
|
|
31
|
+
latestSec = sec;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (latestSec == null) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const { startSec, endSec, label } = utcDayBoundsFromSec(latestSec);
|
|
38
|
+
let dayHigh = Number.NEGATIVE_INFINITY;
|
|
39
|
+
let dayLow = Number.POSITIVE_INFINITY;
|
|
40
|
+
let barCount = 0;
|
|
41
|
+
for (const bar of bars) {
|
|
42
|
+
const time = parseChartTimeFromRow(bar);
|
|
43
|
+
if (time == null) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const sec = timeToUtcSec(time);
|
|
47
|
+
if (sec == null || sec < startSec || sec >= endSec) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const high = coerceFiniteNumber(bar.high);
|
|
51
|
+
const low = coerceFiniteNumber(bar.low);
|
|
52
|
+
if (high == null || low == null) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
dayHigh = Math.max(dayHigh, high);
|
|
56
|
+
dayLow = Math.min(dayLow, low);
|
|
57
|
+
barCount++;
|
|
58
|
+
}
|
|
59
|
+
if (barCount === 0 || !Number.isFinite(dayHigh) || !Number.isFinite(dayLow)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return { dayHigh, dayLow, dayLabelUtc: label, barCount };
|
|
63
|
+
}
|
|
64
|
+
/** From a prepared chart's primary candlestick series rows. */
|
|
65
|
+
export function computeDayHighLowFromCandlestickSeries(series) {
|
|
66
|
+
const candle = series.find(s => s.type === 'candlestick');
|
|
67
|
+
if (!candle?.data.length) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return computeDayHighLowFromBars(candle.data);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=day-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"day-range.js","sourceRoot":"","sources":["../../../src/core/chart/day-range.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { SdkResult } from '../../result.js';
|
|
3
|
+
export declare const CalculateKeyLevelsInputSchema: z.ZodObject<{
|
|
4
|
+
toolResult: z.ZodOptional<z.ZodUnknown>;
|
|
5
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
6
|
+
lookback: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
tolerancePct: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
maxLevels: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export declare const CalculateKeyLevelsOutputSchema: z.ZodObject<{
|
|
11
|
+
levels: z.ZodArray<z.ZodObject<{
|
|
12
|
+
price: z.ZodNumber;
|
|
13
|
+
kind: z.ZodEnum<{
|
|
14
|
+
support: "support";
|
|
15
|
+
resistance: "resistance";
|
|
16
|
+
}>;
|
|
17
|
+
strength: z.ZodNumber;
|
|
18
|
+
touchCount: z.ZodNumber;
|
|
19
|
+
}, z.core.$strict>>;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
export declare function calculateKeyLevels(input: unknown): SdkResult<z.infer<typeof CalculateKeyLevelsOutputSchema>>;
|
|
22
|
+
export declare const CalculatePivotPointsInputSchema: z.ZodObject<{
|
|
23
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
24
|
+
toolResult: z.ZodOptional<z.ZodUnknown>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export declare const CalculatePivotPointsOutputSchema: z.ZodObject<{
|
|
27
|
+
pivots: z.ZodArray<z.ZodObject<{
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
price: z.ZodNumber;
|
|
30
|
+
}, z.core.$strict>>;
|
|
31
|
+
sourceBar: z.ZodObject<{
|
|
32
|
+
high: z.ZodNumber;
|
|
33
|
+
low: z.ZodNumber;
|
|
34
|
+
close: z.ZodNumber;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
}, z.core.$strict>;
|
|
37
|
+
export declare function calculatePivotPoints(input: unknown): SdkResult<z.infer<typeof CalculatePivotPointsOutputSchema>>;
|
|
38
|
+
export declare const CalculateFibonacciRangeInputSchema: z.ZodObject<{
|
|
39
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
40
|
+
toolResult: z.ZodOptional<z.ZodUnknown>;
|
|
41
|
+
}, z.core.$strict>;
|
|
42
|
+
export declare const CalculateFibonacciRangeOutputSchema: z.ZodObject<{
|
|
43
|
+
range: z.ZodObject<{
|
|
44
|
+
high: z.ZodNumber;
|
|
45
|
+
low: z.ZodNumber;
|
|
46
|
+
trend: z.ZodEnum<{
|
|
47
|
+
up: "up";
|
|
48
|
+
down: "down";
|
|
49
|
+
}>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
}, z.core.$strict>;
|
|
52
|
+
export declare function calculateFibonacciRange(input: unknown): SdkResult<z.infer<typeof CalculateFibonacciRangeOutputSchema>>;
|
|
53
|
+
//# sourceMappingURL=calculate-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calculate-tools.d.ts","sourceRoot":"","sources":["../../../../src/core/chart/levels/calculate-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AA4B/C,eAAO,MAAM,6BAA6B;;;;;;kBAAkB,CAAC;AAC7D,eAAO,MAAM,8BAA8B;;;;;;;;;;kBAajC,CAAC;AAEX,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAW5G;AAED,eAAO,MAAM,+BAA+B;;;kBAI1C,CAAC;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;;kBAKnC,CAAC;AAEX,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,OAAO,GACZ,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC,CAO7D;AAED,eAAO,MAAM,kCAAkC;;;kBAI7C,CAAC;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;kBAQtC,CAAC;AAEX,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,OAAO,GACZ,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC,CAchE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { extractOhlcvBarsFromUnknown } from '../fetch-result.js';
|
|
3
|
+
import { calculateFibonacciRangeFromBars, calculateKeyLevelsFromBars } from './key-levels.js';
|
|
4
|
+
import { calculatePivotPointsFromBars } from './pivot-points.js';
|
|
5
|
+
const barsInputSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
toolResult: z.unknown().optional(),
|
|
8
|
+
rows: z.array(z.unknown()).min(1).optional(),
|
|
9
|
+
lookback: z.number().int().min(2).max(20).optional(),
|
|
10
|
+
tolerancePct: z.number().positive().max(0.05).optional(),
|
|
11
|
+
maxLevels: z.number().int().min(1).max(12).optional(),
|
|
12
|
+
})
|
|
13
|
+
.strict();
|
|
14
|
+
function barsFromToolInput(input) {
|
|
15
|
+
if (input.rows?.length) {
|
|
16
|
+
return input.rows;
|
|
17
|
+
}
|
|
18
|
+
if (input.toolResult != null) {
|
|
19
|
+
return (extractOhlcvBarsFromUnknown(input.toolResult) ?? []);
|
|
20
|
+
}
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
export const CalculateKeyLevelsInputSchema = barsInputSchema;
|
|
24
|
+
export const CalculateKeyLevelsOutputSchema = z
|
|
25
|
+
.object({
|
|
26
|
+
levels: z.array(z
|
|
27
|
+
.object({
|
|
28
|
+
price: z.number(),
|
|
29
|
+
kind: z.enum(['support', 'resistance']),
|
|
30
|
+
strength: z.number(),
|
|
31
|
+
touchCount: z.number(),
|
|
32
|
+
})
|
|
33
|
+
.strict()),
|
|
34
|
+
})
|
|
35
|
+
.strict();
|
|
36
|
+
export function calculateKeyLevels(input) {
|
|
37
|
+
const parsed = CalculateKeyLevelsInputSchema.safeParse(input);
|
|
38
|
+
if (!parsed.success) {
|
|
39
|
+
return { ok: false, reason: parsed.error.message };
|
|
40
|
+
}
|
|
41
|
+
const bars = barsFromToolInput(parsed.data);
|
|
42
|
+
if (!bars.length) {
|
|
43
|
+
return { ok: false, reason: 'No OHLCV bars in toolResult or rows.' };
|
|
44
|
+
}
|
|
45
|
+
const levels = calculateKeyLevelsFromBars(bars, parsed.data);
|
|
46
|
+
return { ok: true, data: { levels } };
|
|
47
|
+
}
|
|
48
|
+
export const CalculatePivotPointsInputSchema = barsInputSchema.omit({
|
|
49
|
+
lookback: true,
|
|
50
|
+
tolerancePct: true,
|
|
51
|
+
maxLevels: true,
|
|
52
|
+
});
|
|
53
|
+
export const CalculatePivotPointsOutputSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
pivots: z.array(z.object({ id: z.string(), price: z.number() }).strict()),
|
|
56
|
+
sourceBar: z.object({ high: z.number(), low: z.number(), close: z.number() }).strict(),
|
|
57
|
+
})
|
|
58
|
+
.strict();
|
|
59
|
+
export function calculatePivotPoints(input) {
|
|
60
|
+
const parsed = CalculatePivotPointsInputSchema.safeParse(input);
|
|
61
|
+
if (!parsed.success) {
|
|
62
|
+
return { ok: false, reason: parsed.error.message };
|
|
63
|
+
}
|
|
64
|
+
const bars = barsFromToolInput(parsed.data);
|
|
65
|
+
return calculatePivotPointsFromBars(bars);
|
|
66
|
+
}
|
|
67
|
+
export const CalculateFibonacciRangeInputSchema = barsInputSchema.omit({
|
|
68
|
+
lookback: true,
|
|
69
|
+
tolerancePct: true,
|
|
70
|
+
maxLevels: true,
|
|
71
|
+
});
|
|
72
|
+
export const CalculateFibonacciRangeOutputSchema = z
|
|
73
|
+
.object({
|
|
74
|
+
range: z.object({
|
|
75
|
+
high: z.number(),
|
|
76
|
+
low: z.number(),
|
|
77
|
+
trend: z.enum(['up', 'down']),
|
|
78
|
+
}),
|
|
79
|
+
})
|
|
80
|
+
.strict();
|
|
81
|
+
export function calculateFibonacciRange(input) {
|
|
82
|
+
const parsed = CalculateFibonacciRangeInputSchema.safeParse(input);
|
|
83
|
+
if (!parsed.success) {
|
|
84
|
+
return { ok: false, reason: parsed.error.message };
|
|
85
|
+
}
|
|
86
|
+
const bars = barsFromToolInput(parsed.data);
|
|
87
|
+
if (!bars.length) {
|
|
88
|
+
return { ok: false, reason: 'No OHLCV bars in toolResult or rows.' };
|
|
89
|
+
}
|
|
90
|
+
const range = calculateFibonacciRangeFromBars(bars);
|
|
91
|
+
if (!range) {
|
|
92
|
+
return { ok: false, reason: 'Could not detect a swing range for Fibonacci.' };
|
|
93
|
+
}
|
|
94
|
+
return { ok: true, data: { range } };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=calculate-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calculate-tools.js","sourceRoot":"","sources":["../../../../src/core/chart/levels/calculate-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAC,2BAA2B,EAAC,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAC,+BAA+B,EAAE,0BAA0B,EAAC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAC,4BAA4B,EAAC,MAAM,mBAAmB,CAAC;AAE/D,MAAM,eAAe,GAAG,CAAC;KACvB,MAAM,CAAC;IACP,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACxD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrD,CAAC;KACD,MAAM,EAAE,CAAC;AAEX,SAAS,iBAAiB,CAAC,KAG1B;IACA,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC,IAAiC,CAAC;IAChD,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;QAC9B,OAAO,CAAC,2BAA2B,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAA8B,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,eAAe,CAAC;AAC7D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC;KAC7C,MAAM,CAAC;IACP,MAAM,EAAE,CAAC,CAAC,KAAK,CACd,CAAC;SACC,MAAM,CAAC;QACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB,CAAC;SACD,MAAM,EAAE,CACV;CACD,CAAC;KACD,MAAM,EAAE,CAAC;AAEX,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAChD,MAAM,MAAM,GAAG,6BAA6B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sCAAsC,EAAC,CAAC;IACpE,CAAC;IACD,MAAM,MAAM,GAAG,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAC,MAAM,EAAC,EAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,+BAA+B,GAAG,eAAe,CAAC,IAAI,CAAC;IACnE,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,IAAI;CACf,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC;KAC/C,MAAM,CAAC;IACP,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACvE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAC,CAAC,CAAC,MAAM,EAAE;CACpF,CAAC;KACD,MAAM,EAAE,CAAC;AAEX,MAAM,UAAU,oBAAoB,CACnC,KAAc;IAEd,MAAM,MAAM,GAAG,+BAA+B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,4BAA4B,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,MAAM,kCAAkC,GAAG,eAAe,CAAC,IAAI,CAAC;IACtE,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,IAAI;CACf,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC;KAClD,MAAM,CAAC;IACP,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;QACf,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;KAC7B,CAAC;CACF,CAAC;KACD,MAAM,EAAE,CAAC;AAEX,MAAM,UAAU,uBAAuB,CACtC,KAAc;IAEd,MAAM,MAAM,GAAG,kCAAkC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sCAAsC,EAAC,CAAC;IACpE,CAAC;IACD,MAAM,KAAK,GAAG,+BAA+B,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,+CAA+C,EAAC,CAAC;IAC7E,CAAC;IACD,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAC,KAAK,EAAC,EAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type KeyLevel = {
|
|
2
|
+
price: number;
|
|
3
|
+
kind: 'support' | 'resistance';
|
|
4
|
+
strength: number;
|
|
5
|
+
touchCount: number;
|
|
6
|
+
};
|
|
7
|
+
export type CalculateKeyLevelsOptions = {
|
|
8
|
+
lookback?: number;
|
|
9
|
+
tolerancePct?: number;
|
|
10
|
+
maxLevels?: number;
|
|
11
|
+
};
|
|
12
|
+
/** Swing-based support/resistance levels from OHLCV bars. */
|
|
13
|
+
export declare function calculateKeyLevelsFromBars(bars: Record<string, unknown>[], options?: CalculateKeyLevelsOptions): KeyLevel[];
|
|
14
|
+
/** Dominant swing high/low for Fibonacci anchor. */
|
|
15
|
+
export declare function calculateFibonacciRangeFromBars(bars: Record<string, unknown>[]): {
|
|
16
|
+
high: number;
|
|
17
|
+
low: number;
|
|
18
|
+
trend: 'up' | 'down';
|
|
19
|
+
} | null;
|
|
20
|
+
//# sourceMappingURL=key-levels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-levels.d.ts","sourceRoot":"","sources":["../../../../src/core/chart/levels/key-levels.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,YAAY,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAmDF,6DAA6D;AAC7D,wBAAgB,0BAA0B,CACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,OAAO,GAAE,yBAA8B,GACrC,QAAQ,EAAE,CAsDZ;AAED,oDAAoD;AACpD,wBAAgB,+BAA+B,CAC9C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAC7B;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;CAAC,GAAG,IAAI,CAsC1D"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { coerceFiniteNumber, parseChartTimeFromRow } from '../point-normalize.js';
|
|
2
|
+
function barTimeSec(row) {
|
|
3
|
+
const time = parseChartTimeFromRow(row);
|
|
4
|
+
if (time == null) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
if (typeof time === 'number') {
|
|
8
|
+
return time;
|
|
9
|
+
}
|
|
10
|
+
return Math.floor(Date.UTC(time.year, time.month - 1, time.day) / 1000);
|
|
11
|
+
}
|
|
12
|
+
function detectSwings(bars, lookback) {
|
|
13
|
+
const swings = [];
|
|
14
|
+
for (let i = lookback; i < bars.length - lookback; i++) {
|
|
15
|
+
const high = coerceFiniteNumber(bars[i].high);
|
|
16
|
+
const low = coerceFiniteNumber(bars[i].low);
|
|
17
|
+
const t = barTimeSec(bars[i]);
|
|
18
|
+
if (high == null || low == null || t == null) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
let isHigh = true;
|
|
22
|
+
let isLow = true;
|
|
23
|
+
for (let j = i - lookback; j <= i + lookback; j++) {
|
|
24
|
+
if (j === i) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const h = coerceFiniteNumber(bars[j].high);
|
|
28
|
+
const l = coerceFiniteNumber(bars[j].low);
|
|
29
|
+
if (h != null && h > high) {
|
|
30
|
+
isHigh = false;
|
|
31
|
+
}
|
|
32
|
+
if (l != null && l < low) {
|
|
33
|
+
isLow = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isHigh) {
|
|
37
|
+
swings.push({ price: high, kind: 'resistance', timeSec: t });
|
|
38
|
+
}
|
|
39
|
+
if (isLow) {
|
|
40
|
+
swings.push({ price: low, kind: 'support', timeSec: t });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return swings;
|
|
44
|
+
}
|
|
45
|
+
/** Swing-based support/resistance levels from OHLCV bars. */
|
|
46
|
+
export function calculateKeyLevelsFromBars(bars, options = {}) {
|
|
47
|
+
if (bars.length < 5) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const lookback = Math.max(2, Math.min(options.lookback ?? 3, Math.floor(bars.length / 8)));
|
|
51
|
+
const tolerancePct = options.tolerancePct ?? 0.003;
|
|
52
|
+
const maxLevels = options.maxLevels ?? 8;
|
|
53
|
+
const swings = detectSwings(bars, lookback);
|
|
54
|
+
if (!swings.length) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const clusters = [];
|
|
58
|
+
for (const swing of swings) {
|
|
59
|
+
const tol = swing.price * tolerancePct;
|
|
60
|
+
let merged = false;
|
|
61
|
+
for (const c of clusters) {
|
|
62
|
+
if (c.kind !== swing.kind) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (Math.abs(c.price - swing.price) <= tol) {
|
|
66
|
+
c.touchCount++;
|
|
67
|
+
c.price = (c.price * (c.touchCount - 1) + swing.price) / c.touchCount;
|
|
68
|
+
c.lastTimeSec = Math.max(c.lastTimeSec, swing.timeSec);
|
|
69
|
+
merged = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!merged) {
|
|
74
|
+
clusters.push({
|
|
75
|
+
price: swing.price,
|
|
76
|
+
kind: swing.kind,
|
|
77
|
+
touchCount: 1,
|
|
78
|
+
lastTimeSec: swing.timeSec,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const latestSec = Math.max(...swings.map(s => s.timeSec));
|
|
83
|
+
return clusters
|
|
84
|
+
.map(c => ({
|
|
85
|
+
price: c.price,
|
|
86
|
+
kind: c.kind,
|
|
87
|
+
touchCount: c.touchCount,
|
|
88
|
+
strength: c.touchCount + (c.lastTimeSec >= latestSec - lookback * 3600 ? 1 : 0),
|
|
89
|
+
}))
|
|
90
|
+
.sort((a, b) => b.strength - a.strength || b.touchCount - a.touchCount)
|
|
91
|
+
.slice(0, maxLevels);
|
|
92
|
+
}
|
|
93
|
+
/** Dominant swing high/low for Fibonacci anchor. */
|
|
94
|
+
export function calculateFibonacciRangeFromBars(bars) {
|
|
95
|
+
if (bars.length < 3) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const lookback = Math.max(2, Math.min(5, Math.floor(bars.length / 10)));
|
|
99
|
+
const swings = detectSwings(bars, lookback);
|
|
100
|
+
if (swings.length < 2) {
|
|
101
|
+
let high = Number.NEGATIVE_INFINITY;
|
|
102
|
+
let low = Number.POSITIVE_INFINITY;
|
|
103
|
+
for (const bar of bars) {
|
|
104
|
+
const h = coerceFiniteNumber(bar.high);
|
|
105
|
+
const l = coerceFiniteNumber(bar.low);
|
|
106
|
+
if (h != null) {
|
|
107
|
+
high = Math.max(high, h);
|
|
108
|
+
}
|
|
109
|
+
if (l != null) {
|
|
110
|
+
low = Math.min(low, l);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!Number.isFinite(high) || !Number.isFinite(low) || high === low) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return { high, low, trend: 'up' };
|
|
117
|
+
}
|
|
118
|
+
const recent = [...swings].sort((a, b) => b.timeSec - a.timeSec).slice(0, 6);
|
|
119
|
+
const highSwing = recent
|
|
120
|
+
.filter(s => s.kind === 'resistance')
|
|
121
|
+
.sort((a, b) => b.price - a.price)[0];
|
|
122
|
+
const lowSwing = recent.filter(s => s.kind === 'support').sort((a, b) => a.price - b.price)[0];
|
|
123
|
+
const high = highSwing?.price ?? Math.max(...recent.map(s => s.price));
|
|
124
|
+
const low = lowSwing?.price ?? Math.min(...recent.map(s => s.price));
|
|
125
|
+
if (!Number.isFinite(high) || !Number.isFinite(low) || high === low) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const first = recent[recent.length - 1];
|
|
129
|
+
const last = recent[0];
|
|
130
|
+
const trend = last.price >= first.price ? 'up' : 'down';
|
|
131
|
+
return { high, low, trend };
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=key-levels.js.map
|