O recurso está a ser carregado... Carregamento...

Em termos globais

Versão

Retorna o número de versão atual do sistema.

Número da versão actual do sistema, como:3.6- Não. cordel

Versão (((

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

O número de versão do sistema é o número de versão do programa do docker.

Dormir

A função de sono, fazendo com que o programa pare por um período de tempo.

Sono (milissegundos)

OmillisecondO parâmetro é utilizado para definir a duração do sono e o número de milissegundos. milissegundos verdade Número

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

Por exemplo, ao executar oSleep(1000)Função, o programa irá dormir por 1 segundo.Sleep(0.1)Suporta um parâmetro mínimo de0.000001, ou seja, hibernação de nanossegundos, onde 1 nanossegundo é igual a1e-6milissegundos. Quando se escreve estratégias noPythonA linguagem, oSleep(millisecond)A função de intervalo de sondagem deve ser utilizada para operações de tempo de espera.time.sleep(second)função dePythonÉ...timeIsto é porque usando otime.sleep(second)função em uma estratégia faz o programa de estratégia esperar por um período de tempo na verdade quando backtesting (não pulando sobre a série de tempo do sistema de backtesting), por isso faz com que a estratégia para backtest muito lentamente.

IsVirtual

Determinar se o ambiente de execução da estratégia é um sistema de backtesting.

A estratégia retorna um valor verdadeiro, por exemplo:trueQuando executado no ambiente do sistema de backtesting, a estratégia retorna um valor falso, por exemplo:falsequando executado num ambiente de negociação em tempo real. Bool

É Virtual?

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

Determinar se o ambiente em execução atual é um sistema de backtesting, utilizado para ser compatível com a diferença entre backtesting e negociação em tempo real.

Correio

Envia um e-mail.

Uma entrega bem-sucedida de e-mail retorna um valor verdadeiro, por exemplo,true, e uma entrega falhada retorna um valor falso, por exemplo,false- Não. Bool

Correio ((smtpServidor, smtpUsuário, smtpPassword, mailTo, título, corpo)

Utilizado para especificar oSMTPEndereço de serviço do remetente do correio electrónico. SmtpServer verdade cordel Usado para especificar o endereço de e-mail do remetente. Nome do usuário verdade cordel OSMTPpalavra-passe para a caixa de correio do remetente do email. SmtpPassword verdade cordel Usado para especificar o endereço de e-mail do destinatário do e-mail. mailTo verdade cordel Endereço de email. Título verdade cordel Corpo de e-mail. corpo verdade cordel

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

OsmtpPasswordParâmetro define a palavra-passe para oSMTPserviço, não a senha da caixa de correio. Ao definir osmtpServerParâmetro, se você precisa mudar a porta, você pode adicionar o número da porta diretamente no parâmetrosmtpServerPor exemplo: QQ mailsmtp.qq.com:587, disponível para ensaio. Em caso de erro:unencryped connection, você precisa modificar osmtpServerdoMailFunção. O formato do parâmetro é:ssl://xxx.com:xxx, por exemplo, osslmétodo deSMTPpara correio QQ:ssl://smtp.qq.com:465ousmtp://xxx.com:xxx- Não. Não funciona no sistema de backtesting.

Não, não, não, não.

Mail_Go

Versão assíncrona doMail function.

OMail_Gofunção retorna um objeto simultâneo imediatamente, e você pode usar owaitUm método de que o objeto concorrente para obter o resultado da entrega de correio. uma entrega de correio bem sucedida retorna um valor verdadeiro, por exemplo,true, e uma entrega falhada retorna um valor falso, por exemplo,false- Não. Objeto

Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, título, corpo)

É utilizado para especificar oSMTPEndereço de serviço do remetente do correio electrónico. SMTPServer verdade cordel É usado para especificar o endereço de e-mail do remetente do e-mail. Nome do usuário verdade cordel OSMTPpalavra-passe para a caixa de correio do remetente do email. SmtpPassword verdade cordel É usado para especificar o endereço de e-mail do destinatário do e-mail. E-mail para verdade cordel Endereço de email. Título verdade cordel Corpo do email. corpo verdade cordel

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

Não funciona no sistema de backtesting.

Não, não, não.

SetErrorFilter

Registros de erros de filtragem.

SetErrorFilter (filtros)

Estringência de expressão regular. filtros verdade cordel

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

Filtrar erros comuns.

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

Filtrar uma mensagem de erro de interface.

Os registros de erros correspondentes a esta expressão regular não serão carregados no sistema de registros. Você pode chamá-lo várias vezes (sem limite no número de vezes) para definir várias condições de filtro. As expressões regulares definidas várias vezes serão acumuladas e entrarão em vigor ao mesmo tempo. Você pode definir uma cadeia vazia para redefinir a expressão regular usada para filtrar registros de erros:SetErrorFilter("")Os registos filtrados não são mais escritos no arquivo de banco de dados correspondente ao ID de negociação ao vivo no diretório do docker para evitar que os relatórios de erros frequentes inchaçam o arquivo de banco de dados.

GetPid

Obtenha a identificação do processo de negociação.

Retornar a identificação do processo de negociação em tempo real. cordel

GetPid ((()

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

GetLastError

Recebi a última mensagem de erro.

Última mensagem. cordel

GetLastError (()

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

Não funciona no sistema de backtesting.

GetCommand

Recebe o comando de interação estratégica.

O formato do comando retornado éControlName:Data. ControlNameé o nome do controlo, eDataSe o comando interativo não tiver caixas de entrada, caixas suspensas e outros componentes (por exemplo, um comando de botão sem caixas de entrada), então o formato do comando retornado éControlName, que retorna apenas o nome do controlo. cordel

Obter Comando ((()

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

Detecta o comando de interação e utiliza oLogFunção para emitir o comando de interação quando detectado.

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

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

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

Por exemplo, o controle interativo estratégia adiciona um controle sem uma caixa de entrada, o controle interativo é chamado:buy, a informação relativa à descrição do controlo é:buy, que é um controle de botão. Continue adicionando um controle com uma caixa de entrada. O controle interativo é chamado:selle a mensagem de descrição do controlo é:sellO código de interação é projetado na estratégia para responder aos diferentes controles de interação:

Não funciona no sistema de backtesting.

GetMeta

Obter o valor de Meta escrito ao gerar o código de registro estratégia.

Metadados. cordel

GetMeta ((()

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

Exemplo de cenário de aplicação: utilizaçãoMetaLimitar o montante dos activos geridos pela estratégia.

O cenário de aplicação: necessidade de fazer limites de capital para diferentes locatários estratégicos.MetaO valor definido para a geração do código de registo não pode exceder 190 caracteres e oGetMeta()A função só suporta a negociação em tempo real.Meta) é definido no momento da geração de um código de registo de estratégia, oGetMeta()Função retorna nulo. Não funciona no sistema de backtesting.

Marque

Para primitivoSocketacesso, apoiotcp, udp, tls, unixSuporte a 4 protocolos de comunicação populares:mqtt, nats, amqp, kafka- Suporte para ligação a bases de dados:sqlite3, mysql, postgres, clickhouse.

ODial()Uma chamada normal retorna um objeto de conexão que tem três métodos:read, writeeclose. OreadO método é utilizado para ler os dados, owriteO método é utilizado para enviar dados e oclosemétodo é utilizado para fechar a ligação. OreadO método suporta os seguintes parâmetros:

  • Quando nenhum parâmetro é passado, ele bloqueia até que uma mensagem esteja disponível e retorne, comows.read().
  • Quando passado como um parâmetro, a unidade é milissegundos, especificando o período de espera da mensagem.ws.read(2000)Especifica um timeout de dois segundos (2000 milissegundos).
  • Os seguintes dois parâmetros são válidos apenas para o WebSocket: Passando o parâmetro-1significa que a função retorna imediatamente, independentemente da presença ou ausência de mensagens, por exemplo:ws.read(-1)- Não. Passando o parâmetro-2significa que a função retorna imediatamente com ou sem uma mensagem, mas apenas a mensagem mais recente é devolvida e a mensagem tamponada é descartada.ws.read(-2).

read()Descrição do buffer de funções: Os dados recebidos empurrados pelo protocolo WebSocket podem causar acúmulo de dados se o intervalo de tempo entre a estratégiaread()Os dados são armazenados no buffer, que tem uma estrutura de dados de uma fila com um máximo de 2000.

Scenário Nenhum parâmetro Parâmetro: -1 Parâmetro: -2 Parâmetro: 2000, em milissegundos
Dados já no buffer Retorne os dados mais antigos imediatamente Retorne os dados mais antigos imediatamente Retorna os dados mais recentes imediatamente Retorne os dados mais antigos imediatamente
Não há dados no buffer Retornar quando bloqueado para dados Retorne nulo imediatamente Retorne nulo imediatamente Esperar 2000 ms, retornar nulo se não houver dados, retornar nulo se houver dados
A conexão WebSocket é desconectada ou reconectada pelo subjacente read() função retorna a cadeia vazia, ou seja: , e write() função retorna 0. A situação é detectada. Você pode fechar a conexão usando a função close(), ou se você tiver configurado a reconexão automática, você não precisa fechá-la, o sistema subjacente irá reconectá-la automaticamente.

Objeto

Marque (adressos) Marque (endereço, tempo limite)

Endereço solicitado. Endereço verdade cordel segundos de tempo de espera, tempo de espera Falso Número

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

Exemplo de chamada de função Dial:

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

Para acessar a interface WebSocket do Binance:

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

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

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

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

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

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

Acesso à interface do ticker do WebSocket OKX:

var ws = null               

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

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

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

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

Acesso à interface do ticker do WebSocket da Huobi:

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

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

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

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

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

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

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

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

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

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

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

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

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

Para acessar a interface de autenticação do WebSocket OKX:

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

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

O objeto de conexão devolvido pela função Dial quando se conecta a um banco de dados tem duas funções de método que são exclusivas para ele:

  • exec(sqlString): Usado para executar instruções SQL de uma forma semelhante aoDBExec() function.
  • fd()Ofd()função retorna uma manipulação (por exemplo, a variável manipulação é manipulação) a ser usada por outros fios para reconectar (mesmo que o objeto criado por Dial já tenha sido fechado pela execução doclose()A função de fechar a ligação) passando a alça para oDial()função, por exemplo,Dial(handle)Conexão de reutilização. O seguinte é um exemplo da função Dial ligando a umsqlite3 database.

Detalhes doaddressParâmetro, separado pelo|símbolo após o endereço normal:wss://ws.okx.com:8443/ws/v5/publicSe houver|caracteres na cadeia de parâmetros, então||A parte depois disso é algumas configurações de parâmetros de função, e cada parâmetro está conectado com&A primeira é a dess5Os parâmetros de substituição e de compressão podem ser definidos em conjunto do seguinte modo:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Funções suportadas pelo parâmetro de endereço da função Dial Descrição do parâmetro
Parâmetros relacionados com a compressão de dados do protocolo WebSocket: compress=parâmetro valor compress é o método de compressão, comprimir opções de parâmetros são: gzip_raw, gzip, etc. Se o método gzip não é padrão gzip, você pode usar o método estendido: gzip_raw
Parâmetros relacionados com a compressão de dados do protocolo WebSocket: mode=valor do parâmetro modo é o modo de compressão, o parâmetro de modo pode ser duplo, enviar, recv. dual é compressão bidirecional, enviar dados comprimidos, receber dados comprimidos. enviar é enviar dados comprimidos. recv é receber dados comprimidos, descompressão local.
O protocolo WebSocket define os parâmetros de auto-reconexão relacionados: reconnect=valor do parâmetro reconnect é se deve definir reconnect, reconnect=true é para habilitar reconnect. O padrão é não reconnect quando este parâmetro não é definido.
O protocolo WebSocket define os parâmetros de auto-reconexão subjacentes: intervalo=valor do parâmetro o intervalo é o intervalo de tentativa de reinicialização, em milissegundos, o intervalo=10000 é o intervalo de tentativa de reinicialização de 10 segundos, o padrão é de 1 segundo quando não está definido, ou seja, o intervalo=1000.
O protocolo WebSocket define os parâmetros relacionados com a reconexão automática subjacente: carga útil=valor do parâmetro A carga útil é a mensagem de assinatura que precisa ser enviada quando o WebSocket é reconectado, por exemplo: payload=okokok.
Parâmetros relacionados com calças5 proxy: proxy=valor do parâmetro proxy é a configuração de proxy ss5, formato de valor do parâmetro: socks5://name:pwd@192.168.0.1:1080, nome é o nome de usuário do servidor ss5, pwd é a senha de login do servidor ss5, 1080 é a porta de serviço ss5.

ODial()A função só é suportada para negociação ao vivo. Ao se conectar a um banco de dados usando a função Dial, a cadeia de conexão é escrita com referência ao projeto de driver de linguagem go para cada banco de dados.

Base de dados suportadas Projetos de impulso Corda de ligação Observações
Sqlite3 github.com/mattn/go-sqlite3 sqlite3://file:test.db?cache=shared&mode=memory Osqlite3://Prefixo indica que está a ser utilizado um banco de dados sqlite3, exemplo de chamada:Dial("sqlite3://test1.db")
mysql github.com/go-sql-driver/mysql mysql://username:yourpassword@tcp(localhost:3306)/a sua base de dados?charset=utf8mb4
Postgres github.com/lib/pq postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432
Cliquehouse github.com/ClickHouse/clickhouse-go - Não, não, não, não.

Por favor, note que quando opayloadO conteúdo definido noaddressParâmetro contém caracteres=ou outros caracteres especiais, pode afetar a análise doaddressParâmetro doDialfunção, como o exemplo a seguir.

Exemplo de chamada de interface privada do websocket backPack Exchange:

var client = null

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

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

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

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

function onexit() {
    client.close()
}

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

A seguinte chamada no código funciona bem:

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

Se você escrever isso diretamente empayload, não funcionará corretamente, por exemplo:

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

Atualmente, apenas o JavaScript suporta o uso domqtt, nats, amqp, ekafkaO código de estratégia da linguagem JavaScript é usado como exemplo para mostrar o uso dos quatro protocolos:mqtt, nats, amqp, ekafka:

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

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

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

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

        Sleep(1000)
    }
}

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

Referência de documentação pormenorizada:Explorando FMZ: Prática do protocolo de comunicação entre as estratégias de negociação ao vivo

HttpQuery

Envie um pedido HTTP.

Retorna os dados de resposta da solicitação.JSONstring, ele pode ser analisado peloJSON.parse()função naJavaScriptA estratégia linguística, e pelajson::parse()função naC++Se o depuração for definido como verdadeiro na estrutura de opções, o valor de retorno é um objeto (JSON); se o depuração for definido como falso, o valor de retorno é uma cadeia. cadeia, objeto

HttpQuery (URL) HttpQuery ((url, opções)

URL de solicitação HTTP. URL do endereço verdade cordel As configurações relacionadas com solicitações HTTP, por exemplo, podem ser estruturadas da seguinte forma:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    profile: "chrome_103",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • Perfil: Usado para simular navegadortlsimpressões digitais. As configurações suportadas incluem as seguintes opções: Chrome_:"chrome_103", "chrome_104", "chrome_105", "chrome_106", "chrome_107", "chrome_108", "chrome_109", "chrome_110", "chrome_111", "chrome_112", "chrome_117"- Não. Safari_:"safari_15_6_1", "safari_16_0", "safari_ipad_15_6", "safari_ios_15_5", "safari_ios_15_6", "safari_ios_16_0"- Não. Firefox_:"firefox_102", "firefox_104", "firefox_105", "firefox_106", "firefox_108", "firefox_110", "firefox_117"- Não. Opera_:"opera_89", "opera_90", "opera_91"- Não. - Não, não, não."zalando_android_mobile", "zalando_ios_mobile"- Não. - Não."nike_ios_mobile", "nike_android_mobile"- Não. arranha-céus:"cloudscraper"- Não. - Sim, sim."mms_ios"- Não. mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2"- Não. Confirmado:"confirmed_ios", "confirmed_android"- Não. Está bem."okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • Debug: Quando estiver definido paratrue, oHttpQuerychamada de função retorna a mensagem de resposta completa.false, apenas os dados doBodyda mensagem de resposta é devolvida.
  • Timeout: definição de timeout, definida em 1000 significa 1 segundo de timeout.
  • Charset: Suporta a transcodificação dos dados de resposta solicitados, como GB18030. Todos os campos nesta estrutura são opcionais, por exemplo, oprofilecampo pode ser deixado de fora.

opções Falso Objeto

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

Um exemplo de acesso à interface API de ticker pública OKX.

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

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

A função HttpQuery usa configurações de proxy.

OHttpQuery()Função só suportaJavaScript, C++linguagem,PythonA linguagem pode utilizar ourllibA biblioteca para enviar solicitações HTTP diretamente.HttpQuery()O sistema é utilizado principalmente para aceder às interfaces da troca que não requerem uma assinatura, como as interfaces públicas como as informações do ticker.HttpQuery()O sistema de backtesting pode ser utilizado para enviar solicitações (apenasGETO backtesting limita-se a utilizar 20 visitas a diferentesURLs, eHttpQuery()As visitas cacharão os dados.URLA segunda vez em que se acede aoHttpQuery()A função retorna os dados em cache e não ocorrem mais solicitações reais de rede.

Não, não, não, não.

HttpQuery_Go

Envia uma solicitação HTTP, uma versão assíncrona doHttpQuery function.

OHttpQuery_Go()função imediatamente retorna um objeto concorrente que pode ser usado para obter o resultado de uma solicitação HTTP usando owaitMétodo deJSON.parse()função pode ser usado para analisar oJSON.parse()função naJavaScriptestratégia linguística.
Objeto

HttpQuery_Go (URL) HttpQuery_Go ((url, opções)

URL de solicitação HTTP. URL do endereço verdade cordel As configurações relacionadas com solicitações HTTP, por exemplo, podem ser estruturadas da seguinte forma:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    // profile: "",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • Perfil: Usado para simular navegadortls fingerprints.
  • Debug: Quando estiver definido paratrue, esteHttpQuery_Gochamada de função retorna a mensagem de resposta completa.false, apenas os dados doBodyda mensagem de resposta é devolvida.
  • Timeout: definição de timeout, definida em 1000 significa 1 segundo de timeout. Todos os campos nesta estrutura são opcionais, por exemplo, oprofilecampo pode ser deixado de fora.

opções Falso Objeto

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

Acesso assíncrono à interface pública da bolsa para dados agregados de ticker.

OHttpQuery_Go()Função só suportaJavaScript, oPythonA linguagem pode ser utilizada com ourllibA biblioteca para enviar solicitações HTTP diretamente.HttpQuery_Go()O sistema de transferência de dados é utilizado principalmente para aceder a interfaces que não requerem uma assinatura na bolsa, tais como interfaces públicas como informações de ticker.HttpQuery_Gofunção não é suportada no sistema de backtesting.

Não, não, não, não.

Codificação

Esta função codifica os dados de acordo com os parâmetros transmitidos.

OEncodeFunção que retorna os dados após codificação e criptografia. cordel

Encode ((algo, inputFormat, outputFormat, dados) Encode ((algo, inputFormat, outputFormat, dados, chaveFormat, chave)

O parâmetroalgoé o algoritmo utilizado no cálculo da codificação.raw(não é utilizado algoritmo), o"sinal", 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, 2b.512, blake2s.128, blake2s.256 O parâmetro.algotambém suporta: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk, codificar e decodificar strings.algotambém suporta: ed25519 algoritmo. Suporta o uso de diferentes algoritmos de hash, por exemplo, o parâmetroalgopode ser escrito como ed25519.md5, ed25519.sha512, etc. Ele suportaed25519.seedCalculo. algo verdade cordel Utilizado para especificar o formato de dados dodataParâmetro.inputFormatO parâmetro pode ser definido como um dos seguintes:raw, hex, base64, string. raw significa que os dados são dados brutos, hex significa que os dadoshexcodificado, base64 significa que os dados sãobase64codificado, e string significa que os dados são uma cadeia. inputFormat verdade cordel Utilizado para especificar o formato de dados da saída.outputFormatO parâmetro pode ser definido como um dos seguintes:raw, hex, base64, string. raw significa que os dados são dados brutos, hex significa que os dadoshexcodificado, base64 significa que os dados sãobase64codificado, e string significa que os dados são uma cadeia. outputFormat verdade cordel O parâmetrodatasão os dados a processar. dados verdade cordel Utilizado para especificar o formato de dados dokeyParâmetro.keyO parâmetro pode ser definido como um dos seguintes:raw, hex, base64, string. raw significa que os dados são dados brutos, hex significa que os dadoshexcodificado, base64 significa que os dados sãobase64codificado, e string significa que os dados são uma cadeia. KeyFormat Falso cordel O parâmetrokeyé a chave secreta usada paraHMACO parâmetrokeyé exigido quando o parâmetroalgoestá definido emsignousignTx. OkeyParâmetro não utilizado paraHMACcriptografia quando oalgoO parâmetro é definido como raw (porque o algoritmo deve ser especificado para a criptografia HMAC). Chave Falso cordel

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

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

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

Exemplo de chamada de função Encode.

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

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

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

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

O parâmetroalgotambém suporta: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk para codificar e decodificar cadeias.

OEncode()A função só é suportada para negociação ao vivo.keyekeyFormatOs parâmetros não são transmitidos, entãokeyNão se utiliza encriptação.

UnixNano

Obtenha o carimbo de tempo do momento atual.

OUnixNano()A função retorna o selo de tempo do nanossegundo. Número

UnixNano ((()

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

Se precisar de marcas de tempo de milissegundos, pode usar o seguinte código:

Não, não, não.

Unix

Obtenha o carimbo do momento atual no segundo nível.

Devolve a marca de tempo de segundo nível. Número

Unix ((()

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

Não, não, não, não.

GetOS

Obter as informações do sistema do dispositivo onde o docker está localizado.

Informações do sistema. cordel

GetOS ((()

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

Por exemplo, uma chamada para oGetOS()função para um docker em execução noMac OSsistema operacional pode retornar:darwin/amd64Porque os computadores da Apple têm várias arquiteturas de hardware.darwiné o nome doMac OS system.

MD5

Computa o hash MD5 do parâmetrodata.

Valor hash MD5. cordel

MD5 (dados)

Os dados que requerem cálculo MD5. dados verdade cordel

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

Chamando oMD5("hello world")função, o valor de retorno é:5eb63bbbe01eeed093cb22bb8f5acdc3.

Não, não, não, não.

DBExec

Funções de interface de banco de dados.

Um objeto que contém o resultado da execução de umQuadradodeclaração, por exemplo:


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

Objeto

DBExec ((sql)

Quadradocadeia de instruções. Quadrado verdade cordel

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

Suporte de base de dados em memória, paraDBExecParâmetros funcionais, se:Quadradodeclaração começa com:É adequado para operações de banco de dados que não requerem salvação persistente, por exemplo:

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

Crie uma mesa.

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

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

Adicionar, excluir, verificar e alterar os registos na tabela.

A funçãoDBExec()Pode operar o banco de dados de negociação ao vivo (base de dados SQLite) através da passagem de parâmetros.SQLiteO sistema reservou tabelas na base de dados de negociação ao vivo:kvdb, cfg, log, profit, chart, não operar nessas mesas.TransaçõesO sistema de gestão de dados não é suportado e não é recomendado executar tais operações, que podem causar conflitos no sistema.DBExec()A função só é suportada para negociação ao vivo.

Não, não, não.

UUID

Crie um UUID.

UUID de 32 bits. cordel

UUID (()

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

OUUID()A função suporta apenas negociação ao vivo.

EventLoop

Ouça para os eventos, ele retorna quando há qualquerWebSocketdados legíveis ou tarefas simultâneas, tais como:exchange.Go(), HttpQuery_Go(), etc. são concluídas.

Se o objeto devolvido não for um valor nulo, oEventO conteúdo do retorno é o tipo de desencadeador de evento.

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

Objeto

EventLoop ((() EventLoop (Timeout)

O parâmetrotimeouté a definição de timeout, em milissegundos.timeoutespera que um evento ocorra antes de retornar se for definido como 0. Se for maior que 0, define o evento para esperar por um timeout e retorna o evento mais recente imediatamente se for menor que 0. tempo de espera Falso Número

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

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

A primeira chamada para oEventLoop()função no código inicializa o mecanismo para o evento ouvido, e se o primeiroEventLoop()O sistema subjacente envolve uma estrutura de fila que cacheia um máximo de 500 chamadas de evento.EventLoop()função não é chamada a tempo de tirá-los durante a execução do programa, mais tarde eventos callbacks fora do 500 cache serão perdidos.EventLoop()função não afetam a fila de cache do sistema WebSocket subjacente ou os caches de funções simultâneas, tais comoexchange.Go()Para estes caches, ainda é necessário usar os respectivos métodos para recuperar os dados.EventLoop()função para dados que foram recuperados antes doEventLoop()A função retorna os resultados.EventLoop()A estratégia é baseada em eventos, que são gerados por eventos, que são gerados por eventos, que são gerados por eventos.EventLoop()função retorna um evento, apenas atravessa todas as fontes de dados.exchange.Go()tentam obter dados.EventLoop()A função suporta apenas negociação ao vivo. Ouça os eventos no thread principal quando chamado da função principalmain(). nas estratégias escritas noJavaScriptA linguagem, othreading.Thread()função cria um thread, que também pode ser chamado na função de execução do threads, para ouvir eventos no thread atual.

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

__ Servir

O__ServeA função é usada para criar o serviço HTTP, o serviço TCP e o serviço Websocket (baseado no protocolo HTTP).

Retorna uma cadeia que registra o endereço IP e a porta do serviço criado.127.0.0.1:8088, [::]:8089.

cordel

__Serve ((serveURI, manipulador) __Serve ((serveURI, manipulador,...args)

OserveURIO parâmetro é usado para configurar o protocolo, endereço IP, porta e outras configurações da ligação do serviço, tais comohttp://0.0.0.0:8088?gzip=true, isto é,http://:8088?gzip=true.

  • Protocolo TCPserveURIdefinição de parâmetros, tais comotcp://127.0.0.1:6666?tls=true; pode adicionar certificados e chaves privadas, tais comotls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Protocolo HTTPserveURIconfigurações de parâmetros, tais como:http://127.0.0.1:6666?gzip=true; pode definir as configurações de compressão:gzip=true- Não. OserveURIParâmetro é usado para Https, tais comohttps://127.0.0.1:6666?tls=true&gzip=truePode acrescentarcert_pemecert_key_pemParâmetros para carregar o certificado.

ServirURI verdade cordel OhandlerO parâmetro é usado para passar na função de processamento de roteamento (protocolo HTTP), função de processamento de mensagens (protocolo TCP) e função de processamento de fluxo (Websocket). A função de chamada de volta transmitida pelo parâmetrohandlerPode definir vários parâmetros, o primeiro parâmetro é o objeto ctx (objeto de contexto).

manipulador verdade função O parâmetro real da função callback passado como o parâmetrohandlerPode haver vários parâmetrosarg, por exemplo:

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

Os parâmetros1, 2, 3Passado em quando chamar o__Serve()função correspondem aos parâmetrosa, b, cPassado na função de chamada de volta.

arg Falso cadeia, número, bool, objeto, matriz, função, valor nulo e outros tipos suportados pelo sistema

function main() {
    let httpServer = __Serve("http://:8088?gzip=true", function (ctx) {
        Log("http connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        let path = ctx.path()
        if (path == "/") {
            ctx.write(JSON.stringify({
                path: ctx.path(),
                method: ctx.method(),
                headers: ctx.headers(),
                cookie: ctx.header("Cookie"),
                remote: ctx.remoteAddr(),
                query: ctx.rawQuery()
            }))
        } else if (path == "/tickers") {
            let ret = exchange.GetTickers()
            if (!ret) {
                ctx.setStatus(500)
                ctx.write(GetLastError())
            } else {
                ctx.write(JSON.stringify(ret))
            }
        } else if (path == "/wss") {
            if (ctx.upgrade("websocket")) { // upgrade to websocket
                while (true) {
                    let r = ctx.read(10)
                    if (r == "") {
                        break
                    } else if (r) {
                        if (r == "ticker") {
                            ctx.write(JSON.stringify(exchange.GetTicker()))
                        } else {
                            ctx.write("not support")
                        }
                    }
                }
                Log("websocket closed", ctx.remoteAddr())
            }
        } else {
            ctx.setStatus(404)
        }
    })
    let echoServer = __Serve("tcp://:8089", function (ctx) {
        Log("tcp connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        while (true) {
            let d = ctx.read()
            if (!d) {
                break
            }
            ctx.write(d)
        }
        Log("connect closed")
    })
    Log("http serve on", httpServer, "tcp serve on", echoServer)
    
    for (var i = 0; i < 5; i++) {
        if (i == 2) {
            // test Http
            var retHttp = HttpQuery("http://127.0.0.1:8088?num=123&limit=100", {"debug": true})
            Log("retHttp:", retHttp)
        } else if (i == 3) {
            // test TCP
            var tcpConn = Dial("tcp://127.0.0.1:8089")
            tcpConn.write("Hello TCP Server")
            var retTCP = tcpConn.read()
            Log("retTCP:", retTCP)
        } else if (i == 4) {
            // test Websocket
            var wsConn = Dial("ws://127.0.0.1:8088/wss|compress=gzip")
            wsConn.write("ticker")
            var retWS = wsConn.read(1000)
            Log("retWS:", retWS)
            // no depth
            wsConn.write("depth")
            retWS = wsConn.read(1000)
            Log("retWS:", retWS)
        }
        Sleep(1000)
    }
}
# Unsupported
// Unsupported
  • Esta função suporta apenas estratégias da linguagem JavaScript.
  • O tópico de serviço está isolado do escopo global, por isso não suporta fechamentos ou referências a variáveis externas, funções personalizadas, etc.; no entanto, pode chamar todas as funções da API da plataforma.
  • OWebsocketVocê pode definir um ramo de roteamento no caminho e projetar o código de implementação paraWebsocketPode consultar o código de exemplo nesta secção.

A função de chamada de volta transmitida pelo parâmetrohandlerrecebe umctxParâmetro.ctxParâmetro é um objeto de contexto utilizado para obter e escrever dados, com os seguintes métodos:

  • ctx.proto (() Aplicado ao protocolo Http/TCP, retorna o nome do protocolo quando chamado.HTTP/1.1, tcp.
  • ctx.host() Aplicado ao protocolo HTTP, ele retorna informações de host quando chamado endereço IP e porta.
  • Ctx.path (em inglês) Aplicado ao protocolo HTTP, retorna o caminho de solicitação quando chamado.
  • Ctx.query (chave) Aplicado ao protocolo HTTP, retorna o valor correspondente à chave na consulta na solicitação quando chamada.http://127.0.0.1:8088?num=123, e a função de processamento de chamada de retorno transmitida pelo parâmetrohandlerretorno"123"Quando?ctx.query("num")é chamado.
  • ctx.rawQuery() Aplicado ao protocolo HTTP, quando chamado, retorna a consulta original na solicitação (a consulta da solicitação HTTP).
  • Ctx.header (s) Aplicado ao protocolo Http, e retorna as informações do cabeçalho da solicitação na solicitação quando chamada.
  • Ctx.header (chave) Aplicado ao protocolo HTTP, ele retorna o valor de uma chave no cabeçalho de solicitação especificado quando chamado.User-Agentnos cabeçalhos do presente pedido:ctx.header("User-Agent").
  • Ctx.método Aplicado ao protocolo Http, retorna o método de solicitação quando chamado, comoGET, POST, etc.
  • Ctx.corpo Aplicado ao pedido POST do protocolo HTTP, e retorna o corpo do pedido quando chamado.
  • ctx.setHeader ((chave, valor) Aplicado ao protocolo Http para definir as informações de cabeçalho de solicitação da mensagem de resposta.
  • ctx.setStatus (código) Aplicado ao protocolo Http, define o código de status da mensagem Http. Normalmente, o código de status Http é definido no final do ramo de roteamento. O valor padrão é 200.
  • ctx.remoteAddr() Aplicado ao protocolo Http/TCP, retorna o endereço do cliente remoto e a porta na solicitação quando chamada.
  • ctx.localAddr() Aplicado ao protocolo Http/TCP, retorna o endereço local e a porta do serviço quando chamado.
  • ctx.upgrade ((websocket) Aplicado à implementação do protocolo Websocket baseado no protocolo Http, comutando octxobjeto de contexto para o protocolo Websocket; devolvendo um valor booleano (verdadeiro) se a mudança for bem-sucedida e um valor booleano (falso) se falhar.
  • ctx.read ((timeout_ms) Aplicado à implementação do protocolo Websocket/protocolo TCP baseado no protocolo HTTP, lê dados da conexão Websocket e conexão TCP.readmétodo não é suportado no protocolo HTTP comum. Você pode especificar o parâmetro timeouttimeout_msem milissegundos.
  • Ctx.write (s) Aplicado ao protocolo HTTP/TCP, usado para escrever dados de cadeia.JSON.stringify()para codificar o objeto JSON em uma cadeia de caracteres e, em seguida, escrevê-lo.WebSocketprotocolo, você pode usar este método para passar a cadeia codificada para o cliente.

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

_G

A estrutura de dados é uma tabela KV que é salvada permanentemente no arquivo de banco de dados local do docker.

Dados de valores-chave salvos de forma persistentek-vpares de chaves e valores. cadeia, número, bool, objeto, matriz, valor nulo

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

O parâmetroké o nome da chave no par chave-valor guardado e não é sensível a minúsculas e minúsculas. k Falso string, valor nulo O parâmetrové o valor chave no par chave-valor salvo, que pode ser qualquer dado que possa serJSONserializado. v Falso cadeia, número, bool, objeto, matriz, valor nulo

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

Uma base de dados separada para cada negociação em tempo real, os dados salvos pelo_G()A função estará sempre lá se a estratégia for reiniciada ou o docker parar de funcionar._G()Quando se utiliza o_G()Função para persistir os dados salvos, deve ser usado razoavelmente de acordo com a memória e espaço no disco rígido do dispositivo de hardware, e não deve ser abusado. Ao ligar para o_G()A função é executada em uma negociação ao vivo e não são passados parâmetros, o_G()função retorna oIdO número de transacções em tempo real._G()função, o parâmetrové passado como nulo para indicar a exclusão dok-vQuando se chama o_G()função, apenas o parâmetroké passado na cadeia, e o_G()função retorna o valor da chave correspondente ao parâmetro guardadok. Ao ligar para o_G()função, apenas o parâmetroké passado em um valor nulo, indicando que todos os registos dok-vQuando o par de chaves-valores é excluído.k-vOs pares chave-valor foram salvos persistentemente, o_G()função é chamada novamente, passando no nome da chave que foi salvada persistentemente como parâmetrok. Passando o novo valor da chave como parâmetrovVou atualizar isso.k-vPares chave-valor.

Não, não, não, não.

_D

Converte marcas de tempo de milissegundos ouDateObjetos para cordas de tempo.

Uma cadeia de tempo. cordel

_D() _D (horário) _D (horário, fmt)

Marca de tempo de milissegundos ouDateObjeto. Marca de data e hora Falso Número, objeto Formatar string,JavaScriptformato padrão da língua:yyyy-MM-dd hh:mm:ss; Pythonformato padrão da língua:%Y-%m-%d %H:%M:%S; C++formato padrão da língua:%Y-%m-%d %H:%M:%S- Não. fmt Falso cordel

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

Obter e imprimir a cadeia de tempo atual:

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

O carimbo de data e hora é 1574993606000, utilizando a conversão de código:

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

Formatação com o parâmetrofmté diferente paraJavaScript, Python, eC++línguas, conforme indicado nos seguintes exemplos:

Retorna a cadeia de tempo atual sem passar quaisquer parâmetros._D()função naPythonestratégia, você precisa estar ciente de que os parâmetros passados são carimbos de tempo de segundo nível (carimbos de tempo de nível de milissegundos nas estratégias JavaScript e C ++, onde 1 segundo é igual a 1000 milissegundos)._D()Função para analisar uma cadeia de tempo com uma marca de tempo legível na negociação ao vivo, você precisa prestar atenção ao fuso horário e configuração de hora do sistema operacional onde o programa docker está localizado._D()A função analisa um carimbo de tempo em uma cadeia de tempo legível dependendo do tempo do sistema docker.

Não, não, não, não.

_N

Formatar um número com vírgula flutuante.

O número de vírgula flutuante formatado de acordo com a definição de precisão. Número

_N() _N (número) _N (número, precisão)

O número de vírgula flutuante que precisa ser formatado. Número verdade Número A definição de precisão para a formatação, o parâmetroprecisioné um inteiro, e o parâmetroprecisionpadrões para 4. precisão Falso Número

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

Por exemplo,_N(3.1415, 2)eliminará o valor após3.1415duas casas decimais e a função retorna3.14.

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

Se você precisa mudar todos os dígitos N à esquerda do ponto decimal para 0, você pode escrever assim:

O parâmetroprecisionPode ser um número inteiro positivo, negativo inteiro.

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

_C

Tente novamente a função de tolerância a falhas da interface.

Valor de retorno da função de chamada de retorno quando executada. Todos os tipos são suportados pelo sistema excetovalor lógico falsoevalor nulo.

_C (((pfn) - Não, não, não.

O parâmetropfné uma referência de função, que é umaFunção de recallback- Não. pfn verdade função Parâmetros paraFunções de recallback, pode haver mais de um parâmetroargTipo e número de parâmetrosargDepende dos parâmetros doFunção de recallback- Não. arg Falso string, number, bool, object, array, function, todos os tipos são suportados pelo sistema, como valores nulos

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

Para funções tolerantes a erros sem parâmetros:

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

Para funções com parâmetros tolerantes a erros:

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

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

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

Também pode ser usado para tolerância a falhas de funções personalizadas:

O_C()função continuará a chamar a função especificada até que retorne com sucesso (a função referenciada pelo parâmetropfnretornozeroouFalsoQuando for chamado, tentará ligar novamente.pfnPor exemplo:_C(exchange.GetTicker). O intervalo de tentativa de reinicialização padrão é de 3 segundos, você pode chamar o_CDelay()função para definir o intervalo de reatendimento._CDelay(1000)A utilização de um dispositivo de ensaio para alterar o intervalo de ensaio_C()Função para 1 segundo. A tolerância de falhas pode ser feita para, mas não se limita a, as seguintes funções:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()Todos podem ser chamados pelo_C()A função de tolerância a falhas._C()a função não é limitada à tolerância de falha da função acima listada, o parâmetropfné uma referência de função em vez de uma chamada de função. Observe que é_C(exchange.GetTicker), não_C(exchange.GetTicker()).

_Cruzada

Retorna o número de períodos de intersecção da matrizarr1e a matrizarr2.

Número de períodos transversais da matrizarr1e a matrizarr2- Não. Número

_Cross ((arr1, arr2)

Os elementos são matrizes de tiponumber- Não. arr1 verdade matriz Os elementos são matrizes de tiponumber- Não. arr2 verdade matriz

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

Um conjunto de dados pode ser simulado para testar a função _Cross ((Arr1, Arr2):

Se o valor de retorno do_Cross()Se a função é um número positivo, indica o período de penetração ascendente, se é um número negativo, indica o período de penetração descendente, 0 significa o mesmo que o preço atual.Análise e instruções de utilização sobre a função integrada.

JSONParse

A funçãoJSONParse()é usado para analisarJSON strings.

JSONObjeto. Objeto

JSONParse (s)

JSONA corda. s verdade cordel

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

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

As cadeias de caracteres JSON com grandes valores podem ser analisadas corretamente, e ele irá analisar grandes valores como tipos de cadeia.JSONParse()função não é suportada no sistema de backtest.

Registo