@stocksharp/trading-controls 0.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.
- package/LICENSE +30 -0
- package/NOTICE +21 -0
- package/README.md +240 -0
- package/dist/esm/active-orders-widget.js +382 -0
- package/dist/esm/active-orders-widget.js.map +1 -0
- package/dist/esm/control-types.js +23 -0
- package/dist/esm/control-types.js.map +1 -0
- package/dist/esm/dom.js +55 -0
- package/dist/esm/dom.js.map +1 -0
- package/dist/esm/formatters.js +69 -0
- package/dist/esm/formatters.js.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/positions-widget.js +258 -0
- package/dist/esm/positions-widget.js.map +1 -0
- package/dist/esm/trade-history-widget.js +197 -0
- package/dist/esm/trade-history-widget.js.map +1 -0
- package/dist/esm/trading-data.js +26 -0
- package/dist/esm/trading-data.js.map +1 -0
- package/dist/esm/trading-host.js +79 -0
- package/dist/esm/trading-host.js.map +1 -0
- package/dist/esm/watchlist-widget.js +481 -0
- package/dist/esm/watchlist-widget.js.map +1 -0
- package/dist/sstradingcontrols.js +1740 -0
- package/dist/sstradingcontrols.js.map +7 -0
- package/dist/types/active-orders-widget.d.ts +52 -0
- package/dist/types/active-orders-widget.d.ts.map +1 -0
- package/dist/types/control-types.d.ts +8 -0
- package/dist/types/control-types.d.ts.map +1 -0
- package/dist/types/dom.d.ts +6 -0
- package/dist/types/dom.d.ts.map +1 -0
- package/dist/types/formatters.d.ts +8 -0
- package/dist/types/formatters.d.ts.map +1 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/positions-widget.d.ts +37 -0
- package/dist/types/positions-widget.d.ts.map +1 -0
- package/dist/types/trade-history-widget.d.ts +25 -0
- package/dist/types/trade-history-widget.d.ts.map +1 -0
- package/dist/types/trading-data.d.ts +55 -0
- package/dist/types/trading-data.d.ts.map +1 -0
- package/dist/types/trading-host.d.ts +62 -0
- package/dist/types/trading-host.d.ts.map +1 -0
- package/dist/types/watchlist-widget.d.ts +60 -0
- package/dist/types/watchlist-widget.d.ts.map +1 -0
- package/package.json +129 -0
- package/src/active-orders-widget.ts +411 -0
- package/src/control-types.ts +24 -0
- package/src/dom.ts +68 -0
- package/src/formatters.ts +72 -0
- package/src/index.ts +52 -0
- package/src/positions-widget.ts +305 -0
- package/src/trade-history-widget.ts +221 -0
- package/src/trading-data.ts +121 -0
- package/src/trading-host.ts +300 -0
- package/src/watchlist-widget.ts +513 -0
- package/styles/theme.css +86 -0
- package/styles/trading-controls.css +469 -0
- package/translation-keys.json +58 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
// Watchlist — multi-instance.
|
|
2
|
+
//
|
|
3
|
+
// Builds its own DOM (see `_buildRoot`) rather than cloning a <template> out of
|
|
4
|
+
// the page, so it can be constructed by any host that supplies a `TradingHost`.
|
|
5
|
+
// Each instance has its own search/filter/sort state; favourites are shared,
|
|
6
|
+
// held under one key in the host's preference store.
|
|
7
|
+
//
|
|
8
|
+
// The table is `DataGrid` from `@stocksharp/grids`. The grid holds the FILTERED
|
|
9
|
+
// instruments and does the sorting, which is what makes the two caps mean
|
|
10
|
+
// different things: `renderLimit` caps what gets painted while the export and
|
|
11
|
+
// the subscription sync read the whole filtered set. A live quote patches one
|
|
12
|
+
// cell through the grid's (rowKey, columnKey) lookup instead of repainting — a
|
|
13
|
+
// repaint would restart the flash animation it just triggered.
|
|
14
|
+
import { makeElement, makeIconButton, makePanelId, makePanelRoot } from './dom.js';
|
|
15
|
+
import { ControlTypes } from './control-types.js';
|
|
16
|
+
import { MarketDataLevels, assertHost } from './trading-host.js';
|
|
17
|
+
import { DataGrid } from '@stocksharp/grids/data-grid';
|
|
18
|
+
export class WatchlistWidget {
|
|
19
|
+
static create(hostEl, state, deps) {
|
|
20
|
+
// Assert before building: the markup below is localized through the
|
|
21
|
+
// host, so a missing host has to fail here rather than render a panel
|
|
22
|
+
// captioned with raw English keys.
|
|
23
|
+
const host = assertHost(deps?.host, 'WatchlistWidget');
|
|
24
|
+
const root = WatchlistWidget._buildRoot(host);
|
|
25
|
+
root.id = makePanelId(WatchlistWidget.TYPE);
|
|
26
|
+
hostEl.appendChild(root);
|
|
27
|
+
return new WatchlistWidget(root, state || {}, deps);
|
|
28
|
+
}
|
|
29
|
+
// The panel's markup. The host stylesheet reads this structure, and a
|
|
30
|
+
// docking host lifts `.panel-header`'s children — and, for this panel,
|
|
31
|
+
// `.watchlist-search-row` as well — into its tab strip, which is why the
|
|
32
|
+
// search row is a sibling of the header rather than a child of it.
|
|
33
|
+
//
|
|
34
|
+
// "All" and "Favorites" are the built-in tabs. The rest are appended at
|
|
35
|
+
// runtime from the distinct categories of the loaded instruments, so the
|
|
36
|
+
// tab set is configured through whatever assigns those categories rather
|
|
37
|
+
// than being spelled out here — see _renderCategoryTabs.
|
|
38
|
+
static _buildRoot(host) {
|
|
39
|
+
const search = host.t('SearchInstruments');
|
|
40
|
+
const favorites = host.t('Favorites');
|
|
41
|
+
return makePanelRoot('watchlist-panel', host.t('Watchlist'), [
|
|
42
|
+
makeElement('div', 'panel-header', {}, [
|
|
43
|
+
makeElement('span', '', {}, [host.t('Markets')]),
|
|
44
|
+
makeIconButton('bt-icon-btn panel-export-btn', host.t('ExportToExcel'), 'bi-file-earmark-spreadsheet', { type: 'button' }),
|
|
45
|
+
makeIconButton('bt-icon-btn bt-icon-cancel panel-close-btn', host.t('ClosePanel'), 'bi-x', { type: 'button' }),
|
|
46
|
+
]),
|
|
47
|
+
makeElement('div', 'watchlist-search-row', {}, [
|
|
48
|
+
makeElement('input', 'form-control form-control-sm watchlist-search-input watchlist-search', { type: 'text', placeholder: search, autocomplete: 'off', 'aria-label': search }, []),
|
|
49
|
+
]),
|
|
50
|
+
makeElement('div', 'watchlist-tabs', { role: 'tablist', 'aria-label': host.t('WatchlistFilter') }, [
|
|
51
|
+
makeElement('button', 'wl-tab active', { 'data-filter': 'all', role: 'tab', 'aria-selected': 'true' }, [host.t('All')]),
|
|
52
|
+
makeElement('button', 'wl-tab', { 'data-filter': 'favorites', role: 'tab', 'aria-selected': 'false', 'aria-label': favorites, title: favorites }, ['★']),
|
|
53
|
+
]),
|
|
54
|
+
makeElement('div', 'watchlist-pane', {}, [
|
|
55
|
+
makeElement('table', 'watchlist-table', {}, [
|
|
56
|
+
makeElement('thead', 'watchlist-headers', {}, []),
|
|
57
|
+
makeElement('tbody', 'watchlist-body', {}, []),
|
|
58
|
+
]),
|
|
59
|
+
]),
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
constructor(rootEl, _state, deps) {
|
|
63
|
+
this._host = assertHost(deps?.host, 'WatchlistWidget');
|
|
64
|
+
if (typeof deps?.onSelect !== 'function')
|
|
65
|
+
throw new Error('WatchlistWidget: dep "onSelect" is required');
|
|
66
|
+
this.rootEl = rootEl;
|
|
67
|
+
this._deps = deps;
|
|
68
|
+
this.api = this._host.trading.api;
|
|
69
|
+
this.instruments = [];
|
|
70
|
+
this.stats = new Map();
|
|
71
|
+
this.favorites = new Set(this._loadFavorites());
|
|
72
|
+
this.filter = 'all';
|
|
73
|
+
this.search = '';
|
|
74
|
+
this.currentSymbol = null;
|
|
75
|
+
this._subscribedSyms = new Set();
|
|
76
|
+
this.wsClient = this._host.trading.marketData;
|
|
77
|
+
this.bodyEl = this.rootEl.querySelector('.watchlist-body');
|
|
78
|
+
this.searchEl = this.rootEl.querySelector('.watchlist-search');
|
|
79
|
+
this.tabsEl = this.rootEl.querySelector('.watchlist-tabs');
|
|
80
|
+
this.sortHeaderEl = this.rootEl.querySelector('.watchlist-headers');
|
|
81
|
+
this._closeBtn = this.rootEl.querySelector('.panel-close-btn');
|
|
82
|
+
this._exportBtn = this.rootEl.querySelector('.panel-export-btn');
|
|
83
|
+
this._closeBtn?.addEventListener('click', (e) => {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
this.dispose();
|
|
86
|
+
this._host.close();
|
|
87
|
+
});
|
|
88
|
+
this._exportBtn?.addEventListener('click', (e) => {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
this._export();
|
|
91
|
+
});
|
|
92
|
+
this._grid = this.sortHeaderEl && this.bodyEl
|
|
93
|
+
? new DataGrid({
|
|
94
|
+
head: this.sortHeaderEl,
|
|
95
|
+
body: this.bodyEl,
|
|
96
|
+
columns: this._columns(),
|
|
97
|
+
// Symbol A→Z at rest — an instrument list has no natural "newest",
|
|
98
|
+
// and alphabetical is what the user scans by.
|
|
99
|
+
defaultSort: { col: 'symbol', dir: 'asc' },
|
|
100
|
+
rowKey: (i) => String(i.symbol),
|
|
101
|
+
emptyText: this._host.t('No instruments'),
|
|
102
|
+
rowClass: (i) => (i.symbol === this.currentSymbol ? 'wl-row wl-current' : 'wl-row'),
|
|
103
|
+
bindRow: (tr, i) => tr.addEventListener('click', () => this._deps.onSelect(i.symbol)),
|
|
104
|
+
// Paint a screenful, export and subscribe over the whole filtered set.
|
|
105
|
+
renderLimit: WatchlistWidget.RENDER_CAP,
|
|
106
|
+
// A header click re-renders through the grid, so this is the only
|
|
107
|
+
// place that sees every change to the visible set — including a sort
|
|
108
|
+
// the widget was never told about.
|
|
109
|
+
afterRender: () => {
|
|
110
|
+
this._syncSubs();
|
|
111
|
+
this._publishVisible();
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
: null;
|
|
115
|
+
this._bind();
|
|
116
|
+
this._host.register(this);
|
|
117
|
+
// Auto-init data load: a caller that creates the panel expects a working
|
|
118
|
+
// widget without further ceremony. Unconditional — the host port
|
|
119
|
+
// guarantees an API client, so there is no "maybe we can load" state
|
|
120
|
+
// left to branch on.
|
|
121
|
+
void this.init();
|
|
122
|
+
}
|
|
123
|
+
dispose() {
|
|
124
|
+
// Release every live subscription this widget held — the market-data
|
|
125
|
+
// client refcounts them, so another control's subscription survives if
|
|
126
|
+
// it happened to share a symbol with us.
|
|
127
|
+
for (const sym of this._subscribedSyms) {
|
|
128
|
+
try {
|
|
129
|
+
void this.wsClient?.removeSymbol(sym);
|
|
130
|
+
}
|
|
131
|
+
catch { /* socket may be torn down */ }
|
|
132
|
+
}
|
|
133
|
+
this._subscribedSyms.clear();
|
|
134
|
+
this._host.unregister(this);
|
|
135
|
+
try {
|
|
136
|
+
this.rootEl.remove();
|
|
137
|
+
}
|
|
138
|
+
catch { /* already detached */ }
|
|
139
|
+
}
|
|
140
|
+
async init() {
|
|
141
|
+
try {
|
|
142
|
+
this.instruments = await this.api.searchInstruments('');
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
// Through the port, not the console: this is the diagnostic the
|
|
146
|
+
// user cannot see and support has to, and routing it here is also
|
|
147
|
+
// what makes it assertable.
|
|
148
|
+
this._host.log(`WatchlistWidget: failed to load instruments: ${err}`);
|
|
149
|
+
this.instruments = [];
|
|
150
|
+
}
|
|
151
|
+
this._renderCategoryTabs();
|
|
152
|
+
this._render();
|
|
153
|
+
}
|
|
154
|
+
// Build the filter tabs from the assigned instrument categories. "All" and
|
|
155
|
+
// "Favorites" are built into the markup; here we append one tab per distinct
|
|
156
|
+
// non-empty category found in the loaded instruments. Re-runnable: clears
|
|
157
|
+
// any category tabs a previous load added.
|
|
158
|
+
_renderCategoryTabs() {
|
|
159
|
+
if (!this.tabsEl)
|
|
160
|
+
return;
|
|
161
|
+
this.tabsEl.querySelectorAll('.wl-tab[data-category]').forEach(el => el.remove());
|
|
162
|
+
const cats = Array.from(new Set(this.instruments
|
|
163
|
+
.map(i => (i.category || '').trim())
|
|
164
|
+
.filter(c => c.length > 0)))
|
|
165
|
+
.sort((a, b) => a.localeCompare(b));
|
|
166
|
+
for (const cat of cats) {
|
|
167
|
+
const btn = document.createElement('button');
|
|
168
|
+
btn.className = 'wl-tab';
|
|
169
|
+
btn.setAttribute('role', 'tab');
|
|
170
|
+
btn.setAttribute('aria-selected', 'false');
|
|
171
|
+
btn.dataset.filter = cat;
|
|
172
|
+
btn.dataset.category = '1';
|
|
173
|
+
btn.textContent = cat;
|
|
174
|
+
this.tabsEl.appendChild(btn);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/// Highlight the instrument the rest of the page is showing. Patches the two
|
|
178
|
+
/// affected rows rather than repainting: a repaint here would restart any
|
|
179
|
+
/// flash animation currently running in a price cell.
|
|
180
|
+
setCurrentSymbol(symbol) {
|
|
181
|
+
const previous = this.currentSymbol;
|
|
182
|
+
this.currentSymbol = symbol;
|
|
183
|
+
if (!this._grid)
|
|
184
|
+
return;
|
|
185
|
+
if (previous)
|
|
186
|
+
this._grid.rowElement(String(previous))?.classList.remove('wl-current');
|
|
187
|
+
if (symbol)
|
|
188
|
+
this._grid.rowElement(String(symbol))?.classList.add('wl-current');
|
|
189
|
+
}
|
|
190
|
+
onPriceUpdate(symbol, price) {
|
|
191
|
+
if (price == null || !isFinite(price))
|
|
192
|
+
return;
|
|
193
|
+
let full = symbol;
|
|
194
|
+
if (!full.includes('@')) {
|
|
195
|
+
const match = this.instruments.find(i => String(i.symbol).split('@')[0] === symbol);
|
|
196
|
+
if (match?.symbol)
|
|
197
|
+
full = match.symbol;
|
|
198
|
+
}
|
|
199
|
+
const cur = this.stats.get(full);
|
|
200
|
+
const prev = cur?.lastPrice;
|
|
201
|
+
// Session-day baseline: first observed live price per (UTC-day, symbol).
|
|
202
|
+
// Kept in the host's cache so reloading the page doesn't jump the
|
|
203
|
+
// baseline mid-day. New UTC day = fresh baseline.
|
|
204
|
+
const baselineKey = WatchlistWidget._baselineKey(full);
|
|
205
|
+
let baseline = cur?.baseline;
|
|
206
|
+
if (baseline == null) {
|
|
207
|
+
const stored = this._host.cache.get(baselineKey, null);
|
|
208
|
+
baseline = stored ? Number(stored) : undefined;
|
|
209
|
+
}
|
|
210
|
+
if (baseline == null || !isFinite(baseline) || baseline === 0) {
|
|
211
|
+
baseline = price;
|
|
212
|
+
this._host.cache.set(baselineKey, String(price));
|
|
213
|
+
}
|
|
214
|
+
const chgPct = baseline ? ((price - baseline) / baseline) * 100 : 0;
|
|
215
|
+
this.stats.set(full, { ...(cur || {}), lastPrice: price, baseline, chgPct });
|
|
216
|
+
this._updateRow(full, prev);
|
|
217
|
+
}
|
|
218
|
+
static _baselineKey(symbol) {
|
|
219
|
+
const day = new Date().toISOString().slice(0, 10); // YYYY-MM-DD (UTC)
|
|
220
|
+
return WatchlistWidget.BASELINE_KEY_PREFIX + day + ':' + symbol;
|
|
221
|
+
}
|
|
222
|
+
_bind() {
|
|
223
|
+
if (this.searchEl) {
|
|
224
|
+
this.searchEl.addEventListener('input', () => {
|
|
225
|
+
this.search = (this.searchEl.value || '').trim().toLowerCase();
|
|
226
|
+
this._render();
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (this.tabsEl) {
|
|
230
|
+
this.tabsEl.addEventListener('click', (e) => {
|
|
231
|
+
const tgt = e.target;
|
|
232
|
+
const btn = tgt?.closest('.wl-tab');
|
|
233
|
+
if (!btn)
|
|
234
|
+
return;
|
|
235
|
+
this.filter = btn.dataset.filter || 'all';
|
|
236
|
+
this.tabsEl.querySelectorAll('.wl-tab').forEach(b => b.classList.toggle('active', b === btn));
|
|
237
|
+
this._render();
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// Sort header clicks are handled by the grid (wired in the constructor).
|
|
241
|
+
}
|
|
242
|
+
// The instruments matching the search box and the active tab, unsorted —
|
|
243
|
+
// the grid owns the order.
|
|
244
|
+
_filtered() {
|
|
245
|
+
const q = this.search;
|
|
246
|
+
const rows = [];
|
|
247
|
+
for (const inst of this.instruments) {
|
|
248
|
+
const sym = (inst.symbol || '').toUpperCase();
|
|
249
|
+
// Match the "symbol/exchange" (and "symbol@exchange") display form too, so a
|
|
250
|
+
// full "BTC/IMEX" query resolves — not only the bare symbol "BTC".
|
|
251
|
+
const symL = sym.toLowerCase();
|
|
252
|
+
const shortSym = symL.split('@')[0];
|
|
253
|
+
const exch = (inst.exchange || '').toLowerCase();
|
|
254
|
+
const qualified = `${shortSym}/${exch}`;
|
|
255
|
+
const qualifiedAt = `${shortSym}@${exch}`;
|
|
256
|
+
if (q && !symL.includes(q) && !(inst.name || '').toLowerCase().includes(q) && !qualified.includes(q) && !qualifiedAt.includes(q))
|
|
257
|
+
continue;
|
|
258
|
+
if (this.filter === 'favorites') {
|
|
259
|
+
if (!this.favorites.has(sym))
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
else if (this.filter !== 'all') {
|
|
263
|
+
// Any other filter value is an assigned instrument category,
|
|
264
|
+
// matched case-insensitively.
|
|
265
|
+
if ((inst.category || '').toLowerCase() !== this.filter.toLowerCase())
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
rows.push(inst);
|
|
269
|
+
}
|
|
270
|
+
return rows;
|
|
271
|
+
}
|
|
272
|
+
_render() {
|
|
273
|
+
this._grid?.setRows(this._filtered());
|
|
274
|
+
}
|
|
275
|
+
// The blotter's single column declaration. Prices and percentages come off
|
|
276
|
+
// the live stats map rather than the instrument row, so a quote arriving
|
|
277
|
+
// between two renders is picked up by the next one.
|
|
278
|
+
_columns() {
|
|
279
|
+
const label = (key) => this._host.t(key);
|
|
280
|
+
return [
|
|
281
|
+
{
|
|
282
|
+
key: 'symbol',
|
|
283
|
+
header: label('Symbol'),
|
|
284
|
+
exportable: true,
|
|
285
|
+
value: (i) => i.symbol,
|
|
286
|
+
cellClass: () => 'wl-sym-cell',
|
|
287
|
+
render: (i) => this._symbolCell(i),
|
|
288
|
+
exportValue: (i) => String(i.symbol).split('@')[0],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
key: 'last',
|
|
292
|
+
header: label('Last'),
|
|
293
|
+
headerClass: 'ta-right',
|
|
294
|
+
exportable: true,
|
|
295
|
+
value: (i) => this._statsOf(i).lastPrice,
|
|
296
|
+
cellClass: () => 'wl-last',
|
|
297
|
+
render: (i) => WatchlistWidget._priceText(this._statsOf(i).lastPrice),
|
|
298
|
+
exportValue: (i) => this._statsOf(i).lastPrice ?? '',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
key: 'chgPct',
|
|
302
|
+
header: label('Change24hPct'),
|
|
303
|
+
headerClass: 'ta-right',
|
|
304
|
+
exportable: true,
|
|
305
|
+
value: (i) => this._statsOf(i).chgPct,
|
|
306
|
+
cellClass: (i) => ('wl-chg ' + WatchlistWidget._changeClass(this._statsOf(i).chgPct)).trim(),
|
|
307
|
+
render: (i) => WatchlistWidget._changeText(this._statsOf(i).chgPct),
|
|
308
|
+
exportValue: (i) => this._statsOf(i).chgPct ?? '',
|
|
309
|
+
},
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
_statsOf(instrument) {
|
|
313
|
+
return this.stats.get(String(instrument.symbol)) ?? {};
|
|
314
|
+
}
|
|
315
|
+
// The favourite star plus the short symbol. The star stops the click from
|
|
316
|
+
// reaching the row, whose own listener switches the host's instrument.
|
|
317
|
+
_symbolCell(instrument) {
|
|
318
|
+
const cell = document.createDocumentFragment();
|
|
319
|
+
const star = document.createElement('button');
|
|
320
|
+
star.type = 'button';
|
|
321
|
+
star.className = this.favorites.has(instrument.symbol) ? 'wl-fav active' : 'wl-fav';
|
|
322
|
+
star.title = this._host.t('Favorite');
|
|
323
|
+
star.textContent = '★';
|
|
324
|
+
star.addEventListener('click', (e) => {
|
|
325
|
+
e.stopPropagation();
|
|
326
|
+
this._toggleFavorite(instrument.symbol);
|
|
327
|
+
});
|
|
328
|
+
cell.appendChild(star);
|
|
329
|
+
const label = document.createElement('span');
|
|
330
|
+
label.className = 'wl-sym';
|
|
331
|
+
label.textContent = String(instrument.symbol).split('@')[0];
|
|
332
|
+
cell.appendChild(label);
|
|
333
|
+
return cell;
|
|
334
|
+
}
|
|
335
|
+
// Export the current filtered+sorted view to .xlsx — every matching
|
|
336
|
+
// instrument, without the RENDER_CAP truncation applied to the DOM.
|
|
337
|
+
_export() {
|
|
338
|
+
this._grid?.download('watchlist', this._host.t('Markets'));
|
|
339
|
+
}
|
|
340
|
+
// Patch the price and change cells of one row in place. A full render would
|
|
341
|
+
// replace the cell element and so cancel the flash animation started here.
|
|
342
|
+
_updateRow(symbol, prevPrice) {
|
|
343
|
+
if (!this._grid)
|
|
344
|
+
return;
|
|
345
|
+
const st = this.stats.get(symbol) || {};
|
|
346
|
+
const lastEl = this._grid.cellElement(String(symbol), 'last');
|
|
347
|
+
const chgEl = this._grid.cellElement(String(symbol), 'chgPct');
|
|
348
|
+
if (lastEl && st.lastPrice != null) {
|
|
349
|
+
lastEl.textContent = WatchlistWidget._priceText(st.lastPrice);
|
|
350
|
+
if (prevPrice != null && st.lastPrice !== prevPrice) {
|
|
351
|
+
lastEl.classList.remove('flash-up', 'flash-down');
|
|
352
|
+
void lastEl.offsetWidth;
|
|
353
|
+
lastEl.classList.add(st.lastPrice > prevPrice ? 'flash-up' : 'flash-down');
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (chgEl && st.chgPct != null && isFinite(Number(st.chgPct))) {
|
|
357
|
+
chgEl.textContent = WatchlistWidget._changeText(st.chgPct);
|
|
358
|
+
chgEl.classList.remove('up', 'down');
|
|
359
|
+
chgEl.classList.add(WatchlistWidget._changeClass(st.chgPct));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
_toggleFavorite(symbol) {
|
|
363
|
+
if (!this._host.allow('add to favorites'))
|
|
364
|
+
return;
|
|
365
|
+
if (this.favorites.has(symbol))
|
|
366
|
+
this.favorites.delete(symbol);
|
|
367
|
+
else
|
|
368
|
+
this.favorites.add(symbol);
|
|
369
|
+
this._saveFavorites();
|
|
370
|
+
// Broadcast the change to every other watchlist instance so they reflect
|
|
371
|
+
// the new state without a fresh fetch.
|
|
372
|
+
this._host.broadcast(w => {
|
|
373
|
+
if (w !== this) {
|
|
374
|
+
w.favorites = new Set(this.favorites);
|
|
375
|
+
w._render();
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
this._render();
|
|
379
|
+
}
|
|
380
|
+
_loadFavorites() {
|
|
381
|
+
try {
|
|
382
|
+
const raw = this._host.preferences.get(WatchlistWidget.FAVORITES_KEY, null);
|
|
383
|
+
return raw ? JSON.parse(raw) : [];
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
return [];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
_saveFavorites() {
|
|
390
|
+
try {
|
|
391
|
+
this._host.preferences.set(WatchlistWidget.FAVORITES_KEY, JSON.stringify(Array.from(this.favorites)));
|
|
392
|
+
}
|
|
393
|
+
catch { /* store may be unavailable */ }
|
|
394
|
+
}
|
|
395
|
+
// The symbols at the top of the current order — the ones a user is actually
|
|
396
|
+
// looking at, and the set both the subscriptions and the host's ticker are
|
|
397
|
+
// sized to.
|
|
398
|
+
_visible() {
|
|
399
|
+
return this._grid ? this._grid.sortedRows().slice(0, WatchlistWidget.VISIBLE_CAP) : [];
|
|
400
|
+
}
|
|
401
|
+
// Diff the desired set of visible symbols against currently-held live-price
|
|
402
|
+
// subscriptions, then add/remove to converge. Called after every render that
|
|
403
|
+
// may have changed the visible list (filter, sort, search). add/removeSymbol
|
|
404
|
+
// refcount internally, so another control's subscription on the same symbol
|
|
405
|
+
// is not affected.
|
|
406
|
+
_syncSubs() {
|
|
407
|
+
if (!this.wsClient)
|
|
408
|
+
return;
|
|
409
|
+
const desired = new Set(this._visible().map(i => String(i.symbol).split('@')[0]));
|
|
410
|
+
for (const sym of this._subscribedSyms) {
|
|
411
|
+
if (!desired.has(sym)) {
|
|
412
|
+
try {
|
|
413
|
+
void this.wsClient.removeSymbol(sym);
|
|
414
|
+
}
|
|
415
|
+
catch { /* socket race */ }
|
|
416
|
+
this._subscribedSyms.delete(sym);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// Stagger the subscribe burst — firing every watchlist symbol
|
|
420
|
+
// simultaneously while a chart is fetching its history starves the
|
|
421
|
+
// adapter and stalls the chart's snapshot. 80ms between calls keeps the
|
|
422
|
+
// pipe quiet enough for that fetch to return on time, while still
|
|
423
|
+
// feeling instant to the user.
|
|
424
|
+
let i = 0;
|
|
425
|
+
for (const sym of desired) {
|
|
426
|
+
if (this._subscribedSyms.has(sym))
|
|
427
|
+
continue;
|
|
428
|
+
this._subscribedSyms.add(sym);
|
|
429
|
+
setTimeout(() => {
|
|
430
|
+
try {
|
|
431
|
+
void this.wsClient.addSymbol(sym, MarketDataLevels.Quotes);
|
|
432
|
+
}
|
|
433
|
+
catch { /* socket race */ }
|
|
434
|
+
}, i * 80);
|
|
435
|
+
i++;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Tell the host which symbols are on screen. Only the primary instance
|
|
439
|
+
// speaks for the page: duplicated watchlist panels have their own filters,
|
|
440
|
+
// and the page has one ticker for them to fight over.
|
|
441
|
+
_publishVisible() {
|
|
442
|
+
if (!this._host.isPrimary)
|
|
443
|
+
return;
|
|
444
|
+
this._host.ticker.publish(this._visible().map(i => String(i.symbol)), this.stats);
|
|
445
|
+
}
|
|
446
|
+
static _priceText(price) {
|
|
447
|
+
const n = Number(price);
|
|
448
|
+
if (price == null || !isFinite(n) || n === 0)
|
|
449
|
+
return '--';
|
|
450
|
+
if (n >= 1)
|
|
451
|
+
return n.toFixed(2);
|
|
452
|
+
if (n >= 0.01)
|
|
453
|
+
return n.toFixed(4);
|
|
454
|
+
return n.toFixed(6);
|
|
455
|
+
}
|
|
456
|
+
static _changeText(chgPct) {
|
|
457
|
+
const pct = Number(chgPct);
|
|
458
|
+
if (chgPct == null || !isFinite(pct))
|
|
459
|
+
return '--';
|
|
460
|
+
return `${pct >= 0 ? '+' : ''}${pct.toFixed(2)}%`;
|
|
461
|
+
}
|
|
462
|
+
static _changeClass(chgPct) {
|
|
463
|
+
const pct = Number(chgPct);
|
|
464
|
+
if (chgPct == null || !isFinite(pct))
|
|
465
|
+
return '';
|
|
466
|
+
return pct >= 0 ? 'up' : 'down';
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
WatchlistWidget.FAVORITES_KEY = 'terminal_watchlist_favorites';
|
|
470
|
+
// Cache-key prefix for the per-session baseline price used to compute the
|
|
471
|
+
// change %. Day-scoped so the baseline resets every UTC day and the
|
|
472
|
+
// percent matches "since today open" intuitively. (Without a REST bars
|
|
473
|
+
// endpoint there is no broker-side day-open available, and the watchlist
|
|
474
|
+
// deliberately avoids REST — the live stream is its only source.) It goes
|
|
475
|
+
// in the host's cache rather than its preferences: one key per symbol per
|
|
476
|
+
// day is scratch, not a setting worth syncing.
|
|
477
|
+
WatchlistWidget.BASELINE_KEY_PREFIX = 'wlBaseline:';
|
|
478
|
+
WatchlistWidget.VISIBLE_CAP = 30;
|
|
479
|
+
WatchlistWidget.RENDER_CAP = 300;
|
|
480
|
+
WatchlistWidget.TYPE = ControlTypes.Watchlist;
|
|
481
|
+
//# sourceMappingURL=watchlist-widget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watchlist-widget.js","sourceRoot":"","sources":["../../src/watchlist-widget.ts"],"names":[],"mappings":"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"}
|