资源加载中... loading...

FMZ API Instructions

Author: Zero, Created: 2020-04-20 10:19:00, Updated: 2023-04-12 14:44:56

pp void main() { exchanges[0].IO(“base”, “https://api.huobipro.com”); }


The ZB exchange is special. There are two addresses: one is the market data interface address, and the other is the trading interface address. Switch the address:
```js
function main() {
    // The second parameter of exchange.IO is the trading interface address, and the third parameter is the market interface address, which is switched to an address that can be accessed domestically
    exchange.IO("base", "https://trade.zb.plus", "http://api.zb.plus")    
    // Print the account information
    Log(exchange.GetAccount())                                            
}
def main():
    exchange.IO("base", "https://trade.zb.plus", "http://api.zb.plus")
    Log(exchange.GetAccount())
void main() {
    exchange.IO("base", "https://trade.zb.plus", "http://api.zb.plus");
    Log(exchange.GetAccount());
}
  • Switch market mode Currently supported exchanges:

    Exchange Remarks
    Huobi Spot After supporting WebSocket protocol, the code exchange.IO (“currency”, “ETH”) cannot be used to switch currencies
    • exchange.IO("websocket")

      Switch the market communication protocol to websocket (default is rest), the way to get the market quotes will change after switching. The exchange.GetTicker() and exchange.GetDepth() will be switched to websocket protocol to update, from the raw active acquisition of market data to passive acquisition of market data, only Huobi Exchange is supported currently.

    When the market mode is the push mechanism, you can call the following function to set:

    • exchange.IO("mode", 0) Immediate return mode. If the current market data push has not been received from the exchange, the old market data will be returned immediately. If there is new data, the new data will be returned.

    • exchange.IO("mode", 1) Cache mode (default mode). If the latest market data of the exchange has not been received (compared with the data obtained from the previous interface), wait for receiving and then return. If the latest market data has been received before calling this function, the latest data will be returned immediately.

    • exchange.IO("mode", 2) Forced update mode. Enter and wait until the next latest push data of the exchange is received and then return.

    If you want to get the latest market information at the first time, you can switch to websocket and do not call Sleep function, and test the data immediately. The exchange.GetTicker() and exchange.GetDepth() functions work in cache mode, such as:

    function main () {
        exchange.IO("websocket")
        while (true) {
            Log(exchange.GetTicker())
        }
    }
    
    def main():
        exchange.IO("websocket")
        while True:
            Log(exchange.GetTicker())
    
    void main() {
        exchange.IO("websocket");
        while(true) {
            Log(exchange.GetTicker());
        }
    }
    
  • Exchange leverage account mode

    Use exchange.IO("trade_margin") to switch to the leverage account mode, placing orders and accessing account assets will use the exchange’s leverage interface. Use exchange.IO("trade_normal") to switch back to normal account mode.

    Supported exchanges:

    Exchange Special Remarks
    OKX The trading pairs of the leverage account mode are different from the ordinary ones, and some trading pairs may not be available. Use exchange.IO("cross", true) to switch to leveraged account full position and exchange.IO("cross", false) to switch to isolated position.
    Huobi The trading pairs of the leverage account mode are different from the ordinary ones, and some trading pairs may not be available. Huobi leverage account is divided into crossed position and isolated position. Use trade_margin to switch to a leverage account isolated position; use trade_super_margin to switch to a leverage account crossed position; use trade_normal to switch to a normal currency mode
    ZB The funds can only be transferred in QC. In the leverage trading sector, the funds between different trading pairs are independent, that is, the number of QC coins under the ETH_QC trading pair is not visible in BTC_QC
    Binance The leverage accounts are divided into crossed position and isolated position. Use trade_margin to switch to isolated position; use trade_super_margin to switch to crossed position; use trade_normal to switch to a normal currency mode
    GateIO The leverage accounts are divided into crossed position and isolated position. Use trade_margin to switch to isolated position; use trade_super_margin to switch to crossed position; use trade_normal to switch to a normal currency mode
    AscendEx Use exchange.IO("trade_margin") to switch to leverage account mode, and use exchange.IO("trade_normal") to switch back to normal account mode.

exchange.Log(…)

exchange.Log(LogType, Price, Amount) does not place an order when called, and it only records trading information to output the exchange log information.

Note:

  • This function is a member function of exchange objects, which is different from the global function Log().
  • Parameter value: LogType can take LOG_TYPE_BUY, LOG_TYPE_SELL, LOG_TYPE_CANCEL and Price as price, and Amount as quantity. When LogType is LOG_TYPE_CANCEL, Price parameter is the order ID.

Use exchange.Log(LogType, Price, Amount) to carry out the live trading follow-up testing, simulated order placement, and to assist in recording orders.

The most common usage case is: using the exchange.IO function to access the creating conditional order interface of the exchange to place conditional orders. However, using exchange.IO function will not output the exchange log information in the bot log recording. Thus, you can use exchange.Log(LogType, Price, Amount) to supplement the log output so as to record the placing order information.

var id = 123
function main() {
    // Order type: buy; price: 999; quantity: 0.1
    exchange.Log(LOG_TYPE_BUY, 999, 0.1)      
    // Cancel the order
    exchange.Log(LOG_TYPE_CANCEL, id)         
}
id = 123
def main():
    exchange.Log(LOG_TYPE_BUY, 999, 0.1)
    exchange.Log(LOG_TYPE_CANCEL, id)
void main() {
    auto id = 123;
    exchange.Log(LOG_TYPE_BUY, 999, 0.1);
    exchange.Log(LOG_TYPE_CANCEL, id);
}

exchange.HMAC(…)

exchange.HMAC(Algo, OutputAlgo, Data, Key) supports the HMAC encryption calculation of md5/sha256/sha512/sha1, and only live trading running is supported.

exchange.HMAC("sha256", "hex", "xxxxx", "{{secretkey}}") To quote accessKey, use "{{accesskey}}". To quote secretKey, use "{{secretkey}}"; or you can use plain text "abc-123-xxxx". "{{accessKey}}","{{secretkey}}" is only valid when this function is used. OutputAlgo supports: “hex”, “base64”. Specific example

Push BitMEX position changes (wss protocol)

function main() {
    var APIKEY = "your Access Key(Bitmex API ID)"
    var expires = parseInt(Date.now() / 1000) + 10
    var signature = exchange.HMAC("sha256", "hex", "GET/realtime" + expires, "{{secretkey}}")
    var client = Dial("wss://www.bitmex.com/realtime", 60)
    var auth = JSON.stringify({args: [APIKEY, expires, signature], op: "authKeyExpires"})
    var pos = 0
    client.write(auth)
    client.write('{"op": "subscribe", "args": "position"}')
    while (true) {
        bitmexData = client.read()
        if(bitmexData.table == 'position' && pos != parseInt(bitmexData.data[0].currentQty)){
            Log('position change', pos, parseInt(bitmexData.data[0].currentQty), '@')
            pos = parseInt(bitmexData.data[0].currentQty)
        }
    }
}
import time
def main():
    APIKEY = "your Access Key(Bitmex API ID)"
    expires = int(time.time() + 10)
    signature = exchange.HMAC("sha256", "hex", "GET/realtime" + str(expires), "{{secretkey}}")
    client = Dial("wss://www.bitmex.com/realtime", 60)
    auth = json.dumps({"args": [APIKEY, expires, signature], "op": "authKeyExpires"})
    pos = 0
    client.write(auth)
    client.write('{"op": "subscribe", "args": "position"}')
    while True:
        bitmexData = json.loads(client.read())
        if "table" in bitmexData and bitmexData["table"] == "position" and len(bitmexData["data"]) != 0 and pos != bitmexData["data"][0]["currentQty"]:   
            Log("position change", pos, bitmexData["data"][0]["currentQty"], "@")
            pos = bitmexData["data"][0]["currentQty"]
void main() {
    auto APIKEY = "your Access Key(Bitmex API ID)";
    auto expires = Unix() + 10;
    auto signature = exchange.HMAC("sha256", "hex", format("GET/realtime%d", expires), "{{secretkey}}");
    
    auto client = Dial("wss://www.bitmex.com/realtime", 60);
    json auth = R"({"args": [], "op": "authKeyExpires"})"_json;

    auth["args"].push_back(APIKEY);
    auth["args"].push_back(expires);
    auth["args"].push_back(signature);
    auto pos = 0;
    client.write(auth.dump());
    client.write("{\"op\": \"subscribe\", \"args\": \"position\"}");
    while(true) {
        auto bitmexData = json::parse(client.read());
        if(bitmexData["table"] == "position" && bitmexData["data"][0].find("currentQty") != bitmexData["data"][0].end() && pos != bitmexData["data"][0]["currentQty"]) {
            Log("Test");
            Log("position change", pos, bitmexData["data"][0]["currentQty"], "@");
            pos = bitmexData["data"][0]["currentQty"];
        }
    }
}

exchange.Go(…)

exchange.Go(Method, Args...) is the multi-threaded asynchronous supported function, which can turn the operation of all supported functions into asynchronous concurrent (which only supports cryptocurrency exchanges). Parameter value: Method, of string type, namely the function name concurrently called.

Note:

  • This function only creates multi-threaded execution tasks when runningin live trading. The backtest does not support multi-threaded concurrent execution tasks (the backtest is available, but it is still executed sequentially).
  • After the exchange.Go function returns an object, the wait function is called to retrieve the data returned by the thread through the object. The thread will be released automatically after the data acquisition by calling wait is completed. If specify the timeout parameter of wait, the thread will not be released even if the timeout occurs; in this way, the thread will be released automatically only by obtaining the thread result (no matter the concurrently accessed interface is called successfully or unsuccessfully).
  • In simple terms, no matter the applied thread succeeds or fails, the result must be obtained by the wait function, and the thread resource applied by the exchange.Go function is released automatically by the docker.
  • If the return result of the wait function is not obtained in the end, the thread resources will not be released automatically, which will cause the accumulation of applied threads; if the number of threads exceeds 2000, an error will be reported: "too many routine wait, max is 2000".

Supported functions: GetTicker, GetDepth, GetTrades, GetRecords, GetAccount, GetOrders, GetOrder, CancelOrder, Buy, Sell, GetPosition and IO.

function main(){
    // The following four operations are executed concurrently and asynchronously by multiple threads, without time-consuming, but with immediate return.
    var a = exchange.Go("GetTicker")
    var b = exchange.Go("GetDepth") 
    var c = exchange.Go("Buy", 1000, 0.1)
    var d = exchange.Go("GetRecords", PERIOD_H1)
           
    // Call the "wait" method, to wait for the return of the asynchronously obtained "ticker" result 
    var ticker = a.wait()            
    // Return the depth; it is possible to return null, if the acquisition fails 
    var depth = b.wait()             
    // Return the order number; limit the timeout in 1 second; the timeout returns "undefined"; this object can continue to call "wait" to wait if the last "wait" is timeout 
    var orderId = c.wait(1000)
    if(typeof(orderId) == "undefined") {
        // Timeout, reacquire
        orderId = c.wait()
    }
    var records = d.wait()
}
def main():
    a = exchange.Go("GetTicker")
    b = exchange.Go("GetDepth")
    c = exchange.Go("Buy", 1000, 0.1)
    d = exchange.Go("GetRecords", PERIOD_H1)

    ticker, ok = a.wait()
    depth, ok = b.wait()
    orderId, ok = c.wait(1000)
    if ok == False:
        orderId, ok = c.wait()
    records, ok = d.wait()
void main() {
    auto a = exchange.Go("GetTicker");
    auto b = exchange.Go("GetDepth");
    auto c = exchange.Go("Buy", 1000, 0.1);
    auto d = exchange.Go("GetRecords", PERIOD_H1);

    Ticker ticker;
    Depth depth;
    Records records;
    TId orderId;
    a.wait(ticker);
    b.wait(depth);
    if(!c.wait(orderId, 300)) {
        c.wait(orderId);
    }
    d.wait(records);
}

Note:

  • To judge undefined, use typeof(xx)==="undefined", because null == undefined is available in JavaScript.
function main() {
    var d = exchange.Go("GetRecords", PERIOD_H1)
    // Wait for K-line result
    var records = d.wait()
    // Here we wait for an asynchronous operation that has been waited and ended; it will return null, and record the error
    var ret = d.wait()
}
def main():
    d = exchange.Go("GetRecords", PERIOD_H1)
    records, ok = d.wait()
    ret, ok = d.wait()
void main() {
    auto d = exchange.Go("GetRecords", PERIOD_H1);
    Records records;
    d.wait(records);
    Records ret;
    d.wait(ret);
}

The difference between Python and JavaScript is that Python's wait function returns two parameters: the first is the result returned by the asynchronous API; the second indicates whether the asynchronous call is completed.

Python example:

def main():
    d = exchange.Go("GetRecords", PERIOD_D1)
    # "ok" must return "True", unless the strategy is stopped
    ret, ok = d.wait()          
    # If the waiting times out, or "wait" for an ended instance, "ok" returns "False"
    ret, ok = d.wait(100)       
    ret, ok = d.wait(100)       

Acquire multiple exchanges quotations concurrently:

function main() {
    while(true) {
        var beginTS = new Date().getTime()
        var arrRoutine = []
        var arrTicker = []
        var arrName = []
        for(var i = 0; i < exchanges.length; i++) {
            arrRoutine.push(exchanges[i].Go("GetTicker"))
            arrName.push(exchanges[i].GetName())
        }

        for(var i = 0; i < arrRoutine.length; i++) {
            arrTicker.push(arrRoutine[i].wait())
        }
        var endTS = new Date().getTime()

        var tbl = {
            type: "table", 
            title: "Market Quotes", 
            cols: ["Index", "Name", "Latest Executed Price"], 
            rows: []
        }
        
        for(var i = 0; i < arrTicker.length; i++) {
            tbl.rows.push([i, arrName[i], arrTicker[i].Last])
        }

        LogStatus(_D(), "The total time to acquire multiple platforms concurrently is:", endTS - beginTS, "millisecond", "\n", "`" + JSON.stringify(tbl) + "`")
        Sleep(500)
    }
}
import time 
import json
def main():
    while True:
        beginTS = time.time()
        arrRoutine = []
        arrTicker = []
        arrName = []
        for i in range(len(exchanges)):
            arrRoutine.append(exchanges[i].Go("GetTicker"))
            arrName.append(exchanges[i].GetName())

        for i in range(len(exchanges)):
            ticker, ok = arrRoutine[i].wait()
            arrTicker.append(ticker)

        endTS = time.time()
        tbl = {
            "type": "table", 
            "title": "Market Quote", 
            "cols": ["Index", "Name", "Latest Executed Price"], 
            "rows": [] 
        }

        for i in range(len(arrTicker)):
            tbl["rows"].append([i, arrName[i], arrTicker[i]["Last"]])

        LogStatus(_D(), "The total time to acquire multiple platforms concurrently is:", endTS - beginTS, "second", "\n", "`" + json.dumps(tbl) + "`")
        Sleep(500)
void main() {
    while(true) {
        int length = exchanges.size();
        auto beginTS = UnixNano() / 1000000;
        Ticker arrTicker[length] = {};
        string arrName[length] = {};
        
        // Note that to add a few exchange objects, here we need to execute the "exchanges[n].Go" function several times. In this example, we need to add four exchange objects, which can be modified in details
        auto r0 = exchanges[0].Go("GetTicker");
        auto r1 = exchanges[1].Go("GetTicker");
        auto r2 = exchanges[2].Go("GetTicker");
        auto r3 = exchanges[3].Go("GetTicker");
        GoObj *arrRoutine[length] = {&r0, &r1, &r2, &r3};
        
        for(int i = 0; i < length; i++) {
            arrName[i] = exchanges[i].GetName();
        }

        for(int i = 0; i < length; i++) {
            Ticker ticker;
            arrRoutine[i]->wait(ticker);
            arrTicker[i] = ticker;
        }        
        auto endTS = UnixNano() / 1000000;

        json tbl = R"({
            "type": "table", 
            "title": "Market Quote", 
            "cols": ["Index", "Name", "Latest Executed Price"], 
            "rows": [] 
        })"_json;

        for(int i = 0; i < length; i++) {
            json arr = R"(["", "", ""])"_json;
            arr[0] = format("%d", i);
            arr[1] = arrName[i];
            arr[2] = format("%f", arrTicker[i].Last);
            tbl["rows"].push_back(arr);
        }

        LogStatus(_D(), "The total time to acquire multiple platforms concurrently is:", format("%d", endTS - beginTS), "millisecond", "\n", "`" + tbl.dump() + "`");
        Sleep(500);
    }
}

Concurrent calls to the exchange.IO("api", ...) function:

function main() {
    /*  
       Use the OKX placing order interface to test
        POST /api/v5/trade/order        
    */
    
    var beginTS = new Date().getTime()
    var param = {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"}
    var ret1 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param))
    var ret2 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param))
    var ret3 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param))
    
    var id1 = ret1.wait()
    var id2 = ret2.wait()
    var id3 = ret3.wait()
    var endTS = new Date().getTime()    

    Log("id1:", id1)
    Log("id2:", id2)
    Log("id3:", id3)
    Log("Time for placing orders concurrently:", endTS - beginTS, "millisecond")
}
import time
import json
def main():
    beginTS = time.time()
    param = {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"}
    ret1 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param))
    ret2 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param))
    ret3 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param))

    id1, ok1 = ret1.wait()
    id2, ok2 = ret2.wait()
    id3, ok3 = ret3.wait()
    endTS = time.time()

    Log("id1:", id1)
    Log("id2:", id2)
    Log("id3:", id3)
    Log("Time for placing orders concurrently:", endTS - beginTS, "second")
void main() {
    auto beginTS = UnixNano() / 1000000;
    json param = R"({"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"})"_json;
    auto ret1 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", param.dump());
    auto ret2 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", param.dump());
    auto ret3 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", param.dump());

    json id1 = R"({})"_json;
    json id2 = R"({})"_json;
    json id3 = R"({})"_json;

    ret1.wait(id1);
    ret2.wait(id2);
    ret3.wait(id3);
    auto endTS = UnixNano() / 1000000;

    Log("id1:", id1);
    Log("id2:", id2);
    Log("id3:", id3);
    Log("Time for placing orders concurrently:", endTS - beginTS, "millisecond");
}

Account Information

exchange.GetAccount()

exchange.GetAccount() returns the exchange account information. Return value: Account structure.

  • Account structure
function main(){
    var account = exchange.GetAccount()
    Log("Account information, Balance:", account.Balance, "FrozenBalance:", account.FrozenBalance, "Stocks:",
        account.Stocks, "FrozenStocks:", account.FrozenStocks)
}
def main():
    account = exchange.GetAccount()
    Log("Account information, Balance", account["Balance"], "FrozenBalance:", account["FrozenBalance"], "Stocks:", 
        account["Stocks"], "FrozenStocks:", account["FrozenStocks"])
void main() {
    auto account = exchange.GetAccount();
    Log("Account information, Balance", account.Balance, "FrozenBalance:", account.FrozenBalance, "Stocks:", 
        account.Stocks, "FrozenStocks:", account.FrozenStocks);
}

If the exchange object is set to a cryptocurrency futures exchange and switched to a contract with USDT as margin (refer to the exchange.SetContractType function to know how to switch), the assets take USDT as margin, which is recorded in the attribute of Balance and FrozenBalance.

function main(){
    // Switch the trading pair
    exchange.IO("currency", "BTC_USDT")     
    // Take OKX futures as an example; set the contract as the contract of the week, and the current trading pair is BTC_USDT, so the current contract is BTC USDT-margined contract of this week
    exchange.SetContractType("this_week")   
    // Acquire the data of the current account assets
    var account = exchange.GetAccount()
    // The available balance of USDT as margin
    Log(account.Balance)
    // The frozen amount of USDT as margin
    Log(account.FrozenBalance)
}
def main():
    exchange.IO("currency", "BTC_USDT")
    exchange.SetContractType("this_week")    
    account = exchange.GetAccount()
    Log(account["Balance"])
    Log(account["FrozenBalance"])
void main() {
    exchange.IO("currency", "BTC_USDT");
    exchange.SetContractType("this_week");    
    auto account = exchange.GetAccount();
    Log(account.Balance);
    Log(account.FrozenBalance);
}

exchange.GetName()

exchange.GetName() returns the exchange name. Return value: string type. Generally, it’s used to determine the exchange or exchanges[n] objects in strategy code.

function main() {
    Log("Determine the exchange object to be OKX:", exchange.GetName() == "OKEX")
}
def main():
    Log("Determine the exchange object to be OKX:", exchange.GetName() == "OKEX")
void main() {
    Log("Determine the exchange object to be OKX:", exchange.GetName() == "OKEX");
}

For commanding the line version of docker, you can use the -1 command to print a list of exchange names.

exchange.GetLabel()

exchange.GetLabel() returns the custom label of the exchange. Return value: string type.

img

The exchange or exchanges[n] objects in strategy codes are normally determined by the labels set when configuring the exchange objects.

exchange.GetCurrency()

exchange.GetCurrency() returns the name of the currency pair operated by the exchange, and the cryptocurrency platform returns a string, such as LTC_BTC. Return value: string type.

exchange.SetCurrency(…)

The exchange.SetCurrency(Symbol) function is used to switch the current trading pair of the exchange object. Compatible with the switching method of exchange.IO ("currency","BTC_USDT"). It supports switching trading pairs in the backtesting system, and the name of the pricing currency cannot be changed when switching trading pairs in the backtesting system (for example, BTC_USDT can be switched to LTC_USDT, but it cannot be switched to LTC_BTC). After switching to a trading pair initially set on the non-backtesting page, the number of trading coins is 0 (for example, during the backtest, the initial value of trading pair on the backtest page is BTC_USDT, the number of BTC is 3, and the number of USDT is 10000. If you immediately switch to LTC_USDT, the number of trading coins after switching will be 0, which means the number of LTC in the account is 0, but the shared USDT amount of the switched trading pairs is still 10000).

function main() {
    var ticker = exchange.GetTicker() 
    Log(ticker)
    Log(exchange.GetAccount())    
    // Switch trading pairs, and pay attention to changes in market quote data and account information after switching
    Log("Switch LTC_USDT: ", exchange.SetCurrency("LTC_USDT"))
    ticker = exchange.GetTicker()
    Log(ticker)
    Log(exchange.GetAccount())
}
def main():
    ticker = exchange.GetTicker()
    Log(ticker)
    Log(exchange.GetAccount())
    Log(" Switch LTC_USDT: ", exchange.SetCurrency("LTC_USDT"))
    ticker = exchange.GetTicker()
    Log(ticker)
    Log(exchange.GetAccount())
void main() {
    auto ticker = exchange.GetTicker();
    Log(ticker);
    Log(exchange.GetAccount());
    exchange.SetCurrency("LTC_USDT");
    Log(" Switch LTC_USDT: ");
    ticker = exchange.GetTicker();
    Log(ticker);
    Log(exchange.GetAccount());
}

Backtest operation result:

img

exchange.GetQuoteCurrency()

exchange.GetQuoteCurrency() returns the name of the base currency operated by the echange. For example, BTC_CNY returns CNY, and ETH_BTC returns BTC. Return value: string type.

Futures Trading

For the cryptocurrency futures exchange objects, the contract code must be specified before calling its market, order and other interfaces, and the exchange.SetContractType function needs to be used to set the current contract code. When switching the current trading pair of the exchange object, you need to call the exchange.SetContractType function to reset the contract code. For digital currency exchange contract codes supported by the platform, please refer to the exchange.SetContractType function.

exchange.GetPosition()

exchange.GetPosition() obtains the current position information. Return value: position structure array. If there is no position, it returns an empty array, namely [].

  • Position structure

Normally, the cryptocurrency futures contracts are divided into two types:

  • Delivery Contract When a contract is set to a delivery contract, call the exchange.GetPosition() function, and all positions in the delivery contract under the current trading pair will be returned.

  • Perpetual Contract When a contract is set to a perpetual contract, call the exchange.GetPosition() function, and all positions in the perpetual contract under the current trading pair will be returned.

/*
    Note: if there is no position, it will returns an empty array, so you should judge whether the data returned by the interface is a null array, before you use the returned data
    For example:
    When the exchange is set to OKX futures, if the contract is set to be a delivery contract, when the position data of the current week, the next week, and the quarter is obtained, the data type will be an array of position structure.
    When the exchange is set to OKX futures, if the contract is set to a perpetual contract, the array of position structure containing the position data of the perpetual contract will be obtained.
*/

function main(){
    exchange.SetContractType("this_week")
    exchange.SetMarginLevel(10)
    exchange.SetDirection("buy")
    exchange.Buy(10000, 2)
    var position = exchange.GetPosition()
    if(position.length > 0){
        Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
            position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,
            "ContractType:", position[0].ContractType)
    }
}
def main():
    exchange.SetContractType("this_week")
    exchange.SetMarginLevel(10)
    exchange.SetDirection("buy")
    exchange.Buy(10000, 2)
    position = exchange.GetPosition()
    if len(position) > 0:
        Log("Amount:", position[0]["Amount"], "FrozenAmount:", position[0]["FrozenAmount"], "Price:", 
            position[0]["Price"], "Profit:", position[0]["Profit"], "Type:", position[0]["Type"], 
            "ContractType:", position[0]["ContractType"])
void main() {
    exchange.SetContractType("this_week");
    exchange.SetMarginLevel(10);
    exchange.SetDirection("buy");
    exchange.Buy(10000, 2);
    auto position = exchange.GetPosition();
    if(position.size() > 0) {
        Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:", 
            position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type, 
            "ContractType:", position[0].ContractType);
    } 
}

exchange.SetMarginLevel(…)

exchange.SetMarginLevel(MarginLevel) sets the leverage size. Parameter value: numeric type.

Set the size of the leverage for placing cryptocurrency futures orders, for example:

function main() {
    exchange.SetMarginLevel(10)
}
def main():
    exchange.SetMarginLevel(10)
void main() {
    exchange.SetMarginLevel(10);
}

For cryptocurrency futures, the leverage mechanisms of cryptocurrency futures exchanges are not uniform. On some exchanges, the leverage value of futures is a parameter in the placing order interface. In this case, calling the SetMarginLevel function cannot generate a network request, but only sets the leverage variable in the bottom layer (used to pass parameters in the placing order interface). The futures leverage of some exchanges is a setting of the exchange, which needs to be set on the exchange website page or by using the API interface. At this point, calling the SetMarginLevel function will generate a network request, and it may fail to set the leverage for various reasons. For example: if there are current positions and pending orders, the leverage value may not be set for this trading pair and the underlying object.

Notes for setting the leverage in the strategy design:

  • Only cryptocurrency futures are supported.
  • The backtest supports switching leverages.

exchange.SetDirection(…)

exchange.SetDirection(Direction) set exchange.Buy or exchange.Sell to make directions for placing futures orders. Parameter value: string type.

The SetDirection function sets the correspondence between the futures trading direction and the order placing function:

Order Placing Function Parameter Setting Direction for “SetDirection” Function Remarks
exchange.Buy “buy” buy open long position
exchange.Buy “closesell” buy close short position
exchange.Sell “sell” sell open short position
exchange.Sell “closebuy” sell close long position

The parameter Direction can take the four parameters, including buy, closebuy, sell and closesell.

function main(){
    // Make an example for setting OKX futures weekly contract
    exchange.SetContractType("this_week")    
    // Set 5 times of leverage
    exchange.SetMarginLevel(5)
    // Set the order placing type into placing long order
    exchange.SetDirection("buy")
    // Place an order with the contract quantity of 2, at the price of 10,000
    exchange.Buy(10000, 2)              
    exchange.SetMarginLevel(5)
    exchange.SetDirection("closebuy")
    exchange.Sell(1000, 2)
}
def main():
    exchange.SetContractType("this_week")
    exchange.SetMarginLevel(5)
    exchange.SetDirection("buy")
    exchange.Buy(10000, 2)
    exchange.SetMarginLevel(5)
    exchange.SetDirection("closebuy")
    exchange.Sell(1000, 2)
void main() {
    exchange.SetContractType("this_week");
    exchange.SetMarginLevel(5);
    exchange.SetDirection("buy");
    exchange.Buy(10000, 2);
    exchange.SetMarginLevel(5);
    exchange.SetDirection("closebuy");
    exchange.Sell(1000, 2);
}

exchange.SetContractType(…)

exchange.SetContractType(ContractType) set the contract type. Parameter value: string type. In the cryptocurrency strategies, take “BTC_USDT” as an example. When switch trading pairs by exchange.SetCurrency("BTC_USDT") or exchange.IO("currency", "BTC_USDT"), you need to use the exchange.SetContractType function to reset the contract to determine the current contract that needs to be operated under the new trading pair. The system determines whether it is a currency-based contract or a U-based contract based on the trading pair. For example, when the trading pair is set to BTC_ USDT, use function exchange.SetContractType to set the contract code swap, which is set as the USDT-based perpetual contract of BTC. If the trading pair is BTC_ USD, use function exchange.SetContractType to set the contract code swap, which is set as the currency-based perpetual contract of BTC.

Unless otherwise specified, the delivery contract code in a cryptocurrency futures contract generally includes:

  • this_week: weekly contract
  • next_week: next week contract
  • quarter: quarterly contract
  • next_quarter: next quarter contract

Unless otherwise specified, the perpetual contract code in a cryptocurrency futures contract generally includes:

  • swap: perpetual contract

Set the current contract to a weekly contract:

function main() {
    // Set to weekly contract
    exchange.SetContractType("this_week") 
}
def main():
    exchange.SetContractType("this_week")
void main() {
    exchange.SetContractType("this_week");
}

Detailed description on the contract naming of each supported cryptocurrency exchange is shown as follows:

  • OKX Set to perpetual contract: exchange.SetContractType("swap") Set to this week contract: exchange.SetContractType("this_week") Set to next week contract: exchange.SetContractType("next_week") Set to quarterly contract: exchange.SetContractType("quarter") Set to next quarter contract: exchange.SetContractType("next_quarter") OKX USDT-margined contract can be switched to the contract using USDT settlement corresponding to the current contract by switching trading pair (or set it directly when adding the exchange objects). For example:

    function main() {
        // The default trading pair is BTC_USD, the contract is set to the weekly contract, and the contract is the crypto-margined contract
        exchange.SetContractType("this_week")
        Log("ticker:", exchange.GetTicker())
        
        // Switch trading pairs, and then set a contract to a USDT-margined contract, which is different from the crypto-margined contract
        exchange.IO("currency", "BTC_USDT")   
        exchange.SetContractType("swap")
        Log("ticker:", exchange.GetTicker())
    }
    
    def main():
        exchange.SetContractType("this_week")
        Log("ticker:", exchange.GetTicker())
        exchange.IO("currency", "BTC_USDT")
        exchange.SetContractType("swap")
        Log("ticker:", exchange.GetTicker())
    
    void main() {
        exchange.SetContractType("this_week");
        Log("ticker:", exchange.GetTicker());
        exchange.IO("currency", "BTC_USDT");
        exchange.SetContractType("swap");
        Log("ticker:", exchange.GetTicker());
    }
    
  • Futures_HuobiDM Set to this week contract: exchange.SetContractType("this_week") Set to next week contract: exchange.SetContractType("next_week") Set to quarterly contract: exchange.SetContractType("quarter") Set to next quarter contract: exchange.SetContractType("next_quarter") Set to perpetual contract: exchange.SetContractType("swap")

    The platform supports the USDT-margined contracts. Take the BTC contract as an example. You can switch to a USDT-margined contract only by using exchange.SetCurrency("BTC_USDT"), or by setting the current trading pair to BTC_USDT directly when you configure the bot parameters and add exchange objects. After switching the trading pair, you need to call exchange.SetContractType function again to set the contract.

  • Futures_BitMEX Set to perpetual contract: exchange.SetContractType("XBTUSD"), exchange.SetContractType("APTUSDT"). The contract is settled at some specific time, and log in to the official website of BitMEX to check out each contract code for more details. For example: exchange.SetContractType("XBTM19").

  • Futures_GateIO Set to this week contract: exchange.SetContractType("this_week"). Set to next week contract: exchange.SetContractType("next_week"). Set to quarterly contract: exchange.SetContractType("quarter"). Set to next quarter contract: exchange.SetContractType("next_quarter"). Set to perpetual contract: exchange.SetContractType("swap"). The exchange supports the USDT-margined contracts. Take the BTC contract as an example. You can switch to a USDT-margined contract only by using exchange.SetCurrency("BTC_USDT"), or by setting the current trading pair to BTC_USDT directly when you configure the live trading parameters and add exchange objects. After switching the trading pair, you need to call exchange.SetContractType function again to set the contract.

  • Futures_Deribit Set to perpetual contract: exchange.SetContractType("BTC-PERPETUAL") Supporting Deribit USDC contract; call exchange.SetContractType("ADA_USDC-PERPETUAL") to set ADA USDC-margined perpetual contract. The contract is settled at some specific time, and log in to the official website of Deribit to check out each contract code for more details, such as: exchange.SetContractType("BTC-27APR18").

  • Futures_KuCoin

    • Crypto-Margined Contract; For example, set the trading pair to BTC_USD, and then set the contract code, which is called crypto-margined contract. Set to perpetual contract: exchange.SetContractType("swap") Set to quarterly contract: exchange.SetContractType("quarter") Set to next quarter contract: exchange.SetContractType("next_quarter")
    • USDT-Margined Contract: For example, set the trading pair to BTC_USDT, and then set the contract code, which is USDT-margined contract. Set to perpetual contract: exchange.SetContractType("swap").
  • Futures_Binance Binance Futures defaults to no setting contract status, so you need to set the contract first. Set to perpetual contract: exchange.SetContractType("swap") Binance Futures perpetual contracts can be USDT-margined contracts. For example, in the BTC USDT-margined contract, the trading pair is set to BTC_USDT. Binance Futures perpetual contracts also include crypto-margined contracts. For example, in the crypto-margined contract, set the trading pair to BTC_USD.

    Set to quarterly contract: exchange.SetContractType("quarter") The delivery contracts include crypto-margined contracts (namely taking the used currency as margin). For example, in the quarterly contract of BTC, the trading pair is set to BTC_USD, and then set the contract code exchange.SetContractType("quarter"), which is setting BTC crypto-margined quarterly contract.

    Set to next quarter contract: exchange.SetContractType("next_quarter") For example, in the quarterly crypto-margined contract of BTC, the trading pair is set to BTC_USD, and then set the contract code exchange.SetContractType("next_quarter). Binance supports part of USDT-margined delivery contracts, such as setting the BTC trading pair to BTC_USDT, and then set the contract code.

  • Futures_Bibox Bibox perpetual contract code: swap. Set to perpetual contract: exchange.SetContractType("swap").

  • Futures_AOFEX AOFEX perpetual contract code: swap. Set to perpetual contract: exchange.SetContractType("swap").

  • Futures_BFX BFX perpetual contract code: swap. Set to perpetual contract:exchange.SetContractType("swap").

  • Futures_Bybit Bybit defaults to the perpetual contract of the current trading pair. Contract code: swap. Quarterly contract code: quarter. Next quarter contract code: next_quarter.

  • Futures_Kraken Kraken defaults to no setting contract status, so you need to set the contract code. Contract code: swap: perpetual contract. month: monthly contract. quarter: quarterly contract. next_quarter: next quarter contract.

  • Futures_Bitfinex Bitfinex defaults to the perpetual contract of the current trading pair. Contract code: swap.

  • Futures_Bitget Bitget defaults to the perpetual contract of the current trading pair. Contract code: swap. The trading pair is set to BTC_USD, indicating crypto-margined contract; the trading pair is set to BTC_USDT, indicating USDT-margined contract. The simulated contracts can set the trading pairs into: SBTC_USD and BTC_SUSDT.

  • Futures_dYdX The contract code of dYdX perpetual contract: swap. Set to perpetual contract: exchange.SetContractType("swap"). dYdX only has USDT-margined contracts.

  • Futures_MEXC The contract code of MEXC perpetual contract: swap. Set to perpetual contract: exchange.SetContractType("swap"). The trading pair is set to BTC_USD, indicating crypto-margined contract; the trading pair is set to BTC_USDT, indicating USDT-margined contract.

When writing cryptocurrency strategies, call exchange.SetContractType(ContractType) function and the detailed contract information set by the contract parameter ContractType will be returned.

For example, running the strategy code of OKX contract set as the exchange object:

function main(){
    // Set to weekly contract
    var ret = exchange.SetContractType("this_week")     
    // Return the information of the weekly contract
    Log(ret)
}
def main():
    ret = exchange.SetContractType("this_week")
    Log(ret)
void main() {
    auto ret = exchange.SetContractType("this_week");
    Log(ret);
}

Run the strategy in JavaScript language, and print ret data, namely the detailed information of this_week contract:

{
    "instrument":"BTC-USD-191101",
    "InstrumentID":"BTC-USD-191101"
}   

exchange.GetContractType()

exchange.GetContractType() returns the currently set contract code of the exchange object (exchange), return value: string.

function main () {
    Log(exchange.SetContractType("this_week")) 
    Log(exchange.GetContractType())
}
def main():
    Log(exchange.SetContractType("this_week"))
    Log(exchange.GetContractType())
void main() {
    Log(exchange.SetContractType("this_week"));
    Log(exchange.GetContractType());
}

Futures_OP Errors

The following table describes the error information related to the exchange objects of the cryptocurrency futures contracts:

Value Function display error Trigger function Description
0 Futures_OP 0 exchange.SetMarginLevel error of calling leverage function
1 Futures_OP 1 exchange.SetDirection error of setting futures trading direction function
2 Futures_OP 2 exchange.SetContractType error of setting contract function
3 Futures_OP 3 exchange.GetPosition error of getting position function
4 Futures_OP 4 exchange.IO error of calling IO function

Options Trading

Cryptocurrency Options

Use exchange.SetContractType function to set contracts; Different exchanges have different options contract codes.

Cryptocurrency options exchanges supported by FMZ Quant Trading platform

  • Deribit For Deribit exchange, it is only necessary to call the exchange.SetContractType function to set the contract as an options contract. After setting up the options contract, when calling the market interface such as GetTicker, all the market data of the options contract is obtained. Use exchange.Sell and exchange.Buy functions to place an order, and pay attention to the trading direction when placing an order, and set the trading direction by exchange.SetDirection. Use the exchange.Cancel function to cancel an order; use the exchange.GetPosition function to query positions.

    The strategy code for reference: The Testing Strategy of Deribit Options

  • OKX Setting up contracts, placing orders, canceling orders, querying orders, and obtaining market quotes, etc. are of the same operation as Deribit, and the contract code format is BTC-USD-200626-4500-C. You can query the information related to the contract through the interface https://www.okx.com/api/v5/public/instruments.

    For example, to query the information of BTC options contracts:

    function main() {
        Log(HttpQuery("https://www.okx.com/api/v5/public/instruments?instType=OPTION&uly=BTC-USD"))
    }
    
    import json
    import urllib.request
    def main():
        ret = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/public/instruments?instType=OPTION&uly=BTC-USD").read().decode('utf-8'))
        Log(ret)
    
    void main() {
        Log(HttpQuery("https://www.okx.com/api/v5/public/instruments?instType=OPTION&uly=BTC-USD"));
    }
    
  • Futures_HuobiDM For example, Huobi options contract code: BTC-USDT-201225-P-13000; the contract is a BTC contract; the exercise date is December 25, 2020; the options are Put Options (PUT); the strike price is $13,000. For Call Options, the premium paid by the buyer is USDT, indicating the USDT in the account assets is used; the seller’s margin is currency, which is guaranteed by the currency in the assets. For Put Options, the premium paid by the buyer is USDT, indicating the USDT in the account assets is used; the seller’s margin is USDT, which is guaranteed by the USDT in the assets.

  • Futures_Bybit It supports the USDC option of the Bybit exchange, and set the trading pair to ETH_USDC, call function exchange.SetContractType to set the contract as an option contract. Example of option contract code: ETH-25NOV22-1375-P.

Network Settings

exchange.SetBase(Base)

The exchange.SetBase(Base) function is used to switch the API base address recorded in the exchange objects; For example, switch to OKX domain name https://aws.okx.com, compatible with exchange.IO("base","https://aws.okx.com") switching method. The backtest system does not support switching the API base address of the exchange (the backtest system is a sandbox environment, not a real interface to access the exchange).

function main() {
    // Use the default base address
    Log(exchange.GetTicker())
    // Switch to https://aws.okx.com
    exchange.SetBase("https://aws.okx.com")
    Log(exchange.GetTicker())
}
def main():
    Log(exchange.GetTicker())
    exchange.SetBase("https://aws.okx.com")
    Log(exchange.GetTicker())
void main() {
    Log(exchange.GetTicker());
    exchange.SetBase("https://aws.okx.com");
    Log(exchange.GetTicker());
}

exchange.SetProxy(…)

exchange.SetProxy(...) switches to proxy server to access the exchange. This function has no return value (obtained by variables, and what you obtain is undefined). If the proxy setting fails, a null value will be returned when the interface is called, only for the rest protocol. Each exchange object exchanges[n] can set a proxy. After setting up the proxy, the exchange interface will be accessed through the proxy.

Take the first added exchange object exchange, namely: exchanges[0], as an example:

  • Set the proxy, without username and password: exchange.SetProxy("socks5://127.0.0.1:8889")
  • Set the proxy, and enter the username and password: exchange.SetProxy("socks5://username:password@127.0.0.1:8889") (username is user’s name, password is the password.)
  • Switch to the normal mode, without proxy: exchange.SetProxy("")

Supporting to set the IP address requested by the exchange object.

  • Global specification The docker of windows system interface version can set directly, which is shown as the following image:

img

Other dockers operated by the command prompt use parameter -I to specify IP addresses:

img

  • Based on exchange to specify:

    function main(){
        exchange.SetProxy("ip://10.0.3.15")
        exchange.GetTicker()                      // The reque

More