@tranding-custom-chart/financial 0.0.0-stage → 2.1.0

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.
Files changed (53) hide show
  1. package/README.md +351 -2
  2. package/dist/adapter.d.ts +24 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/adapter.js +47 -0
  5. package/dist/index.d.ts +21 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +20 -0
  8. package/dist/indicators/atr.d.ts +13 -0
  9. package/dist/indicators/atr.d.ts.map +1 -0
  10. package/dist/indicators/atr.js +40 -0
  11. package/dist/indicators/bollinger.d.ts +12 -0
  12. package/dist/indicators/bollinger.d.ts.map +1 -0
  13. package/dist/indicators/bollinger.js +34 -0
  14. package/dist/indicators/ema.d.ts +7 -0
  15. package/dist/indicators/ema.d.ts.map +1 -0
  16. package/dist/indicators/ema.js +26 -0
  17. package/dist/indicators/heikin-ashi.d.ts +14 -0
  18. package/dist/indicators/heikin-ashi.d.ts.map +1 -0
  19. package/dist/indicators/heikin-ashi.js +36 -0
  20. package/dist/indicators/kagi.d.ts +20 -0
  21. package/dist/indicators/kagi.d.ts.map +1 -0
  22. package/dist/indicators/kagi.js +122 -0
  23. package/dist/indicators/line-break.d.ts +18 -0
  24. package/dist/indicators/line-break.d.ts.map +1 -0
  25. package/dist/indicators/line-break.js +73 -0
  26. package/dist/indicators/macd.d.ts +13 -0
  27. package/dist/indicators/macd.d.ts.map +1 -0
  28. package/dist/indicators/macd.js +60 -0
  29. package/dist/indicators/renko.d.ts +19 -0
  30. package/dist/indicators/renko.d.ts.map +1 -0
  31. package/dist/indicators/renko.js +84 -0
  32. package/dist/indicators/rsi.d.ts +7 -0
  33. package/dist/indicators/rsi.d.ts.map +1 -0
  34. package/dist/indicators/rsi.js +47 -0
  35. package/dist/indicators/sma.d.ts +15 -0
  36. package/dist/indicators/sma.d.ts.map +1 -0
  37. package/dist/indicators/sma.js +37 -0
  38. package/dist/indicators/supertrend.d.ts +8 -0
  39. package/dist/indicators/supertrend.d.ts.map +1 -0
  40. package/dist/indicators/supertrend.js +88 -0
  41. package/dist/indicators/volume-profile.d.ts +10 -0
  42. package/dist/indicators/volume-profile.d.ts.map +1 -0
  43. package/dist/indicators/volume-profile.js +134 -0
  44. package/dist/indicators/vwap.d.ts +7 -0
  45. package/dist/indicators/vwap.d.ts.map +1 -0
  46. package/dist/indicators/vwap.js +33 -0
  47. package/dist/indicators/wma.d.ts +7 -0
  48. package/dist/indicators/wma.d.ts.map +1 -0
  49. package/dist/indicators/wma.js +21 -0
  50. package/dist/layout/pane-layout.d.ts +19 -0
  51. package/dist/layout/pane-layout.d.ts.map +1 -0
  52. package/dist/layout/pane-layout.js +39 -0
  53. package/package.json +74 -4
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/heikin-ashi.ts
3
+ * Transforms standard OHLCV candlesticks into smoothed Heikin-Ashi candles.
4
+ *
5
+ * Formulas:
6
+ * - Close_HA = (Open + High + Low + Close) / 4
7
+ * - Open_HA[0] = (Open[0] + Close[0]) / 2
8
+ * - Open_HA[i] = (Open_HA[i-1] + Close_HA[i-1]) / 2
9
+ * - High_HA = max(High, Open_HA, Close_HA)
10
+ * - Low_HA = min(Low, Open_HA, Close_HA)
11
+ */
12
+ export function computeHeikinAshi(bars) {
13
+ if (bars.length === 0)
14
+ return [];
15
+ const result = [];
16
+ for (let i = 0; i < bars.length; i++) {
17
+ const bar = bars[i];
18
+ const haClose = (bar.open + bar.high + bar.low + bar.close) / 4;
19
+ const haOpen = i === 0
20
+ ? (bar.open + bar.close) / 2
21
+ : (result[i - 1].open + result[i - 1].close) / 2;
22
+ const haHigh = Math.max(bar.high, haOpen, haClose);
23
+ const haLow = Math.min(bar.low, haOpen, haClose);
24
+ result.push({
25
+ time: bar.time,
26
+ open: haOpen,
27
+ high: haHigh,
28
+ low: haLow,
29
+ close: haClose,
30
+ volume: bar.volume,
31
+ dateStr: bar.dateStr,
32
+ qualityFlags: bar.qualityFlags,
33
+ });
34
+ }
35
+ return result;
36
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/kagi.ts
3
+ * Algorithmic Kagi line generation from sequential OHLCV bars.
4
+ * Kagi charts filter time and noise, indicating trend reversals and Yang (bullish) / Yin (bearish) inflections.
5
+ */
6
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
7
+ export interface KagiSegment extends OHLCVBar {
8
+ readonly isYang: boolean;
9
+ readonly isUp: boolean;
10
+ readonly originalIndex: number;
11
+ }
12
+ export interface KagiOptions {
13
+ readonly reversalAmount?: number | undefined;
14
+ readonly reversalPercent?: number | undefined;
15
+ }
16
+ /**
17
+ * Computes Kagi trend segments from standard OHLCV bars.
18
+ */
19
+ export declare function computeKagi(bars: readonly OHLCVBar[], options?: KagiOptions): readonly KagiSegment[];
20
+ //# sourceMappingURL=kagi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kagi.d.ts","sourceRoot":"","sources":["../../src/indicators/kagi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,OAAO,GAAE,WAAgB,GACxB,SAAS,WAAW,EAAE,CAsHxB"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/kagi.ts
3
+ * Algorithmic Kagi line generation from sequential OHLCV bars.
4
+ * Kagi charts filter time and noise, indicating trend reversals and Yang (bullish) / Yin (bearish) inflections.
5
+ */
6
+ /**
7
+ * Computes Kagi trend segments from standard OHLCV bars.
8
+ */
9
+ export function computeKagi(bars, options = {}) {
10
+ if (bars.length === 0)
11
+ return [];
12
+ const firstClose = bars[0].close;
13
+ const reversalPct = options.reversalPercent ?? 0.01;
14
+ const reversalThreshold = options.reversalAmount && options.reversalAmount > 0
15
+ ? options.reversalAmount
16
+ : Math.max(0.1, Number((firstClose * reversalPct).toFixed(2)));
17
+ const segments = [];
18
+ let currentStartPrice = firstClose;
19
+ let currentEndPrice = firstClose;
20
+ let currentDirection = null;
21
+ let isYang = true;
22
+ let lastShoulder = firstClose; // Previous peak
23
+ let lastWaist = firstClose; // Previous trough
24
+ for (let i = 1; i < bars.length; i++) {
25
+ const bar = bars[i];
26
+ const price = bar.close;
27
+ if (currentDirection === null) {
28
+ if (price >= currentStartPrice + reversalThreshold) {
29
+ currentDirection = 'up';
30
+ currentEndPrice = price;
31
+ lastShoulder = price;
32
+ }
33
+ else if (price <= currentStartPrice - reversalThreshold) {
34
+ currentDirection = 'down';
35
+ currentEndPrice = price;
36
+ lastWaist = price;
37
+ isYang = false;
38
+ }
39
+ continue;
40
+ }
41
+ if (currentDirection === 'up') {
42
+ if (price > currentEndPrice) {
43
+ // Continue upward trend
44
+ currentEndPrice = price;
45
+ if (!isYang && price > lastShoulder) {
46
+ isYang = true; // Breakout above shoulder turns Yang
47
+ }
48
+ }
49
+ else if (price <= currentEndPrice - reversalThreshold) {
50
+ // Reversal downwards
51
+ segments.push({
52
+ time: bar.time,
53
+ open: currentStartPrice,
54
+ high: currentEndPrice,
55
+ low: currentStartPrice,
56
+ close: currentEndPrice,
57
+ volume: bar.volume ?? 0,
58
+ isYang,
59
+ isUp: true,
60
+ originalIndex: i - 1,
61
+ dateStr: bar.dateStr,
62
+ });
63
+ lastShoulder = currentEndPrice;
64
+ currentStartPrice = currentEndPrice;
65
+ currentEndPrice = price;
66
+ currentDirection = 'down';
67
+ if (isYang && price < lastWaist) {
68
+ isYang = false; // Breakdown below waist turns Yin
69
+ }
70
+ }
71
+ }
72
+ else {
73
+ // currentDirection === 'down'
74
+ if (price < currentEndPrice) {
75
+ // Continue downward trend
76
+ currentEndPrice = price;
77
+ if (isYang && price < lastWaist) {
78
+ isYang = false; // Breakdown below waist turns Yin
79
+ }
80
+ }
81
+ else if (price >= currentEndPrice + reversalThreshold) {
82
+ // Reversal upwards
83
+ segments.push({
84
+ time: bar.time,
85
+ open: currentStartPrice,
86
+ high: currentStartPrice,
87
+ low: currentEndPrice,
88
+ close: currentEndPrice,
89
+ volume: bar.volume ?? 0,
90
+ isYang,
91
+ isUp: false,
92
+ originalIndex: i - 1,
93
+ dateStr: bar.dateStr,
94
+ });
95
+ lastWaist = currentEndPrice;
96
+ currentStartPrice = currentEndPrice;
97
+ currentEndPrice = price;
98
+ currentDirection = 'up';
99
+ if (!isYang && price > lastShoulder) {
100
+ isYang = true; // Breakout above shoulder turns Yang
101
+ }
102
+ }
103
+ }
104
+ }
105
+ // Push terminal active segment
106
+ if (currentDirection !== null) {
107
+ const lastBar = bars[bars.length - 1];
108
+ segments.push({
109
+ time: lastBar.time,
110
+ open: currentStartPrice,
111
+ high: Math.max(currentStartPrice, currentEndPrice),
112
+ low: Math.min(currentStartPrice, currentEndPrice),
113
+ close: currentEndPrice,
114
+ volume: lastBar.volume ?? 0,
115
+ isYang,
116
+ isUp: currentEndPrice >= currentStartPrice,
117
+ originalIndex: bars.length - 1,
118
+ dateStr: lastBar.dateStr,
119
+ });
120
+ }
121
+ return segments;
122
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/line-break.ts
3
+ * Algorithmic Three-Line Break (TLB) chart generation.
4
+ * Filters minor oscillations, adding new blocks only when price exceeds the extreme of the prior N lines.
5
+ */
6
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
7
+ export interface LineBreakBar extends OHLCVBar {
8
+ readonly isUp: boolean;
9
+ readonly originalIndex: number;
10
+ }
11
+ export interface LineBreakOptions {
12
+ readonly lineCount?: number | undefined;
13
+ }
14
+ /**
15
+ * Computes Three-Line Break (TLB) bars from sequential OHLCV bars.
16
+ */
17
+ export declare function computeLineBreak(bars: readonly OHLCVBar[], options?: LineBreakOptions): readonly LineBreakBar[];
18
+ //# sourceMappingURL=line-break.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-break.d.ts","sourceRoot":"","sources":["../../src/indicators/line-break.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,OAAO,GAAE,gBAAqB,GAC7B,SAAS,YAAY,EAAE,CAoEzB"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/line-break.ts
3
+ * Algorithmic Three-Line Break (TLB) chart generation.
4
+ * Filters minor oscillations, adding new blocks only when price exceeds the extreme of the prior N lines.
5
+ */
6
+ /**
7
+ * Computes Three-Line Break (TLB) bars from sequential OHLCV bars.
8
+ */
9
+ export function computeLineBreak(bars, options = {}) {
10
+ if (bars.length === 0)
11
+ return [];
12
+ const lineCount = Math.max(1, options.lineCount ?? 3);
13
+ const result = [];
14
+ // Seed with initial bar
15
+ const first = bars[0];
16
+ result.push({
17
+ time: first.time,
18
+ open: first.open,
19
+ high: Math.max(first.open, first.close),
20
+ low: Math.min(first.open, first.close),
21
+ close: first.close,
22
+ volume: first.volume ?? 0,
23
+ isUp: first.close >= first.open,
24
+ originalIndex: 0,
25
+ dateStr: first.dateStr,
26
+ });
27
+ for (let i = 1; i < bars.length; i++) {
28
+ const bar = bars[i];
29
+ const price = bar.close;
30
+ // Check extremes of recent N lines
31
+ const recent = result.slice(-lineCount);
32
+ let highestHigh = -Infinity;
33
+ let lowestLow = Infinity;
34
+ for (const line of recent) {
35
+ const top = Math.max(line.open, line.close);
36
+ const bottom = Math.min(line.open, line.close);
37
+ if (top > highestHigh)
38
+ highestHigh = top;
39
+ if (bottom < lowestLow)
40
+ lowestLow = bottom;
41
+ }
42
+ const lastLine = result[result.length - 1];
43
+ if (price > highestHigh) {
44
+ // New up line
45
+ result.push({
46
+ time: bar.time,
47
+ open: lastLine.isUp ? lastLine.close : lastLine.open,
48
+ high: price,
49
+ low: lastLine.isUp ? lastLine.close : lastLine.open,
50
+ close: price,
51
+ volume: bar.volume ?? 0,
52
+ isUp: true,
53
+ originalIndex: i,
54
+ dateStr: bar.dateStr,
55
+ });
56
+ }
57
+ else if (price < lowestLow) {
58
+ // New down line
59
+ result.push({
60
+ time: bar.time,
61
+ open: !lastLine.isUp ? lastLine.close : lastLine.open,
62
+ high: !lastLine.isUp ? lastLine.close : lastLine.open,
63
+ low: price,
64
+ close: price,
65
+ volume: bar.volume ?? 0,
66
+ isUp: false,
67
+ originalIndex: i,
68
+ dateStr: bar.dateStr,
69
+ });
70
+ }
71
+ }
72
+ return result;
73
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/macd.ts
3
+ * Moving Average Convergence Divergence (MACD) calculation.
4
+ * Outputs MACD Line, Signal Line, and Histogram oscillator.
5
+ */
6
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
7
+ export interface MACDResult {
8
+ readonly macd: readonly (number | null)[];
9
+ readonly signal: readonly (number | null)[];
10
+ readonly histogram: readonly (number | null)[];
11
+ }
12
+ export declare function computeMACD(bars: readonly OHLCVBar[], fastPeriod?: number, slowPeriod?: number, signalPeriod?: number): MACDResult;
13
+ //# sourceMappingURL=macd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macd.d.ts","sourceRoot":"","sources":["../../src/indicators/macd.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAG5D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAChD;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,UAAU,SAAK,EACf,UAAU,SAAK,EACf,YAAY,SAAI,GACf,UAAU,CA4DZ"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/macd.ts
3
+ * Moving Average Convergence Divergence (MACD) calculation.
4
+ * Outputs MACD Line, Signal Line, and Histogram oscillator.
5
+ */
6
+ import { computeEMA } from './ema.js';
7
+ export function computeMACD(bars, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
8
+ const n = bars.length;
9
+ if (n === 0) {
10
+ return { macd: [], signal: [], histogram: [] };
11
+ }
12
+ const fastEMA = computeEMA(bars, fastPeriod);
13
+ const slowEMA = computeEMA(bars, slowPeriod);
14
+ const macdLine = new Array(n).fill(null);
15
+ for (let i = 0; i < n; i++) {
16
+ const f = fastEMA[i];
17
+ const s = slowEMA[i];
18
+ if (f !== null && f !== undefined && s !== null && s !== undefined) {
19
+ macdLine[i] = f - s;
20
+ }
21
+ }
22
+ // Compute Signal Line as EMA over valid MACD values
23
+ const signalLine = new Array(n).fill(null);
24
+ const validMacdIndices = [];
25
+ for (let i = 0; i < n; i++) {
26
+ if (macdLine[i] !== null) {
27
+ validMacdIndices.push(i);
28
+ }
29
+ }
30
+ if (validMacdIndices.length >= signalPeriod) {
31
+ // Synthetic bar series to reuse standard EMA logic
32
+ const dummyBars = validMacdIndices.map((idx) => ({
33
+ time: bars[idx].time,
34
+ open: macdLine[idx],
35
+ high: macdLine[idx],
36
+ low: macdLine[idx],
37
+ close: macdLine[idx],
38
+ volume: null,
39
+ }));
40
+ const signalValues = computeEMA(dummyBars, signalPeriod);
41
+ for (let k = 0; k < validMacdIndices.length; k++) {
42
+ const origIdx = validMacdIndices[k];
43
+ signalLine[origIdx] = signalValues[k];
44
+ }
45
+ }
46
+ // Compute Histogram: MACD Line - Signal Line
47
+ const histogram = new Array(n).fill(null);
48
+ for (let i = 0; i < n; i++) {
49
+ const m = macdLine[i];
50
+ const s = signalLine[i];
51
+ if (m !== null && m !== undefined && s !== null && s !== undefined) {
52
+ histogram[i] = m - s;
53
+ }
54
+ }
55
+ return {
56
+ macd: macdLine,
57
+ signal: signalLine,
58
+ histogram,
59
+ };
60
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/renko.ts
3
+ * Algorithmic Renko brick generation from OHLCV bar observations.
4
+ * Renko filters time and minor fluctuations, creating bricks of a fixed price size.
5
+ */
6
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
7
+ export interface RenkoBrick extends OHLCVBar {
8
+ readonly isUp: boolean;
9
+ readonly originalIndex: number;
10
+ }
11
+ export interface RenkoOptions {
12
+ readonly brickSize?: number | undefined;
13
+ }
14
+ /**
15
+ * Computes Renko bricks from standard OHLCV bars.
16
+ * Each brick represents a fixed price movement (brickSize).
17
+ */
18
+ export declare function computeRenko(bars: readonly OHLCVBar[], options?: RenkoOptions): readonly RenkoBrick[];
19
+ //# sourceMappingURL=renko.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renko.d.ts","sourceRoot":"","sources":["../../src/indicators/renko.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,OAAO,GAAE,YAAiB,GACzB,SAAS,UAAU,EAAE,CA6EvB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/renko.ts
3
+ * Algorithmic Renko brick generation from OHLCV bar observations.
4
+ * Renko filters time and minor fluctuations, creating bricks of a fixed price size.
5
+ */
6
+ /**
7
+ * Computes Renko bricks from standard OHLCV bars.
8
+ * Each brick represents a fixed price movement (brickSize).
9
+ */
10
+ export function computeRenko(bars, options = {}) {
11
+ if (bars.length === 0)
12
+ return [];
13
+ // Determine brick size
14
+ let brickSize = options.brickSize;
15
+ if (!brickSize || brickSize <= 0) {
16
+ // Dynamic default: 1% of the starting close or median range
17
+ const firstClose = bars[0]?.close ?? 100;
18
+ brickSize = Math.max(0.1, Number((firstClose * 0.005).toFixed(2)));
19
+ }
20
+ const bricks = [];
21
+ let lastBrickPrice = Math.floor(bars[0].close / brickSize) * brickSize;
22
+ let lastDirection = null;
23
+ for (let i = 0; i < bars.length; i++) {
24
+ const bar = bars[i];
25
+ const price = bar.close;
26
+ while (true) {
27
+ if (price >= lastBrickPrice + brickSize) {
28
+ // Up brick
29
+ const open = lastBrickPrice;
30
+ const close = lastBrickPrice + brickSize;
31
+ bricks.push({
32
+ time: bar.time,
33
+ open,
34
+ high: close,
35
+ low: open,
36
+ close,
37
+ volume: bar.volume ? Math.round(bar.volume / 2) : 0,
38
+ isUp: true,
39
+ originalIndex: i,
40
+ dateStr: bar.dateStr,
41
+ });
42
+ lastBrickPrice = close;
43
+ lastDirection = 'up';
44
+ }
45
+ else if (price <= lastBrickPrice - brickSize) {
46
+ // Down brick
47
+ const open = lastBrickPrice;
48
+ const close = lastBrickPrice - brickSize;
49
+ bricks.push({
50
+ time: bar.time,
51
+ open,
52
+ high: open,
53
+ low: close,
54
+ close,
55
+ volume: bar.volume ? Math.round(bar.volume / 2) : 0,
56
+ isUp: false,
57
+ originalIndex: i,
58
+ dateStr: bar.dateStr,
59
+ });
60
+ lastBrickPrice = close;
61
+ lastDirection = 'down';
62
+ }
63
+ else {
64
+ break;
65
+ }
66
+ }
67
+ }
68
+ // If no brick triggered (e.g. range was too narrow), create at least one baseline brick
69
+ if (bricks.length === 0 && bars.length > 0) {
70
+ const b = bars[0];
71
+ bricks.push({
72
+ time: b.time,
73
+ open: b.open,
74
+ high: Math.max(b.open, b.close),
75
+ low: Math.min(b.open, b.close),
76
+ close: b.close,
77
+ volume: b.volume ?? 0,
78
+ isUp: b.close >= b.open,
79
+ originalIndex: 0,
80
+ dateStr: b.dateStr,
81
+ });
82
+ }
83
+ return bricks;
84
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/rsi.ts
3
+ * Relative Strength Index (RSI) using Wilder's smoothed moving average.
4
+ */
5
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
6
+ export declare function computeRSI(bars: readonly OHLCVBar[], period?: number): (number | null)[];
7
+ //# sourceMappingURL=rsi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsi.d.ts","sourceRoot":"","sources":["../../src/indicators/rsi.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,MAAM,SAAK,GACV,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAgDnB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/rsi.ts
3
+ * Relative Strength Index (RSI) using Wilder's smoothed moving average.
4
+ */
5
+ export function computeRSI(bars, period = 14) {
6
+ if (period <= 0 || bars.length <= period) {
7
+ return bars.map(() => null);
8
+ }
9
+ const result = new Array(bars.length).fill(null);
10
+ // Compute initial average gain and loss over first 'period' price changes
11
+ let totalGain = 0;
12
+ let totalLoss = 0;
13
+ for (let i = 1; i <= period; i++) {
14
+ const change = bars[i].close - bars[i - 1].close;
15
+ if (change > 0) {
16
+ totalGain += change;
17
+ }
18
+ else {
19
+ totalLoss += Math.abs(change);
20
+ }
21
+ }
22
+ let avgGain = totalGain / period;
23
+ let avgLoss = totalLoss / period;
24
+ if (avgLoss === 0) {
25
+ result[period] = 100;
26
+ }
27
+ else {
28
+ const rs = avgGain / avgLoss;
29
+ result[period] = 100 - 100 / (1 + rs);
30
+ }
31
+ // Smooth subsequent values using Wilder's technique
32
+ for (let i = period + 1; i < bars.length; i++) {
33
+ const change = bars[i].close - bars[i - 1].close;
34
+ const gain = change > 0 ? change : 0;
35
+ const loss = change < 0 ? Math.abs(change) : 0;
36
+ avgGain = (avgGain * (period - 1) + gain) / period;
37
+ avgLoss = (avgLoss * (period - 1) + loss) / period;
38
+ if (avgLoss === 0) {
39
+ result[i] = 100;
40
+ }
41
+ else {
42
+ const rs = avgGain / avgLoss;
43
+ result[i] = 100 - 100 / (1 + rs);
44
+ }
45
+ }
46
+ return result;
47
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/sma.ts
3
+ * Simple Moving Average (SMA) computation with transparent warm-up and incremental updates.
4
+ */
5
+ import type { OHLCVBar } from '@tranding-custom-chart/core';
6
+ /**
7
+ * Computes SMA over close prices.
8
+ * Returns an array of equal length to bars, with `null` for the warm-up periods.
9
+ */
10
+ export declare function computeSMA(bars: readonly OHLCVBar[], period: number): (number | null)[];
11
+ /**
12
+ * Updates the latest trailing SMA value when the current live candle updates.
13
+ */
14
+ export declare function updateTrailingSMA(bars: readonly OHLCVBar[], period: number, updatedClose: number): number | null;
15
+ //# sourceMappingURL=sma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sma.d.ts","sourceRoot":"","sources":["../../src/indicators/sma.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,MAAM,EAAE,MAAM,GACb,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAqBnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,MAAM,GAAG,IAAI,CAQf"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/sma.ts
3
+ * Simple Moving Average (SMA) computation with transparent warm-up and incremental updates.
4
+ */
5
+ /**
6
+ * Computes SMA over close prices.
7
+ * Returns an array of equal length to bars, with `null` for the warm-up periods.
8
+ */
9
+ export function computeSMA(bars, period) {
10
+ if (period <= 0 || bars.length < period) {
11
+ return bars.map(() => null);
12
+ }
13
+ const result = new Array(bars.length).fill(null);
14
+ let windowSum = 0;
15
+ for (let i = 0; i < bars.length; i++) {
16
+ windowSum += bars[i].close;
17
+ if (i >= period) {
18
+ windowSum -= bars[i - period].close;
19
+ }
20
+ if (i >= period - 1) {
21
+ result[i] = windowSum / period;
22
+ }
23
+ }
24
+ return result;
25
+ }
26
+ /**
27
+ * Updates the latest trailing SMA value when the current live candle updates.
28
+ */
29
+ export function updateTrailingSMA(bars, period, updatedClose) {
30
+ if (period <= 0 || bars.length < period)
31
+ return null;
32
+ let sum = updatedClose;
33
+ for (let i = 1; i < period; i++) {
34
+ sum += bars[bars.length - 1 - i].close;
35
+ }
36
+ return sum / period;
37
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @file packages/chart-financial/src/indicators/supertrend.ts
3
+ * Algorithmic Supertrend calculation engine.
4
+ * Computes ATR-based dynamic trailing stop bands and trend direction (1 = Bullish, -1 = Bearish).
5
+ */
6
+ import type { OHLCVBar, SupertrendResult, SupertrendOptions } from '@tranding-custom-chart/core';
7
+ export declare function computeSupertrend(bars: readonly OHLCVBar[], options?: SupertrendOptions): SupertrendResult;
8
+ //# sourceMappingURL=supertrend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supertrend.d.ts","sourceRoot":"","sources":["../../src/indicators/supertrend.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,QAAQ,EAER,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAGrC,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAuFlB"}