symbols-storage.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { getErrorMessage, logMessage, } from './helpers';
  2. function extractField(data, field, arrayIndex) {
  3. var value = data[field];
  4. return Array.isArray(value) ? value[arrayIndex] : value;
  5. }
  6. var SymbolsStorage = /** @class */ (function () {
  7. function SymbolsStorage(datafeedUrl, datafeedSupportedResolutions, requester) {
  8. this._exchangesList = ['NYSE', 'FOREX', 'AMEX'];
  9. this._symbolsInfo = {};
  10. this._symbolsList = [];
  11. this._datafeedUrl = datafeedUrl;
  12. this._datafeedSupportedResolutions = datafeedSupportedResolutions;
  13. this._requester = requester;
  14. this._readyPromise = this._init();
  15. this._readyPromise.catch(function (error) {
  16. // seems it is impossible
  17. console.error("SymbolsStorage: Cannot init, error=" + error.toString());
  18. });
  19. }
  20. // BEWARE: this function does not consider symbol's exchange
  21. SymbolsStorage.prototype.resolveSymbol = function (symbolName) {
  22. var _this = this;
  23. return this._readyPromise.then(function () {
  24. var symbolInfo = _this._symbolsInfo[symbolName];
  25. if (symbolInfo === undefined) {
  26. return Promise.reject('invalid symbol');
  27. }
  28. return Promise.resolve(symbolInfo);
  29. });
  30. };
  31. SymbolsStorage.prototype.searchSymbols = function (searchString, exchange, symbolType, maxSearchResults) {
  32. var _this = this;
  33. return this._readyPromise.then(function () {
  34. var weightedResult = [];
  35. var queryIsEmpty = searchString.length === 0;
  36. searchString = searchString.toUpperCase();
  37. var _loop_1 = function (symbolName) {
  38. var symbolInfo = _this._symbolsInfo[symbolName];
  39. if (symbolInfo === undefined) {
  40. return "continue";
  41. }
  42. if (symbolType.length > 0 && symbolInfo.type !== symbolType) {
  43. return "continue";
  44. }
  45. if (exchange && exchange.length > 0 && symbolInfo.exchange !== exchange) {
  46. return "continue";
  47. }
  48. var positionInName = symbolInfo.name.toUpperCase().indexOf(searchString);
  49. var positionInDescription = symbolInfo.description.toUpperCase().indexOf(searchString);
  50. if (queryIsEmpty || positionInName >= 0 || positionInDescription >= 0) {
  51. var alreadyExists = weightedResult.some(function (item) { return item.symbolInfo === symbolInfo; });
  52. if (!alreadyExists) {
  53. var weight = positionInName >= 0 ? positionInName : 8000 + positionInDescription;
  54. weightedResult.push({ symbolInfo: symbolInfo, weight: weight });
  55. }
  56. }
  57. };
  58. for (var _i = 0, _a = _this._symbolsList; _i < _a.length; _i++) {
  59. var symbolName = _a[_i];
  60. _loop_1(symbolName);
  61. }
  62. var result = weightedResult
  63. .sort(function (item1, item2) { return item1.weight - item2.weight; })
  64. .slice(0, maxSearchResults)
  65. .map(function (item) {
  66. var symbolInfo = item.symbolInfo;
  67. return {
  68. symbol: symbolInfo.name,
  69. full_name: symbolInfo.full_name,
  70. description: symbolInfo.description,
  71. exchange: symbolInfo.exchange,
  72. params: [],
  73. type: symbolInfo.type,
  74. ticker: symbolInfo.name,
  75. };
  76. });
  77. return Promise.resolve(result);
  78. });
  79. };
  80. SymbolsStorage.prototype._init = function () {
  81. var _this = this;
  82. var promises = [];
  83. var alreadyRequestedExchanges = {};
  84. for (var _i = 0, _a = this._exchangesList; _i < _a.length; _i++) {
  85. var exchange = _a[_i];
  86. if (alreadyRequestedExchanges[exchange]) {
  87. continue;
  88. }
  89. alreadyRequestedExchanges[exchange] = true;
  90. promises.push(this._requestExchangeData(exchange));
  91. }
  92. return Promise.all(promises)
  93. .then(function () {
  94. _this._symbolsList.sort();
  95. logMessage('SymbolsStorage: All exchanges data loaded');
  96. });
  97. };
  98. SymbolsStorage.prototype._requestExchangeData = function (exchange) {
  99. var _this = this;
  100. return new Promise(function (resolve, reject) {
  101. _this._requester.sendRequest(_this._datafeedUrl, 'symbol_info', { group: exchange })
  102. .then(function (response) {
  103. try {
  104. _this._onExchangeDataReceived(exchange, response);
  105. }
  106. catch (error) {
  107. reject(error);
  108. return;
  109. }
  110. resolve();
  111. })
  112. .catch(function (reason) {
  113. logMessage("SymbolsStorage: Request data for exchange '" + exchange + "' failed, reason=" + getErrorMessage(reason));
  114. resolve();
  115. });
  116. });
  117. };
  118. SymbolsStorage.prototype._onExchangeDataReceived = function (exchange, data) {
  119. var symbolIndex = 0;
  120. try {
  121. var symbolsCount = data.symbol.length;
  122. var tickerPresent = data.ticker !== undefined;
  123. for (; symbolIndex < symbolsCount; ++symbolIndex) {
  124. var symbolName = data.symbol[symbolIndex];
  125. var listedExchange = extractField(data, 'exchange-listed', symbolIndex);
  126. var tradedExchange = extractField(data, 'exchange-traded', symbolIndex);
  127. var fullName = tradedExchange + ':' + symbolName;
  128. var ticker = tickerPresent ? extractField(data, 'ticker', symbolIndex) : symbolName;
  129. var symbolInfo = {
  130. ticker: ticker,
  131. name: symbolName,
  132. base_name: [listedExchange + ':' + symbolName],
  133. full_name: fullName,
  134. listed_exchange: listedExchange,
  135. exchange: tradedExchange,
  136. description: extractField(data, 'description', symbolIndex),
  137. has_intraday: definedValueOrDefault(extractField(data, 'has-intraday', symbolIndex), false),
  138. has_no_volume: definedValueOrDefault(extractField(data, 'has-no-volume', symbolIndex), false),
  139. minmov: extractField(data, 'minmovement', symbolIndex) || extractField(data, 'minmov', symbolIndex) || 0,
  140. minmove2: extractField(data, 'minmove2', symbolIndex) || extractField(data, 'minmov2', symbolIndex),
  141. fractional: extractField(data, 'fractional', symbolIndex),
  142. pricescale: extractField(data, 'pricescale', symbolIndex),
  143. type: extractField(data, 'type', symbolIndex),
  144. session: extractField(data, 'session-regular', symbolIndex),
  145. timezone: extractField(data, 'timezone', symbolIndex),
  146. supported_resolutions: definedValueOrDefault(extractField(data, 'supported-resolutions', symbolIndex), this._datafeedSupportedResolutions),
  147. force_session_rebuild: extractField(data, 'force-session-rebuild', symbolIndex),
  148. has_daily: definedValueOrDefault(extractField(data, 'has-daily', symbolIndex), true),
  149. intraday_multipliers: definedValueOrDefault(extractField(data, 'intraday-multipliers', symbolIndex), ['1', '5', '15', '30', '60']),
  150. has_weekly_and_monthly: extractField(data, 'has-weekly-and-monthly', symbolIndex),
  151. has_empty_bars: extractField(data, 'has-empty-bars', symbolIndex),
  152. volume_precision: definedValueOrDefault(extractField(data, 'volume-precision', symbolIndex), 0),
  153. };
  154. this._symbolsInfo[ticker] = symbolInfo;
  155. this._symbolsInfo[symbolName] = symbolInfo;
  156. this._symbolsInfo[fullName] = symbolInfo;
  157. this._symbolsList.push(symbolName);
  158. }
  159. }
  160. catch (error) {
  161. throw new Error("SymbolsStorage: API error when processing exchange " + exchange + " symbol #" + symbolIndex + " (" + data.symbol[symbolIndex] + "): " + error.message);
  162. }
  163. };
  164. return SymbolsStorage;
  165. }());
  166. export { SymbolsStorage };
  167. function definedValueOrDefault(value, defaultValue) {
  168. return value !== undefined ? value : defaultValue;
  169. }