@trdrs/quickcharts 2.2.0 → 2.3.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.
@@ -102,37 +102,4 @@ declare function parseTickBands(variableTickSize: string): TickBand[];
102
102
  * so a spread writes both sides in one column. */
103
103
  declare function tickBandFor(bands: readonly TickBand[], price: number): TickBand | null;
104
104
 
105
- /** How a formatted price is punctuated. A price localizes the decimal sign only, so
106
- * `groupSign` defaults to '' (no thousands separator) and a host that wants grouping asks for it
107
- * explicitly. */
108
- interface NumericPunctuation {
109
- /** What separates the whole part from the decimals. Default '.', or the locale's sign when a
110
- * `locale` is given. */
111
- decimalSign?: string;
112
- /** What separates thousands in the whole part. Default '': a price is written ungrouped, because
113
- * a grouped price is harder to compare against the axis beside it. */
114
- groupSign?: string;
115
- }
116
- interface PriceFormatterOptions {
117
- /** A BCP 47 tag used ONCE, at construction, to derive the decimal sign. Anything explicit in
118
- * `numericPunctuation` wins over it. */
119
- locale?: string;
120
- numericPunctuation?: NumericPunctuation;
121
- }
122
- /** A resolved formatter for one symbol. `format` and `parse` are exact inverses over every price
123
- * that lands on the symbol's own grid. */
124
- interface PriceFormatter {
125
- /** The price as the symbol writes it. */
126
- format(price: number): string;
127
- /** The number a viewer typed, or null when the text is not a price in this symbol's format. */
128
- parse(text: string): number | null;
129
- /** How many digits `format` writes after the decimal sign. 0 for a fractional format, which
130
- * writes none; the widest band's width for a variable-tick format, so a column sized from it
131
- * never has to reflow. */
132
- precision(): number;
133
- }
134
- /** Build the formatter for one symbol's price format. The result is stateless and reusable; a host
135
- * resolves a symbol once and keeps its formatter for as long as the symbol is on screen. */
136
- declare function createPriceFormatter(format: PriceFormat, options?: PriceFormatterOptions): PriceFormatter;
137
-
138
- export { type DataStatus as D, type NumericPunctuation as N, type PriceFormatter as P, type SymbolInfo as S, type TickBand as T, type PriceFormat as a, type PriceFormatterOptions as b, type Subsession as c, type SubsessionId as d, createPriceFormatter as e, parseTickBands as p, tickBandFor as t };
105
+ export { type DataStatus as D, type PriceFormat as P, type SymbolInfo as S, type TickBand as T, type Subsession as a, type SubsessionId as b, parseTickBands as p, tickBandFor as t };
@@ -0,0 +1,222 @@
1
+ import { S as SymbolInfo } from './symbology-D3SLclrU.js';
2
+
3
+ /** The theme roles a mark may wear. A host names a meaning and the mode resolves the color, so a
4
+ * mark stays readable when the viewer switches to light. */
5
+ type MarkColorRole = 'neutral' | 'up' | 'down' | 'info' | 'warning' | 'positive' | 'negative';
6
+ /** Where a bar mark sits relative to its bar. */
7
+ type MarkPlacement = 'above' | 'below';
8
+ /** The glyph a bar mark draws. */
9
+ type MarkShape = 'circle' | 'square' | 'arrowUp' | 'arrowDown';
10
+ /** One mark on a bar. */
11
+ interface BarMark {
12
+ /** Stable within one symbol and window, so a refetch replaces rather than duplicates. */
13
+ id: string;
14
+ /** Epoch SECONDS at the bar's bucket open, the same clock every bar uses. */
15
+ time: number;
16
+ color: MarkColorRole;
17
+ /** The letter or two the glyph carries. */
18
+ text?: string;
19
+ /** The longer words a host would show beside the mark. Carried, never drawn by the chart. */
20
+ label?: string;
21
+ shape?: MarkShape;
22
+ placement?: MarkPlacement;
23
+ }
24
+ /** One mark under the time scale. */
25
+ interface TimescaleMark {
26
+ id: string;
27
+ /** Epoch SECONDS. */
28
+ time: number;
29
+ color: MarkColorRole;
30
+ label?: string;
31
+ }
32
+
33
+ /** One OHLCV bar on the wire: `t` = epoch SECONDS at bucket open (never milliseconds, never an
34
+ * update's wall time), strictly ascending within any batch, one bar per timestamp. */
35
+ interface FeedBar {
36
+ t: number;
37
+ o: number;
38
+ h: number;
39
+ l: number;
40
+ c: number;
41
+ v: number;
42
+ }
43
+ /** A symbol-search result row. `exchange` names the venue the market lists on. `dataSource` names
44
+ * where the market's data comes from, and a row names one only when that source publishes the
45
+ * symbol's data. The row's source cell shows the venue, or the data source for a row with none. */
46
+ interface SymbolRow {
47
+ symbol: string;
48
+ name: string;
49
+ exchange: string;
50
+ type: string;
51
+ dataSource?: string | null;
52
+ /** What the market is priced in, when the feed knows it here. A PAIR market writes itself as
53
+ * `BASE / QUOTE` wherever it is named, and a ticker alone cannot say what the quote is; a row
54
+ * without it keeps the name the feed sent instead. `resolve()` states the same fact for the
55
+ * charted symbol, so a row and the legend that follows it agree. */
56
+ currencyCode?: string;
57
+ }
58
+ interface SearchPage {
59
+ hits: SymbolRow[];
60
+ /** Exact: another page exists at offset + hits.length (never a guess at a page boundary). */
61
+ hasMore: boolean;
62
+ }
63
+ interface HistoryPage {
64
+ bars: FeedBar[];
65
+ /** True when a countBack ask found NOTHING — the "no more history, stop scrolling back" signal.
66
+ * Plain from/to asks never set it (an empty window can be a mid-history gap). */
67
+ noData: boolean;
68
+ /** OPTIONAL gap hint on an EMPTY page that is not the end of history: the epoch-seconds time of
69
+ * the closest bar older than the asked window (a market holiday between `to` and the data).
70
+ * A consumer may retry ONCE with `to = nextTime` to jump the gap instead of dead-ending —
71
+ * {@link olderPageVerdict} is that rule. Feeds without the concept simply never set it. */
72
+ nextTime?: number;
73
+ }
74
+ type OlderPageVerdict = {
75
+ kind: 'bars';
76
+ } | {
77
+ kind: 'hop';
78
+ to: number;
79
+ } | {
80
+ kind: 'end';
81
+ } | {
82
+ kind: 'stop';
83
+ };
84
+ /** The one scroll-back rule for an older-history page, shared by every paging consumer so the gap
85
+ * semantics can't drift between them:
86
+ * - `bars` — the page has data; prepend it (bars are never discarded, whatever flags ride along).
87
+ * - `hop` — empty but `nextTime` points strictly older and this ask wasn't already a hop: re-ask
88
+ * once anchored there (the session-gap answer). One hop per gap keeps a lying feed bounded —
89
+ * an honest hint names a real bar, so the hop can't come back empty.
90
+ * - `end` — empty, `noData`, and no hint: feed inception, the one verdict that seals scroll-back.
91
+ * - `stop` — every other empty page (a transient, or an unusable hint): end this flight WITHOUT
92
+ * sealing; the next gesture asks again. */
93
+ declare function olderPageVerdict(page: HistoryPage, askedTo: number, alreadyHopped: boolean): OlderPageVerdict;
94
+ /** Push events from a live bar subscription. A `snapshot` REPLACES the recent window (delivered on
95
+ * connect and on every transport reconnect — the feed's self-healing re-sync); a `bar` mutates the
96
+ * last bar or appends the next one (bucket-open time). */
97
+ type BarsEvent = {
98
+ kind: 'snapshot';
99
+ bars: FeedBar[];
100
+ } | {
101
+ kind: 'bar';
102
+ bar: FeedBar;
103
+ };
104
+ interface SubscribeHandlers {
105
+ onBars(e: BarsEvent): void;
106
+ /** Feed status codes: 'live' | 'no-data' | server codes ('not_entitled', 'feed_down', …). */
107
+ onStatus?(status: string): void;
108
+ }
109
+ /** Thrown by `history` when the backend has NO feed configured for the symbol — a TERMINAL state
110
+ * (the chart shows "market data unavailable" and closes the live subscription), unlike a transient
111
+ * fetch failure which is retried. */
112
+ declare class FeedUnavailableError extends Error {
113
+ /** The server's typed refusal (e.g. not_entitled / feed_down),
114
+ * when it sent one — lets the host name the actual cause instead of a generic "unavailable". */
115
+ readonly code: string | null;
116
+ constructor(message?: string,
117
+ /** The server's typed refusal (e.g. not_entitled / feed_down),
118
+ * when it sent one — lets the host name the actual cause instead of a generic "unavailable". */
119
+ code?: string | null);
120
+ }
121
+ /** One class in a feed's catalog that holds narrower classes: a `spot` class over its `usdc` and
122
+ * `usdt` quotes, say. `id` is the token the feed is searched with, as a plain string entry is, and
123
+ * `children` are the narrower classes, as tokens or nodes of their own. The search renders two
124
+ * levels, a top-level class and its children: a child's own `children` are not offered, and the
125
+ * child narrows by its `id` alone. */
126
+ interface SearchClassNode {
127
+ readonly id: string;
128
+ readonly children?: readonly (string | SearchClassNode)[];
129
+ }
130
+ /** What a feed's `search` is asked with. `cls` and `classes` say which classes to narrow to; both
131
+ * absent is every class. */
132
+ interface DatafeedSearchOptions {
133
+ /** One class to narrow to. When the viewer may select several classes it is set only while
134
+ * exactly one is selected, so a feed that reads `cls` alone still narrows a single chip. */
135
+ cls?: string;
136
+ /** Every class to narrow to, sent only when the search lets the viewer select several classes at
137
+ * once: a row matches when it is in any of them. A feed may ignore it and read `cls` alone. */
138
+ classes?: readonly string[];
139
+ limit?: number;
140
+ offset?: number;
141
+ }
142
+ /** A feed's coarse, feed-LEVEL capability declaration. Everything optional and the method itself
143
+ * optional: an ABSENT declaration means unconstrained, and a feed must only
144
+ * declare what is true — a finite `resolutions` list from a feed that serves any timeframe would
145
+ * be a lie the chart then enforces. Symbol-level truth (price format, resolutions, session) stays
146
+ * on {@link SymbolInfo}. */
147
+ interface DatafeedConfig {
148
+ /** The wire timeframe tokens this feed can serve ('1m', '4h', '1d', …). Absent = any. */
149
+ resolutions?: readonly string[];
150
+ /** Asset-class tokens the catalog carries, in the order the search offers them. An entry is a
151
+ * token, or a {@link SearchClassNode} whose children the search offers beneath it once it is
152
+ * selected. Absent = unspecified. */
153
+ classes?: readonly (string | SearchClassNode)[];
154
+ }
155
+ /** The datafeed a chart consumes. Implementations must follow the bar rules on {@link FeedBar} and
156
+ * {@link BarsEvent}; everything else (transport, caching, auth) is the implementation's business. */
157
+ interface ChartDatafeed {
158
+ /** OPTIONAL capability negotiation, read once at mount: the widget constrains itself to what the
159
+ * feed declares (e.g. its initial timeframe must be servable). Omit it entirely when the feed
160
+ * has no fixed capability set. */
161
+ config?(): Promise<DatafeedConfig>;
162
+ /** Server-side symbol search, paged. `cls` narrows to one asset class ('' / absent = all), and
163
+ * `classes`, when present, to any of several (see {@link DatafeedSearchOptions}). */
164
+ search(q: string, opts?: DatafeedSearchOptions): Promise<SearchPage>;
165
+ /** Resolve one symbol's metadata; null when the symbol is unknown to the feed's catalogs. */
166
+ resolve(symbol: string): Promise<SymbolInfo | null>;
167
+ /** Historical sealed bars: a [from,to] window (epoch seconds, INCLUSIVE of both ends — the chart
168
+ * pages with `to = oldest − 1` and never re-requests a bar it holds), or `countBack` = the LAST
169
+ * N bars at/before `to` (outranks `from`; the count is an obligation — reach across closures).
170
+ * No range = the feed's default recent window. Throws {@link FeedUnavailableError} when no feed
171
+ * serves the symbol. */
172
+ history(symbol: string, tf: string, range?: {
173
+ from?: number;
174
+ to?: number;
175
+ countBack?: number;
176
+ }): Promise<HistoryPage>;
177
+ /** Live bar push for one (symbol, timeframe). Returns the unsubscribe. The transport owns
178
+ * reconnection and re-syncs by emitting a fresh `snapshot`. */
179
+ subscribeBars(symbol: string, tf: string, handlers: SubscribeHandlers): () => void;
180
+ /** Server clock (epoch seconds) — countdown skew correction. Optional: a feed without one leaves
181
+ * the chart on the client clock. */
182
+ serverTime?(): Promise<number>;
183
+ /** OPTIONAL depth of history for a symbol: the epoch seconds of its earliest available bar, or
184
+ * null when the feed does not know. The range presets read it (a listing from last year offers
185
+ * no five-year range); the chart never probes for it. Omit it entirely when the feed cannot
186
+ * say, and every preset is offered. */
187
+ earliestBar?(symbol: string): Promise<number | null>;
188
+ /** OPTIONAL neutral bar marks over a window (epoch seconds, inclusive of both ends). A mark is a
189
+ * note about a moment: its color is a theme role, its words are the host's, and the chart
190
+ * draws it as given. Omit it entirely when the feed serves none. */
191
+ marks?(symbol: string, from: number, to: number, resolution: string): Promise<readonly BarMark[]>;
192
+ /** OPTIONAL neutral time-scale marks over the same window. */
193
+ timescaleMarks?(symbol: string, from: number, to: number, resolution: string): Promise<readonly TimescaleMark[]>;
194
+ }
195
+
196
+ /** The ticker inside a feed symbol. Only a well-formed `VENUE:TICKER` sheds its prefix; a spread
197
+ * expression, or anything else the pattern does not admit, is its own label and passes through. */
198
+ declare function bareTicker(symbol: string): string;
199
+ /** The three ways one market is written, from one rule. */
200
+ interface SymbolNames {
201
+ /** The compact mark a label wears at a glance: a pair closed up (`BTCUSDC`, `EURUSD`), otherwise
202
+ * the bare ticker (`ES1!`, `AAPL`). A spread expression is its own mark, operators and all. */
203
+ mark: string;
204
+ /** The title a reading wears: a pair spaced (`BTC / USDC`), otherwise the feed's short name where
205
+ * it stated one apart from the description, otherwise the bare ticker. */
206
+ title: string;
207
+ /** The description beside a mark: a pair spaced, otherwise the feed's long description, otherwise
208
+ * the bare ticker, so a market never repeats its own mark for want of a name. */
209
+ description: string;
210
+ }
211
+ /** How a market is named, from a resolved `SymbolInfo`, a search row, or the feed symbol alone
212
+ * before either has landed.
213
+ *
214
+ * A pair market reads as `BTC / USDC` or `EUR / USD`, both sides in the codes the market itself
215
+ * trades in, never a spelled-out currency name. The quote comes from `currencyCode`, and a ticker
216
+ * written as a slash pair (`BTC/USD`) needs no currency to say so. Before a symbol resolves there
217
+ * is no pair to write, so the bare ticker stands on its own rather than guessing at a quote. A
218
+ * market that is not a pair keeps the feed's own words: the short name as its title, the long
219
+ * description beside its mark. */
220
+ declare function symbolNames(symbol: SymbolInfo | SymbolRow | string): SymbolNames;
221
+
222
+ export { type BarMark as B, type ChartDatafeed as C, type DatafeedConfig as D, type FeedBar as F, type HistoryPage as H, type MarkColorRole as M, type OlderPageVerdict as O, type SymbolRow as S, type TimescaleMark as T, type SearchClassNode as a, type BarsEvent as b, type DatafeedSearchOptions as c, FeedUnavailableError as d, type MarkPlacement as e, type MarkShape as f, type SearchPage as g, type SubscribeHandlers as h, type SymbolNames as i, bareTicker as j, olderPageVerdict as o, symbolNames as s };
@@ -0,0 +1,2 @@
1
+ export { i as SymbolNames, j as bareTicker, s as symbolNames } from './symbols-BL1fD4CS.js';
2
+ import './symbology-D3SLclrU.js';
@@ -0,0 +1,9 @@
1
+ import {
2
+ bareTicker,
3
+ symbolNames
4
+ } from "./chunk-GFQQSY47.js";
5
+ export {
6
+ bareTicker,
7
+ symbolNames
8
+ };
9
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trdrs/quickcharts",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Quick Charts: a datafeed-driven charting library with drawings, indicators, layouts and replay over host-supplied data and storage ports.",
5
5
  "keywords": [
6
6
  "charts",
@@ -49,6 +49,10 @@
49
49
  "types": "./dist/glyphs.d.ts",
50
50
  "import": "./dist/glyphs.js"
51
51
  },
52
+ "./symbols": {
53
+ "types": "./dist/symbols.d.ts",
54
+ "import": "./dist/symbols.js"
55
+ },
52
56
  "./styles.css": "./dist/quickcharts.css"
53
57
  },
54
58
  "files": [