@tony01/astroneum 0.4.1-beta.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/CHANGELOG.md +237 -0
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/Indicator-BBI3L_lx.d.ts +1181 -0
- package/dist/ar-SA-AEPUSRMF.js +2 -0
- package/dist/astroneum.css +1 -0
- package/dist/chunk-2SN3RH42.js +2 -0
- package/dist/chunk-2YYGUSVX.js +3 -0
- package/dist/chunk-3GJSZFLM.js +2 -0
- package/dist/chunk-4YOLQ5DC.js +2 -0
- package/dist/chunk-I4YQBP2M.js +3 -0
- package/dist/chunk-OOMZRONH.js +35 -0
- package/dist/chunk-PV2GAINM.js +2 -0
- package/dist/chunk-SDXH2WAI.js +3 -0
- package/dist/chunk-YFPXTHZX.js +2 -0
- package/dist/chunk-YW3STIPY.js +653 -0
- package/dist/de-DE-4PR3NRQ7.js +2 -0
- package/dist/entries/alerts.d.ts +93 -0
- package/dist/entries/alerts.js +2 -0
- package/dist/entries/datafeeds/crypto.d.ts +65 -0
- package/dist/entries/datafeeds/crypto.js +2 -0
- package/dist/entries/datafeeds/polygon.d.ts +113 -0
- package/dist/entries/datafeeds/polygon.js +2 -0
- package/dist/entries/multichart.d.ts +96 -0
- package/dist/entries/multichart.js +2 -0
- package/dist/entries/portfolio.d.ts +55 -0
- package/dist/entries/portfolio.js +2 -0
- package/dist/entries/replay.d.ts +141 -0
- package/dist/entries/replay.js +2 -0
- package/dist/entries/script.d.ts +68 -0
- package/dist/entries/script.js +2 -0
- package/dist/entries/watchlist.d.ts +43 -0
- package/dist/entries/watchlist.js +2 -0
- package/dist/es-ES-HNDVPSLW.js +2 -0
- package/dist/fr-FR-Y7XWRGF2.js +2 -0
- package/dist/hi-IN-KEGIKIMV.js +2 -0
- package/dist/id-ID-QXDIUQUZ.js +2 -0
- package/dist/index.d.ts +1434 -0
- package/dist/index.js +2 -0
- package/dist/it-IT-UDTDFSRB.js +2 -0
- package/dist/ja-JP-NIODTBW3.js +2 -0
- package/dist/ko-KR-DQHPXKBA.js +2 -0
- package/dist/nl-NL-BB3ZHCXS.js +2 -0
- package/dist/pl-PL-I5MZDLFD.js +2 -0
- package/dist/pt-BR-MAMRTOYR.js +2 -0
- package/dist/ru-RU-F43D6B7G.js +2 -0
- package/dist/th-TH-KTFIUAD6.js +2 -0
- package/dist/tr-TR-WFTKJ22Y.js +2 -0
- package/dist/vi-VN-CD3WI2FQ.js +2 -0
- package/dist/zh-CN-Y2C6RSOI.js +3 -0
- package/docs/STRUCTURE.md +231 -0
- package/docs/TODO-DESIGN.md +261 -0
- package/docs/TODO.md +222 -0
- package/docs/api.md +528 -0
- package/docs/datafeed-guide.md +311 -0
- package/docs/design-astroneum.md +479 -0
- package/docs/plugin-development.md +565 -0
- package/docs/tv-functions-skill.md +706 -0
- package/package.json +147 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1434 @@
|
|
|
1
|
+
import { I as IndicatorTemplate, O as OverlayTemplate, X as XAxisTemplate, Y as YAxisTemplate, A as AstroneumOptions, a as AstroneumHandle, C as CandleData, b as IndicatorPlugin, P as Price, T as Timestamp, V as Volume, c as Chart, S as SerializedChartState, d as Period, e as SymbolInfo, D as Datafeed } from './Indicator-BBI3L_lx.js';
|
|
2
|
+
export { f as ChartEventMap, g as ChartPlugin, h as ChartPluginContext, i as DatafeedSubscribeCallback, j as Viewport } from './Indicator-BBI3L_lx.js';
|
|
3
|
+
export { DefaultDatafeed, WebSocketDatafeed, WebSocketDatafeedOptions } from './entries/datafeeds/polygon.js';
|
|
4
|
+
export { BinanceAdapter, BitgetAdapter, CryptoSymbolInfo, DATAFEED_ERROR_EVENT, DatafeedErrorDetail, DatafeedErrorType, ExchangeAdapter, OkxAdapter, STANDARD_CRYPTO_SYMBOLS, StandardCryptoDatafeed, StandardCryptoDatafeedOptions, createStandardCryptoDatafeed } from './entries/datafeeds/crypto.js';
|
|
5
|
+
import * as react from 'react';
|
|
6
|
+
export { MultiChartCount, MultiChartLayout, MultiChartLayoutOptions, MultiChartSlot } from './entries/multichart.js';
|
|
7
|
+
export { BarReplay, BarReplayOptions, BarReplayState } from './entries/replay.js';
|
|
8
|
+
export { Alert, AlertCheckInput, AlertCondition, AlertCreate, AlertFrequency, AlertManager, AlertStatus, AlertTriggeredCallback, NotificationSchedule, SoundDuration, SoundTitle } from './entries/alerts.js';
|
|
9
|
+
export { CompiledIndicator, InputOptions, PlotOptions, ScriptEngine, StudyOptions } from './entries/script.js';
|
|
10
|
+
export { WatchSymbol, Watchlist, WatchlistManager } from './entries/watchlist.js';
|
|
11
|
+
import { Position } from './entries/portfolio.js';
|
|
12
|
+
export { PnLResult, PortfolioTracker, PositionSide } from './entries/portfolio.js';
|
|
13
|
+
|
|
14
|
+
declare function registerIndicator<D = unknown, C = unknown, E = unknown>(indicator: IndicatorTemplate<D, C, E>): void;
|
|
15
|
+
declare function getSupportedIndicators(): string[];
|
|
16
|
+
|
|
17
|
+
declare function registerOverlay<E = unknown>(template: OverlayTemplate<E>): void;
|
|
18
|
+
declare function getSupportedOverlays(): string[];
|
|
19
|
+
|
|
20
|
+
declare function registerXAxis(axis: XAxisTemplate): void;
|
|
21
|
+
|
|
22
|
+
declare function registerYAxis(axis: YAxisTemplate): void;
|
|
23
|
+
|
|
24
|
+
declare const AstroneumChart: react.ForwardRefExoticComponent<AstroneumOptions & react.RefAttributes<AstroneumHandle>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Drawing Style Templates & Presets
|
|
28
|
+
*
|
|
29
|
+
* Provides named overlay style presets that users can apply to drawing tools,
|
|
30
|
+
* plus save/load of custom templates to localStorage.
|
|
31
|
+
*/
|
|
32
|
+
interface OverlayStylePreset {
|
|
33
|
+
/** Unique identifier for this preset. */
|
|
34
|
+
id: string;
|
|
35
|
+
/** Human-readable display name. */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Partial overlay style object compatible with the engine's overlay styles. */
|
|
38
|
+
styles: DrawingStyleTemplate;
|
|
39
|
+
}
|
|
40
|
+
interface DrawingStyleTemplate {
|
|
41
|
+
line?: {
|
|
42
|
+
color?: string;
|
|
43
|
+
size?: number;
|
|
44
|
+
style?: 'solid' | 'dashed' | 'dotted';
|
|
45
|
+
};
|
|
46
|
+
polygon?: {
|
|
47
|
+
color?: string;
|
|
48
|
+
};
|
|
49
|
+
text?: {
|
|
50
|
+
color?: string;
|
|
51
|
+
size?: number;
|
|
52
|
+
family?: string;
|
|
53
|
+
weight?: string;
|
|
54
|
+
};
|
|
55
|
+
rectText?: {
|
|
56
|
+
color?: string;
|
|
57
|
+
size?: number;
|
|
58
|
+
family?: string;
|
|
59
|
+
weight?: string;
|
|
60
|
+
paddingLeft?: number;
|
|
61
|
+
paddingRight?: number;
|
|
62
|
+
paddingTop?: number;
|
|
63
|
+
paddingBottom?: number;
|
|
64
|
+
borderRadius?: number;
|
|
65
|
+
borderSize?: number;
|
|
66
|
+
borderColor?: string;
|
|
67
|
+
backgroundColor?: string;
|
|
68
|
+
};
|
|
69
|
+
point?: {
|
|
70
|
+
color?: string;
|
|
71
|
+
radius?: number;
|
|
72
|
+
borderColor?: string;
|
|
73
|
+
borderSize?: number;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Manager for drawing style presets.
|
|
78
|
+
* Provides access to built-in presets and allows saving/loading custom ones.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const templates = DrawingTemplates.getInstance()
|
|
83
|
+
* const preset = templates.getPreset('bullish')
|
|
84
|
+
* // Apply preset.styles to an overlay via chart.overrideOverlay(...)
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare class DrawingTemplates {
|
|
88
|
+
private static _instance;
|
|
89
|
+
private _custom;
|
|
90
|
+
private constructor();
|
|
91
|
+
static getInstance(): DrawingTemplates;
|
|
92
|
+
private _loadCustom;
|
|
93
|
+
private _saveCustom;
|
|
94
|
+
/** Return all presets (built-in first, then custom). */
|
|
95
|
+
getAll(): OverlayStylePreset[];
|
|
96
|
+
/** Return built-in presets only. */
|
|
97
|
+
getBuiltIn(): OverlayStylePreset[];
|
|
98
|
+
/** Return user-saved custom presets. */
|
|
99
|
+
getCustom(): OverlayStylePreset[];
|
|
100
|
+
/** Find a preset by id (searches built-ins then custom). */
|
|
101
|
+
getPreset(id: string): OverlayStylePreset | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Save a new custom preset (or overwrite an existing custom one with the same id).
|
|
104
|
+
* Note: built-in preset ids cannot be overwritten.
|
|
105
|
+
*/
|
|
106
|
+
saveCustomPreset(preset: OverlayStylePreset): void;
|
|
107
|
+
/** Delete a custom preset by id. Built-in presets cannot be deleted. */
|
|
108
|
+
deleteCustomPreset(id: string): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Apply a preset to an engine overlay via overrideOverlay.
|
|
111
|
+
* Returns the styles object ready to pass to `chart.overrideOverlay({ groupId, styles })`.
|
|
112
|
+
*/
|
|
113
|
+
toOverlayStyles(presetId: string): DrawingStyleTemplate | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Preview a preset on an overlay without saving it. The styles are applied
|
|
116
|
+
* temporarily via overrideOverlay. Combine with the revert function to
|
|
117
|
+
* restore the original styles after preview ends.
|
|
118
|
+
*
|
|
119
|
+
* @returns A revert function that restores the original styles.
|
|
120
|
+
*/
|
|
121
|
+
preview(presetId: string, overlayId: string, chart: {
|
|
122
|
+
overrideOverlay: (o: {
|
|
123
|
+
id?: string;
|
|
124
|
+
styles?: unknown;
|
|
125
|
+
}) => void;
|
|
126
|
+
getOverlays: () => Array<{
|
|
127
|
+
id: string;
|
|
128
|
+
styles: unknown;
|
|
129
|
+
}>;
|
|
130
|
+
}): (() => void) | null;
|
|
131
|
+
/**
|
|
132
|
+
* Apply a specific color to an individual drawing overlay by ID.
|
|
133
|
+
* Changes are persisted with the overlay (stored in overlay styles).
|
|
134
|
+
*/
|
|
135
|
+
static applyColor(chart: {
|
|
136
|
+
overrideOverlay: (o: {
|
|
137
|
+
id?: string;
|
|
138
|
+
styles?: unknown;
|
|
139
|
+
}) => void;
|
|
140
|
+
}, overlayId: string, color: string): void;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* PerformanceMode — data decimation and virtualization utilities.
|
|
145
|
+
*
|
|
146
|
+
* Use these when dealing with very large datasets to keep renders fast:
|
|
147
|
+
* - `decimate(data, maxBars)` — LTTB downsampling
|
|
148
|
+
* - `virtualizeWindow(data, start, end, buffer)` — windowed slice
|
|
149
|
+
* - `shouldDecimate(length, threshold?)` — quick heuristic
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Transform standard OHLCV bars into Heikin-Ashi candles.
|
|
154
|
+
*
|
|
155
|
+
* Heikin-Ashi candles use averaged values to filter out market noise:
|
|
156
|
+
* ha_close = (open + high + low + close) / 4
|
|
157
|
+
* ha_open = (prev_ha_open + prev_ha_close) / 2
|
|
158
|
+
* ha_high = max(high, ha_open, ha_close)
|
|
159
|
+
* ha_low = min(low, ha_open, ha_close)
|
|
160
|
+
*
|
|
161
|
+
* @param data Source candlestick data
|
|
162
|
+
* @returns New array of Heikin-Ashi candles (same timestamps, volume, turnover)
|
|
163
|
+
*/
|
|
164
|
+
declare function heikinAshi(data: CandleData[]): CandleData[];
|
|
165
|
+
interface Bar {
|
|
166
|
+
timestamp: number;
|
|
167
|
+
open: number;
|
|
168
|
+
high: number;
|
|
169
|
+
low: number;
|
|
170
|
+
close: number;
|
|
171
|
+
volume?: number;
|
|
172
|
+
[key: string]: unknown;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Downsample `data` to `targetCount` points using the LTTB algorithm.
|
|
176
|
+
* Always preserves the first and last bar. Returns a new array.
|
|
177
|
+
*/
|
|
178
|
+
declare function decimate<T extends Bar>(data: T[], targetCount: number): T[];
|
|
179
|
+
/**
|
|
180
|
+
* Return only the bars within [visibleStart, visibleEnd] timestamps,
|
|
181
|
+
* extended by `buffer` bars on each side to support look-back indicators.
|
|
182
|
+
*/
|
|
183
|
+
declare function virtualizeWindow<T extends Bar>(data: T[], visibleStart: number, visibleEnd: number, buffer?: number): T[];
|
|
184
|
+
/**
|
|
185
|
+
* Returns true when the dataset is large enough that decimation makes sense.
|
|
186
|
+
* @param dataLength - Total number of bars in the dataset
|
|
187
|
+
* @param threshold - Bar count threshold, default 5000
|
|
188
|
+
*/
|
|
189
|
+
declare function shouldDecimate(dataLength: number, threshold?: number): boolean;
|
|
190
|
+
declare class PerformanceMode {
|
|
191
|
+
static decimate: typeof decimate;
|
|
192
|
+
static virtualizeWindow: typeof virtualizeWindow;
|
|
193
|
+
static shouldDecimate: typeof shouldDecimate;
|
|
194
|
+
static heikinAshi: typeof heikinAshi;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
var indicator = "Indicator";
|
|
198
|
+
var main_indicator = "Main Indicator";
|
|
199
|
+
var sub_indicator = "Sub Indicator";
|
|
200
|
+
var setting = "Setting";
|
|
201
|
+
var timezone = "Timezone";
|
|
202
|
+
var screenshot = "Screenshot";
|
|
203
|
+
var full_screen = "Full Screen";
|
|
204
|
+
var exit_full_screen = "Exit";
|
|
205
|
+
var save = "Save";
|
|
206
|
+
var confirm = "Confirm";
|
|
207
|
+
var color = "Color";
|
|
208
|
+
var show = "Show";
|
|
209
|
+
var cancel = "Cancel";
|
|
210
|
+
var ma = "MA(Moving Average)";
|
|
211
|
+
var ema = "EMA(Exponential Moving Average)";
|
|
212
|
+
var sma = "SMA";
|
|
213
|
+
var boll = "BOLL(Bolinger Bands)";
|
|
214
|
+
var bbi = "BBI(Bull And Bearlndex)";
|
|
215
|
+
var sar = "SAR(Stop and Reverse)";
|
|
216
|
+
var vol = "VOL(Volume)";
|
|
217
|
+
var macd = "MACD(Moving Average Convergence / Divergence)";
|
|
218
|
+
var kdj = "KDJ(KDJ Index)";
|
|
219
|
+
var rsi = "RSI(Relative Strength Index)";
|
|
220
|
+
var bias = "BIAS(Bias Ratio)";
|
|
221
|
+
var brar = "BRAR(Bull and Bear Sentiment)";
|
|
222
|
+
var cci = "CCI(Commodity Channel Index)";
|
|
223
|
+
var dmi = "DMI(Directional Movement Index)";
|
|
224
|
+
var cr = "CR(Energy Index)";
|
|
225
|
+
var psy = "PSY(Psychological Line)";
|
|
226
|
+
var dma = "DMA(Different of Moving Average)";
|
|
227
|
+
var trix = "TRIX(Triple Exponentially Smoothed Moving Average)";
|
|
228
|
+
var obv = "OBV(On Balance Volume)";
|
|
229
|
+
var vr = "VR(Volatility Volume Ratio)";
|
|
230
|
+
var wr = "WR(Williams %R)";
|
|
231
|
+
var mtm = "MTM(Momentum Index)";
|
|
232
|
+
var emv = "EMV(Ease of Movement Value)";
|
|
233
|
+
var roc = "ROC(Price Rate of Change)";
|
|
234
|
+
var pvt = "PVT(Price and Volume Trend)";
|
|
235
|
+
var ao = "AO(Awesome Oscillator)";
|
|
236
|
+
var utc = "UTC";
|
|
237
|
+
var honolulu = "(UTC-10) Honolulu";
|
|
238
|
+
var juneau = "(UTC-8) Juneau";
|
|
239
|
+
var los_angeles = "(UTC-7) Los Angeles";
|
|
240
|
+
var chicago = "(UTC-5) Chicago";
|
|
241
|
+
var toronto = "(UTC-4) Toronto";
|
|
242
|
+
var sao_paulo = "(UTC-3) Sao Paulo";
|
|
243
|
+
var london = "(UTC+1) London";
|
|
244
|
+
var berlin = "(UTC+2) Berlin";
|
|
245
|
+
var bahrain = "(UTC+3) Bahrain";
|
|
246
|
+
var dubai = "(UTC+4) Dubai";
|
|
247
|
+
var ashkhabad = "(UTC+5) Ashkhabad";
|
|
248
|
+
var almaty = "(UTC+6) Almaty";
|
|
249
|
+
var bangkok = "(UTC+7) Bangkok";
|
|
250
|
+
var shanghai = "(UTC+8) Shanghai";
|
|
251
|
+
var tokyo = "(UTC+9) Tokyo";
|
|
252
|
+
var sydney = "(UTC+10) Sydney";
|
|
253
|
+
var norfolk = "(UTC+12) Norfolk";
|
|
254
|
+
var horizontal_straight_line = "Horizontal Line";
|
|
255
|
+
var horizontal_ray_line = "Horizontal Ray";
|
|
256
|
+
var horizontal_segment = "Horizontal Segment";
|
|
257
|
+
var vertical_straight_line = "Vertical Line";
|
|
258
|
+
var vertical_ray_line = "Vertical Ray";
|
|
259
|
+
var vertical_segment = "Vertical Segment";
|
|
260
|
+
var straight_line = "Trend Line";
|
|
261
|
+
var ray_line = "Ray";
|
|
262
|
+
var segment = "Segment";
|
|
263
|
+
var arrow = "Arrow";
|
|
264
|
+
var price_line = "Price Line";
|
|
265
|
+
var price_channel_line = "Price Channel Line";
|
|
266
|
+
var parallel_straight_line = "Parallel Line";
|
|
267
|
+
var fibonacci_line = "Fibonacci Line";
|
|
268
|
+
var fibonacci_segment = "Fibonacci Segment";
|
|
269
|
+
var fibonacci_circle = "Fibonacci Circle";
|
|
270
|
+
var fibonacci_spiral = "Fibonacci Spiral";
|
|
271
|
+
var fibonacci_speed_resistance_fan = "Fibonacci Sector";
|
|
272
|
+
var fibonacci_extension = "Fibonacci Extension";
|
|
273
|
+
var gann_box = "Gann Box";
|
|
274
|
+
var gann_fan = "Gann Fan";
|
|
275
|
+
var pitchfork = "Andrews Pitchfork";
|
|
276
|
+
var rect = "Rect";
|
|
277
|
+
var parallelogram = "Parallelogram";
|
|
278
|
+
var circle = "Circle";
|
|
279
|
+
var triangle = "Triangle";
|
|
280
|
+
var three_waves = "Three Waves";
|
|
281
|
+
var five_waves = "Five Waves";
|
|
282
|
+
var eight_waves = "Eight Waves";
|
|
283
|
+
var any_waves = "Any Waves";
|
|
284
|
+
var abcd = "ABCD Pattern";
|
|
285
|
+
var xabcd = "XABCD Pattern";
|
|
286
|
+
var weak_magnet = "Weak Magnet";
|
|
287
|
+
var strong_magnet = "Strong Magnet";
|
|
288
|
+
var symbol_search = "Symbol Search";
|
|
289
|
+
var symbol_code = "Symbol Code";
|
|
290
|
+
var params_1 = "Parameter 1";
|
|
291
|
+
var params_2 = "Parameter 2";
|
|
292
|
+
var params_3 = "Parameter 3";
|
|
293
|
+
var params_4 = "Parameter 4";
|
|
294
|
+
var params_5 = "Parameter 5";
|
|
295
|
+
var line_1 = "Line 1";
|
|
296
|
+
var line_2 = "Line 2";
|
|
297
|
+
var line_3 = "Line 3";
|
|
298
|
+
var line_4 = "Line 4";
|
|
299
|
+
var line_5 = "Line 5";
|
|
300
|
+
var period = "Period";
|
|
301
|
+
var standard_deviation = "Standard Deviation";
|
|
302
|
+
var candle_type = "Candle Type";
|
|
303
|
+
var candle_solid = "Candle Solid";
|
|
304
|
+
var candle_stroke = "Candle Stroke";
|
|
305
|
+
var candle_up_stroke = "Candle Up Stroke";
|
|
306
|
+
var candle_down_stroke = "Candle Down Stroke";
|
|
307
|
+
var ohlc = "OHLC";
|
|
308
|
+
var area = "Area";
|
|
309
|
+
var last_price_show = "Show Last Price";
|
|
310
|
+
var high_price_show = "Show Highest Price";
|
|
311
|
+
var low_price_show = "Show Lowest Price";
|
|
312
|
+
var indicator_last_value_show = "Show indicator's last value";
|
|
313
|
+
var price_axis_type = "Price Axis Type";
|
|
314
|
+
var normal = "Normal";
|
|
315
|
+
var percentage = "Percentage";
|
|
316
|
+
var log = "Log";
|
|
317
|
+
var reverse_coordinate = "Reverse Coordinate";
|
|
318
|
+
var grid_show = "Show Grids";
|
|
319
|
+
var restore_default = "Restore Defaults";
|
|
320
|
+
var alerts = "Alerts";
|
|
321
|
+
var alert_create = "Create";
|
|
322
|
+
var alert_history = "History";
|
|
323
|
+
var alert_condition = "Condition";
|
|
324
|
+
var alert_price = "Price";
|
|
325
|
+
var alert_note = "Note";
|
|
326
|
+
var alert_note_placeholder = "Optional label…";
|
|
327
|
+
var alert_add = "Add Alert";
|
|
328
|
+
var alert_active = "Active";
|
|
329
|
+
var alert_no_history = "No triggered alerts yet";
|
|
330
|
+
var alert_reactivate = "Re-activate";
|
|
331
|
+
var alert_above = "Above";
|
|
332
|
+
var alert_below = "Below";
|
|
333
|
+
var alert_crosses_above = "Crosses ↑";
|
|
334
|
+
var alert_crosses_below = "Crosses ↓";
|
|
335
|
+
var alert_trigger = "Trigger";
|
|
336
|
+
var alert_trigger_once = "Once only";
|
|
337
|
+
var alert_trigger_every_bar = "Every bar";
|
|
338
|
+
var alert_trigger_bar_close = "Once per bar close";
|
|
339
|
+
var alert_expiration = "Expiration";
|
|
340
|
+
var alert_expiration_open = "Open-ended";
|
|
341
|
+
var alert_expiration_1d = "In 1 day";
|
|
342
|
+
var alert_expiration_1w = "In 1 week";
|
|
343
|
+
var alert_expiration_1m = "In 1 month";
|
|
344
|
+
var alert_expiration_2m = "In 2 months";
|
|
345
|
+
var alert_message = "Message";
|
|
346
|
+
var alert_message_hint = "Sent as the webhook body when a webhook URL is set.";
|
|
347
|
+
var alert_webhook_body = "Webhook body";
|
|
348
|
+
var alert_notifications = "Notifications";
|
|
349
|
+
var alert_back = "Back";
|
|
350
|
+
var alert_apply = "Apply";
|
|
351
|
+
var alert_notif_app = "Notify in app";
|
|
352
|
+
var alert_notif_app_desc = "Provides a push notification in the mobile app.";
|
|
353
|
+
var alert_notif_toast = "Show toast notification";
|
|
354
|
+
var alert_notif_toast_desc = "Displays an onsite notification in the page corner.";
|
|
355
|
+
var alert_notif_email = "Send email";
|
|
356
|
+
var alert_notif_email_desc = "Sends an email to the address in your account settings.";
|
|
357
|
+
var alert_notif_webhook = "Webhook URL";
|
|
358
|
+
var alert_notif_webhook_desc = "Sends a POST request to your URL when the alert triggers.";
|
|
359
|
+
var alert_notif_sound = "Play sound";
|
|
360
|
+
var alert_notif_sound_desc = "Plays an audio cue when your alert triggers.";
|
|
361
|
+
var alert_notif_plaintext = "Send plain text";
|
|
362
|
+
var alert_notif_plaintext_desc = "Sends plain text to an alternative email.";
|
|
363
|
+
var alert_notif_none = "None";
|
|
364
|
+
var alert_webhook_valid = "Valid target URL";
|
|
365
|
+
var alert_webhook_invalid = "Invalid URL — use http(s)://, no private or localhost hosts";
|
|
366
|
+
var alert_sound_once = "Once";
|
|
367
|
+
var alert_sound_repeating = "Repeating";
|
|
368
|
+
var alert_schedule = "Notification schedule";
|
|
369
|
+
var alert_schedule_desc = "Notifications are muted outside this schedule.";
|
|
370
|
+
var alert_schedule_weekdays = "Weekdays";
|
|
371
|
+
var alert_schedule_working_hours = "Working hours (Mon–Fri 09:00–18:00)";
|
|
372
|
+
var alert_schedule_custom = "Custom";
|
|
373
|
+
var alert_webhook_delivered = "Delivered";
|
|
374
|
+
var alert_webhook_failed = "Failed";
|
|
375
|
+
var alert_webhook_sending = "Sending";
|
|
376
|
+
var alert_log = "Log";
|
|
377
|
+
var alert_clear_log = "Clear log";
|
|
378
|
+
var alert_actions = "Actions";
|
|
379
|
+
var alert_no_log = "No alerts triggered yet";
|
|
380
|
+
var alert_webhook_success = "Webhook successfully delivered";
|
|
381
|
+
var alert_webhook_failed_prefix = "Webhook delivery failed";
|
|
382
|
+
var alert_webhook_timeout = "request took too long and timed out";
|
|
383
|
+
var alert_webhook_learn_more = "Learn more";
|
|
384
|
+
var snap_levels = "Snap to price levels";
|
|
385
|
+
var no_magnet = "No snap";
|
|
386
|
+
var script_editor = "Script Editor";
|
|
387
|
+
var script_editor_hint = "Write JavaScript — uses Pine Script–inspired API with ta.* helpers";
|
|
388
|
+
var script_compile = "Compile";
|
|
389
|
+
var script_apply = "Add to Chart";
|
|
390
|
+
var script_compiled = "Compiled";
|
|
391
|
+
var script_api_ref = "API Reference";
|
|
392
|
+
var watchlist = "Watchlist";
|
|
393
|
+
var watchlist_new = "New Watchlist";
|
|
394
|
+
var watchlist_add_list = "Add watchlist";
|
|
395
|
+
var watchlist_delete_list = "Delete watchlist";
|
|
396
|
+
var watchlist_add_symbol = "Add";
|
|
397
|
+
var watchlist_remove_symbol = "Remove symbol";
|
|
398
|
+
var watchlist_enter_symbol = "Enter ticker…";
|
|
399
|
+
var enUS = {
|
|
400
|
+
indicator: indicator,
|
|
401
|
+
main_indicator: main_indicator,
|
|
402
|
+
sub_indicator: sub_indicator,
|
|
403
|
+
setting: setting,
|
|
404
|
+
timezone: timezone,
|
|
405
|
+
screenshot: screenshot,
|
|
406
|
+
full_screen: full_screen,
|
|
407
|
+
exit_full_screen: exit_full_screen,
|
|
408
|
+
save: save,
|
|
409
|
+
confirm: confirm,
|
|
410
|
+
color: color,
|
|
411
|
+
show: show,
|
|
412
|
+
cancel: cancel,
|
|
413
|
+
ma: ma,
|
|
414
|
+
ema: ema,
|
|
415
|
+
sma: sma,
|
|
416
|
+
boll: boll,
|
|
417
|
+
bbi: bbi,
|
|
418
|
+
sar: sar,
|
|
419
|
+
vol: vol,
|
|
420
|
+
macd: macd,
|
|
421
|
+
kdj: kdj,
|
|
422
|
+
rsi: rsi,
|
|
423
|
+
bias: bias,
|
|
424
|
+
brar: brar,
|
|
425
|
+
cci: cci,
|
|
426
|
+
dmi: dmi,
|
|
427
|
+
cr: cr,
|
|
428
|
+
psy: psy,
|
|
429
|
+
dma: dma,
|
|
430
|
+
trix: trix,
|
|
431
|
+
obv: obv,
|
|
432
|
+
vr: vr,
|
|
433
|
+
wr: wr,
|
|
434
|
+
mtm: mtm,
|
|
435
|
+
emv: emv,
|
|
436
|
+
roc: roc,
|
|
437
|
+
pvt: pvt,
|
|
438
|
+
ao: ao,
|
|
439
|
+
utc: utc,
|
|
440
|
+
honolulu: honolulu,
|
|
441
|
+
juneau: juneau,
|
|
442
|
+
los_angeles: los_angeles,
|
|
443
|
+
chicago: chicago,
|
|
444
|
+
toronto: toronto,
|
|
445
|
+
sao_paulo: sao_paulo,
|
|
446
|
+
london: london,
|
|
447
|
+
berlin: berlin,
|
|
448
|
+
bahrain: bahrain,
|
|
449
|
+
dubai: dubai,
|
|
450
|
+
ashkhabad: ashkhabad,
|
|
451
|
+
almaty: almaty,
|
|
452
|
+
bangkok: bangkok,
|
|
453
|
+
shanghai: shanghai,
|
|
454
|
+
tokyo: tokyo,
|
|
455
|
+
sydney: sydney,
|
|
456
|
+
norfolk: norfolk,
|
|
457
|
+
horizontal_straight_line: horizontal_straight_line,
|
|
458
|
+
horizontal_ray_line: horizontal_ray_line,
|
|
459
|
+
horizontal_segment: horizontal_segment,
|
|
460
|
+
vertical_straight_line: vertical_straight_line,
|
|
461
|
+
vertical_ray_line: vertical_ray_line,
|
|
462
|
+
vertical_segment: vertical_segment,
|
|
463
|
+
straight_line: straight_line,
|
|
464
|
+
ray_line: ray_line,
|
|
465
|
+
segment: segment,
|
|
466
|
+
arrow: arrow,
|
|
467
|
+
price_line: price_line,
|
|
468
|
+
price_channel_line: price_channel_line,
|
|
469
|
+
parallel_straight_line: parallel_straight_line,
|
|
470
|
+
fibonacci_line: fibonacci_line,
|
|
471
|
+
fibonacci_segment: fibonacci_segment,
|
|
472
|
+
fibonacci_circle: fibonacci_circle,
|
|
473
|
+
fibonacci_spiral: fibonacci_spiral,
|
|
474
|
+
fibonacci_speed_resistance_fan: fibonacci_speed_resistance_fan,
|
|
475
|
+
fibonacci_extension: fibonacci_extension,
|
|
476
|
+
gann_box: gann_box,
|
|
477
|
+
gann_fan: gann_fan,
|
|
478
|
+
pitchfork: pitchfork,
|
|
479
|
+
rect: rect,
|
|
480
|
+
parallelogram: parallelogram,
|
|
481
|
+
circle: circle,
|
|
482
|
+
triangle: triangle,
|
|
483
|
+
three_waves: three_waves,
|
|
484
|
+
five_waves: five_waves,
|
|
485
|
+
eight_waves: eight_waves,
|
|
486
|
+
any_waves: any_waves,
|
|
487
|
+
abcd: abcd,
|
|
488
|
+
xabcd: xabcd,
|
|
489
|
+
weak_magnet: weak_magnet,
|
|
490
|
+
strong_magnet: strong_magnet,
|
|
491
|
+
symbol_search: symbol_search,
|
|
492
|
+
symbol_code: symbol_code,
|
|
493
|
+
params_1: params_1,
|
|
494
|
+
params_2: params_2,
|
|
495
|
+
params_3: params_3,
|
|
496
|
+
params_4: params_4,
|
|
497
|
+
params_5: params_5,
|
|
498
|
+
line_1: line_1,
|
|
499
|
+
line_2: line_2,
|
|
500
|
+
line_3: line_3,
|
|
501
|
+
line_4: line_4,
|
|
502
|
+
line_5: line_5,
|
|
503
|
+
period: period,
|
|
504
|
+
standard_deviation: standard_deviation,
|
|
505
|
+
candle_type: candle_type,
|
|
506
|
+
candle_solid: candle_solid,
|
|
507
|
+
candle_stroke: candle_stroke,
|
|
508
|
+
candle_up_stroke: candle_up_stroke,
|
|
509
|
+
candle_down_stroke: candle_down_stroke,
|
|
510
|
+
ohlc: ohlc,
|
|
511
|
+
area: area,
|
|
512
|
+
last_price_show: last_price_show,
|
|
513
|
+
high_price_show: high_price_show,
|
|
514
|
+
low_price_show: low_price_show,
|
|
515
|
+
indicator_last_value_show: indicator_last_value_show,
|
|
516
|
+
price_axis_type: price_axis_type,
|
|
517
|
+
normal: normal,
|
|
518
|
+
percentage: percentage,
|
|
519
|
+
log: log,
|
|
520
|
+
reverse_coordinate: reverse_coordinate,
|
|
521
|
+
grid_show: grid_show,
|
|
522
|
+
restore_default: restore_default,
|
|
523
|
+
alerts: alerts,
|
|
524
|
+
alert_create: alert_create,
|
|
525
|
+
alert_history: alert_history,
|
|
526
|
+
alert_condition: alert_condition,
|
|
527
|
+
alert_price: alert_price,
|
|
528
|
+
alert_note: alert_note,
|
|
529
|
+
alert_note_placeholder: alert_note_placeholder,
|
|
530
|
+
alert_add: alert_add,
|
|
531
|
+
alert_active: alert_active,
|
|
532
|
+
alert_no_history: alert_no_history,
|
|
533
|
+
alert_reactivate: alert_reactivate,
|
|
534
|
+
alert_above: alert_above,
|
|
535
|
+
alert_below: alert_below,
|
|
536
|
+
alert_crosses_above: alert_crosses_above,
|
|
537
|
+
alert_crosses_below: alert_crosses_below,
|
|
538
|
+
alert_trigger: alert_trigger,
|
|
539
|
+
alert_trigger_once: alert_trigger_once,
|
|
540
|
+
alert_trigger_every_bar: alert_trigger_every_bar,
|
|
541
|
+
alert_trigger_bar_close: alert_trigger_bar_close,
|
|
542
|
+
alert_expiration: alert_expiration,
|
|
543
|
+
alert_expiration_open: alert_expiration_open,
|
|
544
|
+
alert_expiration_1d: alert_expiration_1d,
|
|
545
|
+
alert_expiration_1w: alert_expiration_1w,
|
|
546
|
+
alert_expiration_1m: alert_expiration_1m,
|
|
547
|
+
alert_expiration_2m: alert_expiration_2m,
|
|
548
|
+
alert_message: alert_message,
|
|
549
|
+
alert_message_hint: alert_message_hint,
|
|
550
|
+
alert_webhook_body: alert_webhook_body,
|
|
551
|
+
alert_notifications: alert_notifications,
|
|
552
|
+
alert_back: alert_back,
|
|
553
|
+
alert_apply: alert_apply,
|
|
554
|
+
alert_notif_app: alert_notif_app,
|
|
555
|
+
alert_notif_app_desc: alert_notif_app_desc,
|
|
556
|
+
alert_notif_toast: alert_notif_toast,
|
|
557
|
+
alert_notif_toast_desc: alert_notif_toast_desc,
|
|
558
|
+
alert_notif_email: alert_notif_email,
|
|
559
|
+
alert_notif_email_desc: alert_notif_email_desc,
|
|
560
|
+
alert_notif_webhook: alert_notif_webhook,
|
|
561
|
+
alert_notif_webhook_desc: alert_notif_webhook_desc,
|
|
562
|
+
alert_notif_sound: alert_notif_sound,
|
|
563
|
+
alert_notif_sound_desc: alert_notif_sound_desc,
|
|
564
|
+
alert_notif_plaintext: alert_notif_plaintext,
|
|
565
|
+
alert_notif_plaintext_desc: alert_notif_plaintext_desc,
|
|
566
|
+
alert_notif_none: alert_notif_none,
|
|
567
|
+
alert_webhook_valid: alert_webhook_valid,
|
|
568
|
+
alert_webhook_invalid: alert_webhook_invalid,
|
|
569
|
+
alert_sound_once: alert_sound_once,
|
|
570
|
+
alert_sound_repeating: alert_sound_repeating,
|
|
571
|
+
alert_schedule: alert_schedule,
|
|
572
|
+
alert_schedule_desc: alert_schedule_desc,
|
|
573
|
+
"alert_schedule_24/7": "24/7",
|
|
574
|
+
alert_schedule_weekdays: alert_schedule_weekdays,
|
|
575
|
+
alert_schedule_working_hours: alert_schedule_working_hours,
|
|
576
|
+
alert_schedule_custom: alert_schedule_custom,
|
|
577
|
+
alert_webhook_delivered: alert_webhook_delivered,
|
|
578
|
+
alert_webhook_failed: alert_webhook_failed,
|
|
579
|
+
alert_webhook_sending: alert_webhook_sending,
|
|
580
|
+
alert_log: alert_log,
|
|
581
|
+
alert_clear_log: alert_clear_log,
|
|
582
|
+
alert_actions: alert_actions,
|
|
583
|
+
alert_no_log: alert_no_log,
|
|
584
|
+
alert_webhook_success: alert_webhook_success,
|
|
585
|
+
alert_webhook_failed_prefix: alert_webhook_failed_prefix,
|
|
586
|
+
alert_webhook_timeout: alert_webhook_timeout,
|
|
587
|
+
alert_webhook_learn_more: alert_webhook_learn_more,
|
|
588
|
+
snap_levels: snap_levels,
|
|
589
|
+
no_magnet: no_magnet,
|
|
590
|
+
script_editor: script_editor,
|
|
591
|
+
script_editor_hint: script_editor_hint,
|
|
592
|
+
script_compile: script_compile,
|
|
593
|
+
script_apply: script_apply,
|
|
594
|
+
script_compiled: script_compiled,
|
|
595
|
+
script_api_ref: script_api_ref,
|
|
596
|
+
watchlist: watchlist,
|
|
597
|
+
watchlist_new: watchlist_new,
|
|
598
|
+
watchlist_add_list: watchlist_add_list,
|
|
599
|
+
watchlist_delete_list: watchlist_delete_list,
|
|
600
|
+
watchlist_add_symbol: watchlist_add_symbol,
|
|
601
|
+
watchlist_remove_symbol: watchlist_remove_symbol,
|
|
602
|
+
watchlist_enter_symbol: watchlist_enter_symbol
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
type LocaleKey = keyof typeof enUS;
|
|
606
|
+
type LocaleMap = Partial<Record<LocaleKey, string>>;
|
|
607
|
+
/**
|
|
608
|
+
* Register a locale dictionary explicitly. Use this to ship your own
|
|
609
|
+
* translations or to override a built-in locale at runtime.
|
|
610
|
+
*/
|
|
611
|
+
declare function load(key: string, ls: LocaleMap): void;
|
|
612
|
+
/**
|
|
613
|
+
* Asynchronously load one of the built-in locales. Resolves with the
|
|
614
|
+
* dictionary, or `null` when the locale is not a built-in (already
|
|
615
|
+
* loaded locales return the cached map). Subsequent lookups for that
|
|
616
|
+
* locale will return its translations.
|
|
617
|
+
*
|
|
618
|
+
* ```ts
|
|
619
|
+
* await loadLocale('ja-JP')
|
|
620
|
+
* chartRef.current?.setLocale('ja-JP')
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
declare function loadLocale(key: string): Promise<LocaleMap | null>;
|
|
624
|
+
/** Names of all built-in locales that can be passed to `loadLocale`. */
|
|
625
|
+
declare const BUILTIN_LOCALES: ReadonlyArray<string>;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Locale-aware number and date formatting utilities.
|
|
629
|
+
* Uses the native Intl API — no extra dependencies.
|
|
630
|
+
*/
|
|
631
|
+
interface FormatPriceOptions {
|
|
632
|
+
/** Number of decimal places. Defaults to 2. */
|
|
633
|
+
precision?: number;
|
|
634
|
+
/** Whether to show compact notation (1.2K, 3.4M). Defaults to false. */
|
|
635
|
+
compact?: boolean;
|
|
636
|
+
/** Currency code, e.g. "USD". When provided, formats as currency. */
|
|
637
|
+
currency?: string;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Format a price / numeric value for display.
|
|
641
|
+
*
|
|
642
|
+
* @example
|
|
643
|
+
* formatPrice(1234567.891, 'en-US', { precision: 2 }) // "1,234,567.89"
|
|
644
|
+
* formatPrice(1234567.891, 'de-DE', { precision: 2 }) // "1.234.567,89"
|
|
645
|
+
* formatPrice(1234567, 'en-US', { compact: true }) // "1.2M"
|
|
646
|
+
* formatPrice(1234.5, 'en-US', { currency: 'USD' }) // "$1,234.50"
|
|
647
|
+
*/
|
|
648
|
+
declare function formatPrice(value: number, locale: string, options?: FormatPriceOptions): string;
|
|
649
|
+
/**
|
|
650
|
+
* Format a volume number compactly.
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* formatVolume(1234567, 'en-US') // "1.2M"
|
|
654
|
+
* formatVolume(54321, 'zh-CN') // "5.4万"
|
|
655
|
+
*/
|
|
656
|
+
declare function formatVolume(value: number, locale: string): string;
|
|
657
|
+
/**
|
|
658
|
+
* Format a percentage value.
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* formatPercent(0.0523, 'en-US') // "5.23%"
|
|
662
|
+
* formatPercent(-0.012, 'fr-FR') // "-1,20 %"
|
|
663
|
+
*/
|
|
664
|
+
declare function formatPercent(value: number, locale: string, precision?: number): string;
|
|
665
|
+
type DateFormatStyle = 'short' | 'medium' | 'long' | 'full';
|
|
666
|
+
type TimeFormatStyle = 'short' | 'medium';
|
|
667
|
+
/**
|
|
668
|
+
* Format a UNIX timestamp (ms or s) as a locale-aware date string.
|
|
669
|
+
*
|
|
670
|
+
* @param timestamp UNIX timestamp in milliseconds (or seconds — auto-detected)
|
|
671
|
+
* @param locale BCP-47 locale string, e.g. "en-US"
|
|
672
|
+
* @param style Intl DateTimeFormat date style
|
|
673
|
+
*/
|
|
674
|
+
declare function formatDate(timestamp: number, locale: string, style?: DateFormatStyle): string;
|
|
675
|
+
/**
|
|
676
|
+
* Format a UNIX timestamp as a locale-aware time string.
|
|
677
|
+
*/
|
|
678
|
+
declare function formatTime(timestamp: number, locale: string, style?: TimeFormatStyle): string;
|
|
679
|
+
/**
|
|
680
|
+
* Format a UNIX timestamp as a combined date+time string.
|
|
681
|
+
*/
|
|
682
|
+
declare function formatDateTime(timestamp: number, locale: string, dateStyle?: DateFormatStyle, timeStyle?: TimeFormatStyle): string;
|
|
683
|
+
/**
|
|
684
|
+
* Format a duration in milliseconds as a human-readable string.
|
|
685
|
+
* Uses RelativeTimeFormat for relative phrases when |ms| < threshold.
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* formatDuration(60_000, 'en-US') // "1 minute"
|
|
689
|
+
* formatDuration(3_600_000, 'de-DE') // "1 Stunde"
|
|
690
|
+
*/
|
|
691
|
+
declare function formatDuration(ms: number, locale: string): string;
|
|
692
|
+
/**
|
|
693
|
+
* Format a Period as a short locale-aware timeframe label.
|
|
694
|
+
*
|
|
695
|
+
* @example
|
|
696
|
+
* formatPeriod({ multiplier: 1, timespan: 'minute' }, 'en-US') // "1m"
|
|
697
|
+
* formatPeriod({ multiplier: 4, timespan: 'hour' }, 'zh-CN') // "4时"
|
|
698
|
+
* formatPeriod({ multiplier: 1, timespan: 'day' }, 'en-US') // "1D"
|
|
699
|
+
*/
|
|
700
|
+
declare function formatPeriod(period: {
|
|
701
|
+
multiplier: number;
|
|
702
|
+
timespan: string;
|
|
703
|
+
}, locale: string): string;
|
|
704
|
+
/**
|
|
705
|
+
* Detect an appropriate number of decimal places for a given price.
|
|
706
|
+
* Useful when `pricePrecision` is not specified on a SymbolInfo.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* detectPricePrecision(0.00001234) // 8
|
|
710
|
+
* detectPricePrecision(1234.56) // 2
|
|
711
|
+
* detectPricePrecision(50000) // 0
|
|
712
|
+
*/
|
|
713
|
+
declare function detectPricePrecision(price: number): number;
|
|
714
|
+
|
|
715
|
+
type NormalizedIndicatorRow = Record<string, number | null>;
|
|
716
|
+
declare function createIndicatorTemplateFromPlugin<TOutput>(plugin: IndicatorPlugin<TOutput>): IndicatorTemplate<NormalizedIndicatorRow, number>;
|
|
717
|
+
declare function registerIndicatorPlugin<TOutput>(plugin: IndicatorPlugin<TOutput>): void;
|
|
718
|
+
declare function registerIndicatorPlugins(plugins: ReadonlyArray<IndicatorPlugin<unknown>>): void;
|
|
719
|
+
|
|
720
|
+
/** Cast a raw number to the Price brand. Use only when the number is known to be a price. */
|
|
721
|
+
declare function asPrice(n: number): Price;
|
|
722
|
+
/** Cast a raw number to the Volume brand. Use only when the number is known to be a volume. */
|
|
723
|
+
declare function asVolume(n: number): Volume;
|
|
724
|
+
/** Cast a raw number to the Timestamp brand (milliseconds). Use only at data ingress. */
|
|
725
|
+
declare function asTimestamp(n: number): Timestamp;
|
|
726
|
+
/**
|
|
727
|
+
* Returns a dispatcher that schedules `fn` on the next animation frame,
|
|
728
|
+
* coalescing rapid calls so only the last value is delivered.
|
|
729
|
+
*
|
|
730
|
+
* @example
|
|
731
|
+
* const dispatch = rafCoalesce((tick: CandleData) => chart.update(tick))
|
|
732
|
+
* ws.onmessage = e => dispatch(parse(e.data)) // safe to call 100×/s
|
|
733
|
+
*/
|
|
734
|
+
declare function rafCoalesce<T>(fn: (value: T) => void): (value: T) => void;
|
|
735
|
+
/**
|
|
736
|
+
* OHLCV-aware frame-coalescing scheduler for financial tick streams.
|
|
737
|
+
*
|
|
738
|
+
* Unlike `rafCoalesce` (which drops intermediate values), `rafMergeTick`
|
|
739
|
+
* merges multiple ticks that arrive within a single animation frame into
|
|
740
|
+
* one financially accurate OHLCV bar:
|
|
741
|
+
*
|
|
742
|
+
* open = first tick's open (bar opening price)
|
|
743
|
+
* high = max across all ticks (price extreme)
|
|
744
|
+
* low = min across all ticks (price extreme)
|
|
745
|
+
* close = last tick's close (current price)
|
|
746
|
+
* volume = sum of all volumes (accurate volume)
|
|
747
|
+
*
|
|
748
|
+
* This is the correct coalescer for financial charting:
|
|
749
|
+
* - Never loses high/low extremes (important for candle accuracy)
|
|
750
|
+
* - Never loses volume (critical for volume indicators)
|
|
751
|
+
* - Delivers one merged tick per rAF frame — O(1) render cost
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* const dispatch = rafMergeTick((merged) => chart.updateData(merged))
|
|
755
|
+
* ws.onmessage = e => dispatch(parseTick(e.data)) // safe to call 500×/s
|
|
756
|
+
*/
|
|
757
|
+
declare function rafMergeTick(fn: (tick: CandleData) => void): (tick: CandleData) => void;
|
|
758
|
+
declare function deepSet(obj: object, path: string, value: unknown): void;
|
|
759
|
+
declare function deepClone<T>(obj: T): T;
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* EventBus — type-safe, zero-dependency synchronous event bus.
|
|
763
|
+
*
|
|
764
|
+
* Usage:
|
|
765
|
+
* const bus = new EventBus<ChartEventMap>()
|
|
766
|
+
* const off = bus.on('tick', candle => chart.update(candle))
|
|
767
|
+
* bus.emit('tick', newCandle)
|
|
768
|
+
* off() // unsubscribe
|
|
769
|
+
*
|
|
770
|
+
* Performance characteristics:
|
|
771
|
+
* - O(n_listeners) per emit — keep listener count low in hot paths
|
|
772
|
+
* - All events are synchronous and ordered (FIFO within an event key)
|
|
773
|
+
* - No allocations on emit when there are no listeners for the key
|
|
774
|
+
*/
|
|
775
|
+
type ListenerOf<TMap, K extends keyof TMap> = (payload: TMap[K]) => void;
|
|
776
|
+
declare class EventBus<TMap extends Record<string, unknown>> {
|
|
777
|
+
private readonly _listeners;
|
|
778
|
+
/**
|
|
779
|
+
* Subscribe to an event. Returns an unsubscribe function.
|
|
780
|
+
* The returned function is idempotent — safe to call multiple times.
|
|
781
|
+
*/
|
|
782
|
+
on<K extends keyof TMap>(event: K, listener: ListenerOf<TMap, K>): () => void;
|
|
783
|
+
/** Unsubscribe a specific listener. No-op if not currently subscribed. */
|
|
784
|
+
off<K extends keyof TMap>(event: K, listener: ListenerOf<TMap, K>): void;
|
|
785
|
+
/** Emit an event, invoking all registered listeners synchronously. */
|
|
786
|
+
emit<K extends keyof TMap>(event: K, payload: TMap[K]): void;
|
|
787
|
+
/**
|
|
788
|
+
* Clear all listeners for a specific event, or all listeners when called
|
|
789
|
+
* with no argument (useful for component teardown).
|
|
790
|
+
*/
|
|
791
|
+
clear(event?: keyof TMap): void;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* TickAnimator — smoothly interpolates the last candlestick bar as live ticks arrive.
|
|
796
|
+
*
|
|
797
|
+
* Problem it solves:
|
|
798
|
+
* Raw WebSocket ticks arrive at irregular bursts (10–500 ms apart). Without
|
|
799
|
+
* animation, the last bar jumps discretely on every tick — jarring at high
|
|
800
|
+
* update rates. TickAnimator interpolates close/high/low between the previous
|
|
801
|
+
* and next confirmed values over a configurable `duration` (default 120 ms),
|
|
802
|
+
* targeting 60–120 fps via requestAnimationFrame.
|
|
803
|
+
*
|
|
804
|
+
* Design rules (per SKILL.md):
|
|
805
|
+
* - Zero allocations inside the rAF loop — all state is pre-allocated
|
|
806
|
+
* - Uses `performance.now()` for sub-millisecond frame timing
|
|
807
|
+
* - Single rAF handle — never stacks multiple loops
|
|
808
|
+
* - Price fields use the branded Price type (compatible with engine CandleData)
|
|
809
|
+
*
|
|
810
|
+
* Usage:
|
|
811
|
+
* const animator = new TickAnimator((interpolated) => chart.updateData(interpolated))
|
|
812
|
+
* ws.onmessage = e => animator.feed(parsedTick)
|
|
813
|
+
* // On symbol change / cleanup:
|
|
814
|
+
* animator.cancel()
|
|
815
|
+
*/
|
|
816
|
+
|
|
817
|
+
interface TickAnimatorOptions {
|
|
818
|
+
/**
|
|
819
|
+
* Duration of the interpolation animation in milliseconds.
|
|
820
|
+
* Lower = more responsive but less smooth.
|
|
821
|
+
* Higher = smoother but introduces lag.
|
|
822
|
+
* Default: 120ms (≈7 frames at 60fps, ≈12 frames at 100fps).
|
|
823
|
+
*/
|
|
824
|
+
duration?: number;
|
|
825
|
+
/**
|
|
826
|
+
* Interpolation easing profile.
|
|
827
|
+
* - 'easeOut' (default): snappy response that settles smoothly.
|
|
828
|
+
* - 'linear': constant-speed interpolation, better for video-like motion.
|
|
829
|
+
*/
|
|
830
|
+
easing?: 'easeOut' | 'linear';
|
|
831
|
+
}
|
|
832
|
+
declare class TickAnimator {
|
|
833
|
+
private readonly _onFrame;
|
|
834
|
+
private readonly _duration;
|
|
835
|
+
private readonly _easing;
|
|
836
|
+
/** Snapshot of the bar at the moment the last tick arrived (animation start). */
|
|
837
|
+
private _fromClose;
|
|
838
|
+
private _fromHigh;
|
|
839
|
+
private _fromLow;
|
|
840
|
+
/** Target values (the actual received tick). */
|
|
841
|
+
private _toClose;
|
|
842
|
+
private _toHigh;
|
|
843
|
+
private _toLow;
|
|
844
|
+
/** Stable fields that don't animate. */
|
|
845
|
+
private _timestamp;
|
|
846
|
+
private _open;
|
|
847
|
+
private _volume;
|
|
848
|
+
private _turnover;
|
|
849
|
+
/** Reused output object — written in-place every rAF frame. No allocation.
|
|
850
|
+
* @warning Consumers MUST NOT retain or mutate this object. It is reused
|
|
851
|
+
* across frames — storing a reference will see stale/corrupted data. */
|
|
852
|
+
private readonly _frame;
|
|
853
|
+
private _startTime;
|
|
854
|
+
private _rafId;
|
|
855
|
+
private _running;
|
|
856
|
+
constructor(onFrame: (tick: CandleData) => void, options?: TickAnimatorOptions);
|
|
857
|
+
/**
|
|
858
|
+
* Feed a new confirmed tick.
|
|
859
|
+
* Starts (or restarts) the interpolation from the last rendered state to `next`.
|
|
860
|
+
* Safe to call at any rate — will coalesce intermediate ticks automatically
|
|
861
|
+
* by updating the target (`_to*`) without resetting the start time.
|
|
862
|
+
*/
|
|
863
|
+
feed(next: CandleData): void;
|
|
864
|
+
/**
|
|
865
|
+
* Cancel the running animation (e.g., on symbol change, unmount).
|
|
866
|
+
* Safe to call at any time, including when not animating.
|
|
867
|
+
*/
|
|
868
|
+
cancel(): void;
|
|
869
|
+
private _elapsed;
|
|
870
|
+
private _tick;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* RingBuffer<T> — fixed-capacity circular buffer with O(1) append, prepend, and index access.
|
|
875
|
+
*
|
|
876
|
+
* Purpose: streaming time-series data (candles, ticks) that grows at the tail
|
|
877
|
+
* and drops the oldest bar at the head when capacity is exceeded.
|
|
878
|
+
* Avoids the O(n) cost of Array.splice() during live streaming.
|
|
879
|
+
*
|
|
880
|
+
* Capacity design: set to your desired visible bar count × 2–4× for history.
|
|
881
|
+
* At 1 tick/second and 4h of data: 14_400 bars → use capacity = 32_768.
|
|
882
|
+
*
|
|
883
|
+
* @example
|
|
884
|
+
* const bars = new RingBuffer<CandleData>(8192)
|
|
885
|
+
* bars.push(tick) // O(1) — auto-drops oldest when full
|
|
886
|
+
* const last = bars.last() // O(1)
|
|
887
|
+
* const bar = bars.at(-1) // O(1) — negative index from tail
|
|
888
|
+
* bars.updateLast(merged) // O(1) — in-place last bar update
|
|
889
|
+
*/
|
|
890
|
+
declare class RingBuffer<T> {
|
|
891
|
+
private readonly _buf;
|
|
892
|
+
private readonly _capacity;
|
|
893
|
+
/** Index of the oldest item (logical position 0). */
|
|
894
|
+
private _head;
|
|
895
|
+
/** Total items ever written — from this we derive the current fill and tail. */
|
|
896
|
+
private _size;
|
|
897
|
+
constructor(capacity: number);
|
|
898
|
+
get length(): number;
|
|
899
|
+
get capacity(): number;
|
|
900
|
+
get isFull(): boolean;
|
|
901
|
+
/**
|
|
902
|
+
* Append an item to the tail.
|
|
903
|
+
* When full, silently overwrites (and advances) the oldest item.
|
|
904
|
+
*/
|
|
905
|
+
push(item: T): void;
|
|
906
|
+
/**
|
|
907
|
+
* Replace the last item in-place.
|
|
908
|
+
* Used to update the current live bar with a new tick merge result.
|
|
909
|
+
* O(1) — no allocation.
|
|
910
|
+
*/
|
|
911
|
+
updateLast(item: T): void;
|
|
912
|
+
/**
|
|
913
|
+
* Access item at logical index.
|
|
914
|
+
* Positive: 0 = oldest, `length - 1` = newest.
|
|
915
|
+
* Negative: -1 = newest, -length = oldest.
|
|
916
|
+
* Returns `undefined` when out of bounds.
|
|
917
|
+
*/
|
|
918
|
+
at(index: number): T | undefined;
|
|
919
|
+
/** Most recently pushed item. O(1). */
|
|
920
|
+
last(): T | undefined;
|
|
921
|
+
/** Oldest item still in the buffer. O(1). */
|
|
922
|
+
first(): T | undefined;
|
|
923
|
+
/**
|
|
924
|
+
* Iterate from oldest to newest without allocating a copy.
|
|
925
|
+
* Uses a standard iterator protocol so it works with `for…of`.
|
|
926
|
+
*/
|
|
927
|
+
[Symbol.iterator](): Iterator<T>;
|
|
928
|
+
/**
|
|
929
|
+
* Return a dense snapshot copy as a plain array, oldest → newest.
|
|
930
|
+
* O(n). Use sparingly — this allocates. Prefer `at()` / iteration.
|
|
931
|
+
*/
|
|
932
|
+
toArray(): T[];
|
|
933
|
+
clear(): void;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* UndoManager — tracks chart overlay mutations for Ctrl+Z / Ctrl+Y support.
|
|
938
|
+
*
|
|
939
|
+
* Every createOverlay / removeOverlay / overrideOverlay is recorded as a
|
|
940
|
+
* snapshot of the full overlay list. Undo pops the stack and restores.
|
|
941
|
+
*
|
|
942
|
+
* Usage:
|
|
943
|
+
* const undo = new UndoManager(chart)
|
|
944
|
+
* chart.createOverlay(...)
|
|
945
|
+
* undo.record() // call after every mutation
|
|
946
|
+
* undo.undo() // Ctrl+Z
|
|
947
|
+
* undo.redo() // Ctrl+Y
|
|
948
|
+
*/
|
|
949
|
+
declare class UndoManager {
|
|
950
|
+
private readonly _chart;
|
|
951
|
+
private _stack;
|
|
952
|
+
private _redoStack;
|
|
953
|
+
private _maxDepth;
|
|
954
|
+
private _lastSnapshot;
|
|
955
|
+
constructor(chart: AstroneumHandle, maxDepth?: number);
|
|
956
|
+
/** Record current overlay state. Call after every overlay mutation. */
|
|
957
|
+
record(): void;
|
|
958
|
+
/** Undo last mutation. Returns true if an undo was performed. */
|
|
959
|
+
undo(): boolean;
|
|
960
|
+
/** Redo last undone mutation. Returns true if a redo was performed. */
|
|
961
|
+
redo(): boolean;
|
|
962
|
+
/** Clear all undo/redo history. */
|
|
963
|
+
clear(): void;
|
|
964
|
+
get canUndo(): boolean;
|
|
965
|
+
get canRedo(): boolean;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* SessionVisualizer — renders session breaks, extended-hours shading, and
|
|
970
|
+
* session extremes (high/low/open/close) as persistent chart overlays.
|
|
971
|
+
*
|
|
972
|
+
* Usage:
|
|
973
|
+
* const sv = new SessionVisualizer(chart, { timezone: 'America/New_York' })
|
|
974
|
+
* sv.enable()
|
|
975
|
+
* // session breaks and extremes auto-update when the chart scrolls/zooms
|
|
976
|
+
* sv.disable()
|
|
977
|
+
*/
|
|
978
|
+
|
|
979
|
+
interface SessionConfig {
|
|
980
|
+
/** IANA timezone, e.g. 'America/New_York'. Default: 'America/New_York' */
|
|
981
|
+
timezone?: string;
|
|
982
|
+
/** Regular market open hour (0-23) in the configured timezone. Default: 9 (9:30 AM ET) */
|
|
983
|
+
openHour?: number;
|
|
984
|
+
/** Regular market open minute. Default: 30 */
|
|
985
|
+
openMinute?: number;
|
|
986
|
+
/** Regular market close hour. Default: 16 (4:00 PM ET) */
|
|
987
|
+
closeHour?: number;
|
|
988
|
+
/** Regular market close minute. Default: 0 */
|
|
989
|
+
closeMinute?: number;
|
|
990
|
+
/** Whether to show extended-hours shading. Default: true */
|
|
991
|
+
showExtendedHours?: boolean;
|
|
992
|
+
/** Whether to show session high/low/open/close lines. Default: true */
|
|
993
|
+
showSessionLevels?: boolean;
|
|
994
|
+
}
|
|
995
|
+
declare class SessionVisualizer {
|
|
996
|
+
private _chart;
|
|
997
|
+
private _config;
|
|
998
|
+
private _enabled;
|
|
999
|
+
private _animFrame;
|
|
1000
|
+
constructor(chart: Chart, config?: SessionConfig);
|
|
1001
|
+
get enabled(): boolean;
|
|
1002
|
+
enable(): void;
|
|
1003
|
+
disable(): void;
|
|
1004
|
+
toggle(): void;
|
|
1005
|
+
/** Call when the chart scrolls/zooms. Debounced via rAF. */
|
|
1006
|
+
refresh(): void;
|
|
1007
|
+
private _refresh;
|
|
1008
|
+
private _removeGuides;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Volume Profile indicator — horizontal histogram of volume at each price level.
|
|
1013
|
+
*
|
|
1014
|
+
* Usage:
|
|
1015
|
+
* import { volumeProfilePlugin } from '@tony01/astroneum'
|
|
1016
|
+
* registerIndicatorPlugin(volumeProfilePlugin)
|
|
1017
|
+
* chart.createIndicator({ name: 'volume_profile' })
|
|
1018
|
+
*
|
|
1019
|
+
* Or set it as a sub-indicator:
|
|
1020
|
+
* <AstroneumChart subIndicators={['VOL', 'volume_profile']} />
|
|
1021
|
+
*/
|
|
1022
|
+
interface VolumeProfileRow {
|
|
1023
|
+
price: number;
|
|
1024
|
+
volume: number;
|
|
1025
|
+
/** Cumulative volume from top → this level */
|
|
1026
|
+
cumulative: number;
|
|
1027
|
+
}
|
|
1028
|
+
declare const volumeProfilePlugin: IndicatorPlugin<VolumeProfileRow>;
|
|
1029
|
+
|
|
1030
|
+
interface ChartTemplate {
|
|
1031
|
+
id: string;
|
|
1032
|
+
name: string;
|
|
1033
|
+
state: SerializedChartState;
|
|
1034
|
+
createdAt: string;
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* ChartTemplateManager — save/load named chart configurations.
|
|
1038
|
+
*
|
|
1039
|
+
* Templates persist to localStorage and include theme, locale, timezone,
|
|
1040
|
+
* styles, indicators, and overlay state. Symbols and periods are intentionally
|
|
1041
|
+
* NOT included — templates apply chart settings to any symbol.
|
|
1042
|
+
*
|
|
1043
|
+
* Usage:
|
|
1044
|
+
* const templates = ChartTemplateManager.getInstance()
|
|
1045
|
+
* templates.save('My Setup', chart.serializeState())
|
|
1046
|
+
* templates.load('My Setup', chart) // applies to current chart
|
|
1047
|
+
*/
|
|
1048
|
+
declare class ChartTemplateManager {
|
|
1049
|
+
private static _instance;
|
|
1050
|
+
private _templates;
|
|
1051
|
+
private constructor();
|
|
1052
|
+
static getInstance(): ChartTemplateManager;
|
|
1053
|
+
/** Save current chart state as a named template. Overwrites if name exists. */
|
|
1054
|
+
save(name: string, state: SerializedChartState): ChartTemplate;
|
|
1055
|
+
/** Load a template onto a chart. Returns false if template not found. */
|
|
1056
|
+
load(name: string, chart: AstroneumHandle): boolean;
|
|
1057
|
+
/** Delete a template by name. Returns false if not found. */
|
|
1058
|
+
delete(name: string): boolean;
|
|
1059
|
+
/** List all saved template names. */
|
|
1060
|
+
list(): string[];
|
|
1061
|
+
/** Get a template by name. */
|
|
1062
|
+
get(name: string): ChartTemplate | undefined;
|
|
1063
|
+
/** Get all templates. */
|
|
1064
|
+
getAll(): ChartTemplate[];
|
|
1065
|
+
private _persist;
|
|
1066
|
+
private _load;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Build a higher-timeframe bar array from lower-TF data using OHLCV resampling.
|
|
1071
|
+
*
|
|
1072
|
+
* This is a client-side resampler — it aggregates lower-TF bars into higher-TF
|
|
1073
|
+
* bars without requiring a second datafeed subscription. The output can be fed
|
|
1074
|
+
* to any indicator calc function that expects CandleData[].
|
|
1075
|
+
*
|
|
1076
|
+
* @example
|
|
1077
|
+
* ```ts
|
|
1078
|
+
* // Resample 15m bars to 4H bars
|
|
1079
|
+
* const h4Bars = resampleBars(bars15m, { multiplier: 4, timespan: 'hour', text: '4H' })
|
|
1080
|
+
* const ema4h = sma(h4Bars.map(b => b.close), 21)
|
|
1081
|
+
*
|
|
1082
|
+
* // Forward-fill to align with lower-TF bars
|
|
1083
|
+
* const aligned = forwardFill(h4Bars, bars15m)
|
|
1084
|
+
* ```
|
|
1085
|
+
*
|
|
1086
|
+
* @param data Source lower-timeframe bars (must be sorted ascending by timestamp)
|
|
1087
|
+
* @param period Target higher timeframe
|
|
1088
|
+
* @returns Resampled bars
|
|
1089
|
+
*/
|
|
1090
|
+
declare function resampleBars(data: CandleData[], period: Period): CandleData[];
|
|
1091
|
+
/**
|
|
1092
|
+
* Forward-fill higher-TF indicator values to align with lower-TF bar array.
|
|
1093
|
+
* Each lower-TF bar gets the indicator value from the most recent higher-TF bar.
|
|
1094
|
+
*
|
|
1095
|
+
* @param htValues Higher-TF indicator values (one per higher-TF bar)
|
|
1096
|
+
* @param htBars Higher-TF bars (same length as htValues)
|
|
1097
|
+
* @param ltBars Lower-TF bars to align to
|
|
1098
|
+
* @returns Array of length ltBars.length, with forward-filled values
|
|
1099
|
+
*/
|
|
1100
|
+
declare function forwardFill(htValues: number[], htBars: Pick<CandleData, 'timestamp'>[], ltBars: Pick<CandleData, 'timestamp'>[]): number[];
|
|
1101
|
+
/**
|
|
1102
|
+
* Convenience: create a higher-TF indicator factory.
|
|
1103
|
+
* Call `calc` on the full lower-TF dataset, then `getValue(i)` for each bar.
|
|
1104
|
+
*
|
|
1105
|
+
* @example
|
|
1106
|
+
* ```ts
|
|
1107
|
+
* const h4Sma = mtfIndicator(bars15m, { multiplier: 4, timespan: 'hour', text: '4H' }, (data) => sma(data, 21))
|
|
1108
|
+
* const h4SmaValues = bars15m.map((_, i) => h4Sma.getValue(i))
|
|
1109
|
+
* ```
|
|
1110
|
+
*/
|
|
1111
|
+
declare function mtfIndicator<T>(data: CandleData[], higherPeriod: Period, indicatorFn: (data: CandleData[]) => T[]): {
|
|
1112
|
+
getValue: (index: number) => T | null;
|
|
1113
|
+
result: T[];
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* PositionVisualizer — renders entry, stop-loss, and take-profit levels
|
|
1118
|
+
* directly on the chart as colored horizontal lines with labels.
|
|
1119
|
+
*
|
|
1120
|
+
* Usage:
|
|
1121
|
+
* const pv = new PositionVisualizer(chart)
|
|
1122
|
+
* pv.show(position)
|
|
1123
|
+
* // When position updates:
|
|
1124
|
+
* pv.update(position)
|
|
1125
|
+
* pv.hide()
|
|
1126
|
+
*/
|
|
1127
|
+
|
|
1128
|
+
interface PositionVisual {
|
|
1129
|
+
position: Position;
|
|
1130
|
+
stopPrice?: number;
|
|
1131
|
+
targetPrice?: number;
|
|
1132
|
+
}
|
|
1133
|
+
declare class PositionVisualizer {
|
|
1134
|
+
private _chart;
|
|
1135
|
+
private _active;
|
|
1136
|
+
constructor(chart: Chart);
|
|
1137
|
+
/** Show position lines on the chart. */
|
|
1138
|
+
show(visual: PositionVisual): void;
|
|
1139
|
+
/** Hide all position lines. */
|
|
1140
|
+
hide(): void;
|
|
1141
|
+
/** Update position lines (calls show internally). */
|
|
1142
|
+
update(visual: PositionVisual): void;
|
|
1143
|
+
get active(): boolean;
|
|
1144
|
+
private _createLine;
|
|
1145
|
+
private _createLabel;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* ZigZag indicator — detects swing highs and lows using price deviation.
|
|
1150
|
+
*
|
|
1151
|
+
* A swing high occurs when price is the highest within a `deviation`-bar
|
|
1152
|
+
* window on both sides. The resulting array contains the pivot prices at
|
|
1153
|
+
* swing points, with NaN for non-pivot bars.
|
|
1154
|
+
*
|
|
1155
|
+
* @param data Source candle data
|
|
1156
|
+
* @param deviation Number of bars to confirm a swing (default 5)
|
|
1157
|
+
* @returns Array of pivot values (NaN = no pivot at that bar)
|
|
1158
|
+
*/
|
|
1159
|
+
declare function zigzag(data: CandleData[], deviation?: number): number[];
|
|
1160
|
+
/**
|
|
1161
|
+
* Detect support and resistance zones from clustered pivot points.
|
|
1162
|
+
* Returns price levels where swings cluster within `tolerance` percentage.
|
|
1163
|
+
*/
|
|
1164
|
+
declare function detectSupportResistance(data: CandleData[], zigzagDeviation?: number, clusterTolerance?: number): Array<{
|
|
1165
|
+
price: number;
|
|
1166
|
+
count: number;
|
|
1167
|
+
type: 'support' | 'resistance';
|
|
1168
|
+
}>;
|
|
1169
|
+
/**
|
|
1170
|
+
* ZigZag IndicatorPlugin — can be registered as a chart indicator and will
|
|
1171
|
+
* render swing lines between pivot points on the chart.
|
|
1172
|
+
*/
|
|
1173
|
+
declare const zigzagPlugin: IndicatorPlugin<number>;
|
|
1174
|
+
|
|
1175
|
+
/**
|
|
1176
|
+
* Candlestick pattern recognition plugin.
|
|
1177
|
+
*
|
|
1178
|
+
* Scans OHLC data for common candlestick patterns and marks them on the chart.
|
|
1179
|
+
* Patterns are grouped: single-bar, two-bar, three-bar.
|
|
1180
|
+
*
|
|
1181
|
+
* Usage:
|
|
1182
|
+
* import { patternRecognitionPlugin, registerIndicatorPlugin } from '@tony01/astroneum'
|
|
1183
|
+
* registerIndicatorPlugin(patternRecognitionPlugin)
|
|
1184
|
+
* chart.createIndicator({ name: 'patterns', calcParams: [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] })
|
|
1185
|
+
*/
|
|
1186
|
+
interface PatternMatch {
|
|
1187
|
+
index: number;
|
|
1188
|
+
pattern: string;
|
|
1189
|
+
type: 'bullish' | 'bearish' | 'neutral';
|
|
1190
|
+
timestamp: number;
|
|
1191
|
+
high: number;
|
|
1192
|
+
low: number;
|
|
1193
|
+
}
|
|
1194
|
+
interface PatternDef {
|
|
1195
|
+
id: string;
|
|
1196
|
+
name: string;
|
|
1197
|
+
category: 'single' | 'two' | 'three';
|
|
1198
|
+
type: 'bullish' | 'bearish' | 'neutral';
|
|
1199
|
+
fn: (data: CandleData[], i: number) => PatternMatch | null;
|
|
1200
|
+
}
|
|
1201
|
+
declare const PATTERN_CATALOGUE: PatternDef[];
|
|
1202
|
+
declare const patternRecognitionPlugin: IndicatorPlugin<PatternMatch>;
|
|
1203
|
+
|
|
1204
|
+
/**
|
|
1205
|
+
* MultiPeriodLayout — renders multiple charts of the same symbol at
|
|
1206
|
+
* different timeframes stacked vertically. Crosshair syncs across all
|
|
1207
|
+
* panes at the same timestamp.
|
|
1208
|
+
*
|
|
1209
|
+
* Usage:
|
|
1210
|
+
* const layout = new MultiPeriodLayout({
|
|
1211
|
+
* container: 'chart-root',
|
|
1212
|
+
* symbol: { ticker: 'BTCUSDT', ... },
|
|
1213
|
+
* periods: [
|
|
1214
|
+
* { multiplier: 4, timespan: 'hour', text: '4H' },
|
|
1215
|
+
* { multiplier: 1, timespan: 'hour', text: '1H' },
|
|
1216
|
+
* { multiplier: 15, timespan: 'minute', text: '15m' },
|
|
1217
|
+
* ],
|
|
1218
|
+
* datafeed: myDatafeed,
|
|
1219
|
+
* })
|
|
1220
|
+
*/
|
|
1221
|
+
|
|
1222
|
+
interface MultiPeriodLayoutOptions extends Omit<AstroneumOptions, 'symbol' | 'period'> {
|
|
1223
|
+
container: string | HTMLElement;
|
|
1224
|
+
symbol: SymbolInfo;
|
|
1225
|
+
/** Periods for each pane (top to bottom). Default: [4H, 1H, 15m] */
|
|
1226
|
+
periods?: Period[];
|
|
1227
|
+
/** localStorage key for persistence. Pass null to disable. */
|
|
1228
|
+
storageKey?: string | null;
|
|
1229
|
+
}
|
|
1230
|
+
declare class MultiPeriodLayout {
|
|
1231
|
+
private _container;
|
|
1232
|
+
private _periods;
|
|
1233
|
+
private _charts;
|
|
1234
|
+
private _options;
|
|
1235
|
+
private _storageKey;
|
|
1236
|
+
private _wrapperEl;
|
|
1237
|
+
constructor(options: MultiPeriodLayoutOptions);
|
|
1238
|
+
private _render;
|
|
1239
|
+
private _destroy;
|
|
1240
|
+
setTheme(theme: string): void;
|
|
1241
|
+
setLocale(locale: string): void;
|
|
1242
|
+
getCharts(): AstroneumHandle[];
|
|
1243
|
+
destroy(): void;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* CompareOverlay — overlays a second symbol's price as a colored line on the
|
|
1248
|
+
* main chart pane. Uses registerIndicatorPlugin infrastructure for rendering.
|
|
1249
|
+
*
|
|
1250
|
+
* Unlike TradingView's compare feature (which supports dual Y-axis), this
|
|
1251
|
+
* implementation normalizes both symbols to percentage change from the first
|
|
1252
|
+
* visible bar, making them visually comparable on a single Y-axis.
|
|
1253
|
+
*
|
|
1254
|
+
* Usage:
|
|
1255
|
+
* const compare = createCompareIndicator('AAPL', myDatafeed)
|
|
1256
|
+
* registerIndicatorPlugin(compare)
|
|
1257
|
+
* chart.createIndicator({ name: 'compare_AAPL' })
|
|
1258
|
+
*/
|
|
1259
|
+
interface CompareIndicatorOptions {
|
|
1260
|
+
/** Display name shown in legend */
|
|
1261
|
+
name: string;
|
|
1262
|
+
/** Color of the compare line */
|
|
1263
|
+
color?: string;
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Create an indicator plugin that overlays a comparison symbol's price data
|
|
1267
|
+
* normalized to percentage change.
|
|
1268
|
+
*/
|
|
1269
|
+
declare function createCompareIndicator(compareSymbol: SymbolInfo, datafeed: Datafeed, period: Period, color?: string): IndicatorPlugin<number>;
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* Depth of Market (DOM) / Order Book indicator plugin.
|
|
1273
|
+
*
|
|
1274
|
+
* Renders a ladder-style order book on the right side of the chart showing
|
|
1275
|
+
* cumulative bid/ask volume at each price level.
|
|
1276
|
+
*
|
|
1277
|
+
* This is a client-side approximation — a real DOM requires Level 2 market
|
|
1278
|
+
* data from the exchange. This implementation uses the visible candle data
|
|
1279
|
+
* to visualize historical volume distribution at price levels, which is
|
|
1280
|
+
* useful for identifying support/resistance and liquidity zones.
|
|
1281
|
+
*
|
|
1282
|
+
* Usage:
|
|
1283
|
+
* import { domPlugin } from '@tony01/astroneum'
|
|
1284
|
+
* registerIndicatorPlugin(domPlugin)
|
|
1285
|
+
* chart.createIndicator({ name: 'dom', calcParams: [20] }) // 20 price levels
|
|
1286
|
+
*/
|
|
1287
|
+
interface DOMLevel {
|
|
1288
|
+
price: number;
|
|
1289
|
+
bidVolume: number;
|
|
1290
|
+
askVolume: number;
|
|
1291
|
+
totalVolume: number;
|
|
1292
|
+
}
|
|
1293
|
+
declare const domPlugin: IndicatorPlugin<DOMLevel>;
|
|
1294
|
+
|
|
1295
|
+
/**
|
|
1296
|
+
* PriceScaleTransform — log, percentage, and indexed-to-100 price axis
|
|
1297
|
+
* scaling implemented as data-level transformations.
|
|
1298
|
+
*
|
|
1299
|
+
* These transforms work by converting candle OHLC data before it reaches
|
|
1300
|
+
* the chart engine, and converting axis tick values back for display.
|
|
1301
|
+
* This avoids modifying the engine core Y-axis renderer.
|
|
1302
|
+
*/
|
|
1303
|
+
|
|
1304
|
+
type PriceScaleMode = 'linear' | 'log' | 'percent' | 'indexed';
|
|
1305
|
+
/**
|
|
1306
|
+
* Transform OHLC data from linear to the target scale mode.
|
|
1307
|
+
* Returns a new array — does not mutate input.
|
|
1308
|
+
*/
|
|
1309
|
+
declare function transformCandles(data: CandleData[], mode: PriceScaleMode, basePrice?: number): CandleData[];
|
|
1310
|
+
/**
|
|
1311
|
+
* Convert a display price from the transformed scale back to linear.
|
|
1312
|
+
*/
|
|
1313
|
+
declare function untransformPrice(value: number, mode: PriceScaleMode, basePrice: number): number;
|
|
1314
|
+
/**
|
|
1315
|
+
* Format a tick label for the given scale mode.
|
|
1316
|
+
*/
|
|
1317
|
+
declare function formatScaleTick(value: number, mode: PriceScaleMode, basePrice: number, precision?: number): string;
|
|
1318
|
+
|
|
1319
|
+
/**
|
|
1320
|
+
* Non-time-based bar generators: Renko, Kagi, Line Break, Tick, Range, Volume.
|
|
1321
|
+
*
|
|
1322
|
+
* Each function takes standard time-based OHLC data and produces a new array
|
|
1323
|
+
* of synthetic bars where timestamps are artificially spaced for equal-width
|
|
1324
|
+
* rendering on a time-based X-axis. This workaround avoids modifying the
|
|
1325
|
+
* engine core BarSpace/VisibleRange.
|
|
1326
|
+
*
|
|
1327
|
+
* Usage:
|
|
1328
|
+
* const renko = generateRenko(bars, 10) // $10 brick size
|
|
1329
|
+
* chart.setData(renko) // feed to chart as candles
|
|
1330
|
+
*/
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* Generate Renko bricks from OHLC data.
|
|
1334
|
+
* Each brick has a fixed price size. A new brick forms when price moves
|
|
1335
|
+
* beyond the brick size in either direction.
|
|
1336
|
+
*
|
|
1337
|
+
* @param data Source OHLC bars (sorted ascending)
|
|
1338
|
+
* @param brickSize Price size of each Renko brick
|
|
1339
|
+
* @returns Array of synthetic bricks with artificial timestamps
|
|
1340
|
+
*/
|
|
1341
|
+
declare function generateRenko(data: CandleData[], brickSize: number): CandleData[];
|
|
1342
|
+
/**
|
|
1343
|
+
* Generate Kagi line segments from OHLC data.
|
|
1344
|
+
* Kagi draws vertical lines (yang = rising, yin = falling) that reverse
|
|
1345
|
+
* when price moves beyond a threshold.
|
|
1346
|
+
*
|
|
1347
|
+
* @param data Source OHLC bars (sorted ascending)
|
|
1348
|
+
* @param reversalPct Reversal threshold as percentage (e.g., 3 = 3%)
|
|
1349
|
+
* @returns Array of synthetic bars representing line segments
|
|
1350
|
+
*/
|
|
1351
|
+
declare function generateKagi(data: CandleData[], reversalPct?: number): CandleData[];
|
|
1352
|
+
/**
|
|
1353
|
+
* Generate tick bars from raw OHLC data by simulating tick aggregation.
|
|
1354
|
+
* Groups bars into buckets of N "ticks" (where each source bar = 1 tick).
|
|
1355
|
+
*
|
|
1356
|
+
* @param data Source OHLC bars
|
|
1357
|
+
* @param ticksPerBar Number of ticks per synthetic bar
|
|
1358
|
+
* @returns Aggregated tick bars
|
|
1359
|
+
*/
|
|
1360
|
+
declare function generateTickBars(data: CandleData[], ticksPerBar: number): CandleData[];
|
|
1361
|
+
/**
|
|
1362
|
+
* Generate range bars from OHLC data.
|
|
1363
|
+
* Each bar covers a fixed price range. New bar forms when price moves beyond
|
|
1364
|
+
* the range boundary.
|
|
1365
|
+
*
|
|
1366
|
+
* @param data Source OHLC bars
|
|
1367
|
+
* @param rangeSize Price range per bar
|
|
1368
|
+
* @returns Range bars with artificial timestamps
|
|
1369
|
+
*/
|
|
1370
|
+
declare function generateRangeBars(data: CandleData[], rangeSize: number): CandleData[];
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* Point & Figure chart generator.
|
|
1374
|
+
*
|
|
1375
|
+
* P&F charts use X and O columns on a grid instead of time-based candles.
|
|
1376
|
+
* X = rising price column, O = falling price column.
|
|
1377
|
+
* Box size = minimum price move to add a mark. Reversal = number of boxes
|
|
1378
|
+
* required to reverse the current column direction.
|
|
1379
|
+
*
|
|
1380
|
+
* Since the engine requires CandleData[] (time-based), we convert P&F
|
|
1381
|
+
* bricks into synthetic candles with artificial 1-minute timestamps
|
|
1382
|
+
* and uniform spacing. Each brick = one candle bar rendered as a solid
|
|
1383
|
+
* block (open=low, close=high for X, open=high, close=low for O).
|
|
1384
|
+
*
|
|
1385
|
+
* Usage:
|
|
1386
|
+
* import { generatePointAndFigure } from '@tony01/astroneum'
|
|
1387
|
+
* const pfBars = generatePointAndFigure(bars, 10, 3) // $10 box, 3-box reversal
|
|
1388
|
+
* // Feed to chart as regular candles
|
|
1389
|
+
*
|
|
1390
|
+
* Also exports a standalone renderer for true P&F grid visualization
|
|
1391
|
+
* via canvas (used with IndicatorPlugin infrastructure).
|
|
1392
|
+
*/
|
|
1393
|
+
|
|
1394
|
+
interface PFConfig {
|
|
1395
|
+
/** Box size in price units. Default: derived from data (1% of average price) */
|
|
1396
|
+
boxSize?: number;
|
|
1397
|
+
/** Number of boxes to reverse direction. Default: 3 */
|
|
1398
|
+
reversal?: number;
|
|
1399
|
+
/** Chart type: 'pf' = X/O columns, 'hilo' = high/low based */
|
|
1400
|
+
method?: 'close' | 'hilo';
|
|
1401
|
+
}
|
|
1402
|
+
interface PFColumn {
|
|
1403
|
+
/** X (rising) or O (falling) */
|
|
1404
|
+
type: 'X' | 'O';
|
|
1405
|
+
/** Price at the top of this column */
|
|
1406
|
+
top: number;
|
|
1407
|
+
/** Price at the bottom of this column */
|
|
1408
|
+
bottom: number;
|
|
1409
|
+
/** Number of boxes in this column */
|
|
1410
|
+
boxes: number;
|
|
1411
|
+
/** Column index (0-based from left) */
|
|
1412
|
+
columnIndex: number;
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Generate Point & Figure columns from price data.
|
|
1416
|
+
* Returns the raw columns for custom rendering.
|
|
1417
|
+
*/
|
|
1418
|
+
declare function computePFColumns(data: CandleData[], config?: PFConfig): PFColumn[];
|
|
1419
|
+
/**
|
|
1420
|
+
* Convert P&F columns to CandleData for rendering in the standard chart engine.
|
|
1421
|
+
* Each X box = green candle (open < close), each O box = red candle (open > close).
|
|
1422
|
+
*/
|
|
1423
|
+
declare function pfColumnsToBars(columns: PFColumn[]): CandleData[];
|
|
1424
|
+
/**
|
|
1425
|
+
* One-shot: generate P&F bars from OHLC data.
|
|
1426
|
+
*/
|
|
1427
|
+
declare function generatePointAndFigure(data: CandleData[], boxSize?: number, reversal?: number): CandleData[];
|
|
1428
|
+
/**
|
|
1429
|
+
* Point & Figure IndicatorPlugin — renders true X/O grid on the chart
|
|
1430
|
+
* via Canvas2D custom render path.
|
|
1431
|
+
*/
|
|
1432
|
+
declare const pointAndFigurePlugin: IndicatorPlugin<number>;
|
|
1433
|
+
|
|
1434
|
+
export { AstroneumChart, AstroneumHandle, AstroneumOptions, BUILTIN_LOCALES, CandleData, type ChartTemplate, ChartTemplateManager, type CompareIndicatorOptions, type DOMLevel, Datafeed, type DateFormatStyle, type DrawingStyleTemplate, DrawingTemplates, EventBus, type FormatPriceOptions, IndicatorPlugin, MultiPeriodLayout, type MultiPeriodLayoutOptions, type OverlayStylePreset, PATTERN_CATALOGUE, type PFColumn, type PFConfig, type PatternDef, type PatternMatch, type Bar as PerformanceBar, PerformanceMode, Period, Position, type PositionVisual, PositionVisualizer, Price, type PriceScaleMode, RingBuffer, SerializedChartState, type SessionConfig, SessionVisualizer, SymbolInfo, TickAnimator, type TickAnimatorOptions, type TimeFormatStyle, Timestamp, UndoManager, Volume, type VolumeProfileRow, asPrice, asTimestamp, asVolume, computePFColumns, createCompareIndicator, createIndicatorTemplateFromPlugin, deepClone, deepSet, detectPricePrecision, detectSupportResistance, domPlugin, formatDate, formatDateTime, formatDuration, formatPercent, formatPeriod, formatPrice, formatScaleTick, formatTime, formatVolume, forwardFill, generateKagi, generatePointAndFigure, generateRangeBars, generateRenko, generateTickBars, getSupportedIndicators, getSupportedOverlays, heikinAshi, loadLocale, load as loadLocales, mtfIndicator, patternRecognitionPlugin, pfColumnsToBars, pointAndFigurePlugin, rafCoalesce, rafMergeTick, registerIndicator, registerIndicatorPlugin, registerIndicatorPlugins, registerOverlay, registerXAxis, registerYAxis, resampleBars, transformCandles, untransformPrice, volumeProfilePlugin, zigzag, zigzagPlugin };
|