Latest beta-version of CcxtAppServer library includes optimized caching of exchange “markets” (instrument specifications and other trading conditions), less memory footprint during parsing of huge json-files, better error handling, and new examples.
This blogpost will present an introductory showcase with most important functions from public APIs – the script CcxtAppSrvShowcase.mq5.
First, include the headers.
#include "ccxtjsmtlib.mqh" #include "ccxtutil.mqh"
In the inputs, the Node server setup should be done (by default, it’s localhost and port 8124).
input group "Connection settings" input string NodeServer = "http://127.0.0.1:8124"; input string NodeAuth = "";
Next, provide a specific exchange you want to work with. Leave the input empty to view a printout with a list of all supported exchanges.
input string Exchange = "";
Also provide a ticker you’re interested in. If you don’t know the name, run the script first time and look at MQL5/Files/CCXT/ folder where all received data is dumped by default, so you can find json-files with full markets info.
input string Ticker = "BCH/USDT";
For watching tests (subscriptions via websockets) specify their duration:
input uint WatchingDuration = 10;
The script demonstrates how to setup credentials for private APIs, but will not use any private function.
input group "Exchange settings (Private API)" input string ApiKey = ""; input string Secret = ""; input string Uid = ""; input string Login = ""; input string Password = "";
Additional settings allow you to control the logging level, dumping of all received data, and timeouts.
input group "Auxiliary settings" input ushort Logging = 1; input bool Dumping = true; input uint Timeout = 5;
Then the main event handler OnStart comes into play. The imported functions, classes and methods from the library are highlighted in yellow. Some parts are omitted for brevity (for details look at the full source code, distributed with the library).
Inline comments are self-explanatory, I think.
If the script is running very first time, it will ask to unpack (manually) CCXT Application Server (extracted as ccxtappsrvbundle.jsc from a built-in resource), and run Node.js with it.
void OnStart() { PrintFormat("CCXT AppSrvLibrary version: %.2f", AppSrvLibraryVersion()); const static string status[] = {"Can't deploy", "App server ZIP is deployed, but not extracted", "App server files are deployed"}; const int d = DeployCcxtAppServer(); Print(status[d + 1]); if(d <= 0) { return; } SetNodeServer(NodeServer, NodeAuth); CcxtLink::Settings settings = {Logging, Dumping, Testing, Timeout, 0}; CcxtLink *link = GetLink(); link.applySettings(settings); if(!StringLen(Exchange)) { Print("Complete list of exchanges:"); Print(ListExchanges().stringify()); Print("Pro list of exchanges with websockets support:"); Print(ListExchanges(true).stringify()); Print("App Server Version: ", AppSrvVersion().stringify()); Print("CCXT lib version: ", CcxtVersion()["version"].stringify()); return; } CCXT::Credentials credentials = {ApiKey, Secret, Uid, Login, Password}; CcxtJsExchangeProIntf *ccxt = CreateExchangePro(Exchange, credentials, false); AutoPtrauto(ccxt); if(link.getLastHttpCode() != 200) { return; } const bool isPro = !!*ccxt["pro"]; if(ShowExchangeProperties) { Print("Is pro: ", isPro); Print("Required Credentials:"); ccxt["requiredCredentials"].print(); Print("Supported features:"); ccxt["has"].print(); AutoPtr f = ccxt.get("facilities"); Print("Facilities: ", f[].stringify()); } AutoPtr check = ccxt.get(); if(Dumping) DumpJsonToFile("CCXT/check-" + Exchange, check[]); if(ccxt.call("now").t != JS_PRIMITIVE) { ccxt.loadMarkets(false , false ); JsValue *info = ccxt.get("markets"); if(Dumping) DumpJsonToFile("CCXT/onlymarkets-" + Exchange, info); } else { Print("Markets are already loaded on Node"); } JsValue *orderbook = ccxt.fetchOrderBook(Ticker, 10); if(Dumping) DumpJsonToFile("CCXT/orderbook-" + Exchange + "-" + Escape(Ticker), orderbook); JsValue *ticker = ccxt.fetchTicker(Ticker); if(Dumping) DumpJsonToFile("CCXT/ticker-" + Exchange + "-" + Escape(Ticker), ticker); JsValue *ohlcv = ccxt.fetchOHLCV(Ticker, "1m", t ? t - 1000 * 60 * 10 : 0, 10); if(Dumping) DumpJsonToFile("CCXT/ohlcv-" + Exchange + "-" + Escape(Ticker), ohlcv); JsValue *trades = ccxt.fetchTrades(Ticker, t ? t - 10000 : 0, 10); if(Dumping) DumpJsonToFile("CCXT/trades-" + Exchange + "-" + Escape(Ticker), trades); if(!!*ccxt["has"]["fetchBidsAsks"]) { string array[] = {Ticker}; JsValue *bidsasks = ccxt.fetchBidsAsks(array); if(Dumping) DumpJsonToFile("CCXT/bidsasks-" + Exchange + "-" + Escape(Ticker), bidsasks); } ccxt.fetchAnything(NULL); ...
The requested URLs and corresponding names of saved files are shown in the log.
And now goes the CCXT PRO part based on websockets and live notification subscriptions.
if(isPro && ccxt.upgrade()) { ccxt.watchOrderBook(Ticker); ccxt.watchTrades(Ticker); string tickers[] = {Ticker}; ccxt.watchBidsAsks(tickers); ccxt.watchTrades(Ticker); const uint start = GetTickCount(); while(!IsStopped() && ccxt.isConnected() && (!WatchingDuration || GetTickCount() - start < WatchingDuration * 1000)) { AutoPtrj = ccxt.readMessage(); if(j[]) { Comment(j[].stringify()); } else { } } } else { if(isPro && ccxt.isConnected()) { Print("Can't upgrade to websockets"); string headers[][2]; if(ccxt.ws().getHeaders(headers)) { } ccxt.ws().close(); } } if(ccxt.isConnected()) { Print("Unsubscribing..."); ccxt.un().watchOrderBook(Ticker); ccxt.un().watchTrades(Ticker); ccxt.un().watchBidsAsks(); ccxt.un().watchTrades(Ticker); const uint start = GetTickCount(); while(!IsStopped() && ccxt.isConnected() && (GetTickCount() - start < 5 * 1000)) { Print("reading..."); AutoPtr j = ccxt.readMessage(); if(j[]) { Comment(j[].stringify()); } else { break; } } Print("Closing..."); ccxt.close(); while(!IsStopped()) { AutoPtr j = ccxt.readMessage(); if(j[]) { Comment(j[].stringify()); } else { break; } } } }
When the script is running, all incoming websocket data is shown as comments on the chart (though the info can update very quickly).
The CCXT Application Server Library is currently in beta-stage and available for testing upon request.