Inventors quantify the API documentation

Author: The Little Dream, Created: 2017-11-27 09:05:08, Updated: 2023-07-12 16:47:31

void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
  • MailAsynchronous version of the functionMail_GoThe function: Use andexchange.GoThe function is similar.

    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)
    }
    
    # 不支持
    
    // 不支持
    

Please note: The Ali Cloud server may block some ports, causing e-mail to be unable to be sent. If you need to change the port, you can add the port number directly in the first parameter, for example:smtp.qq.com:587, the port test is available. In case of error:unencryped connectionIt needs to be modified.Mailof the functionsmtpServerThe format of the parameters is:ssl://xxx.com:xxxFor example, the QQ e-mailSMTPThis is the most common way to use SSL:ssl://smtp.qq.com:465Orsmtp://xxx.com:xxx

SetErrorFilter(…)

SetErrorFilter(RegEx), Filter error logs↑ Parameter value: String type↑ An error log matched by this regular expression will not be uploaded to the log system, and multiple filtering conditions can be invoked (the filtered logs are not written to the database file corresponding to the disk ID in the host directory, preventing frequent error messages from causing database file expansion).

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 an interface error message:

function main() {
    // 随便查询一个不存在的订单,id为123,故意让接口报错
    var order = exchange.GetOrder("123")
    Log(order)
    // 过滤http502错误、GetOrder接口错误,设置错误过滤之后,第二次调用GetOrder不再报错
    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);
}

GetPid()

GetPid(), which returns the disk process ID.

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

GetLastError()

GetLastError(), to get the most recent error information. It is generally not needed because the program automatically uploads the error information to the log system.GetLastError()The function will then clear the error cache, and the next call will not return the error message from the last recording.

function main(){
    // 因为不存在编号为123的订单,所以会出错
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // 订单ID类型:TId,所以不能传入字符串,我们下一个不符合交易所规范的订单来触发
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

GetCommand()

GetCommand(), retrieves the interactive command string ((utf-8)); retrieves the command from the policy interactive interface and clears the cache, returns the empty string without the command; returns the command format as按钮名称:参数If the interactive control has no parameters (e.g. a button control without an input box), the command is the button name.

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

The underlying system has a queue structure that records interaction commands whenGetCommand()When a function is called, it takes the first interaction command in the queue (returns an empty string if there is no interaction command).

Examples of use of interactive controls, policy editor interface setting interactive controls.

img

The strategy is to design interactive code:

function main() {
    while (true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)    
            var arr = cmd.split(":")
            if (arr[0] == "buy") {
                Log("买入,该控件不带数量")
            } else if (arr[0] == "sell") {
                Log("卖出,该控件带数量:", arr[1])
            } else {
                Log("其它控件触发:", arr)
            }
        }
        Sleep(1000)
    } 
}
def main():
    while True:
        LogStatus(_D())
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
            arr = cmd.split(":")
            if arr[0] == "buy":
                Log("买入,该控件不带数量")
            elif arr[0] == "sell":
                Log("卖出,该控件带数量:", arr[1])
            else:
                Log("其它控件触发:", 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("买入,该控件不带数量");
            } else if (arr[0] == "sell") {
                Log("卖出,该控件带数量:", arr[1]);
            } else {
                Log("其它控件触发:", arr);
            }
        }
        Sleep(1000);
    }
}

GetMeta()

GetMeta()The function returns the policy registration code that was written when it was generated.MetaThe function returns a value of the string type. Application scenarios, such as strategies that require funding restrictions for different tenants. Note: When generating the registration codeMetaThis function is only applicable to the physical disk and requires the use of the latest host. If the policy registry code is not set to metadata when generatedGetMeta()Returns the empty value.

Use of scene demonstrations

function main() {
    // 策略允许的计价币最大资产数值
    var maxBaseCurrency = null
    
    // 获取创建注册码时的元数据
    var level = GetMeta()
    
    // 检测Meta对应的条件
    if (level == "level1") {
        // -1为不限制
        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()
        
        // 检测资产数值
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // 停止执行策略交易逻辑
            LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
            continue
        }
        
        // 其它交易逻辑
        
        // 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\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, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
            continue        
        
        # 其它交易逻辑
        
        # 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\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) {
            // 停止执行策略交易逻辑
            LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!");
            continue;
        }
        
        // 其它交易逻辑
        
        // 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker);
    }
}

Dial(…)

Dial(Address, Timeout)The originalSocketAccess and supporttcpudptlsunixProtocol. Parameter value isAddressFor the string type,TimeOutFor the type of value, the unit of value is seconds, if overtimeDial(...)The function returns a null value.

AddressDetails of the parameters:

Parameters
Set upDialParameters of the function The usual address is:wss://ws.okx.com:8443/ws/v5/publicLater|Symbol separation, if there is a string of digits|The characters are in||Use as a separation symbol.&Character connections. For example, ss5 proxy and compression parameters are set together:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
When used with the ws protocol, parameters related to data compression are:compress=参数值 compress is a compression mode, compress parameters, optionalgzip_rawgzipFor example, if the gzip method is not standard gzip, you can use the extension method:gzip_rawI mean, in the separator.|Add settings latercompress=gzip_raw, with&The symbol and the next mode parameter are separated.
When used with the ws protocol, parameters related to data compression are:mode=参数值 mode to mode, optionaldualsendrecvThere are three types.dualFor two-way, send compression data and receive compression data.sendThis is the most common way to send compressed data.recvTo receive the compression data, decompress locally.
The following parameters are used to set up the socks5 agent:proxy=参数值 The proxy is set for the ss5 proxy, and the parameter value format is:socks5://name:pwd@192.168.0.1:1080,name is the username of the ss5 server, pwd is the login password of the ss5 server, and 1080 is the port of the ss5 service.
When using the ws protocol, set the parameters for the underlying auto-reconnect:reconnect=参数值 reconnect is set to reconnect,reconnect=trueFor enabling re-connection. Default not to re-connect when not set.
When using the ws protocol, set the parameters for the underlying auto-reconnect:interval=参数值 interval is the time interval for retesting, in milliseconds,interval=10000For a 10 second retry interval, the default is not set to 1 second, i.e.interval=1000
When using the ws protocol, set the parameters for the underlying auto-reconnect:payload=参数值 The subscription messages that need to be sent when the payload is reconnected to the ws, for example:payload=okok
function main(){
    // Dial支持tcp://,udp://,tls://,unix://协议,可加一个参数指定超时的秒数
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // write可再跟一个数字参数指定超时,write返回成功发送的字节数
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while (true) {
            // read可再跟一个数字参数指定超时,单位:毫秒。返回null指出错或者超时或者socket已经关闭
            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();
    }
}

readThe function supports the following parameters:

  • When no parameters are passed, block until a message is returned. For example:ws.read()
  • When inputting the parameter, the unit is the millisecond, specifying the message waiting time over time. For example:ws.read(2000)Specify a delay time of two seconds (~2000 milliseconds).
  • The following two parameters are only true.websocketEffective: Passing the parameters-1The function returns immediately regardless of whether there is a message, for example:ws.read(-1)I'm not sure. Passing the parameters-2This means that the function returns immediately, regardless of whether there is no message, but only returns the most recent message, and the message in the buffer is discarded; for example,ws.read(-2)

read()The function buffer area describes: Ws protocol pushes the data if it is in the policyread()Too long a time interval between function calls can lead to data accumulation. These data are stored in a buffer zone, with a buffer zone data structure of queues, up to a maximum of 2000; after 2000 the latest data is entered into the buffer zone, and the oldest data is deleted.

The scene.readParameters of the function Parameterless Parameters are: -1 Parameters are: -2 Parameters: 2000, units are milliseconds
Buffer zone data is available Returns the oldest data immediately Returns the oldest data immediately Immediately return to the latest data Returns the oldest data immediately
No data for buffer zone Block until data is available Returns the empty value immediately Returns the empty value immediately Wait 2000 milliseconds, no data returns blank, some data returns
When the ws connection is disconnected or the bottom is reconnected The read ((() function returns an empty string, i.e.::"",write (()) function returns 0, detected in this case. The close ((() function can be used to close the connection, if the auto-reconnect is set, it does not need to be closed, and the system bottom will automatically reconnect.
  • Support for the wss ((WebSocket) protocol Binance's websocket market interface can be accessed at:

    function main() {
        LogStatus("正在连接...")
        // 访问币安的websocket接口
        var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if (!client) {
            Log("连接失败, 程序退出")
            return
        }
        
        while (true) {
            // read只返回调用read之后获取的数据
            var buf = client.read()      
            if (!buf) {
                break
            }
            var table = {
                type: 'table',
                title: '行情图表',
                cols: ['币种', '最高', '最低', '买一', '卖一', '最后成交价', '成交量', '更新时间'],
                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("正在连接...")
        client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if not client:
            Log("连接失败, 程序退出")
            return 
        
        while True:
            buf = client.read()
            if not buf:
                break
            table = {
                "type" : "table", 
                "title" : "行情图表", 
                "cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"], 
                "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("正在连接...");
        auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
        if(!client.Valid) {
            Log("连接失败, 程序退出");
            return;
        }
        
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            json table = R"({
                "type" : "table", 
                "title" : "行情图表", 
                "cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"], 
                "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();
    }
    

    Access the websocket market interface of OKX:

    var ws = null 
    function main(){
        var param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        // 在调用Dial函数时,指定reconnect=true即设置为重连模式,指定payload即为重连时发送的消息。在websocket连接断开后,会自动重连,自动发送消息
        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("发送 :ping", "#FF0000")
                }
                LogStatus("当前时间:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("退出")
    }
    
    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("发送:ping", "#FF0000")
                LogStatus("当前时间:", _D())
                Sleep(1000)  
    
    def onexit():
        ws.close()
        Log("退出")
    
    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("发送:ping", "#FF0000");
                }
                LogStatus("当前时间:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        objWS.close();
        Log("退出");
    }
    

    The websocket market interface for accessing the tokens:

    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)
                // 响应心跳包操作
                try {
                    var jsonRet = JSON.parse(ret)
                    if(typeof(jsonRet.ping) == "number") {
                        var strPong = JSON.stringify({"pong" : jsonRet.ping})
                        ws.write(strPong)
                        Log("响应ping,发送pong:", strPong, "#FF0000")
                    }
                } catch(e) {
                    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                }
                
                LogStatus("当前时间:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("执行ws.close()函数")
    }
    
    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)              
                # 响应心跳包操作
                try:
                    jsonRet = json.loads(ret)
                    if "ping" in jsonRet and type(jsonRet["ping"]) == int:
                        strPong = json.dumps({"pong" : jsonRet["ping"]})
                        ws.write(strPong)
                        Log("响应ping,发送pong:", strPong, "#FF0000")
                except Exception as e:
                    Log("e:", e)
                    
                LogStatus("当前时间:", _D())
                Sleep(1000)
        
    def onexit():
        ws.close()
        Log("执行ws.close()函数")  
    
    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);              
                // 响应心跳包操作
                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("响应ping,发送pong:", strPong, "#FF0000");
                    }
                } catch(exception &e) 
                {
                    Log("e:", e.what());
                }
                
                LogStatus("当前时间:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        // ws.close();
        Log("执行ws.close()函数");
    }
    

    Access the websocket authentication interface of OKX:

    function getLogin(pAccessKey, pSecretKey, pPassphrase) {
        // 签名函数,用于登录
        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)
            }]
        }    
        return login
    }    
    
    var client_private = null 
    function main() {
        // 因为read函数使用了超时设置,过滤超时的报错,否则会有冗余错误输出
        SetErrorFilter("timeout")
        
        // 持仓频道订阅信息
        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)  // 登录时,不能立即订阅私有频道,需要等待服务器反应
        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)
                }
                
                // 检测断开,重连
                if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
                    Log("检测到断开,关闭连接,重连")
                    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))
                }
                
                // 发送心跳包
                var nowPingTS = new Date().getTime()
                if (nowPingTS - lastPingTS > 10 * 1000) {
                    client_private.write("ping")
                    lastPingTS = nowPingTS
                }            
            }        
        }
    }    
    
    function onexit() {    
        var ret = client_private.close()
        Log("关闭连接!", 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("检测到断开,关闭连接,重连")
                    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("关闭连接!", 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("检测到断开,关闭连接,重连");
                        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("退出");
    }
    

HttpQuery(…)

HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader), network URL access. == Parameter value: all for string type ==

Please note:

  • HttpQuery(...)Function only supportedJavaScriptThe language.
  • PythonLanguage can be usedurllibIn the meantime, I'm going to send you an http request.

HttpQuery(...)It is mainly used to access interfaces that do not require a signature, such as public interfaces such as market information.

An example of an API interface that does not require a signature to access OKX, returning a value ofJSONThe strings.JavaScriptThe language strategies can be usedJSON.parse()Functional analysis is also used.

function main(){
    // 一个GET访问不带参数的例子
    var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
    Log(info)
    // 一个GET访问带参数的例子
    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不支持Python,可以使用urllib/urllib2库代替
    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);
}

Returns the contents of a URL if the second parameterPostDataFor the stringa=1&b=2&c=abcIt's a form.POSTHow to submit. Other examplesPUTIt is not possible to change the language.PostDataThe parameter is{method:'PUT', data:'a=1&b=2&c=abc'}PostDataThe parameters can also beJSONString of characters.

CookiesThe form of this parameter is:a=10; b=20, each parameter is decimated;I'm not going to tell you.HeadersThe form of this parameter is:User-Agent: Mobile\nContent-Type: text/htmlThe parameters are replaced with symbols.\nI'm not going to tell you.

The second parameterPostDataYou can customize methods such as:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})Please note:HttpQueryThe function sets the timeout, which can be used in{method:'PUT', data:'a=1&b=2&c=abc'}JoinedtimeoutAttributes (default 60 seconds)

Set the delay by 1 second:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})

DeliveredCookieString requires a third argument, but notPOSTPlease set the second parameter to null. The function returns a fixed string because the URL cannot be simulated.Dummy DataThe interface can be used to send text messages or interact with other API interfaces.

GETExamples of method calls:HttpQuery("http://www.baidu.com")POSTExamples of method calls:HttpQuery("http://www.163.com", "a=1&b=2&c=abc")

Going backHeaderHere are some examples:

HttpQuery("http://www.baidu.com", null, "a=10; b=20", "User-Agent: Mobile\nContent-Type: text/html", true)  // will return {Header: HTTP Header, Body: HTML}
  • HttpQueryThe function uses the following proxy setting:

    function main() {
        // 本次设置代理并发送http请求,无用户名,无密码,此次http请求会通过代理发送
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
    
        // 本次设置代理并发送http请求,输入用户名和密码,仅HttpQuery当前调用生效,之后再次调用HttpQuery("http://www.baidu.com")这样不会使用代理
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
    }
    
    # HttpQuery不支持Python,可以使用Python的urllib2库
    
    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/");
    }
    
  • HttpQueryAsynchronous version of the functionHttpQuery_GoI'm not sure. Use andexchange.GoThe functions are similar, e.g. asynchronous access to the exchange's public interface to obtain aggregated market data.

    function main() {
        // 创建第一个异步线程
        var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
        // 创建第二个异步线程
        var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
        
        // 获取第一个异步线程调用的返回值
        var tickers1 = r1.wait()
        // 获取第二个异步线程调用的返回值
        var tickers2 = r2.wait()
        
        // 打印结果
        Log("tickers1:", tickers1)
        Log("tickers2:", tickers2)
    }
    
    # 不支持
    
    // 不支持
    
  • Use in retesting systemsHttpQuery(...)The function: Can be used in retesting systemsHttpQuery(...)Send request ((support only)GETrequest) to obtain data. Limit retrieval time to 20 different URL visits, andHttpQuery(...)Access caches data, the same URL the second time it is accessedHttpQuery(...)The function returns cached data (no more actual network requests).

    We can run a service program on a server or a device to respond to a policy program.HttpQuery(...)The Go language service program used to test the request was as follows:

    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","open","high","low","close","vol"},
                "data" : []interface{}{
                    []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                    []int64{1564316100000,9495160,9495160,9474260,9489460,338},
                },
            }
            b, _ := json.Marshal(ret)
            w.Write(b)
        }()
    }
    
    func main () {
        fmt.Println("listen http://localhost:9090")
        http.HandleFunc("/data", Handle)
        http.ListenAndServe(":9090", nil)
    }
    

    Used for strategy retrospectionHttpQuery(...)Request to send the function:

    function main() {
        // 可以写自己运行服务程序所在设备的IP地址
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    
    # HttpQuery不支持Python,可以使用Python的urllib2库
    
    void main() {
        // 可以写自己运行服务程序所在设备的IP地址
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    

    img

  • Supports transcoding of response data to requests, supporting common coding. SpecifyPostDataParameters are:{method: "GET",charset:"GB18030"}The data transfer code (GB18030) can be implemented.

Encode(…)

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)The function encodes data based on the input parameters. Returns value: String type.

ParametersalgoThe algorithms used for coding are: *raw * (not using algorithms), *sign *, *sign Tx *, *md4 *, *md5 *, *sha256 *, *sha512 *, *sha1 *, *keccak256 *, *sha3.224 *, *sha3.256 *, *sha3.384 *, *sha3.512 *, *sha3.keccak256 *, *sha3.keccak512 *, *sha512.384 *, *sha512.256 *, *sha512.224 *, *ripmd160 *, *blake2b.256 *, *blake2b.512 *, *blake2s.128 *, *blake2s.256 *.dataThe data to be processed.inputFormat/outputFormat/keyFormatParameters supportedrawhexbase64stringThe code is written in Arabic. What ifkeyFormatIf it's not empty, use parameters.keyEncrypt (HMAC) or use the defaultkeyThe parametersalgoSet to"sign"Or"signTx"When parameters are neededkey

function main(){
    Log(Encode("md5", "raw", "hex", "hello"))
    Log(Encode("sha512", "raw", "base64", "hello"))
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"))

    Log(Encode("raw", "string", "hex", "example"))          // 6578616d706c65
    Log(Encode("raw", "hex", "string", "6578616d706c65"))   // example
}
def main():
    Log(Encode("md5", "raw", "hex", "hello", "", ""))
    Log(Encode("sha512", "raw", "base64", "hello", "", ""))
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)", "", ""))

    Log(Encode("raw", "string", "hex", "example", "", ""))
    Log(Encode("raw", "hex", "string", "6578616d706c65", "", ""))
void main(){
    Log(Encode("md5", "raw", "hex", "hello"));
    Log(Encode("sha512", "raw", "base64", "hello"));
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"));
    
    Log(Encode("raw", "string", "hex", "example"));          // 6578616d706c65
    Log(Encode("raw", "hex", "string", "6578616d706c65"));   // example
}

ParametersalgoIt also supports:text.encoder.utf8text.decoder.utf8text.encoder.gbktext.decoder.gbk, to encode and decode strings.

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

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

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

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

UnixNano()

UnixNano()Returns a nanosecond timestamp. If a millisecond timestamp is required, the following code can be used:

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

Unix()

Unix(), returns the second-level timestamp.

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

GetOS()

GetOS()In this case, the server will return the information to the host's system.

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

On the Apple computerMac OSThe output of the host logs running on the operating system is:

GetOS:darwin/amd64

darwinThat is,Mac OSThe name of the system.

MD5(String)

MD5(String), parameter value: String type.

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

The log output:

MD5 5eb63bbbe01eeed093cb22bb8f5acdc3

DBExec(…)

DBExec(), Parameter value: can be a string, numeric value, boolean value, empty value, etc.; Return value: objects that contain SQLite statement execution results. The database interface functionDBExec()The SQLite database can be operated with input parameters. It supports adding, deleting, checking, modifying and so on.SQLiteSyntax. The system reserved tables in the real disk database:kvdbcfglogprofitchartPlease do not manipulate these tables. Note:DBExec()The function only supports the real disk.

  • Support for memory databases For theDBExecThe parameters of the function, ifsqlThe sentence is:Initially, it operates in the in-memory database, without writing files, faster. It is suitable for database operations that do not require persistent storage, such as:

    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)
        
        // 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
        
        // 查询数据
        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)
        
        # 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
        
        # 查询数据
        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);
        
        // 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
        
        // 查询数据
        Log(DBExec(":SELECT * FROM TEST_TABLE;"));
    }
    
  • Creating tables

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);
}
  • Adding, deleting, and modifying records in 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))
    
    // 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    // 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    // 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))    
    
    // 删除数据
    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))
    
    # 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    # 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    # 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))
    
    # 删除数据
    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));

    // 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
    
    // 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"));
    
    // 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000));
    
    // 删除数据
    Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110));
}

UUID()

UUID()Returns a 32-bit unique UUID, which only applies to the physical disk.

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

EventLoop(timeout)

EventLoop(timeout)In any casewebsocketRead orexchange.GoHttpQuery_GoLet the concurrent task be returned after completion.timeoutIf set to 0, wait for an event to occur before returning, if greater than 0 is set to wait for an event to occur, less than 0 immediately returns to the most recent event.nullThis is the first time I've seen this.EventType of event trigger. This function is only applicable to the disk.

First call in codeEventLoopThe mechanism for initializing the monitoring event only works if it starts for the first time after the event is recalled.EventLoopCalls, which will miss previous events. The underlying system encapsulates a queue structure that caches up to 500 event calls if no timely call is made during program execution.EventLoopRemoving it will lose 500 caches of event calls later.EventLoopCalling a function does not affect the system's underlyingwebsocketThe caching queue is not affected.exchange.GoFor example, the cache of concurrent functions still requires the use of their respective methods to extract data.EventLoopThe data that's been extracted won't be in the function until the function returns.EventLoopThe function produces a return event.

EventLoopThe primary function is to notify the policy layer, the system underlying the receipt of new network data.EventLoopWhen a function returns an event, all it needs to do is traverse all data sources.websocketIt's about connectivity.exchange.GoThe object created attempts to retrieve data.Links to libraries

In the main functionmain()In the middle of the call, listen to the events of the main thread.JavaScriptThe strategy of writing the language is to make it easy for people to understand it.__Thread()A thread created by a function can also be called into the thread's executable function to listen to the events of the current thread.

function main() {
    var routine_getTicker = exchange.Go("GetTicker")
    var routine_getDepth = exchange.Go("GetDepth")
    var routine_getTrades = exchange.Go("GetTrades")
    
    // Sleep(2000),如果这里使用Sleep语句,会导致之后的EventLoop函数错过之前的事件,因为等待了2秒,并发的函数

More

qq89520There's a problem with whether the C_function is going to try it all over again or only once.

haiwwhai_C ((function, args...) is this default 3s? Can I change the default to put _CDelay ((1000) directly before _C ((function, args...)?

lanchaiyeCluster: If you create 1000 robots simultaneously and without the stress, you can create multiple hosts to decentralize tasks. There are code examples for building clusters. How to build multiple hosts to decentralize tasks

wangyj1Log ((talib.help (('MACD')); can only be used in js, there is no talib.help attribute in python...

cjz140What's the difference between _C (function, args...) and sleep function, I think it all means waiting to try again.

3263243yHow to clear ErrorFilter after SetErrorFilter? without filtering error messages.

qq47898077Is there a way to use a third-party library?

qq47898077If you want to inherit a new class defined by an exchange object, what should the parent class fill in?

ethanwuDo you have any local debug tools?

penglihengWhat about exange.IO?

penglihengWhy is the sell function in gray, is the representation function no longer available?

penglihengWhy is the sell function in gray, is the representation function no longer available?

penglihengJS doesn't speak English, haha, I just want to ask if it supports ES6.

penglihengJS doesn't speak English, haha, I just want to ask if it supports ES6.

Don.How do you write the volume mean?

zjuturtleWhat will be the return if the exchange.Buy ((1000) fails to buy at market price?

The NinjaThe new font is beautiful.

hippoBitmex's testing network ((testnet.bitmex.com) also has an API interface, but currently the exchange can only select Bitmex's main station, and the API documentation address is https://testnet.bitmex.com/app/apiOverview How can you support?

cxjijinvar ret1 = exchanges[0].IO (("api", "future_estimated_price", "symbol=btc_usd"); Log (('ok futures estimated delivery price', ret1)); https://dn-filebox.qbox.me/d1ed268c1e75753c5d289447d279aa9d81e41b5f.png Why is it that when you call the functional interface of other exchanges, you write an error message?

allenfrostlineI was wondering what the difference is between realTicker and Ticker? Recently, a strategy for re-writing the utility has appeared simultaneously, but the former API does not seem to mention it.

visionsHello, as a Python developer, what do you think your API documentation is writing about? Some of the field function interfaces look weird, can you write a document like githubpage and readdocs?

allenfrostlineGetAccount: [EAPI:Rate limit exceeded] Want to know how to solve this?

zhjx2314Doesn't support StochRSI, can it be added soon?

yhfggIs the script on your own Ali Cloud server or a botvs cluster?

yhfggWhat version of python do you use?

fkyslyThe interpretation of GetFee should be that it returns a Fee structure string, minus one construct.

zkwapIs there a way to call talib using js?

yhfggRequest the python documentation

wmjbs123Can the background of the code for the strategy editor be black? White prickly eyes, writing code at night, easy nearsightedness

Don.How do I set up the summary in the WeChat push of the robot?

The number is crazy.Is it possible to add a transaction-level field to the order structure?

The little one.GetOrders: Returns all unfinished orders, returns an Order array structure, in China Bitcoin trading ETH, returns only the most recent 10 items, here is a function that returns all unfinished orders in China Bitcoin ETH, meaning that other platforms can return all with GetOrders, only this ghost Chinese Bitcoin returns 10 items,

yhfggThe mathematical functions that are needed for statistical probability theory, where do they come from?

jiebangWhat is the return value of the function $.Cross ((x, y)?

My mother-in-lawThis LogReset clears all logs, and can have a numeric parameter that specifies the number of records to be reserved How does this delete the most recent logs?

edwardgywThe CORRE function in talib doesn't seem to have been ported or missed?

The poor mountain of YangyangIt doesn't seem to have any indicator referencing features!

SmallHow do you translate the k-line time to the present time?

SmallHow to delete numbers in arrays, I'm using records.remove ((records[0])

snakeayuThe most commonly obtained is the hourly K line, how to call the ATR of the daily K line?

snakeayuThe most commonly obtained is the hourly K line, how to call the ATR of the daily K line?

57278863Learn how to get traditional futures priced and ordered, sorry, the roots are thin.

kirinThis is the case with traditional futures trading!

SmallZero, can you write an example of traditional futures trading?

SmallHow to print the holding status when holding multiple blanks at the same time, how to print my [object object], how to get the holding status of multiple and blank blanks, and GetTicker (((), how to get the week, next week, and quarter of the week, the price, the week, next week, and quarter in parentheses I write.

cxjijinIs it possible for a futures exchange to get a market with GetTicker (??), returning a market for that type of contract (??, next week...)?

Selling outWhat indicator can you add to the StochRSI?

momoxCancelOrder ((orderId) Cancel an order based on the order number, return true or false, ask true= The cell was successfully canceled, right?

momox_G(K, V) Can global dictionaries be stored This method saves global variables that can be used to share data between different policies?

flufy3dRising to Popularity

ZeroYou can reset the earnings log with LogProfitReset. The history on the earnings chart before is gone.

xcyCan you directly copy the EA?

sjironmanI feel like this platform is great, great, more interaction in the group.

SmallWhat language is this, is there any material to learn?

jxhbtcData error for a week, can't connect the robot, how to fix it

dyhhuThe index library TA, is it just a calculation of the closing price?

btcrobot hi, world

The Little DreamThe _C function will try again without thinking until it gets a successful result.

The Little DreamPython's talib library needs to be installed.https://www.botvs.com/bbs-topic/669 can be found in this post.

The Little DreamSleep is the number of milliseconds the program does nothing while waiting for the parameter to be set, and _C is the number of milliseconds the function has to re-call the parameter once.

The Little DreamWithout inheritance, JS directly wrapped in the object goes {name: "new object", old_exchange : exchange[0],...... }

The Little DreamLocal editor Remote sync plug-in, basically local editor Remote debugging.

The Little DreamYou can come to the QQ group, and it's easy to discuss.

The Little DreamIn the API documentation, gray means that the function does not have too many open explanations, it shows gray, blue represents more explanations, that's all.

The Little DreamES6 is currently not supported, ^^

The Little DreamCan you come to the group QQ, describe the problem, I'll answer ^^

The Little DreamIt will immediately return an error, and will not order (actually, it is to buy, not enough money!).

zjuturtleFor example, OKCoin, what will be the return if the amount purchased is more than the amount of RMB held?

The Little DreamI'm going to return an order number in OK futures to which exchange.

ZeroIt already supports switching transaction pairs at runtime, and requires downloading the latest host. Supports Bter/Poloniex Detailed API documentation The description of the transaction function bar below ((clear browser cache after refresh if not visible)

The Little DreamQQ me, I'll help you find the problem.

Professional breadwinnersI'm going to set the host's IP?

The Little DreamThis is the underlying link not established The server is not responding. Is the IP address set when the API KEY is requested?

Professional breadwinnersIt's embarrassing... the policies I could run changed to fail in the bit era, and GetAccount can't access GetAccount: Post http://api.btc38.com/v1/getMyBalance.php: read tcp 192.168.0.227:58596->211.149.148.144:80: wsarecv: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 2017-05-23 21:08:24 BitTorrent error GetAccount: timeout This is a list of all the different ways GetAccount is credited in the database. 2017-05-23 21:08:02 Bit Era Error GetAccount: timeout This is a list of all the different ways GetAccount is credited in the database. 2017-05-23 21:07:40 BitTorrent error GetAccount: timeout This is a list of all the different ways GetAccount is credited in the database. This article is part of our upcoming edition of The New York Times Best Seller list. Is it the IP whitelist problem???

The Little DreamThe exchange's servers did not respond, and the TCP protocol was not established for the three handshakes.

Professional breadwinnersA connection attempt failed because the connected party did not properly respond after a period of time, and the connection attempt failed because the connected party did not properly respond after a period of time.

The Little DreamHello! This is exchange.IO ((api, ApiName, Args) This function is not supported, see https://www.botvs.com/bbs-topic/812

Professional breadwinners A connection attempt failed because the connected party did not properly respond after a period of time,

Professional breadwinnersBitcoin Age is not supported?

The Little DreamThis is a list of all the different ways Dn-filebox.qbox.me/a709b30c6cc0a3565234b9e0c99b073f7ba8b454.png is credited in the database. I'm sure it will be okay.

The NinjaFor example, I want to do a full-currency transaction on poloniex, but there are only a few currencies supported by BOTvs, and exchange.IO doesn't seem to support Pnet.

The Little DreamYou can call this exchange.IO.

The NinjaWhat about the API that needs to verify the account?

The Little DreamIf an API that does not require account verification can be used with httpQuery (see BotVS documentation for more details), the actual transaction API needs access.

The Little DreamYou can use the HttpQuery API to transmit parameters: https://www.okcoin.com/api/v1/future_estimated_price.do?symbol=btc_usd, that's it. For exchange APIs that don't require verification of accounts, use the HttpQuery function directly on the platform. This post was originally published on the website: https://www.botvs.com/bbs-topic/850

visionsThank you very much, I hope you have a good API documentation.

The Little DreamWhere did you see the realTicker API?

The Little DreamThis is a list of all the different ways Fe1a6f5563ed43a5357f858ecf8a50239619228e.png is credited in the database. The API documentation is in JavaScript language. The python version is described in the posts at the top of the plugin page.

ZeroHi, thanks for the suggestion, the API documentation is currently being rebuilt.

The Little DreamHello~ shows that the frequency of access is beyond the limit. This is a list of all the different ways Dn-filebox.qbox.me is credited in the database. Is the Sleep function used in the policy? This 1000 is to allow the program to pause one second per round, which can be set by itself, the purpose is to control the frequency of access to the API, because some exchanges set maximum access limits, a certain amount of time beyond a certain number of visits will deny access, block IP addresses.

The Little Dreamhttps://dn-filebox.qbox.me/c29ab7fc279e1b758355f137907cf52dc8257df6.png I personally wrote that the STOCHRSI indicator, which has been compared to OK, is consistent that the speed is a bit slow and needs to be optimized, but is available for now.

ZeroYou can choose to retest on the server provided by botvs or retest on the server hosted by your host, version 2.7.5

The Little DreamThis is the first time I've seen this post.

The Little DreamNow you can configure your own background style.

The Little DreamThe python documentation is being written.

The Little DreamTalib library support is available.

hzzgood48 https://www.botvs.com/bbs-topic/276

The Little DreamIt seems that there is an example in Strategy Square, https://www.botvs.com/strategy/15098

ZeroAccess the AveragePrice attribute of the Order, which the exchange supports, and the one that does not support the attribute will always be 0.

yhfggHow does a third-party source cite?

ZeroIf mathjs is not satisfied, it can only look for a third-party library copy-import policy. To speed up compilation, the system only has a small number of libraries built in.

The Little DreamI'm not polite, there are problems in the group can M me - I'm basically online.

jiebangThank you.

The Little DreamYou can look at the annotated version of the digital currency trading library code analysis, and there's an annotation for the $.Cross function.

ZeroYou can't delete the latest, you can just keep the latest few posts... delete all the old ones before.

kirinTo get each holding using position[i], position is an array.

The Ninja exchange.GetRecords(PERIOD_D1);

kirinMy traditional futures are always the "GetAccount: not login", "password not entered, login not possible"

ZeroThe default is week, which requires the specified SetContractType first.

ZeroSo, this is the return value of the cancellation order that the exchange returned, but the actual cancellation was not cancelled, depending on how it was handled inside the exchange.

momox 3q

ZeroNot for a while, but separated.

xuanxuanOf course not, that's exclusive to MT4.

ZeroJavascript resources are everywhere on the web.

Selling outIs your problem solved?

ZeroMost of the time, the input data can be directly records or an array of pure prices.