CopyFactory trade copying API for javascript (a member of metaapi.cloud project)
CopyFactory is a powerful copy trading API which makes developing forex trade copying applications as easy as writing few lines of code.
CopyFactory API is a member of MetaApi project (https://metaapi.cloud), a powerful cloud forex trading API which supports both MetaTrader 4 and MetaTrader 5 platforms.
MetaApi is a paid service, however we may offer a free tier access in some cases.
The MetaApi pricing was developed with the intent to make your charges less or equal to what you would have to pay for hosting your own infrastructure. This is possible because over time we managed to heavily optimize our MetaTrader infrastructure. And with MetaApi you can save significantly on application development and maintenance costs and time thanks to high-quality API, open-source SDKs and convenience of a cloud service.
We found that developing reliable and flexible trade copier is a task which requires lots of effort, because developers have to solve a series of complex technical tasks to create a product.
We decided to share our product as it allows developers to start with a powerful solution in almost no time, saving on development and infrastructure maintenance costs.
FAQ is located here: https://metaapi.cloud/docs/copyfactory/faq/
Features supported:
- low latency trade copying API
- reliable trade copying API
- suitable for large-scale deployments
- suitable for large number of subscribers
- connect arbitrary number of strategy providers and subscribers
- subscribe accounts to multiple strategies at once
- select arbitrary copy ratio for each subscription
- configure symbol mapping between strategy providers and subscribers
- apply advanced risk filters on strategy provider side
- override risk filters on subscriber side
- provide multiple strategies from a single account based on magic or symbol filters
- supports manual trading on subscriber accounts while copying trades
- synchronize subscriber account with strategy providers
- monitor trading history
- calculate trade copying commissions for account managers
- support portfolio strategies as trading signal source, i.e. the strategies which include signals of several other strategies (also known as combos on some platforms)
- webhooks for external systems to create trading signals on strategies
Please note that trade copying to MT5 netting accounts is not supported in the current API version
Please check Features section of the https://metaapi.cloud/docs/copyfactory/ documentation for detailed description of all settings you can make
CopyFactory SDK is built on top of CopyFactory REST API.
CopyFactory REST API docs are available at https://metaapi.cloud/docs/copyfactory/
Please check this page for FAQ: https://metaapi.cloud/docs/copyfactory/faq/.
We published some code examples in our github repository, namely:
npm install --save metaapi.cloud-sdknpm install --save metaapi.cloud-sdk<scriptsrc="unpkg.com/metaapi.cloud-sdk"></script><script>consttoken='...';constapi=newCopyFactory(token);</script>Please visit https://app.metaapi.cloud/token web UI to obtain your API token.
In order to configure trade copying you need to:
- add MetaApi MetaTrader accounts with CopyFactory as application field value (see above)
- create CopyFactory provider and subscriber accounts and connect them to MetaApi accounts via connectionId field
- create a strategy being copied
- subscribe subscriber CopyFactory accounts to the strategy
importMetaApi,{CopyFactory}from'metaapi.cloud-sdk';consttoken='...';constmetaapi=newMetaApi(token);constcopyfactory=newCopyFactory(token);// retrieve MetaApi MetaTrader accounts with CopyFactory as application field value// provider account must have PROVIDER value in copyFactoryRolesconstproviderMetaapiAccount=awaitapi.metatraderAccountApi.getAccount('providerMetaapiAccountId');if(!providerMetaapiAccount.copyFactoryRoles||!providerMetaapiAccount.copyFactoryRoles.includes('PROVIDER')){thrownewError('Please specify PROVIDER copyFactoryRoles value in your MetaApi account in '+'order to use it in CopyFactory API');}// subscriber account must have SUBSCRIBER value in copyFactoryRolesconstsubscriberMetaapiAccount=awaitapi.metatraderAccountApi.getAccount('subscriberMetaapiAccountId');if(!subscriberMetaapiAccount.copyFactoryRoles||!subscriberMetaapiAccount.copyFactoryRoles.includes('SUBSCRIBER')){thrownewError('Please specify SUBSCRIBER copyFactoryRoles value in your MetaApi account in '+'order to use it in CopyFactory API');}letconfigurationApi=copyfactory.configurationApi;// create a strategy being copiedletstrategyId=awaitconfigurationApi.generateStrategyId();awaitconfigurationApi.updateStrategy(strategyId.id,{name: 'Test strategy',description: 'Some useful description about your strategy',accountId: providerMetaapiAccount.id,maxTradeRisk: 0.1,timeSettings: {lifetimeInHours: 192,openingIntervalInMinutes: 5}});// subscribe subscriber CopyFactory accounts to the strategyawaitconfigurationApi.updateSubscriber(subscriberMetaapiAccount.id,{name: 'Demo account',subscriptions: [{strategyId: strategyId.id,multiplier: 1}]});See esdoc in-code documentation for full definition of possible configuration options.
There are two groups of methods to retrieve paginated lists:
- with pagination in infinite scroll style
- with pagination in a classic style which allows you to calculate page count
They are applied to following entities:
- strategies:
getStrategiesWithInfiniteScrollPaginationandgetStrategiesWithClassicPagination - provider portfolios:
getPortfolioStrategiesWithInfiniteScrollPaginationandgetPortfolioStrategiesWithClassicPagination - subscribers:
getSubscribersWithInfiniteScrollPaginationandgetSubscribersWithClassicPagination
Example of retrieving strategies with pagination in infinite scroll style:
// paginate strategies, see esdoc for full list of filter options availableconststrategies=awaitapi.metatraderAccountApi.getStrategiesWithInfiniteScrollPagination({limit: 10,offset: 0});// get strategies without filter (returns 1000 strategies max)conststrategies=awaitapi.metatraderAccountApi.getStrategiesWithInfiniteScrollPagination();conststrategy=strategies.find(strategy=>strategy._id==='strategyId');Example of retrieving strategies with paginiation in classic style:
// paginate strategies, see esdoc for full list of filter options availableconststrategies=awaitapi.metatraderAccountApi.getStrategiesWithClassicPagination({limit: 10,offset: 0});conststrategy=strategies.items.find(strategy=>strategy._id==='strategyId');// number of all strategies matching filter without pagination optionsconsole.log(strategies.count);// get strategies without filter (returns 1000 strategies max)conststrategies=awaitapi.metatraderAccountApi.getStrategiesWithClassicPagination();CopyFactory allows you to monitor transactions conducted on trading accounts in real time.
lethistoryApi=copyfactory.historyApi;// retrieve trading history, please note that this method support pagination and limits number of recordsconsole.log(awaithistoryApi.getProvidedTransactions(newDate('2020-08-01'),newDate('2020-09-01')));lethistoryApi=copyfactory.historyApi;// retrieve trading history, please note that this method support pagination and limits number of recordsconsole.log(awaithistoryApi.getSubscriptionTransactions(newDate('2020-08-01'),newDate('2020-09-01')));There is a configurable time limit during which the trades can be opened. Sometimes trades can not open in time due to broker errors or trading session time discrepancy. You can resynchronize a subscriber account to place such late trades. Please note that positions which were closed manually on a subscriber account will also be reopened during resynchronization.
letaccountId='...';// CopyFactory account id// resynchronize all strategiesawaitcopyfactory.tradingApi.resynchronize(accountId);// resynchronize specific strategyawaitcopyfactory.tradingApi.resynchronize(accountId,['ABCD']);You can submit external trading signals to your trading strategy.
constaccountId='...';consttradingApi=copyfactory.tradingApi;constsignalId='...';// get signal clientconststrategySignalClient=awaittradingApi.getStrategySignalClient(strategyId);// add trading signalawaitstrategySignalClient.updateExternalSignal(signalId,{symbol: 'EURUSD',type: 'POSITION_TYPE_BUY',time: newDate(),volume: 0.01});// get external signalsconsole.log(awaitsignalClient.getStrategyExternalSignals(strategyId));// remove signalawaitstrategySignalClient.removeExternalSignal(signalId,{time: newDate()});constaccountId='...';constsubscriberSignalClient=awaittradingApi.getSubscriberSignalClient(accountId);// retrieve trading signalsconsole.log(awaitsubscriberSignalClient.getTradingSignals());A subscription to a strategy can be stopped if the strategy have exceeded allowed risk limit.
lettradingApi=copyfactory.tradingApi;letaccountId='...';// CopyFactory account idletstrategyId='...';// CopyFactory strategy id// retrieve list of strategy stopoutsconsole.log(awaittradingApi.getStopouts(accountId));// reset a stopout so that subscription can continueawaittradingApi.resetSubscriptionStopouts(accountId,strategyId,'daily-equity');You can subscribe to a stream of stopout events using the stopout listener.
import{StopoutListener}from'metaapi.cloud-sdk';lettradingApi=copyfactory.tradingApi;// create a custom class based on the StopoutListenerclassListenerextendsStopoutListener{// specify the function called on event arrivalasynconStopout(strategyStopoutEvent){console.log('Strategy stopout event',strategyStopoutEvent);}// specify the function called on error eventasynconError(error){console.log('Error event',error);}}// add listenerconstlistener=newListener();constlistenerId=tradingApi.addStopoutListener(listener);// remove listenertradingApi.removeStopoutListener(listenerId);lettradingApi=copyfactory.tradingApi;letaccountId='...';// CopyFactory account id// retrieve subscriber trading logconsole.log(awaittradingApi.getUserLog(accountId));// retrieve paginated subscriber trading log by time rangeconsole.log(awaittradingApi.getUserLog(accountId,newDate(Date.now()-24*60*60*1000),undefined,20,10));You can subscribe to a stream of strategy or subscriber log events using the user log listener.
import{UserLogListener}from'metaapi.cloud-sdk';lettradingApi=copyfactory.tradingApi;// create a custom class based on the UserLogListenerclassListenerextendsUserLogListener{// specify the function called on event arrivalasynconUserLog(logEvent){console.log('Strategy user log event',logEvent);}// specify the function called on error eventasynconError(error){console.log('Error event',error);}}// add listenerconstlistener=newListener();constlistenerId=tradingApi.addStrategyLogListener(listener,'ABCD');// remove listenertradingApi.removeStrategyLogListener(listenerId);import{UserLogListener}from'metaapi.cloud-sdk';lettradingApi=copyfactory.tradingApi;// create a custom class based on the UserLogListenerclassListenerextendsUserLogListener{// specify the function called on event arrivalasynconUserLog(logEvent){console.log('Subscriber user log event',logEvent);}// specify the function called on error eventasynconError(error){console.log('Error event',error);}}// add listenerconstlistener=newListener();constlistenerId=tradingApi.addSubscriberLogListener(listener,'accountId');// remove listenertradingApi.removeSubscriberLogListener(listenerId);You can subscribe to a stream of strategy or subscriber transaction events using the transaction listener.
import{TransactionListener}from'metaapi.cloud-sdk';lethistoryApi=copyfactory.historyApi;// create a custom class based on the TransactionListenerclassListenerextendsTransactionListener{// specify the function called on event arrivalasynconTransaction(transactionEvent){console.log('Strategy transaction event',transactionEvent);}// specify the function called on error eventasynconError(error){console.log('Error event',error);}}// add listenerconstlistener=newListener();constlistenerId=historyApi.addStrategyTransactionListener(listener,'ABCD');// remove listenerhistoryApi.removeStrategyTransactionListener(listenerId);import{TransactionListener}from'metaapi.cloud-sdk';lethistoryApi=copyfactory.historyApi;// create a custom class based on the TransactionListenerclassListenerextendsTransactionListener{// specify the function called on event arrivalasynconTransaction(transactionEvent){console.log('Subscriber transaction event',transactionEvent);}// specify the function called on error eventasynconError(error){console.log('Error event',error);}}// add listenerconstlistener=newListener();constlistenerId=historyApi.addSubscriberTransactionListener(listener,'accountId');// remove listenerhistoryApi.removeSubscriberTransactionListener(listenerId);Webhooks can be created on specific strategies and their URLs can be provided to external systems to create external trading signals. The URL contains a secret webhook ID, so no extra authorization is required on a REST API invocation to a webhook.
conststrategyId='...';letwebhook=awaitcopyfactory.configurationApi.createWebhook(strategyId);leturl=webhook.url;For example, if webhook.url is https://copyfactory-api-v1.london.agiliumtrade.ai/webhooks/yMLd8aviewgFfS4NBxZETkoVPbWAJ92t then a request can be sent to it to create an external signal:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "symbol": "EURUSD", "type": "POSITION_TYPE_BUY", "time": "2024-12-19T06:52:19.679Z", "volume": 0.1}''https://copyfactory-api-v1.london.agiliumtrade.ai/webhooks/yMLd8aviewgFfS4NBxZETkoVPbWAJ92t'Take a look at our website for the full list of APIs and features supported https://metaapi.cloud/#features
Some of the APIs you might decide to use together with MetaStats API are:
- MetaApi cloud forex API https://metaapi.cloud/docs/client/
- MetaTrader account management API https://metaapi.cloud/docs/provisioning/
- MetaStats forex trading metrics API https://metaapi.cloud/docs/metastats/
- MetaApi MT manager API https://metaapi.cloud/docs/manager/
- MetaApi risk management API https://metaapi.cloud/docs/risk-management/