Erfinder quantifizieren die API-Dokumentation

Schriftsteller:Kleine Träume, Erstellt: 2017-11-27 09:05:08, Aktualisiert: 2023-07-12 16:47:31

void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
  • MailAsynchrone Versionen von FunktionenMail_GoDie Funktion: Nutzung undexchange.GoDie Funktion ist ähnlich.

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

Bitte beachten: Der Ali-Cloud-Server kann einige Ports blockieren, was dazu führt, dass die E-Mails nicht gesendet werden können.smtp.qq.com:587Der Port-Test ist verfügbar. Wenn ein Fehler auftaucht:unencryped connectionDas muss geändert werden.MailDie FunktionsmtpServerDas Format der Parameter lautet:ssl://xxx.com:xxxEin Beispiel ist die QQ-E-Mail.SMTPDas ist ein sehr schwieriger Fall.ssl://smtp.qq.com:465Odersmtp://xxx.com:xxx

SetErrorFilter(...)

SetErrorFilter(RegEx), Filter-Fehlerprotokoll. Parameterwert: String-Typ. Fehlerlogs, die mit diesem Regelausdruck übereinstimmen, werden nicht in das Logsystem hochgeladen, und mehrere Filterbedingungen können mehrmals aufgerufen werden (die gefilterten Logs werden nicht in die Datenbankdateien mit den entsprechenden Festplatten-IDs im Host-Verzeichnis geschrieben, um zu verhindern, dass häufige Fehlermeldungen zu einer Datenbank-Dateiexpansion führen).

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

Sie können auch die Anzeige von einem Interface-Fehler filtern:

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 (siehe unten)

GetPid(), gibt die Festplattenprozess-ID zurück.

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

GetLastError()

GetLastError(), um die letzte Fehlermeldung zu erhalten. Es ist normalerweise nicht notwendig, da der Programm die Fehlermeldung automatisch an das Logsystem hochlädt.GetLastError()Die Funktion löscht den Cache, sodass beim nächsten Aufruf keine Fehlermeldung mehr zurückgegeben wird.

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 (siehe unten)

GetCommand(), erhält die Interaktionsbefehlsstring ((utf-8)); erhält die Befehle, die von der Interaktionspolitik ausgesendet wurden, und räumt den Cache aus, ohne dass die Befehle eine leere Stringung zurückgeben.按钮名称:参数Wenn die Interaktionssteuerung keine Parameter hat (z. B. eine Tastensteuerung ohne Eingabebox), ist der Befehl der Tastenname.

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

Das untergeordnete System hat eine Schlange Struktur, die Interaktionsbefehle aufzeichnet, wennGetCommand()Bei Aufruf der Funktion wird der zuerst eingegebene Interaktionsbefehl aus der Warteschlange herausgenommen (wenn kein Interaktionsbefehl vorhanden ist, kehrt er einen leeren String zurück).

Beispiele für die Verwendung von Interaktionssteuerelementen, die die Interaktionssteuerung in der Strategie-Editor-Schnittstelle einstellen.

img

Die Strategie ist es, den interaktiven Code zu entwerfen:

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()Die Funktion gibt den Registrierungscode zurück, der bei der Erstellung der Registrierungspolitik eingegeben wurde.MetaDer Wert, den die Funktion zurückgibt, ist der String-Typ. Anwendungsszenarien, z.B. eine Strategie, bei der Geldbeschränkungen für verschiedene Mieter erforderlich sind. Bitte beachten Sie, dass die Registrierungskode generiert wirdMetaDie Funktion darf nicht länger als 190 Charaktere sein. Die Funktion ist nur für die Festplatte gültig und erfordert die Verwendung eines neuesten Administrators.GetMeta()Es wird ein Nullwert zurückgegeben.

Informationen über die Verwendung von Szenen

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

Wählen Sie...

Dial(Address, Timeout)Das ist nicht wahr.SocketBesuch, UnterstützungtcpudptlsunixDas Protokoll. Parameterwert:AddressSie können auch eine andere Form verwenden, um die Stringart zu ermitteln.TimeOutDer Typ der Werte ist Sekunden, wenn die Zeit überschritten istDial(...)Die Funktion gibt einen Nullwert zurück.

AddressDie Parameter sind ausführlich:

Parameterbeschreibung
EinstellungenDialFunktionsparameter Die normale Adresse ist:wss://ws.okx.com:8443/ws/v5/publicSpäter|Symboltrennung, wenn es eine Zahlenfolge gibt|Die Zeichen werden in||Als Trennzeichen verwendet.&Zeichenverknüpfungen; z.B. ss5 Agent und Komprimierungsparameter zusammen:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Bei der Verwendung des ws-Protokolls werden folgende Parameter für die Datenkomprimierung verwendet:compress=参数值 Compress ist ein Kompressionsmodus, die Kompress-Parameter sind optionalgzip_rawgzipWenn die gzip-Methode nicht gzip-standard ist, können Sie die Erweiterungsmethode verwenden:gzip_rawDas ist der Unterschied zwischen|Nachträglich hinzufügencompress=gzip_raw, mit&Symbol und die nächste Mode-Parameter getrennt.
Bei der Verwendung des ws-Protokolls werden folgende Parameter für die Datenkomprimierung verwendet:mode=参数值 Modus als Modus, wählbardualsendrecvEs gibt drei Arten.dualDie Daten werden in zwei Richtungen gesendet und empfangen.sendDie Kompressionsdaten werden gesendet.recvUm die Kompressionsdaten zu empfangen, wird lokal entschlüsselt.
Die entsprechenden Parameter für die Einstellung von socks5-Agenten:proxy=参数值 Proxy ist ein s5-Agent, sein Parameterwert ist in diesem Format:socks5://name:pwd@192.168.0.1:1080,name ist der Benutzername des SS5-Servers, pwd ist das Anmeldepasswort des SS5-Servers und 1080 ist der Port des SS5-Service.
Bei der Verwendung des ws-Protokolls werden die folgenden Parameter für die automatische Wiederverknüpfung der Unterseite festgelegt:reconnect=参数值 Sie können auch die Funktion "Reconnect" verwenden, um zu überprüfen, ob Sie eine Neuaufnahme vorgenommen haben.reconnect=trueZur Aktivierung von Wiederverknüpfungen.
Bei der Verwendung des ws-Protokolls werden die folgenden Parameter für die automatische Wiederverknüpfung der Unterseite festgelegt:interval=参数值 Intervall ist ein Intervall in der Wiederholungszeit, in Millisekunden.interval=10000Für den 10-Sekunden-Wiederversuch ist der Standardwert 1 Sekunde nicht gesetzt.interval=1000
Bei der Verwendung des ws-Protokolls werden die folgenden Parameter für die automatische Wiederverknüpfung der Unterseite festgelegt:payload=参数值 Die Abonnementnachrichten, die beim Wiederaufbau der Payload als ws gesendet werden müssen, z. B.: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();
    }
}

readDie Funktion unterstützt folgende Parameter:

  • Wenn keine Parameter übermittelt werden, wird blockiert, bis eine Nachricht zurückgegeben wird.ws.read()
  • Bei der Übertragung der Parameter ist die Einheit Millisekunden und die Wartezeit der Nachrichten wird angegeben.ws.read(2000)Die Zeitverzögerung wird auf zwei Sekunden (z.B. 2000 Millisekunden) festgelegt.
  • Die beiden folgenden Parameter sind nur richtig.websocketWirksam: Eintrittsparameter-1Eine Funktion kann sofort zurückgegeben werden, egal ob es eine Nachricht gibt oder nicht.ws.read(-1)Das ist nicht wahr. Eintrittsparameter-2Die Funktion kehrt unmittelbar zurück, egal ob keine Nachrichten vorhanden sind, aber nur die neuesten Nachrichten.ws.read(-2)

read()Die Funktionsbuffer beschreibt: Die Daten, die durch das WS-Protokoll geschickt werden, werden in der Strategie geschaltet.read()Zu lange Zeitintervalle zwischen Funktionsaufrufen können zu Datenaufkommen führen. Diese Daten werden in einem Buffer gespeichert, dessen Buffer-Datenstruktur eine Reihe von bis zu 2000 Daten umfasst. Nach 2000 werden die neuesten Daten in den Buffer eingegeben und die ältesten Daten gelöscht.

Die Szene.readFunktionsparameter Keine Parameter Parameter: -1 Parameter: -2 Parameter: 2000, die Einheit ist die Millisekunde
Die Daten sind bereits vorhanden Die Daten werden sofort zurückgegeben. Die Daten werden sofort zurückgegeben. Die Daten werden sofort aktualisiert. Die Daten werden sofort zurückgegeben.
Keine Daten für die Bufferzone Blockieren bis Daten vorhanden sind Er gibt sofort einen nullwert zurück. Er gibt sofort einen nullwert zurück. Warten Sie 2000 Millisekunden, keine Daten geben null zurück, Daten geben zurück
Wenn die ws-Verbindung abgerissen wird oder die Unterseite neu verbunden wird Die Funktion read (()) gibt einen leeren String zurück, d.h.::"",write (()) gibt 0 zurück und stellt dies fest. Die Verbindung kann mit der Funktion close (() geschlossen werden.
  • Unterstützt das wss ((WebSocket)) Protokoll Die Websocket-Marktoberfläche von Binance:

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

    Die Websocket-Marktoberfläche für 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("退出");
    }
    

    Die Websocket-Marktoberfläche für den Zugriff auf die Token:

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

    Die Websocket-Verifizierungsoberfläche für 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 ist ein

HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader), Netzwerk-URL-Zugriff. Parameterwert: Alle für den Stringtyp.

Bitte beachten Sie:

  • HttpQuery(...)Funktionen werden nur unterstütztJavaScriptDie Sprache.
  • PythonSprache kann verwendet werdenurllibDas ist eine sehr schwierige Aufgabe.

HttpQuery(...)Es wird hauptsächlich für den Zugriff auf eine Anschlussstelle verwendet, die keine Unterschrift benötigt, z. B. für öffentliche Anschlüsse wie Marktinformationen.

Ein Beispiel für eine API-Schnittstelle, die keine Unterschrift benötigt, um zu OKX zu gelangen, und die einen Wert vonJSONIch bin nicht derjenige, der das sagt.JavaScriptDie Strategie der SpracheJSON.parse()Funktionsanalyse.

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

Wenn die zweite Parameter die Rückgabe eines URLs erhält,PostDataFür die Stringa=1&b=2&c=abcDie Form ist:POSTWie kann ich das machen?PUTSie haben sich nicht verändert.PostDataDie Parameter sind:{method:'PUT', data:'a=1&b=2&c=abc'}PostDataDie Parameter können auchJSONDie Strings.

CookiesDie Form dieses Parameters lautet:a=10; b=20Die Parameter werden mit einem Komma bezeichnet.;Ich bin nicht derjenige, der es tut.HeadersDie Form dieses Parameters lautet:User-Agent: Mobile\nContent-Type: text/htmlDie Parameter werden mit Zeilenzeichen ausgetauscht.\nIch bin nicht derjenige, der es tut.

Der zweite ParameterPostDataSie können sich anpassen, wie zum Beispiel:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})Bitte beachten Sie:HttpQueryDie Funktion setzt die Überstunden ein.{method:'PUT', data:'a=1&b=2&c=abc'}BeitritttimeoutEigenschaften (Standard 60 Sekunden)

Ein Sekunde Zeitverzug:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})

ÜbertragenCookieEine String braucht einen dritten Parameter, aber nichtPOSTBitte setzen Sie den zweiten Parameter auf null. Während des Analogetests kehrt die Funktion eine feste String zurück, da die URL nicht simuliert werden kann.Dummy DataÜber diese Schnittstelle können Sie SMS senden oder mit anderen API-Schnittstellen interagieren.

GETEin Beispiel für einen Anruf:HttpQuery("http://www.baidu.com")POSTEin Beispiel für einen Anruf:HttpQuery("http://www.163.com", "a=1&b=2&c=abc")

ZurückHeaderEin Beispiel für einen Anruf:

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}
  • HttpQueryDie Funktion wird mit einem Agenten eingestellt:

    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/");
    }
    
  • HttpQueryAsynchrone Versionen von FunktionenHttpQuery_GoIch bin nicht derjenige. Nutzung undexchange.GoDie Funktionen sind ähnlich, z. B. ein asynchroner Zugriff auf die öffentliche Schnittstelle der Börse, um Aggregatmarktdaten zu erhalten.

    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)
    }
    
    # 不支持
    
    // 不支持
    
  • Verwendung in Retest-SystemenHttpQuery(...)Die Funktion: Sie können in Retestsystemen verwendet werden.HttpQuery(...)Senden von Anfragen (nur unterstützt)GETVerwenden Sie die folgenden Funktionen: • Anfordern Sie Daten; • Beschränken Sie die Wiederholung auf 20 verschiedene URLs undHttpQuery(...)Der Zugriff speichert Daten, die beim zweiten Zugriff auf dieselbe URL gespeichert werden.HttpQuery(...)Die Funktion kehrt Cache-Daten zurück (es gibt keine tatsächlichen Netzwerkanfragen mehr).

    Wir können einen Serviceprogramm auf einem Server oder Gerät laufen lassen, um auf die Strategie zu reagieren.HttpQuery(...)Die Requests wurden mit dem folgenden Go-Language-Service-Programm getestet:

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

    Strategie-RücksichtHttpQuery(...)Funktionsanforderung:

    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

  • Unterstützt die Umschlüsselung von Reaktionsdaten auf Anfragen und unterstützt die allgemeine Verschlüsselung. BestimmungPostDataParameter:{method: "GET",charset:"GB18030"}Die Datenübertragungskode (GB18030) wird dann umgesetzt.

Verschlüsselung

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)Die Funktion kodiert die Daten nach den eingegebenen Parametern.

ParameteralgoDie Algorithmen, die bei der Codeberechnung verwendet werden, werden unterstützt:??raw (ohne Algorithmen),??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.dataDie Daten, die verarbeitet werden sollen.inputFormat/outputFormat/keyFormatParameter unterstütztrawhexbase64stringDas ist ein sehr schwieriger Fall. WennkeyFormatWenn es nicht null ist, dann benutzen wir die Parameter.keyVerschlüsselung (HMAC), ansonsten ist der StandardkeyParameteralgoSetzen Sie auf"sign"Oder"signTx"Wenn Parameter erforderlich sindkey

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
}

ParameteralgoSie unterstützen auch:text.encoder.utf8text.decoder.utf8text.encoder.gbktext.decoder.gbk, für die String-Codierung, für die Entschlüsselung.

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 (siehe unten)

UnixNano(), die eine Nanosekunden-Zeitspanne zurückgibt. Wenn Sie eine Millisekunden-Zeitspanne erhalten möchten, können Sie folgende Code verwenden:

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(), die Sekunden-Ebene-Zeitknalle zurückgibt.

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

GetOS()

GetOS()Die Daten werden von den Administratoren zurückgesendet.

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

Auf einem Apple ComputerMac OSDie Ausgabe des Administrator-Logs, der unter dem Betriebssystem ausgeführt wird:

GetOS: darwin/amd64

darwinDas heißtMac OSDer Name des Systems.

MD5 ((String)

MD5(String), Parameterwert: Stringtyp.

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

Die Datenbank ist hier:

Wir haben eine Reihe von Problemen.

DBExec ((...)

DBExec(), Parameterwerte: können Strings, Zahlenwerte, Bullwerte, Leerwerte usw. sein. Datenbank-Interface-FunktionenDBExec()Durch die Einführung von Parametern kann die Festplatten-Datenbank (SQLite-Datenbank) bedient werden.SQLiteSyntax.Die Systemreservierungstabelle in der Festplatten-Datenbank:kvdbcfglogprofitchartSie müssen sich nicht an diese Tabellen beteiligen.DBExec()Die Funktion unterstützt nur die Festplatte.

  • Unterstützung von Speicherdatenbanken FürDBExecDie Parameter der Funktion, wennQuadratkilometerDie Sätze sind::Anfänglich wird die Datenbank im Speicher betrieben, ohne Dateien zu schreiben, schneller. Geeignet für Datenbankoperationen, die keine persistierende Speicherung erfordern, wie zum Beispiel:

    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;"));
    }
    
  • Tabellen erstellen

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);
}
  • Anpassung von Tabellenprotokollen
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(), die eine 32-Bit-Unique-UUID zurückgibt, die nur für die Festplatte verwendet wird.

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 (Zeitrahmen)

EventLoop(timeout)Ich habe keine Wahl.websocketLesbar oderexchange.GoHttpQuery_GoSo werden die gleichzeitigen Aufgaben nach Abschluss zurückgegeben.timeoutWenn es auf 0 gesetzt ist, wird erst auf ein Ereignis gewartet, wenn es größer als 0 ist, wird die Ereigniszeit überschritten, wenn es kleiner als 0 ist, wird sofort das jüngste Ereignis zurückgegeben.nullDie Daten werden von den Benutzern gesammelt.EventDer Typ für die Ereignis-Triggerung. Diese Funktion gilt nur für die Festplatte.

Der erste Aufruf im CodeEventLoopWenn Sie das System nicht verwenden, wird die Überwachung erst initialiert, wenn Sie es erst nach dem Abruf des Ereignisses starten.EventLoopAufrufe, die die vorherigen Ereignisse verpassen. Die untergeordnete Systemumwandlung speichert bis zu 500 Ereignisrückrufe, wenn der Programmlauf nicht rechtzeitig aufgerufen wirdEventLoopWenn Sie das nicht tun, verlieren Sie 500 Cache-Ereignisse, die später abgerufen wurden.EventLoopFunktionsaufrufe beeinflussen nicht die SystembasiswebsocketDie Cache-Warteschlangen sind nicht beeinflusst.exchange.GoDie Cache von gleichzeitigen Funktionen, wie z.B. die Cache von parallelen Funktionen, benötigt immer noch eine eigene Methode, um Daten zu extrahieren.EventLoopDie Daten, die entnommen wurden, werden nicht in der Funktion zurückgegeben.EventLoopDie Funktion erzeugt eine Rückkehr.

EventLoopDie Funktion dient hauptsächlich der Benachrichtigung der Policy-Layer, bei der die Systemunterseite neue Netzwerkdaten empfängt.EventLoopWenn eine Funktion ein Ereignis zurückgibt, muss sie nur alle Datenquellen durchlaufen.websocketSie sind in der Lage, sich zu vernetzen.exchange.GoEin Objekt, das erstellt wird, versucht, Daten zu erhalten.Verknüpfungen zur Bibliothek

In der Hauptfunktionmain()Der Hauptthread wird während des Zwischenrufs überwacht.JavaScriptIn der Strategie, Sprache zu schreiben, ist es wichtig, dass die Sprache in der Praxis funktioniert.__Thread()Die Funktion erstellt Threads, die auch in der Exekutivfunktion des Threads aufgerufen werden können, um auf die Ereignisse des aktuellen Threads zu hören.

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秒,并发的函数

Mehr

- Ich weiß nicht.Es gibt ein Problem, ob die _C_Funktion immer wiederholt wird oder nur einmal.

Ich habe dich nicht gesehen._C ((function, args...) ist das Default 3s? Kann man das Default ändern und direkt _CDelay ((1000) vor _C ((function, args...) setzen?

LunchzeitCluster: Wenn Sie 1000 Roboter gleichzeitig und ohne Stress erstellen, können Sie mehrere Administratoren erstellen, um Aufgaben zu verteilen. Gibt es Codebeispiele, wie man Clusters erstellt?

Wir sind hier.Log ((talib.help (('MACD')); kann nur unter js verwendet werden, Python hat keine talib.help-Attribute...

Czz140Was ist der Unterschied zwischen der _C ((function, args...) und der Sleep-Funktion, die ich für eine Wiederholung halte?

3263243ySetErrorFilter: Wie entfernt man einen Fehlerfilter, ohne Fehlermeldungen zu filtern?

QQ47898077Wenn Sie eine Drittanbieter-Bibliothek nutzen möchten, gibt es eine Möglichkeit?

QQ47898077Was sollte die Stammklasse ausfüllen, wenn man eine neue Klasse erben möchte, die von einem Börsenobjekt definiert wird?

EtherGibt es ein lokales Debugging-Tool?

ZürichWas ist mit exange.IO?

ZürichWarum ist die Funktion sell in Grau? Ist die Funktion nicht mehr verfügbar?

ZürichWarum ist die Funktion sell in Grau? Ist die Funktion nicht mehr verfügbar?

ZürichIch habe keine Sprache, haha, aber ich möchte fragen, ob es die Unterstützung von es6 hat.

ZürichIch habe keine Sprache, haha, aber ich möchte fragen, ob es die Unterstützung von es6 hat.

Don.Wie schreibt man die Mittellinie von Volumen?

SchildkröteWas gibt es zurück, wenn es nicht klappt, den Marktpreis zu kaufen?

Der Mann von NingDie neue Schrift sieht gut aus.

FlügelDas Testnetz von Bitmex (testnet.bitmex.com) verfügt ebenfalls über eine API-Schnittstelle, jedoch können die Börsen derzeit nur die Bitmex-Haupthandelsstation auswählen. Die API-Dokumentation ist unter https://testnet.bitmex.com/app/apiOverview Wie unterstützen Sie uns?

- Ich weiß nicht.Der Preis für die Produkte wird von den US-amerikanischen Behörden veranschlagt. Log (('ok Futures Estimated Delivery Price', ret1); https://dn-filebox.qbox.me/d1ed268c1e75753c5d289447d279aa9d81e41b5f.png Wenn Sie die Funktionsoberfläche anderer Börsen aufrufen und einen Fehler melden, warum?

allenfrostlineWas ist der Unterschied zwischen realTicker und Ticker? In jüngster Zeit wurde die Strategie für die Umschreibung von Profit-Suites neu geschrieben und beide erscheinen gleichzeitig, aber die erste API scheint keine Erwähnung zu haben.

VisionenHallo, als Python-Entwickler, was glaubst du, dass deine API-Dokumentation schreibt?

allenfrostlineGetAccount: [EAPI:Rate limit exceeded] Ich möchte wissen, wie man das löst?

Zjx2314StochRSI wird nicht unterstützt, ob es so schnell wie möglich hinzugefügt werden kann

YhfggWenn die Python-Politik auf der Festplatte ist, ist das Skript auf dem eigenen Ali Cloud-Server oder im Botvs-Cluster?

YhfggWelche Version von Python benutzt man?

Schon gutDie Definition von GetFee sollte sein, dass sie eine Fee-Struktur zurückgibt.

ZkwapWie kann man Talib mit js aufrufen?

YhfggAnforderung der python-Dokumentation

- Das ist nicht wahr.Kann man einen schwarzen Code-Hintergrund für Strategie-Editoren verwenden? Weiße Augen, schriftliche Nachtcode, leicht kurzsichtig

Don.Wie kann ich die Zusammenfassung in der Bots-Wechat-Push einstellen?

ZahlreicheKann man in der Order-Struktur ein Feld mit einem gleichen Transaktionspreis hinzufügen?

Kleine KleinigkeitGetOrders: Erhält alle unvollendeten Bestellungen, gibt eine Arraystruktur an, die in China Bitcoin-ETH-Trading, nur die letzten 10 zurückgibt. Hier gibt es eine Funktion, die alle unvollendeten Bestellungen in China Bitcoin ETH zurückgibt, was bedeutet, dass andere Plattformen alle mit GetOrders zurückgeben können.

YhfggDie mathematischen Funktionen, die für die statistische Wahrscheinlichkeit verwendet werden müssen, wo kommen sie her?

Sieh nach.Was bedeutet der Wert, den die Funktion $.Cross ((x, y)) zurückgibt?

Meine Mutter nennt michDas LogReset räumt alle Logs aus und kann einen Zahlenparameter verwenden, um die Anzahl der reservierten Einträge festzulegen. Wie löscht man die letzten Tage?

- Ich weiß nicht.Die CORRE-Funktion in talib scheint nicht übernommen worden zu sein, oder ist sie entfallen?

Die armen Berge von LiuyangEs scheint, dass es keine Indikatorreferenz-Funktion gibt!

Kleine und kleineWie kann ich die Zeit der K-Zeile lesen, um sie in die Zeit der Gegenwart zu übersetzen?

Kleine und kleineWie kann man Zahlen aus Arrays entfernen, wenn ich mit records.remove ((records[0]) arbeite?

SchlangeWie kann man ATR für die Tages-K-Linie aufrufen?

SchlangeWie kann man ATR für die Tages-K-Linie aufrufen?

57278863Lernen Sie, wie man traditionelle Futures zum Preis und zum Auftrag bekommt, leider ist die Basis dünn

KirinDas ist ein Beispiel für traditionelle Futures.

Kleine und kleineZero, kannst du ein Beispiel für traditionelle Futures schreiben?

Kleine und kleineWie kann ich den Zustand von mehreren Leerzeichen gleichzeitig ausdrucken, wie kann ich den Zustand von mehreren Leerzeichen ausdrucken, wie kann ich den Zustand von mehreren Leerzeichen und Leerzeichen ausdrucken, und wie kann ich den Zustand von mehreren Leerzeichen und Leerzeichen erhalten?

- Ich weiß nicht.Kann eine Futures-Börse mit GetTicker (() Märkte abrufen, die diese Art von Vertragsmärkten ((in der Woche, in der nächsten Woche...) zurückgeben?

VerkauftWas ist der StochRSI, kann man dazu hinzufügen?

MoxCancelOrder ((orderId) Kannseln Sie eine Bestellung nach der Bestellnummer, geben Sie true oder false zurück, und fragen Sie true= Die Zelle wurde erfolgreich abgesagt, richtig?

Mox_G(K, V) Speicherbare globalen Wörterbücher Diese Methode speichert globalen Variablen, die für die Datenabteilung zwischen verschiedenen Strategien verwendet werden können.

FlustigDie Schlagzeile

NullSie können das Ertragsprotokoll mit LogProfitReset neu einstellen. Die Geschichte auf den vorherigen Ertragsdiagrammen ist nicht mehr vorhanden.

ZyKann man die EA direkt kopieren?

- Ich weiß.Ich finde die Plattform großartig.

Kleine und kleineWas ist das für eine Sprache, gibt es eine Lernquelle?

jxhbtcDatenfehler eine Woche lang, kein Roboter verbunden

Das ist alles.Der Indexbank TA, ist es nur eine Berechnung für den Verkaufspreis?

BtcrobotHallo, Welt.

Kleine TräumeDie _C-Funktion versucht es ohne Gedanken, bis sie erfolgreich ist.

Kleine TräumeDie Talib-Bibliothek für Python muss installiert werden. https://www.botvs.com/bbs-topic/669 kann in diesem Beitrag besucht werden.

Kleine TräumeSleep ist die Anzahl von Millisekunden, in denen ein Programm nichts tut und wartet, bis die Parameter gesetzt sind, und _C ist die Anzahl der Millisekunden, in denen die Funktion, die die Parameter übermittelt hat, erneut aufgerufen wird.

Kleine TräumeJS wird ohne Vererbung direkt in den Objekt eingebunden.

Kleine TräumeEiner der wichtigsten Funktionen ist die Verwendung von Remote Debugs.

Kleine TräumeIch habe eine Frage, die ich mir nicht stellen kann.

Kleine TräumeIn der API-Dokumentation bedeutet Grau, dass die Funktion ohne zu viele Ausführungen erscheint.

Kleine TräumeES6 ist momentan nicht unterstützt ^^

Kleine TräumeIch bin in der Gruppe QQ, beschreibe die Frage und ich werde sie beantworten ^^

Kleine TräumeDie Anzeige wird direkt einen Fehler zurückgeben und keine Bestellung mehr erfolgen (in Wirklichkeit ist es ein Kauf, nicht genug Geld!).

SchildkröteWie wird OKCoin zurückgegeben, wenn die Anzahl der gekauften Münzen die Menge der gehaltenen Münzen übersteigt?

Kleine TräumeIch habe eine Frage an die Börse gestellt: "Welche Börse gibt es, an der ich eine Bestellnummer bei OK Futures zurückgeben kann?"

NullEs wird bereits unterstützt, dass Transaktionspaare beim Laufen gewechselt werden können, und es ist erforderlich, den neuesten Host herunterzuladen. Unterstützt wird Bter/Poloniex Details API-Dokumentation Transaktionsfunktion Tabellen Beschreibung unten ((Freien Sie den Browser-Cache und aktualisieren Sie, wenn Sie es nicht sehen können)

Kleine TräumeQQ, ich helfe dir, deine Fragen zu beantworten.

BerufstätigeIch setze die IPs der Hosting-Plattformen ein, um eine weiße Liste zu erstellen.

Kleine TräumeDas ist ein unterer Link, der nicht aufgebaut wurde. Der Server reagiert nicht.

BerufstätigeDas ist peinlich... Ich kann die Strategien auswechseln, die in der Bitcoin-Ära fehlten, und GetAccount kann nicht auf GetAccount zugreifen: 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 Bitcoin-Zeitfehler GetAccount: timeout 2017-05-23 21:08:02 Bitcoin-Zeitalter Fehler GetAccount: timeout 2017-05-23 21:07:40 Bitcoin-Zeit Fehler GetAccount: timeout 2017-05-23 21:07:20 Wiederaufnahme Ist es ein Problem mit der IP-Whitelist?

Kleine TräumeDer Server der Börse reagierte nicht, das TCP-Protokoll wurde nicht eingerichtet und die drei Handschläge wurden nicht durchgeführt.

BerufstätigeEine Verbindungsaufgabe scheiterte, weil die verbundene Partei nicht richtig nach einer Zeit reagierte, und die Verbindungsaufgabe scheiterte, weil die verbundene Partei nicht richtig reagierte.

Kleine TräumeHallo! Hier geht es um die Funktion exchange.IO ((api, ApiName, Args), die nicht unterstützt wird, siehe https://www.botvs.com/bbs-topic/812

BerufstätigeEin Anschlussversuch scheiterte, weil die angeschlossene Partei nach einer gewissen Zeit nicht richtig reagierte.

BerufstätigeDie Zeit der Bitcoins unterstützt sie nicht?

Kleine TräumeSiehe auch: https://dn-filebox.qbox.me/a709b30c6cc0a3565234b9e0c99b073f7ba8b454.png Das ist nicht schlecht.

Der Mann von NingZum Beispiel möchte ich einen poloniex-Vollwährungstransaktion durchführen, aber es gibt nur ein paar Währungen, die von BOTvs unterstützt werden, und exchange.IO scheint das P-Netz nicht zu unterstützen.

Kleine TräumeDas kann man mit exchange.IO anrufen.

Der Mann von NingWas ist mit einer API, die einen Account verifizieren muss?

Kleine TräumeWenn keine API zur Authentifizierung eines Kontos benötigt wird, kann httpQuery verwendet werden (siehe BotVS-Dokumentation für weitere Informationen), die tatsächliche Transaktions-API benötigt Zugriff.

Kleine TräumeDie API-Parameter können mit HttpQuery übermittelt werden: https://www.okcoin.com/api/v1/future_estimated_price.do?symbol=btc_usd. Für Börsen-APIs ohne Authentifizierung von Konten müssen Sie die HttpQuery-Funktion direkt auf der Plattform verwenden. Der Post: https://www.botvs.com/bbs-topic/850

VisionenIch hoffe, dass die API-Dokumentation perfekt ist.

Kleine TräumeWo ist die realTicker-API zu sehen?

Kleine TräumeSiehe auch: https://dn-filebox.qbox.me/fe1a6f5563ed43a5357f858ecf8a50239619228e.png Die API-Dokumentation ist in der JavaScript-Sprache beschrieben, die Python-Version beschrieben, die oben auf der Chat-Community-Seite angezeigt wird.

NullHallo, danke für die Tipps, die API-Dokumentation wird gerade neu erstellt.

Kleine TräumeHallo ~ zeigt, dass die Zugriffsfrequenz über die Grenzen hinaus ist. https://dn-filebox.qbox.me/a09498920d04cac62624b7438a058d2098d8fb00.png Ist die Sleep-Funktion in der Strategie eingesetzt worden? Diese 1000 ist eine Sekunde Pause pro Runde, die selbst eingestellt werden kann, um die Häufigkeit des Zugriffs auf die API zu steuern, da einige Börsen eine maximale Zugriffsbeschränkung festlegen, die den Zugriff verweigert und die IP-Adresse sperrt.

Kleine TräumeSiehe auch: https://dn-filebox.qbox.me/c29ab7fc279e1b758355f137907cf52dc8257df6.png Ich persönlich habe geschrieben, dass der bereits verglichenen OK-STOCHRSI-Indikator einverstanden ist, dass die Geschwindigkeit etwas langsamer ist und vorübergehend optimiert werden kann.

NullSie können selbst wählen, ob Sie die Überprüfung auf dem von botvs bereitgestellten Server oder auf dem Server Ihres Hosts durchführen möchten.

Kleine TräumeIch habe das Gefühl, dass ich es nicht kann.

Kleine TräumeJetzt können Sie den Hintergrundstil selbst konfigurieren.

Kleine TräumeDie python-Dokumentation wird geschrieben.

Kleine TräumeIch bin der Meinung, dass es eine gute Idee ist.

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

Kleine TräumeEs scheint ein Beispiel auf Strategie Square zu geben: https://www.botvs.com/strategy/15098

NullDer Zugriff auf die AvergPrice-Attribute von Order, die von den Börsen unterstützt wird, kann, und die nicht unterstützte Börse wird die Attribute immer 0 haben.

YhfggWie zitiert man in einer Drittanbieter-Buchstelle?

NullWenn mathjs das nicht kann, kann es nur nach einer Drittanbieter-Bibliothek suchen, um diese zu kopieren und zu importieren.

Kleine TräumeIch bin nicht sehr freundlich, es gibt Probleme in der Gruppe, ich kann mich - ich bin im Prinzip online - M- machen.

Sieh nach.Ich danke Ihnen.

Kleine TräumeSie können sich die Anmerkungen zu den Codeanalysen der Kryptowährungs-Trading-Klasse anschauen, in denen die Anmerkungen zu der $.Cross-Funktion enthalten sind.

NullEs ist nicht möglich, die neuesten zu löschen, sondern nur die neuesten zu behalten.

KirinUm jede Position mit Position[i] zu erhalten, ist Position eine Array.

Der Mann von NingÜbermittlung von Daten über das System.

KirinMein traditionelles Futures ist immer das GetAccount: not login, "Passwort nicht falsch eingegeben, also nicht eingeloggt".

NullDer Standard ist Woche, um den angegebenen SetContractType zu erhalten.

NullWir haben gerade gesehen, dass das True den Wert der Rückgabe für die Aktion der Stornierung der Bestellung ist, die die Börse zurückgegeben hat, aber die tatsächliche Stornierung ist nicht storniert, abhängig davon, wie sie intern behandelt wird.

Mox3q

NullNein, sondern sie sind abgeschnitten.

ZuanxuanNatürlich nicht, das ist MT4-Exklusivität.

NullJavascript-Informationen gibt es überall im Internet.

VerkauftSind deine Probleme gelöst?

NullDie meisten Daten können entweder direkt als Rekorde oder als reine Preissätze übertragen werden.