binbot-charts 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/components/TVChartContainer.js +24 -32
  2. package/dist/components/datafeed.js +131 -100
  3. package/dist/components/streaming.js +1 -1
  4. package/package.json +2 -2
  5. package/dist/datafeeds/README.md +0 -3
  6. package/dist/datafeeds/udf/README.md +0 -46
  7. package/dist/datafeeds/udf/dist/bundle.js +0 -1
  8. package/dist/datafeeds/udf/lib/data-pulse-provider.js +0 -104
  9. package/dist/datafeeds/udf/lib/helpers.js +0 -20
  10. package/dist/datafeeds/udf/lib/history-provider.js +0 -73
  11. package/dist/datafeeds/udf/lib/iquotes-provider.js +0 -1
  12. package/dist/datafeeds/udf/lib/quotes-provider.js +0 -25
  13. package/dist/datafeeds/udf/lib/quotes-pulse-provider.js +0 -44
  14. package/dist/datafeeds/udf/lib/requester.js +0 -28
  15. package/dist/datafeeds/udf/lib/symbols-storage.js +0 -180
  16. package/dist/datafeeds/udf/lib/udf-compatible-datafeed-base.js +0 -252
  17. package/dist/datafeeds/udf/lib/udf-compatible-datafeed.js +0 -10
  18. package/dist/datafeeds/udf/package.json +0 -17
  19. package/dist/datafeeds/udf/rollup.config.js +0 -25
  20. package/dist/datafeeds/udf/src/data-pulse-provider.ts +0 -152
  21. package/dist/datafeeds/udf/src/helpers.ts +0 -38
  22. package/dist/datafeeds/udf/src/history-provider.ts +0 -134
  23. package/dist/datafeeds/udf/src/iquotes-provider.ts +0 -14
  24. package/dist/datafeeds/udf/src/quotes-provider.ts +0 -37
  25. package/dist/datafeeds/udf/src/quotes-pulse-provider.ts +0 -85
  26. package/dist/datafeeds/udf/src/requester.ts +0 -39
  27. package/dist/datafeeds/udf/src/symbols-storage.ts +0 -298
  28. package/dist/datafeeds/udf/src/udf-compatible-datafeed-base.ts +0 -369
  29. package/dist/datafeeds/udf/src/udf-compatible-datafeed.ts +0 -11
  30. package/dist/datafeeds/udf/tsconfig.json +0 -25
@@ -1,298 +0,0 @@
1
- import {
2
- LibrarySymbolInfo,
3
- SearchSymbolResultItem,
4
- ResolutionString,
5
- } from '../../../charting_library/datafeed-api';
6
-
7
- import {
8
- getErrorMessage,
9
- logMessage,
10
- } from './helpers';
11
-
12
- import { Requester } from './requester';
13
-
14
- interface SymbolInfoMap {
15
- [symbol: string]: LibrarySymbolInfo | undefined;
16
- }
17
-
18
- interface ExchangeDataResponseSymbolData {
19
- 'type': string;
20
- 'timezone': LibrarySymbolInfo['timezone'];
21
- 'description': string;
22
-
23
- 'exchange-listed': string;
24
- 'exchange-traded': string;
25
-
26
- 'session-regular': string;
27
- 'corrections'?: string;
28
- 'session-holidays'?: string;
29
-
30
- 'fractional': boolean;
31
-
32
- 'pricescale': number;
33
-
34
- 'ticker'?: string;
35
-
36
- 'minmov2'?: number;
37
- 'minmove2'?: number;
38
-
39
- 'minmov'?: number;
40
- 'minmovement'?: number;
41
-
42
- 'supported-resolutions'?: ResolutionString[];
43
- 'intraday-multipliers'?: string[];
44
-
45
- 'has-intraday'?: boolean;
46
- 'has-daily'?: boolean;
47
- 'has-weekly-and-monthly'?: boolean;
48
- 'has-empty-bars'?: boolean;
49
- 'has-no-volume'?: boolean;
50
- 'currency-code'?: string;
51
- 'original-currency-code'?: string;
52
- 'unit-id'?: string;
53
- 'original-unit-id'?: string;
54
- 'unit-conversion-types'?: string[];
55
-
56
- 'volume-precision'?: number;
57
- }
58
-
59
- // Here is some black magic with types to get compile-time checks of names and types
60
- type PickArrayedObjectFields<T> = Pick<T, {
61
- // tslint:disable-next-line:no-any
62
- [K in keyof T]-?: NonNullable<T[K]> extends any[] ? K : never;
63
- }[keyof T]>;
64
-
65
- type ExchangeDataResponseArrayedSymbolData = PickArrayedObjectFields<ExchangeDataResponseSymbolData>;
66
- type ExchangeDataResponseNonArrayedSymbolData = Pick<ExchangeDataResponseSymbolData, Exclude<keyof ExchangeDataResponseSymbolData, keyof ExchangeDataResponseArrayedSymbolData>>;
67
-
68
- type ExchangeDataResponse =
69
- {
70
- symbol: string[];
71
- } &
72
- {
73
- [K in keyof ExchangeDataResponseSymbolData]: ExchangeDataResponseSymbolData[K] | NonNullable<ExchangeDataResponseSymbolData[K]>[];
74
- };
75
-
76
- function extractField<Field extends keyof ExchangeDataResponseNonArrayedSymbolData>(data: ExchangeDataResponse, field: Field, arrayIndex: number): ExchangeDataResponseNonArrayedSymbolData[Field];
77
- function extractField<Field extends keyof ExchangeDataResponseArrayedSymbolData>(data: ExchangeDataResponse, field: Field, arrayIndex: number, valueIsArray: true): ExchangeDataResponseArrayedSymbolData[Field];
78
- function extractField<Field extends keyof ExchangeDataResponseSymbolData>(data: ExchangeDataResponse, field: Field, arrayIndex: number, valueIsArray?: boolean): ExchangeDataResponseSymbolData[Field] {
79
- const value: ExchangeDataResponse[keyof ExchangeDataResponseSymbolData] = data[field];
80
-
81
- if (Array.isArray(value) && (!valueIsArray || Array.isArray(value[0]))) {
82
- return value[arrayIndex] as ExchangeDataResponseSymbolData[Field];
83
- }
84
-
85
- return value as ExchangeDataResponseSymbolData[Field];
86
- }
87
-
88
- function symbolKey(symbol: string, currency?: string, unit?: string): string {
89
- // here we're using a separator that quite possible shouldn't be in a real symbol name
90
- return symbol + (currency !== undefined ? '_%|#|%_' + currency : '') + (unit !== undefined ? '_%|#|%_' + unit : '');
91
- }
92
-
93
- export class SymbolsStorage {
94
- private readonly _exchangesList: string[] = ['NYSE', 'FOREX', 'AMEX'];
95
- private readonly _symbolsInfo: SymbolInfoMap = {};
96
- private readonly _symbolsList: string[] = [];
97
- private readonly _datafeedUrl: string;
98
- private readonly _readyPromise: Promise<void>;
99
- private readonly _datafeedSupportedResolutions: ResolutionString[];
100
- private readonly _requester: Requester;
101
-
102
- public constructor(datafeedUrl: string, datafeedSupportedResolutions: ResolutionString[], requester: Requester) {
103
- this._datafeedUrl = datafeedUrl;
104
- this._datafeedSupportedResolutions = datafeedSupportedResolutions;
105
- this._requester = requester;
106
- this._readyPromise = this._init();
107
- this._readyPromise.catch((error: Error) => {
108
- // seems it is impossible
109
- // tslint:disable-next-line:no-console
110
- console.error(`SymbolsStorage: Cannot init, error=${error.toString()}`);
111
- });
112
- }
113
-
114
- // BEWARE: this function does not consider symbol's exchange
115
- public resolveSymbol(symbolName: string, currencyCode?: string, unitId?: string): Promise<LibrarySymbolInfo> {
116
- return this._readyPromise.then(() => {
117
- const symbolInfo = this._symbolsInfo[symbolKey(symbolName, currencyCode, unitId)];
118
- if (symbolInfo === undefined) {
119
- return Promise.reject('invalid symbol');
120
- }
121
-
122
- return Promise.resolve(symbolInfo);
123
- });
124
- }
125
-
126
- public searchSymbols(searchString: string, exchange: string, symbolType: string, maxSearchResults: number): Promise<SearchSymbolResultItem[]> {
127
- interface WeightedItem {
128
- symbolInfo: LibrarySymbolInfo;
129
- weight: number;
130
- }
131
-
132
- return this._readyPromise.then(() => {
133
- const weightedResult: WeightedItem[] = [];
134
- const queryIsEmpty = searchString.length === 0;
135
-
136
- searchString = searchString.toUpperCase();
137
-
138
- for (const symbolName of this._symbolsList) {
139
- const symbolInfo = this._symbolsInfo[symbolName];
140
-
141
- if (symbolInfo === undefined) {
142
- continue;
143
- }
144
-
145
- if (symbolType.length > 0 && symbolInfo.type !== symbolType) {
146
- continue;
147
- }
148
-
149
- if (exchange && exchange.length > 0 && symbolInfo.exchange !== exchange) {
150
- continue;
151
- }
152
-
153
- const positionInName = symbolInfo.name.toUpperCase().indexOf(searchString);
154
- const positionInDescription = symbolInfo.description.toUpperCase().indexOf(searchString);
155
-
156
- if (queryIsEmpty || positionInName >= 0 || positionInDescription >= 0) {
157
- const alreadyExists = weightedResult.some((item: WeightedItem) => item.symbolInfo === symbolInfo);
158
- if (!alreadyExists) {
159
- const weight = positionInName >= 0 ? positionInName : 8000 + positionInDescription;
160
- weightedResult.push({ symbolInfo: symbolInfo, weight: weight });
161
- }
162
- }
163
- }
164
-
165
- const result = weightedResult
166
- .sort((item1: WeightedItem, item2: WeightedItem) => item1.weight - item2.weight)
167
- .slice(0, maxSearchResults)
168
- .map((item: WeightedItem) => {
169
- const symbolInfo = item.symbolInfo;
170
- return {
171
- symbol: symbolInfo.name,
172
- full_name: symbolInfo.full_name,
173
- description: symbolInfo.description,
174
- exchange: symbolInfo.exchange,
175
- params: [],
176
- type: symbolInfo.type,
177
- ticker: symbolInfo.name,
178
- };
179
- });
180
-
181
- return Promise.resolve(result);
182
- });
183
- }
184
-
185
- private _init(): Promise<void> {
186
- interface BooleanMap {
187
- [key: string]: boolean | undefined;
188
- }
189
-
190
- const promises: Promise<void>[] = [];
191
- const alreadyRequestedExchanges: BooleanMap = {};
192
-
193
- for (const exchange of this._exchangesList) {
194
- if (alreadyRequestedExchanges[exchange]) {
195
- continue;
196
- }
197
-
198
- alreadyRequestedExchanges[exchange] = true;
199
- promises.push(this._requestExchangeData(exchange));
200
- }
201
-
202
- return Promise.all(promises)
203
- .then(() => {
204
- this._symbolsList.sort();
205
- logMessage('SymbolsStorage: All exchanges data loaded');
206
- });
207
- }
208
-
209
- private _requestExchangeData(exchange: string): Promise<void> {
210
- return new Promise((resolve: () => void, reject: (error: Error) => void) => {
211
- this._requester.sendRequest<ExchangeDataResponse>(this._datafeedUrl, 'symbol_info', { group: exchange })
212
- .then((response: ExchangeDataResponse) => {
213
- try {
214
- this._onExchangeDataReceived(exchange, response);
215
- } catch (error) {
216
- reject(error);
217
- return;
218
- }
219
-
220
- resolve();
221
- })
222
- .catch((reason?: string | Error) => {
223
- logMessage(`SymbolsStorage: Request data for exchange '${exchange}' failed, reason=${getErrorMessage(reason)}`);
224
- resolve();
225
- });
226
- });
227
- }
228
-
229
- private _onExchangeDataReceived(exchange: string, data: ExchangeDataResponse): void {
230
- let symbolIndex = 0;
231
-
232
- try {
233
- const symbolsCount = data.symbol.length;
234
- const tickerPresent = data.ticker !== undefined;
235
-
236
- for (; symbolIndex < symbolsCount; ++symbolIndex) {
237
- const symbolName = data.symbol[symbolIndex];
238
- const listedExchange = extractField(data, 'exchange-listed', symbolIndex);
239
- const tradedExchange = extractField(data, 'exchange-traded', symbolIndex);
240
- const fullName = tradedExchange + ':' + symbolName;
241
- const currencyCode = extractField(data, 'currency-code', symbolIndex);
242
- const unitId = extractField(data, 'unit-id', symbolIndex);
243
-
244
- const ticker = tickerPresent ? (extractField(data, 'ticker', symbolIndex) as string) : symbolName;
245
-
246
- const symbolInfo: LibrarySymbolInfo = {
247
- ticker: ticker,
248
- name: symbolName,
249
- base_name: [listedExchange + ':' + symbolName],
250
- full_name: fullName,
251
- listed_exchange: listedExchange,
252
- exchange: tradedExchange,
253
- currency_code: currencyCode,
254
- original_currency_code: extractField(data, 'original-currency-code', symbolIndex),
255
- unit_id: unitId,
256
- original_unit_id: extractField(data, 'original-unit-id', symbolIndex),
257
- unit_conversion_types: extractField(data, 'unit-conversion-types', symbolIndex, true),
258
- description: extractField(data, 'description', symbolIndex),
259
- has_intraday: definedValueOrDefault(extractField(data, 'has-intraday', symbolIndex), false),
260
- has_no_volume: definedValueOrDefault(extractField(data, 'has-no-volume', symbolIndex), false),
261
- minmov: extractField(data, 'minmovement', symbolIndex) || extractField(data, 'minmov', symbolIndex) || 0,
262
- minmove2: extractField(data, 'minmove2', symbolIndex) || extractField(data, 'minmov2', symbolIndex),
263
- fractional: extractField(data, 'fractional', symbolIndex),
264
- pricescale: extractField(data, 'pricescale', symbolIndex),
265
- type: extractField(data, 'type', symbolIndex),
266
- session: extractField(data, 'session-regular', symbolIndex),
267
- session_holidays: extractField(data, 'session-holidays', symbolIndex),
268
- corrections: extractField(data, 'corrections', symbolIndex),
269
- timezone: extractField(data, 'timezone', symbolIndex),
270
- supported_resolutions: definedValueOrDefault(extractField(data, 'supported-resolutions', symbolIndex, true), this._datafeedSupportedResolutions),
271
- has_daily: definedValueOrDefault(extractField(data, 'has-daily', symbolIndex), true),
272
- intraday_multipliers: definedValueOrDefault(extractField(data, 'intraday-multipliers', symbolIndex, true), ['1', '5', '15', '30', '60']),
273
- has_weekly_and_monthly: extractField(data, 'has-weekly-and-monthly', symbolIndex),
274
- has_empty_bars: extractField(data, 'has-empty-bars', symbolIndex),
275
- volume_precision: definedValueOrDefault(extractField(data, 'volume-precision', symbolIndex), 0),
276
- format: 'price',
277
- };
278
-
279
- this._symbolsInfo[ticker] = symbolInfo;
280
- this._symbolsInfo[symbolName] = symbolInfo;
281
- this._symbolsInfo[fullName] = symbolInfo;
282
- if (currencyCode !== undefined || unitId !== undefined) {
283
- this._symbolsInfo[symbolKey(ticker, currencyCode, unitId)] = symbolInfo;
284
- this._symbolsInfo[symbolKey(symbolName, currencyCode, unitId)] = symbolInfo;
285
- this._symbolsInfo[symbolKey(fullName, currencyCode, unitId)] = symbolInfo;
286
- }
287
-
288
- this._symbolsList.push(symbolName);
289
- }
290
- } catch (error) {
291
- throw new Error(`SymbolsStorage: API error when processing exchange ${exchange} symbol #${symbolIndex} (${data.symbol[symbolIndex]}): ${error.message}`);
292
- }
293
- }
294
- }
295
-
296
- function definedValueOrDefault<T>(value: T | undefined, defaultValue: T): T {
297
- return value !== undefined ? value : defaultValue;
298
- }
@@ -1,369 +0,0 @@
1
- import {
2
- DatafeedConfiguration,
3
- ErrorCallback,
4
- GetMarksCallback,
5
- HistoryCallback,
6
- IDatafeedChartApi,
7
- IDatafeedQuotesApi,
8
- IExternalDatafeed,
9
- LibrarySymbolInfo,
10
- Mark,
11
- OnReadyCallback,
12
- QuotesCallback,
13
- ResolutionString,
14
- ResolveCallback,
15
- SearchSymbolResultItem,
16
- SearchSymbolsCallback,
17
- ServerTimeCallback,
18
- SubscribeBarsCallback,
19
- TimescaleMark,
20
- SymbolResolveExtension,
21
- } from '../../../charting_library/datafeed-api';
22
-
23
- import {
24
- getErrorMessage,
25
- logMessage,
26
- RequestParams,
27
- UdfErrorResponse,
28
- } from './helpers';
29
-
30
- import {
31
- GetBarsResult,
32
- HistoryProvider,
33
- PeriodParamsWithOptionalCountback,
34
- } from './history-provider';
35
-
36
- import { IQuotesProvider } from './iquotes-provider';
37
- import { DataPulseProvider } from './data-pulse-provider';
38
- import { QuotesPulseProvider } from './quotes-pulse-provider';
39
- import { SymbolsStorage } from './symbols-storage';
40
- import { Requester } from './requester';
41
-
42
- export interface UdfCompatibleConfiguration extends DatafeedConfiguration {
43
- // tslint:disable:tv-variable-name
44
- supports_search?: boolean;
45
- supports_group_request?: boolean;
46
- // tslint:enable:tv-variable-name
47
- }
48
-
49
- export interface ResolveSymbolResponse extends LibrarySymbolInfo {
50
- s: undefined;
51
- }
52
-
53
- // it is hack to let's TypeScript make code flow analysis
54
- export interface UdfSearchSymbolsResponse extends Array<SearchSymbolResultItem> {
55
- s?: undefined;
56
- }
57
-
58
- export const enum Constants {
59
- SearchItemsLimit = 30,
60
- }
61
-
62
- type UdfDatafeedMarkType<T extends TimescaleMark | Mark> = {
63
- [K in keyof T]: T[K] | T[K][];
64
- } & {
65
- id: (string | number)[];
66
- };
67
-
68
- type UdfDatafeedMark = UdfDatafeedMarkType<Mark>;
69
- type UdfDatafeedTimescaleMark = UdfDatafeedMarkType<TimescaleMark>;
70
-
71
- function extractField<Field extends keyof Mark>(data: UdfDatafeedMark, field: Field, arrayIndex: number): Mark[Field];
72
- function extractField<Field extends keyof TimescaleMark>(data: UdfDatafeedTimescaleMark, field: Field, arrayIndex: number): TimescaleMark[Field];
73
- function extractField<T, TField extends keyof T>(data: T, field: TField, arrayIndex: number): T[TField] {
74
- const value = data[field];
75
- return Array.isArray(value) ? value[arrayIndex] : value;
76
- }
77
-
78
- /**
79
- * This class implements interaction with UDF-compatible datafeed.
80
- * See UDF protocol reference at https://github.com/tradingview/charting_library/wiki/UDF
81
- */
82
- export class UDFCompatibleDatafeedBase implements IExternalDatafeed, IDatafeedQuotesApi, IDatafeedChartApi {
83
- protected _configuration: UdfCompatibleConfiguration = defaultConfiguration();
84
- private readonly _datafeedURL: string;
85
- private readonly _configurationReadyPromise: Promise<void>;
86
-
87
- private _symbolsStorage: SymbolsStorage | null = null;
88
-
89
- private readonly _historyProvider: HistoryProvider;
90
- private readonly _dataPulseProvider: DataPulseProvider;
91
-
92
- private readonly _quotesProvider: IQuotesProvider;
93
- private readonly _quotesPulseProvider: QuotesPulseProvider;
94
-
95
- private readonly _requester: Requester;
96
-
97
- protected constructor(datafeedURL: string, quotesProvider: IQuotesProvider, requester: Requester, updateFrequency: number = 10 * 1000) {
98
- this._datafeedURL = datafeedURL;
99
- this._requester = requester;
100
- this._historyProvider = new HistoryProvider(datafeedURL, this._requester);
101
- this._quotesProvider = quotesProvider;
102
-
103
- this._dataPulseProvider = new DataPulseProvider(this._historyProvider, updateFrequency);
104
- this._quotesPulseProvider = new QuotesPulseProvider(this._quotesProvider);
105
-
106
- this._configurationReadyPromise = this._requestConfiguration()
107
- .then((configuration: UdfCompatibleConfiguration | null) => {
108
- if (configuration === null) {
109
- configuration = defaultConfiguration();
110
- }
111
-
112
- this._setupWithConfiguration(configuration);
113
- });
114
- }
115
-
116
- public onReady(callback: OnReadyCallback): void {
117
- this._configurationReadyPromise.then(() => {
118
- callback(this._configuration);
119
- });
120
- }
121
-
122
- public getQuotes(symbols: string[], onDataCallback: QuotesCallback, onErrorCallback: (msg: string) => void): void {
123
- this._quotesProvider.getQuotes(symbols).then(onDataCallback).catch(onErrorCallback);
124
- }
125
-
126
- public subscribeQuotes(symbols: string[], fastSymbols: string[], onRealtimeCallback: QuotesCallback, listenerGuid: string): void {
127
- this._quotesPulseProvider.subscribeQuotes(symbols, fastSymbols, onRealtimeCallback, listenerGuid);
128
- }
129
-
130
- public unsubscribeQuotes(listenerGuid: string): void {
131
- this._quotesPulseProvider.unsubscribeQuotes(listenerGuid);
132
- }
133
-
134
- public getMarks(symbolInfo: LibrarySymbolInfo, from: number, to: number, onDataCallback: GetMarksCallback<Mark>, resolution: ResolutionString): void {
135
- if (!this._configuration.supports_marks) {
136
- return;
137
- }
138
-
139
- const requestParams: RequestParams = {
140
- symbol: symbolInfo.ticker || '',
141
- from: from,
142
- to: to,
143
- resolution: resolution,
144
- };
145
-
146
- this._send<Mark[] | UdfDatafeedMark>('marks', requestParams)
147
- .then((response: Mark[] | UdfDatafeedMark) => {
148
- if (!Array.isArray(response)) {
149
- const result: Mark[] = [];
150
- for (let i = 0; i < response.id.length; ++i) {
151
- result.push({
152
- id: extractField(response, 'id', i),
153
- time: extractField(response, 'time', i),
154
- color: extractField(response, 'color', i),
155
- text: extractField(response, 'text', i),
156
- label: extractField(response, 'label', i),
157
- labelFontColor: extractField(response, 'labelFontColor', i),
158
- minSize: extractField(response, 'minSize', i),
159
- });
160
- }
161
-
162
- response = result;
163
- }
164
-
165
- onDataCallback(response);
166
- })
167
- .catch((error?: string | Error) => {
168
- logMessage(`UdfCompatibleDatafeed: Request marks failed: ${getErrorMessage(error)}`);
169
- onDataCallback([]);
170
- });
171
- }
172
-
173
- public getTimescaleMarks(symbolInfo: LibrarySymbolInfo, from: number, to: number, onDataCallback: GetMarksCallback<TimescaleMark>, resolution: ResolutionString): void {
174
- if (!this._configuration.supports_timescale_marks) {
175
- return;
176
- }
177
-
178
- const requestParams: RequestParams = {
179
- symbol: symbolInfo.ticker || '',
180
- from: from,
181
- to: to,
182
- resolution: resolution,
183
- };
184
-
185
- this._send<TimescaleMark[] | UdfDatafeedTimescaleMark>('timescale_marks', requestParams)
186
- .then((response: TimescaleMark[] | UdfDatafeedTimescaleMark) => {
187
- if (!Array.isArray(response)) {
188
- const result: TimescaleMark[] = [];
189
- for (let i = 0; i < response.id.length; ++i) {
190
- result.push({
191
- id: extractField(response, 'id', i),
192
- time: extractField(response, 'time', i),
193
- color: extractField(response, 'color', i),
194
- label: extractField(response, 'label', i),
195
- tooltip: extractField(response, 'tooltip', i),
196
- });
197
- }
198
-
199
- response = result;
200
- }
201
-
202
- onDataCallback(response);
203
- })
204
- .catch((error?: string | Error) => {
205
- logMessage(`UdfCompatibleDatafeed: Request timescale marks failed: ${getErrorMessage(error)}`);
206
- onDataCallback([]);
207
- });
208
- }
209
-
210
- public getServerTime(callback: ServerTimeCallback): void {
211
- if (!this._configuration.supports_time) {
212
- return;
213
- }
214
-
215
- this._send<string>('time')
216
- .then((response: string) => {
217
- const time = parseInt(response);
218
- if (!isNaN(time)) {
219
- callback(time);
220
- }
221
- })
222
- .catch((error?: string | Error) => {
223
- logMessage(`UdfCompatibleDatafeed: Fail to load server time, error=${getErrorMessage(error)}`);
224
- });
225
- }
226
-
227
- public searchSymbols(userInput: string, exchange: string, symbolType: string, onResult: SearchSymbolsCallback): void {
228
- if (this._configuration.supports_search) {
229
- const params: RequestParams = {
230
- limit: Constants.SearchItemsLimit,
231
- query: userInput.toUpperCase(),
232
- type: symbolType,
233
- exchange: exchange,
234
- };
235
-
236
- this._send<UdfSearchSymbolsResponse | UdfErrorResponse>('search', params)
237
- .then((response: UdfSearchSymbolsResponse | UdfErrorResponse) => {
238
- if (response.s !== undefined) {
239
- logMessage(`UdfCompatibleDatafeed: search symbols error=${response.errmsg}`);
240
- onResult([]);
241
- return;
242
- }
243
-
244
- onResult(response);
245
- })
246
- .catch((reason?: string | Error) => {
247
- logMessage(`UdfCompatibleDatafeed: Search symbols for '${userInput}' failed. Error=${getErrorMessage(reason)}`);
248
- onResult([]);
249
- });
250
- } else {
251
- if (this._symbolsStorage === null) {
252
- throw new Error('UdfCompatibleDatafeed: inconsistent configuration (symbols storage)');
253
- }
254
-
255
- this._symbolsStorage.searchSymbols(userInput, exchange, symbolType, Constants.SearchItemsLimit)
256
- .then(onResult)
257
- .catch(onResult.bind(null, []));
258
- }
259
- }
260
-
261
- public resolveSymbol(symbolName: string, onResolve: ResolveCallback, onError: ErrorCallback, extension?: SymbolResolveExtension): void {
262
- logMessage('Resolve requested');
263
-
264
- const currencyCode = extension && extension.currencyCode;
265
- const unitId = extension && extension.unitId;
266
-
267
- const resolveRequestStartTime = Date.now();
268
- function onResultReady(symbolInfo: LibrarySymbolInfo): void {
269
- logMessage(`Symbol resolved: ${Date.now() - resolveRequestStartTime}ms`);
270
- onResolve(symbolInfo);
271
- }
272
-
273
- if (!this._configuration.supports_group_request) {
274
- const params: RequestParams = {
275
- symbol: symbolName,
276
- };
277
- if (currencyCode !== undefined) {
278
- params.currencyCode = currencyCode;
279
- }
280
- if (unitId !== undefined) {
281
- params.unitId = unitId;
282
- }
283
-
284
- this._send<ResolveSymbolResponse | UdfErrorResponse>('symbols', params)
285
- .then((response: ResolveSymbolResponse | UdfErrorResponse) => {
286
- if (response.s !== undefined) {
287
- onError('unknown_symbol');
288
- } else {
289
- onResultReady(response);
290
- }
291
- })
292
- .catch((reason?: string | Error) => {
293
- logMessage(`UdfCompatibleDatafeed: Error resolving symbol: ${getErrorMessage(reason)}`);
294
- onError('unknown_symbol');
295
- });
296
- } else {
297
- if (this._symbolsStorage === null) {
298
- throw new Error('UdfCompatibleDatafeed: inconsistent configuration (symbols storage)');
299
- }
300
-
301
- this._symbolsStorage.resolveSymbol(symbolName, currencyCode, unitId).then(onResultReady).catch(onError);
302
- }
303
- }
304
-
305
- public getBars(symbolInfo: LibrarySymbolInfo, resolution: ResolutionString, periodParams: PeriodParamsWithOptionalCountback, onResult: HistoryCallback, onError: ErrorCallback): void {
306
- this._historyProvider.getBars(symbolInfo, resolution, periodParams)
307
- .then((result: GetBarsResult) => {
308
- onResult(result.bars, result.meta);
309
- })
310
- .catch(onError);
311
- }
312
-
313
- public subscribeBars(symbolInfo: LibrarySymbolInfo, resolution: ResolutionString, onTick: SubscribeBarsCallback, listenerGuid: string, onResetCacheNeededCallback: () => void): void {
314
- this._dataPulseProvider.subscribeBars(symbolInfo, resolution, onTick, listenerGuid);
315
- }
316
-
317
- public unsubscribeBars(listenerGuid: string): void {
318
- this._dataPulseProvider.unsubscribeBars(listenerGuid);
319
- }
320
-
321
- protected _requestConfiguration(): Promise<UdfCompatibleConfiguration | null> {
322
- return this._send<UdfCompatibleConfiguration>('config')
323
- .catch((reason?: string | Error) => {
324
- logMessage(`UdfCompatibleDatafeed: Cannot get datafeed configuration - use default, error=${getErrorMessage(reason)}`);
325
- return null;
326
- });
327
- }
328
-
329
- private _send<T>(urlPath: string, params?: RequestParams): Promise<T> {
330
- return this._requester.sendRequest<T>(this._datafeedURL, urlPath, params);
331
- }
332
-
333
- private _setupWithConfiguration(configurationData: UdfCompatibleConfiguration): void {
334
- this._configuration = configurationData;
335
-
336
- if (configurationData.exchanges === undefined) {
337
- configurationData.exchanges = [];
338
- }
339
-
340
- if (!configurationData.supports_search && !configurationData.supports_group_request) {
341
- throw new Error('Unsupported datafeed configuration. Must either support search, or support group request');
342
- }
343
-
344
- if (configurationData.supports_group_request || !configurationData.supports_search) {
345
- this._symbolsStorage = new SymbolsStorage(this._datafeedURL, configurationData.supported_resolutions || [], this._requester);
346
- }
347
-
348
- logMessage(`UdfCompatibleDatafeed: Initialized with ${JSON.stringify(configurationData)}`);
349
- }
350
- }
351
-
352
- function defaultConfiguration(): UdfCompatibleConfiguration {
353
- return {
354
- supports_search: false,
355
- supports_group_request: true,
356
- supported_resolutions: [
357
- '1' as ResolutionString,
358
- '5' as ResolutionString,
359
- '15' as ResolutionString,
360
- '30' as ResolutionString,
361
- '60' as ResolutionString,
362
- '1D' as ResolutionString,
363
- '1W' as ResolutionString,
364
- '1M' as ResolutionString,
365
- ],
366
- supports_marks: false,
367
- supports_timescale_marks: false,
368
- };
369
- }
@@ -1,11 +0,0 @@
1
- import { UDFCompatibleDatafeedBase } from './udf-compatible-datafeed-base';
2
- import { QuotesProvider } from './quotes-provider';
3
- import { Requester } from './requester';
4
-
5
- export class UDFCompatibleDatafeed extends UDFCompatibleDatafeedBase {
6
- public constructor(datafeedURL: string, updateFrequency: number = 10 * 1000) {
7
- const requester = new Requester();
8
- const quotesProvider = new QuotesProvider(datafeedURL, requester);
9
- super(datafeedURL, quotesProvider, requester, updateFrequency);
10
- }
11
- }
@@ -1,25 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowSyntheticDefaultImports": true,
4
- "importHelpers": true,
5
- "lib": [
6
- "dom",
7
- "es2018"
8
- ],
9
- "module": "es6",
10
- "moduleResolution": "node",
11
- "noEmitOnError": true,
12
- "noFallthroughCasesInSwitch": true,
13
- "noImplicitReturns": true,
14
- "noUnusedLocals": true,
15
- "outDir": "./lib/",
16
- "rootDir": "src",
17
- "sourceMap": false,
18
- "strict": true,
19
- "target": "es2018",
20
- "types": []
21
- },
22
- "include": [
23
- "./src/**/*.ts"
24
- ]
25
- }