Volume transparency bars #5076 widget.changeTheme should not record an Undo entry in the Undo/Redo stack #4982 Event when source price scale is changed #4884 Time value in shape creating #4878 Price axis icons don't change after applyOverrides #4865 Cannot disable bottom toolbar timezone menu via "timezone_menu" property #4836 Showleftaxis is not valid on the mobile #4828 Fix TypeScript typings for onVisibleRangeChanged method #4802 Invalid on Mobile: 'paneProperties.legendProperties.showBarChange': false, #4797 API to attach an indicator to a particular price scale #4788 saveLoadAdapter is stringified #4776 Changing price scale of the study via changePriceScale method doesn't applies immediately #4774 Broker Config Order Market not visible #4765 [Bug] In the trading mask changing price doesn't update pips #4761 Maximize chart button #4744 Custom study plot color has no effect #4740 Moving average on seconds (createStudy) #4730 [Bug] BUY button get enable after clicking on both pips fields #4718 Overrides are not applied when defaults button is pressed #4706 Trading Terminal passes parentOrderId object while modifying the order #4705 Watermark settings are not saved to LocalStorage #4681 tvWidget.activeChart().resolution() return randomly "D" or "1D" for the daily time-frame #4630 cannot override default background color #4621 Bring to front operation is unavailable in 1.16 #4611 New style of pane buttons #4608 New mobile friendly style of the legend #4607 Centered Zoom with Ctrl #4606 TERMINAL: Apply Date Range to all charts in layout if Sync Interval is enabled #4605 Updated style of the measure tool #4604 New style of indicator loading status #4603 New measure styles #4602 Adaptive drawings dialogs #4600 Allow createStudy use undo #4590 Crosshair only on long press on mobile #4574 saveChartToServer does not call the callbacks if !autoSaveNeeded #4573 How to get current theme? #4534 getAllShapes returns trend_line instead of 'extended' #4507 hideMarksOnBar in v1.15 #4506 Trend_angle is not returned via getAllShapes #4498 How to disable vertical scrolling on the mobile side #4483 Add support for holidays and exchange working days in session spec #4467 closePopupsAndDialogs : The screenshot popup is not being closed #4438 Redirect on TV homepage after mouse click release #4423 setBodyFont of position line tool doesn't work correctly #4353 subscribe('drawing_event') click is not working #4302 "Eraser" and "dot" cursors doesn't work on IE11 #4238 zOrder for shapes with saved layout #4219 Errors/warning in console after load chart #4196 Main series API #4169 Scrolling to the top - href=“#” #4136 Tracking mode #4111 Order line drag with middle mouse button doesn't trigger onMove #4084 There are no values or na in the legend of the additional symbol (compare/add) until hover the cursor on the chart #4058 closePopupsAndDialogs doesn't work for new indicators dialog #4051 toolbar_bg doesn't affect top toolbar #3998 Check if symbol sync is enabled #3997 DOM bottom buttons are missing tooltips #3979 Question about D or 1D resolution #3861 Twitter intent button Android app #3732 Avoid chart appending storage version and "study_templates or charts" to chartStorageAPI #3702 unexpected study id by assigning studies_access option #3630 Drawing shape on indicator/study #3408 Top header in fullscreen? #2610 Allow to modify end date of long/short position tool #2381 Chart can scroll with mouse movement but no button pressed down #1908 Adaptive design for Properties dialog #862
253 lines
11 KiB
JavaScript
253 lines
11 KiB
JavaScript
import { getErrorMessage, logMessage, } from './helpers';
|
|
import { HistoryProvider, } from './history-provider';
|
|
import { DataPulseProvider } from './data-pulse-provider';
|
|
import { QuotesPulseProvider } from './quotes-pulse-provider';
|
|
import { SymbolsStorage } from './symbols-storage';
|
|
function extractField(data, field, arrayIndex) {
|
|
var value = data[field];
|
|
return Array.isArray(value) ? value[arrayIndex] : value;
|
|
}
|
|
/**
|
|
* This class implements interaction with UDF-compatible datafeed.
|
|
* See UDF protocol reference at https://github.com/tradingview/charting_library/wiki/UDF
|
|
*/
|
|
var UDFCompatibleDatafeedBase = /** @class */ (function () {
|
|
function UDFCompatibleDatafeedBase(datafeedURL, quotesProvider, requester, updateFrequency) {
|
|
var _this = this;
|
|
if (updateFrequency === void 0) { updateFrequency = 10 * 1000; }
|
|
this._configuration = defaultConfiguration();
|
|
this._symbolsStorage = null;
|
|
this._datafeedURL = datafeedURL;
|
|
this._requester = requester;
|
|
this._historyProvider = new HistoryProvider(datafeedURL, this._requester);
|
|
this._quotesProvider = quotesProvider;
|
|
this._dataPulseProvider = new DataPulseProvider(this._historyProvider, updateFrequency);
|
|
this._quotesPulseProvider = new QuotesPulseProvider(this._quotesProvider);
|
|
this._configurationReadyPromise = this._requestConfiguration()
|
|
.then(function (configuration) {
|
|
if (configuration === null) {
|
|
configuration = defaultConfiguration();
|
|
}
|
|
_this._setupWithConfiguration(configuration);
|
|
});
|
|
}
|
|
UDFCompatibleDatafeedBase.prototype.onReady = function (callback) {
|
|
var _this = this;
|
|
this._configurationReadyPromise.then(function () {
|
|
callback(_this._configuration);
|
|
});
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.getQuotes = function (symbols, onDataCallback, onErrorCallback) {
|
|
this._quotesProvider.getQuotes(symbols).then(onDataCallback).catch(onErrorCallback);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.subscribeQuotes = function (symbols, fastSymbols, onRealtimeCallback, listenerGuid) {
|
|
this._quotesPulseProvider.subscribeQuotes(symbols, fastSymbols, onRealtimeCallback, listenerGuid);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.unsubscribeQuotes = function (listenerGuid) {
|
|
this._quotesPulseProvider.unsubscribeQuotes(listenerGuid);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.calculateHistoryDepth = function (resolution, resolutionBack, intervalBack) {
|
|
return undefined;
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.getMarks = function (symbolInfo, from, to, onDataCallback, resolution) {
|
|
if (!this._configuration.supports_marks) {
|
|
return;
|
|
}
|
|
var requestParams = {
|
|
symbol: symbolInfo.ticker || '',
|
|
from: from,
|
|
to: to,
|
|
resolution: resolution,
|
|
};
|
|
this._send('marks', requestParams)
|
|
.then(function (response) {
|
|
if (!Array.isArray(response)) {
|
|
var result = [];
|
|
for (var i = 0; i < response.id.length; ++i) {
|
|
result.push({
|
|
id: extractField(response, 'id', i),
|
|
time: extractField(response, 'time', i),
|
|
color: extractField(response, 'color', i),
|
|
text: extractField(response, 'text', i),
|
|
label: extractField(response, 'label', i),
|
|
labelFontColor: extractField(response, 'labelFontColor', i),
|
|
minSize: extractField(response, 'minSize', i),
|
|
});
|
|
}
|
|
response = result;
|
|
}
|
|
onDataCallback(response);
|
|
})
|
|
.catch(function (error) {
|
|
logMessage("UdfCompatibleDatafeed: Request marks failed: " + getErrorMessage(error));
|
|
onDataCallback([]);
|
|
});
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.getTimescaleMarks = function (symbolInfo, from, to, onDataCallback, resolution) {
|
|
if (!this._configuration.supports_timescale_marks) {
|
|
return;
|
|
}
|
|
var requestParams = {
|
|
symbol: symbolInfo.ticker || '',
|
|
from: from,
|
|
to: to,
|
|
resolution: resolution,
|
|
};
|
|
this._send('timescale_marks', requestParams)
|
|
.then(function (response) {
|
|
if (!Array.isArray(response)) {
|
|
var result = [];
|
|
for (var i = 0; i < response.id.length; ++i) {
|
|
result.push({
|
|
id: extractField(response, 'id', i),
|
|
time: extractField(response, 'time', i),
|
|
color: extractField(response, 'color', i),
|
|
label: extractField(response, 'label', i),
|
|
tooltip: extractField(response, 'tooltip', i),
|
|
});
|
|
}
|
|
response = result;
|
|
}
|
|
onDataCallback(response);
|
|
})
|
|
.catch(function (error) {
|
|
logMessage("UdfCompatibleDatafeed: Request timescale marks failed: " + getErrorMessage(error));
|
|
onDataCallback([]);
|
|
});
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.getServerTime = function (callback) {
|
|
if (!this._configuration.supports_time) {
|
|
return;
|
|
}
|
|
this._send('time')
|
|
.then(function (response) {
|
|
var time = parseInt(response);
|
|
if (!isNaN(time)) {
|
|
callback(time);
|
|
}
|
|
})
|
|
.catch(function (error) {
|
|
logMessage("UdfCompatibleDatafeed: Fail to load server time, error=" + getErrorMessage(error));
|
|
});
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.searchSymbols = function (userInput, exchange, symbolType, onResult) {
|
|
if (this._configuration.supports_search) {
|
|
var params = {
|
|
limit: 30 /* SearchItemsLimit */,
|
|
query: userInput.toUpperCase(),
|
|
type: symbolType,
|
|
exchange: exchange,
|
|
};
|
|
this._send('search', params)
|
|
.then(function (response) {
|
|
if (response.s !== undefined) {
|
|
logMessage("UdfCompatibleDatafeed: search symbols error=" + response.errmsg);
|
|
onResult([]);
|
|
return;
|
|
}
|
|
onResult(response);
|
|
})
|
|
.catch(function (reason) {
|
|
logMessage("UdfCompatibleDatafeed: Search symbols for '" + userInput + "' failed. Error=" + getErrorMessage(reason));
|
|
onResult([]);
|
|
});
|
|
}
|
|
else {
|
|
if (this._symbolsStorage === null) {
|
|
throw new Error('UdfCompatibleDatafeed: inconsistent configuration (symbols storage)');
|
|
}
|
|
this._symbolsStorage.searchSymbols(userInput, exchange, symbolType, 30 /* SearchItemsLimit */)
|
|
.then(onResult)
|
|
.catch(onResult.bind(null, []));
|
|
}
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.resolveSymbol = function (symbolName, onResolve, onError) {
|
|
logMessage('Resolve requested');
|
|
var resolveRequestStartTime = Date.now();
|
|
function onResultReady(symbolInfo) {
|
|
logMessage("Symbol resolved: " + (Date.now() - resolveRequestStartTime) + "ms");
|
|
onResolve(symbolInfo);
|
|
}
|
|
if (!this._configuration.supports_group_request) {
|
|
var params = {
|
|
symbol: symbolName,
|
|
};
|
|
this._send('symbols', params)
|
|
.then(function (response) {
|
|
if (response.s !== undefined) {
|
|
onError('unknown_symbol');
|
|
}
|
|
else {
|
|
onResultReady(response);
|
|
}
|
|
})
|
|
.catch(function (reason) {
|
|
logMessage("UdfCompatibleDatafeed: Error resolving symbol: " + getErrorMessage(reason));
|
|
onError('unknown_symbol');
|
|
});
|
|
}
|
|
else {
|
|
if (this._symbolsStorage === null) {
|
|
throw new Error('UdfCompatibleDatafeed: inconsistent configuration (symbols storage)');
|
|
}
|
|
this._symbolsStorage.resolveSymbol(symbolName).then(onResultReady).catch(onError);
|
|
}
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.getBars = function (symbolInfo, resolution, rangeStartDate, rangeEndDate, onResult, onError) {
|
|
this._historyProvider.getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate)
|
|
.then(function (result) {
|
|
onResult(result.bars, result.meta);
|
|
})
|
|
.catch(onError);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.subscribeBars = function (symbolInfo, resolution, onTick, listenerGuid, onResetCacheNeededCallback) {
|
|
this._dataPulseProvider.subscribeBars(symbolInfo, resolution, onTick, listenerGuid);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype.unsubscribeBars = function (listenerGuid) {
|
|
this._dataPulseProvider.unsubscribeBars(listenerGuid);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype._requestConfiguration = function () {
|
|
return this._send('config')
|
|
.catch(function (reason) {
|
|
logMessage("UdfCompatibleDatafeed: Cannot get datafeed configuration - use default, error=" + getErrorMessage(reason));
|
|
return null;
|
|
});
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype._send = function (urlPath, params) {
|
|
return this._requester.sendRequest(this._datafeedURL, urlPath, params);
|
|
};
|
|
UDFCompatibleDatafeedBase.prototype._setupWithConfiguration = function (configurationData) {
|
|
this._configuration = configurationData;
|
|
if (configurationData.exchanges === undefined) {
|
|
configurationData.exchanges = [];
|
|
}
|
|
if (!configurationData.supports_search && !configurationData.supports_group_request) {
|
|
throw new Error('Unsupported datafeed configuration. Must either support search, or support group request');
|
|
}
|
|
if (configurationData.supports_group_request || !configurationData.supports_search) {
|
|
this._symbolsStorage = new SymbolsStorage(this._datafeedURL, configurationData.supported_resolutions || [], this._requester);
|
|
}
|
|
logMessage("UdfCompatibleDatafeed: Initialized with " + JSON.stringify(configurationData));
|
|
};
|
|
return UDFCompatibleDatafeedBase;
|
|
}());
|
|
export { UDFCompatibleDatafeedBase };
|
|
function defaultConfiguration() {
|
|
return {
|
|
supports_search: false,
|
|
supports_group_request: true,
|
|
supported_resolutions: [
|
|
'1',
|
|
'5',
|
|
'15',
|
|
'30',
|
|
'60',
|
|
'1D',
|
|
'1W',
|
|
'1M',
|
|
],
|
|
supports_marks: false,
|
|
supports_timescale_marks: false,
|
|
};
|
|
}
|