Skip to content
TradingToolCrypto edited this page Dec 24, 2023 · 14 revisions
  • please use the Robot Framework (CBP-Framework)

CryptoBridge Core API (CryptoBridgeProClass)

  • libraries that interact with the crypto exchanges

Depreciated 2023

  • all functionality has been moved to the CBP-Framework

Open Source Examples

Building Robots that run on CB_Charts

If you want to run robots on the CustomSymbol charts that the CB_Charts robot creates, you will need to bypass MT5 brokerages completely. This way, you can run your robot directly on the crypto exchange data by using chart data from the CB_Charts robot (imports data from crypto exchange and creates a native MT5 chart).

Programming Knowledge Required

You will need to redesign all order management concepts such as,

  • Opening a trade
  • Closing a trade
  • adjusting order sizes
  • Canceling orders
  • Handling stoplosses and takeprofits.

CB-API Advantages

CB_API is an unified api to trade at all crypto exchanges with the same code. All functions are normalized, therefore you can focus on your trading algorithms instead of deciphering each exchanges unique api docs. Integration is as easy as adding one header file.

Library Import

All you need to do is add the CryptoBridgeProClass into your projects by using the MQL #include <> to import the files such as

#include <TradingToolCrypto\CBP\CryptoBridgeProClass.mqh>  
CryptoBridge bridge;      // cryptoBridge class

After adding the class, you can access all the functions by typing bridge. then when you add the "." after the word bridge, MetaEditor will use intellisense to list all the available functions within the library. Below, you will find all the available functions.

Functions

Public API Calls

  bool Get_Exchange_Server_Time(int exchangeNumber);
  bool Get_OpenInterest(string sym, int exchangeNumber, int quote_precision);
  bool Get_FundRate(string sym, int exchangeNumber, int quote_precision);
  bool Get_PriceBest(string sym, int exchangeNumber, int quote_precision);
  bool Get_Price(string sym, int exchangeNumber, int quote_precision);

Private API Calls require Init_Api_Keys() function before accessing any function. This function should be within Oninit() in most cases, unless you plan to build robots that are trading at multiple exchanges simultaneously.

  bool Init_Api_Keys(int exchange);
  bool Hedge_Mode(bool on_true_off_false, int exchangeNumber);
  bool Get_Balance(string sym, string quote_base, int exchangeNumber);
  bool Get_Position(string sym, int exchangeNumber, int quote_precision);
  bool Get_OpenOrders(string sym, int exchangeNumber, int quote_precision);
  bool Open_Trade(string sym, string side, string orderType, string orderSize, string orderPrice, int quoteDigit, int lotDigit, int exchangeNumber);
  bool Open_Trade_Stop(string sym, string side, string orderType, string orderSize, string stopPrice, int quoteDigit, int lotDigit, int exchangeNumber);
  bool Open_Trade_StopLimit(string sym, string side, string orderType, string orderSize, string orderPrice, string stopPrice, int quoteDigit, int lotDigit, int exchangeNumber);
  bool Modify_Trade(string sym, string side, string orderType, string orderSize,string orderPrice, string id, int orderNumber,  int quoteDigit, int lotDigit,int exchangeNumber);
  bool Cancel_Trade(string sym, string orderId, int exchangeNumber, int order_number);
  bool Cancel_Trade_All(string sym, int exchangeNumber);
  bool Margin_Close_Position(string sym, string side, string orderType, string orderSize, string orderPrice, int quoteDigit, int lotDigit, int exchangeNumber);
  bool Margin_Set_Leverage(string sym, double leverage, int exchangeNumber);

These functions are a part of the CryptoBridgePro class that help us build our projects

string Get_Exchange_Name(int exchangeNumber);
void Parse_Orders(string exchangeName, int order_location, int id_location);
void Parse_Positions(string exchangeName, int pos_location, int liq_location, int quoteDigit);
void Parse_Wallets(string exchangeName);
double Get_Wallet_Info(int robotInstance, string exchangeName, string walletInfoSymbol);

OnInit()

int OnInit()
{
   if(bridge.Init_Api_Keys(Exchange_Number))
     {
      Print("Api Keys Loaded ");
     }
   EventSetMillisecondTimer(1000);
   return (INIT_SUCCEEDED);
}

Exchange_Number

  • BINANCE_DEX = 0
  • BINANCE = 1
  • BYBIT = 2
  • BITMEX = 3
  • KUCOIN = 4
  • BINANCE_FUTURES = 5
  • BINANCE_US = 6
  • DERIBIT = 7
  • OKEX = 8
  • MORE EXCHANGES 9+

The Exchange_Number is an input parameter that allows you to select the exchange that you want to trade with. Alternatively, you can enter the corresponding exchange number into the bridge.Init_Api_Keys(enter int value here) function if you need to interact with then one exchange at a time. Exchange_Number is the only input parameter that you need to change when you trade at a different exchange.

OnTimer() or OnTick()

The OnTimer or OnTick function is where you place all your logic for your strategy.

void OnTimer()
{
   /*
   Ping pong strategy
   */
   // api call to get the open orders
   if (!bridge.Get_OpenOrders(Exchange_Symbol_Name, Exchange_Number,Exchange_Quote_Precision))
   {
      Print("Failed to check OpenOrders");
   }
   else
   {
      // if any orders exist, they will be presented within the SubWindow Indicator
      bridge.Parse_Orders(exchangename, 640, 1040);
      Print("Parsing Open Orders if available");
   }

   // If any order exists, you can access the results within the arrays below
   int loop_orders = ArraySize(exchange_name);
   // if the array exchange_name has a value > 0 , then we have open orders
   if (loop_orders > 0)
   {
      for (int i = 0; i < loop_orders; i++)
      {
         Print("Symbol: " + exchange_symbol[i] +
               " Type: " + exchange_ordertype[i] +
               " Side: " + exchange_orderside[i] +
               " Price: " + DoubleToString(exchange_orderprice[i], Exchange_Quote_Precision) +
               " Volume: " + DoubleToString(exchange_ordersize[i], Exchange_Lot_Precision));
      }
   }
   else
   {
      Print(" No Orders exist: Processing Logic......");
      // no orders exist
      Sleep(1000);
      if (!bridge.Get_Position(Exchange_Symbol_Name, Exchange_Number, Exchange_Quote_Precision))
      {
         Print("Failed to check Get_Position");
      }
      else
      {
         // if any positions exist, they will be presented within the SubWindow Indicator
         bridge.Parse_Positions(exchangename, 275, 200, Exchange_Lot_Precision);
         Print("Parsing Positions if available");

         // If any positions exists, you can access the results within the arrays below
         int loop_positions = ArraySize(exchange_name_p);
         // if the array exchange_name_p has a value > 0 , then we have open positions
         if (loop_positions > 0)
         {
            for (int i = 0; i < loop_positions; i++)
            {
               Print("Symbol: " + exchange_symbol_p[i] +
                     " Side: " + exchange_orderside_p[i] +
                     " Price: " + DoubleToString(exchange_orderprice_p[i], Exchange_Quote_Precision) +
                     " Volume: " + DoubleToString(exchange_ordersize_p[i], Exchange_Lot_Precision));
            }
         }
         else
         {
            Print(" No Position exist: Processing Logic to do something......");
         }
      }

      // Leverage
      // maximum exposure
      // liq price
      // position size ( 1% per order)
      // takeprofit

      // grab the latest bid and ask prices
         double ask = 0, bid = 0, spread = 0;
         Sleep(1000);
         if (bridge.Get_PriceBest(Exchange_Symbol_Name, Exchange_Number, Exchange_Quote_Precision))
         {
            ask = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Ask");
            bid = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Bid");
            Print(" Bid: " + bid + " Ask: " + ask);
            if (ask != 0 && bid != 0)
            {
               spread = ask - bid;
            }
         }

         double entry_buy_price = NormalizeDouble(bid - spread, Exchange_Quote_Precision);
         if (bridge.Open_Trade(Exchange_Symbol_Name, "BUY", "LIMIT", Exchange_Lotsize, entry_buy_price,Exchange_Quote_Precision,Exchange_Lot_Precision, Exchange_Number))
         {
            Print(" Buy Limit Placed ");
         }

         Sleep(1000);

         double entry_sell_price = NormalizeDouble(ask + spread, Exchange_Quote_Precision);
         if (bridge.Open_Trade(Exchange_Symbol_Name, "SELL", "LIMIT", Exchange_Lotsize, entry_sell_price,Exchange_Quote_Precision,Exchange_Lot_Precision, Exchange_Number))
         {
            Print(" Sell Limit Placed ");
         }
   }
}

Get_Exchange_Name

Input the Exchange_Number and output the exchange name as a string variable for later use.

string exchangename = Get_Exchange_Name(Exchange_Number);

Open_Trade()

If the order is successfully placed, the function will return true, otherwise the function will return false.

bool Open_Trade(string sym, string side, string orderType, string orderSize, string orderPrice, int quoteDigit, int lotDigit, int exchangeNumber);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
side BUY or SELL
orderType MARKET, LIMIT
orderSize Contract size or coin amount such as "1000" contracts or "0.01" coins
orderPrice "0" for MARKET orderType or enter the price such as "12345.67" for LIMIT
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2
lotDigit How many values after the decimal. Bitmex and Bybit = 0 while binance BTCUSDT is 4
exchangeNumber What exchange are you trading at? 0-9
orderID Submit a client order id

Open_Trade_Stop()

If the order is successfully placed, the function will return true, otherwise the function will return false.

bool Open_Trade_Stop(string sym, string side, string orderType, string orderSize, string stopPrice, int quoteDigit, int lotDigit, int exchangeNumber);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
side BUY or SELL
orderType STOP_LOSS
orderSize Contract size or coin amount such as "1000" contracts or "0.01" coins
stopPrice enter the price such as "12345.67"
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2
lotDigit How many values after the decimal. Bitmex and Bybit = 0 while binance BTCUSDT is 4
exchangeNumber What exchange are you trading at? 0-9
orderID Submit a client order id

Open_Trade_StopLimit()

If the order is successfully placed, the function will return true, otherwise the function will return false.

bool Open_Trade_StopLimit(string sym, string side, string orderType, string orderSize, string orderPrice, string stopPrice, int quoteDigit, int lotDigit, int exchangeNumber);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
side BUY or SELL
orderType STOP_LOSS_LIMIT
orderSize Contract size or coin amount such as "1000" contracts or "0.01" coins
orderPrice Known as the executed price: enter the price such as "12345.67"
stopPrice Known as the trigger price: enter the price such as "12345.67"
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2
lotDigit How many values after the decimal. Bitmex and Bybit = 0 while binance BTCUSDT is 4
exchangeNumber What exchange are you trading at? 0-9
orderID Submit a client order id

Get_PriceBest()

The function fetches the Best Bid, Ask, and Quantity available. The values are then saved as a GlobalVariable for later use. The function will return true if the latest data was received from the exchange, otherwise the function will return false.

bool Get_PriceBest(string sym, int exchangeNumber, int quote_precision);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
exchangeNumber What exchange are you trading at? 0-9
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2

GlobalVariable

Access the Price data by using

string exchangename = Get_Exchange_Name(Exchange_Number);
double ask = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Ask");
double bid = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Bid");
double askQuantity = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Ask_q");
double bidQuantity = GlobalVariableGet(exchangename + "_" + Exchange_Symbol_Name + "_Bid_q");

Get_Position() and Get_OpenOrders()

The function fetches the positions and orders from the exchange. The values are then saved as a GlobalVariable for later use. The function will return true if the latest data was received from the exchange, otherwise the function will return false.

bool Get_Position(string sym, int exchangeNumber, int quote_precision);
bool Get_OpenOrders(string sym, int exchangeNumber, int quote_precision);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
exchangeNumber What exchange are you trading at? 0-9
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2

Parse_Orders() and Parse_Positions()

After a successful Get_Orders() or Get_Position() you will want to parse the data into arrays for later by using the Parse_Orders() and Parse_Positions() functions.

void Parse_Orders(string exchangeName, int order_location, int id_location);
void Parse_Positions(string exchangeName, int pos_location, int liq_location, int quoteDigit);
Variable Description
exchangeName The exchange name is required to find the orders and positions
location The text object location within the SubWindow indicator
quoteDigit How many values are after the decimal. BTCUSD 12345.67 has a value of 2

Parse Orders Array

The Parse_Orders() function returns the exchange orders within the arrays for easy access. See the example scripts.

string exchange_name[];
string exchange_symbol[];
string exchange_ordertype[];
string exchange_orderside[];
double exchange_orderprice[];
double exchange_ordersize[];
int    exchange_orderindex[];
string exchange_orderid[];

Parse Positions Array

The Parse_Positions() function returns the exchange positions within the arrays for easy access.

string exchange_name_p[];
string exchange_symbol_p[];
string exchange_ordertype_p[];
string exchange_orderside_p[];
double exchange_orderprice_p[];
double exchange_ordersize_p[];

Get_Balance()

bool Get_Balance(string sym, string quote_base, int exchangeNumber);
Variable Description
sym The market name such as XBTUSD at Bitmex, BTCUSDT at Binance Futures, ETHUSD at Bybit
quote_base Not supported (for later use)
exchangeNumber What exchange are you trading at? 0-9

Parse_Wallets()

void Parse_Wallets(string exchangeName);
Variable Description
exchangeName The exchange name is required to find the orders and positions

Parse Wallets array

The exchange_wallets array contains the asset or variable name, such as USDT, PNL, MARGIN, etc while the exchange_wallets_balance contains the value.

string exchange_wallets[];
double exchange_wallets_balance[];

OrderSendClass

The CryptoBridge OrderSendClass is a universal way to adapt your current Metatrader5 robot with crypto exchanges in three easy steps. The powerful CryptoBridgeProClass (Unified Exchange API for MQL Developers) is imported into the OrderSendClass to unlock all of the exchange functionality. This means that any robot you build for metatrader5 can trade on the supported list of Crypto Exchanges.

The OrderSendClass is designed to use your current robot on a Demo Account at any MT5 brokerage that offers crypto pairs. When your robot opens trades ( TP/SL, Pending Orders) on the demo account, the order requests are mirrored to your exchange account.

Step 1 Add the include file

Add the include file into the top of your project

#property copyright "TradingToolCrypto"
#property link      "https://tradingtoolcrypto.github.io/"
#property strict
#include <TradingToolCrypto\CBP\OrderSendClass.mqh>

Step 2 Add InitCBP

Add this function InitCBP() into the OnInit() metatrader initialization function

int OnInit()
  {

   if(InitCBP())
     {
      Print("CRYPTO-BRIDGE-PRO API KEYS LOADED");
     }
     return(INIT_SUCCEEDED);
}

Step 3 Find OrderSend Functions

Find all the OrderSend() metatrader functions and add OrderSendCBP() function above it with the same mql_request, mql_result parameter names.

     OrderSendCBP(mrequest,mresult);
     //--- send order
     bool success = OrderSend(mrequest,mresult);

Compile

Run the compile button within the MetaEditor and your project has added all the CryptoBridge Functionality.

Crypto Bridge API Setup

If you already have the CryptoBridgePro setup, you can save the config file and load that set file into your robot. If you don't have this config file,

  • Insert your Api Key and Secret into the correct exchange name
  • if you are using a testnet, include the word demo otherwise include live CryptoBridgePro setup

Select Exchange and Symbol

  • Select the Exchange Number within the dropdown box.
  • Type in the Exchange Symbol Name such as BTCUSDT (Binance), XBTUSD (Bitmex), BTCUSD (Bybit).
  • Adjust Exchange Lotsize
  • Adjust Exchange Lot Precision
  • Adjust Exchange Quote Precision
  • Skip Exchange Leverage
  • Skip Exchange Millisecond Speed CryptoBridgePro setup

OrderSend Class Setup

OrderSend Class setup

  • Send To Exchange = sends all order requests to the selected exchange and symbol.
  • Send TP = sends a take profit as a limit order to the exchange when the robot opens a market order or stop-market order. In most cases, Send TP = true. The request.takeprofit variable must be included within the OrderSend function request.
  • Send SL = sends a stop-market to the exchange when the robot opens a market order or stop-market order. In most cases, Send SL = true if you are using market orders only. The request.stoploss variable must be included within the OrderSend function request.

MetaTrader Buy Stop / Sell Stop If you are using stop-market orders to enter the market, Send SL = false.

How to send the Stoploss

You will need to adjust/modify the request.stoploss once the stop-market order is filled. Once the open position has a stoploss value, the exchange opens your stop-market order at the requested price.