The resource loading... loading...

Trade

exchange.Buy

The exchange.Buy() function is used to place buy orders. The Buy() function is a member function of the exchange object {@var/EXCHANGE exchange}. The Buy() function operates on the exchange account bound to the exchange object exchange. The purpose of the member functions (methods) of the exchange object is only related to exchange, and it will not be repeated after the documentation.

A successful order returns the order Id, a failed order returns a null value. The attribute Id of the order {@struct/Order Order} structure of the FMZ platform consists of the exchange product code and the exchange original order ID, separated by English commas. For example, the attribute Id format of the spot trading pair ETH_USDT order of the OKX exchange is: ETH-USDT,1547130415509278720. When calling the exchange.Buy() function to place an order, the return value order Id is consistent with the Id attribute of the order {@struct/Order Order} structure.

string, null value

exchange.Buy(price, amount) exchange.Buy(price, amount, …args)

The price parameter is used to set the order price. price true number The amount parameter is used to set the order amount. amount true number Extended parameters that can output accompanying information to this order log, arg parameters can be passed more than one. arg false string, number, bool, object, array, null and any other type supported by the system

function main() {
    var id = exchange.Buy(100, 1);
    Log("id:", id);
}
def main():
    id = exchange.Buy(100, 1)
    Log("id:", id)
void main() {
    auto id = exchange.Buy(100, 1);
    Log("id:", id);
}

The order number returned by exchange.Buy() can be used to query the order information and cancel the order.

// The following is an error call
function main() {
    exchange.SetContractType("quarter")
  
    // Set the shorting direction
    exchange.SetDirection("sell")     
    // If you place a buy order, an error will be reported, and shorting can only be sold
    var id = exchange.Buy(50, 1)

    // Set the long direction
    exchange.SetDirection("buy")      
    // If you place a sell order, it will report an error, go long, only buy
    var id2 = exchange.Sell(60, 1)    
  
    // Set direction to close long positions
    exchange.SetDirection("closebuy")    
    // If you place a buy order, it will report an error, close long, only sell
    var id3 = exchange.Buy(-1, 1)        
  
    // Set direction to close short positions
    exchange.SetDirection("closesell")   
    // If you place a sell order, it will report an error, close short, only buy
    var id4 = exchange.Sell(-1, 1)       
}
# The following is an error call
def main():
    exchange.SetContractType("quarter")
    exchange.SetDirection("sell")
    id = exchange.Buy(50, 1)
    exchange.SetDirection("buy")
    id2 = exchange.Sell(60, 1)
    exchange.SetDirection("closebuy")
    id3 = exchange.Buy(-1, 1)
    exchange.SetDirection("closesell")
    id4 = exchange.Sell(-1, 1)
// The following is an error call
void main() {
    exchange.SetContractType("quarter");
    exchange.SetDirection("sell");
    auto id = exchange.Buy(50, 1);
    exchange.SetDirection("buy");
    auto id2 = exchange.Sell(60, 1);
    exchange.SetDirection("closebuy");
    auto id3 = exchange.Buy(-1, 1);
    exchange.SetDirection("closesell");
    auto id4 = exchange.Sell(-1, 1);
}

When placing an order for a cryptocurrency futures contract, care must be taken to ensure that the trade direction is set correctly, as a mismatch between the trade direction and the trade function will result in an error:

direction is sell, invalid order type Buy
direction is buy, invalid order type Sell
direction is closebuy, invalid order type Buy
direction is closesell, invalid order type Sell
// For example, the trading pair: ETH_BTC, place a buy order at the market price
function main() {
    // Place a buy order at the market price and buy ETH coins with a value of 0.1 BTC (denominated currency)
    exchange.Buy(-1, 0.1)    
}
def main():
    exchange.Buy(-1, 0.1)
void main() {
    exchange.Buy(-1, 0.1);
}

Spot market order.

When placing an order for a futures contract, you must pay attention to whether the trade direction is set correctly, as an error will be reported if the trade direction and the trade function do not match. The order size for cryptocurrency futures contracts is the number of contracts if not specified. The parameter price is set to -1 for placing market orders, which requires the exchange’s order placement interface to support market orders. When placing market orders for cryptocurrency spot contracts, the parameter amount is the amount of money in the currency of the order. When placing market orders for cryptocurrency futures contracts, the amount parameter amount is the number of contracts. There are a few cryptocurrency exchanges that do not support market order interface during live trading. The order quantity for market buy orders on some spot exchanges is the number of trading coins. Please refer to the Special Instructions for Exchanges in the “User Guide” for details. If you are using an older version of the docker, the return value of the order Id of the exchange.Buy() function may be different from the return value of the order Id described in the current document.

{@fun/Trade/exchange.Sell exchange.Sell}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}, {@fun/Futures/exchange.SetDirection exchange.SetDirection}

exchange.Sell

The exchange.Sell() function is used to place sell orders.

A successful order returns the order Id, a failed order returns a null value. The attribute Id of the order {@struct/Order Order} structure of the FMZ platform consists of the exchange product code and the exchange original order ID, separated by English commas. For example, the attribute Id format of the spot trading pair ETH_USDT order of the OKX exchange is: ETH-USDT,1547130415509278720. When calling the exchange.Sell() function to place an order, the return value order Id is consistent with the Id attribute of the order {@struct/Order Order} structure. string, null value

exchange.Sell(price, amount) exchange.Sell(price, amount, …args)

The price parameter is used to set the order price. price true number The amount parameter is used to set the order amount. amount true number Extended parameters that can output accompanying information to this order log, arg parameters can be passed more than one. arg false string, number, bool, object, array, null and any other type supported by the system

function main(){
    var id = exchange.Sell(100, 1)
    Log("id:", id)
}
def main():
    id = exchange.Sell(100, 1)
    Log("id:", id)
void main() {
    auto id = exchange.Sell(100, 1);
    Log("id:", id);
}

The order number returned by exchange.Sell() can be used to query order information and cancel orders.

// The following is an error call
function main() {
    exchange.SetContractType("quarter")
  
    // Set the shorting direction
    exchange.SetDirection("sell")     
    // If you place a buy order, an error will be reported, and shorting can only be sold
    var id = exchange.Buy(50, 1)                  

    // Set the long direction
    exchange.SetDirection("buy")      
    // If you place a sell order, it will report an error, go long, only buy
    var id2 = exchange.Sell(60, 1)    
  
    // Set direction to close long positions
    exchange.SetDirection("closebuy")    
    // If you place a buy order, it will report an error, close long, only sell
    var id3 = exchange.Buy(-1, 1)        
  
    // Set direction to close short positions
    exchange.SetDirection("closesell")   
    // If you place a sell order, it will report an error, close short, only buy
    var id4 = exchange.Sell(-1, 1)       
}
# The following is an error call
def main():
    exchange.SetContractType("quarter")
    exchange.SetDirection("sell")
    id = exchange.Buy(50, 1)
    exchange.SetDirection("buy")
    id2 = exchange.Sell(60, 1)
    exchange.SetDirection("closebuy")
    id3 = exchange.Buy(-1, 1)
    exchange.SetDirection("closesell")
    id4 = exchange.Sell(-1, 1)
// The following is an error call
void main() {
    exchange.SetContractType("quarter");
    exchange.SetDirection("sell");
    auto id = exchange.Buy(50, 1);
    exchange.SetDirection("buy");
    auto id2 = exchange.Sell(60, 1);
    exchange.SetDirection("closebuy");
    auto id3 = exchange.Buy(-1, 1);
    exchange.SetDirection("closesell");
    auto id4 = exchange.Sell(-1, 1);
}

When placing an order for a cryptocurrency futures contract, care must be taken to ensure that the trade direction is set correctly, as a mismatch between the trade direction and the trade function will result in an error:

direction is sell, invalid order type Buy
direction is buy, invalid order type Sell
direction is closebuy, invalid order type Buy
direction is closesell, invalid order type Sell
// For example, the trading pair: ETH_BTC, place a sell order at the market price
function main() {
    // Note: place a market order to sell, sell 0.2 ETH
    exchange.Sell(-1, 0.2)   
}
def main():
    exchange.Sell(-1, 0.2)
void main() {
    exchange.Sell(-1, 0.2);
}

Spot market order.

When placing an order for a futures contract, you must pay attention to whether the trade direction is set correctly, as an error will be reported if the trade direction and the trade function do not match. The order amount for cryptocurrency futures contracts is the number of contracts if not specified. The parameter price is set to -1 for placing market orders, which requires the exchange’s order placement interface to support market orders. When placing market orders for cryptocurrency spot contracts, the amount parameter amount is the amount in trading currency. When placing market orders for cryptocurrency futures contracts, the amount parameter amount is the number of contracts. There are a few cryptocurrency exchanges that do not support market order interface during live trading. If you are using an older version of the docker, the return value of the order Id of the exchange.Sell() function may be different from the return value of the order Id described in the current document.

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}, {@fun/Futures/exchange.SetDirection exchange.SetDirection}

exchange.CreateOrder

The exchange.CreateOrder() function is used to place an order.

If the order is successfully placed, the order ID is returned; if the order fails, a null value is returned. The attribute Id of the order {@struct/Order Order} structure of the FMZ platform consists of the exchange product code and the exchange original order ID, separated by English commas. For example, the attribute Id format of the order of the spot trading pair ETH_USDT of the OKX exchange is: ETH-USDT,1547130415509278720. When calling the exchange.CreateOrder(symbol, side, price, amount) function to place an order, the return value of the order Id is consistent with the Id property of the order {@struct/Order Order} structure. string, null value

exchange.CreateOrder(symbol, side, price, amount) exchange.CreateOrder(symbol, side, price, amount, …args)

The parameter symbol is used to specify the specific trading pair and contract code of the order. When calling the exchange.CreateOrder(symbol, side, price, amount) function to place an order, exchange is the spot exchange object. If the order denominated currency is USDT and the tranding currency is BTC, the parameter symbol is: "BTC_USDT", in the format of the trading pair defined by the FMZ platform. When calling the exchange.CreateOrder(symbol, side, price, amount) function to place an order, exchange is the futures exchange object. If the order is a BTC’s U-standard perpetual contract order, the parameter symbol is: "BTC_USDT.swap", and the format is a combination of the trading pair and contract code defined by the FMZ platform, separated by the character “.”. When calling the exchange.CreateOrder(symbol, side, price, amount) function to place an order, exchange is the futures exchange object. If the order is a BTC’s U-standard option contract order, the parameter symbol is: "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example), and the format is a combination of the trading pair defined by the FMZ platform and the specific option contract code defined by the exchange, separated by the character “.”. symbol true string The side parameter is used to specify the trading direction of the order. For spot exchange objects, the optional values of the side parameter are: buy, sell. buy means buying, and sell means selling. For futures exchange objects, the optional values of the side parameter are: buy, closebuy, sell, closesell. buy means opening a long position, closebuy means closing a long position, sell means opening a short position, and closesell means closing a short position.

side true string The parameter price is used to set the price of the order. A price of -1 indicates that the order is a market order. price true number The parameter amount is used to set the order quantity. Please note that when the order is a market buy order, the order quantity is the purchase amount; the order quantity of the market buy order of some spot exchanges is the number of trading coins. For details, please refer to the Special Instructions for Exchanges in the “User Guide”. amount true number Extended parameters can output additional information to this order log. Multiple arg parameters can be passed. arg false Any type supported by the system, such as string, number, bool, object, array, null value, etc.

function main() {
    var id = exchange.CreateOrder("BTC_USDT", "buy", 60000, 0.01)           // Spot exchange objects place orders for currency-to-currency transactions BTC_USDT trading pairs
    // var id = exchange.CreateOrder("BTC_USDT.swap", "buy", 60000, 0.01)   // Futures exchange objects place orders for BTC's U-standard perpetual contracts
    Log("Order Id:", id)
}
def main():
    id = exchange.CreateOrder("BTC_USDT", "buy", 60000, 0.01)          # Spot exchange objects place orders for currency-to-currency transactions BTC_USDT trading pairs
    # id = exchange.CreateOrder("BTC_USDT.swap", "buy", 60000, 0.01)   # Futures exchange objects place orders for BTC's U-standard perpetual contracts
    Log("Order Id:", id)
void main() {
    auto id = exchange.CreateOrder("BTC_USDT", "buy", 60000, 0.01);           // Spot exchange objects place orders for currency-to-currency transactions BTC_USDT trading pairs
    // auto id = exchange.CreateOrder("BTC_USDT.swap", "buy", 60000, 0.01);   // Futures exchange objects place orders for BTC's U-standard perpetual contracts
    Log("Order Id:", id);
}

Spot exchange objects and futures exchange objects call the exchange.CreateOrder() function to place an order.

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}

exchange.CancelOrder

The exchange.CancelOrder() function is used to cancel the order. The attribute Id of the order {@struct/Order Order} structure of the FMZ platform consists of the exchange product code and the exchange original order ID, separated by English commas. For example, the attribute Id format of the order of the spot trading pair ETH_USDT of the OKX exchange is: ETH-USDT,1547130415509278720. The parameter orderId passed in when calling the exchange.CancelOrder() function to cancel an order is consistent with the Id property of the order {@struct/Order Order} structure.

The exchange.CancelOrder() function returns a true value, for example true means that the cancel order request was sent successfully. If it returns a false value, such as false, means that the cancel order request failed to be sent. The return value only represents the success or failure of the request sent to determine whether the exchange cancels the order. You can call exchange.GetOrders() to determine if the order is cancelled. bool

exchange.CancelOrder(orderId) exchange.CancelOrder(orderId, …args)

The orderId parameter is used to specify the order to be cancelled. orderId true number, string Extended parameters, you can output the attached information to this withdrawal log, arg parameters can be passed more than one. arg false string, number, bool, object, array, null and any other type supported by the system

function main(){
    var id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
}
def main():
    id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
void main() {
    auto id = exchange.Sell(99999, 1);
    exchange.CancelOrder(id);
}

Cancel the order.

function main() {
    if (exchange.GetName().includes("Futures_")) {
        Log("Set the contract as: perpetual contract, set the trade direction as: open long position.")
        exchange.SetContractType("swap")
        exchange.SetDirection("buy")
    }
    
    var ticker = exchange.GetTicker()
    exchange.Buy(ticker.Last * 0.5, 0.1)
    
    var orders = exchange.GetOrders()
    for (var i = 0 ; i < orders.length ; i++) {
        exchange.CancelOrder(orders[i].Id, "Cancelled orders:", orders[i])
        Sleep(500)
    }
}
def main():
    if exchange.GetName().find("Futures_") != -1:
        Log("Set the contract as: perpetual contract, set the trade direction as: open long position.")
        exchange.SetContractType("swap")
        exchange.SetDirection("buy")
    
    ticker = exchange.GetTicker()
    exchange.Buy(ticker["Last"] * 0.5, 0.1)            

    orders = exchange.GetOrders()
    for i in range(len(orders)):
        exchange.CancelOrder(orders[i]["Id"], "Cancelled orders:", orders[i])
        Sleep(500)
void main() {
    if (exchange.GetName().find("Futures_") != std::string::npos) {
        Log("Set the contract as: perpetual contract, set the trade direction as: open long position.");
        exchange.SetContractType("swap");
        exchange.SetDirection("buy");
    }            

    auto ticker = exchange.GetTicker();
    exchange.Buy(ticker.Last * 0.5, 0.1);            

    auto orders = exchange.GetOrders();
    for (int i = 0 ; i < orders.size() ; i++) {
        exchange.CancelOrder(orders[i].Id, "Cancelled orders:", orders[i]);
        Sleep(500);
    }
}

FMZ API functions that can produce log output functions such as: Log(), exchange.Buy(), exchange.CancelOrder() can be followed by some accompanying output parameters after the necessary parameters. For example: exchange.CancelOrder(orders[i].Id, orders[i]), so that when canceling the order whose Id is orders[i].Id, the order’s information is output with it. That is, the {@struct/Order Order} structure of orders[i].

If you are using an older version of the docker, the orderId parameter of the exchange.CancelOrder() function may be different from the orderId described in the current document.

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}

exchange.GetOrder

The exchange.GetOrder() function is used to get the order information.

Query the order details according to the order number, and return the {@struct/Order Order} structure if the query succeeds, or return null if the query fails. {@struct/Order Order}, null value

exchange.GetOrder(orderId)

The orderId parameter is used to specify the order to be queried. The attribute Id of the order {@struct/Order Order} structure of the FMZ platform consists of the exchange product code and the exchange original order ID, separated by English commas. For example, the attribute Id format of the order of the spot trading pair ETH_USDT of the OKX exchange is: ETH-USDT,1547130415509278720. The parameter orderId passed in when calling the exchange.GetOrder() function to query an order is consistent with the Id property of the order {@struct/Order Order} structure.

orderId true string

function main(){
    var id = exchange.Sell(1000, 1)
    // Parameter id is the order number, you need to fill in the number of the order you want to query
    var order = exchange.GetOrder(id)      
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
        order.DealAmount, "Status:", order.Status, "Type:", order.Type)
}
def main():
    id = exchange.Sell(1000, 1)
    order = exchange.GetOrder(id)
    Log("Id:", order["Id"], "Price:", order["Price"], "Amount:", order["Amount"], "DealAmount:", 
        order["DealAmount"], "Status:", order["Status"], "Type:", order["Type"])
void main() {
    auto id = exchange.Sell(1000, 1);
    auto order = exchange.GetOrder(id);
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:", 
        order.DealAmount, "Status:", order.Status, "Type:", order.Type);
}

The exchange.GetOrder() function is not supported by some exchanges. The AvgPrice attribute in the {@struct/Order Order} structure of the return value is the average price of the transaction. Some exchanges do not support this field, and if they do not, it is set to 0. If you are using an older version of the docker, the orderId parameter of the exchange.GetOrder() function may differ from the orderId described in the current documentation. Exchanges that do not support the exchange.GetOrder() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetOrder Zaif / Coincheck / Bitstamp

{@struct/Order Order}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}, {@fun/Trade/exchange.GetHistoryOrders exchange.GetHistoryOrders}

exchange.GetOrders

The exchange.GetOrders() function is used to get outstanding orders.

The exchange.GetOrders() function returns an array of {@struct/Order Order} structures if the request for data succeeds, and it returns null values if the request for data fails. {@struct/Order Order} array, null value

exchange.GetOrders() exchange.GetOrders(symbol)

The parameter symbol is used to set the transaction symbol or transaction symbol range to be queried. For spot exchange objects, if the symbol parameter is not passed, the uncompleted order data of all spot products will be requested. For futures exchange objects, if the symbol parameter is not passed, the default is to request the uncompleted order data of all varieties in the dimension range of the current trading pair and contract code.

symbol false string

/*backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

function main() {
    var arrSymbol = ["ETH_USDT", "BTC_USDT", "LTC_USDT", "SOL_USDT"]

    for (var symbol of arrSymbol) {
        var t = exchange.GetTicker(symbol)
        exchange.CreateOrder(symbol, "buy", t.Last / 2, 0.01)
    }

    var spotOrders = exchange.GetOrders()

    var tbls = []
    for (var orders of [spotOrders]) {
        var tbl = {type: "table", title: "test GetOrders", cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
        for (var order of orders) {
            tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
        }
        tbls.push(tbl)
    }

    LogStatus("`" + JSON.stringify(tbls) +  "`")

    // Print out the information once and then return to prevent the order from being executed during the subsequent backtest and affecting data observation
    return
}
'''backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
'''

import json

def main():
    arrSymbol = ["ETH_USDT", "BTC_USDT", "LTC_USDT", "SOL_USDT"]

    for symbol in arrSymbol:
        t = exchange.GetTicker(symbol)
        exchange.CreateOrder(symbol, "buy", t["Last"] / 2, 0.01)

    spotOrders = exchange.GetOrders()

    tbls = []
    for orders in [spotOrders]:
        tbl = {"type": "table", "title": "test GetOrders", "cols": ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], "rows": []}
        for order in orders:
            tbl["rows"].append([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
        tbls.append(tbl)

    LogStatus("`" + json.dumps(tbls) +  "`")

    return
/*backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

void main() {
    auto arrSymbol = {"ETH_USDT", "BTC_USDT", "LTC_USDT", "SOL_USDT"};
    
    for (const auto& symbol : arrSymbol) {
        auto t = exchange.GetTicker(symbol);
        exchange.CreateOrder(symbol, "buy", t.Last / 2, 0.01);
    }

    auto spotOrders = exchange.GetOrders();

    json tbls = R"([])"_json;
    std::vector<std::vector<Order>> arr = {spotOrders};
    for (const auto& orders : arr) {
        json tbl = R"({
            "type": "table", 
            "title": "test GetOrders", 
            "cols": ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"],
            "rows": []
        })"_json;

        for (const auto& order : orders) {
            json arrJson = R"([])"_json;

            arrJson.push_back("Symbol");
            arrJson.push_back("Id");
            arrJson.push_back(order.Price);
            arrJson.push_back(order.Amount);
            arrJson.push_back(order.DealAmount);
            arrJson.push_back(order.AvgPrice);
            arrJson.push_back(order.Status);
            arrJson.push_back(order.Type);
            arrJson.push_back(order.Offset);
            arrJson.push_back(order.ContractType);

            tbl["rows"].push_back(arrJson);
        }

        tbls.push_back(tbl);
    }
    
    LogStatus(_D(), "\n", "`" + tbls.dump() + "`");

    return;
}

Use the spot exchange object to place buy orders for multiple different trading pairs at half the current price, and then query the outstanding order information.

/*backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

function main() {
    var arrSymbol = ["BTC_USDT.swap", "BTC_USDT.quarter", "ETH_USDT.swap", "ETH_USDT.quarter"]

    for (var symbol of arrSymbol) {
        var t = exchange.GetTicker(symbol)
        exchange.CreateOrder(symbol, "buy", t.Last / 2, 1)
        exchange.CreateOrder(symbol, "sell", t.Last * 2, 1)
    }

    var defaultOrders = exchange.GetOrders()
    var swapOrders = exchange.GetOrders("USDT.swap")
    var futuresOrders = exchange.GetOrders("USDT.futures")
    var btcUsdtSwapOrders = exchange.GetOrders("BTC_USDT.swap")

    var tbls = []
    var arr = [defaultOrders, swapOrders, futuresOrders, btcUsdtSwapOrders]
    var tblDesc = ["defaultOrders", "swapOrders", "futuresOrders", "btcUsdtSwapOrders"]
    for (var index in arr) {
        var orders = arr[index]
        var tbl = {type: "table", title: tblDesc[index], cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
        for (var order of orders) {
            tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
        }
        tbls.push(tbl)
    }

    LogStatus("`" + JSON.stringify(tbls) +  "`")

    // Print out the information once and then return to prevent the order from being executed during the subsequent backtest and affecting data observation
    return
}
'''backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
'''

import json

def main():
    arrSymbol = ["BTC_USDT.swap", "BTC_USDT.quarter", "ETH_USDT.swap", "ETH_USDT.quarter"]

    for symbol in arrSymbol:
        t = exchange.GetTicker(symbol)
        exchange.CreateOrder(symbol, "buy", t["Last"] / 2, 1)
        exchange.CreateOrder(symbol, "sell", t["Last"] * 2, 1)

    defaultOrders = exchange.GetOrders()
    swapOrders = exchange.GetOrders("USDT.swap")
    futuresOrders = exchange.GetOrders("USDT.futures")
    btcUsdtSwapOrders = exchange.GetOrders("BTC_USDT.swap")

    tbls = []
    arr = [defaultOrders, swapOrders, futuresOrders, btcUsdtSwapOrders]
    tblDesc = ["defaultOrders", "swapOrders", "futuresOrders", "btcUsdtSwapOrders"]
    for index in range(len(arr)):
        orders = arr[index]
        tbl = {"type": "table", "title": tblDesc[index], "cols": ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], "rows": []}
        for order in orders:
            tbl["rows"].append([order["Symbol"], order["Id"], order["Price"], order["Amount"], order["DealAmount"], order["AvgPrice"], order["Status"], order["Type"], order["Offset"], order["ContractType"]])
        tbls.append(tbl)

    LogStatus("`" + json.dumps(tbls) +  "`")

    return
/*backtest
start: 2024-05-21 00:00:00
end: 2024-09-05 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

void main() {
    auto arrSymbol = {"BTC_USDT.swap", "BTC_USDT.quarter", "ETH_USDT.swap", "ETH_USDT.quarter"};
    
    for (const auto& symbol : arrSymbol) {
        auto t = exchange.GetTicker(symbol);
        exchange.CreateOrder(symbol, "buy", t.Last / 2, 1);
        exchange.CreateOrder(symbol, "sell", t.Last * 2, 1);
    }
    
    auto defaultOrders = exchange.GetOrders();
    auto swapOrders = exchange.GetOrders("USDT.swap");
    auto futuresOrders = exchange.GetOrders("USDT.futures");
    auto btcUsdtSwapOrders = exchange.GetOrders("BTC_USDT.swap");
    
    json tbls = R"([])"_json;
    std::vector<std::vector<Order>> arr = {defaultOrders, swapOrders, futuresOrders, btcUsdtSwapOrders};
    std::string tblDesc[] = {"defaultOrders", "swapOrders", "futuresOrders", "btcUsdtSwapOrders"};
    for (int index = 0; index < arr.size(); index++) {
        auto orders = arr[index];
        json tbl = R"({
            "type": "table", 
            "cols": ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"],
            "rows": []
        })"_json;
        tbl["title"] = tblDesc[index];
    
        for (const auto& order : orders) {
            json arrJson = R"([])"_json;

            arrJson.push_back(order.Symbol);
            arrJson.push_back(to_string(order.Id));    // The Id attribute type in the Order structure is TId, which is encoded using a C++ function to_string built into the FMZ platform.
            arrJson.push_back(order.Price);
            arrJson.push_back(order.Amount);
            arrJson.push_back(order.DealAmount);
            arrJson.push_back(order.AvgPrice);
            arrJson.push_back(order.Status);
            arrJson.push_back(order.Type);
            arrJson.push_back(order.Offset);
            arrJson.push_back(order.ContractType);
    
            tbl["rows"].push_back(arrJson);
        }
    
        tbls.push_back(tbl);
    }
    
    LogStatus(_D(), "\n", "`" + tbls.dump() + "`");
    
    return;
}

Use futures exchange objects to place orders for multiple different trading pairs and contract codes. Place orders at prices far away from the counterparty price, keep orders in an unfulfilled state, and query orders in multiple ways.

function main() {
    var orders = exchange.GetOrders("BTC_USDT")           // Examples of spot products
    // var orders = exchange.GetOrders("BTC_USDT.swap")   // Examples of futures products
    Log("orders:", orders)
}
def main():
    orders = exchange.GetOrders("BTC_USDT")          # Examples of spot products
    # orders = exchange.GetOrders("BTC_USDT.swap")   # Examples of futures products
    Log("orders:", orders)
void main() {
    auto orders = exchange.GetOrders("BTC_USDT");           // Examples of spot products
    // auto orders = exchange.GetOrders("BTC_USDT.swap");   // Examples of futures products
    Log("orders:", orders);
}

When calling the exchange.GetOrders() function, pass in the Symbol parameter to request order data for a specific trading pair and contract code.

In the GetOrders function, the usage scenarios of the symbol parameter are summarized as follows:

Exchange Object Classification symbol Parameters Query Scope Remark
Spot Do not pass symbol parameter Query all spot trading pairs For all calling scenarios, if the exchange interface does not support it, an error will be reported and a null value will be returned. No further explanation will be given.
Spot Specify the trading type, the symbol parameter is: “BTC_USDT” Query the specified BTC_USDT trading pair For spot exchange objects, the symbol parameter format is: “BTC_USDT”
Futures Do not pass symbol parameter Query all trading products within the current trading pair and contract code dimension range If the current trading pair is BTC_USDT and the contract code is swap, all USDT-margined perpetual contracts will be queried. This is equivalent to calling GetOrders("USDT.swap")
Futures Specify the trading type, the symbol parameter is: “BTC_USDT.swap” Query the USDT-based perpetual contract for a specified BTC For futures exchange objects, the parameter symbol format is: a combination of trading pair and contract code defined by the FMZ platform, separated by the characters "..
Futures Specify the range of trading products, the symbol parameter is: “USDT.swap” Query all USDT-based perpetual contracts -
Futures exchanges that support options Do not pass symbol parameter Query all option contracts within the current trading pair dimension range If the current trading pair is BTC_USDT, the contract is set to an option contract, for example, Binance option contract: BTC-240108-40000-C
Futures exchanges that support options Specify specific trading products Query the specified option contract For example, for Binance Futures Exchange, the symbol parameter is: BTC_USDT.BTC-240108-40000-C
Futures exchanges that support options Specify the range of trading products, the symbol parameter is: “USDT.option” Query all USDT-based options contracts -

In the GetOrders function, the futures exchange object query dimension range is summarized as follows:

symbol Parameters Request Range Definition Remark
USDT.swap USDT-based perpetual contract range. For

dimensions that are not supported by the exchange API interface, an error will be reported and a null value will be returned when calling. | | USDT.futures | USDT-based delivery contract range. | - | | USD.swap | Range of currency-based perpetual contracts. | - | | USD.futures | Range of currency-based delivery contracts. | - | | USDT.option | USDT-based options contract range. | - | | USD.option | Currency-based options contract range. | - | | USDT.futures_combo | Range of CFD combinations. | Futures_Deribit Exchange | | USD.futures_ff | Range of mixed margin delivery contracts. | Futures_Kraken Exchange | | USD.swap_pf | Range of mixed margin perpetual contracts. | Futures_Kraken Exchange |

When the account represented by the exchange object exchange has no pending orders within the query range or specified trading instruments (active orders in an unfulfilled state), calling this function returns an empty array, that is: []. The following exchanges require the instrument to pass in the instrument parameter when querying the currently uncompleted orders. When calling the GetOrders function with these exchanges, if the instrument parameter is not passed in, only the uncompleted orders of the current instrument are requested, not the uncompleted orders of all instruments (because the exchange interface does not support this). Zaif, MEXC, LBank, Korbit, Coinw, BitMart, Bithumb, BitFlyer, BigONE.

Exchanges that do not support the exchange.GetOrders() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetOrders Futures_Bibox

{@struct/Order Order}, {@fun/Trade/exchange.GetOrder exchange.GetOrder}, {@fun/Trade/exchange.GetHistoryOrders exchange.GetHistoryOrders}

exchange.GetHistoryOrders

The exchange.GetHistoryOrders() function is used to obtain the current trading pair, the historical orders for contracts; it supports the specification of specific trading varieties.

The exchange.GetHistoryOrders() function returns an array of {@struct/Order Order} structures if the request for data succeeds, and null if the request fails. {@struct/Order Order} arrays, null values

exchange.GetHistoryOrders() exchange.GetHistoryOrders(symbol) exchange.GetHistoryOrders(symbol, since) exchange.GetHistoryOrders(symbol, since, limit) exchange.GetHistoryOrders(since) exchange.GetHistoryOrders(since, limit)

The symbol parameter is used to specify the trade symbol. In the case of the BTC_USDT trading pair, for example, when the exchange is a spot exchange object, the parameter format for symbol is BTC_USDT; if it’s a futures exchange object, taking perpetual contract as an example, the parameter format for symbol is: BTC_USDT.swap. If you are querying the order data of option contracts, set the parameter symbol to "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example). The format is a combination of the trading pair defined by the FMZ platform and the specific option contract code defined by the exchange, separated by the character “.”. If this parameter is not passed, the order data of the currently set trading pair and contract code will be requested by default.

symbol false string The since parameter is used to specify the starting timestamp of the query in milliseconds. since false number The limit parameter is used to specify the number of orders to query. limit false number

function main() {
    var historyOrders = exchange.GetHistoryOrders()
    Log(historyOrders)
}
def main():
    historyOrders = exchange.GetHistoryOrders()
    Log(historyOrders)
void main() {
    auto historyOrders = exchange.GetHistoryOrders();
    Log(historyOrders);
}
  • When symbol, since, limit parameters are not specified, the default query is the current trading pair, the historical orders of contract. Queries the historical orders within a certain range nearest to the current time, the query range depends on the single query range of the exchange interface.
  • When the symbol parameter is specified, query the history of orders for the set trade type.
  • When the since parameter is specified, query in the direction of the current time using the since timestamp as the start time.
  • If the limit parameter is specified, the query is returned after a sufficient number of entries.
  • This function is only supported for exchanges that provide a historical order query interface.

Exchanges that do not support the exchange.GetHistoryOrders() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetHistoryOrders Zaif / Upbit / Coincheck / Bitstamp / Bithumb / BitFlyer / BigONE Futures_dYdX / Futures_Bibox / Futures_ApolloX

{@struct/Order Order}, {@fun/Trade/exchange.GetOrder exchange.GetOrder}, {@fun/Trade/exchange.GetOrders exchange.GetOrders}

exchange.SetPrecision

exchange.SetPrecision() function is used to set the precision of the exchange exchange object price and order amount, after setting, the system will ignore the excess data automatically.

exchange.SetPrecision(pricePrecision, amountPrecision)

The pricePrecision parameter is used to control the precision of the price data. pricePrecision true number The amountPrecision parameter is used to control the precision of the amount of data to be ordered. amountPrecision true number

function main(){
    // Set the decimal precision of price to 2 bits, and the decimal precision of variety order amount to 3 bits
    exchange.SetPrecision(2, 3)
}
def main():
    exchange.SetPrecision(2, 3)
void main() {
    exchange.SetPrecision(2, 3);
}

The backtesting system does not support this function, and the numerical accuracy of the backtesting system is handled automatically.

{@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}

exchange.SetRate

Set the current exchange rate of the exchange object.

exchange.SetRate(rate)

The rate parameter is used to specify the conversion exchange rate. rate true number

function main(){
    Log(exchange.GetTicker())
    // Set exchange rate conversion
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    // Set to 1, no conversion
    exchange.SetRate(1)
}
def main():
    Log(exchange.GetTicker())
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    exchange.SetRate(1)
void main() {
    Log(exchange.GetTicker());
    exchange.SetRate(7);
    Log(exchange.GetTicker());
    exchange.SetRate(1);
}

If an exchange rate value has been set using the exchange.SetRate() function, such as 7. Then all price information such as tickers, depths, order prices, etc. for the exchange represented by the current exchange exchange object will be converted by multiplying it by the set exchange rate of 7. For example, exchange is an exchange with the US dollar as the denomination currency. After executing exchange.SetRate(7), all prices on the live market will be converted to prices close to CNY denomination by multiplying by 7.

{@fun/Market/exchange.GetRate exchange.GetRate}

exchange.IO

The exchange.IO() function is used for other interface calls related to the exchange object.

The exchange.IO() function calls other interfaces related to the exchange object, returning the requested response data on a successful call and it returns null on a failed call. string, number, bool, object, array, null, and any other type supported by the system

exchange.IO(k, …args)

The k parameter is used to set the call type, with optional values "api", "currency", "base", "trade_margin", "trade_normal", "public_base", "mbase", selfTradePreventionMode, simulate, cross, dual, unified and so on. k true string Extended parameters, passed according to the specific call scenario, arg parameters can be passed more than one. Due to the polymorphic mechanism of the exchange.IO() function, different parameter settings correspond to different functions. The number and type of parameters to the exchange.IO() function are indeterminate. arg true string, number, bool, object, array, null and any other types supported by the system

function main() {
    var arrOrders = [
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"},
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ]
    
    // Call exchange.IO to access the exchange's bulk order interface directly
    var ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", JSON.stringify(arrOrders))
    Log(ret)
}
import json
def main():
    arrOrders = [
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"}, 
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ]
    ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", json.dumps(arrOrders))
    Log(ret)
void main() {
    json arrOrders = R"([
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"},
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ])"_json;
    auto ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", arrOrders.dump());
    Log(ret);
}

Using the exchange.IO("api", httpMethod, resource, params, raw) call form of the exchange.IO() function, it is necessary to understand the API interface of the exchange and check the relevant documentation first. This will allow you to extend the functionality that is not added to the FMZ platform. Submitting a POST request does not require you to worry about encrypting, signing, or verifying the parameters, which are already handled by FMZ at the bottom, as long as you fill in the corresponding parameters. You can refer to the batch order example of OKX Exchange futures contracts, and use the parameter raw to pass the order parameters:

var amount = 1
var price = 10
var basecurrency = "ltc"
function main () {
    // Note that both amount.toString() and price.toString() have a ' character on the left and right side
    var message = "symbol=" + basecurrency + "&amount='" + amount.toString() + "'&price='" + price.toString() + "'&side=buy" + "&type=limit"
    var id = exchange.IO("api", "POST", "/v1/order/new", message)
}
amount = 1
price = 10
basecurrency = "ltc"
def main():
    message = "symbol=" + basecurrency + "&amount='" + str(amount) + "'&price='" + str(price) + "'&side=buy" + "&type=limit"
    id = exchange.IO("api", "POST", "/v1/order/new", message)
void main() {
    auto amount = 1.0;
    auto price = 10.0;
    auto basecurrency = "ltc";
    string message = format("symbol=%s&amount=\"%.1f\"&price=\"%.1f\"&side=buy&type=limit", basecurrency, amount, price);
    auto id = exchange.IO("api", "POST", "/v1/order/new", message);
}

If the key value in the params parameter (i.e., Http request parameter) is a string, it needs to be written in single quotes (i.e., the symbol ') around the parameter value to wrap the parameter value.

function main() {
    var ret = exchange.IO("api", "GET", "https://www.okx.com/api/v5/account/max-withdrawal", "ccy=BTC")
    Log(ret)
}
def main():
    ret = exchange.IO("api", "GET", "https://www.okx.com/api/v5/account/max-withdrawal", "ccy=BTC")
    Log(ret)
void main() {
    auto ret = exchange.IO("api", "GET", "https://www.okx.com/api/v5/account/max-withdrawal", "ccy=BTC");
    Log(ret);
}

It supports passing in complete url parameters, which can omit the operation of switching the base address (calling the exchange.SetBase() function).

function main(){
    var ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT")
    Log(ret)
}
def main():
    ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT")
    Log(ret)
void main() {
    auto ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT");
    Log(ret);
}

Example of a call without the parameter raw:

function main() {
    // For example, if you set the current trading pair of the exchange object to BTC_USDT at the beginning of the live trading, print the current trading pair tickers
    Log(exchange.GetTicker())
    // Switch the trading pair to LTC_BTC      
    exchange.IO("currency", "LTC_BTC")
    Log(exchange.GetTicker())
}
def main():
    Log(exchange.GetTicker())
    exchange.IO("currency", "LTC_BTC")
    Log(exchange.GetTicker())
void main() {
    Log(exchange.GetTicker());
    exchange.IO("currency", "LTC_BTC");
    Log(exchange.GetTicker());
}

Switch the trading pair of current exchange, so that it will switch the trading pair configured by code at live trading creation or at backtest.

function main () {
    // exchanges[0] is the first exchange object added when the live trading is created 
    exchanges[0].IO("base", "https://api.huobi.pro")
}
def main():
    exchanges[0].IO("base", "https://api.huobi.pro")
void main() {
    exchanges[0].IO("base", "https://api.huobi.pro");
}```
For example, the default base address when the exchange object is wrapped is ```https://api.huobipro.com```, and when you need to switch to ```https://api.huobi.pro```, use the following code to switch:
```javascript
function main() {
    exchange.SetBase("https://api.bitfinex.com")
    exchange.IO("mbase", "https://api-pub.bitfinex.com")
}
def main():
    exchange.SetBase("https://api.bitfinex.com")
    exchange.IO("mbase", "https://api-pub.bitfinex.com")
void main() {
    exchange.SetBase("https://api.bitfinex.com");
    exchange.IO("mbase", "https://api-pub.bitfinex.com");
}

For exchanges with different base addresses for the ticker interface and trading interface, for example, Bitfinex Futures have two addresses, one for the ticker interface and the other for the trading interface. Bitfinex futures switch private interface base address using exchange.SetBase("xxx"). Bitfinex futures switch public interface base address using exchange.IO("mbase", "xxx").

I. For cryptocurrency-centric exchanges other API interface calls that are not uniformly encapsulated, with parameter k set to "api":

exchange.IO("api", httpMethod, resource, params, raw)
  • httpMethod : The parameter is a string type, fill in the request type POST, GET, etc.
  • resource : The parameter is of string type and fills in the request path; It supports the use of complete request paths, see the reference example for details.
  • params : The parameter is a string type, filled with request parameters, encoded with URL.
  • raw : The parameter is the raw string parameter and can be left out.

The exchange.IO("api", httpMethod, resource, params, raw) function call will access the exchange interface and return null if the call fails and an error occurs. Only the real trading supports calling the exchange.IO("api", httpMethod, resource, params, raw) function.

II. For switching trading pairs, the parameter k is set to "currency":

exchange.IO("currency", currency)
  • currency : The parameter is a string type with a uniform upper case format, using an underscore to separate baseCurrency from quoteCurrency, such as BTC_USDT.

    1. Backtesting system now supports switching trading pairs (only for digital currency spot exchange objects), when backtesting, you need to pay attention that you can only switch to trading pairs with the same denominated currency, for example, the current trading pair is ETH_BTC can only switch to LTC_BTC, not to LTC_USDT.
    2. For cryptocurrency futures contracts the exchange object switches trading pairs and the contract code needs to be set again to determine which contract is to be traded.
    3. Using the {@fun/Account/exchange.SetCurrency exchange.SetCurrency} function to switch trading pairs is exactly the same as using exchange.IO("currency", currency) to switch trading pairs.

III. Used to switch the cryptocurrency spot exchange object leveraged account mode:

  • The parameter k is set to "trade_margin" to switch to the spot leverage account mode. Placing orders and obtaining account assets will access the exchange’s spot leveraged interface. If the exchange distinguishes between full margin and isolated margin in spot leverage, use: exchange.IO("trade_super_margin") to switch to full margin for leveraged account, and exchange.IO("trade_margin") to switch to isolated margin for leveraged account.
  • Parameter k is set to "trade_normal" to switch back to normal spot account mode.

Spot exchanges that support switching between leveraged account models:

Exchanges Special remarks
OKX Trading pairs in leveraged account mode are different from normal ones, some trading pairs may not have them. Use exchange.IO("trade_super_margin") to switch to full position for leveraged accounts and use exchange.IO("trade_margin") to switch to position by position. Use trade_normal to switch to normal spot mode. Use exchange.IO("tdMode", "cross") to directly specify the leverage mode.
Huobi Leveraged account mode trading pairs are different from normal ones, some trading pairs may not have them. There are full positions and position-by-position in Huobi leveraged accounts. Use trade_margin to switch to leverage account position by position, use trade_super_margin to switch to leverage account full position. Use trade_normal to switch to normal currency-currency mode.
Binance Leveraged account mode is divided into position by position and full position, use trade_margin to switch to position by position, use trade_super_margin to switch to full position, use trade_normal to switch to normal currency-currency mode.
GateIO Leveraged account mode is divided into position by position and full position, use trade_margin to switch to position by position, use trade_super_margin to switch to full position, use trade_normal to switch to normal currency-currency mode.
AscendEx Use exchange.IO("trade_margin") to switch to leverage account mode and exchange.IO("trade_normal") to switch back to normal account mode.
WOO Use exchange.IO("trade_margin") to switch to leverage account mode and exchange.IO("trade_normal") to switch back to normal account mode.
CoinEx Use exchange.IO("trade_margin") to switch to leveraged account mode and exchange.IO("trade_normal") to switch back to normal account mode.

IV. Other switching functions: Check out the exchange.IO() function for Other switching functions in the User Guide.

{@fun/NetSettings/exchange.SetBase exchange.SetBase}, {@fun/Account/exchange.SetCurrency exchange.SetCurrency}, {@var EXCHANGE_OP_IO_CONTROL}

exchange.Log

The exchange.Log() function is used to output the log of order placement and withdrawal in the log column area. When called, no orders are placed, only the transaction log is output and recorded.

exchange.Log(orderType, price, amount) exchange.Log(orderType, price, amount, …args)

The orderType parameter is used to set the output log type, the optional values are {@var/LOG_TYPE/LOG_TYPE_BUY LOG_TYPE_BUY}, {@var/LOG_TYPE/LOG_TYPE_SELL LOG_TYPE_SELL}, {@var/LOG_TYPE/LOG_TYPE_CANCEL LOG_TYPE_CANCEL}. orderType true number The price parameter is used to set the price displayed in the output log. price true number The amount parameter is used to set the amount of orders placed displayed in the output log. amount true number Extended parameters that can output accompanying information to this log, arg parameters can be passed more than one. arg false string, number, bool, object, array, null and any other type supported by the system

var id = 123
function main() {
    // Order type buy, price 999, amount 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);
}

Using exchange.Log(orderType, price, amount) can be used for live trading order following tests, simulated order placement, and it can assist in logging order placement. One of the most common scenarios is to use the {@fun/Trade/exchange.IO exchange.IO} function to access the exchange’s interface for creating conditional orders, but using the exchange.IO() function does not output the transaction log information in the live trading log record. This is where the exchange.Log() function can be used to supplement the output log in order to record order placement information, and the same is true for order withdrawal operations.

When the orderType parameter is LOG_TYPE_CANCEL, the price parameter is the order Id of the withdrawn order, which is used to print the withdrawal log when the order is withdrawn directly using the exchange.IO() function. The exchange.Log() function is a member function of the {@var/EXCHANGE exchange} exchange object, as distinguished from the global function {@fun/Log Log}.

{@fun/Log Log}, {@var/EXCHANGE exchange}, {@var/LOG_TYPE/LOG_TYPE_BUY LOG_TYPE_BUY}, {@var/LOG_TYPE/LOG_TYPE_SELL LOG_TYPE_SELL}, {@var/LOG_TYPE/LOG_TYPE_CANCEL LOG_TYPE_CANCEL}

exchange.Encode

The exchange.Encode() function is used for signature encryption calculations.

The exchange.Encode() function returns the calculated hash value encoding. string

exchange.Encode(algo, inputFormat, outputFormat, data) exchange.Encode(algo, inputFormat, outputFormat, data, keyFormat, key)

The parameter algo is the algorithm used for encoding calculation. Supported settings are: “raw” (no algorithm used), “sign”, “signTx”, “md4”, “md5”, “sha256”, “sha512”, “sha1”, “keccak256”, “sha3.224”, “sha3.256”, “sha3.384”, “sha3.512”, “sha3.keccak256”, “sha3.keccak512”, “sha512.384”, “sha512.256”, “sha512.224”, “ripemd160”, “blake2b.256”, “blake2b.512”, “blake2s.128”, “blake2s.256”. The parameter algo also supports: “text.encoder.utf8”, “text.decoder.utf8”, “text.encoder.gbk”, “text.decoder.gbk”, for encoding and decoding strings. The parameter algo also supports: “ed25519” algorithm. It supports the use of different hash algorithms, for example, the parameter algo can be written as “ed25519.md5”, “ed25519.sha512”, etc. Supports ed25519.seed calculation. algo true string Used to specify the data format of the data parameter. The inputFormat parameter can be set to one of: “raw”, “hex”, “base64”, and “string”. “raw” means the data is raw data, “hex” means the data is hex encoded, “base64” means the data is base64 encoded, and “string” means the data is a string. inputFormat true string Used to specify the output data format. The outputFormat parameter supports the following settings: “raw”, “hex”, “base64”, “string”. “raw” means the data is raw data, “hex” means the data is hex encoded, “base64” means the data is base64 encoded, and “string” means the data is a string. outputFormat true string The parameter data is the data to be processed. data true string Used to specify the data format of the key parameter. The key parameter can be set to one of: “raw”, “hex”, “base64”, and “string”. “raw” means the data is raw data, “hex” means the data is hex encoded, “base64” means the data is base64 encoded, and “string” means the data is a string. keyFormat false string The key parameter is used to specify the key used in the signature calculation, and it can be used as a plaintext string. You can also use "{{accesskey}}", "{{secretkey}}" to refer to the accessKey and secretKey configured in the {@var/EXCHANGE exchange} exchange object. key false string

function main() {
    var APIKEY = "your Access Key(Bitmex API ID)"
    var expires = parseInt(Date.now() / 1000) + 10
    var signature = exchange.Encode("sha256", "string", "hex", "GET/realtime" + expires, "hex", "{{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.Encode("sha256", "string", "hex", "GET/realtime" + expires, "hex", "{{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.Encode("sha256", "string", "hex", format("GET/realtime%d", expires), "hex", "{{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"];
        }
    }
}

Example of BitMEX position change push (wss protocol):

Only the real trading supports calling the exchange.Encode() function. The "{{accesskey}}", "{{secretkey}}" references are only valid when the exchange.Encode() function is used.

{@var/EXCHANGE exchange}, {@fun/Global/Encode Encode}

exchange.Go

Multi-threaded asynchronous support functions can turn the operations of all supported functions into asynchronous concurrent execution.

The exchange.Go() function returns a concurrent object immediately, and you can use the wait() method of that concurrent object to get the result of the concurrent request. object

exchange.Go(method) exchange.Go(method, …args)

The method parameter is used to specify the name of the concurrent function. Note that the parameter is a function name string, not a function reference. method true string Parameters to concurrently executing functions, there may be more than one parameter arg. The type and number of parameter arg depends on the parameters of the concurrent execution function. arg false string, number, bool, object, array, function, null, and all other types supported by the system

function main(){
    // The following four operations are concurrently executed asynchronously by multiple threads and do not take time and return immediately
    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 ticker results asynchronously 
    var ticker = a.wait()            
    // Returns the depth, or null if it fails 
    var depth = b.wait()             
    // return order number, limited to 1 second timeout, if timeout, returns undefined, the object can continue to call wait if the last wait 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);
}

Exchange.Go() function usage example, to determine undefined to use typeof(xx) === "undefined", because null == undefined is valid in JavaScript.

function main() {
    var d = exchange.Go("GetRecords", PERIOD_H1)
    // Waiting for K-line results
    var records = d.wait()
    // Here waits an asynchronous operation that has been waited and finished, it will return null, and log the error message
    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);
}

Calling the wait() method on a concurrent object that has been released will report an error:

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: "ticker", 
            cols: ["index", "name", "latest-deal-price"], 
            rows: []
        }
        
        for(var i = 0; i < arrTicker.length; i++) {
            tbl.rows.push([i, arrName[i], arrTicker[i].Last])
        }            

        LogStatus(_D(), "Total time taken to obtain tickers from multiple exchanges concurrently:", 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": "ticker", 
            "cols": ["index", "name", "latest-deal-price"], 
            "rows": [] 
        }            

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

        LogStatus(_D(), "Total time taken to obtain tickers from multiple exchanges concurrently:", 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 several exchange objects, several exchanges[n].Go functions have to be executed here, this example is to add four exchange objects, the details can be modified
        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": "ticker", 
            "cols": ["index", "name", "latest-deal-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(), "Total time taken to obtain tickers from multiple exchanges concurrently:", format("%d", endTS - beginTS), "millisecond", "\n", "`" + tbl.dump() + "`");
        Sleep(500);
    }
}

Concurrent access to multiple exchange tickers:

function main() {
    /*  
        Testing with OKX futures order interface
        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("Concurrent order placement time consumption:", 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("Concurrent order placement time consumption:", 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("Concurrent order placement time consumption:", endTS - beginTS, "millisecond");
}

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

This function only creates multi-threaded execution tasks when running in real trading, backtesting does not support multi-threaded concurrent task execution (backtesting is available, but still executed sequentially). After the exchange.Go() function returns an object, its wait() function is called through that object to get the data returned by the thread. The wait() function must be called to get the data before the thread will be released automatically. If the timeout parameter of the wait() function is specified, the thread will not be released automatically even if a timeout occurs. The result of the thread must be obtained before it will be released automatically (regardless of the success or failure of the interface call for concurrent access). In simple terms, the requested thread must be obtained by the wait() function regardless of whether the execution succeeds or fails, and the resource of the thread requested by the exchange.Go() function must be released automatically by the docker. The wait() method supports a timeout parameter: Without a timeout parameter, that is, wait(), or with a timeout parameter of 0, that is, wait(0). The wait() function blocks and waits until the concurrent thread has finished running, returning the result of the concurrent thread’s execution. Set the timeout parameter -1, i.e. wait(-1). The wait() function returns immediately, with different return values for different programming languages, see this subsection for an example call. Set the specific timeout parameter, wait(300), and the wait() function will wait a maximum of 300 milliseconds before returning.

If the return result of the final wait() function is not obtained, the thread resources will not be released automatically, which will lead to the accumulation of threads requested, and more than 2000 will report an error: "too many routine wait, max is 2000". Supported functions: GetTicker, GetDepth, GetTrades, GetRecords, GetAccount, GetOrders, GetOrder, CancelOrder, Buy, Sell, GetPositions, IO. All these functions are executed based on the current {@var/EXCHANGE exchange} exchange object when called concurrently. The difference between Python language and JavaScript language is that the wait() function of concurrent objects in Python language returns two parameters. The first parameter is the result returned by an asynchronous API call, and the second parameter indicates whether the asynchronous call is completed.


def main():
    d = exchange.Go("GetRecords", PERIOD_D1)
    # ok will return True definitely, unless the strategy is stopped
    ret, ok = d.wait()          
    # If the wait times out, or if it waits for an instance that has already ended, ok returns False
    ret, ok = d.wait(100)  

{@fun/Global/Mail_Go Mail_Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}, {@fun/Global/EventLoop EventLoop}

Market Account