The resource loading... loading...

Built-in functions

Global

Version

Returns the current version number of the system.

Current system version number, such as 3.6. string

Version()

function main() {
    Log("version:", Version())
}
def main():
    Log("version:", Version())
void main() {
    Log("version:", Version());
}

The system version number is the version number of the docker’s program.

Sleep

The sleep function, causing the program to pause for a period of time.

Sleep(millisecond)

The millisecond parameter is used to set the duration of sleep and the number of milliseconds. millisecond true number

function main() {
    Sleep(1000 * 10)   // Wait for 10 seconds
    Log("Waited for 10 seconds")
}
def main():
    Sleep(1000 * 10)
    Log("Waited for 10 seconds")
void main() {
    Sleep(1000 * 10);
    Log("Waited for 10 seconds");
}

For example, when executing the Sleep(1000) function, the program will sleep for 1 second. It supports operations with sleep time less than 1 millisecond, for example setting Sleep(0.1). It supports a minimum parameter of 0.000001, i.e. nanosecond hibernation, where 1 nanosecond is equal to 1e-6 milliseconds. When writing strategies in the Python language, the Sleep(millisecond) function should be used for polling interval, time-to-wait operations. It is not recommended to use the time.sleep(second) function of Python's time library. This is because using the time.sleep(second) function in a strategy makes the strategy program wait for a period of time actually when backtesting (not skipping on the time series of the backtesting system), so it causes the strategy to backtest very slowly.

IsVirtual

Determine whether the running environment of the strategy is a backtesting system.

The strategy returns a true value, e.g.: true when running in the backtesting system environment. The strategy returns a false value, e.g.: false when running in a live trading environment. bool

IsVirtual()

function main() {
    if (IsVirtual()) {
        Log("The current backtest system environment.")
    } else {
        Log("The current live trading environment.")
    }
}
def main():
    if IsVirtual():
        Log("The current backtest system environment.")
    else:
        Log("The current live trading environment.")
void main() {
    if (IsVirtual()) {
        Log("The current backtest system environment.");
    } else {
        Log("The current live trading environment.");
    }
}

Determine whether the current running environment is a backtesting system, which is used to be compatible with the difference between backtesting and live trading.

Mail

Send an email.

A successful email delivery returns a true value, e.g., true, and a failed delivery returns a false value, e.g., false. bool

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)

Used to specify the SMTP service address of the email sender. smtpServer true string Used to specify the email address of the email sender. smtpUsername true string The SMTP password for the email sender’s mailbox. smtpPassword true string Used to specify the email address of the email recipient. mailTo true string Email title. title true string Email body. body true string

function main(){
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
}
def main():
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}

The smtpPassword parameter sets the password for the SMTP service, not the mailbox password. When setting the smtpServer parameter, if you need to change the port, you can add the port number directly in the parameter smtpServer. For example: QQ mail smtp.qq.com:587, which is available for testing. If an error is reported: unencryped connection, you need to modify the smtpServer of the Mail function. The parameter format is: ssl://xxx.com:xxx, for example, the ssl method of SMTP for QQ mail: ssl://smtp.qq.com:465 or smtp://xxx.com:xxx. It does not work in the backtesting system.

{@fun/Global/Mail_Go Mail_Go}

Mail_Go

Asynchronous version of the Mail function.

The Mail_Go function returns a concurrent object immediately, and you can use the wait method of that concurrent object to get the result of the mail delivery. A successful mail delivery returns a true value, e.g., true, and a failed delivery returns a false value, e.g., false. object

Mail_Go(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)

It’s used to specify the SMTP service address of the email sender. smtpServer true string It’s used to specify the email address of the email sender. smtpUsername true string The SMTP password for the email sender’s mailbox. smtpPassword true string It’s used to specify the email address of the email recipient. mailTo true string Email title. title true string Email body. body true string

function main() {
    var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
    var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
    
    var ret1 = r1.wait()
    var ret2 = r2.wait()
    
    Log("ret1:", ret1)
    Log("ret2:", ret2)
}
# Not supported.
// Not supported.

It does not work in the backtesting system.

{@fun/Global/Mail Mail}

SetErrorFilter

Filter error logs.

SetErrorFilter(filters)

Regular expression string. filters true string

function main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
}
def main():
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
void main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");
}

Filtering common errors.

function main() {
    // A random query for a non-existent order with an id of 123, allowing the interface to report an error deliberately
    var order = exchange.GetOrder("123")
    Log(order)
    // Filter http502 errors, GetOrder interface errors, after setting the error filter, the second call to GetOrder will no longer report errors
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
}
def main():
    order = exchange.GetOrder("123")
    Log(order)
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
void main() {
    TId orderId;
    Order order = exchange.GetOrder(orderId);
    Log(order);
    SetErrorFilter("502:|GetOrder");
    order = exchange.GetOrder(orderId);
    Log(order);
}

Filter an interface error message.

Error logs matched by this regular expression will not be uploaded to the log system. You can call it multiple times (no limit on the number of times) to set multiple filter conditions. Regular expressions set multiple times will be accumulated and take effect at the same time. You can set an empty string to reset the regular expression used to filter error logs: SetErrorFilter(""). The filtered logs are no longer written to the database file corresponding to the live trading Id in the docker directory to prevent frequent error reporting from bloating the database file.

GetPid

Get the live trading process Id.

Return the live trading process Id. string

GetPid()

function main(){
    var id = GetPid()
    Log(id)
}
def main():
    id = GetPid()
    Log(id)
void main() {
    auto id = GetPid();
    Log(id);
}

GetLastError

Get the last error message.

Last error message. string

GetLastError()

function main(){
    // Because the order number 123 does not exist, so there will be an error.
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // Order ID type: TId, so you can't pass in a string, we place an order that doesn't meet the exchange specification to trigger
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

It does not work in the backtesting system.

GetCommand

Gets the strategy interaction command.

The format of the returned command is ControlName:Data. ControlName is the name of the control, and Data is the data entered in the control. If the interactive control does not have input boxes, drop-down boxes and other components (for example, a button control without input boxes) then the returned command format is ControlName, which returns the control name only. string

GetCommand()

function main(){
    while(true) { 
        var cmd = GetCommand()
        if (cmd) { 
            Log(cmd)
        }
        Sleep(1000) 
    }
}
def main():
    while True:
        cmd = GetCommand()
        if cmd:
            Log(cmd)
        Sleep(1000)
void main() {
    while(true) {
        auto cmd = GetCommand();
        if(cmd != "") {
            Log(cmd);
        }
        Sleep(1000);
    }
}

Detects the interaction command and uses the Log function to output the interaction command when it is detected.

function main() {
    while (true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)    
            var arr = cmd.split(":")
            if (arr[0] == "buy") {
                Log("Buy, the control without number")
            } else if (arr[0] == "sell") {
                Log("Sell, the control with the number of:", arr[1])
            } else {
                Log("Other controls trigger:", arr)
            }
        }
        Sleep(1000)
    } 
}
def main():
    while True:
        LogStatus(_D())
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
            arr = cmd.split(":")
            if arr[0] == "buy":
                Log("Buy, the control without number")
            elif arr[0] == "sell":
                Log("Sell, the control with the number of:", arr[1])
            else:
                Log("Other controls trigger:", arr)
        Sleep(1000)
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void split(const string& s,vector<string>& sv,const char flag = ' ') {
    sv.clear();
    istringstream iss(s);
    string temp;            

    while (getline(iss, temp, flag)) {
        sv.push_back(temp);
    }
    return;
}            

void main() {
    while(true) {
        LogStatus(_D());
        auto cmd = GetCommand();
        if (cmd != "") {
            vector<string> arr;
            split(cmd, arr, ':');
            if(arr[0] == "buy") {
                Log("Buy, the control without number");
            } else if (arr[0] == "sell") {
                Log("Sell, the control with the number of:", arr[1]);
            } else {
                Log("Other controls trigger:", arr);
            }
        }
        Sleep(1000);
    }
}

For example, the strategy interactive control adds a control without an input box, the interactive control is named: buy, the control description information is: buy, which is a button control. Continue by adding a control with an input box. The interactive control is named: sell and the control description message is: sell, which is an interactive control that is a combination of a button and an input box. The interaction code is designed in the strategy to respond to the different interaction controls:

It does not work in the backtesting system.

GetMeta

Get the value of Meta written when generating the strategy registration code.

Meta data. string

GetMeta()

function main() {
    // The maximum asset value of the denominated currency allowed by the strategy.
    var maxBaseCurrency = null
    
    // Get the metadata when creating the registration code.
    var level = GetMeta()
    
    // Detecting the conditions corresponding to Meta.
    if (level == "level1") {
        // -1 for unrestricted
        maxBaseCurrency = -1       
    } else if (level == "level2") {
        maxBaseCurrency = 10     
    } else if (level == "level3") {
        maxBaseCurrency = 1
    } else {
        maxBaseCurrency = 0.5
    }
    
    while(1) {
        Sleep(1000)
        var ticker = exchange.GetTicker()
        
        // Detect asset values
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop executing strategy trading logic
            LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!")
            continue
        }
        
        // Other trading logic
        
        // Normal output of status bar information
        LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker)
    }
}
def main():
    maxBaseCurrency = null
    level = GetMeta()
    
    if level == "level1":
        maxBaseCurrency = -1       
    elif level == "level2":
        maxBaseCurrency = 10     
    elif level == "level3":
        maxBaseCurrency = 1
    else:
        maxBaseCurrency = 0.5
    
    while True:
        Sleep(1000)
        ticker = exchange.GetTicker()        
        acc = exchange.GetAccount()
        if maxBaseCurrency != -1 and maxBaseCurrency < acc["Stocks"] + acc["FrozenStocks"]:
            LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!")
            continue        
        
        # Other trading logic
        
        # Normal output of status bar information
        LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker)
void main() {
    auto maxBaseCurrency = 0.0;
    auto level = GetMeta();
    
    if (level == "level1") {
        maxBaseCurrency = -1;  
    } else if (level == "level2") {
        maxBaseCurrency = 10;
    } else if (level == "level3") {
        maxBaseCurrency = 1;
    } else {
        maxBaseCurrency = 0.5;
    }
    
    while(1) {
        Sleep(1000);
        auto ticker = exchange.GetTicker();  
        auto acc = exchange.GetAccount();
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop execution strategy trading logic.
            LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!");
            continue;
        }
        
        // Other trading logic
        
        // Normal output of status bar information
        LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker);
    }
}

Example application scenario: Use Meta to limit the amount of assets operated by the strategy.

Application scenario: need to do capital limits for different strategy renters. The length of the Meta value set when generating the registration code cannot exceed 190 characters, and the GetMeta() function only supports live trading. If no metadata (Meta) is set when generating a strategy registration code, the GetMeta() function returns null. It does not work in the backtesting system.

Dial

For primitive Socket access, supporting tcp, udp, tls, unix protocols. Support 4 popular communication protocols: mqtt, nats, amqp, kafka. Support for connecting to databases: sqlite3, mysql, postgres, clickhouse.

The Dial() function returns null if it times out. A normal call returns a connection object that has three methods: read, write and close. The read method is used to read data, the write method is used to send data and the close method is used to close the connection. The read method supports the following parameters:

  • When no parameters are passed, it blocks until a message is available and returns, such as ws.read().
  • When passed in as a parameter, the unit is milliseconds, specifying the message wait timeout period. For example: ws.read(2000) specifies a timeout of two seconds (2000 milliseconds).
  • The following two parameters are valid only for WebSocket: Passing the parameter -1 means that the function returns immediately, regardless of the presence or absence of messages, for example: ws.read(-1). Passing the parameter -2 means that the function returns immediately with or without a message, but only the latest message is returned, and the buffered message is discarded. For example, ws.read(-2).

read() function buffer description: The incoming data pushed by the WebSocket protocol may cause data accumulation if the time interval between strategy read() function calls is too long. These data are stored in the buffer, which has a data structure of a queue with a maximum of 2000. After 2000 is exceeded, the newest data enters the buffer and the oldest data is cleared out.

Scenario No parameter Parameter: -1 Parameter: -2 Parameter: 2000, in milliseconds
Data already in the buffer Return oldest data immediately Return oldest data immediately Return latest data immediately Return oldest data immediately
No data in the buffer Return when blocked to data Return null immediately Return null immediately Wait 2000 ms, return null if no data, return null if there is data
WebSocket connection is disconnected or reconnected by the underlying read() function returns the empty string, i.e.: “”, and write() function returns 0. The situation is detected. You can close the connection using the close() function, or if you have set up automatic reconnection, you don’t need to close it, the system underlying will reconnect it automatically.

object

Dial(address) Dial(address, timeout)

Request address. address true string timeout seconds, timeout false number

function main(){
    // Dial supports tcp://,udp://,tls://,unix://protocol, you can add a parameter to specify the number of seconds for the timeout
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // write can be followed by a numeric parameter to specify the timeout, write returns the number of bytes successfully sent
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while (true) {
            // read can be followed by a numeric parameter specifying the timeout in milliseconds. Returning null indicates an error or timeout or that the socket has been closed
            var buf = client.read()
            if (!buf) {
                 break
            }
            Log(buf)
        }
        client.close()
    }
}
def main():
    client = Dial("tls://www.baidu.com:443")
    if client:
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while True:
            buf = client.read()
            if not buf:
                break
            Log(buf)
        client.close()
void main() {
    auto client = Dial("tls://www.baidu.com:443");
    if(client.Valid) {
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            Log(buf);
        }
        client.close();
    }
}

Example of a Dial function call:

function main() {
    LogStatus("Connecting...")
    // Accessing WebSocket interface of Binance
    var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
    if (!client) {
        Log("Connection failed, program exited")
        return
    }
    
    while (true) {
        // read returns only the data retrieved after the read call
        var buf = client.read()      
        if (!buf) {
            break
        }
        var table = {
            type: 'table',
            title: 'Ticker Chart',
            cols: ['Currency', 'Highest', 'Lowest', 'Buy 1', 'Sell 1', 'Last traded price', 'Volume', 'Update time'],
            rows: []
        }
        var obj = JSON.parse(buf)
        _.each(obj, function(ticker) {
            table.rows.push([ticker.s, ticker.h, ticker.l, ticker.b, ticker.a, ticker.c, ticker.q, _D(ticker.E)])
        })
        LogStatus('`' + JSON.stringify(table) + '`')
    }
    client.close()
}
import json
def main():
    LogStatus("Connecting...")
    client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
    if not client:
        Log("Connection failed, program exited")
        return 
    
    while True:
        buf = client.read()
        if not buf:
            break
        table = {
            "type" : "table", 
            "title" : "Ticker Chart", 
            "cols" : ['Currency', 'Highest', 'Lowest', 'Buy 1', 'Sell 1', 'Last traded price', 'Volume', 'Update time'], 
            "rows" : [] 
        }
        obj = json.loads(buf)
        for i in range(len(obj)):
            table["rows"].append([obj[i]["s"], obj[i]["h"], obj[i]["l"], obj[i]["b"], obj[i]["a"], obj[i]["c"], obj[i]["q"], _D(int(obj[i]["E"]))])
        LogStatus('`' + json.dumps(table) + '`')
    client.close()
void main() {
    LogStatus("Connecting...");
    auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
    if(!client.Valid) {
        Log("Connection failed, program exited");
        return;
    }
    
    while(true) {
        auto buf = client.read();
        if(buf == "") {
            break;
        }
        json table = R"({
            "type" : "table", 
            "title" : "Ticker Chart", 
            "cols" : ["Currency", "Highest", "Lowest", "Buy 1", "Sell 1", "Last traded price", "Volume", "Update time"], 
            "rows" : []
        })"_json;
        json obj = json::parse(buf);
        for(auto& ele : obj.items()) {
            table["rows"].push_back({ele.value()["s"], ele.value()["h"], ele.value()["l"], ele.value()["b"], ele.value()["a"], ele.value()["c"], 
                ele.value()["q"], _D(ele.value()["E"])});
        }
        LogStatus("`" + table.dump() + "`");
    }
    client.close();
}

To access the WebSocket ticker interface of Binance:

var ws = null 
function main(){
    var param = {
        "op": "subscribe",
        "args": [{
            "channel": "tickers",
            "instId": "BTC-USDT"
        }]
    }
    // When calling Dial function, specify reconnect=true to set reconnection mode and payload to be the message sent when reconnecting. When the WebSocket connection is disconnected, it will reconnect and send messages automatically.
    ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
    if(ws){
        var pingCyc = 1000 * 20
        var lastPingTime = new Date().getTime()
        while(true){
            var nowTime = new Date().getTime()
            var ret = ws.read()
            Log("ret:", ret)
            if(nowTime - lastPingTime > pingCyc){
                var retPing = ws.write("ping")
                lastPingTime = nowTime
                Log("Send : ping", "#FF0000")
            }
            LogStatus("Current time:", _D())
            Sleep(1000)
        }
    }
}              

function onexit() {
    ws.close() 
    Log("exit")
}
import json
import time              

ws = None
def main():
    global ws 
    param = {
        "op": "subscribe",
        "args": [{
            "channel": "tickers",
            "instId": "BTC-USDT"
        }]
    }
    ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
    if ws:
        pingCyc = 1000 * 20
        lastPingTime = time.time() * 1000
        while True:
            nowTime = time.time() * 1000
            ret = ws.read()
            Log("ret:", ret)
            if nowTime - lastPingTime > pingCyc:
                retPing = ws.write("ping")
                lastPingTime = nowTime
                Log("Send: ping", "#FF0000")
            LogStatus("Current time:", _D())
            Sleep(1000)              

def onexit():
    ws.close()
    Log("exit")
auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");              

void main() {
    json param = R"({
        "op": "subscribe",
        "args": [{
            "channel": "tickers",
            "instId": "BTC-USDT"
        }]
    })"_json;
    
    objWS.write(param.dump());
    if(objWS.Valid) {
        uint64_t pingCyc = 1000 * 20;
        uint64_t lastPingTime = Unix() * 1000;
        while(true) {
            uint64_t nowTime = Unix() * 1000;
            auto ret = objWS.read();
            Log("ret:", ret);
            if(nowTime - lastPingTime > pingCyc) {
                auto retPing = objWS.write("ping");
                lastPingTime = nowTime;
                Log("Send: ping", "#FF0000");
            }
            LogStatus("Current time:", _D());
            Sleep(1000);
        }
    }
}              

void onexit() {
    objWS.close();
    Log("exit");
}

Access to OKX’s WebSocket ticker interface:

var ws = null               

function main(){
    var param = {"sub": "market.btcusdt.detail", "id": "id1"}
    ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
    if(ws){
        while(1){
            var ret = ws.read()
            Log("ret:", ret)
            // Respond to heartbeat packet operations
            try {
                var jsonRet = JSON.parse(ret)
                if(typeof(jsonRet.ping) == "number") {
                    var strPong = JSON.stringify({"pong" : jsonRet.ping})
                    ws.write(strPong)
                    Log("Respond to ping, send pong:", strPong, "#FF0000")
                }
            } catch(e) {
                Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
            }
            
            LogStatus("Current time:", _D())
            Sleep(1000)
        }
    }
}              

function onexit() {
    ws.close() 
    Log("Execute the ws.close() function")
}
import json
ws = None              

def main():
    global ws
    param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
    ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
    if ws:
        while True:
            ret = ws.read()
            Log("ret:", ret)              
            # Respond to heartbeat packet operations
            try:
                jsonRet = json.loads(ret)
                if "ping" in jsonRet and type(jsonRet["ping"]) == int:
                    strPong = json.dumps({"pong" : jsonRet["ping"]})
                    ws.write(strPong)
                    Log("Respond to ping, send pong:", strPong, "#FF0000")
            except Exception as e:
                Log("e:", e)
                
            LogStatus("Current time:", _D())
            Sleep(1000)
    
def onexit():
    ws.close()
    Log("Execute the ws.close() function")  
using namespace std;
void main() {
    json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
    auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
    if(ws.Valid) {
        while(true) {
            auto ret = ws.read();
            Log("ret:", ret);              
            // Respond to heartbeat packet operations
            try 
            {
                auto jsonRet = json::parse(ret);
                if(jsonRet["ping"].is_number()) {
                    json pong = R"({"pong" : 0})"_json;
                    pong["pong"] = jsonRet["ping"];
                    auto strPong = pong.dump();
                    ws.write(strPong);
                    Log("Respond to ping, send pong:", strPong, "#FF0000");
                }
            } catch(exception &e) 
            {
                Log("e:", e.what());
            }
            
            LogStatus("Current time:", _D());
            Sleep(1000);
        }
    }
}              

void onexit() {
    // ws.close();
    Log("Execute the ws.close() function");
}

Access to Huobi’s WebSocket ticker interface:

function getLogin(pAccessKey, pSecretKey, pPassphrase) {
    // Signature function for login
    var ts = (new Date().getTime() / 1000).toString()
    var login = {
        "op": "login",
        "args":[{
            "apiKey"    : pAccessKey,
            "passphrase" : pPassphrase,
            "timestamp" : ts,
            "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)   // exchange.HMAC has been deprecated and is temporarily supported. Please use the latest exchange.Encode function instead.
        }]
    }    
    return login
}                

var client_private = null 
function main() {
    // Because the read function uses a timeout setting, filtering the timeout reports errors that would otherwise be output with redundant errors
    SetErrorFilter("timeout")
    
    // Position channel subscription information
    var posSubscribe = {
        "op": "subscribe",
        "args": [{
            "channel": "positions",
            "instType": "ANY"
        }]
    }                

    var accessKey = "xxx"
    var secretKey = "xxx"
    var passphrase = "xxx"            

    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
    client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
    Sleep(3000)  // When logging in, you cannot subscribe to private channels immediately, you need to wait for server response
    client_private.write(JSON.stringify(posSubscribe))
    if (client_private) {
        var lastPingTS = new Date().getTime()
        while (true) {
            var buf = client_private.read(-1)
            if (buf) {
                Log(buf)
            }
            
            // Detect disconnection, reconnect
            if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
                Log("Disconnection detected, close connection, reconnect")
                client_private.close()
                client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
                Sleep(3000)
                client_private.write(JSON.stringify(posSubscribe))
            }
            
            // Send heartbeat packets
            var nowPingTS = new Date().getTime()
            if (nowPingTS - lastPingTS > 10 * 1000) {
                client_private.write("ping")
                lastPingTS = nowPingTS
            }            
        }        
    }
}                

function onexit() {    
    var ret = client_private.close()
    Log("Close the connection!", ret)
}
import json
import time
  
def getLogin(pAccessKey, pSecretKey, pPassphrase):
    ts = str(time.time())
    login = {
        "op": "login",
        "args":[{
            "apiKey"    : pAccessKey,
            "passphrase" : pPassphrase,
            "timestamp" : ts,
            "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
        }]
    }
    return login                 

client_private = None 
def main():
    global client_private
    SetErrorFilter("timeout")
    
    posSubscribe = {
        "op": "subscribe",
        "args": [{
            "channel": "positions",
            "instType": "ANY"
        }]
    }                  

    accessKey = "xxx"
    secretKey = "xxx"
    passphrase = "xxx"
    
    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
    client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
    Sleep(3000)
    client_private.write(json.dumps(posSubscribe))
    if client_private:
        lastPingTS = time.time() * 1000
        while True:
            buf = client_private.read(-1)
            if buf:
                Log(buf)
            
            if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
                Log("Disconnection detected, close connection, reconnect")
                ret = client_private.close()
                client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
                Sleep(3000)
                client_private.write(json.dumps(posSubscribe))
            
            nowPingTS = time.time() * 1000
            if nowPingTS - lastPingTS > 10 * 1000:
                client_private.write("ping")
                lastPingTS = nowPingTS                

def onexit():
    ret = client_private.close()
    Log("Close the connection!", ret)
auto client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");                  

json getLogin(string pAccessKey, string pSecretKey, string pPassphrase) {
    auto ts = std::to_string(Unix());
    json login = R"({
        "op": "login",
        "args": [{
            "apiKey": "",
            "passphrase": "",
            "timestamp": "",
            "sign": ""
        }]
    })"_json;
    login["args"][0]["apiKey"] = pAccessKey;
    login["args"][0]["passphrase"] = pPassphrase;
    login["args"][0]["timestamp"] = ts;
    login["args"][0]["sign"] = exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey);
    return login;
}                  

void main() {
    SetErrorFilter("timeout");
    json posSubscribe = R"({
        "op": "subscribe",
        "args": [{
            "channel": "positions",
            "instType": "ANY"
        }]
    })"_json;
    
    auto accessKey = "xxx";
    auto secretKey = "xxx";
    auto passphrase = "xxx";
    
    client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
    Sleep(3000);
    client_private.write(posSubscribe.dump());                

    if (client_private.Valid) {
        uint64_t lastPingTS = Unix() * 1000;                  

        while (true) {
            auto buf = client_private.read(-1);
            if (buf != "") {
                Log(buf);
            }
            if (buf == "") {
                if (client_private.write(posSubscribe.dump()) == 0) {
                    Log("Disconnection detected, close connection, reconnect");
                    client_private.close();
                    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
                    client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
                    Sleep(3000);
                    client_private.write(posSubscribe.dump());
                }
            }
            
            uint64_t nowPingTS = Unix() * 1000;
            if (nowPingTS - lastPingTS > 10 * 1000) {
                client_private.write("ping");
                lastPingTS = nowPingTS;
            }
        }
    }
}                  

void onexit() {
    client_private.close();
    Log("exit");
}

To access OKX’s WebSocket authentication interface:

var client = null 
function main() {
    // client = Dial("sqlite3://:memory:")   // Using an in-memory database
    client = Dial("sqlite3://test1.db")      // Open/connect to the database file in the docker's directory
    
    // record handle
    var sqlite3Handle = client.fd()
    Log("sqlite3Handle:", sqlite3Handle)
    
    // Querying tables in the database
    var ret = client.exec("SELECT name FROM sqlite_master WHERE type='table'")
    Log(ret)
}

function onexit() {
    Log("Execute client.close()")
    client.close()
}
// Not supported
// Not supported

The connection object returned by the Dial function when connecting to a database has two method functions that are unique to it:

  • exec(sqlString): Used to execute SQL statements in a manner similar to the DBExec() function.
  • fd(): The fd() function returns a handle (e.g., the handle variable is handle) to be used by other threads to reconnect (even if the object created by Dial has already been closed by the execution of the close() function to close the connection) by passing the handle into the Dial() function, for example, Dial(handle) reuse connection. The following is an example of the Dial function connecting to a sqlite3 database.

Details of the address parameter, separated by the | symbol after the normal address: wss://ws.okx.com:8443/ws/v5/public. If there are | characters in the parameter string, then || is used as the separator sign. The part after that is some function parameter settings, and each parameter is connected with & characters. For example, the ss5 proxy and compression parameters can be set together as follows: Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Functions supported by the address parameter of the Dial function Parameter description
Parameters related to WebSocket protocol data compression: compress=parameter value compress is the compression method, compress parameter options are: gzip_raw, gzip, etc. If the gzip method is not standard gzip, you can use the extended method: gzip_raw
Parameters related to WebSocket protocol data compression: mode=parameter value mode is the compression mode, mode parameter can be dual, send, recv. dual is two-way compression, send compressed data, receive compressed data. send is send compressed data. recv is receive compressed data, local decompression.
WebSocket protocol sets the underlying auto-reconnect related parameters: reconnect=parameter value reconnect is whether to set reconnect, reconnect=true is to enable reconnect. The default is no reconnect when this parameter is not set.
WebSocket protocol sets the underlying auto-reconnect related parameters: interval=parameter value interval is the retry interval, in milliseconds, interval=10000 is the retry interval of 10 seconds, the default is 1 second when it’s not set, that is, interval=1000.
WebSocket protocol sets the underlying auto-reconnect related parameters: payload=parameter value payload is the subscription message that needs to be sent when the WebSocket is reconnected, e.g.: payload=okokok.
Parameters related to socks5 proxy: proxy=parameter value proxy is ss5 proxy setting, parameter value format: socks5://name:pwd@192.168.0.1:1080, name is ss5 server username, pwd is ss5 server login password, 1080 is ss5 service port.

The Dial() function is only supported for live trading. When connecting to a database using the Dial function, the connection string is written with reference to the go language driver project for each database.

Databases supported Driving projects Connection string Remarks
sqlite3 github.com/mattn/go-sqlite3 sqlite3://file:test.db?cache=shared&mode=memory The sqlite3:// prefix indicates that a sqlite3 database is being used, example call: Dial("sqlite3://test1.db")
mysql github.com/go-sql-driver/mysql mysql://username:yourpassword@tcp(localhost:3306)/yourdatabase?charset=utf8mb4
postgres github.com/lib/pq postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432
clickhouse github.com/ClickHouse/clickhouse-go clickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase

Please note that when the payload content set in the address parameter contains characters = or other special characters, it may affect the parsing of the address parameter of the Dial function, such as the following example.

backPack Exchange websocket private interface call example:

var client = null

function main() {
    // Base64-encoded public key of the key pair, i.e. the access key configured on FMZ
    var base64ApiKey = "xxx"

    var ts = String(new Date().getTime())
    var data = "instruction=subscribe&timestamp=" + ts + "&window=5000"

    // Since signEd25519 returns a base64 encoding, it contains the character "="
    var signature = signEd25519(data)
    
    // The payload may contain the character "=" after being encoded by JSON
    payload = {
        "method": "SUBSCRIBE",
        "params": ["account.orderUpdate"],
        "signature": [base64ApiKey, signature, ts, "5000"]
    }

    client = Dial("wss://ws.backpack.exchange")
    client.write(JSON.stringify(payload))
    if (!client) {
        Log("Connection failed, program exited")
        return
    }
    
    while (true) {
        var buf = client.read()      
        Log(buf)
    }    
}

function onexit() {
    client.close()
}

function signEd25519(data) {
    return exchange.Encode("ed25519.seed", "raw", "base64", data, "base64", "{{secretkey}}")
}

The following call in the code works fine:

client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))

If you write it directly in payload, it will not work properly, for example:

client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))

Currently, only JavaScript supports the use of the mqtt, nats, amqp, and kafka communication protocols in the Dial function. The JavaScript language strategy code is used as an example to show the use of the four protocols: mqtt, nats, amqp, and kafka:

// We need to configure and deploy proxy servers for each protocol first.
// For the sake of demonstration, the subscription (read operation) and publishing (write operation) of the topic test_topic are all performed in the current strategy.
var arrConn = []
var arrName = []

function main() {
    LogReset(1)
    conn_nats = Dial("nats://admin@127.0.0.1:4222?topic=test_topic")
    conn_mqtt = Dial("mqtt://127.0.0.1:1883?topic=test_topic")
    conn_amqp = Dial("amqp://q:admin@127.0.0.1:5672/?queue=test_Queue")
    conn_kafka = Dial("kafka://localhost:9092/test_topic")
    arrConn = [conn_nats, conn_amqp, conn_mqtt, conn_kafka]
    arrName = ["nats", "amqp", "mqtt", "kafka"]

    while (true) {
        for (var i in arrConn) {
            var conn = arrConn[i]
            var name = arrName[i]

            // Write data
            conn.write(name + ", time: " + _D() + ", test msg.")
            
            // Read data
            var readMsg = conn.read(1000)
            Log(name + " readMsg: ", readMsg, "#FF0000")
        }

        Sleep(1000)
    }
}

function onexit() {
    for (var i in arrConn) {
        arrConn[i].close()
        Log("close", arrName[i], "connect")
    }
}

Detailed documentation reference: Exploring FMZ: Practice of Communication Protocol Between Live Trading Strategies

HttpQuery

Send an Http request.

Returns the response data of the request. If the return value is a JSON string, it can be parsed by the JSON.parse() function in the JavaScript language strategy, and by the json::parse() function in the C++ language strategy. If debug is set to true in the options structure, the return value is an object (JSON); if debug is set to false, the return value is a string. string, object

HttpQuery(url) HttpQuery(url, options)

Http request url. url true string Http request-related settings, for example, can be structured as follows:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    profile: "chrome_103",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • profile: Used to simulate browser tls fingerprints. The supported settings include the following options: chrome_:"chrome_103", "chrome_104", "chrome_105", "chrome_106", "chrome_107", "chrome_108", "chrome_109", "chrome_110", "chrome_111", "chrome_112", "chrome_117", safari_:"safari_15_6_1", "safari_16_0", "safari_ipad_15_6", "safari_ios_15_5", "safari_ios_15_6", "safari_ios_16_0", firefox_:"firefox_102", "firefox_104", "firefox_105", "firefox_106", "firefox_108", "firefox_110", "firefox_117", opera_:"opera_89", "opera_90", "opera_91", zalando_:"zalando_android_mobile", "zalando_ios_mobile", nike_:"nike_ios_mobile", "nike_android_mobile", cloudscraper:"cloudscraper", mms_:"mms_ios", mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2", confirmed_:"confirmed_ios", "confirmed_android", okhttp4_:"okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • debug: When it’s set to true, the HttpQuery function call returns the full reply message. When it’s set to false, only the data in the Body of the reply message is returned.
  • timeout: Timeout setting, set 1000 means 1 second timeout.
  • charset: It supports transcoding of the requested response data, such as GB18030. It supports common encoding. All fields in this structure are optional, for example, the profile field can be left out.

options false object

function main(){
    // An example of GET access without parameters
    var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
    Log(info)
    // An example of GET access with parameters
    var ticker = JSON.parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"))
    Log(ticker)
}
import json
import urllib.request
def main():
    # HttpQuery does not support Python, you can use the urllib/urllib2 library instead
    info = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/public/time").read().decode('utf-8'))
    Log(info)
    ticker = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/market/books?instId=BTC-USDT").read().decode('utf-8'))
    Log(ticker)
void main() {
    auto info = json::parse(HttpQuery("https://www.okx.com/api/v5/public/time"));
    Log(info);
    auto ticker = json::parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"));
    Log(ticker);
}

An example of accessing the OKX public ticker API interface.

function main() {
    // Setting proxy and sending an http request for this time, no username, no password, this http request will be sent through the proxy
    HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")            

    // Setting proxy and sending an http request for this time, enter the user name and password, only the current call to HttpQuery takes effect, and then call HttpQuery again ("http://www.baidu.com") so that the proxy will not be used.
    HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
}
# HttpQuery does not support Python, you can use the urllib/urllib2 library instead
void main() {
    HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/");
    HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/");
}

The HttpQuery function uses proxy settings.

The HttpQuery() function only supports JavaScript, C++ language, Python language can use the urllib library to send Http requests directly. The HttpQuery() is mainly used to access the interfaces of the exchange that do not require a signature, such as public interfaces like ticker information. The HttpQuery() can be used in the backtesting system to send requests (only GET requests are supported) to obtain data. Backtesting is limited to using 20 visits to different URLs, and HttpQuery() visits will cache data. When the same URL is accessed a second time, the HttpQuery() function returns the cached data and no more actual network requests occur.

{@fun/Global/HttpQuery_Go HttpQuery_Go}

HttpQuery_Go

Sends an Http request, an asynchronous version of the HttpQuery function.

The HttpQuery_Go() function immediately returns a concurrent object that can be used to obtain the result of an Http request using the wait method of the The JSON.parse() function can be used to parse the JSON.parse() function in the JavaScript language’s strategy.
object

HttpQuery_Go(url) HttpQuery_Go(url, options)

Http request url. url true string Http request-related settings, for example, can be structured as follows:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    // profile: "",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • profile: Used to simulate browser tls fingerprints.
  • debug: When it’s set to true, this HttpQuery_Go function call returns the full reply message. When it’s set to false, only the data in the Body of the reply message is returned.
  • timeout: Timeout setting, set 1000 means 1 second timeout. All fields in this structure are optional, for example, the profile field can be left out.

options false object

function main() {
    // Create the first asynchronous thread
    var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
    // Create the second asynchronous thread
    var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
    
    // Get the return value of the first asynchronous thread call
    var tickers1 = r1.wait()
    // Get the return value of the second asynchronous thread call
    var tickers2 = r2.wait()
    
    // Print results
    Log("tickers1:", tickers1)
    Log("tickers2:", tickers2)
}
# Not supported
// Not supported

Asynchronous access to the exchange’s public interface for aggregated ticker data.

The HttpQuery_Go() function only supports JavaScript, the Python language can be used with the urllib library to send Http requests directly. The HttpQuery_Go() is mainly used to access interfaces that do not require a signature on the exchange, such as public interfaces like ticker information. The HttpQuery_Go function is not supported in the backtesting system.

{@fun/Global/HttpQuery HttpQuery}

Encode

This function encodes the data according to the parameters passed in.

The Encode function returns the data after encoding and encryption. string

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

The parameter algo is the algorithm used in the encoding calculation. The support setting is: raw (no algorithm is used), the"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”, encode and decode strings. The parameter algo also supports: “ed25519” algorithm. Supports the use of different hash algorithms, for example, the parameter algo can be written as “ed25519.md5”, “ed25519.sha512”, etc. It supports ed25519.seed calculation. algo true string Used to specify the data format of the data parameter. The inputFormat parameter can be set as one of the followings: 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. inputFormat true string Used to specify the data format of the output. The outputFormat parameter can be set as one of the followings: 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 as one of the followings: 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. keyFormat false string The parameter key is the secret key used for HMAC encryption. The parameter key is required when the parameter algo is set to sign or signTx. The key parameter is not used for HMAC encryption when the algo parameter is set to “raw” (because the algorithm must be specified for HMAC encryption). key false string

function main() {
    Log(Encode("raw", "raw", "hex", "example", "raw", "123"))            // 6578616d706c65
    Log(Encode("raw", "raw", "hex", "example"))                          // 6578616d706c65
    Log(Encode("sha256", "raw", "hex", "example", "raw", "123"))         // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "", "123"))            // 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c
    Log(Encode("sha256", "raw", "hex", "example", null, "123"))          // 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c
    Log(Encode("sha256", "raw", "hex", "example", "string", "123"))      // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    
    Log(Encode("raw", "raw", "hex", "123"))           // 313233
    Log(Encode("raw", "raw", "base64", "123"))        // MTIz
    
    Log(Encode("sha256", "raw", "hex", "example", "hex", "313233"))      // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "base64", "MTIz"))     // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
}
def main():
    Log(Encode("raw", "raw", "hex", "example", "raw", "123"))            # 6578616d706c65
    Log(Encode("raw", "raw", "hex", "example", "", ""))                  # 6578616d706c65
    Log(Encode("sha256", "raw", "hex", "example", "raw", "123"))         # 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "", "123"))            # 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c            

    Log(Encode("sha256", "raw", "hex", "example", "string", "123"))      # 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    
    Log(Encode("raw", "raw", "hex", "123", "", ""))           # 313233
    Log(Encode("raw", "raw", "base64", "123", "", ""))        # MTIz
    
    Log(Encode("sha256", "raw", "hex", "example", "hex", "313233"))      # 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "base64", "MTIz"))     # 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
void main() {
    Log(Encode("raw", "raw", "hex", "example", "raw", "123"));            // 6578616d706c65
    Log(Encode("raw", "raw", "hex", "example"));                          // 6578616d706c65
    Log(Encode("sha256", "raw", "hex", "example", "raw", "123"));         // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "", "123"));            // 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c            

    Log(Encode("sha256", "raw", "hex", "example", "string", "123"));      // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
                
    Log(Encode("raw", "raw", "hex", "123"));           // 313233
    Log(Encode("raw", "raw", "base64", "123"));        // MTIz
                
    Log(Encode("sha256", "raw", "hex", "example", "hex", "313233"));      // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
    Log(Encode("sha256", "raw", "hex", "example", "base64", "MTIz"));     // 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84ba
}

Example of Encode function call.

function main(){
    var ret1 = Encode("text.encoder.utf8", "raw", "hex", "hello")     // e4bda0e5a5bd
    Log(ret1)    
    var ret2 = Encode("text.decoder.utf8", "hex", "string", ret1)   
    Log(ret2)            

    var ret3 = Encode("text.encoder.gbk", "raw", "hex", "hello")      // c4e3bac3
    Log(ret3)
    var ret4 = Encode("text.decoder.gbk", "hex", "string", ret3)
    Log(ret4)
}
def main():
    ret1 = Encode("text.encoder.utf8", "raw", "hex", "hello", "", "")     # e4bda0e5a5bd
    Log(ret1)    
    ret2 = Encode("text.decoder.utf8", "hex", "string", ret1, "", "")   
    Log(ret2)            

    ret3 = Encode("text.encoder.gbk", "raw", "hex", "hello", "", "")      # c4e3bac3
    Log(ret3)
    ret4 = Encode("text.decoder.gbk", "hex", "string", ret3, "", "")
    Log(ret4)
void main(){
    auto ret1 = Encode("text.encoder.utf8", "raw", "hex", "hello");     // e4bda0e5a5bd
    Log(ret1);    
    auto ret2 = Encode("text.decoder.utf8", "hex", "string", ret1);   
    Log(ret2);            

    auto ret3 = Encode("text.encoder.gbk", "raw", "hex", "hello");      // c4e3bac3
    Log(ret3);
    auto ret4 = Encode("text.decoder.gbk", "hex", "string", ret3);
    Log(ret4);
}

The parameter algo also supports: “text.encoder.utf8”, “text.decoder.utf8”, “text.encoder.gbk”, “text.decoder.gbk” to encode and decode strings.

The Encode() function is only supported for live trading. If key and keyFormat parameters are not passed, then key encryption is not used.

UnixNano

Get the nanosecond timestamp of the current moment.

The UnixNano() function returns the nanosecond timestamp. number

UnixNano()

function main() {
    var time = UnixNano() / 1000000
    Log(_N(time, 0))
}
def main():
    time = UnixNano()
    Log(time)
void main() {
    auto time = UnixNano();
    Log(time);
}

If you need to get millisecond timestamps, you can use the following code:

{@fun/Global/Unix Unix}

Unix

Get the timestamp of the current moment at the second level.

Returns the second-level timestamp. number

Unix()

function main() {
    var t = Unix()
    Log(t)
}
def main():
    t = Unix()
    Log(t)
void main() {
    auto t = Unix();
    Log(t);
}

{@fun/Global/UnixNano UnixNano}

GetOS

Get the system information of the device where the docker is located.

System information. string

GetOS()

function main() {
    Log("GetOS:", GetOS())
}
def main():
    Log("GetOS:", GetOS())
void main() {
    Log("GetOS:", GetOS());
}

For example, a call to the GetOS() function for a docker running on the Mac OS operating system might return: darwin/amd64. Because Apple computers have multiple hardware architectures. darwin is the name of the Mac OS system.

MD5

Computes the MD5 hash of the parameter data.

MD5 hash value. string

MD5(data)

The data that requires MD5 calculation. data true string

function main() {
    Log("MD5", MD5("hello world"))
}
def main():
    Log("MD5", MD5("hello world"))
void main() {
    Log("MD5", MD5("hello world"));
}

Calling the MD5("hello world") function, the return value is: 5eb63bbbe01eeed093cb22bb8f5acdc3.

{@fun/Global/Encode Encode}

DBExec

Database interface functions.

An object containing the result of the execution of a sql statement, for example:


{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}

object

DBExec(sql)

sql statement string. sql true string

function main() {
    var strSql = [
        ":CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ].join("")
    var ret = DBExec(strSql)
    Log(ret)
    
    // Add a piece of data
    Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    // Query data
    Log(DBExec(":SELECT * FROM TEST_TABLE;"))
}
def main():
    arr = [
        ":CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ]
    strSql = ""
    for i in range(len(arr)):
        strSql += arr[i]
    ret = DBExec(strSql)
    Log(ret)
    
    # Add a piece of data
    Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    # Query data
    Log(DBExec(":SELECT * FROM TEST_TABLE;"))
void main() {
    string strSql = ":CREATE TABLE TEST_TABLE(\
        TS INT PRIMARY KEY NOT NULL,\
        HIGH REAL NOT NULL,\
        OPEN REAL NOT NULL,\
        LOW REAL NOT NULL,\
        CLOSE REAL NOT NULL,\
        VOLUME REAL NOT NULL)";
    auto ret = DBExec(strSql);
    Log(ret);
    
    // Add a piece of data
    Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
    
    // Query data
    Log(DBExec(":SELECT * FROM TEST_TABLE;"));
}

Support in-memory database, for DBExec function parameters, if sql statement starts with : then operate in in-memory database, it will be faster without writing files. It’s suitable for database operations that do not require persistent saving, for example:

function main() {
    var strSql = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ].join("")
    var ret = DBExec(strSql)
    Log(ret)
}
def main():
    arr = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ]
    strSql = ""
    for i in range(len(arr)):
        strSql += arr[i]
    ret = DBExec(strSql)
    Log(ret)
void main() {
    string strSql = "CREATE TABLE TEST_TABLE(\
        TS INT PRIMARY KEY NOT NULL,\
        HIGH REAL NOT NULL,\
        OPEN REAL NOT NULL,\
        LOW REAL NOT NULL,\
        CLOSE REAL NOT NULL,\
        VOLUME REAL NOT NULL)";
    auto ret = DBExec(strSql);
    Log(ret);
}

Create a table.

function main() {
    var strSql = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ].join("")
    Log(DBExec(strSql))
    
    // Add a piece of data
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    // Query data
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    // Modify data
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))    
    
    // Delete data
    Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110))
}
def main():
    arr = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ]
    strSql = ""
    for i in range(len(arr)):
        strSql += arr[i]
    Log(DBExec(strSql))
    
    # Add a piece of data
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    # Query data
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    # Modify data
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))
    
    # Delete data
    Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110))
void main() {
    string strSql = "CREATE TABLE TEST_TABLE(\
        TS INT PRIMARY KEY NOT NULL,\
        HIGH REAL NOT NULL,\
        OPEN REAL NOT NULL,\
        LOW REAL NOT NULL,\
        CLOSE REAL NOT NULL,\
        VOLUME REAL NOT NULL)";
    Log(DBExec(strSql));            

    // Add a piece of data
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
    
    // Query data
    Log(DBExec("SELECT * FROM TEST_TABLE;"));
    
    // Modify data
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000));
    
    // Delete data
    Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110));
}

Add, delete, check and change the records in the table.

The function DBExec() can operate the live trading database (SQLite database) by passing in parameters. Realize the operation of adding, deleting, checking and changing data in the live trading database, supporting SQLite grammar. The system reserved tables in the live trading database: kvdb, cfg, log, profit, chart, do not operate on these tables. Currently Transactions are not supported and it is not recommended to perform such operations, which can cause conflicts in the system. The DBExec() function is only supported for live trading.

{@fun/Global/_G _G}

UUID

Create a UUID.

32-bit UUID. string

UUID()

function main() {
    var uuid1 = UUID()
    var uuid2 = UUID()
    Log(uuid1, uuid2)
}
def main():
    uuid1 = UUID()
    uuid2 = UUID()
    Log(uuid1, uuid2)
void main() {
    auto uuid1 = UUID();
    auto uuid2 = UUID();
    Log(uuid1, uuid2);
}

The UUID() function supports live trading only.

EventLoop

Listen for events, it returns when there is any WebSocket readable data or concurrent tasks, such as exchange.Go(), HttpQuery_Go(), etc. are completed.

If the returned object is not null value, the Event contained in the return content is the event trigger type. For example, the following return value structure:

{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}

object

EventLoop() EventLoop(timeout)

The parameter timeout is the timeout setting, in milliseconds. The parameter timeout waits for an event to occur before returning if it is set to 0. If it is greater than 0, it sets the event to wait for a timeout, and returns the most recent event immediately if it is less than 0. timeout false number

function main() {
    var routine_getTicker = exchange.Go("GetTicker")
    var routine_getDepth = exchange.Go("GetDepth")
    var routine_getTrades = exchange.Go("GetTrades")
    
    // Sleep(2000), if the Sleep statement is used here, it will cause the subsequent EventLoop function to miss the previous events, because after waiting for 2 seconds, the concurrent function has received the data, and the subsequent EventLoop listening mechanism started, it misses these events.
    // These events will not be missed unless EventLoop(-1) is called at the beginning of the first line of code to first initialize the EventLoop's listening mechanism.            

    // Log("GetDepth:", routine_getDepth.wait()) If the wait function is called in advance to retrieve the result of a concurrent call to the GetDepth function, the event that the GetDepth function receives the result of the request will not be returned in the EventLoop function.
    var ts1 = new Date().getTime()
    var ret1 = EventLoop(0)
    
    var ts2 = new Date().getTime()
    var ret2 = EventLoop(0)
    
    var ts3 = new Date().getTime()
    var ret3 = EventLoop(0)
    
    Log("The first concurrent task completed was:", _D(ts1), ret1)
    Log("The second concurrent task completed was:", _D(ts2), ret2)
    Log("The third concurrent task completed was:", _D(ts3), ret3)
    
    Log("GetTicker:", routine_getTicker.wait())
    Log("GetDepth:", routine_getDepth.wait())
    Log("GetTrades:", routine_getTrades.wait())
}
import time
def main():
    routine_getTicker = exchange.Go("GetTicker")
    routine_getDepth = exchange.Go("GetDepth")
    routine_getTrades = exchange.Go("GetTrades")
    
    ts1 = time.time()
    ret1 = EventLoop(0)
    
    ts2 = time.time()
    ret2 = EventLoop(0)
    
    ts3 = time.time()
    ret3 = EventLoop(0)
    
    Log("The first concurrent task completed was:", _D(ts1), ret1)
    Log("The second concurrent task completed was:", _D(ts2), ret2)
    Log("The third concurrent task completed was:", _D(ts3), ret3)
    
    Log("GetTicker:", routine_getTicker.wait())
    Log("GetDepth:", routine_getDepth.wait())
    Log("GetTrades:", routine_getTrades.wait())
void main() {
    auto routine_getTicker = exchange.Go("GetTicker");
    auto routine_getDepth = exchange.Go("GetDepth");
    auto routine_getTrades = exchange.Go("GetTrades");
    
    auto ts1 = Unix() * 1000;
    auto ret1 = EventLoop(0);
    
    auto ts2 = Unix() * 1000;
    auto ret2 = EventLoop(0);
    
    auto ts3 = Unix() * 1000;
    auto ret3 = EventLoop(0);
    
    Log("The first concurrent task completed was:", _D(ts1), ret1);
    Log("The second concurrent task completed was:", _D(ts2), ret2);
    Log("The third concurrent task completed was:", _D(ts3), ret3);
    
    Ticker ticker;
    Depth depth;
    Trades trades;
    routine_getTicker.wait(ticker);
    routine_getDepth.wait(depth);
    routine_getTrades.wait(trades);
    
    Log("GetTicker:", ticker);
    Log("GetDepth:", depth);
    Log("GetTrades:", trades);
}

The first call to the EventLoop() function in the code initializes the mechanism for that listened event, and if the first EventLoop() call starts after the event callback, it will miss the previous events. The underlying system wraps a queue structure that caches a maximum of 500 event callbacks. If the EventLoop() function is not called in time to take them out during program execution, later event callbacks outside the 500 cache will be lost. Calls to the EventLoop() function do not affect the cache queue of the underlying system WebSocket or the caches of concurrent functions such as exchange.Go(). For these caches, it is still necessary to use the respective methods to retrieve the data. No return event will be generated in the EventLoop() function for data that has been retrieved before the EventLoop() function returns. The main purpose of the EventLoop() function is to notify the strategy layer that new network data has been received by the underlying system. The whole strategy is driven by events. When the EventLoop() function returns an event, just traverses all data sources. For example, WebSocket connections, objects created by exchange.Go() try to get data. The EventLoop() function supports live trading only. Listen for events in the main thread when called from the main function main(). In strategies written in the JavaScript language, the threading.Thread() function creates a thread, which can also be called in the thread’s execution function, to listen for events in the current thread.

{@fun/Global/Dial Dial}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}

__Serve

The __Serve function is used to create Http service, TCP service, and Websocket service (based on Http protocol).

Returns a string that records the IP address and port of the created service. For example: 127.0.0.1:8088, [::]:8089.

string

__Serve(serveURI, handler) __Serve(serveURI, handler, …args)

The serveURI parameter is used to configure the protocol, IP address, port and other settings of the service binding, such as http://0.0.0.0:8088?gzip=true, that is, http://:8088?gzip=true.

  • TCP protocol serveURI parameter setting, such as tcp://127.0.0.1:6666?tls=true; you can add certificates and private keys, such as tls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Http protocol serveURI parameter settings, such as http://127.0.0.1:6666?gzip=true; you can set compression settings: gzip=true. The serveURI parameter is used for Https, such as https://127.0.0.1:6666?tls=true&gzip=true; you can add cert_pem and cert_key_pem parameters to load the certificate.

serveURI true string The handler parameter is used to pass in the routing processing function (Http protocol), message processing function (TCP protocol), and Stream processing function (Websocket). The callback function passed in by the parameter handler can define multiple parameters, the first parameter is the ctx object (context object).

handler true function The actual parameter of the callback function passed as the parameter handler. There may be multiple parameters arg, for example:

__Serve("http://:8088", function(ctx, a, b, c) {
    Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)

The parameters 1, 2, 3 passed in when calling the __Serve() function correspond to the parameters a, b, c passed in the callback function.

arg false string, number, bool, object, array, function, null value and other types supported by the system

function main() {
    let httpServer = __Serve("http://:8088?gzip=true", function (ctx) {
        Log("http connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        let path = ctx.path()
        if (path == "/") {
            ctx.write(JSON.stringify({
                path: ctx.path(),
                method: ctx.method(),
                headers: ctx.headers(),
                cookie: ctx.header("Cookie"),
                remote: ctx.remoteAddr(),
                query: ctx.rawQuery()
            }))
        } else if (path == "/tickers") {
            let ret = exchange.GetTickers()
            if (!ret) {
                ctx.setStatus(500)
                ctx.write(GetLastError())
            } else {
                ctx.write(JSON.stringify(ret))
            }
        } else if (path == "/wss") {
            if (ctx.upgrade("websocket")) { // upgrade to websocket
                while (true) {
                    let r = ctx.read(10)
                    if (r == "") {
                        break
                    } else if (r) {
                        if (r == "ticker") {
                            ctx.write(JSON.stringify(exchange.GetTicker()))
                        } else {
                            ctx.write("not support")
                        }
                    }
                }
                Log("websocket closed", ctx.remoteAddr())
            }
        } else {
            ctx.setStatus(404)
        }
    })
    let echoServer = __Serve("tcp://:8089", function (ctx) {
        Log("tcp connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        while (true) {
            let d = ctx.read()
            if (!d) {
                break
            }
            ctx.write(d)
        }
        Log("connect closed")
    })
    Log("http serve on", httpServer, "tcp serve on", echoServer)
    
    for (var i = 0; i < 5; i++) {
        if (i == 2) {
            // test Http
            var retHttp = HttpQuery("http://127.0.0.1:8088?num=123&limit=100", {"debug": true})
            Log("retHttp:", retHttp)
        } else if (i == 3) {
            // test TCP
            var tcpConn = Dial("tcp://127.0.0.1:8089")
            tcpConn.write("Hello TCP Server")
            var retTCP = tcpConn.read()
            Log("retTCP:", retTCP)
        } else if (i == 4) {
            // test Websocket
            var wsConn = Dial("ws://127.0.0.1:8088/wss|compress=gzip")
            wsConn.write("ticker")
            var retWS = wsConn.read(1000)
            Log("retWS:", retWS)
            // no depth
            wsConn.write("depth")
            retWS = wsConn.read(1000)
            Log("retWS:", retWS)
        }
        Sleep(1000)
    }
}
# Unsupported
// Unsupported
  • This function supports JavaScript language strategies only.
  • The service thread is isolated from the global scope, so it does not support closures or references to external variables, custom functions, etc.; however, it can call all platform API functions.
  • The Websocket service is implemented based on the Http protocol. You can set a routing branch in the path and design the implementation code for Websocket message subscription/push. You can refer to the sample code in this section.

The callback function passed in by the parameter handler receives a ctx parameter. The ctx parameter is a context object used to get and write data, with the following methods:

  • ctx.proto() Applied to Http/TCP protocol, returns the protocol name when called. For example: HTTP/1.1, tcp.
  • ctx.host() Applied to Http protocol, it returns host information when called IP address and port.
  • ctx.path() Applied to the Http protocol, returns the request path when called.
  • ctx.query(key) Applied to Http protocol, returns the value corresponding to the key in the query in the request when called. For example, the request sent is: http://127.0.0.1:8088?num=123, and the callback processing function passed in by the parameter handler returns "123" when ctx.query("num") is called.
  • ctx.rawQuery() Applied to the Http protocol, when called, returns the original query in the request (the query of the Http request).
  • ctx.headers() Applied to the Http protocol, and returns the request header information in the request when called.
  • ctx.header(key) Applied to Http protocol, it returns the value of a key in the specified request header when called. For example, get the User-Agent in the headers of the current request: ctx.header("User-Agent").
  • ctx.method() Applied to the Http protocol, returns the request method when called, such as GET, POST, etc.
  • ctx.body() Applied to POST request of Http protocol, and returns the body of the request when called.
  • ctx.setHeader(key, value) Applied to the Http protocol to set the request header information of the response message.
  • ctx.setStatus(code) Applied to Http protocol, set Http message status code. Usually, Http status code is set at the end of the routing branch. The default value is 200.
  • ctx.remoteAddr() Applied to Http/TCP protocol, returns the remote client address and port in the request when called.
  • ctx.localAddr() Applied to Http/TCP protocol, returns the local address and port of the service when called.
  • ctx.upgrade(“websocket”) Applied to the Websocket protocol implementation based on the Http protocol, switching the ctx context object to the Websocket protocol; returning a Boolean value (true) if the switch is successful, and a Boolean value (false) if it fails.
  • ctx.read(timeout_ms) Applied to Websocket protocol implementation/TCP protocol based on Http protocol, reads data of Websocket connection and TCP connection. The read method is not supported in ordinary Http protocol. You can specify the timeout parameter timeout_ms in milliseconds.
  • ctx.write(s) Applied to Http/TCP protocol, used to write string data. You can use JSON.stringify() to encode the JSON object into a string and then write it. For the WebSocket protocol, you can use this method to pass the encoded string to the client.

{@fun/Global/HttpQuery HttpQuery}, {@fun/Global/HttpQuery_Go HttpQuery_Go}

_G

Persistently save data, the function implements a global dictionary function that can be saved. The data structure is a KV table that is permanently saved in the docker’s local database file.

Persistent saved key-value data in k-v key-value pairs. string, number, bool, object, array, null value

_G() _G(k) _G(k, v)

The parameter k is the name of the key in the saved key-value pair, and is not case-sensitive. k false string, null value The parameter v is the key value in the saved key-value pair, which can be any data that can be JSON serialized. v false string, number, bool, object, array, null value

function main(){
    // Set a global variable num with a value of 1
    _G("num", 1)     
    // Change a global variable num to the value of the string ok
    _G("num", "ok")    
    // Delete the global variable num
    _G("num", null)
    // Returns the value of the global variable num
    Log(_G("num"))
    // Delete all global variables
    _G(null)
    // Return to live trading ID
    var robotId = _G()
}
def main():
    _G("num", 1)     
    _G("num", "ok")    
    _G("num", None)
    Log(_G("num"))
    _G(None)
    robotId = _G()
void main() {
    _G("num", 1);
    _G("num", "ok");
    _G("num", NULL);
    Log(_G("num"));
    _G(NULL);
    // Not support auto robotId = _G();
}

A separate database for each live trading, the data saved by the _G() function will always be there if the strategy is restarted or the docker stops running. If the backtesting is finished, the data saved in the backtesting system by the _G() function will be cleared. When using the _G() function to persist the saved data, it should be used reasonably according to the memory and hard disk space of the hardware device, and should not be abused. When calling the _G() function in a live trading and no parameters are passed, the _G() function returns the Id of the current live trading. When calling the _G() function, the parameter v is passed as null to indicate the deletion of the k-v key-value pair. When calling the _G() function, only the parameter k is passed in the string, and the _G() function returns the key value corresponding to the saved parameter k. When calling the _G() function, only the parameter k is passed in a null value, indicating that all records of the k-v key-value pair is deleted. When the k-v key-value pairs have been saved persistently, the _G() function is called again, passing in the name of the key that has been saved persistently as parameter k. Passing in the new key value as parameter v will update that k-v key-value pair.

{@fun/Global/DBExec DBExec}

_D

Converts millisecond timestamps or Date objects to time strings.

Time string. string

_D() _D(timestamp) _D(timestamp, fmt)

Millisecond timestamp or Date object. timestamp false number、object Format string, JavaScript language default format: yyyy-MM-dd hh:mm:ss; Python language default format: %Y-%m-%d %H:%M:%S; C++ language default format: %Y-%m-%d %H:%M:%S. fmt false string

function main(){
    var time = _D()
    Log(time)
}
def main():
    strTime = _D()
    Log(strTime)
void main() {
    auto strTime = _D();
    Log(strTime);
}

Get and print the current time string:

function main() {
    Log(_D(1574993606000))
}
def main():
    # Running this code on a server in Beijing time: 2019-11-29 10:13:26 , a docker on another server in another region results in: 2019-11-29 02:13:26
    Log(_D(1574993606))
void main() {
    Log(_D(1574993606000));
}

The timestamp is 1574993606000, using the code conversion:

function main() {
    Log(_D(1574993606000, "yyyy--MM--dd hh--mm--ss"))   // 2019--11--29 10--13--26
}
def main():
    # 1574993606 is timestamped in seconds.
    Log(_D(1574993606, "%Y--%m--%d %H--%M--%S"))        #  2019--11--29 10--13--26
void main() {
    Log(_D(1574993606000, "%Y--%m--%d %H--%M--%S"));    // 2019--11--29 10--13--26
}

Formatting with the parameter fmt is different for JavaScript, Python, and C++ languages, as shown in the following examples:

Returns the current time string without passing any parameters. When using the _D() function in the Python strategy, you need to be aware that the parameters passed are second-level timestamps (millisecond-level timestamps in the JavaScript and C++ strategies, where 1 second is equal to 1000 milliseconds). When using the _D() function to parse a time string with a readable timestamp in the live trading, you need to pay attention to the time zone and time setting of the operating system where the docker program is located. The _D() function parses a timestamp into a readable time string depending on the time of the docker’s system.

{@fun/Global/UnixNano UnixNano}, {@fun/Global/Unix Unix}

_N

Format a floating point number.

The formatted floating point number according to the precision setting. number

_N() _N(num) _N(num, precision)

The floating point number that needs to be formatted. num true number The precision setting for formatting, the parameter precision is an integer, and the parameter precision defaults to 4. precision false number

function main(){
    var i = 3.1415
    Log(i)
    var ii = _N(i, 2)
    Log(ii)
}
def main():
    i = 3.1415
    Log(i)
    ii = _N(i, 2)
    Log(ii)
void main() {
    auto i = 3.1415;
    Log(i);
    auto ii = _N(i, 2);
    Log(ii);
}

For example, _N(3.1415, 2) will delete the value after 3.1415 two decimal places and the function returns 3.14.

function main(){
    var i = 1300
    Log(i)
    var ii = _N(i, -3)
    // Check the logs and see that it is 1000
    Log(ii)
}
def main():
    i = 1300
    Log(i)
    ii = _N(i, -3)
    Log(ii)
void main() {
    auto i = 1300;
    Log(i);
    auto ii = _N(i, -3);
    Log(ii);
}

If you need to change all the N digits to the left of the decimal point to 0, you can write it like this:

The parameter precision can be a positive integer, negative integer.

{@fun/Trade/exchange.SetPrecision exchange.SetPrecision}

_C

Retry function for interface fault tolerance.

The return value of the callback function when it is executed. All types are supported by the system except logical false value and null value.

_C(pfn) _C(pfn, …args)

The parameter pfn is a function reference, which is a callback function. pfn true function Parameters to callback functions, there may be more than one parameter arg. The type and number of parameters arg depends on the parameters of the callback function. arg false string, number, bool, object, array, function, all types are supported by the system, such as null values

function main(){
    var ticker = _C(exchange.GetTicker)
    // Adjust _C() function retry interval to 2 seconds
    _CDelay(2000)
    var depth = _C(exchange.GetDepth)
    Log(ticker)
    Log(depth)
}
def main():
    ticker = _C(exchange.GetTicker)
    _CDelay(2000)
    depth = _C(exchange.GetDepth)
    Log(ticker)
    Log(depth)
void main() {
    auto ticker = _C(exchange.GetTicker);
    _CDelay(2000);
    auto depth = _C(exchange.GetDepth);
    Log(ticker);
    Log(depth);
}

For error-tolerant functions without parameters:

function main(){
    var records = _C(exchange.GetRecords, PERIOD_D1)
    Log(records)
}
def main():
    records = _C(exchange.GetRecords, PERIOD_D1)
    Log(records)
void main() {
    auto records = _C(exchange.GetRecords, PERIOD_D1);
    Log(records);
}

For functions with parameters that are error tolerant:

var test = function(a, b){
    var time = new Date().getTime() / 1000
    if(time % b == 3){
        Log("Eligible!", "#FF0000")
        return true
    }
    Log("Retry!", "#FF0000")
    return false
}            

function main(){
    var ret = _C(test, 1, 5)
    Log(ret)
}
import time
def test(a, b):
    ts = time.time()
    if ts % b == 3:
        Log("Eligible!", "#FF0000")
        return True
    Log("Retry!", "#FF0000")
    return False            

def main():
    ret = _C(test, 1, 5)
    Log(ret)
// C++ does not support fault tolerance for custom functions in this way

It can also be used for fault tolerance of custom functions:

The _C() function will keep calling the specified function until it returns successfully (the function referenced by the parameter pfn returns null or false when called will retry calling pfn). For example _C(exchange.GetTicker). The default retry interval is 3 seconds, you can call the _CDelay() function to set the retry interval. For example, _CDelay(1000) means to change the retry interval of the _C() function to 1 second. Fault tolerance can be done for, but is not limited to, the following functions:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions() All can be called by the _C() function for fault tolerance. The _C() function is not limited to the above listed function fault tolerance, the parameter pfn is a function reference rather than a function call. Note that it is _C(exchange.GetTicker), not _C(exchange.GetTicker()).

_Cross

Returns the number of intersection periods of the array arr1 and the array arr2.

The number of cross periods of the array arr1 and the array arr2. number

_Cross(arr1, arr2)

Elements are arrays of type number. arr1 true array Elements are arrays of type number. arr2 true array

// Fast line indicator
var arr1 = [1,2,3,4,5,6,8,8,9]
// Slow line indicator
var arr2 = [2,3,4,5,6,7,7,7,7]
function main(){
    Log("_Cross(arr1, arr2) : ", _Cross(arr1, arr2))
    Log("_Cross(arr2, arr1) : ", _Cross(arr2, arr1))
}
arr1 = [1,2,3,4,5,6,8,8,9]     
arr2 = [2,3,4,5,6,7,7,7,7]
def main():
    Log("_Cross(arr1, arr2) : ", _Cross(arr1, arr2))
    Log("_Cross(arr2, arr1) : ", _Cross(arr2, arr1))
void main() {
    vector<double> arr1 = {1,2,3,4,5,6,8,8,9};
    vector<double> arr2 = {2,3,4,5,6,7,7,7,7};
    Log("_Cross(arr1, arr2) : ", _Cross(arr1, arr2));
    Log("_Cross(arr2, arr1) : ", _Cross(arr2, arr1));
}

A set of data can be simulated to test the _Cross(Arr1, Arr2) function:

If the return value of the _Cross() function is a positive number, it indicates the period of upward penetration, if it’s a negative number, it indicates the period of downward penetration, 0 means the same as the current price. Specific instructions for use: Analysis and instructions for use about built-in function _Cross.

JSONParse

The function JSONParse() is used to parse JSON strings.

JSON object. object

JSONParse(s)

JSON string. s true string

function main() {
    let s1 = '{"num": 8754613216564987646512354656874651651358}'
    Log("JSON.parse:", JSON.parse(s1))    // JSON.parse: {"num":8.754613216564988e+39}
    Log("JSONParse:", JSONParse(s1))      // JSONParse:  {"num":"8754613216564987646512354656874651651358"}
    
    let s2 = '{"num": 123}'
    Log("JSON.parse:", JSON.parse(s2))    // JSON.parse: {"num":123}
    Log("JSONParse:", JSONParse(s2))      // JSONParse:  {"num":123}
}
import json

def main():
    s1 = '{"num": 8754613216564987646512354656874651651358}'
    Log("json.loads:", json.loads(s1))    # json.loads: map[num:8.754613216564987e+39]
    Log("JSONParse:", JSONParse(s1))      # JSONParse:  map[num:8754613216564987646512354656874651651358]
    
    s2 = '{"num": 123}'
    Log("json.loads:", json.loads(s2))    # json.loads: map[num:123]
    Log("JSONParse:", JSONParse(s2))      # JSONParse:  map[num:123]
void main() {
    auto s1 = "{\"num\":8754613216564987646512354656874651651358}";
    Log("json::parse:", json::parse(s1));
    // Log("JSONParse:", JSONParse(s1));   // The function is not supported.
    
    auto s2 = "{\"num\":123}";
    Log("json::parse:", json::parse(s2));
    // Log("JSONParse:", JSONParse(s2));   // The function is not supported.
}

JSON strings with large values can be parsed correctly, and it will parse large values as string types. The JSONParse() function is not supported in the backtest system.

Log

Log

Output logs.

Log(…msgs)

The parameter msg is the content of the output, and the parameter msg can be passed more than one. msg false string, number, bool, object, array, any type supported by the system such as null.

function main() {
    Log("msg1", "msg2", "msg3")
}
def main():
    Log("msg1", "msg2", "msg3")
void main() {
    Log("msg1", "msg2", "msg3");
}

Multiple msg parameters can be passed:

function main() {
    Log("Hello, FMZ Quant!@")
    Sleep(1000 * 5)
    // Add #ff0000 to the string to print the log in red and push the message
    Log("Hello, #ff0000@")
}
def main():
    Log("Hello, FMZ Quant!@")
    Sleep(1000 * 5)
    Log("Hello, #ff0000@")
void main() {
    Log("Hello, FMZ Quant!@");
    Sleep(1000 * 5);
    Log("Hello, #ff0000@");
}

It supports setting the color of output message, if we use setting color and push at the same time, we need to set color first and use @ character to set push last.

function main() {
    Log("`data:image/png;base64,AAAA`")
}
def main():
    Log("`data:image/png;base64,AAAA`")
void main() {
    Log("`data:image/png;base64,AAAA`");
}

The Log() function supports printing base64 encoded images, starting with ` and ending with `, for example:

import matplotlib.pyplot as plt 
def main(): 
    plt.plot([3,6,2,4,7,1]) 
    Log(plt)

The Log() function supports direct printing of Python's matplotlib.pyplot object. As long as the object contains the savefig method, it can be printed directly using the Log function, for example:

function main() {
    Log("[trans]中文|abc[/trans]")
}
def main():
    Log("[trans]中文|abc[/trans]")
void main() {
    Log("[trans]中文|abc[/trans]");
}

The Log() function supports language switching. The Log() function outputs text that will switch to the corresponding language automatically based on the language setting on the platform page, for example:

The Log() function outputs a log message in the log area of the live trading or backtesting system, and the log is saved in the live trading database when the live trading is running. The Log() function outputs a log message ending with the @ character, then this log will enter the message push queue. Push to the email address, WebHook address, etc. configured in the Push Settings of the current FMZ Quant Trading Platform account. Message pushing is not supported by Debugging Tools, backtesting system. There is a frequency limit for message push. The specific restriction rules are as follows: within a 20-second cycle of a live trading, only the last push message will be retained and pushed, and other messages will be filtered and not pushed (the push log output by the Log function will be printed and displayed normally in the log area). For WebHook push, you can use the service program written by Golang:

package main
import (
    "fmt"
    "net/http"
)            

func Handle (w http.ResponseWriter, r *http.Request) {
    defer func() {
        fmt.Println("req:", *r)
    }()
}            

func main () {
    fmt.Println("listen http://localhost:9090")
    http.HandleFunc("/data", Handle)
    http.ListenAndServe(":9090", nil)
}

Set WebHook in Push Settings: http://XXX.XX.XXX.XX:9090/data?data=Hello_FMZ. After running the written Golang service program, we start running the strategy live trading, the following is the strategy written in JavaScript language, the strategy runs by executing the Log() function and pushing the message:

function main() {
    Log("msg", "@")
}

A service program written in the Golang language receives the push and the service program prints the message:

listen http://localhost:9090
req: {GET /data?data=Hello_FMZ HTTP/1.1 1 1 map[User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.x.xxxx.xxx Safari/537.36] Accept-Encoding:[gzip]] {} <nil> 0 [] false 1XX.XX.X.XX:9090 map[] map[] <nil> map[] XXX.XX.XXX.XX:4xxx2 /data?data=Hello_FMZ <nil> <nil> <nil> 0xc420056300

{@fun/Log/LogReset LogReset}, {@fun/Log/LogVacuum LogVacuum}

LogProfit

Record the P&L value, print the P&L value and plot the return curve based on the P&L value.

LogProfit(profit) LogProfit(profit, …args)

The parameter profit is the revenue data, which is given by the design algorithm and calculation in the strategy. profit true number Extended parameter to output incidental information to the revenue log, arg parameters can be passed more than one. arg false string, number, bool, object, array, any type supported by the system such as null.

function main() {
    // Print 30 points on the earnings chart
    for(var i = 0; i < 30; i++) {
        LogProfit(i, '&')
        Sleep(500)
    }
}
def main():
    for i in range(30):
        LogProfit(i, '&')
        Sleep(500)
void main() {
    for(int i = 0; i < 30; i++) {
        LogProfit(i, '&');
        Sleep(500);
    }
}

The LogProfit function, if it ends with the character &, draws the revenue chart only and does not print the revenue log. For example:

{@fun/Log/LogProfitReset LogProfitReset}

LogProfitReset

Clear all revenue logs, revenue charts.

LogProfitReset() LogProfitReset(remain)

The remain parameter is used to specify the number of log entries (integer value) to keep. remain false number

function main() {
    // Print 30 points on the revenue chart, then reset and keep only the last 10 points
    for(var i = 0; i < 30; i++) {
        LogProfit(i)
        Sleep(500)
    }
    LogProfitReset(10)
}
def main():
    for i in range(30):
        LogProfit(i)
        Sleep(500)
    LogProfitReset(10)
void main() {
    for(int i = 0; i < 30; i++) {
        LogProfit(i);
        Sleep(500);
    }
    LogProfitReset(10);
}

{@fun/Log/LogProfit LogProfit}

LogStatus

Output information in the status bar of the backtesting system or live trading page.

LogStatus(…msgs)

The parameter msg is the content of the output, and the parameter msg can be passed more than one. msg false string, number, bool, object, array, any type supported by the system such as null.

function main() {
    LogStatus('This is a general status alert')
    LogStatus('This is a status alert in red font #ff0000')
    LogStatus('This is a multi-line status message \n I am the second line')
}
def main():
    LogStatus('This is a general status alert')
    LogStatus('This is a status alert in red font #ff0000')
    LogStatus('This is a multi-line status message \n I am the second line')
void main() {
    LogStatus("This is a general status alert");
    LogStatus("This is a status alert in red font #ff0000");
    LogStatus("This is a multi-line status message \n I am the second line");
}

It supports setting the color of the output content:

function main() {
    var table = {type: 'table', title: 'Position information', cols: ['Column 1', 'Column 2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]}
    // JSON serialization with the ` character on both sides, as a complex message format (support tables currently)
    LogStatus('`' + JSON.stringify(table) + '`')                    
    // Table information can also appear in multiple rows
    LogStatus('First line of message\n`' + JSON.stringify(table) + '`\n third line of message')
    // It supports multiple tables at the same time, will be displayed in a group with TAB
    LogStatus('`' + JSON.stringify([table, table]) + '`')
    
    // You can also construct a button in the form, and use the GetCommand strategy to receive the contents of the cmd attribute                                
    var table = { 
        type: 'table', 
        title: 'Position operations', 
        cols: ['Column 1', 'Column 2', 'Action'], 
        rows: [ 
            ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': 'Close out positions'}]
        ]
    }
    LogStatus('`' + JSON.stringify(table) + '`') 
    // Or construct a separate button
    LogStatus('`' + JSON.stringify({'type':'button', 'cmd': 'coverAll', 'name': 'Close out positions'}) + '`') 
    // Customizable button style (bootstrap's button attribute)
    LogStatus('`' + JSON.stringify({'type':'button', 'class': 'btn btn-xs btn-danger', 'cmd': 'coverAll', 'name': 'Close out positions'}) + '`')
}
import json
def main():
    table = {"type": "table", "title": "Position information", "cols": ["Column 1", "Column 2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}
    LogStatus('`' + json.dumps(table) + '`')
    LogStatus('First line of message\n`' + json.dumps(table) + '`\n third line of message')
    LogStatus('`' + json.dumps([table, table]) + '`')            

    table = {
        "type" : "table", 
        "title" : "Position operations", 
        "cols" : ["Column 1", "Column 2", "Action"], 
        "rows" : [
            ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "Close out positions"}]
        ] 
    }
    LogStatus('`' + json.dumps(table) + '`')
    LogStatus('`' + json.dumps({"type": "button", "cmd": "coverAll", "name": "Close out positions"}) + '`')
    LogStatus('`' + json.dumps({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "Close out positions"}) + '`')
void main() {
    json table = R"({"type": "table", "title": "Position information", "cols": ["Column 1", "Column 2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]})"_json;
    LogStatus("`" + table.dump() + "`");
    LogStatus("First line of message\n`" + table.dump() + "`\n third line of message");
    json arr = R"([])"_json;
    arr.push_back(table);
    arr.push_back(table);
    LogStatus("`" + arr.dump() + "`");            

    table = R"({
        "type" : "table", 
        "title" : "Position operations", 
        "cols" : ["Column 1", "Column 2", "Action"], 
        "rows" : [
            ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "Close out positions"}]
        ] 
    })"_json;
    LogStatus("`" + table.dump() + "`");
    LogStatus("`" + R"({"type": "button", "cmd": "coverAll", "name": "Close out positions"})"_json.dump() + "`");
    LogStatus("`" + R"({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "Close out positions"})"_json.dump() + "`");
}

Example of data output in the status bar:

function main() {
    var table = {
        type: "table",
        title: "status bar button style",
        cols: ["default", "original", "success", "info", "warning", "danger"], 
        rows: [
            [
                {"type":"button", "class": "btn btn-xs btn-default", "name": "default"},
                {"type":"button", "class": "btn btn-xs btn-primary", "name": "original"},
                {"type":"button", "class": "btn btn-xs btn-success", "name": "success"},
                {"type":"button", "class": "btn btn-xs btn-info", "name": "info"},
                {"type":"button", "class": "btn btn-xs btn-warning", "name": "warning"},
                {"type":"button", "class": "btn btn-xs btn-danger", "name": "danger"}
            ]
        ]
    }
    LogStatus("`" + JSON.stringify(table) + "`")
}
import json
def main():
    table = {
        "type": "table",
        "title": "status bar button style",
        "cols": ["default", "original", "success", "info", "warning", "danger"], 
        "rows": [
            [
                {"type":"button", "class": "btn btn-xs btn-default", "name": "default"},
                {"type":"button", "class": "btn btn-xs btn-primary", "name": "original"},
                {"type":"button", "class": "btn btn-xs btn-success", "name": "success"},
                {"type":"button", "class": "btn btn-xs btn-info", "name": "info"},
                {"type":"button", "class": "btn btn-xs btn-warning", "name": "warning"},
                {"type":"button", "class": "btn btn-xs btn-danger", "name": "danger"}
            ]
        ]
    }
    LogStatus("`" + json.dumps(table) + "`")
void main() {
    json table = R"({
        "type": "table",
        "title": "status bar button style",
        "cols": ["default", "original", "success", "info", "warning", "danger"], 
        "rows": [
            [
                {"type":"button", "class": "btn btn-xs btn-default", "name": "default"},
                {"type":"button", "class": "btn btn-xs btn-primary", "name": "original"},
                {"type":"button", "class": "btn btn-xs btn-success", "name": "success"},
                {"type":"button", "class": "btn btn-xs btn-info", "name": "info"},
                {"type":"button", "class": "btn btn-xs btn-warning", "name": "warning"},
                {"type":"button", "class": "btn btn-xs btn-danger", "name": "danger"}
            ]
        ]
    })"_json;
    LogStatus("`" + table.dump() + "`");
}

It supports for designing button controls in the status bar (old button structure):

function main() {
    var table = {
        type: "table",
        title: "Status bar button disable, description function test",
        cols: ["Column 1", "Column 2", "Column 3"], 
        rows: []
    }
    var button1 = {"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button"}
    var button2 = {"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button, set to disabled", "disabled": true}
    var button3 = {"type": "button", "name": "button3", "cmd": "button3", "description": "This is the third button, set to enable", "disabled": false}
    table.rows.push([button1, button2, button3])
    LogStatus("`" + JSON.stringify(table) + "`")
}
import json
def main():
    table = {
        "type": "table",
        "title": "Status bar button disable, description function test",
        "cols": ["Column 1", "Column 2", "Column 3"], 
        "rows": []
    }
    button1 = {"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button"}
    button2 = {"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button, set to disabled", "disabled": True}
    button3 = {"type": "button", "name": "button3", "cmd": "button3", "description": "This is the third button, set to enable", "disabled": False}
    table["rows"].append([button1, button2, button3])
    LogStatus("`" + json.dumps(table) + "`")
void main() {
    json table = R"({
        "type": "table",
        "title": "Status bar button disable, description function test",
        "cols": ["Column 1", "Column 2", "Column 3"], 
        "rows": []
    })"_json;
    json button1 = R"({"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button"})"_json;
    json button2 = R"({"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button, set to disabled", "disabled": true})"_json;
    json button3 = R"({"type": "button", "name": "button3", "cmd": "button3", "description": "This is the third button, set to enable", "disabled": false})"_json;
    json arr = R"([])"_json;
    arr.push_back(button1);
    arr.push_back(button2);
    arr.push_back(button3);
    table["rows"].push_back(arr);
    LogStatus("`" + table.dump() + "`");
}

Set the disabled, description function of the status bar button (old button structure):

function test1() {
    Log("Calling custom functions")
}            

function main() {
    while (true) {
        var table = {
            type: 'table',
            title: 'operation',
            cols: ['column1', 'column2', 'Action'],
            rows: [
                ['a', '1', {
                    'type': 'button',                       
                    'cmd': "CoverAll",                      
                    'name': 'Close out positions'                           
                }],
                ['b', '1', {
                    'type': 'button',
                    'cmd': 10,                              
                    'name': 'Send values'
                }],
                ['c', '1', {
                    'type': 'button',
                    'cmd': _D(),                          
                    'name': 'Calling functions'
                }],
                ['d', '1', {
                    'type': 'button',
                    'cmd': 'test1',       
                    'name': 'Calling custom functions'
                }]
            ]
        }
        LogStatus(_D(), "\n", '`' + JSON.stringify(table) + '`')            

        var str_cmd = GetCommand()
        if (str_cmd) {
            Log("Received interaction data str_cmd:", "type:", typeof(str_cmd), "value:", str_cmd)
            if(str_cmd == "test1") {
                test1()
            }
        }            

        Sleep(500)
    }
}
import json
def test1():
    Log("Calling custom functions")            

def main():
    while True:
        table = {
            "type": "table", 
            "title": "operation", 
            "cols": ["column1", "column2", "Action"],
            "rows": [
                ["a", "1", {
                    "type": "button", 
                    "cmd": "CoverAll",
                    "name": "Close out positions"
                }],
                ["b", "1", {
                    "type": "button",
                    "cmd": 10,
                    "name": "Send values" 
                }], 
                ["c", "1", {
                    "type": "button",
                    "cmd": _D(),
                    "name": "Calling functions" 
                }],
                ["d", "1", {
                    "type": "button",
                    "cmd": "test1",
                    "name": "Calling custom functions" 
                }]
            ]
        }            

        LogStatus(_D(), "\n", "`" + json.dumps(table) + "`")
        str_cmd = GetCommand()
        if str_cmd:
            Log("Received interaction data str_cmd:", "type:", typeof(str_cmd), "value:", str_cmd)
            if str_cmd == "test1":
                test1()
        Sleep(500)
void test1() {
    Log("Calling custom functions");
}            

void main() {
    while(true) {
        json table = R"({
            "type": "table", 
            "title": "operation", 
            "cols": ["column1", "column2", "Action"],
            "rows": [
                ["a", "1", {
                    "type": "button", 
                    "cmd": "CoverAll",
                    "name": "Close out positions"
                }],
                ["b", "1", {
                    "type": "button",
                    "cmd": 10,
                    "name": "Send values" 
                }], 
                ["c", "1", {
                    "type": "button",
                    "cmd": "",
                    "name": "Calling functions" 
                }],
                ["d", "1", {
                    "type": "button",
                    "cmd": "test1",
                    "name": "Calling custom functions" 
                }]
            ]
        })"_json;
        table["rows"][2][2]["cmd"] = _D();
        LogStatus(_D(), "\n", "`" + table.dump() + "`");
        auto str_cmd = GetCommand();
        if(str_cmd != "") {
            Log("Received interaction data str_cmd:", "type:", typeof(str_cmd), "value:", str_cmd);
            if(str_cmd == "test1") {
                test1();
            }
        }
        Sleep(500);
    }
}

In combination with the GetCommand() function, construct the status bar button interaction function (old button structure):

function main() {
    var tbl = {
        type: "table",
        title: "operation",
        cols: ["column1", "column2"],
        rows: [
            ["Open position operation", {"type": "button", "cmd": "open", "name": "open position", "input": {"name": "number of open positions", "type": "number", "defValue": 1}}],
            ["Close position operation", {"type": "button", "cmd": "coverAll", "name": "close all positions"}]
        ] 
    }            

    LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)
        }
        Sleep(1000)
    }
}
import json            

def main():
    tbl = {
        "type": "table", 
        "title": "operation", 
        "cols": ["column1", "column2"],
        "rows": [
            ["Open position operation", {"type": "button", "cmd": "open", "name": "open position", "input": {"name": "number of open positions", "type": "number", "defValue": 1}}],
            ["Close position operation", {"type": "button", "cmd": "coverAll", "name": "close all positions"}]
        ]
    }            

    LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`")
    while True:
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
        Sleep(1000)
void main() {
    json tbl = R"({
        "type": "table", 
        "title": "operation", 
        "cols": ["column1", "column2"],
        "rows": [
            ["Open position operation", {"type": "button", "cmd": "open", "name": "open position", "input": {"name": "number of open positions", "type": "number", "defValue": 1}}],
            ["Close position operation", {"type": "button", "cmd": "coverAll", "name": "close all positions"}]
        ]
    })"_json;            

    LogStatus(_D(), "\n", "`" + tbl.dump() + "`");
    while(true) {
        auto cmd = GetCommand();
        if(cmd != "") {
            Log("cmd:", cmd);
        }
        Sleep(1000);
    }
}

Input data is also supported when constructing status bar buttons for interaction, and the interaction commands are captured by the GetCommand() function eventually. Add input items (old button structure) to the data structure of the button control in the status bar, for example, adding "input": {"name": "number of open positions", "type": "number", "defValue": 1} to {"type": "button", "cmd": "open", "name": "open position"} will cause a popup with an input box control to appear when the button is clicked (the default value in the input box is 1, which is the data set by defValue). You can enter a data to be sent along with the button command. For example, when the following test code runs, after clicking the "open position’’ button, a popup window with an input box pops up. Enter 111 in the input box and click “OK”. The GetCommand() function will then capture the message: open:111.

function main() {
    var tbl = {
        type: "table",
        title: "Demonstrate grouping button control",
        cols: ["operation"],
        rows: []
    }

    // Creating a grouping button control structure
    var groupBtn = {
        type: "button",
        cmd: "open",
        name: "open positions",
        group: [
            {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "market order|pending order"},
            {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100},
            {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100},
            {"name": "boolean", "description": "yes/no|boolean", "type": "boolean", "defValue": true}
        ]
    }

    // test button 1
    var testBtn1 = {"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button."}
    var testBtn2 = {"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button.", "input": {"name": "number of positions opened", "type": "number", "defValue": 1}}

    // Add groupBtn to tbl
    tbl.rows.push([groupBtn])
    // It supports multiple buttons in a cell of a status bar table, i.e. the data in a cell is an array of button structures: [testBtn1, testBtn2].
    tbl.rows.push([[testBtn1, testBtn2]])

    while (true) {
        LogStatus("`" + JSON.stringify(tbl) + "`", "\n", "The grouping button control can also be set directly on the status bar in addition to being set on the status bar form:", "`" + JSON.stringify(groupBtn) + "`")
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)
        }
        Sleep(5000)
    }
}
import json

def main():
    tbl = {
        "type": "table",
        "title": "Demonstrate grouping button control",
        "cols": ["operation"],
        "rows": []
    }

    groupBtn = {
        "type": "button",
        "cmd": "open",
        "name": "open positions",
        "group": [
            {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "market order|pending order"},
            {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100},
            {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100},
            {"name": "boolean", "description": "yes/no|boolean", "type": "boolean", "defValue": True}
        ]
    }

    testBtn1 = {"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button."}
    testBtn2 = {"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button.", "input": {"name": "number of positions opened", "type": "number", "defValue": 1}}

    tbl["rows"].append([groupBtn])
    tbl["rows"].append([[testBtn1, testBtn2]])

    while True:
        LogStatus("`" + json.dumps(tbl) + "`", "\n", "The grouping button control can also be set directly on the status bar in addition to being set on the status bar form:", "`" + json.dumps(groupBtn) + "`")
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
        Sleep(5000)
void main() {
    json tbl = R"({
        "type": "table", 
        "title": "Demonstrate grouping button control", 
        "cols": ["operation"],
        "rows": []
    })"_json;

    json groupBtn = R"({
        "type": "button", 
        "name": "open positions", 
        "cmd": "open", 
        "group": [
            {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "market order|pending order"},
            {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100},
            {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100},
            {"name": "boolean", "description": "yes/no|boolean", "type": "boolean", "defValue": true}
    ]})"_json;

    json testBtn1 = R"({"type": "button", "name": "button1", "cmd": "button1", "description": "This is the first button."})"_json;
    json testBtn2 = R"({"type": "button", "name": "button2", "cmd": "button2", "description": "This is the second button.", "input": {"name": "number of positions opened", "type": "number", "defValue": 1}})"_json;
    
    tbl["rows"].push_back({groupBtn});
    tbl["rows"].push_back({{testBtn1, testBtn2}});
    
    while(true) {
        LogStatus("`" + tbl.dump() + "`", "\n", "The grouping button control can also be set directly on the status bar in addition to being set on the status bar form:", "`" + groupBtn.dump() + "`");
        auto cmd = GetCommand();
        if(cmd != "") {
            Log("cmd:", cmd);
        }
        Sleep(5000);
    }
}

It supports for grouped button controls (old button structure), functionally consistent with status bar buttons that support data entry (set by using the “input” field). Interactive commands are ultimately captured by the GetCommand() function. The difference is that with the "group" field setting, when the button is clicked to trigger the interaction, the dialog that pops up on the page contains a set of group of input controls set up to enter a group of data at once. A few points to note about the "group" field in the structure of the status bar button control and the group button control:

  • The type property in group supports only the following four types, and the defValue property is the default value. “selected”: A dropdown box control that uses the | symbol to separate each option in a dropdown box as it is set. “number”: Numeric input box control. “string”: String input box control. “boolean”: Checkbox control, checked for (Boolean) true, unchecked for (Boolean) false.
  • Controls on interactive input support dependency settings: For example, in the following example: "name": "tradePrice@orderType==1" setting, which makes the tradePrice input control available only when the orderType drop-down control is selected as a Pending Order.
  • Bilingual control name support for interactive inputs For example, in the following example: description : order type setting, use| symbols to separate the content of the description in Chinese and English.
  • name, description in group and name, description in the button structure do not have the same definitions even though they have the same field names. The definition of name in group is also different from the definition of name in input.
  • When the group button control is triggered, the interaction content is sent in the format of the button’s cmd field value and the group field’s associated data, such as the output of the Log("cmd:", cmd) statement in the following example test: cmd: open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true}, i.e., what is returned by the GetCommand() function when an interaction occurs: open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true}.
  • The type property of the button control supports only: "button". Button controls that support input data, i.e. controls with the input property set, the type property in the configuration information of the input field supports multiple control types. Refer to the following examples:
function main() {
    // Status bar button control (set input field to implement) testBtn1 button triggered by the page in the drop-down box control using the options field to set options, using the defValue field to set the default options. This is different from the other examples in this chapter, which use defValue to set the options directly.
    var testBtn1 = {
        type: "button",
        name: "testBtn1",
        cmd: "cmdTestBtn1",
        input: {name: "testBtn1ComboBox", type: "selected", options: ["A", "B"], defValue: 1}
    }

    /* 
      Status bar button control (set input field implementation) testBtn2 button triggered by the page in the drop-down box control using the options field to set the options, options field in the options field not only supports the string,
      the use of the ```{text: "description", value: "value"}``` structure is also supported. Use the defValue field to set the default option, which can be multiple choice (multiple choice via array structure). Multiple choice requires setting the additional field multiple to a true value.
    */
    var testBtn2 = {
        type: "button", 
        name: "testBtn2",
        cmd: "cmdTestBtn2",
        input: {
            name: "testBtn2MultiComboBox", 
            type: "selected", 
            description: "Implementing dropdown box multi-selection", 
            options: [{text: "Option A", value: "A"}, {text: "Option B", value: "B"}, {text: "Option C", value: "C"}],
            defValue: ["A", "C"],
            multiple: true
        }
    }

    // Status bar grouping button control (set group field implementation) testBtn3 button triggered by the page in the drop-down box control using the options field to set options, also supports the direct use of defValue set options.
    var testBtn3 = {
        type: "button",                     
        name: "testBtn3",
        cmd: "cmdTestBtn3", 
        group: [
            {name: "comboBox1", label: "labelComboBox1", description: "Dropdown box 1", type: "selected", defValue: 1, options: ["A", "B"]}, 
            {name: "comboBox2", label: "labelComboBox2", description: "Dropdown box 2", type: "selected", defValue: "A|B"}, 
            {name: "comboBox3", label: "labelComboBox3", description: "Dropdown box 3", type: "selected", defValue: [0, 2], multiple: true, options: ["A", "B", "C"]}, 
            {
                name: "comboBox4", 
                label: "labelComboBox4", 
                description: "Dropdown box 4", 
                type: "selected", 
                defValue: ["A", "C"], 
                multiple: true, 
                options: [{text: "Option A", value: "A"}, {text: "Option B", value: "B"}, {text: "Option C", value: "C"}, {text: "Option D", value: "D"}]
            }
        ]
    }
    while (true) {
        LogStatus("`" + JSON.stringify(testBtn1) + "`\n", "`" + JSON.stringify(testBtn2) + "`\n", "`" + JSON.stringify(testBtn3) + "`\n")
        var cmd = GetCommand()
        if (cmd) {
            Log(cmd)
        }
        Sleep(5000)
    }
}
import json

def main():
    testBtn1 = {
        "type": "button",
        "name": "testBtn1",
        "cmd": "cmdTestBtn1",
        "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1}
    }

    testBtn2 = {
        "type": "button", 
        "name": "testBtn2",
        "cmd": "cmdTestBtn2",
        "input": {
            "name": "testBtn2MultiComboBox", 
            "type": "selected", 
            "description": "Implementing dropdown box multi-selection", 
            "options": [{"text": "Option A", "value": "A"}, {"text": "Option B", "value": "B"}, {"text": "Option C", "value": "C"}],
            "defValue": ["A", "C"],
            "multiple": True
        }
    }

    testBtn3 = {
        "type": "button",                     
        "name": "testBtn3",
        "cmd": "cmdTestBtn3", 
        "group": [
            {"name": "comboBox1", "label": "labelComboBox1", "description": "Dropdown box 1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, 
            {"name": "comboBox2", "label": "labelComboBox2", "description": "Dropdown box 2", "type": "selected", "defValue": "A|B"}, 
            {"name": "comboBox3", "label": "labelComboBox3", "description": "Dropdown box 3", "type": "selected", "defValue": [0, 2], "multiple": True, "options": ["A", "B", "C"]}, 
            {
                "name": "comboBox4", 
                "label": "labelComboBox4", 
                "description": "Dropdown box 4", 
                "type": "selected", 
                "defValue": ["A", "C"], 
                "multiple": True, 
                "options": [{"text": "Option A", "value": "A"}, {"text": "Option B", "value": "B"}, {"text": "Option C", "value": "C"}, {"text": "Option D", "value": "D"}]
            }
        ]
    }

    while True:
        LogStatus("`" + json.dumps(testBtn1) + "`\n", "`" + json.dumps(testBtn2) + "`\n", "`" + json.dumps(testBtn3) + "`\n")
        cmd = GetCommand()
        if cmd:
            Log(cmd)
        Sleep(5000)
void main() {
    json testBtn1 = R"({
        "type": "button",
        "name": "testBtn1",
        "cmd": "cmdTestBtn1",
        "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1}
    })"_json;
    
    json testBtn2 = R"({
        "type": "button", 
        "name": "testBtn2",
        "cmd": "cmdTestBtn2",
        "input": {
            "name": "testBtn2MultiComboBox", 
            "type": "selected", 
            "description": "Implementing dropdown box multi-selection", 
            "options": [{"text": "Option A", "value": "A"}, {"text": "Option B", "value": "B"}, {"text": "Option C", "value": "C"}],
            "defValue": ["A", "C"],
            "multiple": true
        }
    })"_json;
    
    json testBtn3 = R"({
        "type": "button",                     
        "name": "testBtn3",
        "cmd": "cmdTestBtn3", 
        "group": [
            {"name": "comboBox1", "label": "labelComboBox1", "description": "Dropdown box 1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, 
            {"name": "comboBox2", "label": "labelComboBox2", "description": "Dropdown box 2", "type": "selected", "defValue": "A|B"}, 
            {"name": "comboBox3", "label": "labelComboBox3", "description": "Dropdown box 3", "type": "selected", "defValue": [0, 2], "multiple": true, "options": ["A", "B", "C"]}, 
            {
                "name": "comboBox4", 
                "label": "labelComboBox4", 
                "description": "Dropdown box 4", 
                "type": "selected", 
                "defValue": ["A", "C"], 
                "multiple": true, 
                "options": [{"text": "Option A", "value": "A"}, {"text": "Option B", "value": "B"}, {"text": "Option C", "value": "C"}, {"text": "Option D", "value": "D"}]
            }
        ]
    })"_json;
    
    while (true) {
        LogStatus("`" + testBtn1.dump() + "`\n", "`" + testBtn2.dump() + "`\n", "`" + testBtn3.dump() + "`\n");
        auto cmd = GetCommand();
        if (cmd != "") {
            Log(cmd);
        }
        Sleep(5000);
    }
}

When the status bar group button control (implemented by setting the group field) and the status bar button control (implemented by setting the input field) are clicked to trigger interaction (old button structure), the drop-down box control in the dialog box that pops up on the page also supports multiple selections. The following example demonstrates how to design a drop-down box control with multiple selection options:

var symbols = ["BTC_USDT.swap", "ETH_USDT.swap", "LTC_USDT.swap", "BNB_USDT.swap", "SOL_USDT.swap"]

function createBtn(tmp, group) {
    var btn = JSON.parse(JSON.stringify(tmp))

    _.each(group, function(eleByGroup) {
        btn["group"].unshift(eleByGroup)
    })

    return btn
}

function main() {
    var arrManager = []

    _.each(symbols, function(symbol) {
        arrManager.push({
            "symbol": symbol,
        })
    })

    // Btn
    var tmpBtnOpen = {
        "type": "button",
        "cmd": "open",
        "name": "Open a position and place an order",
        "group": [{
            "type": "selected",
            "name": "tradeType",
            "label": "Order type",
            "description": "Market order, limit order",
            "default": 0,
            "group": "Trading setup",
            "settings": {
                "options": ["Market order", "Limit order"],
                "required": true,
            }
        }, {
            "type": "selected",
            "name": "direction",
            "label": "Trading direction",
            "description": "Buy, sell",
            "default": "buy",
            "group": "Trading setup",
            "settings": {
                "render": "segment",
                "required": true,
                "options": [{"name": "buy", "value": "buy"}, {"name": "sell", "value": "sell"}],
            }
        }, {
            "type": "number",
            "name": "price",
            "label": "price",
            "description": "The price of the order",
            "group": "Trading setup",
            "filter": "tradeType==1",
            "settings": {
                "required": true,
            }
        }, {
            "type": "number",
            "name": "amount",
            "label": "Order quantity",
            "description": "Order quantity",
            "group": "Trading setup",
            "settings": {
                "required": true,
            }
        }],
    }

    while (true) {
        var tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []}

        _.each(arrManager, function(m) {
            var btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "Trading instruments", "default": m["symbol"], "settings": {"required": true}}])
            tbl["rows"].push([m["symbol"], btnOpen])
        })

        var cmd = GetCommand()
        if (cmd) {
            Log("Receive interaction:", cmd)

            // Parsing interaction messages: open:{"symbol":"LTC_USDT.swap","tradeType":0,"direction":"buy","amount":111}
            // According to the first colon: the previous instruction determines which button template triggers the message
            var arrCmd = cmd.split(":", 2)
            if (arrCmd[0] == "open") {
                var msg = JSON.parse(cmd.slice(5))
                Log("Trading instruments:", msg["symbol"], ", Trading direction:", msg["direction"], ", Order type:", msg["tradeType"] == 0 ? "Market order" : "Limit order", msg["tradeType"] == 0 ? ", Order price: current market price" : ", Order price:" + msg["price"], ", Order quantity:", msg["amount"])
            }
        }

        LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}
import json

symbols = ["BTC_USDT.swap", "ETH_USDT.swap", "LTC_USDT.swap", "BNB_USDT.swap", "SOL_USDT.swap"]

def createBtn(tmp, group):
    btn = json.loads(json.dumps(tmp))
    for eleByGroup in group:
        btn["group"].insert(0, eleByGroup)
    return btn

def main():
    arrManager = []

    for symbol in symbols:
        arrManager.append({"symbol": symbol})

    # Btn
    tmpBtnOpen = {
        "type": "button",
        "cmd": "open",
        "name": "Open a position and place an order",
        "group": [{
            "type": "selected",
            "name": "tradeType",
            "label": "Order type",
            "description": "Market order, limit order",
            "default": 0,
            "group": "Trading setup",
            "settings": {
                "options": ["Market order", "Limit order"],
                "required": True,
            }
        }, {
            "type": "selected",
            "name": "direction",
            "label": "Trading direction",
            "description": "Buy, sell",
            "default": "buy",
            "group": "Trading Setup",
            "settings": {
                "render": "segment",
                "required": True,
                "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}],
            }
        }, {
            "type": "number",
            "name": "price",
            "label": "price",
            "description": "The price of the order",
            "group": "Trading Setup",
            "filter": "tradeType==1",
            "settings": {
                "required": True,
            }
        }, {
            "type": "number",
            "name": "amount",
            "label": "Order quantity",
            "description": "Order quantity",
            "group": "Trading Setup",
            "settings": {
                "required": True,
            }
        }],
    }

    while True:
        tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []}
        for m in arrManager:
            btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "交易品种", "default": m["symbol"], "settings": {"required": True}}])
            tbl["rows"].append([m["symbol"], btnOpen])

        cmd = GetCommand()

        if cmd != "" and cmd != None:
            Log("Receive interaction:", cmd) 

            # Parsing interaction messages: open:{"symbol":"LTC_USDT.swap","tradeType":0,"direction":"buy","amount":111}
            # According to the first colon: the previous instruction determines which button template triggers the message
            arrCmd = cmd.split(":")
            if arrCmd[0] == "open":
                msg = json.loads(cmd[5:])
                Log("Trading instruments:", msg["symbol"], ", Trading direction:", msg["direction"], ", Order type:", "Market order" if msg["tradeType"] == 0 else "Limit order", ", Order price: current market price" if msg["tradeType"] == 0 else ", Order price:" + str(msg["price"]), ", Order quantity:", msg["amount"])
        
        # Output status bar information
        LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`")
        Sleep(1000)
// Omit...

Use the latest button structure to construct the buttons in the status bar table. When clicking the button to trigger the interaction, a multi-control pop-up window will pop up. For more details, please refer to: User Guide - Interactive Controls in the Status Bar.

function main() {
    var table = { 
        type: 'table', 
        title: 'position operation', 
        cols: ['column1', 'column2', 'Action'], 
        rows: [ 
            ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': 'close positions'}]
        ]
    } 
    var ticker = exchange.GetTicker()
    // Add a row of data, merge the first and second cells, and output the ticker variable in the merged cell
    table.rows.push([{body : JSON.stringify(ticker), colspan : 2}, "abc"])    
    LogStatus('`' + JSON.stringify(table) + '`')
}
import json
def main():
    table = {
        "type" : "table",
        "title" : "position operation",
        "cols" : ["column1", "column2", "Action"],
        "rows" : [
            ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "close positions"}]
        ]
    }
    ticker = exchange.GetTicker()
    table["rows"].append([{"body": json.dumps(ticker), "colspan": 2}, "abc"])
    LogStatus("`" + json.dumps(table) + "`")
void main() {
    json table = R"({
        "type" : "table",
        "title" : "position operation",
        "cols" : ["column1", "column2", "Action"],
        "rows" : [
            ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "close positions"}]
        ]
    })"_json;            

    auto ticker = exchange.GetTicker();
    json jsonTicker = R"({"Buy": 0, "Sell": 0, "High": 0, "Low": 0, "Volume": 0, "Last": 0, "Time": 0})"_json;
    jsonTicker["Buy"] = ticker.Buy;
    jsonTicker["Sell"] = ticker.Sell;
    jsonTicker["Last"] = ticker.Last;
    jsonTicker["Volume"] = ticker.Volume;
    jsonTicker["Time"] = ticker.Time;
    jsonTicker["High"] = ticker.High;
    jsonTicker["Low"] = ticker.Low;            

    json arr = R"([{"body": {}, "colspan": 2}, "abc"])"_json;
    arr[0]["body"] = jsonTicker;
    table["rows"].push_back(arr);
    LogStatus("`" + table.dump() + "`");
}

Horizontal merge of cells within the table drawn by the LogStatus() function:

function main() {
    var table = { 
        type: 'table', 
        title: 'table demo', 
        cols: ['columnA', 'columnB', 'columnC'], 
        rows: [ 
            ['A1', 'B1', {'type':'button', 'cmd': 'coverAll', 'name': 'C1'}]
        ]
    }             

    var ticker = exchange.GetTicker()
    var name = exchange.GetName()            

    table.rows.push([{body : "A2 + B2:" + JSON.stringify(ticker), colspan : 2}, "C2"])
    table.rows.push([{body : "A3 + A4 + A5:" + name, rowspan : 3}, "B3", "C3"])
    // A3 is merged by the first cell in the previous row
    table.rows.push(["B4", "C4"])
    // A2 is merged by the first cell of the previous row
    table.rows.push(["B5", "C5"])                                            
    table.rows.push(["A6", "B6", "C6"])
    LogStatus('`' + JSON.stringify(table) + '`')
}
import json
def main():
    table = {
        "type" : "table", 
        "title" : "table demo", 
        "cols" : ["columnA", "columnB", "columnC"], 
        "rows" : [
            ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}]
        ]
    }
    
    ticker = exchange.GetTicker()
    name = exchange.GetName()
    
    table["rows"].append([{"body": "A2 + B2:" + json.dumps(ticker), "colspan": 2}, "C2"])
    table["rows"].append([{"body": "A3 + A4 + A5:" + name, "rowspan": 3}, "B3", "C3"])
    table["rows"].append(["B4", "C4"])
    table["rows"].append(["B5", "C5"])
    table["rows"].append(["A6", "B6", "C6"])
    LogStatus("`" + json.dumps(table) + "`")
void main() {
    json table = R"({
        "type" : "table", 
        "title" : "table demo", 
        "cols" : ["columnA", "columnB", "columnC"], 
        "rows" : [
            ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}]
        ]
    })"_json;
    // For testing purposes, the code is short and easy to read, and the constructed data is used here
    json jsonTicker = R"({"High": 0, "Low": 0, "Buy": 0, "Sell": 0, "Last": 0, "Time": 0, "Volume": 0})"_json;
    auto name = exchange.GetName();
    json arr1 = R"([{"body": "", "colspan": 2}, "C2"])"_json;
    arr1[0]["body"] = "A2 + B2:" + jsonTicker.dump();
    json arr2 = R"([{"body": "", "rowspan": 3}, "B3", "C3"])"_json;
    arr2[0]["body"] = "A3 + A4 + A5:" + name;
    table["rows"].push_back(arr1);
    table["rows"].push_back(arr2);
    table["rows"].push_back(R"(["B4", "C4"])"_json);
    table["rows"].push_back(R"(["B5", "C5"])"_json);
    table["rows"].push_back(R"(["A6", "B6", "C6"])"_json);
    LogStatus("`" + table.dump() + "`");
}

Vertically merge the cells in the table drawn by the LogStatus() function:

function main() {
    var table1 = {type: 'table', title: 'table1', cols: ['column1', 'column2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]}
    var table2 = {type: 'table', title: 'table2', cols: ['column1', 'column2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]}
    LogStatus('`' + JSON.stringify([table1, table2]) + '`')
}
import json
def main():
    table1 = {"type": "table", "title": "table1", "cols": ["column1", "column2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]}
    table2 = {"type": "table", "title": "table2", "cols": ["column1", "column2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]}
    LogStatus("`" + json.dumps([table1, table2]) + "`")
void main() {
    json table1 = R"({"type": "table", "title": "table1", "cols": ["column1", "column2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json;
    json table2 = R"({"type": "table", "title": "table2", "cols": ["column1", "column2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json;
    json arr = R"([])"_json;
    arr.push_back(table1);
    arr.push_back(table2);
    LogStatus("`" + arr.dump() + "`");
}

Status bar table pagination display:

function main(){
    var tab1 = {
        type : "table",
        title : "table1",
        cols : ["1", "2"],
        rows : []
    }
    var tab2 = {
        type : "table",
        title : "table2",
        cols : ["1", "2", "3"],
        rows : []
    }
    var tab3 = {
        type : "table",
        title : "table3",
        cols : ["A", "B", "C"],
        rows : []
    }            

    tab1.rows.push(["jack", "lucy"])
    tab2.rows.push(["A", "B", "C"])
    tab3.rows.push(["A", "B", "C"])            

    LogStatus('`' + JSON.stringify(tab1) + '`\n' + 
        '`' + JSON.stringify(tab2) + '`\n' +
        '`' + JSON.stringify(tab3) + '`')
  
    Log("exit")
}
import json
def main():
    tab1 = {
        "type": "table", 
        "title": "table1", 
        "cols": ["1", "2"], 
        "rows": []
    }
    tab2 = {
        "type": "table", 
        "title": "table2", 
        "cols": ["1", "2", "3"], 
        "rows": []
    }
    tab3 = {
        "type": "table", 
        "title": "table3", 
        "cols": ["A", "B", "C"], 
        "rows": []
    }            

    tab1["rows"].append(["jack", "lucy"])
    tab2["rows"].append(["A", "B", "C"])
    tab3["rows"].append(["A", "B", "C"])
    LogStatus("`" + json.dumps(tab1) + "`\n" + 
        "`" + json.dumps(tab2) + "`\n" + 
        "`" + json.dumps(tab3) + "`")
void main() {
    json tab1 = R"({
        "type": "table", 
        "title": "table1", 
        "cols": ["1", "2"], 
        "rows": []
    })"_json;
    json tab2 = R"({
        "type": "table", 
        "title": "table2", 
        "cols": ["1", "2", "3"], 
        "rows": []
    })"_json;
    json tab3 = R"({
        "type": "table", 
        "title": "table3", 
        "cols": ["A", "B", "C"], 
        "rows": []
    })"_json;
    tab1["rows"].push_back(R"(["jack", "lucy"])"_json);
    tab2["rows"].push_back(R"(["A", "B", "C"])"_json);
    tab3["rows"].push_back(R"(["A", "B", "C"])"_json);
    LogStatus("`" + tab1.dump() + "`\n" + 
        "`" + tab2.dump() + "`\n" +
        "`" + tab3.dump() + "`");
}

In addition to displaying tables in pages, multiple tables can also be displayed in a top-down order:

function main() {
    var tbl = {
        type : "table",
        title : "test scroll",
        scroll : "auto",
        cols : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", 
            "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"],
        rows : []
    }

    for (var i = 1 ; i < 100 ; i++) {
        tbl.rows.push([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, 
            "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i])
    }
    
    LogStatus("`" + JSON.stringify(tbl) + "`")
}
import json

def main():
    tbl = {
        "type" : "table",
        "title" : "test scroll",
        "scroll" : "auto",
        "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", 
            "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"],
        "rows" : []
    }

    for index in range(1, 100):
        i = str(index)
        tbl["rows"].append([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, 
            "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i])
    
    LogStatus("`" + json.dumps(tbl) + "`")
void main() {
    json table = R"({
        "type" : "table",
        "title" : "test scroll",
        "scroll" : "auto",
        "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", 
            "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"],
        "rows" : []
    })"_json;

    for (int index = 1; index < 100; ++index) {
        std::string i = std::to_string(index);
        table["rows"].push_back({i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i,
            "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i});
    }

    LogStatus("`" + table.dump() + "`");
}

Support to set horizontal and vertical scroll mode of status bar table. Set scroll attribute to "auto", when the number of vertical rows of the status bar table exceeds 20 rows, the content will be scrolled. When the number of horizontal columns exceeds the page display range, the scroll attribute can be used to alleviate the lagging problem of writing a large amount of data in the status bar during live trading. Refer to the following test example:

The information output from the LogStatus() function when the live trading is running is not saved to the live trading database, but it updates the current live trading’s status bar content only. The LogStatus() function supports printing base64 encoded images, starting with ` and ending with `. For example: LogStatus("`data:image/png;base64,AAAA`"). The LogStatus() function supports passing matplotlib.pyplot objects directly into Python, as long as the object contains the savefig method, it can be passed as a parameter to the LogStatus() function, for example:

import matplotlib.pyplot as plt 
def main():
    plt.plot([3,6,2,4,7,1])
    LogStatus(plt) 

When the strategy is running live trading, if you go through the history on the live trading page, the status bar will sleep and stop updating. Only the status bar data will be refreshed when the log is on the first page. It supports outputting base64 encoded images in the status bar, and it also supports outputting base64 encoded images in the table displayed in the status bar. Since the string data of the encoded image is generally very long, the sample code is not shown.

{@fun/Global/GetCommand GetCommand}

EnableLog

Turn on or off logging of order information.

EnableLog(enable)

If the enable parameter is set to a false value, e.g. false, the order log (i.e. the log generated by functions like exchange.Buy()) is not printed and is not written to the database of the live trading. enable true bool

function main() {
    EnableLog(false)
}
def main():
    EnableLog(False)
void main() {
    EnableLog(false);
}

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

Chart

Customize the chart drawing function.

Chart object. object

Chart(options)

The options parameter is the chart configuration. The Chart() function parameter options is a JSON serializable HighStocks parameter for Highcharts.StockChart. An additional __isStock attribute is added over the native parameter, and if __isStock:false is specified, it is displayed as a normal chart. If the __isStock attribute is set to a false value e.g. false, i.e. the chart used is a Highcharts chart. If the __isStock attribute is set to a true value e.g. true, i.e. the chart used is a Highstocks chart (by default __isStock is true e.g. true). You can query the HighStocks chart library. options true object, object array

function main() {
    var cfgA = {
        extension: {
            layout: 'single', // No grouping, display separately, default to group 'group'
            height: 300, // Specify the height
        },
        title: {
            text: 'handicap chart'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: 'buy one',
            data: [],
        }, {
            name: 'sell one',
            data: [],
        }]
    }
    var cfgB = {
        title: {
            text: 'spread chart'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: 'spread',
            type: 'column',
            data: [],
        }]
    }            

    var cfgC = {
        __isStock: false,
        title: {
            text: 'pie chart'
        },
        series: [{
            type: 'pie',
            name: 'one',
            data: [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]  // Instead of updating the initial data with the add function, the sequence can be updated by changing the chart configuration directly.
        }]
    };
    var cfgD = {
        extension: {
            layout: 'single',
            col: 8, // Specify the cell value for the width, the total value is 12
            height: '300px',
        },
        title: {
            text: 'handicap chart'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: 'buy one',
            data: [],
        }, {
            name: 'sell one',
            data: [],
        }]
    }
    var cfgE = {
        __isStock: false,
        extension: {
            layout: 'single',
            col: 4,
            height: '300px',
        },
        title: {
            text: 'pie chart2'
        },
        series: [{
            type: 'pie',
            name: 'one',
            data: [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]
        }]
    };            

    var chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE]);
    chart.reset()
        // Add a number of points to the pie chart, add can only update the data points added by add, built-in data points cannot be updated later.
    chart.add(3, {
        name: "ZZ",
        y: Math.random() * 100
    });
    while (true) {
        Sleep(1000)
        var ticker = exchange.GetTicker()
        if (!ticker) {
            continue;
        }
        var diff = ticker.Sell - ticker.Buy
        cfgA.subtitle = {
            text: 'buy one ' + ticker.Buy + ', sell one ' + ticker.Sell,
        };
        cfgB.subtitle = {
            text: 'spread ' + diff,
        };            

        chart.add([0, [new Date().getTime(), ticker.Buy]]);
        chart.add([1, [new Date().getTime(), ticker.Sell]]);
        // Equivalent to updating the first data series of the second chart
        chart.add([2, [new Date().getTime(), diff]]);
        chart.add(4, [new Date().getTime(), ticker.Buy]);
        chart.add(5, [new Date().getTime(), ticker.Buy]);
        cfgC.series[0].data[0][1] = Math.random() * 100;
        cfgE.series[0].data[0][1] = Math.random() * 100;
        // update is actually the same as resetting the chart's configuration
        chart.update([cfgA, cfgB, cfgC, cfgD, cfgE]);
    }
}            
import random
import time
def main():
    cfgA = {
        "extension" : {
            "layout" : "single", 
            "height" : 300,
            "col" : 8
        }, 
        "title" : {
            "text" : "handicap chart"
        },
        "xAxis" : {
            "type" : "datetime" 
        }, 
        "series" : [{
            "name" : "buy one",
            "data" : []
        }, {
            "name" : "sell one", 
            "data" : []
        }]
    }                

    cfgB = {
        "title" : {
            "text" : "spread chart"
        }, 
        "xAxis" : {
            "type" : "datetime",
        }, 
        "series" : [{
            "name" : "spread", 
            "type" : "column", 
            "data" : []
        }]
    }                

    cfgC = {
        "__isStock" : False,
        "title" : {
            "text" : "pie chart"
        }, 
        "series" : [{
            "type" : "pie", 
            "name" : "one", 
            "data" : [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]
        }]
    }                

    cfgD = {
        "extension" : {
            "layout" : "single",
            "col" : 8,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "handicap chart"
        }, 
        "series" : [{
            "name" : "buy one", 
            "data" : []
        }, {
            "name" : "sell one",
            "data" : []
        }]
    }                

    cfgE = {
        "__isStock" : False, 
        "extension" : {
            "layout" : "single", 
            "col" : 4,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "pie chart2"
        },
        "series" : [{
            "type" : "pie",
            "name" : "one", 
            "data" : [
                ["A", 25], 
                ["B", 25], 
                ["C", 25], 
                ["D", 25]
            ]
        }]
    }
    
    chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE])
    chart.reset()
    chart.add(3, {
        "name" : "ZZ",
        "y" : random.random() * 100
    })
    
    while True:
        Sleep(1000)
        ticker = exchange.GetTicker()
        if not ticker :
            continue
        diff = ticker["Sell"] - ticker["Buy"]
        cfgA["subtitle"] = {
            "text" : "buy one" + str(ticker["Buy"]) + "sell one" + str(ticker["Sell"])
        }
        cfgB["subtitle"] = {
            "text" : "spread " + str(diff)
        }
        
        chart.add(0, [time.time() * 1000, ticker["Buy"]])
        chart.add(1, [time.time() * 1000, ticker["Sell"]])
        chart.add(2, [time.time() * 1000, diff])
        chart.add(4, [time.time() * 1000, ticker["Buy"]])
        chart.add(5, [time.time() * 1000, ticker["Buy"]])
        cfgC["series"][0]["data"][0][1] = random.random() * 100
        cfgE["series"][0]["data"][0][1] = random.random() * 100
void main() {
    json cfgA = R"({
        "extension" : {
            "layout" : "single", 
            "height" : 300,
            "col" : 8
        }, 
        "title" : {
            "text" : "handicap chart"
        },
        "xAxis" : {
            "type" : "datetime" 
        }, 
        "series" : [{
            "name" : "buy one",
            "data" : []
        }, {
            "name" : "sell one", 
            "data" : []
        }]
    })"_json;                

    json cfgB = R"({
        "title" : {
            "text" : "spread chart"
        }, 
        "xAxis" : {
            "type" : "datetime"
        }, 
        "series" : [{
            "name" : "spread", 
            "type" : "column", 
            "data" : []
        }]
    })"_json;    
    
    json cfgC = R"({
        "__isStock" : false,
        "title" : {
            "text" : "pie chart"
        }, 
        "series" : [{
            "type" : "pie", 
            "name" : "one", 
            "data" : [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25]
            ]
        }]
    })"_json;    
    
    json cfgD = R"({
        "extension" : {
            "layout" : "single",
            "col" : 8,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "handicap chart"
        }, 
        "series" : [{
            "name" : "buy one", 
            "data" : []
        }, {
            "name" : "sell one",
            "data" : []
        }]
    })"_json;    
    
    json cfgE = R"({
        "__isStock" : false, 
        "extension" : {
            "layout" : "single", 
            "col" : 4,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "pie chart2"
        },
        "series" : [{
            "type" : "pie",
            "name" : "one", 
            "data" : [
                ["A", 25], 
                ["B", 25], 
                ["C", 25], 
                ["D", 25]
            ]
        }]
    })"_json;            

    auto chart = Chart({cfgA, cfgB, cfgC, cfgD, cfgE});
    chart.reset();
    json zz = R"({
        "name" : "ZZ", 
        "y" : 0
    })"_json;
    zz["y"] = rand() % 100;
    chart.add(3, zz);
    
    while(true) {
        Sleep(1000);
        auto ticker = exchange.GetTicker();
        if(!ticker.Valid) {
            continue;
        }
        auto diff = ticker.Sell - ticker.Buy;
        json cfgASubTitle = R"({"text" : ""})"_json;
        cfgASubTitle["text"] = format("buy one %f , sell one %f", ticker.Buy, ticker.Sell);
        cfgA["subtitle"] = cfgASubTitle;
        
        json cfgBSubTitle = R"({"text" : ""})"_json;
        cfgBSubTitle["text"] = format("spread %f", diff);
        cfgB["subtitle"] = cfgBSubTitle;            

        chart.add(0, {Unix() * 1000, ticker.Buy});
        chart.add(1, {Unix() * 1000, ticker.Sell});
        chart.add(2, {Unix() * 1000, diff});
        chart.add(4, {Unix() * 1000, ticker.Buy});
        chart.add(5, {Unix() * 1000, ticker.Buy});
        cfgC["series"][0]["data"][0][1] = rand() % 100;
        cfgE["series"][0]["data"][0][1] = rand() % 100;
        chart.update({cfgA, cfgB, cfgC, cfgD, cfgE});
    }
}

Multi-chart drawing configuration:

  • extension.layout attribute If the attribute is set with the value “single”, the charts will not be stacked (not displayed as tabs), but will be displayed separately (tiled).
  • extension.height attribute The attribute is used to set the height of the chart, either as a numeric value, or as “300px”.
  • extension.col attribute The attribute is used to set the width of the chart, the page width is divided into 12 cells, set 8 ,that is, the chart occupies 8 cells width.
// This chart is an object in the JavaScript language, and before using the Chart function, we need to declare an object variable chart to configure the chart. var chart = {                                           
    // This field marks whether the chart is a general chart or not, if you are interested, you can change it to false and run it.
    __isStock: true,                                    
    // Scaling tool
    tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},    
    // title
    title : { text : 'spread analysis chart'},                       
    // selection range
    rangeSelector: {                                    
        buttons:  [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
        selected: 0,
        inputEnabled: false
    },
    // Coordinate axis horizontal axis that is: x-axis, the current setting type is: time
    xAxis: { type: 'datetime'},                         
    // Coordinate axis vertical axis that is: y-axis, default value adjusted with the size of the data
    yAxis : {                                           
        // title
        title: {text: 'spread'},                           
        // Whether to enable the right vertical axis
        opposite: false                                 
    },
    // Data series, this sttribute holds the individual data series (lines, K-charts, labels, etc...)
    series : [                                          
        // The index is 0, and the data array holds the data of the index series
        {name : "line1", id : "line1,buy1Price", data : []},                          
        // Index is 1, set dashStyle:'shortdash' i.e.: set the dashed line
        {name : "line2", id : "line2,lastPrice", dashStyle : 'shortdash', data : []}  
    ]
} function main(){
    // Call the Chart function to initialize the chart
    var ObjChart = Chart(chart)         
    // Clear out
    ObjChart.reset()                      
    while(true){
        // Gets the timestamp of this poll, i.e. a millisecond timestamp. It's used to determine the position of the X-axis written to the chart.
        var nowTime = new Date().getTime()
        // Get the ticker data
        var ticker = _C(exchange.GetTicker)
        // Get buy one price from the return value of the ticker data
        var buy1Price = ticker.Buy    
        // To obtain the final transaction price, we add 1 in order not to overlap the 2 lines
        var lastPrice = ticker.Last + 1
        // Data sequence with timestamp as X-value and buy one price as Y-value passed into index 0
        ObjChart.add(0, [nowTime, buy1Price])
        // ditto
        ObjChart.add(1, [nowTime, lastPrice])
        Sleep(2000)
    }
}```
```python
import time
chart = {
    "__isStock" : True,
    "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"},  
    "title" : {"text" : "spread analysis chart"}, 
    "rangeSelector" : {
        "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], 
        "selected": 0,
        "inputEnabled": False 
    }, 
    "xAxis": {"type": "datetime"}, 
    "yAxis": {
        "title": {"text": "spread"},
        "opposite": False
    },
    "series": [{
        "name": "line1", "id": "line1,buy1Price", "data": []
    }, {
        "name": "line2", "id": "line2,lastPrice", "dashStyle": "shortdash", "data": []
    }]
}
def main():
    ObjChart = Chart(chart)
    ObjChart.reset()
    while True:
        nowTime = time.time() * 1000
        ticker = exchange.GetTicker()
        buy1Price = ticker["Buy"]
        lastPrice = ticker["Last"] + 1
        ObjChart.add(0, [nowTime, buy1Price])
        ObjChart.add(1, [nowTime, lastPrice])
        Sleep(2000)
void main() {
    // When writing strategies in C++, try not to declare global variables that are not of the base type, so the chart configuration object is declared inside the main function.
    json chart = R"({
        "__isStock" : true,
        "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"},  
        "title" : {"text" : "spread analysis chart"}, 
        "rangeSelector" : {
            "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], 
            "selected": 0,
            "inputEnabled": false 
        }, 
        "xAxis": {"type": "datetime"}, 
        "yAxis": {
            "title": {"text": "spread"},
            "opposite": false
        },
        "series": [{
            "name": "line1", "id": "line1,buy1Price", "data": []
        }, {
            "name": "line2", "id": "line2,lastPrice", "dashStyle": "shortdash", "data": []
        }]
    })"_json;
    auto ObjChart = Chart(chart);
    ObjChart.reset();
    while(true) {
        auto nowTime = Unix() * 1000;
        auto ticker = exchange.GetTicker();
        auto buy1Price = ticker.Buy;
        auto lastPrice = ticker.Last + 1.0;
        ObjChart.add(0, {nowTime, buy1Price});
        ObjChart.add(1, {nowTime, lastPrice});
        Sleep(2000);
    }
}

Example of a simple drawing:

// Objects used to initialize the chart
var chart = {                                   
    // Chart title
    title: {text: "line value triggers the plotLines value"},   
    // Y-axis related settings
    yAxis: {                                    
        // A horizontal line perpendicular to the Y-axis, used as a trigger line, is a structural array that can set multiple trigger lines
        plotLines: [{                           
            // The value of the trigger line, how much it set, this line will be displayed in the corresponding value position
            value: 0,                           
            // Set the color of the trigger line
            color: 'red',                       
            // Width
            width: 2,                           
            // Displaying labels
            label: {                            
                // Label text
                text: 'Trigger value',                  
                // Centered label position
                align: 'center'                 
            }
        }]
    },
    // X-axis related settings, here the setting type is time axis
    xAxis: {type: "datetime"},                  
    series: [
        {name: "sin", type: "spline", data: []},
        // This is an important data series, you can set multiple data series, according to the array index control
        {name: "cos", type: "spline", data: []}
    ]  
}
function main(){
    // Circumference
    var pi = 3.1415926535897
    // Variables for recording timestamps
    var time = 0                   
    // Angle
    var angle = 0                        
    // Coordinate y values for receiving sine and cosine values
    var y = 0          
    // Call the API interface to initialize the chart with the chart object
    var objChart = Chart(chart)        
    // Initially, clear the chart
    objChart.reset()
    // Set the value of the trigger line to 1
    chart.yAxis.plotLines[0].value = 1
    // Loop
    while(true){                          
        // Get the timestamp of the current moment
        time = new Date().getTime() 
        // Angle increases by 5 degrees every 500ms and calculates the sine value
        y = Math.sin(angle * 2 * pi / 360)
        // Write the calculated y value to the data series of the corresponding index of the chart, the first parameter of the add function is the specified data series index
        objChart.add(0, [time, y])
        // Calculate the cosine value
        y = Math.cos(angle * 2 * pi / 360)
        objChart.add(1, [time, y])
        // Increase by 5 degrees
        angle += 5
        // Pause for 5 seconds to avoid drawing too often and growing data too fast
        Sleep(5000)     
    }
}
import math
import time
chart = {
    "title": {"text": "line value triggers the plotLines value"}, 
    "yAxis": {
        "plotLines": [{
            "value": 0,
            "color": "red",
            "width": 2,
            "label": {
                "text": "trigger value", 
                "align": "center"
            }
        }]
    },
    "xAxis": {"type": "datetime"},
    "series": [{"name": "sin", "type": "spline", "data": []},
               {"name": "cos", "type": "spline", "data": []}]
}
def main():
    pi = 3.1415926535897
    ts = 0
    angle = 0
    y = 0
    objChart = Chart(chart)
    objChart.reset()
    chart["yAxis"]["plotLines"][0]["value"] = 1
    while True:
        ts = time.time() * 1000
        y = math.sin(angle * 2 * pi / 360)
        objChart.add(0, [ts, y])
        y = math.cos(angle * 2 * pi / 360)
        objChart.add(1, [ts, y])
        angle += 5
        Sleep(5000)
void main() {
    json chart = R"({
        "title": {"text": "line value triggers the plotLines value"}, 
        "yAxis": {
            "plotLines": [{
                "value": 0,
                "color": "red",
                "width": 2,
                "label": {
                    "text": "trigger value", 
                    "align": "center"
                }
            }]
        },
        "xAxis": {"type": "datetime"},
        "series": [{"name": "sin", "type": "spline", "data": []},
                   {"name": "cos", "type": "spline", "data": []}]     
    })"_json;            

    auto pi = 3.1415926535897;
    auto ts = 0;
    auto angle = 0.0;
    auto y = 0.0;
    auto objChart = Chart(chart);
    objChart.reset();
    chart["yAxis"]["plotLines"][0]["value"] = 1;
    while(true) {
        ts = Unix() * 1000;
        y = sin(angle * 2 * pi / 360);
        objChart.add(0, {ts, y});
        y = cos(angle * 2 * pi / 360);
        objChart.add(1, {ts, y});
        angle += 5;
        Sleep(5000);
    }
}

Example of trigonometric curve drawing:

/*backtest
start: 2020-03-11 00:00:00
end: 2020-04-09 23:59:00
period: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/            

var chartCfg = {
    subtitle: {
        text: "subtitle",
    },
    yAxis: [{
        height: "40%",
        lineWidth: 2,
        title: {
            text: 'PnL',
        },
        tickPixelInterval: 20,
        minorGridLineWidth: 1,
        minorTickWidth: 0,
        opposite: true,
        labels: {
            align: "right",
            x: -3,
        }
    }, {
        title: {
            text: 'Profit',
        },
        top: "42%",
        height: "18%",
        offset: 0,
        lineWidth: 2
    }, {
        title: {
            text: 'Vol',
        },
        top: '62%',
        height: '18%',
        offset: 0,
        lineWidth: 2
    }, {
        title: {
            text: 'Asset',
        },
        top: '82%',
        height: '18%',
        offset: 0,
        lineWidth: 2
    }],
    series: [{
        name: 'PnL',
        data: [],
        id: 'primary',
        tooltip: {
            xDateFormat: '%Y-%m-%d %H:%M:%S'
        },
        yAxis: 0
    }, {
        type: 'column',
        lineWidth: 2,
        name: 'Profit',
        data: [],
        yAxis: 1,
    }, {
        type: 'column',
        name: 'Trade',
        data: [],
        yAxis: 2
    }, {
        type: 'area',
        step: true,
        lineWidth: 0,
        name: 'Long',
        data: [],
        yAxis: 2
    }, {
        type: 'area',
        step: true,
        lineWidth: 0,
        name: 'Short',
        data: [],
        yAxis: 2
    }, {
        type: 'line',
        step: true,
        color: '#5b4b00',
        name: 'Asset',
        data: [],
        yAxis: 3
    }, {
        type: 'pie',
        innerSize: '70%',
        name: 'Random',
        data: [],
        center: ['3%', '6%'],
        size: '15%',
        dataLabels: {
            enabled: false
        },
        startAngle: -90,
        endAngle: 90,
    }],
};            

function main() {
    let c = Chart(chartCfg);
    let preTicker = null;
    while (true) {
        let t = exchange.GetTicker();
        
        c.add(0, [t.Time, t.Last]); // PnL
        c.add(1, [t.Time, preTicker ? t.Last - preTicker.Last : 0]); // profit
        let r = Math.random();
        var pos = parseInt(t.Time/86400);
        c.add(2, [t.Time, pos/2]); // Vol
        c.add(3, [t.Time, r > 0.8 ? pos : null]); // Long
        c.add(4, [t.Time, r < 0.8 ? -pos : null]); // Short
        c.add(5, [t.Time, Math.random() * 100]); // Asset
        // update pie
        chartCfg.series[chartCfg.series.length-1].data = [
            ["A", Math.random()*100],
            ["B", Math.random()*100],
         ];
        c.update(chartCfg)
        preTicker = t;
    }
}
'''backtest
start: 2020-03-11 00:00:00
end: 2020-04-09 23:59:00
period: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
'''            

import random            

chartCfg = {
    "subtitle": {
        "text": "subtitle"
    },
    "yAxis": [{
        "height": "40%",
        "lineWidth": 2,
        "title": {
            "text": 'PnL'
        },
        "tickPixelInterval": 20,
        "minorGridLineWidth": 1,
        "minorTickWidth": 0,
        "opposite": True,
        "labels": {
            "align": "right",
            "x": -3
        }
    }, {
        "title": {
            "text": 'Profit'
        },
        "top": "42%",
        "height": "18%",
        "offset": 0,
        "lineWidth": 2
    }, {
        "title": {
            "text": 'Vol'
        },
        "top": '62%',
        "height": '18%',
        "offset": 0,
        "lineWidth": 2
    }, {
        "title": {
            "text": 'Asset'
        },
        "top": '82%',
        "height": '18%',
        "offset": 0,
        "lineWidth": 2
    }],
    "series": [{
        "name": 'PnL',
        "data": [],
        "id": 'primary',
        "tooltip": {
            "xDateFormat": '%Y-%m-%d %H:%M:%S'
        },
        "yAxis": 0
    }, {
        "type": 'column',
        "lineWidth": 2,
        "name": 'Profit',
        "data": [],
        "yAxis": 1
    }, {
        "type": 'column',
        "name": 'Trade',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'area',
        "step": True,
        "lineWidth": 0,
        "name": 'Long',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'area',
        "step": True,
        "lineWidth": 0,
        "name": 'Short',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'line',
        "step": True,
        "color": '#5b4b00',
        "name": 'Asset',
        "data": [],
        "yAxis": 3
    }, {
        "type": 'pie',
        "innerSize": '70%',
        "name": 'Random',
        "data": [],
        "center": ['3%', '6%'],
        "size": '15%',
        "dataLabels": {
            "enabled": False
        },
        "startAngle": -90,
        "endAngle": 90
    }]
}            

def main():
    c = Chart(chartCfg)
    preTicker = None
    while True:
        t = exchange.GetTicker()
        c.add(0, [t["Time"], t["Last"]])
        profit = t["Last"] - preTicker["Last"] if preTicker else 0
        c.add(1, [t["Time"], profit])
        r = random.random()
        pos = t["Time"] / 86400
        c.add(2, [t["Time"], pos / 2])
        long = pos if r > 0.8 else None
        c.add(3, [t["Time"], long])
        short = -pos if r < 0.8 else None
        c.add(4, [t["Time"], short])
        c.add(5, [t["Time"], random.random() * 100])            

        # update pie
        chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [
            ["A", random.random() * 100], 
            ["B", random.random() * 100]
        ]
        c.update(chartCfg)
        preTicker = t
/*backtest
start: 2020-03-11 00:00:00
end: 2020-04-09 23:59:00
period: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/            

void main() {
    json chartCfg = R"({
        "subtitle": {
            "text": "subtitle"
        },
        "yAxis": [{
            "height": "40%",
            "lineWidth": 2,
            "title": {
                "text": "PnL"
            },
            "tickPixelInterval": 20,
            "minorGridLineWidth": 1,
            "minorTickWidth": 0,
            "opposite": true,
            "labels": {
                "align": "right",
                "x": -3
            }
        }, {
            "title": {
                "text": "Profit"
            },
            "top": "42%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }, {
            "title": {
                "text": "Vol"
            },
            "top": "62%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }, {
            "title": {
                "text": "Asset"
            },
            "top": "82%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }],
        "series": [{
            "name": "PnL",
            "data": [],
            "id": "primary",
            "tooltip": {
                "xDateFormat": "%Y-%m-%d %H:%M:%S"
            },
            "yAxis": 0
        }, {
            "type": "column",
            "lineWidth": 2,
            "name": "Profit",
            "data": [],
            "yAxis": 1
        }, {
            "type": "column",
            "name": "Trade",
            "data": [],
            "yAxis": 2
        }, {
            "type": "area",
            "step": true,
            "lineWidth": 0,
            "name": "Long",
            "data": [],
            "yAxis": 2
        }, {
            "type": "area",
            "step": true,
            "lineWidth": 0,
            "name": "Short",
            "data": [],
            "yAxis": 2
        }, {
            "type": "line",
            "step": true,
            "color": "#5b4b00",
            "name": "Asset",
            "data": [],
            "yAxis": 3
        }, {
            "type": "pie",
            "innerSize": "70%",
            "name": "Random",
            "data": [],
            "center": ["3%", "6%"],
            "size": "15%",
            "dataLabels": {
                "enabled": false
            },
            "startAngle": -90,
            "endAngle": 90
        }]
    })"_json;
    
    Chart c = Chart(chartCfg);
    Ticker preTicker;
    while(true) {
        auto t = exchange.GetTicker();
        c.add(0, {t.Time, t.Last});
        auto profit = preTicker.Valid ? t.Last - preTicker.Last : 0;
        c.add(1, {t.Time, profit});    
        auto r = rand() % 100;
        auto pos = t.Time / 86400.0;
        c.add(2, {t.Time, pos / 2.0});
        auto longPos = r > 0.8 ? pos : NULL;
        c.add(3, {t.Time, longPos});
        auto shortPos = r < 0.8 ? -pos : NULL;
        c.add(4, {t.Time, shortPos});
        c.add(5, {t.Time, rand() % 100});
        
        // update pie 
        json pie = R"([["A", 0], ["B", 0]])"_json;
        pie[0][1] = rand() % 100;
        pie[1][1] = rand() % 100;
        chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie;
        
        c.update(chartCfg);
        preTicker = t;
    }
}            

Complex examples of using hybrid charts:

// update pie
chartCfg.series[chartCfg.series.length-1].data = [
    ["A", Math.random()*100],
    ["B", Math.random()*100],
];
c.update(chartCfg)
# update pie
chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [
    ["A", random.random() * 100], 
    ["B", random.random() * 100]
]
c.update(chartCfg)
// update pie 
json pie = R"([["A", 0], ["B", 0]])"_json;
pie[0][1] = rand() % 100;
pie[1][1] = rand() % 100;
chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie;
c.update(chartCfg);

Charts of type pie are charts without a timeline, and you need to update the chart configuration directly when updating the data. For example, the code in the above example updates the chart using c.update(chartCfg) after updating the data, as follows:

The Chart() function returns a chart object that has 4 methods: add(), reset(), update(), del().

    1. The update() method: The update() method can update the chart configuration information. The parameter of this method is the Chart configuration object (JSON).
    1. The del() method: The del() method can delete the data series of the specified index based on the passed series parameter.
    1. The add() method: The add() method can write data to the chart, with the following parameters in order:
    • series: used to set the data series index, which is an integer.
    • data: used to set the specific data to be written, it is an array.
    • index (optional): used to set the data index, it’s an integer. Specify the specific index position of the modified data, and it supports negative numbers, the setting is -1 refers to the last data in the data set. For example, when drawing a line, modify the data on the last point of the line: chart.add(0, [1574993606000, 13.5], -1), that is, change the data on the penultimate first point of the chart series[0].data. The index parameter is not set, which means that the data is added to the last point of the current data series.
    1. The reset() method: The reset() method is used to empty the chart data. The reset() method can take a parameter remain to specify the number of entries to keep. No parameter remain is passed to clear all data.

{@fun/Log/KLineChart KLineChart}

KLineChart

The function is used for custom drawing at strategy runtime using a drawing method similar to the Pine language.

The chart object. The KLineChart() function returns a chart object with several methods, among which you need to pay attention to begin() and close(). The drawing operation must start with a begin() function call and end with a close() function call when traversing over the KLine data to perform the drawing operation. object

KLineChart(options)

The options parameter is the chart configuration. options true object, object array

function main() {
    // Call the KLineChart function to create a chart control object c
    let c = KLineChart({
        overlay: true
    })            

    // Use the Spot Exchange object test to get K-line data. If you use the futures exchange object test, you need to set up the contract first.
    let bars = exchange.GetRecords()
    if (!bars) {
        return
    }            
    
    // Execute the drawing operation by traversing over the K-line data. The drawing operation must start with the ```c.begin(bar)``` function call and end with the ```c.close()``` function call.
    bars.forEach(function(bar, index) {
        c.begin(bar)
        c.barcolor(bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.2)')
        if (bar.Close > bar.Open) {
            c.bgcolor('rgba(0, 255, 0, 0.5)')
        }
        let h = c.plot(bar.High, 'high')
        let l = c.plot(bar.Low, 'low')            

        c.fill(h, l, {
            color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)'
        })
        c.hline(bar.High)
        c.plotarrow(bar.Close - bar.Open)
        c.plotshape(bar.Low, {
            style: 'diamond'
        })
        c.plotchar(bar.Close, {
            char: 'X'
        })
        c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)
        if (bar.Close > bar.Open) {
            // long/short/closelong/closeshort
            c.signal("long", bar.High, 1.5)
        } else if (bar.Close < bar.Open) {
            c.signal("closelong", bar.Low, 1.5)
        }
        c.close()
    })
}
def main():
    # Call the KLineChart function to create a chart control object c
    c = KLineChart({
        "overlay": True
    })            

    # Use the Spot Exchange object test to get K-line data. If you use the futures exchange object test, you need to set up the contract first.
    bars = exchange.GetRecords()
    if not bars:
        return            

    for bar in bars:
        c.begin(bar)
        c.barcolor('rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(0, 0, 0, 0.2)')
        if bar.Close > bar.Open:
            c.bgcolor('rgba(0, 255, 0, 0.5)')            

        h = c.plot(bar.High, 'high')
        l = c.plot(bar.Low, 'low')            

        c.fill(h, l, 'rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(255, 0, 0, 0.2)')
        c.hline(bar.High)
        c.plotarrow(bar.Close - bar.Open)        
        c.plotshape(bar.Low, style = 'diamond')
        c.plotchar(bar.Close, char = 'X')
        c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)
        if bar.Close > bar.Open:
            # long/short/closelong/closeshort
            c.signal("long", bar.High, 1.5)
        elif bar.Close < bar.Open:
            c.signal("closelong", bar.Low, 1.5)            

        c.close()
// Not supported for now

If a chart control object is necessary to draw in the strategy custom drawing area, use the KLineChart() function to create the object. The parameter to the KLineChart() function is a chart configuration structure, the one used in the reference code is simple: {overlay: true}. This chart configuration structure only sets the drawing content to be output on the main chart. If overlay is set to a false value, e.g. false, the content on the chart is output on the secondary chart. If you need to specify a drawing function to draw on the main chart, you can also specify the parameter overlay as a true value in the specific function call, for example: true.

c.barcolor(bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.2)')   // Use the example illustrated in the reference code in this example, without further ado
c.barcolor('rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(0, 0, 0, 0.2)')
//  Not supported for now

The drawing interface functions of the Pine language supported in the drawing operation are: barcolor, which sets the K-line color.

barcolor(color, offset, editable, show_last, title, display) display parameters are optional: “none”, “all”

c.bgcolor('rgba(0, 255, 0, 0.5)')
c.bgcolor('rgba(0, 255, 0, 0.5)')
// Not supported for now

bgcolor, fills the background of the K-line with the specified color.

bgcolor(color, offset, editable, show_last, title, display, overlay) display parameters are optional: “none”, “all”

c.plot(bar.High, 'high')
c.plot(bar.Open < bar.Close ? NaN : bar.Close, "Close", {style: "linebr"})  // Support for drawing discontinuous data lines
h = c.plot(bar.High, 'high')
h = c.plot(None if bar.Open < bar.Close else bar.Close, "Close", style = "linebr")  # Support for drawing discontinuous data lines
// Not supported for now

plot, plot a series of data on a chart.

plot(series, title, color, linewidth, style, trackprice, histbase, offset, join, editable, show_last, display) style parameters are optional: “stepline_diamond”, “stepline”, “cross”, “areabr”, “area”, “circles”, “columns”, “histogram”, “linebr”, “line” display parameters are optional: “none”, “all”

let h = c.plot(bar.High, 'high')
let l = c.plot(bar.Low, 'low')

c.fill(h, l, {color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)'})
h = c.plot(bar.High, 'high')
l = c.plot(bar.Low, 'low')

c.fill(h, l, color = 'rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(255, 0, 0, 0.2)'})
// Not supported for now

fill, fill the background between two plots or hline with the provided colors.

fill(hline1, hline2, color, title, editable, fillgaps, display) display parameters are optional: “none”, “all”

Since the JavaScript language cannot specify incoming parameters based on the names of function formal parameters, to solve this problem, you can use a {key: value} structure to specify the parameters to be passed to a certain formal parameter name. For example, the reference code uses {color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0, 0.2)'} specifies the color parameter of the fill function. If you need to specify multiple parameters with consecutive form parameter names, you can use {key1: value1, key2: value2, key3: value3}. For example, in this example, an additional title parameter is specified: {color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0, 0.2)', title: 'fill'}. For the color value, you can set it with 'rgba(255, 0, 0, 0, 0.2)' or with '#FF0000'.

c.hline(bar.High)
c.hline(bar.High)
// Not supported for now

hline, the horizontal line is presented at a given fixed price level.

hline(price, title, color, linestyle, linewidth, editable, display) linestyle parameters are optional: “dashed”, “dotted”, “solid” display parameters are optional: “none”, “all”

c.plotarrow(bar.Close - bar.Open)
c.plotarrow(bar.Close - bar.Open)
// Not supported for now

plotarrow, plot up and down arrows on the chart.

plotarrow(series, title, colorup, colordown, offset, minheight, maxheight, editable, show_last, display) display parameters are optional: “none”, “all”

c.plotshape(bar.Low, {style: 'diamond'})
c.plotshape(bar.Low, style = 'diamond')
// Not supported for now

plotshape, draw visual shapes on the chart.

plotshape(series, title, style, location, color, offset, text, textcolor, editable, size, show_last, display) style parameters are optional: “diamond”, “square”, “label_down”, “label_up”, “arrow_down”, “arrow_up”, “circle”, “flag”, “triangle_down”, “triangle_up”, “cross”, “xcross” location parameters are optional: “abovebar”, “belowbar”, “top”, “bottom”, “absolute” size parameters are optional: “10px”, “14px”, “20px”, “40px”, “80px”, comparing size.tiny, size.small, size.normal, size.large, size.huge in Pine language. size.auto is size.small. display parameters are optional: “none”, “all”

c.plotchar(bar.Close, {char: 'X'})
c.plotchar(bar.Close, char = 'X')
// Not supported for now

plotchar, draw visual shapes on the chart using any given Unicode character.

plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display) location parameters are optional: “abovebar”, “belowbar”, “top”, “bottom”, “absolute” size parameters are optional: “10px”, “14px”, “20px”, “40px”, “80px”, comparing size.tiny, size.small, size.normal, size.large, size.huge in Pine language. size.auto is size.small. display parameters are optional: “none”, “all”

c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)
c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)
// Not supported for now

plotcandle, plot a K-line chart on a chart.

plotcandle(open, high, low, close, title, color, wickcolor, editable, show_last, bordercolor, display) display parameters are optional: “none”, “all”

c.signal("long", bar.High, 1.5)
c.signal("long", bar.High, 1.5)
// Not supported for now

signal, a function not available on the Pine language, is used to draw buy and sell signals here.

signal(direction, price, qty, id) The parameter ‘‘long’’ is passed in to indicate the direction of the transaction, you can choose ‘‘long’’, ‘‘closelong’’, ‘‘short’’, ‘‘closeshort’’. The parameter bar.High is the Y-axis position of the marker signal. The passed parameter 1.5 indicates the number of transactions of the signal. The fourth parameter can be passed to replace the default text content drawn, and the default text of the drawn signal marker is the direction of the transaction, e.g. ‘‘closelong’’.

c.reset()
c.reset()
// Not supported for now

reset, a function not available on the Pine language, is used to empty the chart data.

reset(remain) The reset() method can take one parameter, remain, to specify the number of data to keep. Not passing remain means clearing all data.

Strategy custom drawing can only use one of the ways of KLineChart() function or Chart() function. For some color and style settings used in the KLineChart() function call, please refer to the Use the KLineChart function to make strategy drawing design easier.

{@fun/Log/Chart Chart}

LogReset

Clear the log.

LogReset(remain)

The remain parameter is used to set the number of recent log entries to keep. remain false number

function main() {
    // Keep the last 10 logs and clear the rest
    LogReset(10)     
}
def main():
    LogReset(10)
void main() {
    LogReset(10);
}

The startup log for each start of the strategy live trading counts as one, so if no parameters are passed in and there is no log output at the start of the strategy, no logs will be displayed at all, waiting for the docker log to be returned (not an exception).

{@fun/Log Log}, {@fun/Log/LogVacuum LogVacuum}

LogVacuum

Used to reclaim the storage space occupied by SQLite when deleting data after calling the LogReset() function to clear the log.

LogVacuum()

function main() {
    LogReset()
    LogVacuum()
}
def main():
    LogReset()
    LogVacuum()
void main() {
    LogReset()
    LogVacuum()
}

The reason is that SQLite does not reclaim the occupied space when deleting data, and it needs to execute VACUUM to clean up the table and free up space. File move operation occurs when this function is called, and the delay is large, so it is recommended to call at a suitable time interval.

{@fun/Log/LogReset LogReset}

console.log

It is used to output debugging information in the “debug information” column in the live trading page. For example, if the live trading Id is 123456, the console.log function outputs debugging information on the live trading page, and at the same time, create a log file with the extension .log and write debugging information in the /logs/storage/123456/ in the directory of the docker to which the live trading belongs, with the filename prefix stdout_.

console.log(…msgs)

The parameter msg is the content of the output, and the parameter msg can be passed more than one. msg false string, number, bool, object, array, null and other types supported by the system.

function main() {
    console.log("test console.log")
}
# Not supported
// Not supported
  • Only the JavaScript language supports this function.
  • This function is only supported by live trading, but not by “Debugging Tools” or “Backtesting System”.
  • Outputting an object is converted to the string [object Object], so try to output as much readable information as possible.

{@fun/Log/console.error console.error}

console.error

Used for error output in the “Debug message” field on the live trading page. For example, if the live trading Id is 123456, the console.error function creates a log file with the extension .log in the /logs/storage/123456/ directory of the docker where the live trading belongs, and writes the error output with the prefix stderr_.

console.error(…msgs)

The parameter msg is the content of the output, and the parameter msg can be passed more than one. msg false string, number, bool, object, array, null and other types supported by the system.

function main() {
    console.error("test console.error")
}
# Not supported
// Not supported
  • Only the JavaScript language supports this function.
  • This function is only supported by live trading, but not by “Debugging Tools” or “Backtesting System”.
  • Outputting an object is converted to the string [object Object], so try to output as much readable information as possible.

{@fun/Log/console.log console.log}

Market

exchange.GetTicker

Get the {@struct/Ticker Ticker} structure of the spot or contract corresponding to the currently set trading pair, contract code, i.e. the ticker data. GetTicker () function is a member function of the exchange object {@var/EXCHANGE exchange}, the use of exchange object member functions (methods) only related to exchange, and it will not be repeated in the document.

The exchange.GetTicker() function returns the {@struct/Ticker Ticker} structure when the request for data succeeds, and returns null value when the request for data fails. {@struct/Ticker Ticker}, null value

exchange.GetTicker() exchange.GetTicker(symbol)

The parameter symbol is used to specify the specific trading pair and contract code corresponding to the requested {@struct/Ticker Ticker} data. If this parameter is not passed, the market data of the currently set trading pair and contract code will be requested by default. When calling the exchange.GetTicker(symbol) function, exchange is the spot exchange object. If you need to request market data with the denominated currency as USDT and the trading currency as BTC, the parameter symbol is: "BTC_USDT", and the format is the trading pair format defined by the FMZ platform. When calling the exchange.GetTicker(symbol) function, exchange is the futures exchange object. If you need to request the market data of BTC’s U-standard perpetual contract, 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.GetTicker(symbol) function, exchange is the futures exchange object. If you need to request the market data of BTC’s U-standard option contract, the parameter symbol is: "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example), the format is the 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 false string

function main(){
    // If it is a futures exchange object, set the contract code first, e.g. set it as a perpetual contract
    // exchange.SetContractType("swap")

    var ticker = exchange.GetTicker()
    /*
        The exchange interface may not be accessible due to network reasons (even if the docker program's device can open the exchange website, the API interface may not be accessible).
        At this point, the ticker is null, and it will cause an error when accessing ticker.High, so when testing this code, make sure that the exchange interface can be accessed.
    */
    Log("Symbol:", ticker.Symbol, "High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Open:", ticker.Open, "Volume:", ticker.Volume)
}
def main():
    ticker = exchange.GetTicker()
    Log("Symbol:", ticker["Symbol"], "High:", ticker["High"], "Low:", ticker["Low"], "Sell:", ticker["Sell"], "Buy:", ticker["Buy"], "Last:", ticker["Last"], "Open:", ticker.Open, "Volume:", ticker["Volume"])
void main() {
    auto ticker = exchange.GetTicker();
    Log("Symbol:", ticker.Symbol, "High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Open:", ticker.Open, "Volume:", ticker.Volume);
}

For futures exchange objects (i.e., exchange or exchanges[0]), you need to set the contract code using the exchange.SetContractType() function before calling the ticker function, which will not be repeated.

function main() {
    var ticker = exchange.GetTicker("BTC_USDT")
    Log(ticker)
}
def main():
    ticker = exchange.GetTicker("BTC_USDT")
    Log(ticker)
void main() {
    auto ticker = exchange.GetTicker("BTC_USDT");
    Log(ticker);
}

Use the symbol parameter to request market data for a specific symbol (spot symbol).

The Ticker data returned by the exchange.GetTicker() function in the backtesting system. Where High and Low are simulated values, taken from the sell one and buy one of the market at that time. The Ticker data returned by the exchange.GetTicker() function in the real market. Where the High and Low values are based on the data returned by the encapsulated exchange Tick interface, which includes the highest and lowest prices within a certain period (usually a 24-hour period). Exchanges that do not support the exchange.GetTicker() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetTicker Futures_Aevo

{@fun/Market/exchange.GetDepth exchange.GetDepth}, {@fun/Market/exchange.GetTrades exchange.GetTrades}, {@fun/Market/exchange.GetRecords exchange.GetRecords}, {@fun/Market/exchange.GetTickers exchange.GetTickers}

exchange.GetDepth

Get the {@struct/Depth Depth} structure of the spot or contract corresponding to the currently set trading pair, contract code, i.e. order book data.

The exchange.GetDepth() function returns the {@struct/Depth Depth} structure if the request for data succeeds, and it returns null if the request for data fails. {@struct/Depth Depth}, null value

exchange.GetDepth() exchange.GetDepth(symbol)

The parameter symbol is used to specify the specific trading pair and contract code corresponding to the requested {@struct/Depth Depth} data. If this parameter is not passed, the order book data of the currently set trading pair and contract code will be requested by default. When calling the exchange.GetDepth(symbol) function, exchange is the spot exchange object. If you need to request to obtain the order book data with the denominated currency as USDT and the transaction currency as BTC, the parameter symbol is: "BTC_USDT", and the format is the trading pair format defined by the FMZ platform. When calling the exchange.GetDepth(symbol) function, exchange is the futures exchange object. If you need to request the order book data of BTC’s U-standard perpetual contract, 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.GetDepth(symbol) function, exchange is the futures exchange object. If you need to request the order book data of the BTC’s U-standard option contract, the parameter symbol is: "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example), the format is the 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 false string

function main(){
    var depth = exchange.GetDepth()
    /*
        The exchange interface may not be accessible due to network reasons (even if the docker program's device can open the exchange website, the API interface may not be accessible).
        At this point, the depth is null, which will cause an error when accessing depth.Asks[1].Price, so make sure you can access the exchange interface when testing the code.
    */
    var price = depth.Asks[1].Price
    Log("Sell 2 price is:", price)
}
def main():
    depth = exchange.GetDepth()
    price = depth["Asks"][1]["Price"]
    Log("Sell 2 price is:", price)
void main() {
    auto depth = exchange.GetDepth();
    auto price = depth.Asks[1].Price;
    Log("Sell 2 price is:", price);
}

Test exchange.GetDepth() function:

function main() {
    // BTC U-based perpetual contract
    var depth = exchange.GetDepth("BTC_USDT.swap")
    Log(depth)
}
def main():
    depth = exchange.GetDepth("BTC_USDT.swap")
    Log(depth)
void main() {
    auto depth = exchange.GetDepth("BTC_USDT.swap");
    Log(depth);
}

When the configured exchange object is a futures exchange object, use the symbol parameter to request the order book data of a specific symbol (futures symbol).

In the backtesting system, the data for each grade returned by the exchange.GetDepth() function when using the Simulate Tick backtesting are all simulated values. In the backtesting system, the data returned by the exchange.GetDepth() function when using the Real Tick backtesting is a second level deep snapshot.

{@fun/Market/exchange.GetTicker exchange.GetTicker}, {@fun/Market/exchange.GetTrades exchange.GetTrades}, {@fun/Market/exchange.GetRecords exchange.GetRecords}

exchange.GetTrades

Get the {@struct/Trade Trade} structure array of the spot or contract corresponding to the currently set trading pair, contract code, i.e. the market transaction data.

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

exchange.GetTrades() exchange.GetTrades(symbol)

The parameter symbol is used to specify the specific trading pair and contract code corresponding to the requested {@struct/Trade Trade} array data. If this parameter is not passed, the latest transaction record data of the currently set trading pair and contract code will be requested by default. When calling the exchange.GetTrades(symbol) function, exchange is the spot exchange object. If you need to request to obtain the order book data with the denominated currency as USDT and the trading currency as BTC, the parameter symbol is: "BTC_USDT", and the format is the trading pair format defined by the FMZ platform. When calling the exchange.GetTrades(symbol) function, exchange is the futures exchange object. If you need to request the order book data of BTC’s U-standard perpetual contract, 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.GetTrades(symbol) function, exchange is the futures exchange object. If you need to request the order book data of BTC’s U-standard option contract, the parameter symbol is: "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example), the format is the 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 false string

function main(){
    var trades = exchange.GetTrades()
    /*
        The exchange interface may not be accessible due to network reasons (even if the docker program's device can open the exchange website, the API interface may not be accessible).
        At this point, trade is null. When accessing trade[0].Id, it will cause an error. Therefore, when testing this code, ensure that you can access the exchange interface.
    */
    Log("id:", trades[0].Id, "time:", trades[0].Time, "Price:", trades[0].Price, "Amount:", trades[0].Amount, "type:", trades[0].Type)
}
def main():
    trades = exchange.GetTrades()
    Log("id:", trades[0]["Id"], "time:", trades[0]["Time"], "Price:", trades[0]["Price"], "Amount:", trades[0]["Amount"], "type:", trades[0]["Type"])
void main() {
    auto trades = exchange.GetTrades();
    Log("id:", trades[0].Id, "time:", trades[0].Time, "Price:", trades[0].Price, "Amount:", trades[0].Amount, "type:", trades[0].Type);
}

Test the exchange.GetTrades() function:

function main() {
    // BTC's U-based perpetual contract
    var trades = exchange.GetTrades("BTC_USDT.swap")
    Log(trades)
}
def main():
    trades = exchange.GetTrades("BTC_USDT.swap")
    Log(trades)
void main() {
    auto trades = exchange.GetTrades("BTC_USDT.swap");
    Log(trades);
}

When the configured exchange object is a futures exchange object, use the symbol parameter to request market transaction record data for a specific symbol (futures symbol).

exchange.GetTrades() function to get the current trading pairs, the market’s transaction history (not their own) corresponding to contracts. Some exchanges do not support this function, and the specific data returned is how much of the range of transaction records depends on the exchange and needs to be handled according to the specific situation. The return data is an array, where each element of the chronological order and exchange.GetRecords () function returns the same order of data, that is, the last element of the array is the data closest to the current time. The exchange.GetTrades() function returns an empty array when using Simulate Tick backtesting in the backtesting system. The data returned by the exchange.GetTrades() function when using Real Tick backtesting in the backtesting system is the order flow snapshot data, i.e. the {@struct/Trade Trade} structure array. Exchanges that do not support the exchange.GetTrades() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetTrades Futures_BitMart / Futures_Bibox

{@fun/Market/exchange.GetTicker exchange.GetTicker}, {@fun/Market/exchange.GetDepth exchange.GetDepth}, {@fun/Market/exchange.GetRecords exchange.GetRecords}

exchange.GetRecords

Get the {@struct/Record Record} structure array of the spot or contract corresponding to the currently set trading pair, contract code, i.e. K-line data.

The exchange.GetRecords() function returns an array of {@struct/Record Record} structures when the request for data succeeds, and it returns null values when the request for data fails. {@struct/Record Record}arrays, null values

exchange.GetRecords() exchange.GetRecords(symbol) exchange.GetRecords(symbol, period) exchange.GetRecords(symbol, period, limit) exchange.GetRecords(period) exchange.GetRecords(period, limit)

The parameter symbol is used to specify the specific trading pair and contract code corresponding to the requested {@struct/Record Record} array data. If this parameter is not passed, the K-line data of the currently set trading pair and contract code will be requested by default. When calling the exchange.GetRecords(symbol) function, exchange is the spot exchange object. If you need to request to obtain the data with the denominated currency as USDT and the transaction currency as BTC, the parameter symbol is: "BTC_USDT", and the format is the trading pair format defined by the FMZ platform. When calling the exchange.GetRecords(symbol) function, exchange is the futures exchange object. If you need to request the order book data of BTC’s U-standard perpetual contract, 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.GetRecords(symbol) function, exchange is the futures exchange object. If you need to request the order book data of BTC’s U-standard option contract, the parameter symbol is: "BTC_USDT.BTC-240108-40000-C" (taking Binance Option BTC-240108-40000-C as an example), the format is the 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 false string The parameter period specifies the period of the requested K-line data, for example: {@var/PERIOD/PERIOD_M1 PERIOD_M1}, {@var/PERIOD/PERIOD_M5 PERIOD_M5}, {@var/PERIOD/PERIOD_M15 PERIOD_M15}, etc. The value of parameter period can be passed not only the defined standard period, but also integer values in seconds. If this parameter is not passed, the period of the K-line data requested by default is the default K-line period of the current strategy real-time/backtest configuration. period false number The parameter limit is used to specify the length of the requested K-line data. If this parameter is not passed, the default request length is the maximum number of K-line bars requested at a time of the exchange K-line interface. This parameter may cause paging to query the exchange K-line data, and the time consumption of the function call will increase during paging query. limit false number

function main() {
    // Print K-line data with a K-line period of 120 seconds (2 minutes)
    Log(exchange.GetRecords(60 * 2))         
    // Print K-line data with a K-line period of 5 minutes
    Log(exchange.GetRecords(PERIOD_M5))      
}
def main():
    Log(exchange.GetRecords(60 * 2))
    Log(exchange.GetRecords(PERIOD_M5))
void main() {
    Log(exchange.GetRecords(60 * 2)[0]);
    Log(exchange.GetRecords(PERIOD_M5)[0]);
}

Get K-line data for a custom period.

function main() {
    var records = exchange.GetRecords(PERIOD_H1)
    /*
        The exchange interface may not be accessible due to network reasons (even if the docker program's device can open the exchange website, the API interface may not be accessible).
        At this point, records is null. When accessing records[0].Time, it will cause an error. Therefore, when testing this code, ensure that you can access the exchange interface.
    */
    Log("The first k-line data is Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High)
    Log("The second k-line data is Time:", records[1].Time ,"Close:", records[1].Close)
    Log("Current K-line (latest)", records[records.length-1], "Previous K-line", records[records.length-2])
}
def main():
    records = exchange.GetRecords(PERIOD_H1)
    Log("The first k-line data is Time:", records[0]["Time"], "Open:", records[0]["Open"], "High:", records[0]["High"])
    Log("The second k-line data Time:", records[1]["Time"], "Close:", records[1]["Close"])
    Log("Current K-line (latest)", records[-1], "Previous K-line", records[-2])
void main() {
    auto records = exchange.GetRecords(PERIOD_H1);
    Log("The first k-line data is Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High);
    Log("The second k-line data Time:", records[1].Time, "Close:", records[1].Close);
    Log("Current K-line (latest)", records[records.size() - 1], "Previous K-line", records[records.size() - 2]);
}

Output K-line bar data:

function main() {
    var records = exchange.GetRecords("BTC_USDT.swap", 60, 100)
    Log(records)
}
def main():
    records = exchange.GetRecords("BTC_USDT.swap", 60, 100)
    Log(records)
void main() {
    auto records = exchange.GetRecords("BTC_USDT.swap", 60, 100);
    Log(records);
}

When the configured exchange object is a futures exchange object, use the symbol, period, and limit parameters to request the K-line data of a specific product (futures product).

The default K-line period can be set in the backtest and real trading pages. If you specify a parameter when calling the exchange.GetRecords() function, the K-line data corresponding to that parameter period will be obtained. If no parameter is specified when the function is called, the corresponding K-line data will be returned according to the K-line period set in the backtest and real market parameters. The return value is an array of Record structures, the returned K-line data will be accumulated over time, the upper limit of the accumulated K-line bars is affected by the exchange.SetMaxBarLen() function setting. The default limit is 5000 bars when it’s not set. When the K-line data reaches the K-line bar accumulation limit, it will be updated by adding a K-line bar and deleting the earliest K-line bar (e.g. queue in/out). Some exchanges do not provide a K-line interface, so the docker collects market transaction record data (Trade structured array) in real time to generate K-lines. If the exchange’s K-line interface supports paging queries, multiple API requests will be made when calling the exchange.SetMaxBarLen() function to set a larger K-line length. When the exchange.GetRecords() function is called initially, the number of K-line bars obtained differs between backtesting and real trading: - The backtesting system will obtain a certain number of K-line bars before the start of the backtesting time range in advance (the default is 5000, the settings of the backtesting system and the amount of data will affect the final number returned), as the initial K-line data. - The number of K-line bars obtained during the actual trading is based on the maximum amount of data that can be obtained from the K-line interface of the exchange. The period parameter is set to 5, which is a request to get K-line data with a period of 5 seconds. If the period parameter is not divisible by 60 (i.e., the period represented is not divisible by minutes). The underlying system uses the relevant interface of exchange.GetTrades() to obtain the transaction record data and synthesize the required K-line data. If the period parameter is divisible by 60, then the required K-line data is synthesized using a minimum of 1-minute K-line data (if possible, the required K-line data is synthesized using a larger period). The simulated level backtesting in the backtesting system requires the setting of the underlying K-line period (when the backtesting system simulates level backtesting, the corresponding K-line data is used to generate Tick data according to the set underlying K-line period). It should be noted that the period of the K-line data obtained in the strategy should not be smaller than the underlying K-line period. Because in the simulation level backtesting, the K-line data of each period in the backtesting system is synthesized from the K-line data of the underlying K-line period. The C++ language has the following code example if you need to construct your own K-line data:

#include <sstream>
void main() { 
    Records r;
    r.Valid = true;
    for (auto i = 0; i < 10; i++) {
        Record ele;
        ele.Time = i * 100000;
        ele.High = i * 10000;
        ele.Low = i * 1000;
        ele.Close = i * 100;
        ele.Open = i * 10;
        ele.Volume = i * 1;
        r.push_back(ele);
    }
    // Output display: Records[10]
    Log(r);                      
    auto ma = TA.MA(r,10);       
    // Output display: [nan,nan,nan,nan,nan,nan,nan,nan,nan,450]
    Log(ma);                     
}

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

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetRecords Zaif / Coincheck / BitFlyer Futures_Aevo

{@fun/Market/exchange.GetTicker exchange.GetTicker}, {@fun/Market/exchange.GetDepth exchange.GetDepth}, {@fun/Market/exchange.GetTrades exchange.GetTrades}, {@fun/Market/exchange.SetMaxBarLen exchange.SetMaxBarLen}

exchange.GetPeriod

Get the K-line period set on the FMZ Quant Trading platform website page when backtesting and running the strategy in live trading, i.e. the default K-line period used when calling the exchange.GetRecords() function without passing parameters.

K-line period in seconds, integer value in seconds. number

exchange.GetPeriod()

function main() {
    // For example, the K-line period set on the website page of the FMZ Quant Trading platform during backtesting and live trading is 1 hour.
    var period = exchange.GetPeriod()
    Log("K-line period:", period / (60 * 60), "hours")
}
def main():
    period = exchange.GetPeriod()
    Log("K-line period:", period / (60 * 60), "hours")
void main() {
    auto period = exchange.GetPeriod();
    Log("K-line period:", period / (60 * 60.0), "hours");
}

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

exchange.SetMaxBarLen

Set the maximum length of the K-line.

exchange.SetMaxBarLen(n)

The parameter n is used to specify the maximum K-line length. n true number

function main() {
    exchange.SetMaxBarLen(50)
    var records = exchange.GetRecords()
    Log(records.length, records)
}
def main():
    exchange.SetMaxBarLen(50)
    r = exchange.GetRecords()
    Log(len(r), r)
void main() {
    exchange.SetMaxBarLen(50);
    auto r = exchange.GetRecords();
    Log(r.size(), r[0]);
}

The exchange.SetMaxBarLen() function affects two aspects for cryptocurrency strategy runtime:

  • Affects the number of K-line bars (Bars) that are obtained on the first call.
  • Affects the maximum number of K-line bars (Bars).

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

exchange.GetRawJSON

Get the original content returned by the last rest request for the current exchange object ({@var/EXCHANGE exchange}, {@var/EXCHANGE/exchanges exchanges}).

The response data for the rest request. string

exchange.GetRawJSON()

function main(){
    exchange.GetAccount(); 
    var obj = JSON.parse(exchange.GetRawJSON());
    Log(obj);
}
import json
def main():
    exchange.GetAccount()
    obj = json.loads(exchange.GetRawJSON())
    Log(obj)
void main() {
    auto obj = exchange.GetAccount();
    // C++ does not support the GetRawJSON function
    Log(obj);
}

The exchange.GetRawJSON() function is only supported for the real trading. The function is not supported by strategies in the C++ language.

{@var/EXCHANGE exchange}

exchange.GetRate

Get the exchange rate currently set for the exchange object.

The current value of the exchange rate of the exchange object. number

exchange.GetRate()

function main(){
    Log(exchange.GetTicker())
    // Set up exchange rate conversion
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    Log("Current exchange rate:", exchange.GetRate())
}
def main():
    Log(exchange.GetTicker())
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    Log("Current exchange rate:", exchange.GetRate())
void main() {
    Log(exchange.GetTicker());
    exchange.SetRate(7);
    Log(exchange.GetTicker());
    Log("Current exchange rate:", exchange.GetRate());
}

If exchange.SetRate() has not been called to set the conversion rate, the exchange.GetRate() function returns a default rate value of 1. That is, the data related to the currently displayed currency (quoteCurrency) has not been converted. If an exchange rate value has been set using exchange.SetRate(), for example, exchange.SetRate(7). Then all price information, such as quotes, depths, and order prices obtained through the exchange exchange object will be converted by multiplying by the set exchange rate 7. If exchange corresponds to an exchange with USD as the denomination currency, after calling exchange.SetRate(7), all prices in the live market will be converted to a price close to CNY by multiplying 7. At this point, the exchange rate value obtained using exchange.GetRate() is 7.

{@fun/Trade/exchange.SetRate exchange.SetRate}

exchange.SetData

The exchange.SetData() function is used to set the data loaded when the strategy is running.

The length of the string after parameter value JSON encoding. number

exchange.SetData(key, value)

The name of the data collection. key true string The data to be loaded by the exchange.SetData() function has a data structure of an array. The data structure is the same as the data format requested by the exchange.GetData() function when requesting external data, i.e.: "schema": ["time", "data"]. value true array

/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
function main() {
    var data = [
        [1579536000000, "abc"],
        [1579622400000, 123],
        [1579708800000, {"price": 123}],
        [1579795200000, ["abc", 123, {"price": 123}]]
    ]
    exchange.SetData("test", data)
    while(true) {
        Log(exchange.GetData("test"))
        Sleep(1000)
    }
}
'''backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
'''              

def main():
    data = [
        [1579536000000, "abc"],
        [1579622400000, 123],
        [1579708800000, {"price": 123}],
        [1579795200000, ["abc", 123, {"price": 123}]]
    ]
    exchange.SetData("test", data)
    while True:
        Log(exchange.GetData("test"))
        Sleep(1000)
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/              

void main() {
    json data = R"([
        [1579536000000, "abc"],
        [1579622400000, 123],
        [1579708800000, {"price": 123}],
        [1579795200000, ["abc", 123, {"price": 123}]]
    ])"_json;
    
    exchange.SetData("test", data);
    while(true) {
        Log(exchange.GetData("test"));
        Sleep(1000);
    }
}

It requires that the data for the parameter value be in the same format as the data variable in the following example. You can see that the timestamp 1579622400000 corresponds to the time 2020-01-22 00:00:00, and that when the strategy program is run after this time, call the exchange.GetData() function to get the data before the next data timestamp 1579708800000, that is, time 2020-01-23 00:00:00. What you get are [1579622400000, 123] the contents of that data, as the program continues to run, the time changes, and so on to get the data item by item. In the following example, at runtime (backtesting or live trading), the current moment reaches or exceeds the timestamp 1579795200000, the exchange.GetData() function is called and the return value is: {"Time":1579795200000,"Data":["abc", 123,{"price":123}]}. "Time":1579795200000 corresponds to 1579795200000 in data [1579795200000, ["abc", 123, {"price": 123}]]. "Data":["abc", 123, {"price": 123}] corresponds to data ["abc", 123, {"price": 123}]] in [1579795200000, ["abc", 123, {"price": 123}]].

The loaded data can be any economic indicators, industry data, relevant indicators, etc., used for strategy quantitative assessment of all quantifiable information.

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

exchange.GetData

The exchange.GetData() function is used to get data loaded by the exchange.SetData() function or provided by an external link.

Records in the data collection. object

exchange.GetData(key) exchange.GetData(key, timeout)

The name of the data collection. key true string Used to set the cache timeout in milliseconds. Defaults to a one minute cache timeout for live tradings. timeout false number

/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
function main() {
    exchange.SetData("test", [[1579536000000, _D(1579536000000)], [1579622400000, _D(1579622400000)], [1579708800000, _D(1579708800000)]])
    while(true) {
        Log(exchange.GetData("test"))
        Sleep(1000 * 60 * 60 * 24)
    }
}
'''backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
'''  
def main():
    exchange.SetData("test", [[1579536000000, _D(1579536000000/1000)], [1579622400000, _D(1579622400000/1000)], [1579708800000, _D(1579708800000/1000)]])
    while True:
        Log(exchange.GetData("test"))
        Sleep(1000 * 60 * 60 * 24)
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/    
void main() {
    json arr = R"([[1579536000000, ""], [1579622400000, ""], [1579708800000, ""]])"_json;
    arr[0][1] = _D(1579536000000);
    arr[1][1] = _D(1579622400000);
    arr[2][1] = _D(1579708800000);
    exchange.SetData("test", arr);
    while(true) {
        Log(exchange.GetData("test"));
        Sleep(1000 * 60 * 60 * 24);
    }
}

The call to get the data written directly.

/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
function main() {
    while(true) {
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
        Sleep(1000)
    }
}
'''backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
'''              

def main():
    while True:
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
        Sleep(1000)
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/              

void main() {
    while(true) {
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"));
        Sleep(1000);
    }
}

It support for requesting data through external links, the format of the data requested to:

{
    "schema":["time","data"],
    "data":[
        [1579536000000, "abc"],
        [1579622400000, 123],
        [1579708800000, {"price": 123}],
        [1579795200000, ["abc", 123, {"price": 123}]]
    ]
}

Where schema is the data format for each record in the body of the loaded data, which is fixed to ["time", "data"] corresponding to the format of the entry-by-entry data in the data attribute. What is stored in the data attribute is the body of the data, with each entry consisting of a millisecond-level timestamp and the data content (which can be any JSON-encodable data). The service program for testing, written in Go:

package main
import (
    "fmt"
    "net/http"
    "encoding/json"
)                

func Handle (w http.ResponseWriter, r *http.Request) {
    defer func() {
        fmt.Println("req:", *r)
        ret := map[string]interface{}{
            "schema": []string{"time","data"},
            "data": []interface{}{
                []interface{}{1579536000000, "abc"},
                []interface{}{1579622400000, 123},
                []interface{}{1579708800000, map[string]interface{}{"price":123}},
                []interface{}{1579795200000, []interface{}{"abc", 123, map[string]interface{}{"price":123}}},
            },
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()
}                

func main () {
    fmt.Println("listen http://localhost:9090")
    http.HandleFunc("/data", Handle)
    http.ListenAndServe(":9090", nil)
}

The program’s response data upon receipt of the request:

{
    "schema":["time","data"],
    "data":[
        [1579536000000, "abc"],
        [1579622400000, 123],
        [1579708800000, {"price": 123}],
        [1579795200000, ["abc", 123, {"price": 123}]]
    ]
}

Test strategy code:

function main() {
    Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
    Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"))
}
def main():
    Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
    Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"))
void main() {
    Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"));
    Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"));
}

The call method to get the data of an external link.

function main() {
    Log(exchange.GetData("https://www.datadata.com/api/v1/query/xxx/data"))   // The xxx part of the link is the code of the query data, here xxx is an example.
}
def main():
    Log(exchange.GetData("https://www.datadata.com/api/v1/query/xxx/data"))
void main() {
    Log(exchange.GetData("https://www.datadata.com/api/v1/query/xxx/data"));
}

Request data for a query created on the platform datadata, requesting that the data format of the answer be (must have time, data fields described in schema):

{
    "data": [],
    "schema": ["time", "data"]
}

The “data” field is the required data content, and the data in the “data” field needs to be the same as what is agreed in the “schema”. When the exchange.GetData() function is called, a JSON object is returned, e.g.: {"Time":1579795200000, "Data":"..."}.

Get the data at once for backtesting and cache one minute of data for live trading. In the backtesting system, when requesting data using the access interface, the backtesting system automatically adds from (timestamped in seconds), to (timestamped in seconds) to the request, parameters such as period (underlying K-line period, timestamped in milliseconds) are used to determine the time frame over which the data is to be acquired.

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

exchange.GetMarkets

The exchange.GetMarkets() function is used to get exchange market information.

Dictionary containing the {@struct/Market Market} structure. object

exchange.GetMarkets()

function main() {
    var markets = exchange.GetMarkets()
    var currency = exchange.GetCurrency()

    // Get the current contract code can also use exchange.GetContractType() function
    var ct = "swap"

    var key = currency + "." + ct
    Log(key, ":", markets[key])
}
def main():
    markets = exchange.GetMarkets()
    currency = exchange.GetCurrency()
    ct = "swap"

    key = currency + "." + ct
    Log(key, ":", markets[key])
void main() {
    auto markets = exchange.GetMarkets();
    auto currency = exchange.GetCurrency();

    auto ct = "swap";
    auto key = currency + "." + ct;
    Log(key, ":", markets[key]);
}

Example of a call to a futures exchange object:

/*backtest
start: 2023-05-10 00:00:00
end: 2023-05-20 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

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

    var tbl1 = {
        type: "table",
        title: "markets1",
        cols: ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        rows: []
    }

    var markets1 = exchange.GetMarkets()
    for (var key in markets1) {
        var market = markets1[key]
        tbl1.rows.push([key, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize, market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal])
    }

    for (var symbol of arrSymbol) {
        exchange.GetTicker(symbol)
    }

    var tbl2 = {
        type: "table",
        title: "markets2",
        cols: ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        rows: []
    }

    var markets2 = exchange.GetMarkets()
    for (var key in markets2) {
        var market = markets2[key]
        tbl2.rows.push([key, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize, market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal])
    }

    LogStatus("`" + JSON.stringify([tbl1, tbl2]) + "`")
}
'''backtest
start: 2023-05-10 00:00:00
end: 2023-05-20 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
'''

import json

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

    tbl1 = {
        "type": "table",
        "title": "markets1",
        "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        "rows": []
    }

    markets1 = exchange.GetMarkets()
    for key in markets1:
        market = markets1[key]
        tbl1["rows"].append([key, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]])

    for symbol in arrSymbol:
        exchange.GetTicker(symbol)

    tbl2 = {
        "type": "table",
        "title": "markets2",
        "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        "rows": []
    }

    markets2 = exchange.GetMarkets()
    for key in markets2:
        market = markets2[key]
        tbl2["rows"].append([key, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]])

    LogStatus("`" + json.dumps([tbl1, tbl2]) + "`")
/*backtest
start: 2023-05-10 00:00:00
end: 2023-05-20 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

void main() {
    auto arrSymbol = {"SOL_USDT.swap", "BTC_USDT.quarter", "ETH_USDT.swap", "ETH_USDT.quarter"};

    json tbl1 = R"({
        "type": "table",
        "title": "markets1",
        "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        "rows": []
    })"_json;

    auto markets1 = exchange.GetMarkets();
    for (auto& [key, market] : markets1.items()) {
        json arrJson = {key, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]};
        tbl1["rows"].push_back(arrJson);
    }

    for (const auto& symbol : arrSymbol) {
        exchange.GetTicker(symbol);
    }

    json tbl2 = R"({
        "type": "table",
        "title": "markets2",
        "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
        "rows": []
    })"_json;

    auto markets2 = exchange.GetMarkets();
    for (auto& [key, market] : markets2.items()) {
        json arrJson = {key, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]};
        tbl2["rows"].push_back(arrJson);
    }

    json tbls = R"([])"_json;
    tbls.push_back(tbl1);
    tbls.push_back(tbl2);
    LogStatus("`" + tbls.dump() + "`");
}

Use the futures exchange object to call the exchange.GetMarkets() function in the backtesting system. Before calling any market function, GetMarkets only returns the market data of the current default trading pair. After calling the market function, it returns the market data of all requested varieties. You can refer to the following test example:

The exchange.GetMarkets() function returns a dictionary with a key named the name of the trade variety, and for spot fixes formatted as a trading pair, for example:

{
    "BTC_USDT" : {...},  // The key value is the Market structure
    "LTC_USDT" : {...},  
    ...
}

For futures contract exchanges, as there may be multiple contracts for a single variety, e.g. BTC_USDT trading pairs, there are perpetual contracts, quarterly contracts, and so on. The exchange.GetMarkets() function returns a dictionary with the key name of the pair combined with the contract code, for example:

{
    "BTC_USDT.swap" : {...},     // The key value is the Market structure
    "BTC_USDT.quarter" : {...}, 
    "LTC_USDT.swap" : {...},
    ...
}
  • The exchange.GetMarkets() function supports live tradings, backtesting system.
  • The exchange.GetMarkets() function returns market information only for the varieties that are traded on line on the exchange.
  • The exchange.GetMarkets() function does not support options contracts.

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

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetMarkets Coincheck / Bithumb / BitFlyer

{@struct/Market Market}

exchange.GetTickers

The exchange.GetTickers() function is used to get exchange aggregated ticker data (the array of {@struct/Ticker Ticker} structure). exchange returns ticker data for all trading pairs when it is a spot exchange object; exchange returns ticker data for all contracts when it is a futures exchange object.

The exchange.GetTickers() function returns an array of {@struct/Ticker Ticker} structures when it succeeds in requesting data, and null when it fails. {@struct/Ticker Ticker} arrays, null values

exchange.GetTickers()

function main() {
    var tickers = exchange.GetTickers()
    if (tickers && tickers.length > 0) {
        Log("Number of tradable items on the exchange:", tickers.length)
    }
}
def main():
    tickers = exchange.GetTickers()
    if tickers and len(tickers) > 0:
        Log("Number of tradable items on the exchange:", len(tickers))
void main() {
    auto tickers = exchange.GetTickers();
    if (tickers.Valid && tickers.size() > 0) {
        Log("Number of tradable items on the exchange:", tickers.size());
    }
}

Call the exchange.GetTickers() function to obtain aggregated market data.

/*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 = ["ADA_USDT", "LTC_USDT", "ETH_USDT", "SOL_USDT"]
    
    // Before requesting other trading pair market data, call Get Tickers
    var tickers1 = exchange.GetTickers()
    var tbl1 = {type: "table", title: "tickers1", cols: ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], rows: []}
    for (var ticker of tickers1) {
        tbl1.rows.push([ticker.Symbol, ticker.High, ticker.Open, ticker.Low, ticker.Last, ticker.Buy, ticker.Sell, ticker.Time, ticker.Volume])
    }
    
    // Request market data for other trading pairs
    for (var symbol of arrSymbol) {
        exchange.GetTicker(symbol)
    }

    // Call GetTickers again
    var tickers2 = exchange.GetTickers()
    var tbl2 = {type: "table", title: "tickers2", cols: ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], rows: []}
    for (var ticker of tickers2) {
        tbl2.rows.push([ticker.Symbol, ticker.High, ticker.Open, ticker.Low, ticker.Last, ticker.Buy, ticker.Sell, ticker.Time, ticker.Volume])
    }

    LogStatus("`" + JSON.stringify([tbl1, tbl2]) +  "`")
}
'''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 = ["ADA_USDT", "LTC_USDT", "ETH_USDT", "SOL_USDT"]
        
    tickers1 = exchange.GetTickers()
    tbl1 = {"type": "table", "title": "tickers1", "cols": ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], "rows": []}
    for ticker in tickers1:
        tbl1["rows"].append([ticker["Symbol"], ticker["High"], ticker["Open"], ticker["Low"], ticker["Last"], ticker["Buy"], ticker["Sell"], ticker["Time"], ticker["Volume"]])
    
    for symbol in arrSymbol:
        exchange.GetTicker(symbol)
    
    tickers2 = exchange.GetTickers()
    tbl2 = {"type": "table", "title": "tickers2", "cols": ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], "rows": []}
    for ticker in tickers2:
        tbl2["rows"].append([ticker["Symbol"], ticker["High"], ticker["Open"], ticker["Low"], ticker["Last"], ticker["Buy"], ticker["Sell"], ticker["Time"], ticker["Volume"]])
    
    LogStatus("`" + json.dumps([tbl1, tbl2]) +  "`")
/*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"}]
*/

json tickerToJson(const Ticker& ticker) {
    json arrJson;

    arrJson.push_back(ticker.Symbol);
    arrJson.push_back(ticker.High);
    arrJson.push_back(ticker.Open);
    arrJson.push_back(ticker.Low);
    arrJson.push_back(ticker.Last);
    arrJson.push_back(ticker.Buy);
    arrJson.push_back(ticker.Sell);
    arrJson.push_back(ticker.Time);
    arrJson.push_back(ticker.Volume);

    return arrJson;
}

void main() {
    std::string arrSymbol[] = {"ADA_USDT", "LTC_USDT", "ETH_USDT", "SOL_USDT"};
    
    auto tickers1 = exchange.GetTickers();
    json tbl1 = R"({
        "type": "table", 
        "cols": ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"],
        "rows": []
    })"_json;
    tbl1["title"] = "tickers1";
    
    for (const auto& ticker : tickers1) {
        json arrJson = tickerToJson(ticker);
        tbl1["rows"].push_back(arrJson);
    }
    
    for (const std::string& symbol : arrSymbol) {
        exchange.GetTicker(symbol);
    }
    
    auto tickers2 = exchange.GetTickers();
    json tbl2 = R"({
        "type": "table", 
        "cols": ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"],
        "rows": []
    })"_json;
    tbl2["title"] = "tickers2";
    
    for (const auto& ticker : tickers2) {
        json arrJson = tickerToJson(ticker);
        tbl2["rows"].push_back(arrJson);
    }
    
    json tbls = R"([])"_json;
    tbls.push_back(tbl1);
    tbls.push_back(tbl2);
    LogStatus("`" + tbls.dump() + "`");
}

Use the spot exchange object and call the exchange.GetTickers() function in the backtest system. Before calling any market function, GetTickers only returns the ticker data of the current default trading pair. After calling the market function, it returns the ticker data of all requested varieties. You can refer to the following test example:

  • This function requests the exchange to aggregate tickers interface, no need to set up trading pairs, contract code before calling. It only returns the tickers of the online trading varieties on the exchange.
  • The backtesting system supports this function.
  • Exchange objects that do not provide an aggregated ticker interface do not support this function.
  • This function does not support option contracts.

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

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetTickers Zaif / WOO / Gemini / Coincheck / BitFlyer / Bibox Futures_WOO / Futures_dYdX / Futures_Deribit / Futures_Bibox / Futures_Aevo

{@struct/Ticker Ticker}, {@fun/Market/exchange.GetTicker exchange.GetTicker}

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}

Account

exchange.GetAccount

The exchange.GetAccount() function is used to request exchange account information. The GetAccount() function is a member function of the exchange object {@var/EXCHANGE 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.

Query the account asset information and return the {@struct/Account Account} structure if the query succeeds or null if it fails. {@struct/Account Account}, null value

exchange.GetAccount()

function main(){
    // Switching trading pairs
    exchange.IO("currency", "BTC_USDT")     
    // Take OKX futures as an example, set the contract as the current week's contract, the current trading pair is BTC_USDT, so the current contract is BTC's U-nominal current week contract
    exchange.SetContractType("this_week")   
    // Get current account asset data
    var account = exchange.GetAccount()
    // Available balance of USDT as margin
    Log(account.Balance)
    // USDT freeze amount as margin
    Log(account.FrozenBalance)
    // Current asset equity
    Log(account.Equity)
    // The unrealized profit and loss of all positions held with the current asset as margin
    Log(account.UPnL)
}
def main():
    exchange.IO("currency", "BTC_USDT")
    exchange.SetContractType("this_week")    
    account = exchange.GetAccount()
    Log(account["Balance"])
    Log(account["FrozenBalance"])
    Log(account["Equity"])
    Log(account["UPnL"])
void main() {
    exchange.IO("currency", "BTC_USDT");
    exchange.SetContractType("this_week");    
    auto account = exchange.GetAccount();
    Log(account.Balance);
    Log(account.FrozenBalance);
    Log(account["Equity"])
    Log(account["UPnL"])
}

Set up trading pairs, contract codes, and get current account information.

If the exchange object is set to a cryptocurrency futures contract exchange, and switched to a contract with USDT as margin (see {@fun/Account/exchange.SetCurrency exchange.SetCurrency}, {@fun/Futures/exchange.SetContractType exchange.SetContractType} functions for how to switch). The asset is USDT as margin, which is recorded in the Balance, FrozenBalance attributes of the {@struct/Account Account} structure. If the exchange object is set to a cryptocurrency futures contract exchange, and switched to a currency-based contract, the asset is in currency as margin and is recorded in the Stocks, FrozenStocks attributes of the {@struct/Account Account} structure. When using the Binance Futures unified account, when calling the exchange.GetAccount() function to request account information, the encapsulated data is the amount of all assets converted into USD. It is displayed in the Balance field of the {@struct/Account Account} structure. If you need to calculate the conversion amount of other assets, you can use the USD conversion amount divided by the index price (of the asset to be converted) and then divided by the pledge rate (of the asset to be converted) to calculate it.

{@struct/Account Account}, {@fun/Account/exchange.SetCurrency exchange.SetCurrency}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}

exchange.GetAssets

The exchange.GetAssets function is used to request exchange account asset information.

The exchange.GetAssets() function returns an array of {@struct/Asset Asset} structures if the request for data succeeds, or null if the request fails. {@struct/Asset Asset} array, null value

exchange.GetAssets()

function main() {
    // exchange.SetCurrency("BTC_USDT")  // You can set up trading pairs
    // exchange.SetContractType("swap")  // You can set up contracts
    var assets = exchange.GetAssets()
    Log(assets)
}
def main():
    # exchange.SetCurrency("BTC_USDT")  # You can set up trading pairs
    # exchange.SetContractType("swap")  # You can set up contracts
    assets = exchange.GetAssets()
    Log(assets)
void main() {
    // exchange.SetCurrency("BTC_USDT");  // You can set up trading pairs
    // exchange.SetContractType("swap");  // You can set up contracts
    auto assets = exchange.GetAssets();
    Log(assets);
}

Get information about the assets of an exchange account, exchange.GetAssets() returns an array with elements of the Asset structure.

The GetAssets() function of the Futures Exchange object returns the margin assets under the current trading pair (currency-based, USDT-based, USDC-based, etc.).

{@struct/Asset Asset}

exchange.GetName

The exchange.GetName() function is used to get the name of the exchange to which the current exchange object is bound.

The exchange.GetName() function returns the name of the exchange defined by the FMZ Quant Trading platform. string

exchange.GetName()

function main() {
    Log("The exchange object exchange is judged to be Binance spot, and the result is judged to be:", exchange.GetName() == "Binance")
}
def main():
    Log("The exchange object exchange is judged to be Binance spot, and the result is judged to be:", exchange.GetName() == "Binance")
void main() {
    Log("The exchange object exchange is judged to be Binance spot, and the result is judged to be:", exchange.GetName() == "Binance");
}

The exchange.GetName() function is generally used to identify the exchange objects, such as exchange or exchanges[1], exchanges[2] in the strategy code. The names of cryptocurrency futures contract exchanges have the fixed prefix Futures_.

{@fun/Account/exchange.GetLabel exchange.GetLabel}

exchange.GetLabel

The exchange.GetLabel() function is used to get the custom label that was set when the exchange object was configured.

The exchange.GetLabel() function returns the custom label that was set when the exchange object was configured. string

exchange.GetLabel()

function main() {
    Log("exchange label:", exchange.GetLabel())
}
def main():
    Log("exchange label:", exchange.GetLabel())
void main() {
    Log("exchange label:", exchange.GetLabel());
}

Exchange objects such as exchange or exchanges[1], exchanges[2] in the strategy code are identified by the set tag.

{@var/EXCHANGE exchange}

exchange.GetCurrency

The exchange.GetCurrency() function is used to get the currently set trading pair.

The exchange.GetCurrency() function returns the trading pair set by the current {@var/EXCHANGE exchange} exchange object. string

exchange.GetCurrency()

function main() {
    Log("the current trading pair of exchange is:", exchange.GetCurrency())
}
def main():
    Log("the current trading pair of exchange is:", exchange.GetCurrency())
void main() {
    Log("the current trading pair of exchange is:", exchange.GetCurrency());
}

The trading pair format is uppercase uniformly, using underscores to separate baseCurrency and quoteCurrency, such as BTC_USDT.

{@fun/Account/exchange.SetCurrency exchange.SetCurrency}

exchange.SetCurrency

The exchange.SetCurrency() function is used to switch the current trading pair of the exchange object {@var/EXCHANGE exchange}.

exchange.SetCurrency(currency)

The currency parameter is used to set the trading pair to be switched. The trading pair format is uppercase uniformly, using an underscore to separate baseCurrency from quoteCurrency, such as BTC_USDT. currency true string

function main() {
    var ticker = exchange.GetTicker() 
    Log(ticker)
    Log(exchange.GetAccount())    
    // Switching trading pairs, pay attention to the changes of ticker data and account information after switching
    exchange.SetCurrency("LTC_USDT")
    Log("Switch to LTC_USDT")
    ticker = exchange.GetTicker()
    Log(ticker)
    Log(exchange.GetAccount())
}
def main():
    ticker = exchange.GetTicker()
    Log(ticker)
    Log(exchange.GetAccount())
    exchange.SetCurrency("LTC_USDT")
    Log("Switch to 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 to LTC_USDT");
    ticker = exchange.GetTicker();
    Log(ticker);
    Log(exchange.GetAccount());
}
  1. Compatible with exchange.IO("currency", "BTC_USDT") switching method, please refer to {@fun excahnge.IO}.
  2. Support switching trading pairs in the backtesting system, the name of the denominated currency cannot be changed when switching trading pairs in the backtesting system. For example: BTC_USDT can be switched to LTC_USDT, not to LTC_BTC.
  3. The number of trading currencies is 0 after switching to the trading pair initially set on the non-backtest page. For example, when backtesting the initial trading pair set on the backtest page is BTC_USDT, the number of BTC is 3, the number of USDT is 10000. At this time, switch to LTC_USDT immediately, the number of trading currencies is 0 after switching, i.e. the number of LTC_USDT in the account is 0. That is, the number of LTC in the account is 0, and the switched trading pair shares the number of USDT, which is 10000.

{@fun/Account/exchange.GetCurrency exchange.GetCurrency}

exchange.GetQuoteCurrency

The exchange.GetQuoteCurrency() function is used to get the name of the denominated currency of the current trading pair, i.e. quoteCurrency.

The exchange.GetQuoteCurrency() function returns the name of the denominated currency of the current trading pair. string

exchange.GetQuoteCurrency()

function main() {
    exchange.SetCurrency("BTC_USDT")
    Log("BTC_USDT denominated currency name:", exchange.GetQuoteCurrency())
    // exchange.SetCurrency("ETH_BTC")
    // Log("ETH_BTC denominated currency name:", exchange.GetQuoteCurrency())
}
def main():
    exchange.SetCurrency("BTC_USDT")
    Log("BTC_USDT denominated currency name:", exchange.GetQuoteCurrency())
    # exchange.SetCurrency("ETH_BTC")
    # Log("ETH_BTC denominated currency name:", exchange.GetQuoteCurrency())
void main() {
    exchange.SetCurrency("BTC_USDT");
    Log("BTC_USDT denominated currency name:", exchange.GetQuoteCurrency());
    // exchange.SetCurrency("ETH_BTC")
    // Log("ETH_BTC denominated currency name:", exchange.GetQuoteCurrency())
}

For example: {@var/EXCHANGE exchange} exchange object’s current transaction pair is BTC_USDT, the exchange.GetQuoteCurrency() function returns USDT. If the current trading pair is ETH_BTC, the exchange.GetQuoteCurrency() function returns BTC.

{@fun/Account/exchange.GetCurrency exchange.GetCurrency}, {@fun/Account/exchange.SetCurrency exchange.SetCurrency}

Futures

exchange.GetPositions

The exchange.GetPositions() function is used to get the position information; The GetPositions() function is a member function of the exchange object {@var/EXCHANGE exchange}. The GetPositions() function gets the position information of 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 will not be repeated here.

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

exchange.GetPositions() exchange.GetPositions(symbol)

The parameter symbol is used to set the trading symbol or trading symbol range to be queried. If the symbol parameter is not passed, the default is to request the position data of all symbols 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":"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) {
        exchange.CreateOrder(symbol, "buy", -1, 1)
        exchange.CreateOrder(symbol, "sell", -1, 1)
    }

    var defaultPositions = exchange.GetPositions()
    var swapPositions = exchange.GetPositions("USDT.swap")
    var futuresPositions = exchange.GetPositions("USDT.futures")
    var btcUsdtSwapPositions = exchange.GetPositions("BTC_USDT.swap")

    var tbls = []
    var arr = [defaultPositions, swapPositions, futuresPositions, btcUsdtSwapPositions]
    var tblDesc = ["defaultPositions", "swapPositions", "futuresPositions", "btcUsdtSwapPositions"]
    for (var index in arr) {
        var positions = arr[index]
        var tbl = {type: "table", title: tblDesc[index], cols: ["Symbol", "MarginLevel", "Amount", "FrozenAmount", "Price", "Profit", "Type", "ContractType", "Margin"], rows: [] }
        for (var pos of positions) {
            tbl.rows.push([pos.Symbol, pos.MarginLevel, pos.Amount, pos.FrozenAmount, pos.Price, pos.Profit, pos.Type, pos.ContractType, pos.Margin])
        }
        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:
        exchange.CreateOrder(symbol, "buy", -1, 1)
        exchange.CreateOrder(symbol, "sell", -1, 1)

    defaultPositions = exchange.GetPositions()
    swapPositions = exchange.GetPositions("USDT.swap")
    futuresPositions = exchange.GetPositions("USDT.futures")
    btcUsdtSwapPositions = exchange.GetPositions("BTC_USDT.swap")

    tbls = []
    arr = [defaultPositions, swapPositions, futuresPositions, btcUsdtSwapPositions]
    tblDesc = ["defaultPositions", "swapPositions", "futuresPositions", "btcUsdtSwapPositions"]
    for index in range(len(arr)):
        positions = arr[index]
        tbl = {"type": "table", "title": tblDesc[index], "cols": ["Symbol", "MarginLevel", "Amount", "FrozenAmount", "Price", "Profit", "Type", "ContractType", "Margin"], "rows": []}
        for pos in positions:
            tbl["rows"].append([pos["Symbol"], pos["MarginLevel"], pos["Amount"], pos["FrozenAmount"], pos["Price"], pos["Profit"], pos["Type"], pos["ContractType"], pos["Margin"]])

        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) {
        exchange.CreateOrder(symbol, "buy", -1, 1);
        exchange.CreateOrder(symbol, "sell", -1, 1);
    }
    
    auto defaultPositions = exchange.GetPositions();
    auto swapPositions = exchange.GetPositions("USDT.swap");
    auto futuresPositions = exchange.GetPositions("USDT.futures");
    auto btcUsdtSwapPositions = exchange.GetPositions("BTC_USDT.swap");
    
    json tbls = R"([])"_json;
    std::vector<std::vector<Position>> arr = {defaultPositions, swapPositions, futuresPositions, btcUsdtSwapPositions};
    std::string tblDesc[] = {"defaultPositions", "swapPositions", "futuresPositions", "btcUsdtSwapPositions"};
    for (int index = 0; index < arr.size(); index++) {
        auto positions = arr[index];
        json tbl = R"({
            "type": "table", 
            "cols": ["Symbol", "MarginLevel", "Amount", "FrozenAmount", "Price", "Profit", "Type", "ContractType", "Margin"],
            "rows": []
        })"_json;
        tbl["title"] = tblDesc[index];
    
        for (const auto& pos : positions) {
            json arrJson = R"([])"_json;
    
            arrJson.push_back(pos.Symbol);
            arrJson.push_back(pos.MarginLevel);
            arrJson.push_back(pos.Amount);
            arrJson.push_back(pos.FrozenAmount);
            arrJson.push_back(pos.Price);
            arrJson.push_back(pos.Profit);
            arrJson.push_back(pos.Type);
            arrJson.push_back(pos.ContractType);
            arrJson.push_back(pos.Margin);
    
            tbl["rows"].push_back(arrJson);
        }
    
        tbls.push_back(tbl);
    }
    
    LogStatus(_D(), "\n", "`" + tbls.dump() + "`");
    
    return; 
}

Use futures exchange objects to place market orders for multiple different trading pairs and contract codes. Query positions in multiple ways.

Cryptocurrency futures contracts are different from cryptocurrency spot, which has only the logical concept of a position. In the system of FMZ Quant Trading platform, the specific types of cryptocurrency futures contracts are identified by trading pairs, contract code together. Please refer to {@fun/Account/exchange.SetCurrency exchange.SetCurrency}, {@fun/Futures/exchange.SetContractType exchange.SetContractType} functions. In the GetPositions function, the usage scenarios of the symbol parameter are summarized as follows:

Exchange Object Classification symbol Parameters Query Scope Remark
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-based perpetual contracts will be queried. This is equivalent to calling GetPositions("USDT.swap")
Futures Specify the trading product, the symbol parameter is: “BTC_USDT.swap” Query the USDT-based perpetual contract of a specified BTC For futures exchange objects, the format of parameter symbol 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 product 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 GetPositions function, the futures exchange object query dimension range is summarized as follows:

symbol Parameters Request Scope 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 | Scope of currency-based perpetual contracts. | - |

| USD.futures | Scope 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 | Scope of mixed margin delivery contracts. | Futures_Kraken Exchange |

| USD.swap_pf | Mixed margin perpetual contract range. | Futures_Kraken Exchange |

Compatible with exchange.GetPosition() call, GetPosition is exactly the same as GetPositions.

When the account represented by the exchange object exchange has no positions in the query range or specified trading instruments, the exchange.GetPositions() function returns an empty array, for example: [].

{@struct/Position Position}, {@fun/Account/exchange.SetCurrency exchange.SetCurrency}, {@fun/Futures/exchange.SetContractType exchange.SetContractType}

exchange.SetMarginLevel

The exchange.SetMarginLevel() function is used to set the leverage value of the trading pair or contract specified by the symbol parameter. Compatible with only passing in the parameter marginLevel to set the leverage value of the current trading pair or contract of the {@var/EXCHANGE exchange} exchange object.

exchange.SetMarginLevel(symbol, marginLevel) exchange.SetMarginLevel(marginLevel)

The symbol parameter is used to specify the trading pair or contract for which the leverage value needs to be adjusted. The format of the symbol parameter of the SetMarginLevel() function is consistent with the format of the symbol parameter of the GetTicker() function. symbol false string The marginLevel parameter is used to set the leverage value, which is usually an integer for exchanges and it also supports floating point leverage value settings for some exchanges. marginLevel true number

function main() {
    exchange.SetMarginLevel(10)
    // Set the leverage of BTC’s USDT-margined perpetual contract to 15
    exchange.SetMarginLevel("BTC_USDT.swap", 15)
}
def main():
    exchange.SetMarginLevel(10)
    exchange.SetMarginLevel("BTC_USDT.swap", 15)
void main() {
    exchange.SetMarginLevel(10);
    exchange.SetMarginLevel("BTC_USDT.swap", 15); 
}

The exchange.SetMarginLevel() function supports cryptocurrency futures contract exchange objects only. The backtesting system supports calling the exchange.SetMarginLevel() function to set the leverage value. For cryptocurrency futures contracts, the leverage mechanism is not uniform due to the cryptocurrency futures contract exchanges. In some exchanges, the leverage value of the futures contract is a parameter in the order placement interface, when calling the exchange.SetMarginLevel() function does not generate a network request, but only sets the leverage variable in the underlying FMZ system (used for passing parameters in the order placement interface). The leverage value of some exchange futures contracts is a setting of the exchange, which needs to be set on the exchange website page or using the API interface. In this case calling the exchange.SetMarginLevel() function will generate a network request and may fail to set leverage. There can be many reasons for this, for example: there is a current position or pending order, which makes it impossible to set a new leverage value for this trading pair or contract. Exchanges that do not support the exchange.SetMarginLevel() function:

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
SetMarginLevel Futures_dYdX / Futures_Deribit

{@var/EXCHANGE exchange}

exchange.SetDirection

The exchange.SetDirection() function is used to set the order direction of the {@fun/Trade/exchange.Buy exchange.Buy} function, {@fun/Trade/exchange.Sell exchange.Sell} function when placing orders for futures contracts.

exchange.SetDirection(direction)

The direction parameter is used to set the direction of the futures contract when the order is placed. The optional values are: "buy", "closesell", "sell", "closebuy". direction true string

function main(){
    // For example, set to OKX futures contract of this week
    exchange.SetContractType("this_week")    
    // Set leverage to 5 times
    exchange.SetMarginLevel(5)
    // Set the order type to long
    exchange.SetDirection("buy")
    // Place an order for 2 contracts at 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);
}

The exchange.SetDirection() function sets the correspondence between the direction of the futures contract transaction and the order placement function:

Order placement functions The direction set by the parameters of the SetDirection function Remarks
exchange.Buy “buy” Buy and open long positions
exchange.Buy “closesell” Buy and close short positions
exchange.Sell “sell” Sell and open short positions
exchange.Sell “closebuy” Sell and close long positions

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

exchange.SetContractType

The exchange.SetContractType() function is used to set the current contract code of the {@var/EXCHANGE exchange} exchange object.

The exchange.SetContractType() function returns a structure that contains the exchange contract code corresponding to the current contract code. For example, for the Binance Futures contract exchange, the current contract code is quarter, and the return value structure of this function is: {"InstrumentID": "BTCUSD_230630", "instrument": "BTCUSD_230630"}. object

exchange.SetContractType(symbol)

The symbol parameter is used to set the contract code, the optional values are: "this_week", "next_week", "quarter", "next_quarter", "swap", etc. Cryptocurrency futures contracts delivery contract codes, if not specified, generally have:

  • this_week: the current week’s contract.
  • next_week: the next week’s contract.
  • quarter: quarterly contract.
  • next_quarter: the next quarterly contract. Permanent contracts codes in cryptocurrency futures contracts, if not specified, generally have:
  • swap: perpetual contract.

symbol true string

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

Set the current contract as the current week’s contract:

function main() {
    // The default trading pair is BTC_USD, set the contract for this week, and the contract is a currency standard contract
    exchange.SetContractType("this_week")
    Log("ticker:", exchange.GetTicker())
    
    // Switching trading pairs, then setting up contracts, switching to USDT as margin contracts, as opposed to currency standard contracts
    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());
}

When setting up a contract with USDT as margin, you need to switch the trading pair in the code (you can also set the trading pair directly when adding the exchange object):

function main(){
    // Set the contract for this week
    var ret = exchange.SetContractType("this_week")     
    // Return information about the current week's contracts
    Log(ret)
}
def main():
    ret = exchange.SetContractType("this_week")
    Log(ret)
void main() {
    auto ret = exchange.SetContractType("this_week");
    Log(ret);
}

Print the return value of the exchange.SetContractType() function:

In the cryptocurrency futures contract strategy, take an example of switching to the BTC_USDT trading pair: When switching trading pairs using the exchange.SetCurrency("BTC_USDT") or exchange.IO("currency", "BTC_USDT") functions, after switching, you need to use the exchange.SetContractType() function to reset the contract in order to determine the current contract to be operated under the new trading pair. The system determines whether it is a currency standard contract or a USDT standard contract based on the trading pair. For example, if a trading pair is set to BTC_USDT, use the exchange.SetContractType("swap") function to set the contract code to swap. At this point, it is set to BTC for the USDT standard perpetual contract. If the trading pair is BTC_USD, use the exchange.SetContractType("swap") function to set the contract code to swap. At this point, it is set to BTC's currency standard perpetual contract. Details of the supported cryptocurrency futures contract exchanges, with contract names for each exchange as follows:

  • Futures_OKCoin (OKX) Set to perpetual contracts: exchange.SetContractType("swap") Set to the contract of this week: exchange.SetContractType("this_week") Set to next week’s contract: exchange.SetContractType("next_week") Set to monthly contract: exchange.SetContractType("month") Set to next month contract: exchange.SetContractType("next_month") Set to quarterly contracts: exchange.SetContractType("quarter") Set to next quarter contract: exchange.SetContractType("next_quarter")

    OKX has pre-market trading contracts: the contract delivery date is a fixed time. The contract code defined by the exchange is, for example: HMSTR-USDT-250207. Set the trading pair to HMSTR_USDT on the FMZ platform, and then use exchange.SetContractType("HMSTR-USDT-250207") to set the contract. For functions that support the symbol parameter, such as: exchange.GetTicker(), exchange.CreateOrder(), etc. You can specify the symbol parameter as: HMSTR_USDT.HMSTR-USDT-250207 to obtain the market data of this contract or place an order.

  • Futures_HuobiDM (Huobi futures) Set to the contract of this week: exchange.SetContractType("this_week"). Set to next week’s contract: exchange.SetContractType("next_week"). Set to quarterly contracts: exchange.SetContractType("quarter"). Set to next quarter contract: exchange.SetContractType("next_quarter"). Set to perpetual contracts: exchange.SetContractType("swap"). It supports contracts with USDT as margin, take BTC contract as an example: use exchange.IO("currency", "BTC_USDT") to switch to a contract that uses USDT as margin. Or set the current trading pair to BTC_USDT directly when configuring live trading parameters and adding exchange objects. After switching trading pairs, you need to call exchange.SetContractType() function again to set the contract.

  • Futures_BitMEX (BitMEX) Set to perpetual contracts: exchange.SetContractType("swap"). Futures_BitMEX exchange delivery contracts are monthly contracts with the following contract codes (from January to December):

    "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    

    Setting up delivery contracts: exchange.SetContractType("December"). For example, when the trading pair is set to XBT_USDT, the exchange.SetContractType("December") function is called to set the contract for December delivery in the USDT based of BTC (corresponding to the actual contract code of XBTUSDTZ23).

    Futures_BitMEX Contract Information Summary

    Contract code defined by Futures_BitMEX The corresponding trading pair in FMZ The corresponding contract code in FMZ Remark
    DOGEUSD DOGE_USD swap USD denominated, XBT settled. XBT is BTC.
    DOGEUSDT DOGE_USDT swap USDT denominated, USDT settled.
    XBTETH XBT_ETH swap ETH denominated, XBT settled.
    XBTEUR XBT_EUR swap EUR-denominated, XBT settled.
    USDTUSDC USDT_USDC swap USDC denominated, XBT settled.
    ETHUSD_ETH ETH_USD_ETH swap USD denominated, ETH settled.
    XBTH24 XBT_USD March Expiration date: March 24, month code is: H; USD denominated, XBT settled.
    ETHUSDZ23 ETH_USD December Expiration date: Dec 23, month code is: Z; USD denominated, XBT settled.
    XBTUSDTZ23 XBT_USDT December Expiration date: December 23, month code is: Z ; USDT denominated, USDT settled.
    ADAZ23 ADA_XBT December Expiration date: December 23, month code is: Z ; XBT billing, XBT settled.
    P_XBTETFX23 USDT_XXX P_XBTETFX23 Expiration: 11/23/23; denominated as a percentage and settled in USDT.
  • Futures_GateIO Set to the contract of this week: exchange.SetContractType("this_week"). Set to next week’s contract: exchange.SetContractType("next_week"). Set to quarterly contracts: exchange.SetContractType("quarter"). Set to next quarter contract: exchange.SetContractType("next_quarter"). Set to perpetual contracts: exchange.SetContractType("swap"). It supports contracts with USDT as margin, take BTC contract as an example: use exchange.IO("currency", "BTC_USDT") to switch to a contract that uses USDT as margin. Or set the current trading pair to BTC_USDT directly when configuring live trading parameters and adding exchange objects. After switching trading pairs, you need to call exchange.SetContractType() function again to set the contract.

  • Futures_Deribit Set to perpetual contracts: exchange.SetContractType("swap"). It supports Deribit’s USDC contract. The delivery contracts are: "this_week", "next_week", "month", "quarter", "next_quarter", "third_quarter", "fourth_quarter". CFD (future_combo): "this_week,swap", "next_week,swap", "next_quarter,this_week", "third_quarter,this_week", "month,next_week", there are many combinations. For option contracts you need to pass in the specific option contract code defined by the exchange, see the Deribit website for details.

  • Futures_KuCoin For example, if the trading pair is set to BTC_USD and the contract code is set, it is a currency-based contract: Set to perpetual contracts: exchange.SetContractType("swap"). Set to quarterly contracts: exchange.SetContractType("quarter"). Set to next quarter contract: exchange.SetContractType("next_quarter").

    USDT as margin contract: For example, if the trading pair is set to BTC_USDT, and then set the contract code, it is a contract with USDT as margin. Set to perpetual contracts: exchange.SetContractType("swap").

  • Futures_Binance Binance Futures Exchange defaults to the perpetual contract of the current trading pair, contract code: swap. Set to perpetual contracts: exchange.SetContractType("swap"), the perpetual contracts of Binance have contracts that use USDT as margin. For example, USDT standard perpetual contract of BTC can be used as a margin contract, and the trading pair is set to BTC_USDT. Binance also supports perpetual contracts that use coins as margin, for example, BTC's Binance standard perpetual contract, with the trading pair set to BTC_USD. Set to quarterly contracts: exchange.SetContractType("quarter"), the delivery contract has a currency standard contract (i.e., using currencies as margin), for example, BTC's quarterly contract, the trading pair is set to: BTC_USD and then set the contract exchange.SetContractType("quarter"), it is set to BTC quarterly contract with a currency standard contract. Set to next quarter contract: exchange.SetContractType("next_quarter"), for example, BTC of the currency standard quarterly contract, the trading pair set to: BTC_USD, and then set the contract exchange.SetContractType("next_quarter"). Binance supports partial USDT as margin delivery contract, take BTC as an example, set trading pair to BTC_USDT, then set the contract code.

    Support for Binance Options contracts: The format of the option contract code is based on the option contract code defined by the exchange: BTC-241227-15000-C, XRP-240112-0.5-C, BTC-241227-15000-P. Take the Binance option contract code BTC-241227-15000-P as an example: BTC is the option currency code, 241227 is the exercise date, 15000 is the exercise price, P represents a put option, and C represents a call option. For details on the option type, whether it is European option or American option, please refer to the relevant information of the exchange’s option contract. The exchange may restrict option sellers and require them to apply for qualifications separately. Binance options require seller qualifications.

  • Futures_Bibox Contract code for Bibox perpetual contracts: swap. Set to perpetual contracts: exchange.SetContractType("swap").

  • Futures_Bybit The default is the perpetual contract for the current trading pair, contract code: swap. This week contract code: this_week. Next week contract code: next_week. Third week contract code: third_week. Monthly contract code: month. Next month contract code: next_month. Quarterly contract code: quarter. Next quarter contract code: next_quarter. Third quarter contract code: third_quarter.

  • Futures_Kraken The default is the perpetual contract of the current trading pair, contract code: swap. swap: perpetual contract. month: current month contract. quarter: quarterly contract. next_quarter: next quarter contract. swap_pf: Mixed margin perpetual contract. quarter_ff: Mixed margin quarterly contract. month_ff: Mixed margin current month contract. next_quarter_ff: Mixed margin next quarter contract.

  • Futures_Bitfinex Default is the perpetual contract for the current trading pair, contract code: swap.

  • Futures_Bitget Default is the perpetual contract for the current trading pair, contract code: swap. The trading pair is set to BTC_USD for currency standard contracts, and the trading pair is set to BTC_USDT for contracts settled by USDT. Demo contracts can be set up with trading pairs as SBTC_USD, BTC_SUSDT.

  • Futures_dYdX Contract code for dYdX perpetual contracts: swap. Set to perpetual contracts: exchange.SetContractType("swap"), dYdX has USDT standard contracts only.

  • Futures_MEXC Contract code for MEXC perpetual contracts: swap. Set to perpetual contracts: exchange.SetContractType("swap"). Set trading pair to BTC_USD, which is currency standard contract, and set trading pair to BTC_USDT, which is USDT-settled contract.

  • Futures_Crypto Tokens in an account on the crypto.com exchange can be converted into USD-denominated credits to be used as margin for contract trading. Set to perpetual contract: exchange.SetContractType("swap"). Example of calling the exchange.SetContractType("swap") function to set a perpetual contract for BTC when the trading pair is set to BTC_USD. The crypto.com exchange delivery contracts are monthly contracts with the following contract codes (from January to December):

    "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    

    Set the delivery contract: exchange.SetContractType("October"). For example, when the trading pair is set to BTC_USD, call the function exchange.SetContractType("October") to set the October delivery contract for BTC. The corresponding contract code at the current moment is: BTCUSD-231027.

  • Futures_WOO Futures_WOO exchange supports USDT based contracts with a perpetual contract code of swap. For example, when the trading pair is set to BTC_USDT, the function exchange.SetContractType("swap") is called to set the current contract to be a USDT based perpetual contract for BTC.

{@fun/Futures/exchange.GetContractType exchange.GetContractType}, {@fun/Account/exchange.SetCurrency exchange.SetCurrency}

exchange.GetContractType

The exchange.GetContractType() function is used to get the contract code for the current setting of the {@var/EXCHANGE exchange} exchange object.

The exchange.GetContractType() function returns the contract code defined by the FMZ platform, for example: this_week, swap, etc. string

exchange.GetContractType()

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());
}

{@fun/Futures/exchange.SetContractType exchange.SetContractType}

exchange.GetFundings

The exchange.GetFundings() function is used to obtain the funding rate data for the current period.

The exchange.GetFundings() function returns an array of {@struct/Funding Funding} structures when the data request is successful, and returns a null value when the data request fails. {@struct/Funding Funding} array, null value

exchange.GetFundings() exchange.GetFundings(symbol)

The parameter symbol is used to set the transaction symbol or transaction symbol range to be queried. When the symbol parameter is not passed, the current funding rate data of all instruments will be requested by default in the dimension range of the current trading pair and contract code.

symbol false string

/*backtest
start: 2024-10-01 00:00:00
end: 2024-10-23 00:05:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDC"}]
*/

function main() {
    // LPT_USDT.swap 4-hour period
    var symbols = ["SOL_USDT.swap", "ETH_USDT.swap", "LTC_USDT.swap", "SOL_USDC.swap", "ETH_USDC.swap", "BTC_USD.swap", "BTC_USDT.quarter", "LPT_USDT.swap"]
    for (var symbol of symbols) {
        exchange.GetTicker(symbol)
    }
    
    var arr = []
    var arrParams = ["no param", "LTC_USDT.swap", "USDT.swap", "USD.swap", "USDC.swap", "USDT.futures", "BTC_USDT.quarter"]
    for (p of arrParams) {
        if (p == "no param") {
            arr.push(exchange.GetFundings())
        } else {
            arr.push(exchange.GetFundings(p))
        }
    }
    
    var tbls = []
    var index = 0
    for (var fundings of arr) {
        var tbl = {
            "type": "table",
            "title": arrParams[index],
            "cols": ["Symbol", "Interval", "Time", "Rate"],
            "rows": [],
        }
    
        for (var f of fundings) {
            tbl["rows"].push([f.Symbol, f.Interval / 3600000, _D(f.Time), f.Rate * 100 + " %"])
        }
        tbls.push(tbl)
        index++
    }
    
    LogStatus(_D(), "\n Requested market types:", symbols, "\n`" + JSON.stringify(tbls) + "`")
}
'''backtest
start: 2024-10-01 00:00:00
end: 2024-10-23 00:05:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDC"}]
'''
    
import json
    
def main():
    # LPT_USDT.swap 4-hour period
    symbols = ["SOL_USDT.swap", "ETH_USDT.swap", "LTC_USDT.swap", "SOL_USDC.swap", "ETH_USDC.swap", "BTC_USD.swap", "BTC_USDT.quarter", "LPT_USDT.swap"]
    for symbol in symbols:
        exchange.GetTicker(symbol)
    
    arr = []
    arrParams = ["no param", "LTC_USDT.swap", "USDT.swap", "USD.swap", "USDC.swap", "USDT.futures", "BTC_USDT.quarter"]
    for p in arrParams:
        if p == "no param":
            arr.append(exchange.GetFundings())
        else:
            arr.append(exchange.GetFundings(p))
    
    tbls = []
    index = 0
    for fundings in arr:
        tbl = {
            "type": "table",
            "title": arrParams[index],
            "cols": ["Symbol", "Interval", "Time", "Rate"],
            "rows": [],
        }
    
        for f in fundings:
            tbl["rows"].append([f["Symbol"], f["Interval"] / 3600000, _D(f["Time"]), str(f["Rate"] * 100) + " %"])
    
        tbls.append(tbl)
        index += 1
    
    LogStatus(_D(), "\n Requested market types:", symbols, "\n`" + json.dumps(tbls) + "`")
/*backtest
start: 2024-10-01 00:00:00
end: 2024-10-23 00:05:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDC"}]
*/
    
void main() {
    // LPT_USDT.swap 4-hour period
    json arrSymbol = R"([])"_json;
    std::string symbols[] = {"SOL_USDT.swap", "ETH_USDT.swap", "LTC_USDT.swap", "SOL_USDC.swap", "ETH_USDC.swap", "BTC_USD.swap", "BTC_USDT.quarter", "LPT_USDT.swap"};
    for (const std::string& symbol : symbols) {
        exchange.GetTicker(symbol);
        arrSymbol.push_back(symbol);
    }
    
    std::vector<std::vector<Funding>> arr = {};
    std::string arrParams[] = {"no param", "LTC_USDT.swap", "USDT.swap", "USD.swap", "USDC.swap", "USDT.futures", "BTC_USDT.quarter"};
    for (const std::string& p : arrParams) {
        if (p == "no param") {
            arr.push_back(exchange.GetFundings());
        } else {
            arr.push_back(exchange.GetFundings(p));
        }
    }
    
    json tbls = R"([])"_json;
    int index = 0;
    for (int i = 0; i < arr.size(); i++) {
        auto fundings = arr[i];
    
        json tbl = R"({
            "type": "table", 
            "cols": ["Symbol", "Interval", "Time", "Rate"],
            "rows": []
        })"_json;
        tbl["title"] = arrParams[index];
    
        for (int j = 0; j < fundings.size(); j++) {
            auto f = fundings[j];
            // json arrJson = {f.Symbol, f.Interval / 3600000, _D(f.Time), string(f.Rate * 100) + " %"};
            json arrJson = {f.Symbol, f.Interval / 3600000, _D(f.Time), f.Rate};
            tbl["rows"].push_back(arrJson);
        }
        tbls.push_back(tbl);
        index++;
    }
    
    LogStatus(_D(), "\n Requested market types:", arrSymbol.dump(), "\n`" + tbls.dump() + "`");
}

Use the futures exchange object to call the exchange.GetFundings() function in the backtesting system. Before calling any market function, GetFundings only returns the Funding data of the current default trading pair. After calling the market function, it returns the Funding data of all requested varieties. You can refer to the following test example:

For futures exchanges that do not support batch query of funding rate data, if the symbol parameter is specified as the query range, for example: USDT.swap or the symbol parameter is not passed, the interface will report an error. When calling the GetFundings() function using this type of futures exchange object, you must specify the symbol parameter as a specific perpetual contract type in order to query the current funding rate data of the type. The exchange.GetFundings() function supports real trading and backtesting systems. Exchanges that do not support batch acquisition of funding rate data: Futures_Bitget, Futures_OKX, Futures_MEXC, Futures_Deribit, Futures_Crypto. Need to pass in the symbol parameter with the specific symbol code, for example: ETH_USDT.swap.

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

Function Name Unsupported Spot Exchanges Unsupported Futures Exchanges
GetFundings Futures_DigiFinex

{@struct/Funding Funding}

NetSettings

exchange.SetBase

The exchange.SetBase() function is used to set the base address of the exchange API interface configured in the {@var/EXCHANGE exchange} exchange object.

exchange.SetBase(s)

The s parameter is used to specify the exchange API interface base address. s true string

function main() {
    // Use 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());
}

Switching the exchange API base address is not supported in the backtesting system, because the backtesting system is a sandbox simulation environment and it does not really access the exchange API interface.

{@fun/Trade/exchange.IO exchange.IO}

exchange.GetBase

The exchange.GetBase() function is used to get the current exchange API interface base address.

The current exchange API interface base address. string

exchange.GetBase()

function main() {
    Log(exchange.GetBase())
}
def main():
    Log(exchange.GetBase())
void main() {
    Log(exchange.GetBase());
}

{@fun/NetSettings/exchange.SetBase exchange.SetBase}

exchange.SetProxy

The exchange.SetProxy() function is used to set the proxy configuration of the {@var/EXCHANGE exchange} exchange object.

exchange.SetProxy(proxy)

The proxy parameter is used to specify the proxy configuration. proxy true string

function main() {
    exchange.SetProxy("socks5://192.168.1.10:8080")
    // If you can't access the exchange ticker interface, set up an available ss5 proxy and you can access the ticker interface
    Log(exchange.GetTicker())
}
def main():
    exchange.SetProxy("socks5://192.168.1.10:8080")
    Log(exchange.GetTicker())
void main() {
    exchange.SetProxy("socks5://192.168.1.10:8080");
    Log(exchange.GetTicker());
}

Configure the {@var/EXCHANGE exchange} exchange object socks5 proxy:

function main(){
    exchange.SetProxy("ip://10.0.3.15")
    // The requested IP address is 10.0.3.15
    exchange.GetTicker()
}
def main():
    exchange.SetProxy("ip://10.0.3.15")
    exchange.GetTicker()
void main() {
    exchange.SetProxy("ip://10.0.3.15");
    exchange.GetTicker();
}

In addition to global specification of the IP address of the request from the {@var/EXCHANGE exchange} exchange object, there is also support for specifying an IP address based on {@var/EXCHANGE exchange}:

If the proxy setting fails, the exchange.SetProxy() function will return null when called. The exchange.SetProxy() function sets the proxy for the rest protocol only. One proxy can be set for each {@var/EXCHANGE exchange} exchange object, and access to the exchange interface bound to the {@var/EXCHANGE exchange} exchange object after setting the proxy will be accessed through the proxy. Support for setting socks5 proxy, taking the first exchange object added {@var/EXCHANGE exchange} i.e.: exchanges[0] as an example:

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

Supports setting the IP address of the request from the {@var/EXCHANGE exchange} exchange object, globally specified.

{@var/EXCHANGE exchange}

exchange.SetTimeout

The exchange.SetTimeout() function is used to set the timeout of the rest request for the {@var/EXCHANGE exchange} exchange object.

exchange.SetTimeout(timeout)

The timeout parameter is used to specify the number of milliseconds for the timeout setting. timeout true number

function main() {
    exchange.SetTimeout(3000)
    Log(exchange.GetTicker())
}
def main():
    exchange.SetTimeout(3000)
    Log(exchange.GetTicker())
void main() {
    exchange.SetTimeout(3000);
    Log(exchange.GetTicker());
}

The parameter timeout is a millisecond value, 1000 milliseconds equals 1 second. Restricted to the rest protocol only, used to set the timeout on rest requests, it takes effect by setting once only. For example, exchange.SetTimeout(3000), sets the rest request timeout for the exchange exchange object to 3 seconds. Calling functions with network requests such as exchange.GetTicker() that do not receive an answer for more than 3 seconds will time out, and function calls that do time out will return null values. SetTimeout() is not a global function, it is a method of the {@var/EXCHANGE exchange} exchange object.

{@var/EXCHANGE exchange}

Threads

The FMZ Quant Trading Platform truly supports the multi-threaded function of the JavaScript language strategy from the bottom of the system, and implements the following objects:

Objects Directions Remarks
threading Multithreaded global object Member functions: Thread, getThread, mainThread, etc.
Thread Thread object Member functions: peekMessage, postMessage, join, etc.
ThreadLock Thread lock object Member functions: acquire, release. They can be passed into the thread environment as parameters of the thread execution function.
ThreadEvent Event object Member functions: set, clear, wait, isSet. They can be passed into the thread environment as a parameter of the thread execution function.
ThreadCondition Condition object Member functions: notify, notifyAll, wait, acquire, release. They can be passed into the thread environment as a parameter of the thread execution function.
ThreadDict Dictionary object Member functions: get, set. They can be passed into the thread environment as parameters of the thread execution function.

threading

The threading object is a global multithreading management tool that provides functions such as creating concurrent threads, thread locks, and condition objects. This section introduces the member functions of the threading object. This object is only supported by the JavaScript language strategy.

Thread

The Thread() function is used to create concurrent threads.

The Thread() function returns a Thread object, which is used to manage created concurrent threads, thread communication, etc.

Thread object

Thread(func, …args) Thread(…items)

The parameter func is a function for concurrent execution (passed by reference), and supports passing in anonymous functions. func can accept multiple parameters, which will be passed in through ...args during concurrent execution. Therefore, the parameter list of func needs to be consistent with ...args.

func true function The parameter arg is the actual parameter passed to func (i.e. the concurrent thread execution function) when the callback is executed; there may be multiple parameters arg, and the parameter list of func needs to be consistent with ...args.

arg false string, number, bool, object, array, function, null value and other types supported by the system The parameter item is an array containing the function references and their parameters to be executed concurrently. Multiple groups of item parameters can be passed in when calling the Thread function.

item true array

function test1(a, b, c) {
    Log("test1:", a, b, c)
}

function main() {
    var t1 = threading.Thread(test1, 1, 2, 3)
    var t2 = threading.Thread(function (msg) {
        Log("msg:", msg)
    }, "Hello thread2")

    t1.join()
    t2.join()
}

Create concurrent threads for both a custom function and an anonymous function.

function test1(msg) {
    Log("msg:", msg)
    test2("Hello test2")
}

function main() {
    var t1 = threading.Thread(
        [function(a, b, c) {Log(a, b, c)}, 1, 2, 3], 
        [test1, "Hello test1"], 
        [`function test2(msg) {Log("msg:", msg)}`])

    t1.join()
}

Use the Thread(...items) form to create concurrent threads and execute multiple functions sequentially.

function testFunc1(p) {
    Log("testFunc1 p:", p)
}

function main() {
    threading.Thread(function(pfn) {
        var threadName = threading.currentThread().name()
        var threadId = threading.currentThread().id()
        pfn(`in thread threadName: ${threadName}, threadId: ${threadId}`)
    }, testFunc1).join()
}

It supports passing parameters to concurrently executed functions.

function ml(input) {
    const net = new brain.NeuralNetwork()
    net.train([
        { input: [0, 0], output: [0] },
        { input: [0, 1], output: [1] },
        { input: [1, 0], output: [1] },
        { input: [1, 1], output: [0] },
    ])
    return net.run(input)
}

function main() {
    var ret = threading.Thread([ml, [1, 0]], [HttpQuery("https://unpkg.com/brain.js")]).join()

    // ret: {"id":1,"terminated":false,"elapsed":337636000,"ret":{"0":0.9339330196380615}}
    Log(ret)
}

It supports passing in function strings and can import external libraries dynamically for concurrent computing.

The thread function func passed into the Thread() function for concurrent execution runs in an isolated environment, so variables outside the thread cannot be directly referenced, and compilation will fail when referenced. At the same time, references to other closure functions are not supported within the thread. All APIs provided by the platform can be called within the thread, but other user-defined functions cannot be called.

It supports backtesting system and live trading environment. All concurrent thread-related functions are only supported as code compatibility in the backtesting system and will not be actually executed by concurrent threads, so they will not be repeated in this chapter.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

getThread

The getThread() function is used to get the thread object based on the specified thread Id.

The getThread() function returns the Thread object with the threadId specified by the parameter

Thread object

getThread(threadId)

The parameter threadId is the thread object ID. Get the corresponding thread object by specifying the parameter.

threadId true number

function main() {
    var t1 = threading.Thread(function () {
        Log("Hello thread1")
    })
    // The Thread object has a method: id(), which is used to get the thread ID. You can view the section of the document corresponding to the Thread object.
    var threadId = t1.id()
    var threadName = t1.name()
    Log("threadId:", threadId, ", threadName:", threadName)
    
    var t2 = threading.getThread(threadId)
    Log(`threadId == t2.id():`, threadId == t2.id(), `, threadName == t2.name():`, threadName == t2.name())
}

Get the specified thread object through threadId.

It supports backtesting system and live trading environment.

If the thread you want to obtain has been executed and released, you cannot use threading.getThread(threadId) to obtain the thread object of the thread.

{@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

mainThread

The mainThread() function is used to obtain the thread object of the main thread, that is, the thread where the main() function in the strategy is located.

The mainThread() function returns the thread object of the main thread.

Thread object

mainThread()

function main() {
    Log("The threadId of the main thread:", threading.mainThread().id())
}

Get the Thread object of the main thread and output the threadId of the main thread.

function test() {
    Log("Output the main thread ID in the test function:", threading.mainThread().id())
}

function main() {
    var t1 = threading.Thread(test)
    t1.join()
}

The thread object of the main thread can also be obtained in concurrent threads.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

currentThread

The currentThread() function is used to get the thread object of the current thread.

The currentThread() function returns the thread object of the current thread.

Thread object

currentThread()

function test() {
    Log("Id of the current thread:", threading.currentThread().id())
}

function main() {
    var t1 = threading.Thread(test)
    t1.join()
}

Get the Thread object of the current thread and output the threadId of the current thread.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

Lock

The Lock() function is used to create a thread lock object.

The Lock() function returns a thread lock object.

ThreadLock object

Lock()

function consumer(productionQuantity, dict, lock) {
    for (var i = 0; i < productionQuantity; i++) {
        lock.acquire()
        var count = dict.get("count")        
        Log("consumer:", count)
        Sleep(1000)
        lock.release()
    }
}

function producer(productionQuantity, dict, lock) {
    for (var i = 0; i < productionQuantity; i++) {
        lock.acquire()
        dict.set("count", i)
        Log("producer:", i)
        Sleep(1000)
        lock.release()
    }
}

function main() {
    var dict = threading.Dict()
    dict.set("count", -1)
    var lock = threading.Lock()
    var productionQuantity = 10
    var producerThread = threading.Thread(producer, productionQuantity, dict, lock)
    var consumerThread = threading.Thread(consumer, productionQuantity, dict, lock)

    consumerThread.join()
    producerThread.join()
}

Two concurrent threads access a common resource.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

Condition

The Condition() function is used to create a condition variable object, which is used to achieve synchronization and communication between threads in a multi-threaded concurrent environment. Through Condition(), a thread can wait when certain conditions are not met until another thread notifies it that the condition has been met.

The Condition() function returns a ThreadCondition object.

ThreadCondition object

Condition()

function consumer(productionQuantity, dict, condition) {
    for (var i = 0; i < productionQuantity; i++) {
        condition.acquire()
        while (dict.get("array").length == 0) {
            condition.wait()
        }
        var arr = dict.get("array")
        var count = arr.shift()
        dict.set("array", arr)
        Log("consumer:", count, ", array:", arr)
        condition.release()
        Sleep(1000)
    }
}

function producer(productionQuantity, dict, condition) {
    for (var i = 0; i < productionQuantity; i++) {
        condition.acquire()
        var arr = dict.get("array")
        arr.push(i)
        dict.set("array", arr)
        Log("producer:", i, ", array:", arr)
        condition.notify()
        condition.release()
        Sleep(1000)
    }
}

function main() {
    var dict = threading.Dict()
    dict.set("array", [])
    var condition = threading.Condition()
    var productionQuantity = 10
    var producerThread = threading.Thread(producer, productionQuantity, dict, condition)
    var consumerThread = threading.Thread(consumer, productionQuantity, dict, condition)
    consumerThread.join()
    producerThread.join()
}

Two concurrent threads access a common resource.

The backtesting system does not implement this functionality, it only defines it.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

Event

The Event() function is used to create a thread event object, which is used for synchronization between threads, allowing one thread to wait for notification or signal from another thread.

The Event() function returns a ThreadEvent object.

ThreadEvent object

Event()

function consumer(productionQuantity, dict, pEvent, cEvent) {
    for (var i = 0; i < productionQuantity; i++) {
        while (dict.get("array").length == 0) {
            pEvent.wait()
        }
        if (pEvent.isSet()) {
            pEvent.clear()
        }

        var arr = dict.get("array")
        var count = arr.shift()
        dict.set("array", arr)
        Log("consumer:", count, ", array:", arr)
        cEvent.set()
        Sleep(1000)
    }
}

function producer(productionQuantity, dict, pEvent, cEvent) {
    for (var i = 0; i < productionQuantity; i++) {
        while (dict.get("array").length != 0) {
            cEvent.wait()
        }
        if (cEvent.isSet()) {
            cEvent.clear()
        }

        var arr = dict.get("array")
        arr.push(i)
        dict.set("array", arr)
        Log("producer:", i, ", array:", arr)        
        pEvent.set()       
        Sleep(1000)
    }
}

function main() {    
    var dict = threading.Dict()
    dict.set("array", [])
    var pEvent = threading.Event()
    var cEvent = threading.Event()
    var productionQuantity = 10
    var producerThread = threading.Thread(producer, productionQuantity, dict, pEvent, cEvent)
    var consumerThread = threading.Thread(consumer, productionQuantity, dict, pEvent, cEvent)

    consumerThread.join()
    producerThread.join()
}

Two concurrent threads access a common resource.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

Dict

The Dict() function is used to create a dictionary object for passing to concurrent threads.

The Dict() function returns a ThreadDict object.

ThreadDict object

Dict()

function threadFun1(obj) {
    obj["age"] = 100
    while (true) {
        Log("threadFun1 obj:", obj)
        Sleep(5000)
    }
}

function threadFun2(obj) {
    while (true) {
        Log("threadFun2 obj:", obj)
        Sleep(5000)
    }
}

function main() {
    var obj = {"age": 10}
    var t1 = threading.Thread(threadFun1, obj)
    var t2 = threading.Thread(threadFun2, obj)
    t1.join()
    t2.join()    
}

Pass a normal object to the concurrent thread execution function to test whether modifying the key value of the object will cause changes in the key value of the object in other threads.

function threadFun1(threadDict) {
    threadDict.set("age", 100)
    while (true) {
        Log(`threadFun1 threadDict.get("age"):`, threadDict.get("age"))
        Sleep(5000)
    }
}

function threadFun2(threadDict) {
    while (true) {
        Log(`threadFun2 threadDict.get("age"):`, threadDict.get("age"))
        Sleep(5000)
    }
}

function main() {
    var threadDict = threading.Dict()
    threadDict.set("age", 10)
    var t1 = threading.Thread(threadFun1, threadDict)
    var t2 = threading.Thread(threadFun2, threadDict)

    t1.join()
    t2.join()    
}

Pass the ThreadDict object created by the Dict() function to the concurrent thread execution function, and test whether modifying the key value of the object will cause the key value of the object in other threads to change.

When a common object is passed to a concurrent thread function, it is passed as a deep copy. Modifying the key value in a concurrent thread will not affect the dictionary in other threads.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/pending pending}, {@fun/Threads/threading/eventLoop eventLoop}

pending

The pending function is used to obtain the number of concurrent threads running in the current strategy program.

The pending() function returns the number of concurrent threads that the current strategy program is running.

number

pending()

function threadFun1() {
    Log("threadFun1")
    Sleep(3000)
}

function threadFun2() {
    for (var i = 0; i < 3; i++) {
        LogStatus(_D(), "print from threadFun2")
        Sleep(3000)
    }
}

function main() {
    Log(`begin -- threading.pending():`, threading.pending())

    var t1 = threading.Thread(threadFun1)
    var t2 = threading.Thread(threadFun2)
    Log(`after threading.Thread -- threading.pending():`, threading.pending())

    t1.join()
    t2.join()
    Log(`after thread.join -- threading.pending():`, threading.pending())
}

Create two concurrently running threads and call the pending() function at different time nodes.

When the strategy main() function starts running, calling the function pending() directly will return 1, because the main thread where the strategy main() function is located is also a pending thread.

It supports backtesting system and live trading environment.

{@fun/Threads/threading/getThread getThread}, {@fun/Threads/threading/mainThread mainThread}, {@fun/Threads/threading/currentThread currentThread}, {@fun/Threads/threading/Lock Lock}, {@fun/Threads/threading/Condition Condition}, {@fun/Threads/threading/Event Event}, {@fun/Threads/threading/Dict Dict}, {@fun/Threads/threading/Thread Thread}, {@fun/Threads/threading/eventLoop eventLoop}

Thread

Thread objects can be created or returned by threading.Thread(), threading.getThread(), threading.mainThread(), and threading.currentThread().

peekMessage

The peekMessage() function is used to get a message from a thread.

The peekMessage() function returns the message received by the thread associated with the current thread object.

string, number, bool, object, array, null value and other types supported by the system

peekMessage() peekMessage(timeout)

The parameter timeout is the timeout setting. It will block and wait for the number of milliseconds set by the parameter and return data. If there is no data and the timeout exceeds the limit, a null value will be returned. If timeout is set to 0 or the timeout parameter is not passed, it means that the process will block and wait until data is received from the channel. If timeout is set to -1, it means that the process will not block and return data immediately. If there is no data, a null value will be returned.

timeout false number

function main() {
    var t1 = threading.Thread(function() {
        for (var i = 0; i < 10; i++) {
            Log("thread1 postMessage():", i)
            threading.mainThread().postMessage(i)
            Sleep(500)
        }        
    })

    while (true) {
        var msg = threading.currentThread().peekMessage()
        Log("main peekMessage():", msg)
        if (msg == 9) {
            break
        }
        Sleep(1000)
    }

    t1.join()
}

Send messages to the main thread from a concurrent thread.

When writing programs, we need to pay attention to thread deadlock problems.

{@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

postMessage

The postMessage() function is used to send a message to a thread.

postMessage(msg)

The parameter msg is the message to be sent.

msg true Any type supported by the system, such as string, number, bool, object, array, function, null value, etc.

function main() {
    var t1 = threading.Thread(function() {
        for (var i = 0; i < 10; i++) {
            Log("thread1 postMessage():", i)
            threading.mainThread().postMessage(i)
            Sleep(500)
        }        
    })
    for (var i = 0; i < 10; i++) {
        var event = threading.mainThread().eventLoop()
        Log("main event:", event)
        Sleep(500)
    }
    t1.join()
}

Send messages in concurrent threads and use eventLoop() to receive message notifications.

function main() {
    threading.mainThread().postMessage(function(msg) {
        Log("func from mainThread, msg:", msg)
    })
    
    threading.Thread(function() {
        var func = threading.mainThread().peekMessage()
        func("in " + threading.currentThread().name())
    }).join()
}

It supports sending a function.

When a thread’s execution function calls the postMessage() function to send a signal or data, a message event is also generated. We can use the eventLoop() function to receive message notifications.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

join

The join() function is used to wait for the thread to exit and reclaim system resources.

The ThreadRet object contains data about the execution result. The properties include the following:

  • id: Thread Id.
  • terminated: Whether the thread is forced to end.
  • elapsed: The running time of the thread in nanoseconds.
  • ret: The return value of the thread function.

ThreadRet object

join() join(timeout)

The timeout parameter is used to set the timeout in milliseconds for waiting for the thread to finish. When the timeout parameter is set to 0 or the timeout parameter is not set, the join() function will block and wait until the thread finishes executing. When the timeout parameter is set to -1, the join() function will return immediately.

timeout false number

function main() {
    var t1 = threading.Thread(function() {
        Log("Hello thread1")
        Sleep(5000)
    })

    var ret = t1.join(1000)
    Log("ret:", ret)   // ret: undefined

    ret = t1.join()
    Log("ret:", ret)   // ret: {"id":1,"terminated":false,"elapsed":5003252000}
}

Test the join() function for timeout and output the return value.

The join() function times out and returns undefined.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

terminate

The terminate() function is used to forcibly terminate a thread and release the hardware resources used by the created thread.

terminate()

function main() {
    var t1 = threading.Thread(function() {
        for (var i = 0; i < 10; i++) {
            Log("thread1 i:", i)
            Sleep(1000)
        }
    })

    Sleep(3000)
    t1.terminate()
    Log("after t1.terminate()")

    while (true) {
        LogStatus(_D())
        Sleep(1000)
    }
}

Terminate the execution of a thread forcefully. After forcibly terminating a thread, there will be no output from this thread in the log.

For threads that are forcibly terminated by the terminate() function, we can no longer use the join() function to wait for them to terminate.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

getData

The getData() function is used to access variables recorded in the thread environment. The data is valid when the thread has not executed the join() function (waiting for exit success) and has not executed the terminate() function (terminating the thread forcibly).

The getData() function returns the key value corresponding to the key parameter in the key-value pair stored in the current thread context.

string, number, bool, object, array, null value and other types supported by the system

getData() getData(key)

The key parameter is the key name of the stored key-value pair.

key true string

function main() {
    var t1 = threading.Thread(function() {
        for (var i = 0; i < 5; i++) {
            threading.currentThread().setData("count", i)
            Log(`setData("count"):`, i)
            Sleep(1000)
        }
    })
    for (var i = 0; i < 5; i++) {
        var count = threading.getThread(t1.id()).getData("count")
        Log(`getData("count"):`, count)
        Sleep(1000)
    }
    t1.join()
}

Record the value of the key count in the concurrent thread environment, and then read the key value of count in the main thread.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

setData

The setData() function is used to store variables in the thread context.

setData(key, value)

The key parameter is used to specify the key name of the stored key-value pair.

key true string The value parameter is used to specify the key value of the stored key-value pair.

value true Any type supported by the system, such as string, number, bool, object, array, function, null value, etc.

function main() {
    var t1 = threading.Thread(function() {
        threading.currentThread().setData("data", 100)
    })
    Sleep(1000)
    Log(`t1.getData("data"):`, t1.getData("data"))
    t1.join()
}

Set the key-value pair in the concurrent thread and read the key-value pair in the main thread.

function main() {
    threading.mainThread().setData("func2", function(p) {
        Log("func2 p:", p)
    })
    
    var t1 = threading.Thread(function() {
        threading.currentThread().setData("func1", function(p) {
            Log("func1 p:", p)
        })
    
        var func2 = threading.mainThread().getData("func2")
        func2("test2")
    })
    
    Sleep(1000)
    var func1 = t1.getData("func1")
    func1("test1")
    t1.join()
}

It supports key-value passing into functions.

The data is valid when the thread has not executed the join() function (waiting for exit success) and has not executed the terminate() function (terminating the thread forcibly). The value of the parameter value must be a serializable variable.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

id

The id() function is used to return the threadId of the current multithreaded object instance.

The return value of the id() function is threadId.

number

id()

function main() {
    var t1 = threading.Thread(function() {
        threading.currentThread().setData("data", 100)
    })
    Log(`t1.id():`, t1.id())
    t1.join()
}

Create a concurrently running thread and output the threadId of this concurrent thread in the main thread.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/name name}, {@fun/Threads/Thread/eventLoop eventLoop}

name

The name() function is used to return the name of the current multithreaded object instance.

The name() function returns the concurrent thread name.

string

name()

function main() {
    var t1 = threading.Thread(function() {
        threading.currentThread().setData("data", 100)
    })
    Log(`t1.name():`, t1.name())  // t1.name(): Thread-1
    t1.join()
}

Create a concurrent thread and output the name of the concurrent thread in the main thread.

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/eventLoop eventLoop}

eventLoop

The eventLoop() function is used to listen for events received by the thread.

The eventLoop() function returns the event information received by the current thread. See Event Information Structure.

object, null value

eventLoop() eventLoop(timeout)

The parameter timeout is the timeout setting in milliseconds. If the parameter timeout is set to 0, it will wait for an event to occur before returning. If it is greater than 0, it will set the event waiting timeout. If it is less than 0, it will return the latest event immediately.

timeout false number

function main() {
    var t1 = threading.Thread(function() {
        while (true) {
            var eventMsg = threading.currentThread().eventLoop()     // Blocking wait
            // 2024-11-14 10:14:18 thread1 eventMsg: {"Seq":1,"Event":"thread","ThreadId":0,"Index":1,"Queue":0,"Nano":1731550458699947000}
            Log(_D(), "thread1 eventMsg:", eventMsg)
        }
    })

    var t2 = threading.Thread(function() {
        while (true) {
            var eventMsg = threading.currentThread().eventLoop(-1)   // Return immediately
            Log(_D(), "thread2 eventMsg:", eventMsg)
            Sleep(5000)
        }
    })

    var t3 = threading.Thread(function() {
        while (true) {
            var eventMsg = threading.currentThread().eventLoop(3000) // Set a 3 second timeout
            Log(_D(), "thread3 eventMsg:", eventMsg)
        }
    })

    t1.postMessage("Hello ", t1.name())
    t2.postMessage("Hello ", t2.name())
    t3.postMessage("Hello ", t3.name())
    t1.join()
    t2.join()
    t3.join()
}

Execute three threads concurrently and output the received event information. If the timeout occurs or the function returns immediately, the output value is null.

The processing mechanism of the eventLoop() function is the same as the global function EventLoop().

{@fun/Threads/Thread/peekMessage peekMessage}, {@fun/Threads/Thread/postMessage postMessage}, {@fun/Threads/Thread/join join}, {@fun/Threads/Thread/terminate terminate}, {@fun/Threads/Thread/getData getData}, {@fun/Threads/Thread/setData setData}, {@fun/Threads/Thread/id id}, {@fun/Threads/Thread/name name}

ThreadLock

Thread lock object, used for multi-thread synchronization processing.

acquire

The acquire() function is used to request a thread lock (lock).

acquire()

Please refer to the threading.Lock() section for examples.

The acquire() function is used to request a thread lock. When a thread calls the acquire() function of a thread lock object, it attempts to acquire the lock. If the lock is not currently held by another thread, the calling thread successfully acquires the lock and continues execution. If the lock is already held by another thread, the thread calling acquire() will be blocked until the lock is released.

{@fun/Threads/threading/Lock Lock}, {@fun/Threads/ThreadLock/release release}

release

The release() function is used to release a thread lock (unlock).

release()

function consumer(productionQuantity, dict, pLock, cLock) {
    for (var i = 0; i < productionQuantity; i++) {
        pLock.acquire()
        cLock.acquire()
        var arr = dict.get("array")
        var count = arr.shift()
        dict.set("array", arr)
        Log("consumer:", count, ", array:", arr)
        cLock.release()
        Sleep(1000)
        pLock.release()
    }
}

function producer(productionQuantity, dict, pLock, cLock) {
    for (var i = 0; i < productionQuantity; i++) {
        cLock.acquire()   // cLock.acquire() placed after pLock.acquire() will not cause deadlock
        pLock.acquire()   
        var arr = dict.get("array")
        arr.push(i)
        dict.set("array", arr)
        Log("producer:", i, ", array:", arr)
        pLock.release()
        Sleep(1000)
        cLock.release()
    }
}

function main() {
    var dict = threading.Dict()
    dict.set("array", [])
    var pLock = threading.Lock()
    var cLock = threading.Lock()
    var productionQuantity = 10
    var producerThread = threading.Thread(producer, productionQuantity, dict, pLock, cLock)
    var consumerThread = threading.Thread(consumer, productionQuantity, dict, pLock, cLock)

    consumerThread.join()
    producerThread.join()
}

Testing deadlock scenarios

It should be noted that improper use of thread locks may lead to deadlock.

{@fun/Threads/threading/Lock Lock}, {@fun/Threads/ThreadLock/acquire acquire}

ThreadEvent

Event object, used for multi-threaded event notification and signal.

set

The set() function is used to notify events (set signals).

set()

Please refer to the threading.Event() section for examples.

If the signal has been set using set(), it cannot be set again. We need to clear the signal and set it again.

{@fun/Threads/ThreadEvent/clear clear}, {@fun/Threads/ThreadEvent/wait wait}, {@fun/Threads/ThreadEvent/isSet isSet}

clear

The clear() function is used to clear the signal.

clear()

Please refer to the threading.Event() section for examples.

{@fun/Threads/ThreadEvent/set set}, {@fun/Threads/ThreadEvent/wait wait}, {@fun/Threads/ThreadEvent/isSet isSet}

wait

The wait() function is used to set an event (signal) wait, and will block before the event (signal) is set; it supports setting a timeout parameter.

The wait() function returns whether the timeout has occurred. If so, it returns a true value.

bool

wait() wait(timeout)

The timeout parameter is used to set the waiting timeout in milliseconds.

timeout false number

function main() {
    var event = threading.Event()
    var t1 = threading.Thread(function(event) {
        var ret = event.wait(100)
        Log(`event.wait(100):`, ret)
        ret = event.wait()
        Log(`event.wait():`, ret)
    }, event)

    Sleep(1000)
    event.set()
    t1.join()
}

Test the return value of the wait() function.

{@fun/Threads/ThreadEvent/set set}, {@fun/Threads/ThreadEvent/clear clear}, {@fun/Threads/ThreadEvent/isSet isSet}

isSet

The isSet() function is used to determine whether an event (signal) has been set.

The isSet() function returns whether the event (signal) has been set; if the event (signal) has been set, it returns a true value.

bool

isSet()

Please refer to the threading.Event() section for examples.

{@fun/Threads/ThreadEvent/set set}, {@fun/Threads/ThreadEvent/clear clear}, {@fun/Threads/ThreadEvent/wait wait}

ThreadCondition

Condition object, used for multi-thread synchronization.

notify

The notify() function is used to wake up a waiting thread (if any). Only threads that have called the wait() method will be woken up.

notify()

function consumer(dict, condition) {
    while (true) {
        condition.acquire()
        while (dict.get("array").length == 0) {
            Log(threading.currentThread().name(), "wait()...", ", array:", dict.get("array"))
            condition.wait()
        }
        var arr = dict.get("array")
        var num = arr.shift()
        Log(threading.currentThread().name(), ", num:", num, ", array:", arr, "#FF0000")
        dict.set("array", arr)
        Sleep(1000)
        condition.release()
    }
}

function main() {
    var condition = threading.Condition()
    var dict = threading.Dict()
    dict.set("array", [])
    var t1 = threading.Thread(consumer, dict, condition)
    var t2 = threading.Thread(consumer, dict, condition)
    var t3 = threading.Thread(consumer, dict, condition)
    Sleep(1000)
    var i = 0
    while (true) {
        condition.acquire()
        var msg = ""
        var arr = dict.get("array")
        var randomNum = Math.floor(Math.random() * 5) + 1
        if (arr.length >= 3) {
            condition.notifyAll()
            msg = "notifyAll"
        } else {
            arr.push(i)
            dict.set("array", arr)
            if (randomNum > 3 && arr.length > 0) {
                condition.notify()
                msg = "notify"
            } else {
                msg = "pass"
            }
            i++
        }

        Log(_D(), "randomNum:", randomNum, ", array:", arr, ", msg:", msg)
        condition.release()
        Sleep(1000)
    }
}

Use the notify() function to wake up the waiting thread.

The notify() function wakes up a thread in the waiting queue.

When the notify() function wakes up a thread, the thread will reacquire the thread lock.

{@fun/Threads/ThreadCondition/notifyAll notifyAll}, {@fun/Threads/ThreadCondition/wait wait}, {@fun/Threads/ThreadCondition/acquire acquire}, {@fun/Threads/ThreadCondition/release release}

notifyAll

The notifyAll() function wakes up all waiting threads.

notifyAll()

Please refer to the ThreadCondition.notify() section for examples.

The notifyAll() function wakes up all waiting threads one by one, and the awakened threads reacquire the thread lock.

{@fun/Threads/ThreadCondition/notify notify}, {@fun/Threads/ThreadCondition/wait wait}, {@fun/Threads/ThreadCondition/acquire acquire}, {@fun/Threads/ThreadCondition/release release}

wait

The wait() function is used to make a thread wait under certain designed conditions.

wait()

Please refer to the ThreadCondition.notify() section for examples.

The wait() function releases the thread lock and reacquires the thread lock when woken up.

{@fun/Threads/ThreadCondition/notify notify}, {@fun/Threads/ThreadCondition/notifyAll notifyAll}, {@fun/Threads/ThreadCondition/acquire acquire}, {@fun/Threads/ThreadCondition/release release}

acquire

The acquire() function is used to request a thread lock (lock).

acquire()

Please refer to the ThreadCondition.notify() section for examples.

Before using wait(), you need to request the thread lock (lock) of the current condition object.

{@fun/Threads/ThreadCondition/notify notify}, {@fun/Threads/ThreadCondition/notifyAll notifyAll}, {@fun/Threads/ThreadCondition/wait wait}, {@fun/Threads/ThreadCondition/release release}

release

The release() function is used to release a thread lock (unlock).

release()

Please refer to the ThreadCondition.notify() section for examples.

After using wait(), we need to release the thread lock (unlock) of the current condition object.

{@fun/Threads/ThreadCondition/notify notify}, {@fun/Threads/ThreadCondition/notifyAll notifyAll}, {@fun/Threads/ThreadCondition/wait wait}, {@fun/Threads/ThreadCondition/acquire acquire}

ThreadDict

Dictionary object, used for data sharing.

get

The get() function is used to get the key value recorded in the dictionary object.

The get() function returns the value of the key specified by the key parameter.

string, number, bool, object, array, null value and other types supported by the system

get(key)

The key parameter is used to specify the key name corresponding to the key to be obtained.

key true string

function main() {
    var event = threading.Event()
    var dict = threading.Dict()
    dict.set("data", 100)
    
    var t1 = threading.Thread(function(dict, event) {
        Log(`thread1, dict.get("data"):`, dict.get("data"))
        
        event.set()
        event.clear()
        
        event.wait()
        Log(`after main change data, thread1 dict.get("data"):`, dict.get("data"))
    
        dict.set("data", 0)
    }, dict, event)
    
    event.wait()
    
    dict.set("data", 99)
    
    event.set()
    event.clear()
    
    t1.join()
    Log(`main thread, dict.get("data"):`, dict.get("data"))
}

Use event objects to notify threads to read and modify data.

{@fun/Threads/ThreadDict/set set}

set

The set() function is used to set a key-value pair.

set(key, value)

The parameter key is used to set the key name to be modified.

key true string The parameter value is used to set the key value to be modified.

value true string, number, bool, object, array, function, null value and other types supported by the system

function main() {
    var dict1 = threading.Dict()
    dict1.set("func1", function(p) {
        Log("func1 p:", p)
    })
    
    threading.Thread(function(dict1) {
        var func1 = dict1.get("func1")
        func1("test")
    }, dict1).join()
}

It supports key-value passing into functions.

{@fun/Threads/ThreadDict/get get}

Web3

exchange.IO("abi", …)

In the FMZ Quant Trading Platform, it mainly implements various functions, calls related to blockchain through exchange.IO() function. The following document describes the exchange.IO() function separately according to its function. The call method of the exchange.IO("abi", ...) function is used to register an ABI.

exchange.IO(k, address, abiContent)

The k parameter is used to set the function of the exchange.IO() function, set to "abi" means that the function is used to register ABI. k true string The address parameter is used to specify the address of the smart contract. address true string The abiContent parameter is used to specify the ABI of the smart contract. abiContent true string

function main() {
    // register Uniswap SwapRouter02 abi
    var routerAddress = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    var abi = `[{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"}]`
    
    // Get the ```ABI``` content of the contract can be obtained with the following URL, taking the ```result``` field only, e.g:
    exchange.IO("abi", routerAddress, abi)
}

The methods of calling smart contract do not need to be registered if they are standard ERC20 methods. Get the ABI content of the contract can be obtained with the following URL, taking the result field only, e.g:

https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

exchange.IO("api", “eth”, …)

The calling method of exchange.IO("api", "eth", ...) function is used to call the Ethereum RPC method.

The exchange.IO("api", "eth", ...) function returns the return value of the called RPC method. string, number, bool, object, array, null and all other types supported by the system

exchange.IO(k, blockChain, rpcMethod) exchange.IO(k, blockChain, rpcMethod, …args)

The k parameter is used to set the function of the exchange.IO() function, set to "api" indicates that the function is used to extend the call request. k true string The blockChain parameter is used to set the function of the exchange.IO() function, set to "eth" indicates that the function is used for RPC method calls on the Ethereum Network. blockChain true string The rpcMethod parameter is used to set the RPC method to be called by the exchange.IO() function. rpcMethod true string The arg parameter is used to specify the parameters of the RPC method to be called. There may be more than one arg parameter. The type and number of arg parameters depend on the RPC method specified by the rpcMethod parameter. arg false string, number, bool, object, array, function, null, and all other types supported by the system

function main() {
    // "owner" needs to be replaced with the specific wallet address
    // Parameter labels for the "latest" string position: 'latest', 'earliest' or 'pending', please refrer to https://eth.wiki/json-rpc/API#the-default-block-parameter
    // The return value ethBalance is a hexadecimal string: 0x9b19ce56113070
    var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest")              

    // ETH has a precision unit of 1e18
    var ethDecimal = 18              

    // Because of the JavaScript language precision, it is necessary to use the system underlying package function BigInt, BigDecimal to process
    // Convert ethBalance to readable amount, 0x9b19ce56113070 to 0.043656995388076145
    Log(Number((BigDecimal(BigInt(ethBalance))/BigDecimal(Math.pow(10, ethDecimal))).toString()))
}

Check the balance of ETH in your wallet:

function mian() {
    // ETH has a precision unit of 1e18
    var ethDecimal = 18  

    // Number of transfers, readable amount e.g. 0.01 ETH
    var sendAmount = 0.01  

    // Due to the JavaScript language precision, it is necessary to use the system underlying encapsulated functions BigInt, BigDecimal to process, and to convert the readable amount to the data processed on the chain
    var toAmount = (BigDecimal(sendAmount)*BigDecimal(Math.pow(10, ethDecimal))).toFixed(0)
    
    // "toAddress" is the address of the recipient's ETH wallet at the time of the transfer, which needs to be filled in specifically, and toAmount is the number of transfers
    exchange.IO("api", "eth", "send", "toAddress", toAmount)
}

For ETH transfers, you can set the {gasPrice: 11, gasLimit: 111, nonce: 111} parameter, which is set on the last parameter of the exchange.IO() function, according to your specific needs. You can omit the nonce and use the system default, or leave gasLimit/gasPrice/nonce unset and use the system default value for all.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
    Log("gasPrice:", toAmount(gasPrice, 0))   // 5000000000 , in wei (5 gwei)
}

Query gasPrice:

function toAmount(s, decimals) {
    // The toAmount function can convert hex-encoded values to decimal values
    return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}                

function main() {
    // Coding approve (authorization) method calls
    var data = exchange.IO("encode", "0x111111111117dC0aa78b770fA6A738034120C302", "approve", "0xe592427a0aece92de3edee1f18e0157c05861564", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
    Log("data:", data)
    var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
    Log("gasPrice:", toAmount(gasPrice, 0))
    var obj = {
        "from" : "0x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",   // walletAddress
        "to"  : "0x111111111117dC0aa78b770fA6A738034120C302",
        "gasPrice" : gasPrice,
        "value" : "0x0",
        "data" : "0x" + data,
    }
    
    var gasLimit = exchange.IO("api", "eth", "eth_estimateGas", obj)
    Log("gasLimit:", toAmount(gasLimit, 0))
    Log("gas fee", toAmount(gasLimit, 0) * toAmount(gasPrice, 0) / 1e18)
}

Query eth_estimateGas:

The second parameter of the exchange.IO() function with "eth" can directly call the RPC methods available to the Ethereum node server.

{@fun BigDecimal}, {@fun BigInt}

exchange.IO("encode", …)

The exchange.IO("encode", ...) function is called for data encoding.

The exchange.IO("encode", ...) function returns the encoded data. string

exchange.IO(k, dataFormat, …args) exchange.IO(k, address, dataFormat) exchange.IO(k, address, dataFormat, …args)

The k parameter is used to set the function of the exchange.IO() function, set to "encode" means the function is used for data encoding. k true string The address parameter is used to set the address of the smart contract. When calling the exchange.IO("encode", ...) function, passing in the address parameter indicates encoding the method call on the smart contract. When calling the exchange.IO("encode", ...) function, if the address parameter is not passed, the function is used to encode the specified type order and is functionally equivalent to abi.encode in Solidity. address false string The dataFormat parameter is used to specify the method, type, and order of the encoded data. dataFormat true string The arg parameter is used to specify the specific data value that matches the dataFormat parameter. There may be more than one arg parameter, and the type and number of arg parameters depends on the dataFormat parameter setting. arg false string, number, tuple, array, and all other types supported by the system

function main() {
    // Main network address of ContractV3SwapRouterV2: 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
    // Calling the unwrapWETH9 method requires registering the ABI first, which is omitted here
    // "owner" represents the wallet address, which need to fill in the specific, 1 represents the number of unpacking, unpacking a WETH into ETH
    var data = exchange.IO("encode", "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", "unwrapWETH9(uint256,address)", 1, "owner")
    Log(data)
}

For example, calling the encoding method unwrapWETH9:

function main() {
    var x = 10 
    var address = "0x02a5fBb259d20A3Ad2Fdf9CCADeF86F6C1c1Ccc9"
    var str = "Hello World"
    var array = [1, 2, 3]
    var ret = exchange.IO("encode", "uint256,address,string,uint256[]", x, address, str, array)   // uint i.e. uint256 , the type length needs to be specified on FMZ
    Log("ret:", ret)
    /*
    000000000000000000000000000000000000000000000000000000000000000a    // x
    00000000000000000000000002a5fbb259d20a3ad2fdf9ccadef86f6c1c1ccc9    // address
    0000000000000000000000000000000000000000000000000000000000000080    // Offset of str
    00000000000000000000000000000000000000000000000000000000000000c0    // Offset of array
    000000000000000000000000000000000000000000000000000000000000000b    // The length of str
    48656c6c6f20576f726c64000000000000000000000000000000000000000000    // str data
    0000000000000000000000000000000000000000000000000000000000000003    // The length of the array
    0000000000000000000000000000000000000000000000000000000000000001    // array the first data
    0000000000000000000000000000000000000000000000000000000000000002    // array the second data
    0000000000000000000000000000000000000000000000000000000000000003    // array the third data
    */
}

It’s equivalent to the encoding example of abi.encode in Solidity:

function main() {
    var types = "tuple(a uint256,b uint8,c address),bytes"
    var ret = exchange.IO("encode", types, {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }, "0011")
    Log("encode: ", ret)
}

It supports encoding a tuple or a type order containing a tuple. This type order consists of tuple, bytes, so when calling exchange.IO() for encoding, you need to continue passing two parameters:

    1. Variables corresponding to the tuple type:
    
    {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }
    
    

    The parameters passed in must also be consistent with the structure and type of tuple, as defined in the types parameter of the form: tuple(a uint256,b uint8,c address).

    1. Variables corresponding to type bytes:
    "0011"
    
function main() {
    var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"]   // ETH address, USDT address
    var ret = exchange.IO("encode", "address[]", path)
    Log("encode: ", ret)
}

It supports for sequential encoding of arrays or types containing arrays:

The exchange.IO() function encapsulates the encode method, which can return the function call code to hex string format. For specific use, you can refer to the platform’s publicly available “Uniswap V3 Trade” Template. When coding method calls on smart contracts, the corresponding ABI needs to be registered first.

exchange.IO("encodePacked", …)

The exchange.IO("encodePacked", ...) function is called in a way that is used for encodePacked encoding.

The exchange.IO("encodePacked", ...) function returns the encodePacked encoded data. string

exchange.IO(k, dataFormat, …args)

The k parameter is used to set the function of the exchange.IO() function, set to "encodePacked" means that the function is used for data encodePacked encoding. k true string The dataFormat parameter is used to specify the type and order of the encodePacked encoded data. dataFormat true string The arg parameter is used to specify the specific data value that matches the dataFormat parameter. There may be more than one arg parameter, and the type and number of arg parameters depends on the dataFormat parameter setting. arg true string, number, tuple, array, and all other types supported by the system

function main() {
    var fee = exchange.IO("encodePacked", "uint24", 3000)
    var tokenInAddress = "0x111111111117dC0aa78b770fA6A738034120C302"
    var tokenOutAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"
    var path = tokenInAddress.slice(2).toLowerCase()
    path += fee + tokenOutAddress.slice(2).toLowerCase()
    Log("path:", path)
}

When using Uniswap V3, you need to pass in parameters like the exchange path, you need to use the encodePacked encoding operation:

exchange.IO("decode", …)

The exchange.IO("decode", ...) function is called in a way that is used for decoding.

The exchange.IO("decode", ...) function returns the decoded data. Returns a string when there is only one data specified by the dataFormat parameter. Returns an array when there is more than one data specified by the dataFormat parameter. array、string

exchange.IO(k, dataFormat, data)

The k parameter is used to set the function of the exchange.IO() function, and setting it to "decode" means that the function is used for data decoding. k true string The dataFormat parameter is used to specify the type and order of the decoded data. dataFormat true string The data parameter is used to set the data to be decoded. data true string

function main() {
    var types = "tuple(a uint256,b uint8,c address),bytes"
    var ret = exchange.IO("encode", types, {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }, "0011")
    Log("encode: ", ret)            

    var rawData = exchange.IO("decode", types, ret)
    Log("decode:", rawData)
}

Inverse operation of the exchange.IO("encode", ...) function:

function main() {
    // register SwapRouter02 abi
    var walletAddress = "0x398a93ca23CBdd2642a07445bCD2b8435e0a373f"
    var routerAddress = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    var abi = `[{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"}]`
    exchange.IO("abi", routerAddress, abi)   // abi only uses the contents of the local exactOutput method, the full abi can be searched on the Internet              

    // encode path
    var fee = exchange.IO("encodePacked", "uint24", 3000)
    var tokenInAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    var tokenOutAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7"
    var path = tokenInAddress.slice(2).toLowerCase()
    path += fee + tokenOutAddress.slice(2).toLowerCase()
    Log("path:", path)              

    var dataTuple = {
        "path" : path, 
        "recipient" : walletAddress, 
        "amountOut" : 1000, 
        "amountInMaximum" : 1, 
    }
    // encode SwapRouter02 exactOutput 
    var rawData = exchange.IO("encode", routerAddress, "exactOutput", dataTuple)
    Log("method hash:", rawData.slice(0, 8))   // 09b81346
    Log("params hash:", rawData.slice(8))              

    // decode exactOutput params
    var decodeRaw = exchange.IO("decode", "tuple(path bytes,recipient address,amountOut uint256,amountInMaximum uint256)", rawData.slice(8))
    Log("decodeRaw:", decodeRaw)
}

The following example first performs an encodePacked operation on the path parameter processing, because the exactOutput method call that needs to be encoded later requires path as a parameter. Then encode the exactOutput method of the routing contract, which has only one parameter of type tuple. The method name exactOutput is encoded as: 0x09b81346, and using the exchange.IO("decode", ...) method to decode the resulting decodeRaw, consistent with the variable dataTuple.

For data processing, the exchange.IO() function supports not only encoding, but also decoding.

exchange.IO("key", …)

The exchange.IO("key", ...) function is called in a way to switch private keys.

exchange.IO(k, key)

The parameter k is used to set the function of the exchange.IO() function, set to "key" means the function is used to switch the private key. k true string The key parameter is used to set the private key. key true string

function main() {
    exchange.IO("key", "Private Key")   // "Private Key" represents the private key string, which needs to be filled in specifically
}

The exchange.IO() function supports switching private keys and it can manipulate multiple wallet addresses. It is also possible to add multiple exchange objects (see: {@var/EXCHANGE/exchanges exchanges}) for manipulating multiple wallet addresses.

exchange.IO("api", …)

The exchange.IO("api", ...) function is called in a way that is used to call the methods of the smart contract.

The exchange.IO("api", ...) function returns the return value of the called smart contract method. string, number, bool, object, array, null and all other types supported by the system

exchange.IO(k, address, method) exchange.IO(k, address, method, …args) exchange.IO(k, address, method, value, …args)

The k parameter is used to set the function of the exchange.IO() function, set to "api" indicates that the function is used to extend the call request. k true string The address parameter is used to specify the address of the smart contract. address true string The method parameter is used to specify the method of the smart contract to be called. method true string The value parameter is used to set the amount of ETH to be sent. The stateMutability attribute of the smart contract method to be executed is payable, then the value parameter needs to be passed. The "stateMutability": "payable" attribute can be viewed from the ABI. The exchange.IO() function will determine the required parameter based on the stateMutability attribute in the ABI that has been registered. If the stateMutability attribute is nonpayable, then the value parameter does not need to be passed. value false number、string The arg parameter is used to specify the parameters of the method of the smart contract to be called. There may be more than one arg parameter, and the type and number of arg parameters depends on the method of the smart contract to be called. arg false string, number, bool, and all other types supported by the system

function main(){
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"    // The contract address of the token, the token is 1INCH in the example
    Log(exchange.IO("api", tokenAddress, "decimals"))                  // Query, print 1INCH tokens with precision index of 18
}

The decimals method is a constant method of ERC20 that does not incur gas consumption and it can query the precision data of a token. The decimals method has no parameters. Return value: the precision data of the token.

function main(){
    // The contract address of the token, in the example the token is 1INCH
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                          

    // For example, the query yields 1000000000000000000, divided by the precision unit of the token 1e18, the wallet to which the current exchange object is bound has authorized 1 1INCH to the spender address
    Log(exchange.IO("api", tokenAddress, "allowance", "owner", "spender"))   
}

The allowance method is a constant method of ERC20 that does not generate gas consumption and can query the authorized amount of a token for a certain contract address. The allowance method takes 2 parameters, the first one is the wallet address and the second one is the authorized address. Return value: the authorization amount of the token.
owner: the address of the wallet, the example is replaced by the string “owner”, the actual use needs to fill in the specific address. spender: the address of the authorized contract, the example is replaced by the string “spender”, the actual use needs to fill in the specific address, for example, it can be Uniswap V3 router v1 address.

function main(){
    // The contract address of the token, the token is 1INCH in the example
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                 

    // The hexadecimal string of the authorization amount: 0xde0b6b3a7640000 , the corresponding decimal string: 1e18 , 1e18 divided by the precision unit of the token, i.e. 1 token amount, so this refers to the authorization of one token
    Log(exchange.IO("api", tokenAddress, "approve", "spender", "0xde0b6b3a7640000"))  
}```
The ```approve``` method is a non-```constant``` method of ERC20, which generates gas consumption and is used to authorize the operation amount of a token to a contract address. The ```approve``` method takes 2 parameters, the first one is the address to be authorized and the second one is the amount to be authorized. Return value: txid.  
```spender```: the address of the authorized contract, the example is replaced by the string "spender", the actual use needs to fill in the specific address, for example, it can be ```Uniswap V3 router v1``` address. ```0xde0b6b3a7640000```: the number of authorizations, here is the hexadecimal string, the corresponding decimal value is 1e18, divided by the token precision unit in the example (i.e. 1e18). The result is that 1 token is authorized. The third parameter of the ```exchange.IO()``` function is passed to the method name ```approve```, which can also be written in the form of methodId, such as "0x571ac8b0". It is also possible to write the full standard method name, for example: "approve(address,uint256)".
```javascript
function main() {
    var ContractV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    var tokenInName = "ETH"
    var amountIn = 0.01
    var options = {gasPrice: 5000000000, gasLimit: 21000, nonce: 100}   // This is an example, depending on the actual scene settings
    var data = ""                                                       // The encoded data, here is the empty string, depending on the actual scene settings
    var tx = exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", (tokenInName == 'ETH' ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})
}

The multicall method is a non-constant method of Uniswap V3 that generates gas consumption and is used to redeem tokens in multiple ways. The multicall method may have various ways of passing parameters, you can check the ABI that contains the method specifically, you need to register the ABI before calling the method. Return value: txid.

For specific examples of multicall method calls, you can refer to the platform’s publicly available “Uniswap V3 Trade” Template

Some details are described here using pseudo-code:


exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)

ContractV3SwapRouterV2: address of router v2 of Uniswap V3. value: the amount of ETH to transfer, set to 0 if the tokenIn token of the exchange operation is not ETH. deadline: deadline is the parameter of the multicall method, which can be set to (new Date().getTime() / 1000) + 3600, indicating that it is valid for one hour. data: data is the parameter of the multicall method, the data of the packing operation to be performed.

Similar to exchange.IO("api", "eth", "send", "toAddress", toAmount), the gasLimit/gasPrice/nonce setting of the method call can be specified when calling the multicall method. Again, we use pseudo-code to describe:


exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})

The parameter {gasPrice: 11, gasLimit: 111, nonce: 111} can be set according to specific needs, which is set to the last parameter of the exchange.IO() function. You can omit the nonce and use the system default value, or leave gasLimit/gasPrice/nonce unset and use the system default value for all.

exchange.IO("address")

The exchange.IO("address") function is called in such a way as to get the address of the wallet configured by the {@var/EXCHANGE exchange} exchange object.

The exchange.IO("address") function returns the configured wallet address. string

exchange.IO(k)

The k parameter is used to set the function of the exchange.IO() function, set to "address" means that the function is used to get the configured wallet address. k true string

function main() {
    Log(exchange.IO("address"))         // Print the wallet address of the private key configured on the exchange object
}

exchange.IO("base", …)

The exchange.IO("base", ...) function is called in a way to set the RPC node address.

exchange.IO(k, address)

The k parameter is used to set the function of the exchange.IO() function, set to "base" means the function is used to switch RPC nodes. k true string The address parameter is used to set the RPC node address. address true string

function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // Switching to BSC chain
}

TA

TA.MACD

The TA.MACD() function is used to calculate the exponential smoothed dissimilarity and similarity MACD indicator.

The return value of the TA.MACD() function is a two-dimensional array with the structure: [DIF, DEA, MACD]. array

TA.MACD(inReal) TA.MACD(inReal, optInFastPeriod, optInSlowPeriod, optInSignalPeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastPeriod parameter is used to set the fast period. optInFastPeriod false number The optInSlowPeriod parameter is used to set the slow period. optInSlowPeriod false number The optInSignalPeriod parameter is used to set the signal period. optInSignalPeriod false number

function main(){
    // You can fill in different k-line periods, such as PERIOD_M1,PERIOD_M30,PERIOD_H1...
    var records = exchange.GetRecords(PERIOD_M15)
    var macd = TA.MACD(records, 12, 26, 9)
    // Watching the logs, you can see that three arrays are returned, corresponding to DIF, DEA and MACD.
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
}
def main():
    r = exchange.GetRecords(PERIOD_M15)
    macd = TA.MACD(r, 12, 26, 9)
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
void main() {
    auto r = exchange.GetRecords(PERIOD_M15);
    auto macd = TA.MACD(r, 12, 26, 9);
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2]);
}

The TA indicator library of FMZ Quant, optimized for common indicator algorithms. It supports JavaScript, Python, C++ language strategy calls, open source TA library code. The default values of the optInFastPeriod, optInSlowPeriod, and optInSignalPeriod parameters of the TA.MACD() function are: 12, 26, and 9.

{@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.KDJ

The TA.KDJ() function is used to calculate stochastic indicators.

The return value of the TA.KDJ() function is a two-dimensional array with the structure: [K, D, J]. array

TA.KDJ(inReal) TA.KDJ(inReal, period, kPeriod, dPeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The period parameter is used to set period 1. period false number The kPeriod parameter is used to set period 2. kPeriod false number The dPeriod parameter is used to set period 3. dPeriod false number

function main(){
    var records = exchange.GetRecords(PERIOD_M15)
    var kdj = TA.KDJ(records, 9, 3, 3)
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
}
def main():
    r = exchange.GetRecords(PERIOD_M15)
    kdj = TA.KDJ(r, 9, 3, 3)
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
void main() {
    auto r = exchange.GetRecords();
    auto kdj = TA.KDJ(r, 9, 3, 3);
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2]);
}

The default values for the period, kPeriod, and dPeriod parameters of the TA.KDJ() function are: 9, 3, and 3.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.RSI

The TA.RSI() function is used to calculate the Strength Indicator.

The return value of the TA.RSI() function is: a one-dimensional array. array

TA.RSI(inReal) TA.RSI(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period. optInTimePeriod false number

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var rsi = TA.RSI(records, 14)
    Log(rsi)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    rsi = TA.RSI(r, 14)
    Log(rsi)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto rsi = TA.RSI(r, 14);
    Log(rsi); 
}

The default value of the optInTimePeriod parameter of the TA.RSI() function is: 14.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.ATR

The TA.ATR() function is used to calculate the Average True Volatility Indicator.

The return value of the TA.ATR() function is: a one-dimensional array. array

TA.ATR(inPriceHLC) TA.ATR(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period. optInTimePeriod false number

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var atr = TA.ATR(records, 14)
    Log(atr)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    atr = TA.ATR(r, 14)
    Log(atr)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto atr = TA.ATR(r, 14);
    Log(atr);
}

The default value of the optInTimePeriod parameter of the TA.ATR() function is: 14.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.OBV

The TA.OBV() function is used to calculate the energy tide indicator.

The return value of the TA.OBV() function is: a one-dimensional array. array

TA.OBV(inReal) TA.OBV(inReal, inPriceV)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The inPriceV parameter is used to specify the transaction amount data. inPriceV false {@struct/Record Record} structure array

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var obv = TA.OBV(records)
    Log(obv)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    obv = TA.OBV(r)
    Log(obv)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto obv = TA.OBV(r);
    Log(obv);
}

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.MA

The TA.MA() function is used to calculate the MACD Indicator.

The return value of the TA.MA() function is: a one-dimensional array. array

TA.MA(inReal) TA.MA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period. optInTimePeriod false number

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var ma = TA.MA(records, 14)
    Log(ma)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    ma = TA.MA(r, 14)
    Log(ma)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto ma = TA.MA(r, 14);
    Log(ma);
}

The default value of the optInTimePeriod parameter of the TA.MA() function is: 9.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.EMA

The TA.EMA() function is used to calculate the exponential average indicator.

The return value of the TA.EMA() function is: a one-dimensional array. array

TA.EMA(inReal) TA.EMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period. optInTimePeriod false number

function main(){
    var records = exchange.GetRecords()
    // Determine if the number of K-line bars meets the calculation period of the indicator
    if (records && records.length > 9) {
        var ema = TA.EMA(records, 9)          
        Log(ema)
    }
}
def main():
    r = exchange.GetRecords()
    if r and len(r) > 9:
        ema = TA.EMA(r, 9)
        Log(ema)
void main() {
    auto r = exchange.GetRecords();
    if(r.Valid && r.size() > 9) {
        auto ema = TA.EMA(r, 9);
        Log(ema);
    }
}

The default value of the optInTimePeriod parameter of the TA.EMA() function is: 9.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.BOLL

The TA.BOLL() function is used to calculate the Bollinger Band indicator.

The return value of the TA.BOLL() function is a two-dimensional array with the structure: [upLine, midLine, downLine]. array

TA.BOLL(inReal) TA.BOLL(inReal, period, multiplier)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The period parameter is used to set the period. period false number The multiplier parameter is used to set the multiplier. multiplier false number

function main() {
    var records = exchange.GetRecords()
    if(records && records.length > 20) {
        var boll = TA.BOLL(records, 20, 2)
        var upLine = boll[0]
        var midLine = boll[1]
        var downLine = boll[2]
        Log(upLine)
        Log(midLine)
        Log(downLine)
    }
}
def main():
    r = exchange.GetRecords()
    if r and len(r) > 20:
        boll = TA.BOLL(r, 20, 2)
        upLine = boll[0]
        midLine = boll[1]
        downLine = boll[2]
        Log(upLine)
        Log(midLine)
        Log(downLine)
void main() {
    auto r = exchange.GetRecords();
    if(r.Valid && r.size() > 20) {
        auto boll = TA.BOLL(r, 20, 2);
        auto upLine = boll[0];
        auto midLine = boll[1];
        auto downLine = boll[2];
        Log(upLine);
        Log(midLine);
        Log(downLine);
    }
}

The default values for the period and multiplier parameters of the TA.BOLL() function are: 20 and 2.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.Alligator

The TA.Alligator() function is used to calculate the Alligator Indicator.

The return value of the TA.Alligator() function is a two-dimensional array with the structure: [jawLine, teethLine, lipsLine]. array

TA.Alligator(inReal) TA.Alligator(inReal, jawLength, teethLength, lipsLength)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The jawLength parameter is used to set the jaw period. jawLength false number The teethLength parameter is used to set the teeth period. teethLength false number The lipsLength parameter is used to set the upper lip period. lipsLength false number

function main(){
    var records = exchange.GetRecords()
    var alligator = TA.Alligator(records)
    Log("jawLine:", alligator[0])
    Log("teethLine:", alligator[1])
    Log("lipsLine:", alligator[2])
}
def main():
    records = exchange.GetRecords()
    alligator = TA.Alligator(records)
    Log("jawLine:", alligator[0])
    Log("teethLine:", alligator[1])
    Log("lipsLine:", alligator[2])
void main() {
    auto records = exchange.GetRecords();
    auto alligator = TA.Alligator(records);
    Log("jawLine:", alligator[0]);
    Log("teethLine:", alligator[1]);
    Log("lipsLine:", alligator[2]);
}

The default values of the jawLength, teethLength, and lipsLength parameters of the TA.Alligator() function are: 13, 8, and 5.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.CMF

The TA.CMF() function is used to calculate the Chaikin Money Flow Indicator.

The return value of the TA.CMF() function is: a one-dimensional array. array

TA.CMF(inReal) TA.CMF(inReal, inPriceV)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The inPriceV parameter is used to specify the volume data. inPriceV false {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var cmf = TA.CMF(records)
    Log(cmf)
}
def main():
    records = exchange.GetRecords()
    cmf = TA.CMF(records)
    Log(cmf)
void main() {
    auto records = exchange.GetRecords();
    auto cmf = TA.CMF(records);
    Log(cmf);
}

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

TA.Highest

The TA.Highest() function is used to calculate the period highest price.

The TA.Highest() function returns the maximum value of an attribute in the last certain period, excluding the current Bar. number

TA.Highest(inReal) TA.Highest(inReal, period, attr)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The period parameter is used to set the period. period false number The attr parameter is used to set the attributes, optionally: Open, Close, Low, High, Volume, OpenInterest. attr false string

function main() {
    var records = exchange.GetRecords()
    var highestForOpen = TA.Highest(records, 10, "Open")
    Log(highestForOpen)
}
def main():
    records = exchange.GetRecords()
    highestForOpen = TA.Highest(records, 10, "Open")
    Log(highestForOpen)
void main() {
    auto records = exchange.GetRecords();
    auto highestForOpen = TA.Highest(records.Open(), 10);
    Log(highestForOpen);
}

For example, if the TA.Highest(records, 30, "High") function is called, if the period parameter period is set to 0, it means to calculate all Bars of the K-line data passed in by the inReal parameter; if the attribute parameter attr is not specified, the K-line data passed in by the inReal parameter is considered to be an ordinary array.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Lowest TA.Lowest}

TA.Lowest

The TA.Lowest() function is used to calculate the period lowest price.

The TA.Lowest() function returns the minimum value of an attribute in the last certain period, excluding the current Bar. number

TA.Lowest(inReal) TA.Lowest(inReal, period, attr)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The period parameter is used to set the period. period false number The attr parameter is used to set the attributes, optionally: Open, Close, Low, High, Volume, OpenInterest. attr false string

function main() {
    var records = exchange.GetRecords()
    var lowestForOpen = TA.Lowest(records, 10, "Open")
    Log(lowestForOpen)
}
def main():
    records = exchange.GetRecords()
    lowestForOpen = TA.Lowest(records, 10, "Open")
    Log(lowestForOpen)
void main() {
    auto records = exchange.GetRecords();
    auto lowestForOpen = TA.Lowest(records.Open(), 10);
    Log(lowestForOpen);
}

For example, if the TA.Lowest(records, 30, "Low") function is called, if the period parameter period is set to 0, it means to calculate all Bars of the K-line data passed in by the inReal parameter; if the attribute parameter attr is not specified, the K-line data passed in by the inReal parameter is considered to be an ordinary array. The use of the TA.Highest() and TA.Lowest() functions in the C++ strategy needs to be noted that the Highest() and Lowest() functions each have only 2 parameters. And the first parameter passed in is not the K-line data r obtained when the function auto r = exchange.GetRecords() was called. You need to call the r method and pass in the specific attribute data. For example, pass in the r.Close() closing price data. Close, High, Low, Open, Volume as in the r.Close() call method.

Example test of C++ language strategy:

void main() { 
    Records r;
    r.Valid = true;
    for (auto i = 0; i < 10; i++) {
        Record ele;
        ele.Time = i * 100000;
        ele.High = i * 10000;
        ele.Low = i * 1000;
        ele.Close = i * 100;
        ele.Open = i * 10;
        ele.Volume = i * 1;
        r.push_back(ele);
    }            

    for(int j = 0; j < r.size(); j++){
        Log(r[j]);
    }            

    // Note: the first parameter passed is not r, you need to call r.Close()
    auto highest = TA.Highest(r.Close(), 8);   
    Log(highest);                     
}

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}

TA.SMA

The TA.SMA() function is used to calculate the simple moving average indicator.

The return value of the TA.SMA() function is: a one-dimensional array. array

TA.SMA(inReal) TA.SMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period. optInTimePeriod false number

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var sma = TA.SMA(records, 14)
    Log(sma)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    sma = TA.SMA(r, 14)
    Log(sma)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto sma = TA.SMA(r, 14);
    Log(sma);
}

The default value of the optInTimePeriod parameter of the TA.SMA() function is: 9.

{@fun/TA/TA.MACD TA.MACD}, {@fun/TA/TA.KDJ TA.KDJ}, {@fun/TA/TA.RSI TA.RSI}, {@fun/TA/TA.ATR TA.ATR}, {@fun/TA/TA.OBV TA.OBV}, {@fun/TA/TA.MA TA.MA}, {@fun/TA/TA.EMA TA.EMA}, {@fun/TA/TA.BOLL TA.BOLL}, {@fun/TA/TA.Alligator TA.Alligator}, {@fun/TA/TA.CMF TA.CMF}, {@fun/TA/TA.Highest TA.Highest}, {@fun/TA/TA.Lowest TA.Lowest}

Talib

talib.CDL2CROWS

The talib.CDL2CROWS() function is used to calculate Two Crows (K-line chart - Two Crows).

The return value of the talib.CDL2CROWS() function is a one-dimensional array. array

talib.CDL2CROWS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL2CROWS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL2CROWS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL2CROWS(records);
    Log(ret);
}

The CDL2CROWS() function is described in the talib library documentation as: CDL2CROWS(Records[Open,High,Low,Close]) = Array(outInteger) For calls in the Python language, passing parameters is different and needs to be based on the above description: Records[Open,High,Low,Close].

Example of splitting a variable records (i.e. parameter inPriceOHLC, type {@struct/Record Record} array of structures) into: Open list: written in Python as records.Open. High list: written as records.High in Python. Low list: written in Python as records.Low. Close list: written in Python as records.Close.

Called in Python strategy code:

talib.CDL2CROWS(records.Open, records.High, records.Low, records.Close)

The other talib indicators are described in the same way and they will not be repeated.

talib.CDL3BLACKCROWS

The talib.CDL3BLACKCROWS() function is used to calculate Three Black Crows (K-line chart - Three Black Crows).

The return value of the talib.CDL3BLACKCROWS() function is: a one-dimensional array. array

talib.CDL3BLACKCROWS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3BLACKCROWS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3BLACKCROWS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3BLACKCROWS(records);
    Log(ret);
}

The CDL3BLACKCROWS() function is described in the talib library documentation as: CDL3BLACKCROWS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDL3INSIDE

The talib.CDL3INSIDE() function is used to calculate Three Inside Up/Down (K-line chart: Three Inside Up/Down).

The return value of the talib.CDL3INSIDE() function is: a one-dimensional array. array

talib.CDL3INSIDE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3INSIDE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3INSIDE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3INSIDE(records);
    Log(ret);
}

The CDL3INSIDE() function is described in the talib library documentation as: CDL3INSIDE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDL3LINESTRIKE

The talib.CDL3LINESTRIKE() function is used to calculate the Three-Line Strike (K-line chart: Three-Line Strike).

The return value of the talib.CDL3LINESTRIKE() function is: a one-dimensional array. array

talib.CDL3LINESTRIKE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3LINESTRIKE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3LINESTRIKE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3LINESTRIKE(records);
    Log(ret);
}

The CDL3LINESTRIKE() function is described in the talib library documentation as: CDL3LINESTRIKE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDL3OUTSIDE

The talib.CDL3OUTSIDE() function is used to calculate Three Outside Up/Down (K-line chart: Three Outside Up/Down).

The return value of the talib.CDL3OUTSIDE() function is: a one-dimensional array. array

talib.CDL3OUTSIDE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3OUTSIDE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3OUTSIDE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3OUTSIDE(records);
    Log(ret);
}

The CDL3OUTSIDE() function is described in the talib library documentation as: CDL3OUTSIDE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDL3STARSINSOUTH

The talib.CDL3STARSINSOUTH() function is used to calculate Three Stars In The South (K-line chart: Three Stars In The South).

The return value of the talib.CDL3STARSINSOUTH() function is: a one-dimensional array. array

talib.CDL3STARSINSOUTH(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3STARSINSOUTH(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3STARSINSOUTH(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3STARSINSOUTH(records);
    Log(ret);
}

The CDL3STARSINSOUTH() function is described in the talib library documentation as: CDL3STARSINSOUTH(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDL3WHITESOLDIERS

The talib.CDL3WHITESOLDIERS() function is used to calculate Three Advancing White Soldiers (K-line chart: Three Advancing White Soldiers).

The return value of the talib.CDL3WHITESOLDIERS() function is: a one-dimensional array. array

talib.CDL3WHITESOLDIERS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDL3WHITESOLDIERS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDL3WHITESOLDIERS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDL3WHITESOLDIERS(records);
    Log(ret);
}

The CDL3WHITESOLDIERS() function is described in the talib library documentation as: CDL3WHITESOLDIERS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLABANDONEDBABY

The talib.CDLABANDONEDBABY() function is used to calculate Abandoned Baby (K-line chart: Abandoned Baby).

The return value of the talib.CDLABANDONEDBABY() function is: a one-dimensional array. array

talib.CDLABANDONEDBABY(inPriceOHLC) talib.CDLABANDONEDBABY(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is used to set the Penetration, the default value is 0.3. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLABANDONEDBABY(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLABANDONEDBABY(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLABANDONEDBABY(records);
    Log(ret);
}

The CDLABANDONEDBABY() function is described in the talib library documentation as: CDLABANDONEDBABY(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)

talib.CDLADVANCEBLOCK

The talib.CDLADVANCEBLOCK() function is used to calculate the Advance Block (K-line chart: Advance).

The return value of the talib.CDLADVANCEBLOCK() function is a one-dimensional array. array

talib.CDLADVANCEBLOCK(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLADVANCEBLOCK(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLADVANCEBLOCK(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLADVANCEBLOCK(records);
    Log(ret);
}

The CDLADVANCEBLOCK() function is described in the talib library documentation as: CDLADVANCEBLOCK(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLBELTHOLD

The talib.CDLBELTHOLD() function is used to calculate the Belt-hold (K-line chart: Belt-hold).

The return value of the talib.CDLBELTHOLD() function is: a one-dimensional array. array

talib.CDLBELTHOLD(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLBELTHOLD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLBELTHOLD(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLBELTHOLD(records);
    Log(ret);
}

The CDLBELTHOLD() function is described in the talib library documentation as: CDLBELTHOLD(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLBREAKAWAY

The talib.CDLBREAKAWAY() function is used to calculate the Breakaway (K-line chart: Breakaway).

The return value of the talib.CDLBREAKAWAY() function is: a one-dimensional array. array

talib.CDLBREAKAWAY(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLBREAKAWAY(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLBREAKAWAY(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLBREAKAWAY(records);
    Log(ret);
}

CDLBREAKAWAY() function is described in the talib library documentation as: CDLBREAKAWAY(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLCLOSINGMARUBOZU

The talib.CDLCLOSINGMARUBOZU() function is used to calculate Closing Marubozu (K-line chart: closing bareheaded and barefoot).

The return value of the talib.CDLCLOSINGMARUBOZU() function is: a one-dimensional array. array

talib.CDLCLOSINGMARUBOZU(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLCLOSINGMARUBOZU(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLCLOSINGMARUBOZU(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLCLOSINGMARUBOZU(records);
    Log(ret);
}

The CDLCLOSINGMARUBOZU() function is described in the talib library documentation as: CDLCLOSINGMARUBOZU(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLCONCEALBABYSWALL

The talib.CDLCONCEALBABYSWALL() function is used to calculate the Concealing Baby Swallow (K-line chart: Concealing Baby Swallow pattern).

The return value of the talib.CDLCONCEALBABYSWALL() function is: a one-dimensional array. array

talib.CDLCONCEALBABYSWALL(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLCONCEALBABYSWALL(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLCONCEALBABYSWALL(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLCONCEALBABYSWALL(records);
    Log(ret);
}

The CDLCONCEALBABYSWALL() function is described in the talib library documentation as: CDLCONCEALBABYSWALL(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLCOUNTERATTACK

The talib.CDLCOUNTERATTACK() function is used to calculate Counterattack (K-line chart:Counterattack).

The return value of the talib.CDLCOUNTERATTACK() function is a one-dimensional array. array

talib.CDLCOUNTERATTACK(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLCOUNTERATTACK(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLCOUNTERATTACK(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLCOUNTERATTACK(records);
    Log(ret);
}

The CDLCOUNTERATTACK() function is described in the talib library documentation as: CDLCOUNTERATTACK(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLDARKCLOUDCOVER

The talib.CDLDARKCLOUDCOVER() function is used to calculate Dark Cloud Cover (K-line chart: dark cloud cover).

The return value of the talib.CDLDARKCLOUDCOVER() function is a one-dimensional array. array

talib.CDLDARKCLOUDCOVER(inPriceOHLC) talib.CDLDARKCLOUDCOVER(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is used to set the Penetration, the default value is 0.5. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLDARKCLOUDCOVER(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLDARKCLOUDCOVER(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLDARKCLOUDCOVER(records);
    Log(ret);
}

The CDLDARKCLOUDCOVER() function is described in the talib library documentation as: CDLDARKCLOUDCOVER(Records[Open,High,Low,Close],Penetration = 0.5) = Array(outInteger)

talib.CDLDOJI

The talib.CDLDOJI() function is used to calculate Doji (K-line chart: Doji).

The return value of the talib.CDLDOJI() function is: a one-dimensional array. array

talib.CDLDOJI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLDOJI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLDOJI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLDOJI(records);
    Log(ret);
}

The CDLDOJI() function is described in the talib library documentation as: CDLDOJI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLDOJISTAR

The talib.CDLDOJISTAR() function is used to calculate the Doji Star (K-line chart: Doji Star).

The return value of the talib.CDLDOJISTAR() function is: a one-dimensional array. array

talib.CDLDOJISTAR(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLDOJISTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLDOJISTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLDOJISTAR(records);
    Log(ret);
}

The CDLDOJISTAR() function is described in the talib library documentation as: CDLDOJISTAR(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLDRAGONFLYDOJI

The talib.CDLDRAGONFLYDOJI() function is used to calculate Dragonfly Doji (K-line chart: Dragonfly Doji).

The return value of the talib.CDLDRAGONFLYDOJI() function is: a one-dimensional array. array

talib.CDLDRAGONFLYDOJI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLDRAGONFLYDOJI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLDRAGONFLYDOJI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLDRAGONFLYDOJI(records);
    Log(ret);
}

The CDLDRAGONFLYDOJI() function is described in the talib library documentation as: CDLDRAGONFLYDOJI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLENGULFING

The talib.CDLENGULFING() function is used to calculate the Engulfing Pattern (K-line chart: engulfing).

The return value of the talib.CDLENGULFING() function is a one-dimensional array. array

talib.CDLENGULFING(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLENGULFING(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLENGULFING(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLENGULFING(records);
    Log(ret);
}

The CDLENGULFING() function is described in the talib library documentation as: CDLENGULFING(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLEVENINGDOJISTAR

The talib.CDLEVENINGDOJISTAR() function is used to calculate the Evening Doji Star (K-line chart: Evening Doji Star).

The return value of the talib.CDLEVENINGDOJISTAR() function is: a one-dimensional array. array

talib.CDLEVENINGDOJISTAR(inPriceOHLC) talib.CDLEVENINGDOJISTAR(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is used to set the Penetration, the default value is 0.3. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLEVENINGDOJISTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLEVENINGDOJISTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLEVENINGDOJISTAR(records);
    Log(ret);
}

The CDLEVENINGDOJISTAR() function is described in the talib library documentation as: CDLEVENINGDOJISTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)

talib.CDLEVENINGSTAR

The talib.CDLEVENINGSTAR() function is used to calculate the Evening Star (K-line chart: Evening Star).

The return value of the talib.CDLEVENINGSTAR() function is: a one-dimensional array. array

talib.CDLEVENINGSTAR(inPriceOHLC) talib.CDLEVENINGSTAR(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is used to set the Penetration, the default value is 0.3. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLEVENINGSTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLEVENINGSTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLEVENINGSTAR(records);
    Log(ret);
}

The CDLEVENINGSTAR() function is described in the talib library documentation as: CDLEVENINGSTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)

talib.CDLGAPSIDESIDEWHITE

The talib.CDLGAPSIDESIDEWHITE() function is used to calculate Up/Down-gap side-by-side white lines (K-line chart: Up/Down gap side-by-side white lines).

The return value of the talib.CDLGAPSIDESIDEWHITE() function is: a one-dimensional array. array

talib.CDLGAPSIDESIDEWHITE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLGAPSIDESIDEWHITE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLGAPSIDESIDEWHITE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLGAPSIDESIDEWHITE(records);
    Log(ret);
}

The CDLGAPSIDESIDEWHITE() function is described in the talib library documentation as: CDLGAPSIDESIDEWHITE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLGRAVESTONEDOJI

The talib.CDLGRAVESTONEDOJI() function is used to calculate the Gravestone Doji (K-line chart: Gravestone Doji).

The return value of the talib.CDLGRAVESTONEDOJI() function is: a one-dimensional array. array

talib.CDLGRAVESTONEDOJI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLGRAVESTONEDOJI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLGRAVESTONEDOJI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLGRAVESTONEDOJI(records);
    Log(ret);
}

The CDLGRAVESTONEDOJI() function is described in the talib library documentation as: CDLGRAVESTONEDOJI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHAMMER

The talib.CDLHAMMER() function is used to calculate Hammer (K-line chart: Hammer).

The return value of the talib.CDLHAMMER() function is: a one-dimensional array. array

talib.CDLHAMMER(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHAMMER(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHAMMER(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHAMMER(records);
    Log(ret);
}

The CDLHAMMER() function is described in the talib library documentation as: CDLHAMMER(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHANGINGMAN

The talib.CDLHANGINGMAN() function is used to calculate Hanging Man (K-line chart: Hanging Man).

The return value of the talib.CDLHANGINGMAN() function is a one-dimensional array. array

talib.CDLHANGINGMAN(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHANGINGMAN(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHANGINGMAN(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHANGINGMAN(records);
    Log(ret);
}

The CDLHANGINGMAN() function is described in the talib library documentation as: CDLHANGINGMAN(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHARAMI

The talib.CDLHARAMI() function is used to calculate the Harami Pattern (K-line chart: negative and positive lines).

The return value of the talib.CDLHARAMI() function is a one-dimensional array. array

talib.CDLHARAMI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHARAMI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHARAMI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHARAMI(records);
    Log(ret);
}

The CDLHARAMI() function is described in the talib library documentation as: CDLHARAMI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHARAMICROSS

The talib.CDLHARAMICROSS() function is used to calculate the Harami Cross Pattern (K-line chart: cross negative and positive lines).

The return value of the talib.CDLHARAMICROSS() function is: a one-dimensional array. array

talib.CDLHARAMICROSS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHARAMICROSS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHARAMICROSS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHARAMICROSS(records);
    Log(ret);
}

The CDLHARAMICROSS() function is described in the talib library documentation as: CDLHARAMICROSS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHIGHWAVE

The talib.CDLHIGHWAVE() function is used to calculate the High-Wave Candle (K-line chart: Long Leg Cross).

The return value of the talib.CDLHIGHWAVE() function is a one-dimensional array. array

talib.CDLHIGHWAVE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHIGHWAVE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHIGHWAVE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHIGHWAVE(records);
    Log(ret);
}

The CDLHIGHWAVE() function is described in the talib library documentation as: CDLHIGHWAVE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHIKKAKE

The talib.CDLHIKKAKE() function is used to calculate the Hikkake Pattern (K-line chart: trap).

The return value of the talib.CDLHIKKAKE() function is a one-dimensional array. array

talib.CDLHIKKAKE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHIKKAKE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHIKKAKE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHIKKAKE(records);
    Log(ret);
}

The CDLHIKKAKE() function is described in the talib library documentation as: CDLHIKKAKE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHIKKAKEMOD

The talib.CDLHIKKAKEMOD() function is used to calculate the Modified Hikkake Pattern (K-line chart: Modified Trap).

The return value of the talib.CDLHIKKAKEMOD() function is: a one-dimensional array. array

talib.CDLHIKKAKEMOD(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHIKKAKEMOD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHIKKAKEMOD(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHIKKAKEMOD(records);
    Log(ret);
}

The CDLHIKKAKEMOD() function is described in the talib library documentation as: CDLHIKKAKEMOD(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLHOMINGPIGEON

The talib.CDLHOMINGPIGEON() function is used to calculate the Homing Pigeon (K-line chart: Pigeon).

The return value of the talib.CDLHOMINGPIGEON() function is: a one-dimensional array. array

talib.CDLHOMINGPIGEON(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLHOMINGPIGEON(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLHOMINGPIGEON(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLHOMINGPIGEON(records);
    Log(ret);
}

The CDLHOMINGPIGEON() function is described in the talib library documentation as: CDLHOMINGPIGEON(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLIDENTICAL3CROWS

The talib.CDLIDENTICAL3CROWS() function is used to calculate Identical Three Crows (K-line chart: same three crows).

The return value of the talib.CDLIDENTICAL3CROWS() function is: a one-dimensional array. array

talib.CDLIDENTICAL3CROWS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLIDENTICAL3CROWS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLIDENTICAL3CROWS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLIDENTICAL3CROWS(records);
    Log(ret);
}

The CDLIDENTICAL3CROWS() function is described in the talib library documentation as: CDLIDENTICAL3CROWS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLINNECK

The talib.CDLINNECK() function is used to calculate the In-Neck Pattern (K-line chart: neckline).

The return value of the talib.CDLINNECK() function is: a one-dimensional array. array

talib.CDLINNECK(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLINNECK(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLINNECK(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLINNECK(records);
    Log(ret);
}

The CDLINNECK() function is described in the talib library documentation as: CDLINNECK(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLINVERTEDHAMMER

The talib.CDLINVERTEDHAMMER() function is used to calculate the Inverted Hammer (K-line chart: Inverted Hammer).

The return value of the talib.CDLINVERTEDHAMMER() function is: a one-dimensional array. array

talib.CDLINVERTEDHAMMER(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLINVERTEDHAMMER(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLINVERTEDHAMMER(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLINVERTEDHAMMER(records);
    Log(ret);
}

The CDLINVERTEDHAMMER() function is described in the talib library documentation as: CDLINVERTEDHAMMER(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLKICKING

The talib.CDLKICKING() function is used to calculate Kicking (K-line chart: kicking).

The return value of the talib.CDLKICKING() function is a one-dimensional array. array

talib.CDLKICKING(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLKICKING(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLKICKING(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLKICKING(records);
    Log(ret);
}

The CDLKICKING() function is described in the talib library documentation as: CDLKICKING(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLKICKINGBYLENGTH

The talib.CDLKICKINGBYLENGTH() function is used to calculate the kick - bull/bear determined by the longer Marubozu (K-line chart: kick bull/kick bear).

The return value of the talib.CDLKICKINGBYLENGTH() function is: a one-dimensional array. array

talib.CDLKICKINGBYLENGTH(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLKICKINGBYLENGTH(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLKICKINGBYLENGTH(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLKICKINGBYLENGTH(records);
    Log(ret);
}

The CDLKICKINGBYLENGTH() function is described in the talib library documentation as: CDLKICKINGBYLENGTH(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLLADDERBOTTOM

The talib.CDLLADDERBOTTOM() function is used to calculate the Ladder Bottom (K-line chart: Ladder Bottom).

The return value of the talib.CDLLADDERBOTTOM() function is: a one-dimensional array. array

talib.CDLLADDERBOTTOM(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLLADDERBOTTOM(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLLADDERBOTTOM(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLLADDERBOTTOM(records);
    Log(ret);
}

The CDLLADDERBOTTOM() function is described in the talib library documentation as: CDLLADDERBOTTOM(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLLONGLEGGEDDOJI

The talib.CDLLONGLEGGEDDOJI() function is used to calculate the Long Legged Doji (K-line chart: Long Legged Doji).

The return value of the talib.CDLLONGLEGGEDDOJI() function is: a one-dimensional array. array

talib.CDLLONGLEGGEDDOJI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLLONGLEGGEDDOJI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLLONGLEGGEDDOJI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLLONGLEGGEDDOJI(records);
    Log(ret);
}

The CDLLONGLEGGEDDOJI() function is described in the talib library documentation as: CDLLONGLEGGEDDOJI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLLONGLINE

The talib.CDLLONGLINE() function is used to calculate the Long Line Candle (K-line chart: Long Line).

The return value of the talib.CDLLONGLINE() function is: a one-dimensional array. array

talib.CDLLONGLINE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLLONGLINE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLLONGLINE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLLONGLINE(records);
    Log(ret);
}

The CDLLONGLINE() function is described in the talib library documentation as: CDLLONGLINE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLMARUBOZU

The talib.CDLMARUBOZU() function is used to calculate the Marubozu (K-line chart: bare head and bare foot).

The return value of the talib.CDLMARUBOZU() function is a one-dimensional array. array

talib.CDLMARUBOZU(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLMARUBOZU(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLMARUBOZU(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLMARUBOZU(records);
    Log(ret);
}

The CDLMARUBOZU() function is described in the talib library documentation as: CDLMARUBOZU(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLMATCHINGLOW

The talib.CDLMATCHINGLOW() function is used to calculate Matching Low (K-line chart: Matching Low).

The return value of the talib.CDLMATCHINGLOW() function is: a one-dimensional array. array

talib.CDLMATCHINGLOW(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLMATCHINGLOW(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLMATCHINGLOW(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLMATCHINGLOW(records);
    Log(ret);
}

The CDLMATCHINGLOW() function is described in the talib library documentation as: CDLMATCHINGLOW(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLMATHOLD

The talib.CDLMATHOLD() function is used to calculate Mat Hold (K-line chart: Mat Hold).

The return value of the talib.CDLMATHOLD() function is: a one-dimensional array. array

talib.CDLMATHOLD(inPriceOHLC) talib.CDLMATHOLD(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is optional and is used to specify the percentage of the width of the rising/falling trend line, the default value is 0.5. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLMATHOLD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLMATHOLD(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLMATHOLD(records);
    Log(ret);
}

The CDLMATHOLD() function is described in the talib library documentation as: CDLMATHOLD(Records[Open,High,Low,Close],Penetration = 0.5) = Array(outInteger)

talib.CDLMORNINGDOJISTAR

The talib.CDLMORNINGDOJISTAR() function is used to calculate the Morning Doji Star (K-line chart: Morning Doji Star).

The return value of the talib.CDLMORNINGDOJISTAR() function is: a one-dimensional array. array

talib.CDLMORNINGDOJISTAR(inPriceOHLC) talib.CDLMORNINGDOJISTAR(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is used to specify the degree of overlap between the validation opening price and the solid part, the default value is 0.3. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLMORNINGDOJISTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLMORNINGDOJISTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLMORNINGDOJISTAR(records);
    Log(ret);
}

The CDLMORNINGDOJISTAR() function is described in the talib library documentation as: CDLMORNINGDOJISTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)

talib.CDLMORNINGSTAR

The talib.CDLMORNINGSTAR() function is used to calculate Morning Star (K-line chart: Morning Star).

The return value of the talib.CDLMORNINGSTAR() function is: a one-dimensional array. array

talib.CDLMORNINGSTAR(inPriceOHLC) talib.CDLMORNINGSTAR(inPriceOHLC, optInPenetration)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array The optInPenetration parameter is the price float percentage threshold required for trend confirmation and takes a value in the range [0,1], with a default value of 0.3. optInPenetration false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLMORNINGSTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLMORNINGSTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLMORNINGSTAR(records);
    Log(ret);
}

The CDLMORNINGSTAR() function is described in the talib library documentation as: CDLMORNINGSTAR(Records[Open,High,Low,Close],Penetration=0.3) = Array(outInteger)

talib.CDLONNECK

The talib.CDLONNECK() function is used to calculate the On-Neck Pattern (K-line chart: On-Neck Pattern).

The return value of the talib.CDLONNECK() function is a one-dimensional array. array

talib.CDLONNECK(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLONNECK(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLONNECK(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLONNECK(records);
    Log(ret);
}

The CDLONNECK() function is described in the talib library documentation as: CDLONNECK(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLPIERCING

The talib.CDLPIERCING() function is used to calculate the Piercing Pattern (K-line chart: Piercing Pattern).

The return value of the talib.CDLPIERCING() function is a one-dimensional array. array

talib.CDLPIERCING(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLPIERCING(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLPIERCING(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLPIERCING(records);
    Log(ret);
}

The CDLPIERCING() function is described in the talib library documentation as: CDLPIERCING(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLRICKSHAWMAN

The talib.CDLRICKSHAWMAN() function is used to calculate Rickshaw Man (K-line chart: Rickshaw Man).

The return value of the talib.CDLRICKSHAWMAN() function is: a one-dimensional array. array

talib.CDLRICKSHAWMAN(inPriceOHLC)

The inPriceOHLC parameter is used to specify K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLRICKSHAWMAN(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLRICKSHAWMAN(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLRICKSHAWMAN(records);
    Log(ret);
}

The CDLRICKSHAWMAN() function is described in the talib library documentation as: CDLRICKSHAWMAN(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLRISEFALL3METHODS

The talib.CDLRISEFALL3METHODS() function is used to calculate Rising/Falling Three Methods (K-line chart: Rising/Falling Three Methods).

The return value of the talib.CDLRISEFALL3METHODS() function is: a one-dimensional array. array

talib.CDLRISEFALL3METHODS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLRISEFALL3METHODS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLRISEFALL3METHODS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLRISEFALL3METHODS(records);
    Log(ret);
}

The CDLRISEFALL3METHODS() function is described in the talib library documentation as: CDLRISEFALL3METHODS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSEPARATINGLINES

The talib.CDLSEPARATINGLINES() function is used to calculate Separating Lines (K-line chart: Separating Lines).

The return value of the talib.CDLSEPARATINGLINES() function is a one-dimensional array. array

talib.CDLSEPARATINGLINES(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSEPARATINGLINES(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSEPARATINGLINES(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSEPARATINGLINES(records);
    Log(ret);
}

The CDLSEPARATINGLINES() function is described in the talib library documentation as: CDLSEPARATINGLINES(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSHOOTINGSTAR

The talib.CDLSHOOTINGSTAR() function is used to calculate the Shooting Star (K-line chart: Shooting Star).

The return value of the talib.CDLSHOOTINGSTAR() function is a one-dimensional array. array

talib.CDLSHOOTINGSTAR(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSHOOTINGSTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSHOOTINGSTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSHOOTINGSTAR(records);
    Log(ret);
}

The CDLSHOOTINGSTAR() function is described in the talib library documentation as: CDLSHOOTINGSTAR(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSHORTLINE

The talib.CDLSHORTLINE() function is used to calculate the Short Line Candle (K-line chart: Short Line).

The return value of the talib.CDLSHORTLINE() function is: a one-dimensional array. array

talib.CDLSHORTLINE(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSHORTLINE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSHORTLINE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSHORTLINE(records);
    Log(ret);
}

The CDLSHORTLINE() function is described in the talib library documentation as: CDLSHORTLINE(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSPINNINGTOP

The talib.CDLSPINNINGTOP() function is used to calculate Spinning Top (K-line chart: Spinning Top).

The return value of the talib.CDLSPINNINGTOP() function is: a one-dimensional array. array

talib.CDLSPINNINGTOP(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSPINNINGTOP(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSPINNINGTOP(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSPINNINGTOP(records);
    Log(ret);
}

The CDLSPINNINGTOP() function is described in the talib library documentation as: CDLSPINNINGTOP(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSTALLEDPATTERN

The talib.CDLSTALLEDPATTERN() function is used to calculate Stalled Pattern (K-line chart: Stalled Pattern).

The return value of the talib.CDLSTALLEDPATTERN() function is: a one-dimensional array. array

talib.CDLSTALLEDPATTERN(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSTALLEDPATTERN(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSTALLEDPATTERN(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSTALLEDPATTERN(records);
    Log(ret);
}

The CDLSTALLEDPATTERN() function is described in the talib library documentation as: CDLSTALLEDPATTERN(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLSTICKSANDWICH

The talib.CDLSTICKSANDWICH() function is used to calculate the Stick Sandwich (K-line chart: Stick Sandwich).

The return value of the talib.CDLSTICKSANDWICH() function is a one-dimensional array. array

talib.CDLSTICKSANDWICH(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLSTICKSANDWICH(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLSTICKSANDWICH(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLSTICKSANDWICH(records);
    Log(ret);
}

The CDLSTICKSANDWICH() function is described in the talib library documentation as: CDLSTICKSANDWICH(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLTAKURI

The talib.CDLTAKURI() function is used to calculate Takuri (dragonfly doji with a very long lower shadow line) (K-line chart: Takuri).

The return value of the talib.CDLTAKURI() function is a one-dimensional array. array

talib.CDLTAKURI(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLTAKURI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLTAKURI(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLTAKURI(records);
    Log(ret);
}

The CDLTAKURI() function is described in the talib library documentation as: CDLTAKURI(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLTASUKIGAP

The talib.CDLTASUKIGAP() function is used to calculate the Tasuki Gap (K-line chart: Tasuki Gap).

The return value of the talib.CDLTASUKIGAP() function is a one-dimensional array. array

talib.CDLTASUKIGAP(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLTASUKIGAP(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLTASUKIGAP(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLTASUKIGAP(records);
    Log(ret);
}

The CDLTASUKIGAP() function is described in the talib library documentation as: CDLTASUKIGAP(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLTHRUSTING

The talib.CDLTHRUSTING() function is used to calculate the Thrusting Pattern (K-line chart: Thrusting Pattern).

The return value of the talib.CDLTHRUSTING() function is: a one-dimensional array. array

talib.CDLTHRUSTING(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLTHRUSTING(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLTHRUSTING(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLTHRUSTING(records);
    Log(ret);
}

The CDLTHRUSTING() function is described in the talib library documentation as: CDLTHRUSTING(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLTRISTAR

The talib.CDLTRISTAR() function is used to calculate the Tristar Pattern (K-line chart: Tristar Pattern).

The return value of the talib.CDLTRISTAR() function is: a one-dimensional array. array

talib.CDLTRISTAR(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLTRISTAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLTRISTAR(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLTRISTAR(records);
    Log(ret);
}

The CDLTRISTAR() function is described in the talib library documentation as: CDLTRISTAR(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLUNIQUE3RIVER

The talib.CDLUNIQUE3RIVER() function is used to calculate the Unique 3 River (K-line chart: Unique 3 River).

The return value of the talib.CDLUNIQUE3RIVER() function is: a one-dimensional array. array

talib.CDLUNIQUE3RIVER(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLUNIQUE3RIVER(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLUNIQUE3RIVER(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLUNIQUE3RIVER(records);
    Log(ret);
}

The CDLUNIQUE3RIVER() function is described in the talib library documentation as: CDLUNIQUE3RIVER(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLUPSIDEGAP2CROWS

The talib.CDLUPSIDEGAP2CROWS() function is used to calculate Upside Gap Two Crows (K-line chart: Upside Gap Two Crows).

The return value of the talib.CDLUPSIDEGAP2CROWS() function is: a one-dimensional array. array

talib.CDLUPSIDEGAP2CROWS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLUPSIDEGAP2CROWS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLUPSIDEGAP2CROWS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLUPSIDEGAP2CROWS(records);
    Log(ret);
}

The CDLUPSIDEGAP2CROWS() function is described in the talib library documentation as: CDLUPSIDEGAP2CROWS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.CDLXSIDEGAP3METHODS

The talib.CDLXSIDEGAP3METHODS() function is used to calculate Upside/Downside Gap Three Methods (K-line chart: Upside/Downside Gap Three Methods).

The return value of the talib.CDLXSIDEGAP3METHODS() function is: a one-dimensional array. array

talib.CDLXSIDEGAP3METHODS(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CDLXSIDEGAP3METHODS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CDLXSIDEGAP3METHODS(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CDLXSIDEGAP3METHODS(records);
    Log(ret);
}

The CDLXSIDEGAP3METHODS() function is described in the talib library documentation as: CDLXSIDEGAP3METHODS(Records[Open,High,Low,Close]) = Array(outInteger)

talib.AD

The talib.AD() function is used to calculate the Chaikin A/D Line (line stochastic indicator).

The return value of the talib.AD() function is: a one-dimensional array. array

talib.AD(inPriceHLCV)

The inPriceHLCV parameter is used to specify the K-line data. inPriceHLCV true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.AD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.AD(records.High, records.Low, records.Close, records.Volume)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.AD(records);
    Log(ret);
}

The AD() function is described in the talib library documentation as: AD(Records[High,Low,Close,Volume]) = Array(outReal)

talib.ADOSC

The talib.ADOSC() function is used to calculate the Chaikin A/D Oscillator (Chaikin Oscillator).

The return value of the talib.ADOSC() function is a one-dimensional array. array

talib.ADOSC(inPriceHLCV) talib.ADOSC(inPriceHLCV, optInFastPeriod, optInSlowPeriod)

The inPriceHLCV parameter is used to specify the K-line data. inPriceHLCV true {@struct/Record Record} structure array The optInFastPeriod parameter is used to set the fast period. optInFastPeriod false number The optInSlowPeriod parameter is used to set the slow period. optInSlowPeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ADOSC(records, 3, 10)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ADOSC(records.High, records.Low, records.Close, records.Volume, 3, 10)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ADOSC(records, 3, 10);
    Log(ret);
}

The ADOSC() function is described in the talib library documentation as: ADOSC(Records[High,Low,Close,Volume],Fast Period = 3,Slow Period = 10) = Array(outReal)

talib.OBV

The talib.OBV() function is used to calculate On Balance Volume (energy tide).

The return value of the talib.OBV() function is a one-dimensional array. array

talib.OBV(inReal) talib.OBV(inReal, inPriceV)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The inPriceV parameter is used to specify the K-line data. inPriceV false {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.OBV(records, records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.OBV(records.Close, records.Volume)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.OBV(records);
    Log(ret);
}

The OBV() function is described in the talib library documentation as: OBV(Records[Close],Records[Volume]) = Array(outReal)

talib.ACOS

The talib.ACOS() function is used to calculate Vector Trigonometric ACos (inverse cosine function).

The return value of the talib.ACOS() function is a one-dimensional array. array

talib.ACOS(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.ACOS(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.ACOS(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.ACOS(data);
    Log(ret);
}

The ACOS() function is described in the talib library documentation as: ACOS(Records[Close]) = Array(outReal)

talib.ASIN

The talib.ASIN() function is used to calculate the Vector Trigonometric ASin (inverse sine function).

The return value of the talib.ASIN() function is a one-dimensional array. array

talib.ASIN(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.ASIN(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.ASIN(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.ASIN(data);
    Log(ret);
}

The ASIN() function is described in the talib library documentation as: ASIN(Records[Close]) = Array(outReal)

talib.ATAN

The talib.ATAN() function is used to calculate the Vector Trigonometric ATan (inverse tangent function).

The return value of the talib.ATAN() function is: a one-dimensional array. array

talib.ATAN(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-3.14/2, 0, 3.14/2]
    var ret = talib.ATAN(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-3.14/2, 0, 3.14/2]
    ret = talib.ATAN(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-3.14/2, 0, 3.14/2};
    auto ret = talib.ATAN(data);
    Log(ret);
}

The ATAN() function is described in the talib library documentation as: ATAN(Records[Close]) = Array(outReal)

talib.CEIL

The talib.CEIL() function is used to calculate Vector Ceil (rounding function).

The return value of the talib.CEIL() function is a one-dimensional array. array

talib.CEIL(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CEIL(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CEIL(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CEIL(records);
    Log(ret);
}

The CEIL() function is described in the talib library documentation as: CEIL(Records[Close]) = Array(outReal)

talib.COS

The talib.COS() function is used to calculate the Vector Trigonometric Cos (cosine function).

The return value of the talib.COS() function is: a one-dimensional array. array

talib.COS(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-3.14, 0, 3.14]
    var ret = talib.COS(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-3.14, 0, 3.14]
    ret = talib.COS(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-3.14, 0, 3.14};
    auto ret = talib.COS(data);
    Log(ret);
}

The COS() function is described in the talib library documentation as: COS(Records[Close]) = Array(outReal)

talib.COSH

The talib.COSH() function is used to calculate Vector Trigonometric Cosh (hyperbolic cosine value).

The return value of the talib.COSH() function is a one-dimensional array. array

talib.COSH(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.COSH(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.COSH(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.COSH(data);
    Log(ret);
}

The COSH() function is described in the talib library documentation as: COSH(Records[Close]) = Array(outReal)

talib.EXP

The talib.EXP() function is used to calculate the Vector Arithmetic Exp (exponential function).

The return value of the talib.EXP() function is: a one-dimensional array. array

talib.EXP(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [0, 1, 2]
    var ret = talib.EXP(data)    // e^0, e^1, e^2
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [0, 1.0, 2.0]
    ret = talib.EXP(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {0, 1.0, 2.0};
    auto ret = talib.EXP(data);
    Log(ret);
}

The EXP() function is described in the talib library documentation as: EXP(Records[Close]) = Array(outReal)

talib.FLOOR

The talib.FLOOR() function is used to calculate the Vector Floor (rounded down).

The return value of the talib.FLOOR() function is a one-dimensional array. array

talib.FLOOR(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.FLOOR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.FLOOR(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.FLOOR(records);
    Log(ret);
}

The FLOOR() function is described in the talib library documentation as: FLOOR(Records[Close]) = Array(outReal)

talib.LN

The talib.LN() function is used to calculate the Vector Log Natural (natural logarithm).

The return value of the talib.LN() function is a one-dimensional array. array

talib.LN(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [1, 2, 3]
    var ret = talib.LN(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [1.0, 2.0, 3.0]
    ret = talib.LN(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {1, 2, 3};
    auto ret = talib.LN(data);
    Log(ret);
}

The LN() function is described in the talib library documentation as: LN(Records[Close]) = Array(outReal)

talib.LOG10

The talib.LOG10() function is used to calculate Vector Log10 (logarithmic function).

The return value of the talib.LOG10() function is a one-dimensional array. array

talib.LOG10(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [10, 100, 1000]
    var ret = talib.LOG10(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [10.0, 100.0, 1000.0]
    ret = talib.LOG10(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {10, 100, 1000};
    auto ret = talib.LOG10(data);
    Log(ret);
}

The LOG10() function is described in the talib library documentation as: LOG10(Records[Close]) = Array(outReal)

talib.SIN

The talib.SIN() function is used to calculate Vector Trigonometric Sin (sine value).

The return value of the talib.SIN() function is a one-dimensional array. array

talib.SIN(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-3.14/2, 0, 3.14/2]
    var ret = talib.SIN(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-3.14/2, 0, 3.14/2]
    ret = talib.SIN(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-3.14/2, 0, 3.14/2};
    auto ret = talib.SIN(data);
    Log(ret);
}

The SIN() function is described in the talib library documentation as: SIN(Records[Close]) = Array(outReal)

talib.SINH

The talib.SINH() function is used to calculate the Vector Trigonometric Sinh (hyperbolic sine function).

The return value of the talib.SINH() function is: a one-dimensional array. array

talib.SINH(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.SINH(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.SINH(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.SINH(data);
    Log(ret);
}

The SINH() function is described in the talib library documentation as: SINH(Records[Close]) = Array(outReal)

talib.SQRT

The talib.SQRT() function is used to calculate the Vector Square Root (square root).

The return value of the talib.SQRT() function is: a one-dimensional array. array

talib.SQRT(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [4, 64, 100]
    var ret = talib.SQRT(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [4.0, 64.0, 100.0]
    ret = talib.SQRT(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {4, 64, 100};
    auto ret = talib.SQRT(data);
    Log(ret);
}

The SQRT() function is described in the talib library documentation as: SQRT(Records[Close]) = Array(outReal)

talib.TAN

The talib.TAN() function is used to calculate the Vector Trigonometric Tan (tangent).

The return value of the talib.TAN() function is a one-dimensional array. array

talib.TAN(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.TAN(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.TAN(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.TAN(data);
    Log(ret);
}

The TAN() function is described in the talib library documentation as: TAN(Records[Close]) = Array(outReal)

talib.TANH

The talib.TANH() function is used to calculate the Vector Trigonometric Tanh (hyperbolic tangent function).

The return value of the talib.TANH() function is: a one-dimensional array. array

talib.TANH(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var data = [-1, 0, 1]
    var ret = talib.TANH(data)
    Log(ret)
}
import talib
import numpy as np
def main():
    data = [-1.0, 0, 1.0]
    ret = talib.TANH(np.array(data))
    Log(ret)
void main() {
    std::vector<double> data = {-1, 0, 1};
    auto ret = talib.TANH(data);
    Log(ret);
}

The TANH() function is described in the talib library documentation as: TANH(Records[Close]) = Array(outReal)

talib.MAX

The talib.MAX() function is used to calculate the highest (maximum) value for a specific period.

The return value of the talib.MAX() function is: a one-dimensional array. array

talib.MAX(inReal) talib.MAX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MAX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MAX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MAX(records);
    Log(ret);
}

The MAX() function is described in the talib library documentation as: MAX(Records[Close],Time Period = 30) = Array(outReal)

talib.MAXINDEX

The talib.MAXINDEX() function is used to calculate the index of the highest value in the specified period (maximum index).

The return value of the talib.MAXINDEX() function is: a one-dimensional array. array

talib.MAXINDEX(inReal) talib.MAXINDEX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MAXINDEX(records, 5)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MAXINDEX(records.Close, 5)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MAXINDEX(records, 5);
    Log(ret);
}

The MAXINDEX() function is described in the talib library documentation as: MAXINDEX(Records[Close],Time Period = 30) = Array(outInteger)

talib.MIN

The talib.MIN() function is used to calculate the lowest value (minimum value)** for the specified period.

The return value of the talib.MIN() function is: a one-dimensional array. array

talib.MIN(inReal) talib.MIN(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MIN(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MIN(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MIN(records);
    Log(ret);
}

The MIN() function is described in the talib library documentation as: MIN(Records[Close],Time Period = 30) = Array(outReal)

talib.MININDEX

The talib.MININDEX() function is used to calculate the lowest value index (minimum value index) for the specified period.

The return value of the talib.MININDEX() function is: a one-dimensional array. array

talib.MININDEX(inReal) talib.MININDEX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MININDEX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MININDEX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MININDEX(records);
    Log(ret);
}

The MININDEX() function is described in the talib library documentation as: MININDEX(Records[Close],Time Period = 30) = Array(outInteger)

talib.MINMAX

The talib.MINMAX() function is used to calculate the lowest and highest (minimum and maximum) values for the specified period.

The return value of the talib.MINMAX() function is a two-dimensional array. The first element of this two-dimensional array is the array of minimum values, and the second element is the array of maximum values. array

talib.MINMAX(inReal) talib.MINMAX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MINMAX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MINMAX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MINMAX(records);
    Log(ret);
}

The MINMAX() function is described in the talib library documentation as: MINMAX(Records[Close],Time Period = 30) = [Array(outMin),Array(outMax)]

talib.MINMAXINDEX

The talib.MINMAXINDEX() function is used to calculate the index of the lowest and highest (minimum and maximum index) values in the specified period.

The return value of the talib.MINMAXINDEX() function is: a two-dimensional array. The first element of this two-dimensional array is the minimum indexed array, and the second element is the maximum indexed array. array

talib.MINMAXINDEX(inReal) talib.MINMAXINDEX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MINMAXINDEX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MINMAXINDEX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MINMAXINDEX(records);
    Log(ret);
}

The MINMAXINDEX() function is described in the talib library documentation as: MINMAXINDEX(Records[Close],Time Period = 30) = [Array(outMinIdx),Array(outMaxIdx)]

talib.SUM

The talib.SUM() function is used to calculate Summation.

The return value of the talib.SUM() function is: a one-dimensional array. array

talib.SUM(inReal) talib.SUM(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.SUM(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.SUM(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.SUM(records);
    Log(ret);
}

The SUM() function is described in the talib library documentation as: SUM(Records[Close],Time Period = 30) = Array(outReal)

talib.HT_DCPERIOD

The talib.HT_DCPERIOD() function is used to calculate the Hilbert Transform - Dominant Cycle Period (Hilbert Transform, Dominant Period).

The return value of the talib.HT_DCPERIOD() function is: a one-dimensional array. array

talib.HT_DCPERIOD(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_DCPERIOD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_DCPERIOD(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_DCPERIOD(records);
    Log(ret);
}

The HT_DCPERIOD() function is described in the talib library documentation as: HT_DCPERIOD(Records[Close]) = Array(outReal)

talib.HT_DCPHASE

The talib.HT_DCPHASE() function is used to calculate the Hilbert Transform - Dominant Cycle Phase (Hilbert Transform, Dominant Cycle Phase).

The return value of the talib.HT_DCPHASE() function is: a one-dimensional array. array

talib.HT_DCPHASE(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_DCPHASE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_DCPHASE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_DCPHASE(records);
    Log(ret);
}

The HT_DCPHASE() function is described in the talib library documentation as: HT_DCPHASE(Records[Close]) = Array(outReal)

talib.HT_PHASOR

The talib.HT_PHASOR() function is used to calculate the Hilbert Transform - Phasor Components (Hilbert Transform, Phase Components).

The return value of the talib.HT_PHASOR() function is a two-dimensional array. array

talib.HT_PHASOR(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_PHASOR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_PHASOR(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_PHASOR(records);
    Log(ret);
}

The HT_PHASOR() function is described in the talib library documentation as: HT_PHASOR(Records[Close]) = [Array(outInPhase),Array(outQuadrature)]

talib.HT_SINE

The talib.HT_SINE() function is used to calculate the Hilbert Transform - SineWave (Hilbert Transform, Sine Wave).

The return value of the talib.HT_SINE() function is: a two-dimensional array. array

talib.HT_SINE(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_SINE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_SINE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_SINE(records);
    Log(ret);
}

The HT_SINE() function is described in the talib library documentation as: HT_SINE(Records[Close]) = [Array(outSine),Array(outLeadSine)]

talib.HT_TRENDMODE

The talib.HT_TRENDMODE() function is used to calculate the Hilbert Transform - Trend and Cycle Mode.

The return value of the talib.HT_TRENDMODE() function is: a one-dimensional array. array

talib.HT_TRENDMODE(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_TRENDMODE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_TRENDMODE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_TRENDMODE(records);
    Log(ret);
}

The HT_TRENDMODE() function is described in the talib library documentation as: HT_TRENDMODE(Records[Close]) = Array(outInteger)

talib.ATR

The talib.ATR() function is used to calculate the Average True Range.

The return value of the talib.ATR() function is a one-dimensional array. array

talib.ATR(inPriceHLC) talib.ATR(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ATR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ATR(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ATR(records);
    Log(ret);
}

The ATR() function is described in the talib library documentation as: ATR(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.NATR

The talib.NATR() function is used to calculate the Normalized Average True Range.

The return value of the talib.NATR() function is a one-dimensional array. array

talib.NATR(inPriceHLC) talib.NATR(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.NATR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.NATR(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.NATR(records);
    Log(ret);
}

The NATR() function is described in the talib library documentation as: NATR(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.TRANGE

The talib.TRANGE() function is used to calculate the True Range.

The return value of the talib.TRANGE() function is: a one-dimensional array. array

talib.TRANGE(inPriceHLC)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TRANGE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TRANGE(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TRANGE(records);
    Log(ret);
}

The TRANGE() function is described in the talib library documentation as: TRANGE(Records[High,Low,Close]) = Array(outReal)

talib.BBANDS

The talib.BBANDS() function is used to calculate Bollinger Bands.

The return value of the talib.BBANDS() function is: a two-dimensional array. The array contains three elements which are: the upper line array, the middle line array, and the lower line array. array

talib.BBANDS(inReal) talib.BBANDS(inReal, optInTimePeriod) talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp) talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp, optInNbDevDn) talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp, optInNbDevDn, optInMAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 5. optInTimePeriod false number The optInNbDevUp parameter is used to set the upline multiplier, the default value is 2. optInNbDevUp false number The optInNbDevDn parameter is used to set the lower line multiplier, the default value is 2. optInNbDevDn false number The optInMAType parameter is used to set the mean type, the default value is 0. optInMAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.BBANDS(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.BBANDS(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.BBANDS(records);
    Log(ret);
}

The BBANDS() function is described in the talib library documentation as: BBANDS(Records[Close],Time Period = 5,Deviations up = 2,Deviations down = 2,MA Type = 0) = [Array(outRealUpperBand),Array(outRealMiddleBand),Array(outRealLowerBand)]

talib.DEMA

The talib.DEMA() function is used to calculate the Double Exponential Moving Average.

The return value of the talib.DEMA() function is a one-dimensional array. array

talib.DEMA(inReal) talib.DEMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.DEMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.DEMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.DEMA(records);
    Log(ret);
}

The DEMA() function is described in the talib library documentation as: DEMA(Records[Close],Time Period = 30) = Array(outReal)

talib.EMA

The talib.EMA() function is used to calculate the Exponential Moving Average.

The return value of the talib.EMA() function is a one-dimensional array. array

talib.EMA(inReal) talib.EMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.EMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.EMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.EMA(records);
    Log(ret);
}

The EMA() function is described in the talib library documentation as: EMA(Records[Close],Time Period = 30) = Array(outReal)

talib.HT_TRENDLINE

The talib.HT_TRENDLINE() function is used to calculate the Hilbert Transform - Instantaneous Trendline (Hilbert Transform, Instantaneous Trend).

The return value of the talib.HT_TRENDLINE() function is: a one-dimensional array. array

talib.HT_TRENDLINE(inReal)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays

function main() {
    var records = exchange.GetRecords()
    var ret = talib.HT_TRENDLINE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.HT_TRENDLINE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.HT_TRENDLINE(records);
    Log(ret);
}

The HT_TRENDLINE() function is described in the talib library documentation as: HT_TRENDLINE(Records[Close]) = Array(outReal)

talib.KAMA

The talib.KAMA() function is used to calculate the Kaufman Adaptive Moving Average.

The return value of the talib.KAMA() function is: a one-dimensional array. array

talib.KAMA(inReal) talib.KAMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.KAMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.KAMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.KAMA(records);
    Log(ret);
}

The KAMA() function is described in the talib library documentation as: KAMA(Records[Close],Time Period = 30) = Array(outReal)

talib.MA

The talib.MA() function is used to calculate the Moving average.

The return value of the talib.MA() function is: a one-dimensional array. array

talib.MA(inReal) talib.MA(inReal, optInTimePeriod) talib.MA(inReal, optInTimePeriod, optInMAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number The optInMAType parameter is used to set the mean type, the default value is 0. optInMAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MA(records);
    Log(ret);
}

The MA() function is described in the talib library documentation as: MA(Records[Close],Time Period = 30,MA Type = 0) = Array(outReal)

talib.MAMA

The talib.MAMA() function is used to calculate the MESA Adaptive Moving Average.

The return value of the talib.MAMA() function is: a two-dimensional array. array

talib.MAMA(inReal) talib.MAMA(inReal, optInFastLimit) talib.MAMA(inReal, optInFastLimit, optInSlowLimit)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastLimit parameter is used to set the Fast Limit, the default value is 0.5. optInFastLimit false number The optInSlowLimit parameter is used to set the Slow Limit, the default value is 0.05. optInSlowLimit false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MAMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MAMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MAMA(records);
    Log(ret);
}

The MAMA() function is described in the talib library documentation as: MAMA(Records[Close],Fast Limit = 0.5,Slow Limit = 0.05) = [Array(outMAMA),Array(outFAMA)]

talib.MIDPOINT

The talib.MIDPOINT() function is used to calculate the MidPoint over period (midpoint).

The return value of the talib.MIDPOINT() function is a one-dimensional array. array

talib.MIDPOINT(inReal) talib.MIDPOINT(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MIDPOINT(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MIDPOINT(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MIDPOINT(records);
    Log(ret);
}

The MIDPOINT() function is described in the talib library documentation as: MIDPOINT(Records[Close],Time Period = 14) = Array(outReal)

talib.MIDPRICE

The talib.MIDPRICE() function is used to calculate the Midpoint Price over period (midpoint price).

The return value of the talib.MIDPRICE() function is a one-dimensional array. array

talib.MIDPRICE(inPriceHL) talib.MIDPRICE(inPriceHL, optInTimePeriod)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MIDPRICE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MIDPRICE(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MIDPRICE(records);
    Log(ret);
}

The MIDPRICE() function is described in the talib library documentation as: MIDPRICE(Records[High,Low],Time Period = 14) = Array(outReal)

talib.SAR

The talib.SAR() function is used to calculate the Parabolic SAR.

The return value of the talib.SAR() function is: a one-dimensional array. array

talib.SAR(inPriceHL) talib.SAR(inPriceHL, optInAcceleration) talib.SAR(inPriceHL, optInAcceleration, optInMaximum)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInAcceleration parameter is used to set the Acceleration Factor, the default value is 0.02. optInAcceleration false number The optInMaximum parameter is used to set the AF Maximum, the default value is 0.2. optInMaximum false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.SAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.SAR(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.SAR(records);
    Log(ret);
}

The SAR() function is described in the talib library documentation as: SAR(Records[High,Low],Acceleration Factor = 0.02,AF Maximum = 0.2) = Array(outReal)

talib.SAREXT

The talib.SAREXT() function is used to calculate the Parabolic SAR - Extended (enhanced parabolic steering).

The return value of the talib.SAREXT() function is a one-dimensional array. array

talib.SAREXT(inPriceHL) talib.SAREXT(inPriceHL, optInStartValue) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort, optInAccelerationShort) talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort, optInAccelerationShort, optInAccelerationMaxShort)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInStartValue parameter is used to set the Start Value, the default value is 0. optInStartValue false number The optInOffsetOnReverse parameter is used to set Offset on Reverse, the default value is 0. optInOffsetOnReverse false number The optInAccelerationInitLong parameter is used to set the AF Init Long, the default value is 0.02. optInAccelerationInitLong false number The optInAccelerationLong parameter is used to set the AF Long, the default value is 0.02. optInAccelerationLong false number The optInAccelerationMaxLong parameter is used to set the AF Max Long, the default value is 0.2. optInAccelerationMaxLong false number The optInAccelerationInitShort parameter is used to set AF Init Short, the default value is 0.02. optInAccelerationInitShort false number The optInAccelerationShort parameter is used to set AF Short, the default value is 0.02. optInAccelerationShort false number The optInAccelerationMaxShort parameter is used to set AF Max Short, the default value is 0.2. optInAccelerationMaxShort false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.SAREXT(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.SAREXT(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.SAREXT(records);
    Log(ret);
}

The SAREXT() function is described in the talib library documentation as: SAREXT(Records[High,Low],Start Value = 0,Offset on Reverse = 0,AF Init Long = 0.02,AF Long = 0.02,AF Max Long = 0.2,AF Init Short = 0.02,AF Short = 0.02,AF Max Short = 0.2) = Array(outReal)

talib.SMA

The talib.SMA() function is used to calculate Simple Moving Average.

The return value of the talib.SMA() function is: a one-dimensional array. array

talib.SMA(inReal) talib.SMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.SMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.SMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.SMA(records);
    Log(ret);
}

The SMA() function is described in the talib library documentation as: SMA(Records[Close],Time Period = 30) = Array(outReal)

talib.T3

The talib.T3() function is used to calculate the Triple Exponential Moving Average (T3) (triple exponential moving average).

The return value of the talib.T3() function is a one-dimensional array. array

talib.T3(inReal) talib.T3(inReal, optInTimePeriod) talib.T3(inReal, optInTimePeriod, optInVFactor)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 5. optInTimePeriod false number The optInVFactor parameter is used to set the Volume Factor, the default value is 0.7. optInVFactor false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.T3(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.T3(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.T3(records);
    Log(ret);
}

The T3() function is described in the talib library documentation as: T3(Records[Close],Time Period = 5,Volume Factor = 0.7) = Array(outReal)

talib.TEMA

The talib.TEMA() function is used to calculate Triple Exponential Moving Average.

The return value of the talib.TEMA() function is a one-dimensional array. array

talib.TEMA(inReal) talib.TEMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TEMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TEMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TEMA(records);
    Log(ret);
}

The TEMA() function is described in the talib library documentation as: TEMA(Records[Close],Time Period = 30) = Array(outReal)

talib.TRIMA

The talib.TRIMA() function is used to calculate the Triangular Moving Average (tri-exponential moving average).

The return value of the talib.TRIMA() function is a one-dimensional array. array

talib.TRIMA(inReal) talib.TRIMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TRIMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TRIMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TRIMA(records);
    Log(ret);
}

The TRIMA() function is described in the talib library documentation as: TRIMA(Records[Close],Time Period = 30) = Array(outReal)

talib.WMA

The talib.WMA() function is used to calculate the Weighted Moving Average (WMA).

The return value of the talib.WMA() function is a one-dimensional array. array

talib.WMA(inReal) talib.WMA(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.WMA(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.WMA(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.WMA(records);
    Log(ret);
}

The WMA() function is described in the talib library documentation as: WMA(Records[Close],Time Period = 30) = Array(outReal)

talib.LINEARREG

The talib.LINEARREG() function is used to calculate Linear Regression.

The return value of the talib.LINEARREG() function is a one-dimensional array. array

talib.LINEARREG(inReal) talib.LINEARREG(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.LINEARREG(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.LINEARREG(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.LINEARREG(records);
    Log(ret);
}

The LINEARREG() function is described in the talib library documentation as: LINEARREG(Records[Close],Time Period = 14) = Array(outReal)

talib.LINEARREG_ANGLE

The talib.LINEARREG_ANGLE() function is used to calculate the Linear Regression Angle.

The return value of the talib.LINEARREG_ANGLE() function is: a one-dimensional array. array

talib.LINEARREG_ANGLE(inReal) talib.LINEARREG_ANGLE(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.LINEARREG_ANGLE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.LINEARREG_ANGLE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.LINEARREG_ANGLE(records);
    Log(ret);
}

The LINEARREG_ANGLE() function is described in the talib library documentation as: LINEARREG_ANGLE(Records[Close],Time Period = 14) = Array(outReal)

talib.LINEARREG_INTERCEPT

The talib.LINEARREG_INTERCEPT() function is used to calculate the Linear Regression Intercept.

The return value of the talib.LINEARREG_INTERCEPT() function is: a one-dimensional array. array

talib.LINEARREG_INTERCEPT(inReal) talib.LINEARREG_INTERCEPT(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.LINEARREG_INTERCEPT(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.LINEARREG_INTERCEPT(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.LINEARREG_INTERCEPT(records);
    Log(ret);
}

The LINEARREG_INTERCEPT() function is described in the talib library documentation as: LINEARREG_INTERCEPT(Records[Close],Time Period = 14) = Array(outReal)

talib.LINEARREG_SLOPE

The talib.LINEARREG_SLOPE() function is used to calculate the Linear Regression Slope.

The return value of the talib.LINEARREG_SLOPE() function is: a one-dimensional array. array

talib.LINEARREG_SLOPE(inReal) talib.LINEARREG_SLOPE(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.LINEARREG_SLOPE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.LINEARREG_SLOPE(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.LINEARREG_SLOPE(records);
    Log(ret);
}

The LINEARREG_SLOPE() function is described in the talib library documentation as: LINEARREG_SLOPE(Records[Close],Time Period = 14) = Array(outReal)

talib.STDDEV

The talib.STDDEV() function is used to calculate Standard Deviation.

The return value of the talib.STDDEV() function is: a one-dimensional array. array

talib.STDDEV(inReal) talib.STDDEV(inReal, optInTimePeriod) talib.STDDEV(inReal, optInTimePeriod, optInNbDev)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 5. optInTimePeriod false number The optInNbDev parameter is used to set the Deviations, the default value is 1. optInNbDev false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.STDDEV(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.STDDEV(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.STDDEV(records);
    Log(ret);
}

The STDDEV() function is described in the talib library documentation as: STDDEV(Records[Close],Time Period = 5,Deviations = 1) = Array(outReal)

talib.TSF

The talib.TSF() function is used to calculate Time Series Forecast.

The return value of the talib.TSF() function is a one-dimensional array. array

talib.TSF(inReal) talib.TSF(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TSF(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TSF(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TSF(records);
    Log(ret);
}

The TSF() function is described in the talib library documentation as: TSF(Records[Close],Time Period = 14) = Array(outReal)

talib.VAR

The talib.VAR() function is used to calculate Variance.

The return value of the talib.VAR() function is: a one-dimensional array. array

talib.VAR(inReal) talib.VAR(inReal, optInTimePeriod) talib.VAR(inReal, optInTimePeriod, optInNbDev)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 5. optInTimePeriod false number The optInNbDev parameter is used to set the Deviations, the default value is 1. optInNbDev false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.VAR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.VAR(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.VAR(records);
    Log(ret);
}

The VAR() function is described in the talib library documentation as: VAR(Records[Close],Time Period = 5,Deviations = 1) = Array(outReal)

talib.ADX

The talib.ADX() function is used to calculate the Average Directional Movement Index.

The return value of the talib.ADX() function is a one-dimensional array. array

talib.ADX(inPriceHLC) talib.ADX(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ADX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ADX(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ADX(records);
    Log(ret);
}

The ADX() function is described in the talib library documentation as: ADX(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.ADXR

The talib.ADXR() function is used to calculate the Average Directional Movement Index Rating (assessment index).

The return value of the talib.ADXR() function is a one-dimensional array. array

talib.ADXR(inPriceHLC) talib.ADXR(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ADXR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ADXR(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ADXR(records);
    Log(ret);
}

The ADXR() function is described in the talib library documentation as: ADXR(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.APO

The talib.APO() function is used to calculate the Absolute Price Oscillator.

The return value of the talib.APO() function is: a one-dimensional array. array

talib.APO(inReal) talib.APO(inReal, optInFastPeriod) talib.APO(inReal, optInFastPeriod, optInSlowPeriod) talib.APO(inReal, optInFastPeriod, optInSlowPeriod, optInMAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastPeriod parameter is used to set the fast period, the default value is 12. optInFastPeriod false number The optInSlowPeriod parameter is used to set the slow period, the default value is 26. optInSlowPeriod false number The optInMAType parameter is used to set the mean type, the default value is 0. optInMAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.APO(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.APO(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.APO(records);
    Log(ret);
}

The APO() function is described in the talib library documentation as: APO(Records[Close],Fast Period = 12,Slow Period = 26,MA Type = 0) = Array(outReal)

talib.AROON

The talib.AROON() function is used to calculate the Aroon (Aroon indicator).

The return value of the talib.AROON() function is a two-dimensional array. array

talib.AROON(inPriceHL) talib.AROON(inPriceHL, optInTimePeriod)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.AROON(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.AROON(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.AROON(records);
    Log(ret);
}

The AROON() function is described in the talib library documentation as: AROON(Records[High,Low],Time Period = 14) = [Array(outAroonDown),Array(outAroonUp)]

talib.AROONOSC

The talib.AROONOSC() function is used to calculate the Aroon Oscillator.

The return value of the talib.AROONOSC() function is: a one-dimensional array. array

talib.AROONOSC(inPriceHL) talib.AROONOSC(inPriceHL, optInTimePeriod)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.AROONOSC(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.AROONOSC(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.AROONOSC(records);
    Log(ret);
}

The AROONOSC() function is described in the talib library documentation as: AROONOSC(Records[High,Low],Time Period = 14) = Array(outReal)

talib.BOP

The talib.BOP() function is used to calculate the Balance Of Power.

The return value of the talib.BOP() function is a one-dimensional array. array

talib.BOP(inPriceOHLC)

The inPriceOHLC parameter is used to specify the K-line data. inPriceOHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.BOP(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.BOP(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.BOP(records);
    Log(ret);
}

The BOP() function is described in the talib library documentation as: BOP(Records[Open,High,Low,Close]) = Array(outReal)

talib.CCI

The talib.CCI() function is used to calculate the Commodity Channel Index (homeopathic indicator).

The return value of the talib.CCI() function is a one-dimensional array. array

talib.CCI(inPriceHLC) talib.CCI(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CCI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CCI(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CCI(records);
    Log(ret);
}

The CCI() function is described in the talib library documentation as: CCI(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.CMO

The talib.CMO() function is used to calculate the Chande Momentum Oscillator (CMO).

The return value of the talib.CMO() function is: a one-dimensional array. array

talib.CMO(inReal) talib.CMO(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.CMO(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.CMO(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.CMO(records);
    Log(ret);
}

The CMO() function is described in the talib library documentation as: CMO(Records[Close],Time Period = 14) = Array(outReal)

talib.DX

The talib.DX() function is used to calculate the Directional Movement Index.

The return value of the talib.DX() function is: a one-dimensional array. array

talib.DX(inPriceHLC) talib.DX(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.DX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.DX(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.DX(records);
    Log(ret);
}

The DX() function is described in the talib library documentation as: DX(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.MACD

The talib.MACD() function is used to calculate Moving Average Convergence/Divergence (exponentially smoothed moving average).

The return value of the talib.MACD() function is: a two-dimensional array. array

talib.MACD(inReal) talib.MACD(inReal, optInFastPeriod) talib.MACD(inReal, optInFastPeriod, optInSlowPeriod) talib.MACD(inReal, optInFastPeriod, optInSlowPeriod, optInSignalPeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastPeriod parameter is used to set the fast period, the default value is 12. optInFastPeriod false number The optInSlowPeriod parameter is used to set the slow period, the default value is 26. optInSlowPeriod false number The optInSignalPeriod parameter is used to set the signal period, the default value is 9. optInSignalPeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MACD(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MACD(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MACD(records);
    Log(ret);
}

The MACD() function is described in the talib library documentation as: MACD(Records[Close],Fast Period = 12,Slow Period = 26,Signal Period = 9) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]

talib.MACDEXT

The talib.MACDEXT() function is used to calculate MACD with controllable MA type.

The return value of the talib.MACDEXT() function is a two-dimensional array. array

talib.MACDEXT(inReal) talib.MACDEXT(inReal, optInFastPeriod) talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType) talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod) talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType) talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType, optInSignalPeriod) talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType, optInSignalPeriod, optInSignalMAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastPeriod parameter is used to set the fast period, the default value is 12. optInFastPeriod false number The optInFastMAType parameter is used to set the fast average type, the default value is 0. optInFastMAType false number The optInSlowPeriod parameter is used to set the slow period, the default value is 26. optInSlowPeriod false number The optInSlowMAType parameter is used to set the slow mean type, the default value is 0. optInSlowMAType false number The optInSignalPeriod parameter is used to set the signal period, the default value is 9. optInSignalPeriod false number The optInSignalMAType parameter is used to set the signal mean type, the default value is 0. optInSignalMAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MACDEXT(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MACDEXT(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MACDEXT(records);
    Log(ret);
}

The MACDEXT() function is described in the talib library documentation as: MACDEXT(Records[Close],Fast Period = 12,Fast MA = 0,Slow Period = 26,Slow MA = 0,Signal Period = 9,Signal MA = 0) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]

talib.MACDFIX

The talib.MACDFIX() function is used to calculate Moving Average Convergence/Divergence Fix 12/26.

The return value of the talib.MACDFIX() function is a two-dimensional array. array

talib.MACDFIX(inReal) talib.MACDFIX(inReal, optInSignalPeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInSignalPeriod parameter is used to set the signal period, the default value is 9. optInSignalPeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MACDFIX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MACDFIX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MACDFIX(records);
    Log(ret);
}

The MACDFIX() function is described in the talib library documentation as: MACDFIX(Records[Close],Signal Period = 9) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]

talib.MFI

The talib.MFI() function is used to calculate the Money Flow Index.

The return value of the talib.MFI() function is a one-dimensional array. array

talib.MFI(inPriceHLCV) talib.MFI(inPriceHLCV, optInTimePeriod)

The inPriceHLCV parameter is used to specify the K-line data. inPriceHLCV true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MFI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MFI(records.High, records.Low, records.Close, records.Volume)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MFI(records);
    Log(ret);
}

The MFI() function is described in the talib library documentation as: MFI(Records[High,Low,Close,Volume],Time Period = 14) = Array(outReal)

talib.MINUS_DI

The talib.MINUS_DI() function is used to calculate the Minus Directional Indicator (negative indicator).

The return value of the talib.MINUS_DI() function is a one-dimensional array. array

talib.MINUS_DI(inPriceHLC) talib.MINUS_DI(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MINUS_DI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MINUS_DI(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MINUS_DI(records);
    Log(ret);
}

The MINUS_DI() function is described in the talib library documentation as: MINUS_DI(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.MINUS_DM

The talib.MINUS_DM() function is used to calculate the Minus Directional Movement (negative motion).

The return value of the talib.MINUS_DM() function is a one-dimensional array. array

talib.MINUS_DM(inPriceHL) talib.MINUS_DM(inPriceHL, optInTimePeriod)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MINUS_DM(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MINUS_DM(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MINUS_DM(records);
    Log(ret);
}

The MINUS_DM() function is described in the talib library documentation as: MINUS_DM(Records[High,Low],Time Period = 14) = Array(outReal)

talib.MOM

The talib.MOM() function is used to calculate Momentum.

The return value of the talib.MOM() function is a one-dimensional array. array

talib.MOM(inReal) talib.MOM(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 10. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MOM(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MOM(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MOM(records);
    Log(ret);
}

The MOM() function is described in the talib library documentation as: MOM(Records[Close],Time Period = 10) = Array(outReal)

talib.PLUS_DI

The talib.PLUS_DI() function is used to calculate the Plus Directional Indicator.

The return value of the talib.PLUS_DI() function is: a one-dimensional array. array

talib.PLUS_DI(inPriceHLC) talib.PLUS_DI(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.PLUS_DI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.PLUS_DI(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.PLUS_DI(records);
    Log(ret);
}

The PLUS_DI() function is described in the talib library documentation as: PLUS_DI(Records[High,Low,Close],Time Period = 14) = Array(outReal)

talib.PLUS_DM

The talib.PLUS_DM() function is used to calculate Plus Directional Movement.

The return value of the talib.PLUS_DM() function is a one-dimensional array. array

talib.PLUS_DM(inPriceHL) talib.PLUS_DM(inPriceHL, optInTimePeriod)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.PLUS_DM(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.PLUS_DM(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.PLUS_DM(records);
    Log(ret);
}

The PLUS_DM() function is described in the talib library documentation as: PLUS_DM(Records[High,Low],Time Period = 14) = Array(outReal)

talib.PPO

The talib.PPO() function is used to calculate the Percentage Price Oscillator.

The return value of the talib.PPO() function is a one-dimensional array. array

talib.PPO(inReal) talib.PPO(inReal, optInFastPeriod) talib.PPO(inReal, optInFastPeriod, optInSlowPeriod) talib.PPO(inReal, optInFastPeriod, optInSlowPeriod, optInMAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInFastPeriod parameter is used to set the fast period, the default value is 12. optInFastPeriod false number The optInSlowPeriod parameter is used to set the slow period, the default value is 26. optInSlowPeriod false number The optInMAType parameter is used to set the mean type, the default value is 0. optInMAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.PPO(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.PPO(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.PPO(records);
    Log(ret);
}

The PPO() function is described in the talib library documentation as: PPO(Records[Close],Fast Period = 12,Slow Period = 26,MA Type = 0) = Array(outReal)

talib.ROC

The talib.ROC() function is used to calculate Rate of change : ((price/prevPrice)-1)*100 (rate of change indicator).

The return value of the talib.ROC() function is a one-dimensional array. array

talib.ROC(inReal) talib.ROC(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 10. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ROC(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ROC(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ROC(records);
    Log(ret);
}

The ROC() function is described in the talib library documentation as: ROC(Records[Close],Time Period = 10) = Array(outReal)

talib.ROCP

The talib.ROCP() function is used to calculate Rate of change Percentage: (price-prevPrice)/prevPrice (rate of price change).

The return value of the talib.ROCP() function is: a one-dimensional array. array

talib.ROCP(inReal) talib.ROCP(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 10. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ROCP(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ROCP(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ROCP(records);
    Log(ret);
}

The ROCP() function is described in the talib library documentation as: ROCP(Records[Close],Time Period = 10) = Array(outReal)

talib.ROCR

The talib.ROCR() function is used to calculate the Rate of change ratio: (price/prevPrice) (price change ratio).

The return value of the talib.ROCR() function is a one-dimensional array. array

talib.ROCR(inReal) talib.ROCR(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 10. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ROCR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ROCR(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ROCR(records);
    Log(ret);
}

The ROCR() function is described in the talib library documentation as: ROCR(Records[Close],Time Period = 10) = Array(outReal)

talib.ROCR100

The talib.ROCR100() function is used to calculate Rate of change ratio 100 scale: (price/prevPrice)*100 (price change ratio).

The return value of the talib.ROCR100() function is: a one-dimensional array. array

talib.ROCR100(inReal) talib.ROCR100(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 10. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ROCR100(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ROCR100(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ROCR100(records);
    Log(ret);
}

The ROCR100() function is described in the talib library documentation as: ROCR100(Records[Close],Time Period = 10) = Array(outReal)

talib.RSI

The talib.RSI() function is used to calculate the Relative Strength Index.

The return value of the talib.RSI() function is a one-dimensional array. array

talib.RSI(inReal) talib.RSI(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.RSI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.RSI(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.RSI(records);
    Log(ret);
}

The RSI() function is described in the talib library documentation as: RSI(Records[Close],Time Period = 14) = Array(outReal)

talib.STOCH

The talib.STOCH() function is used to calculate the Stochastic (STOCH indicator).

The return value of the talib.STOCH() function is a two-dimensional array. array

talib.STOCH(inPriceHLC) talib.STOCH(inPriceHLC, optInFastK_Period) talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period) talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType) talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType, optInSlowD_Period) talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType, optInSlowD_Period, optInSlowD_MAType)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInFastK_Period parameter is used to set the Fast-K period, the default value is 5. optInFastK_Period false number The optInSlowK_Period parameter is used to set the Slow-K period, the default value is 3. optInSlowK_Period false number The optInSlowK_MAType parameter is used to set the Slow-K average type, the default value is 0. optInSlowK_MAType false number The optInSlowD_Period parameter is used to set the Slow-D period, the default value is 3. optInSlowD_Period false number The optInSlowD_MAType parameter is used to set the Slow-D average type, the default value is 0. optInSlowD_MAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.STOCH(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.STOCH(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.STOCH(records);
    Log(ret);
}

The STOCH() function is described in the talib library documentation as: STOCH(Records[High,Low,Close],Fast-K Period = 5,Slow-K Period = 3,Slow-K MA = 0,Slow-D Period = 3,Slow-D MA = 0) = [Array(outSlowK),Array(outSlowD)]

talib.STOCHF

The talib.STOCHF() function is used to calculate the Stochastic Fast (fast STOCH indicator).

The return value of the talib.STOCHF() function is a two-dimensional array. array

talib.STOCHF(inPriceHLC) talib.STOCHF(inPriceHLC, optInFastK_Period) talib.STOCHF(inPriceHLC, optInFastK_Period, optInFastD_Period) talib.STOCHF(inPriceHLC, optInFastK_Period, optInFastD_Period, optInFastD_MAType)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInFastK_Period parameter is used to set the Fast-K period, the default value is 5. optInFastK_Period false number The optInFastD_Period parameter is used to set the Fast-D period, the default value is 3. optInFastD_Period false number The optInFastD_MAType parameter is used to set the Fast-D average type, the default value is 0. optInFastD_MAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.STOCHF(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.STOCHF(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.STOCHF(records);
    Log(ret);
}

The STOCHF() function is described in the talib library documentation as: STOCHF(Records[High,Low,Close],Fast-K Period = 5,Fast-D Period = 3,Fast-D MA = 0) = [Array(outFastK),Array(outFastD)]

talib.STOCHRSI

The talib.STOCHRSI() function is used to calculate the Stochastic Relative Strength Index.

The return value of the talib.STOCHRSI() function is: a two-dimensional array. array

talib.STOCHRSI(inReal) talib.STOCHRSI(inReal, optInTimePeriod) talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period) talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period, optInFastD_Period) talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period, optInFastD_Period, optInFastD_MAType)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number The optInFastK_Period parameter is used to set the Fast-K period, the default value is 5. optInFastK_Period false number The optInFastD_Period parameter is used to set the Fast-D period, the default value is 3. optInFastD_Period false number The optInFastD_MAType parameter is used to set the Fast-D average type, the default value is 0. optInFastD_MAType false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.STOCHRSI(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.STOCHRSI(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.STOCHRSI(records);
    Log(ret);
}

The STOCHRSI() function is described in the talib library documentation as: STOCHRSI(Records[Close],Time Period = 14,Fast-K Period = 5,Fast-D Period = 3,Fast-D MA = 0) = [Array(outFastK),Array(outFastD)]

talib.TRIX

The talib.TRIX() function is used to calculate the 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA.

The return value of the talib.TRIX() function is: a one-dimensional array. array

talib.TRIX(inReal) talib.TRIX(inReal, optInTimePeriod)

The inReal parameter is used to specify the K-line data. inReal true {@struct/Record Record} structure arrays, numeric arrays The optInTimePeriod parameter is used to set the period, the default value is 30. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TRIX(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TRIX(records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TRIX(records);
    Log(ret);
}

The TRIX() function is described in the talib library documentation as: TRIX(Records[Close],Time Period = 30) = Array(outReal)

talib.ULTOSC

The talib.ULTOSC() function is used to calculate the Ultimate Oscillator.

The return value of the talib.ULTOSC() function is a one-dimensional array. array

talib.ULTOSC(inPriceHLC) talib.ULTOSC(inPriceHLC, optInTimePeriod1) talib.ULTOSC(inPriceHLC, optInTimePeriod1, optInTimePeriod2) talib.ULTOSC(inPriceHLC, optInTimePeriod1, optInTimePeriod2, optInTimePeriod3)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod1 parameter is used to set the first period, the default value is 7. optInTimePeriod1 false number The optInTimePeriod2 parameter is used to set the second period, the default value is 14. optInTimePeriod2 false number The optInTimePeriod3 parameter is used to set the third period, the default value is 28. optInTimePeriod3 false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.ULTOSC(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.ULTOSC(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.ULTOSC(records);
    Log(ret);
}

The ULTOSC() function is described in the talib library documentation as: ULTOSC(Records[High,Low,Close],First Period = 7,Second Period = 14,Third Period = 28) = Array(outReal)

talib.WILLR

The talib.WILLR() function is used to calculate Williams’ %R.

The return value of the talib.WILLR() function is: a one-dimensional array. array

talib.WILLR(inPriceHLC) talib.WILLR(inPriceHLC, optInTimePeriod)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array The optInTimePeriod parameter is used to set the period, the default value is 14. optInTimePeriod false number

function main() {
    var records = exchange.GetRecords()
    var ret = talib.WILLR(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.WILLR(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.WILLR(records);
    Log(ret);
}```

The ```WILLR()``` function is described in the talib library documentation as: ```WILLR(Records[High,Low,Close],Time Period = 14) = Array(outReal)```

### talib.AVGPRICE

The ```talib.AVGPRICE()``` function is used to calculate **Average Price**.

The return value of the ```talib.AVGPRICE()``` function is a one-dimensional array.
array

talib.AVGPRICE(inPriceOHLC)

The ```inPriceOHLC``` parameter is used to specify the K-line data.
inPriceOHLC
true
{@struct/Record Record} structure array

```javascript
function main() {
    var records = exchange.GetRecords()
    var ret = talib.AVGPRICE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.AVGPRICE(records.Open, records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.AVGPRICE(records);
    Log(ret);
}

The AVGPRICE() function is described in the talib library documentation as: AVGPRICE(Records[Open,High,Low,Close]) = Array(outReal)

talib.MEDPRICE

The talib.MEDPRICE() function is used to calculate the Median Price.

The return value of the talib.MEDPRICE() function is a one-dimensional array. array

talib.MEDPRICE(inPriceHL)

The inPriceHL parameter is used to specify the K-line data. inPriceHL true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.MEDPRICE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.MEDPRICE(records.High, records.Low)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.MEDPRICE(records);
    Log(ret);
}

The MEDPRICE() function is described in the talib library documentation as: MEDPRICE(Records[High,Low]) = Array(outReal)

talib.TYPPRICE

The talib.TYPPRICE() function is used to calculate Typical Price.

The return value of the talib.TYPPRICE() function is a one-dimensional array. array

talib.TYPPRICE(inPriceHLC)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.TYPPRICE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.TYPPRICE(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.TYPPRICE(records);
    Log(ret);
}

The TYPPRICE() function is described in the talib library documentation as: TYPPRICE(Records[High,Low,Close]) = Array(outReal)

talib.WCLPRICE

The talib.WCLPRICE() function is used to calculate the Weighted Close Price.

The return value of the talib.WCLPRICE() function is a one-dimensional array. array

talib.WCLPRICE(inPriceHLC)

The inPriceHLC parameter is used to specify the K-line data. inPriceHLC true {@struct/Record Record} structure array

function main() {
    var records = exchange.GetRecords()
    var ret = talib.WCLPRICE(records)
    Log(ret)
}
import talib
def main():
    records = exchange.GetRecords()
    ret = talib.WCLPRICE(records.High, records.Low, records.Close)
    Log(ret)
void main() {
    auto records = exchange.GetRecords();
    auto ret = talib.WCLPRICE(records);
    Log(ret);
}

The WCLPRICE() function is described in the talib library documentation as: WCLPRICE(Records[High,Low,Close]) = Array(outReal)

Structures