'use strict'; import TrackerEventListenerManager from './trackerEventListenerManager'; import PeriodStatisticsStreamManager from './periodStatisticsStreamManager'; import EquityChartStreamManager from './equityChartStreamManager'; import EquityBalanceStreamManager from './equityBalanceStreamManager'; import moment from 'moment'; /** * metaapi.cloud RiskManagement equity tracking API client (see https://metaapi.cloud/docs/risk-management/) */ export default class EquityTrackingClient { /** * Constructs RiskManagement equity tracking API client instance * @param {DomainClient} domainClient domain client * @param {MetaApi} metaApi metaApi SDK instance */ constructor(domainClient, metaApi) { this._domainClient = domainClient; this._trackerEventListenerManager = new TrackerEventListenerManager(domainClient); this._equityBalanceStreamManager = new EquityBalanceStreamManager(domainClient, metaApi); this._periodStatisticsStreamManager = new PeriodStatisticsStreamManager(domainClient, this, metaApi); this._equityChartStreamManager = new EquityChartStreamManager(domainClient, this, metaApi); } /** * Creates a profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/createTracker/ * @param {String} accountId id of the MetaApi account * @param {NewTracker} tracker profit/drawdown tracker * @return {Promise} promise resolving with profit/drawdown tracker id */ createTracker(accountId, tracker) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, method: 'POST', data: tracker }); } /** * Returns trackers defined for an account. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackers/ * @param {String} accountId id of the MetaApi account * @return {Promise} promise resolving with trackers */ getTrackers(accountId) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, method: 'GET' }); } /** * Returns profit/drawdown tracker by account and id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTracker/ * @param {string} accountId id of the MetaApi account * @param {string} id tracker id * @returns {Promise} promise resolving with profit/drawdown tracker found */ getTracker(accountId, id) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, method: 'GET' }); } /** * Returns profit/drawdown tracker by account and name * @param {string} accountId id of the MetaApi account * @param {string} name tracker name * @returns {Promise} promise resolving with profit/drawdown tracker found */ getTrackerByName(accountId, name) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/name/${encodeURIComponent(name)}`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, method: 'GET' }); } /** * Updates profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/updateTracker/ * @param {String} accountId id of the MetaApi account * @param {String} id id of the tracker * @param {TrackerUpdate} update tracker update * @return {Promise} promise resolving when profit/drawdown tracker updated */ updateTracker(accountId, id, update) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, method: 'PUT', data: update }); } /** * Removes profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/removeTracker/ * @param {String} accountId id of the MetaApi account * @param {String} id id of the tracker * @return {Promise} promise resolving when profit/drawdown tracker removed */ deleteTracker(accountId, id) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, method: 'DELETE' }); } /** * Returns tracker events by broker time range. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackerEvents/ * @param {String} [startBrokerTime] value of the event time in broker timezone to start loading data from, inclusive, * in 'YYYY-MM-DD HH:mm:ss.SSS format * @param {String} [endBrokerTime] value of the event time in broker timezone to end loading data at, inclusive, * in 'YYYY-MM-DD HH:mm:ss.SSS format * @param {String} [accountId] id of the MetaApi account * @param {String} [trackerId] id of the tracker * @param {Number} [limit] pagination limit, default is 1000 * @return {Promise} promise resolving with tracker events */ getTrackerEvents(startBrokerTime, endBrokerTime, accountId, trackerId, limit) { return this._domainClient.requestApi({ url: '/users/current/tracker-events/by-broker-time', params: {startBrokerTime, endBrokerTime, accountId, trackerId, limit}, method: 'GET' }); } /** * Adds a tracker event listener and creates a job to make requests * @param {TrackerEventListener} listener tracker event listener * @param {String} [accountId] account id * @param {String} [trackerId] tracker id * @param {Number} [sequenceNumber] sequence number * @return {String} listener id */ addTrackerEventListener(listener, accountId, trackerId, sequenceNumber) { return this._trackerEventListenerManager.addTrackerEventListener(listener, accountId, trackerId, sequenceNumber); } /** * Removes tracker event listener and cancels the event stream * @param {String} listenerId tracker event listener id */ removeTrackerEventListener(listenerId) { this._trackerEventListenerManager.removeTrackerEventListener(listenerId); } /** * Returns account profit and drawdown tracking statistics by tracker id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackingStats/ * @param {String} accountId id of MetaAPI account * @param {String} trackerId id of the tracker * @param {String} [startTime] time to start loading stats from, default is current time. Note that stats is loaded in * backwards direction * @param {Number} [limit] number of records to load, default is 1 * @param {Boolean} [realTime] if true, real-time data will be requested * @return {Promise} promise resolving with profit and drawdown statistics */ getTrackingStatistics(accountId, trackerId, startTime, limit, realTime = false) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${trackerId}/statistics`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, params: {startTime, limit, realTime}, method: 'GET' }); } /** * Adds a period statistics event listener * @param {PeriodStatisticsListener} listener period statistics event listener * @param {String} accountId account id * @param {String} trackerId tracker id * @returns {Promise} listener id */ addPeriodStatisticsListener(listener, accountId, trackerId) { return this._periodStatisticsStreamManager.addPeriodStatisticsListener(listener, accountId, trackerId); } /** * Removes period statistics event listener by id * @param {String} listenerId listener id */ removePeriodStatisticsListener(listenerId) { this._periodStatisticsStreamManager.removePeriodStatisticsListener(listenerId); } /** * Returns equity chart by account id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getEquityChart/ * @param {String} accountId metaApi account id * @param {String} [startTime] starting broker time in YYYY-MM-DD HH:mm:ss format * @param {String} [endTime] ending broker time in YYYY-MM-DD HH:mm:ss format * @param {Boolean} [realTime] if true, real-time data will be requested * @param {Boolean} [fillSkips] if true, skipped records will be automatically filled based on existing ones * @return {Promise} promise resolving with equity chart */ async getEquityChart(accountId, startTime, endTime, realTime = false, fillSkips = false) { const records = await this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/equity-chart`, headers: {'auth-token': this._domainClient.token, 'api-version': '1'}, params: {startTime, endTime, realTime}, method: 'GET' }); if(fillSkips){ let i = 0; while(i < records.length - 1) { const timeDiff = new Date(records[i + 1].startBrokerTime).getTime() - new Date(records[i].startBrokerTime).getTime(); if(timeDiff > 60 * 60 * 1000 && records[i].lastBalance !== undefined) { const recordCopy = JSON.parse(JSON.stringify(records[i])); recordCopy.minEquity = recordCopy.lastEquity; recordCopy.maxEquity = recordCopy.lastEquity; recordCopy.averageEquity = recordCopy.lastEquity; recordCopy.minBalance = recordCopy.lastBalance; recordCopy.maxBalance = recordCopy.lastBalance; recordCopy.averageBalance = recordCopy.lastBalance; const startBrokerTime = new Date(recordCopy.startBrokerTime); startBrokerTime.setUTCHours(startBrokerTime.getUTCHours() + 1); startBrokerTime.setUTCMinutes(0); startBrokerTime.setUTCSeconds(0); startBrokerTime.setUTCMilliseconds(0); recordCopy.startBrokerTime = moment(startBrokerTime).format('YYYY-MM-DD HH:mm:ss.SSS'); startBrokerTime.setUTCHours(startBrokerTime.getUTCHours() + 1); startBrokerTime.setUTCMilliseconds(-1); recordCopy.endBrokerTime = moment(startBrokerTime).format('YYYY-MM-DD HH:mm:ss.SSS'); recordCopy.brokerTime = recordCopy.endBrokerTime; records.splice(i + 1, 0, recordCopy); } i++; } } return records; } /** * Adds an equity chart event listener * @param {EquityChartListener} listener equity chart event listener * @param {String} accountId account id * @param {Date} [startTime] date to start tracking from * @returns {Promise} listener id */ addEquityChartListener(listener, accountId, startTime) { return this._equityChartStreamManager.addEquityChartListener(listener, accountId, startTime); } /** * Removes equity chart event listener by id * @param {String} listenerId equity chart listener id */ removeEquityChartListener(listenerId) { this._equityChartStreamManager.removeEquityChartListener(listenerId); } /** * Adds an equity balance event listener * @param {EquityBalanceListener} listener equity balance event listener * @param {string} accountId account id * @returns {Promise} listener id */ addEquityBalanceListener(listener, accountId) { return this._equityBalanceStreamManager.addEquityBalanceListener(listener, accountId); } /** * Removes equity balance event listener by id * @param {string} listenerId equity balance listener id */ removeEquityBalanceListener(listenerId) { this._equityBalanceStreamManager.removeEquityBalanceListener(listenerId); } }