'use strict'; import MetaApiClient from '../metaapi.client'; import SubscriberSignalClient from './subscriberSignal.client'; import StrategySignalClient from './strategySignal.client'; import StopoutListenerManager from './streaming/stopoutListenerManager'; import UserLogListenerManager from './streaming/userLogListenerManager'; import ConfigurationClient from './configuration.client'; import DomainClient from '../domain.client'; import StopoutListener from './streaming/stopoutListener'; import UserLogListener from './streaming/userLogListener'; import { CopyFactoryStrategyStopout, CopyFactoryStrategyStopoutReason, CopyFactoryUserLogMessage } from './trading.client.schemas'; export * from './trading.client.schemas'; /** * metaapi.cloud CopyFactory trading API (trade copying trading API) client (see * https://metaapi.cloud/docs/copyfactory/) */ export default class TradingClient extends MetaApiClient { private _configurationClient: ConfigurationClient; private _stopoutListenerManager: StopoutListenerManager; private _userLogListenerManager: UserLogListenerManager; /** * Constructs CopyFactory trading API client instance * @param {DomainClient} domainClient domain client * @param {ConfigurationClient} configurationClient configuration client */ constructor(domainClient: DomainClient, configurationClient: ConfigurationClient) { super(domainClient); this._domainClient = domainClient; this._configurationClient = configurationClient; this._stopoutListenerManager = new StopoutListenerManager(domainClient); this._userLogListenerManager = new UserLogListenerManager(domainClient); } /** * Resynchronizes the account. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/resynchronize/ * @param {string} accountId account id * @param {Array} [strategyIds] array of strategy ids to recynchronize. Default is to synchronize all * strategies * @param {Array} [positionIds] array of position ids to resynchronize. Default is to synchronize all * positions * @return {Promise} promise which resolves when resynchronization is scheduled */ async resynchronize(accountId: string, strategyIds?: Array, positionIds?: Array): Promise { if (this._isNotJwtToken()) { return this._handleNoAccessError('resynchronize'); } const opts = { url: `/users/current/subscribers/${accountId}/resynchronize`, method: 'POST', headers: { 'auth-token': this._token }, params: { strategyId: strategyIds, positionId: positionIds }, json: true }; return this._domainClient.requestCopyFactory(opts); } /** * Generates an instance of signal client for a subscriber * @param {string} subscriberId subscriber account id */ async getSubscriberSignalClient(subscriberId: string): Promise { if (this._isNotJwtToken()) { return this._handleNoAccessError('getSubscriberSignalClient'); } let accountData = await this._domainClient.getAccountInfo(subscriberId); const host = await this._domainClient.getSignalClientHost(accountData.regions); return new SubscriberSignalClient(accountData.id, host, this._domainClient); } /** * Generates an instance of signal client for a strategy * @param {string} strategyId strategy id */ async getStrategySignalClient(strategyId: string): Promise { if (this._isNotJwtToken()) { return this._handleNoAccessError('getStrategySignalClient'); } const strategy = await this._configurationClient.getStrategy(strategyId); const accountData = await this._domainClient.getAccountInfo(strategy.accountId); const host = await this._domainClient.getSignalClientHost(accountData.regions); return new StrategySignalClient(accountData.id, strategyId, host, this._domainClient); } /** * Returns subscriber account stopouts. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/getStopOuts/ * @param {string} subscriberId subscriber id * @return {Promise>} promise which resolves with stopouts found */ async getStopouts(subscriberId: string): Promise> { if (this._isNotJwtToken()) { return this._handleNoAccessError('getStopouts'); } const opts = { url: `/users/current/subscribers/${subscriberId}/stopouts`, method: 'GET', headers: { 'auth-token': this._token }, json: true }; return this._domainClient.requestCopyFactory(opts); } /** * Resets subscription stopouts. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/resetSubscriptionStopOuts/ * @param {string} subscriberId subscriber id * @param {string} strategyId strategy id * @param {CopyFactoryStrategyStopoutReason} reason stopout reason to reset * yearly-equity, monthly-equity, daily-equity * @return {Promise} promise which resolves when the stopouts are reset */ resetSubscriptionStopouts( subscriberId: string, strategyId: string, reason: CopyFactoryStrategyStopoutReason ): Promise { if (this._isNotJwtToken()) { return this._handleNoAccessError('resetSubscriptionStopouts'); } const opts = { url: `/users/current/subscribers/${subscriberId}/subscription-strategies/` + `${strategyId}/stopouts/${reason}/reset`, method: 'POST', headers: { 'auth-token': this._token }, json: true }; return this._domainClient.requestCopyFactory(opts); } /** * Resets subscriber stopouts. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/resetSubscriberStopOuts/ * @param {string} subscriberId subscriber id * @param {CopyFactoryStrategyStopoutReason} reason stopout reason to reset * yearly-equity, monthly-equity, daily-equity * @return {Promise} promise which resolves when the stopouts are reset */ resetSubscriberStopouts(subscriberId: string, reason: CopyFactoryStrategyStopoutReason): Promise { if (this._isNotJwtToken()) { return this._handleNoAccessError('resetSubscriberStopouts'); } const opts = { url: `/users/current/subscribers/${subscriberId}/stopouts/${reason}/reset`, method: 'POST', headers: { 'auth-token': this._token }, json: true }; return this._domainClient.requestCopyFactory(opts); } /** * Returns copy trading user log for an account and time range. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/getUserLog/ * @param {string} subscriberId subscriber id * @param {Date} [startTime] time to start loading data from * @param {Date} [endTime] time to stop loading data at * @param {string} [strategyId] strategy id filter * @param {string} [positionId] position id filter * @param {'DEBUG'|'INFO'|'WARN'|'ERROR'} [level] minimum severity level * @param {Number} [offset] pagination offset. Default is 0 * @param {Number} [limit] pagination limit. Default is 1000 * @return {Promise>} promise which resolves with log records found */ async getUserLog( subscriberId: string, startTime?: Date, endTime?: Date, strategyId?: string, positionId?: string, level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR', offset = 0, limit = 1000 ): Promise> { if (this._isNotJwtToken()) { return this._handleNoAccessError('getUserLog'); } const opts = { url: `/users/current/subscribers/${subscriberId}/user-log`, method: 'GET', params: { startTime, endTime, strategyId, positionId, level, offset, limit }, headers: { 'auth-token': this._token }, json: true }; let result = await this._domainClient.requestCopyFactory(opts, true); if (result) { result.map(r => r.time = new Date(r.time)); } return result; } /** * Returns event log for CopyFactory strategy, sorted in reverse chronological order. See * https://metaapi.cloud/docs/copyfactory/restApi/api/trading/getStrategyLog/ * @param {string} strategyId strategy id to retrieve log for * @param {Date} [startTime] time to start loading data from * @param {Date} [endTime] time to stop loading data at * @param {string} [positionId] position id filter * @param {'DEBUG'|'INFO'|'WARN'|'ERROR'} [level] minimum severity level * @param {Number} [offset] pagination offset. Default is 0 * @param {Number} [limit] pagination limit. Default is 1000 * @return {Promise>} promise which resolves with log records found */ async getStrategyLog( strategyId: string, startTime?: Date, endTime?: Date, positionId?: string, level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR', offset = 0, limit = 1000 ): Promise> { if (this._isNotJwtToken()) { return this._handleNoAccessError('getStrategyLog'); } const opts = { url: `/users/current/strategies/${strategyId}/user-log`, method: 'GET', params: { startTime, endTime, positionId, level, offset, limit }, headers: { 'auth-token': this._token }, json: true }; let result = await this._domainClient.requestCopyFactory(opts, true); if (result) { result.map(r => r.time = new Date(r.time)); } return result; } /** * Adds a stopout listener and creates a job to make requests * @param {StopoutListener} listener stopout listener * @param {string} [accountId] account id * @param {string} [strategyId] strategy id * @param {Number} [sequenceNumber] sequence number * @return {string} listener id */ addStopoutListener( listener: StopoutListener, accountId?: string, strategyId?: string, sequenceNumber?: number ): string { return this._stopoutListenerManager.addStopoutListener(listener, accountId, strategyId, sequenceNumber); } /** * Removes stopout listener and cancels the event stream * @param {string} listenerId stopout listener id */ removeStopoutListener(listenerId: string): void { this._stopoutListenerManager.removeStopoutListener(listenerId); } /** * Adds a strategy log listener and creates a job to make requests * @param {UserLogListener} listener user log listener * @param {string} strategyId strategy id * @param {Date} [startTime] log search start time * @param {string} [positionId] position id filter * @param {'DEBUG'|'INFO'|'WARN'|'ERROR'} [level] minimum severity level * @param {Number} [limit] log pagination limit * @return {string} listener id */ addStrategyLogListener( listener: UserLogListener, strategyId: string, startTime?: Date, positionId?: string, level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR', limit?: number ): string { return this._userLogListenerManager.addStrategyLogListener( listener, strategyId, startTime, positionId, level, limit ); } /** * Removes strategy log listener and cancels the event stream * @param {string} listenerId strategy log listener id */ removeStrategyLogListener(listenerId: string): void { this._userLogListenerManager.removeStrategyLogListener(listenerId); } /** * Adds a subscriber log listener and creates a job to make requests * @param {UserLogListener} listener user log listener * @param {string} subscriberId subscriber id * @param {Date} [startTime] log search start time * @param {string} [strategyId] strategy id filter * @param {string} [positionId] position id filter * @param {'DEBUG'|'INFO'|'WARN'|'ERROR'} [level] minimum severity level * @param {Number} [limit] log pagination limit * @return {string} listener id */ addSubscriberLogListener( listener: UserLogListener, subscriberId: string, startTime?: Date, strategyId?: string, positionId?: string, level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR', limit?: number ): string { return this._userLogListenerManager.addSubscriberLogListener( listener, subscriberId, startTime, strategyId, positionId, level, limit ); } /** * Removes subscriber log listener and cancels the event stream * @param {string} listenerId subscriber log listener id */ removeSubscriberLogListener(listenerId: string): void { this._userLogListenerManager.removeSubscriberLogListener(listenerId); } }