Sumber dimuat naik... memuat...

Global

Versi

Mengembalikan nombor versi semasa sistem.

Nombor versi sistem semasa, seperti:3.6. senar

Versi ((()

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

Nombor versi sistem adalah nombor versi program docker.

Tidur

Fungsi tidur, menyebabkan program berhenti untuk tempoh masa.

Tidur (millisecond)

PeraturanmillisecondParameter digunakan untuk menetapkan tempoh tidur dan bilangan milidetik. Milisaat betul nombor

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

Sebagai contoh, apabila melaksanakanSleep(1000)Ia menyokong operasi dengan waktu tidur kurang daripada 1 milisaat, contohnya menetapkanSleep(0.1). Ia menyokong parameter minimum0.000001, iaitu hibernasi nanosegund, di mana 1 nanosegund sama dengan1e-6Milisaat. Apabila menulis strategi dalamPythonBahasa,Sleep(millisecond)fungsi harus digunakan untuk pengundian selang, masa-ke-menunggu operasi.time.sleep(second)fungsiPython...timePerpustakaan. Ini kerana menggunakantime.sleep(second)fungsi dalam strategi membuat program strategi menunggu untuk tempoh masa sebenarnya apabila backtesting (tidak melangkau pada siri masa sistem backtesting), jadi ia menyebabkan strategi untuk backtesting sangat perlahan.

IsVirtual

Tentukan sama ada persekitaran menjalankan strategi adalah sistem backtesting.

Strategi mengembalikan nilai sebenar, contohnya:trueapabila dijalankan dalam persekitaran sistem backtesting. Strategi mengembalikan nilai palsu, contohnya:falseapabila dijalankan dalam persekitaran perdagangan langsung. bool

IsVirtual ((()

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

Tentukan sama ada persekitaran semasa adalah sistem backtesting, yang digunakan untuk serasi dengan perbezaan antara backtesting dan perdagangan langsung.

Surat

Hantar e-mel.

Penghantaran e-mel yang berjaya mengembalikan nilai sebenar, contohnya,true, dan penghantaran gagal mengembalikan nilai palsu, contohnya,false. bool

Mail ((smtpServer, smtpUsername, smtpPassword, mailTo, tajuk, badan)

Digunakan untuk menentukanSMTPalamat perkhidmatan penghantar e-mel. smtpServer betul senar Digunakan untuk menentukan alamat e-mel penghantar e-mel. smtpNama pengguna betul senar PeraturanSMTPkata laluan untuk peti mel penghantar e-mel. smtpPassword betul senar Digunakan untuk menentukan alamat e-mel penerima e-mel. mailTo betul senar Alamat e-mel. tajuk betul senar Email badan. badan betul senar

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

PeraturansmtpPasswordparameter menetapkan kata laluan untukSMTPPerkhidmatan, bukan kata laluan kotak mel. Apabila menetapkansmtpServerparameter, jika anda perlu menukar port, anda boleh menambah nombor port terus dalam parametersmtpServerContohnya: QQ mailsmtp.qq.com:587, yang tersedia untuk ujian. Jika kesalahan dilaporkan:unencryped connection, anda perlu mengubahsuaismtpServerdaripadaMailFormat parameter adalah:ssl://xxx.com:xxx, contohnya,sslkaedahSMTPuntuk surat QQ:ssl://smtp.qq.com:465atausmtp://xxx.com:xxx. Ia tidak berfungsi dalam sistem backtesting.

{@fun/Global/Mail_Go Mail_Go}

Mail_Go

Versi asinkronMail function.

PeraturanMail_Gofungsi mengembalikan objek serentak dengan serta-merta, dan anda boleh menggunakanwaitkaedah objek serentak itu untuk mendapatkan hasil penghantaran mel. Penghantaran mel yang berjaya mengembalikan nilai yang benar, contohnya,true, dan penghantaran gagal mengembalikan nilai palsu, contohnya,false. objek

Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, tajuk, badan)

Ia digunakan untuk menentukanSMTPalamat perkhidmatan penghantar e-mel. smtpServer betul senar Ia digunakan untuk menentukan alamat e-mel penghantar e-mel. smtpNama pengguna betul senar PerkhidmatanSMTPkata laluan untuk peti mel penghantar e-mel. smtpPassword betul senar Ia digunakan untuk menentukan alamat e-mel penerima e-mel. mailTo betul senar Alamat e-mel. tajuk betul senar E-mel badan. badan betul senar

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.

Ia tidak berfungsi dalam sistem backtesting.

{@fun/Global/Mail Mail}

SetErrorFilter

Log ralat penapis.

SetErrorFilter ((filter)

Senar ungkapan biasa. penapis betul senar

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

Menyaring kesilapan biasa.

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

Menapis mesej ralat antara muka.

Log ralat yang sepadan dengan ungkapan biasa ini tidak akan dimuat naik ke sistem log. Anda boleh memanggilnya beberapa kali (tidak ada had pada bilangan kali) untuk menetapkan pelbagai syarat penapis. Ungkapan biasa yang ditetapkan beberapa kali akan terkumpul dan berkuat kuasa pada masa yang sama. Anda boleh menetapkan rentetan kosong untuk menetapkan semula ungkapan biasa yang digunakan untuk menapis log ralat:SetErrorFilter(""). log disaring tidak lagi ditulis ke fail pangkalan data yang sepadan dengan ID perdagangan hidup dalam direktori docker untuk mengelakkan laporan ralat yang kerap dari membengkak fail pangkalan data.

GetPid

Dapatkan ID proses dagangan secara langsung.

Kembalikan ID proses dagangan secara langsung. senar

GetPid ((()

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

GetLastError

Dapatkan mesej ralat terakhir.

Mesej ralat terakhir. senar

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

Ia tidak berfungsi dalam sistem backtesting.

GetCommand

Dapatkan arahan strategi interaksi.

Format arahan yang dikembalikan adalahControlName:Data. ControlNameadalah nama kawalan, danDataadalah data yang dimasukkan ke dalam kawalan. Jika kawalan interaktif tidak mempunyai kotak input, kotak drop-down dan komponen lain (contohnya kawalan butang tanpa kotak input) maka format arahan yang dikembalikan adalahControlName, yang mengembalikan nama kawalan sahaja. senar

DapatkanCommand()

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

Mengesan arahan interaksi dan menggunakanLogfungsi untuk mengeluarkan arahan interaksi apabila dikesan.

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

Sebagai contoh, kawalan interaktif strategi menambah kawalan tanpa kotak input, kawalan interaktif dinamakan:buy, maklumat deskripsi kawalan adalah:buy, yang merupakan kawalan butang. Lanjutkan dengan menambah kawalan dengan kotak input. Kawalan interaktif dinamakan:selldan mesej penerangan kawalan adalah:sell, yang merupakan kawalan interaktif yang merupakan gabungan butang dan kotak input. Kod interaksi direka dalam strategi untuk bertindak balas terhadap kawalan interaksi yang berbeza:

Ia tidak berfungsi dalam sistem backtesting.

GetMeta

Dapatkan nilai Meta ditulis apabila menjana kod pendaftaran strategi.

Metadata. senar

DapatkanMeta

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

Contoh senario aplikasi: PenggunaanMetauntuk mengehadkan jumlah aset yang dikendalikan oleh strategi.

Senario permohonan: perlu melakukan had modal untuk penyewa strategi yang berbeza.Metanilai yang ditetapkan apabila menjana kod pendaftaran tidak boleh melebihi 190 aksara danGetMeta()Jika tiada metadata (Meta) ditetapkan semasa menjana kod pendaftaran strategi,GetMeta()fungsi mengembalikan null. Ia tidak berfungsi dalam sistem backtesting.

Pilih

Untuk primitifSocketakses, menyokongtcp, udp, tls, unixSokong 4 protokol komunikasi popular:mqtt, nats, amqp, kafka. Sokongan untuk menyambung ke pangkalan data:sqlite3, mysql, postgres, clickhouse.

PeraturanDial()fungsi mengembalikan null jika ia masa keluar. panggilan biasa mengembalikan objek sambungan yang mempunyai tiga kaedah:read, writedanclose.readkaedah digunakan untuk membaca data,writekaedah digunakan untuk menghantar data danclosekaedah digunakan untuk menutup sambungan. Peraturanreadkaedah menyokong parameter berikut:

  • Apabila tiada parameter yang diteruskan, ia menyekat sehingga mesej tersedia dan kembali, sepertiws.read().
  • Apabila diteruskan sebagai parameter, unit adalah milidetik, menentukan tempoh masa tunggu mesej.ws.read(2000)menentukan masa lapang dua saat (2000 milidetik).
  • Kedua parameter berikut adalah sah hanya untuk WebSocket: Memindahkan parameter-1bermaksud bahawa fungsi mengembalikan dengan serta-merta, tanpa mengira kehadiran atau ketiadaan mesej, contohnya:ws.read(-1). Memindahkan parameter-2bermaksud bahawa fungsi kembali dengan atau tanpa mesej, tetapi hanya mesej terkini yang dikembalikan, dan mesej yang dipaparkan dibuang.ws.read(-2).

read()Penerangan penyangga fungsi: Data masuk yang didorong oleh protokol WebSocket boleh menyebabkan pengumpulan data jika selang masa antara strategiread()Panggilan fungsi terlalu lama. Data ini disimpan dalam penyangga, yang mempunyai struktur data antrian dengan maksimum 2000. Selepas 2000 melebihi, data terbaru dimasukkan ke dalam penyangga dan data tertua dibersihkan.

Senario Tiada parameter Parameter: -1 Parameter: -2 Parameter: 2000, dalam milidetik
Data yang sudah dalam penyangga Kembalikan data tertua dengan segera Kembalikan data tertua dengan segera Kembalikan data terkini dengan segera Kembalikan data tertua dengan segera
Tiada data dalam buffer Kembali apabila disekat ke data Kembalikan null dengan segera Kembalikan null dengan segera Tunggu 2000 ms, pulangkan null jika tiada data, pulangkan null jika ada data
Sambungan WebSocket diputuskan atau disambungkan semula oleh asas read() fungsi mengembalikan rentetan kosong, iaitu: , dan write() fungsi mengembalikan 0. Situasi dikesan. Anda boleh menutup sambungan menggunakan close() fungsi, atau jika anda telah menetapkan sambungan semula automatik, anda tidak perlu menutupnya, sistem yang mendasari akan menyambungkan semula secara automatik.

objek

Panggil (alamat) Panggil (alamat, masa lapang)

Alamat permintaan. alamat betul senar detik masa henti, masa lapang palsu nombor

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

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

Untuk mengakses antara muka ticker WebSocket 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");
}

Akses kepada OKXs WebSocket ticker antara muka:

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

Akses kepada Huobi WebSocket ticker antara muka:

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

Untuk mengakses OKXs antara muka pengesahan WebSocket:

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

Objek sambungan yang dikembalikan oleh fungsi Dial apabila menyambung ke pangkalan data mempunyai dua fungsi kaedah yang unik kepadanya:

  • exec(sqlString): Digunakan untuk melaksanakan pernyataan SQL dengan cara yang sama denganDBExec() function.
  • fd(): Pertubuhanfd()fungsi mengembalikan pegangan (contohnya, pembolehubah pegangan adalah pegangan) untuk digunakan oleh utas lain untuk menyambung semula (walaupun objek yang dicipta oleh Dial telah ditutup dengan pelaksanaanclose()fungsi untuk menutup sambungan) dengan melewati pemegang ke dalamDial()fungsi, sebagai contoh,Dial(handle)Sambungan penggunaan semula. Berikut adalah contoh fungsi Dial yang menyambung kesqlite3 database.

Perincianaddressparameter, dipisahkan oleh|simbol selepas alamat biasa:wss://ws.okx.com:8443/ws/v5/publicJika ada.|aksara dalam rentetan parameter, kemudian||digunakan sebagai tanda pemisah. Bahagian selepas itu adalah beberapa tetapan parameter fungsi, dan setiap parameter disambungkan dengan&contohnya,ss5Parameter proxy dan mampatan boleh ditetapkan bersama-sama seperti berikut:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Fungsi yang disokong oleh parameter alamat fungsi Dial Penerangan parameter
Parameter yang berkaitan dengan pemampatan data protokol WebSocket: compress=parameter value memampatkan adalah kaedah mampatan, pilihan parameter mampatan adalah: gzip_raw, gzip, dan lain-lain Jika kaedah gzip bukan gzip standard, anda boleh menggunakan kaedah lanjutan: gzip_raw
Parameter yang berkaitan dengan pemampatan data protokol WebSocket: mod=nilai parameter mod adalah mod mampatan, parameter mod boleh menjadi dua, menghantar, recv. dual adalah mampatan dua hala, menghantar data mampat, menerima data mampat. menghantar adalah menghantar data mampat. recv adalah menerima data mampat, dekompresi tempatan.
Protokol WebSocket menetapkan parameter yang berkaitan dengan sambungan semula automatik yang mendasari: reconnect=nilai parameter reconnect adalah sama ada untuk menetapkan reconnect, reconnect=true adalah untuk membolehkan reconnect. lalai adalah tidak reconnect apabila parameter ini tidak ditetapkan.
Protokol WebSocket menetapkan parameter yang berkaitan dengan auto-reconnect yang mendasari: interval=nilai parameter interval adalah selang percubaan semula, dalam milidetik, interval=10000 adalah selang percubaan semula 10 saat, lalai adalah 1 saat apabila ia tidak ditetapkan, iaitu interval=1000.
Protokol WebSocket menetapkan parameter yang berkaitan dengan auto-reconnect yang mendasari: payload=nilai parameter payload adalah mesej langganan yang perlu dihantar apabila WebSocket disambungkan semula, contohnya: payload=okokok.
Parameter yang berkaitan dengan stoking5 proxy: proxy=nilai parameter proxy adalah persediaan proxy ss5, format nilai parameter: socks5://name:pwd@192.168.0.1:1080, nama adalah nama pengguna pelayan ss5, pwd adalah kata laluan masuk pelayan ss5, 1080 adalah port perkhidmatan ss5.

PeraturanDial()Fungsi hanya disokong untuk perdagangan langsung. Apabila menyambung ke pangkalan data menggunakan fungsi Dial, rentetan sambungan ditulis dengan merujuk kepada projek pemandu bahasa go untuk setiap pangkalan data.

Pangkalan data disokong Projek Pemacu Tali sambungan Catatan
Sqlite3 github.com/mattn/go-sqlite3 sqlite3://file:test.db?cache=shared&mode=memory Peraturansqlite3://awalan menunjukkan bahawa pangkalan data sqlite3 sedang digunakan, contoh panggilan:Dial("sqlite3://test1.db")
MySQL github.com/go-sql-driver/mysql mysql://username:yourpassword@tcp(localhost:3306)/database anda?charset=utf8mb4
Pelancongan github.com/lib/pq postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432
rumah klik github.com/ClickHouse/clickhouse-go klikhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase

Sila ambil perhatian bahawa apabilapayloadkandungan yang ditetapkan dalamaddressparameter mengandungi aksara=atau ciri khas lain, ia boleh menjejaskan analisisaddressparameterDialfungsi, seperti contoh berikut.

contoh panggilan antara muka peribadi 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}}")
}

Panggilan berikut dalam kod berfungsi dengan baik:

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

Jika anda menulisnya terus ke dalampayload, ia tidak akan berfungsi dengan baik, sebagai contoh:

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

Pada masa ini, hanya JavaScript menyokong penggunaanmqtt, nats, amqp, dankafkaKod strategi bahasa JavaScript digunakan sebagai contoh untuk menunjukkan penggunaan empat protokol:mqtt, nats, amqp, dankafka:

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

Rujukan dokumentasi terperinci:Menjelajah FMZ: Amalan Protokol Komunikasi Antara Strategi Dagangan Langsung

HttpQuery

Kirim permintaan HTTP.

Mengembalikan data tindak balas permintaan.JSONstring, ia boleh dianalisis olehJSON.parse()fungsi dalamJavaScriptstrategi bahasa, dan olehjson::parse()fungsi dalamC++Jika debug ditetapkan kepada benar dalam struktur pilihan, nilai pulangan adalah objek (JSON); jika debug ditetapkan kepada palsu, nilai pulangan adalah rentetan. senar, objek

HttpQuery ((url) HttpQuery ((url, pilihan)

URL permintaan HTTP. url betul senar Seting yang berkaitan dengan permintaan HTTP, misalnya, boleh disusun seperti berikut:

{
    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
}
  • profil: Digunakan untuk mensimulasikan pelayartlscap jari. Tetapan yang disokong termasuk pilihan berikut: chrome_:"chrome_103", "chrome_104", "chrome_105", "chrome_106", "chrome_107", "chrome_108", "chrome_109", "chrome_110", "chrome_111", "chrome_112", "chrome_117"... Safari_:"safari_15_6_1", "safari_16_0", "safari_ipad_15_6", "safari_ios_15_5", "safari_ios_15_6", "safari_ios_16_0"... Firefox_:"firefox_102", "firefox_104", "firefox_105", "firefox_106", "firefox_108", "firefox_110", "firefox_117"... Opera_:"opera_89", "opera_90", "opera_91"... Zalando:"zalando_android_mobile", "zalando_ios_mobile"... Nike_:"nike_ios_mobile", "nike_android_mobile"... pencakar awan:"cloudscraper"... mms_:"mms_ios"... mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2"... Diperakui:"confirmed_ios", "confirmed_android"... ok."okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • debug: Apabila ia ditetapkan untuktrue, yangHttpQuerypanggilan fungsi mengembalikan mesej jawapan penuh.false, hanya data dalamBodydaripada mesej jawapan dikembalikan.
  • timeout: tetapan timeout, set 1000 bermaksud 1 detik timeout.
  • Charset: Ia menyokong transcoding data tindak balas yang diminta, seperti GB18030. Semua medan dalam struktur ini adalah pilihan, contohnya,profilemedan boleh ditinggalkan.

pilihan palsu objek

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

Contoh mengakses antara muka API ticker awam 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/");
}

Fungsi HttpQuery menggunakan tetapan proksi.

PeraturanHttpQuery()fungsi hanya menyokongJavaScript, C++bahasa,Pythonbahasa boleh menggunakanurllibperpustakaan untuk menghantar permintaan Http secara langsung.HttpQuery()digunakan terutamanya untuk mengakses antara muka pertukaran yang tidak memerlukan tandatangan, seperti antara muka awam seperti maklumat ticker.HttpQuery()boleh digunakan dalam sistem backtesting untuk menghantar permintaan (hanyaGETPercubaan belakang terhad kepada menggunakan 20 lawatan keURLs, danHttpQuery()kunjungan akan cache data.URLdiperolehi untuk kali kedua,HttpQuery()fungsi mengembalikan data yang disimpan dan tiada lagi permintaan rangkaian sebenar berlaku.

{@fun/Global/HttpQuery_Go HttpQuery_Go}

HttpQuery_Go

Menghantar permintaan HTTP, versi asynchronousHttpQuery function.

PeraturanHttpQuery_Go()fungsi segera mengembalikan objek serentak yang boleh digunakan untuk mendapatkan hasil permintaan Http menggunakanwaitkaedahJSON.parse()fungsi boleh digunakan untuk menganalisisJSON.parse()fungsi dalamJavaScriptstrategi bahasa.
objek

HttpQuery_Go (url) HttpQuery_Go ((url, pilihan)

URL permintaan HTTP. url betul senar Seting yang berkaitan dengan permintaan HTTP, misalnya, boleh disusun seperti berikut:

{
    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
}
  • profil: Digunakan untuk mensimulasikan pelayartls fingerprints.
  • debug: Apabila ia ditetapkan untuktrue, iniHttpQuery_Gopanggilan fungsi mengembalikan mesej jawapan penuh.false, hanya data dalamBodydaripada mesej jawapan dikembalikan.
  • timeout: tetapan timeout, set 1000 bermaksud 1 detik timeout. Semua medan dalam struktur ini adalah pilihan, contohnya,profilemedan boleh ditinggalkan.

pilihan palsu objek

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

Akses asynchronous ke antara muka awam pertukaran untuk data ticker agregat.

PeraturanHttpQuery_Go()fungsi hanya menyokongJavaScript, yangPythonbahasa boleh digunakan denganurllibperpustakaan untuk menghantar permintaan Http secara langsung.HttpQuery_Go()digunakan terutamanya untuk mengakses antara muka yang tidak memerlukan tandatangan di bursa, seperti antara muka awam seperti maklumat ticker.HttpQuery_Gofungsi tidak disokong dalam sistem backtesting.

{@fun/Global/HttpQuery HttpQuery}

Enkod

Fungsi ini mengkodkan data mengikut parameter yang dihantar.

PeraturanEncodefungsi mengembalikan data selepas pengekodan dan penyulitan. senar

Encode ((algo, inputFormat, outputFormat, data) Encode ((algo, inputFormat, outputFormat, data, kunciFormat, kunci)

Parameteralgoadalah algoritma yang digunakan dalam pengiraan pengekodan. Tetapan sokongan adalah:raw(tidak ada algoritma yang digunakan), "tanda", tandaTx, 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 Parameter.algojuga menyokong: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk, enkod dan dekod rentetan. Parameteralgojuga menyokong: ed25519 algoritma. Menyokong penggunaan algoritma hash yang berbeza, contohnya parameteralgoboleh ditulis sebagai ed25519.md5, ed25519.sha512, dll. Ia menyokonged25519.seedpengiraan. sesuatu betul senar Digunakan untuk menentukan format datadataparameter.inputFormatparameter boleh ditetapkan sebagai salah satu daripada berikut:raw, hex, base64, string. raw bermaksud data adalah data mentah, hex bermaksud data adalahhexdikodkan, base64 bermaksud data adalahbase64dikodkan, dan string bermaksud data adalah rentetan. inputFormat betul senar Digunakan untuk menentukan format data output.outputFormatparameter boleh ditetapkan sebagai salah satu daripada berikut:raw, hex, base64, string. raw bermaksud data adalah data mentah, hex bermaksud data adalahhexdikodkan, base64 bermaksud data adalahbase64dikodkan, dan string bermaksud data adalah rentetan. outputFormat betul senar Parameterdataadalah data yang akan diproses. data betul senar Digunakan untuk menentukan format datakeyparameter.keyparameter boleh ditetapkan sebagai salah satu daripada berikut:raw, hex, base64, string. raw bermaksud data adalah data mentah, hex bermaksud data adalahhexdikodkan, base64 bermaksud data adalahbase64dikodkan, dan string bermaksud data adalah rentetan. keyFormat palsu senar Parameterkeyadalah kunci rahsia yang digunakan untukHMACParameterkeydiperlukan apabila parameteralgoditetapkan kepadasignatausignTx.keyparameter tidak digunakan untukHMACpenyulitan apabilaalgoparameter ditetapkan kepada raw (kerana algoritma mesti ditentukan untuk penyulitan HMAC). kunci palsu senar

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
}

Contoh panggilan fungsi 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);
}

Parameteralgojuga menyokong: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk untuk mengkod dan mendekodkan rentetan.

PeraturanEncode()fungsi hanya disokong untuk perdagangan langsung.keydankeyFormatparameter tidak lulus, makakeypenyulitan tidak digunakan.

UnixNano

Dapatkan cap masa nanodetik saat ini.

PeraturanUnixNano()Fungsi mengembalikan cap masa nanodetik. nombor

UnixNano ((()

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

Jika anda perlu mendapatkan stempel masa milidetik, anda boleh menggunakan kod berikut:

{@fun/Global/Unix Unix}

Unix

Dapatkan cap masa saat ini di peringkat kedua.

Mengembalikan cap masa peringkat kedua. nombor

Unix ((()

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

{@fun/Global/UnixNano UnixNano}

GetOS

Dapatkan maklumat sistem peranti di mana docker terletak.

Maklumat sistem. senar

GetOS()

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

Sebagai contoh, panggilan kepadaGetOS()fungsi untuk pelabuhan yang berjalan padaMac OSsistem operasi mungkin kembali:darwin/amd64Kerana komputer Apple mempunyai pelbagai seni bina perkakasan.darwinadalah namaMac OS system.

MD5

Mengira hash MD5 parameterdata.

Nilai hash MD5. senar

MD5 (data)

Data yang memerlukan pengiraan MD5. data betul senar

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

MenghubungiMD5("hello world")fungsi, nilai pulangan adalah:5eb63bbbe01eeed093cb22bb8f5acdc3.

{@fun/Global/Encode Encode}

DBExec

Fungsi antara muka pangkalan data.

Objek yang mengandungi hasil pelaksanaansqlpernyataan, contohnya:


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

objek

DBExec ((sql)

sqlString arahan. sql betul senar

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

Sokongan pangkalan data dalam memori, untukDBExecparameter fungsi, jikasqlpernyataan bermula dengan:Ia sesuai untuk operasi pangkalan data yang tidak memerlukan simpanan berterusan, contohnya:

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

Buat meja.

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

Tambah, hapuskan, periksa dan ubah rekod dalam jadual.

FungsiDBExec()dapat mengendalikan pangkalan data perdagangan langsung (pangkalan data SQLite) dengan menyampaikan parameter.SQLiteSistem disediakan jadual dalam pangkalan data perdagangan langsung:kvdb, cfg, log, profit, chart, jangan beroperasi di atas meja ini.Transaksitidak disokong dan tidak disyorkan untuk melakukan operasi tersebut, yang boleh menyebabkan konflik dalam sistem.DBExec()Fungsi hanya disokong untuk perdagangan langsung.

{@fun/Global/_G _G}

UUID

Buat UUID.

UUID 32-bit. senar

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

PeraturanUUID()Fungsi ini hanya menyokong perdagangan langsung.

EventLoop

Dengarkan untuk peristiwa, ia kembali apabila ada apa-apaWebSocketdata yang boleh dibaca atau tugas serentak, seperti:exchange.Go(), HttpQuery_Go(), dan lain-lain telah selesai.

Jika objek yang dikembalikan bukan nilai sifar,Eventyang terkandung dalam kandungan pulangan adalah jenis pemicu peristiwa. Sebagai contoh, struktur nilai pulangan berikut:

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

objek

EventLoop ((() EventLoop (timeout)

Parametertimeoutadalah tetapan masa lapang, dalam mili saat.timeoutmenanti sesuatu peristiwa berlaku sebelum kembali jika ia ditetapkan kepada 0. Jika ia lebih besar daripada 0, ia menetapkan peristiwa untuk menunggu masa lapang, dan mengembalikan peristiwa yang paling baru dengan serta-merta jika ia kurang daripada 0. masa lapang palsu nombor

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

Panggilan pertama kepadaEventLoop()Fungsi dalam kod menghidupkan mekanisme untuk peristiwa yang didengar, dan jika yang pertamaEventLoop()panggilan bermula selepas callback peristiwa, ia akan terlepas peristiwa sebelumnya. sistem yang mendasari membungkus struktur antrian yang menyimpan maksimum 500 callback peristiwa.EventLoop()fungsi tidak dipanggil pada masa untuk mengambil mereka keluar semasa pelaksanaan program, kemudian panggilan balik acara di luar 500 cache akan hilang.EventLoop()fungsi tidak mempengaruhi barisan cache sistem asas WebSocket atau cache fungsi serentak sepertiexchange.Go(). Untuk cache ini, ia masih perlu menggunakan kaedah masing-masing untuk mendapatkan data.EventLoop()fungsi untuk data yang telah diambil sebelumEventLoop()fungsi kembali.EventLoop()fungsi adalah untuk memaklumkan lapisan strategi bahawa data rangkaian baru telah diterima oleh sistem yang mendasari. keseluruhan strategi didorong oleh peristiwa.EventLoop()fungsi mengembalikan peristiwa, hanya melintasi semua sumber data.exchange.Go()cuba untuk mendapatkan data.EventLoop()Fungsi ini hanya menyokong perdagangan langsung. Dengarkan peristiwa dalam benang utama apabila dipanggil dari fungsi utamamain(). Dalam strategi yang ditulis dalamJavaScriptBahasa,threading.Thread()fungsi mencipta thread, yang juga boleh dipanggil dalam fungsi pelaksanaan threads, untuk mendengar peristiwa dalam thread semasa.

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

__ Berkhidmat

Peraturan__Servefungsi digunakan untuk membuat perkhidmatan Http, perkhidmatan TCP, dan perkhidmatan Websocket (berdasarkan protokol Http).

Mengembalikan rentetan yang merekodkan alamat IP dan pelabuhan perkhidmatan yang dicipta.127.0.0.1:8088, [::]:8089.

senar

__Serve (serveURI, pengendali) __Serve ((serveURI, pengendali,...args)

PeraturanserveURIparameter digunakan untuk mengkonfigurasi protokol, alamat IP, pelabuhan dan tetapan lain yang mengikat perkhidmatan, sepertihttp://0.0.0.0:8088?gzip=true, iaitu,http://:8088?gzip=true.

  • Protokol TCPserveURItetapan parameter, sepertitcp://127.0.0.1:6666?tls=true; anda boleh menambah sijil dan kunci peribadi, sepertitls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Protokol HTTPserveURItetapan parameter, sepertihttp://127.0.0.1:6666?gzip=true; anda boleh menetapkan tetapan mampatan:gzip=true. PeraturanserveURIparameter digunakan untuk Https, sepertihttps://127.0.0.1:6666?tls=true&gzip=true; anda boleh menambahcert_pemdancert_key_pemparameter untuk memuat sijil.

berkhidmatURI betul senar PeraturanhandlerParameter digunakan untuk lulus dalam fungsi pemprosesan laluan (protokol HTTP), fungsi pemprosesan mesej (protokol TCP), dan fungsi pemprosesan aliran (Websocket). Fungsi panggilan balik yang dihantar oleh parameterhandlerboleh menentukan beberapa parameter, parameter pertama adalah objek ctx (objek konteks).

pengendali betul fungsi Parameter sebenar fungsi callback yang dihantar sebagai parameterhandlerMungkin ada pelbagai parameter.argContohnya:

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

Parameter1, 2, 3telah berlalu dalam apabila memanggil__Serve()fungsi sepadan dengan parametera, b, cdilewatkan dalam fungsi panggilan balik.

arg palsu rentetan, nombor, bool, objek, susunan, fungsi, nilai sifar dan jenis lain yang disokong oleh sistem

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
  • Fungsi ini menyokong strategi bahasa JavaScript sahaja.
  • Benang perkhidmatan terpencil dari skop global, jadi ia tidak menyokong penutupan atau rujukan kepada pembolehubah luaran, fungsi tersuai, dan lain-lain; Walau bagaimanapun, ia boleh memanggil semua fungsi API platform.
  • PeraturanWebsocketPerkhidmatan ini dilaksanakan berdasarkan protokol Http. Anda boleh menetapkan cawangan penghala dalam laluan dan merancang kod pelaksanaan untukWebsocketAnda boleh merujuk kepada contoh kod di bahagian ini.

Fungsi callback yang dihantar oleh parameterhandlermenerimactxparameter.ctxparameter adalah objek konteks yang digunakan untuk mendapatkan dan menulis data, dengan kaedah berikut:

  • ctx.proto (() Digunakan untuk protokol Http/TCP, mengembalikan nama protokol apabila dipanggil.HTTP/1.1, tcp.
  • ctx.host() Digunakan untuk protokol Http, ia mengembalikan maklumat hos apabila dipanggil alamat IP dan port.
  • ctx.path ((() Digunakan pada protokol Http, mengembalikan laluan permintaan apabila dipanggil.
  • ctx.query (kunci) Digunakan untuk protokol Http, mengembalikan nilai yang sepadan dengan kunci dalam pertanyaan dalam permintaan apabila dipanggil.http://127.0.0.1:8088?num=123, dan fungsi pemprosesan panggilan balik yang dihantar oleh parameterhandlerpengembalian"123"bila?ctx.query("num")dipanggil.
  • ctx.rawQuery() Digunakan untuk protokol Http, apabila dipanggil, mengembalikan pertanyaan asal dalam permintaan (soalan permintaan Http).
  • ctx.headers ((() Digunakan untuk protokol HTTP, dan mengembalikan maklumat tajuk permintaan dalam permintaan apabila dipanggil.
  • Ctx.header (kunci) Digunakan untuk protokol Http, ia mengembalikan nilai kunci dalam tajuk permintaan yang ditentukan apabila dipanggil.User-AgentDalam tajuk permintaan semasa:ctx.header("User-Agent").
  • ctx.metod ()) Digunakan untuk protokol Http, mengembalikan kaedah permintaan apabila dipanggil, sepertiGET, POST, dan lain-lain
  • ctx.body ((() Digunakan untuk permintaan POST protokol HTTP, dan mengembalikan badan permintaan apabila dipanggil.
  • ctx.setHeader (kunci, nilai) Digunakan untuk protokol HTTP untuk menetapkan maklumat tajuk permintaan mesej tindak balas.
  • ctx.setStatus (kode) digunakan untuk protokol Http, menetapkan kod status mesej Http. Biasanya, kod status Http ditetapkan di akhir cawangan penghalaan. Nilai lalai adalah 200.
  • ctx.remoteAddr() Digunakan untuk protokol Http / TCP, mengembalikan alamat klien jauh dan port dalam permintaan apabila dipanggil.
  • ctx.localAddr() Digunakan untuk protokol HTTP / TCP, mengembalikan alamat tempatan dan pelabuhan perkhidmatan apabila dipanggil.
  • ctx.upgrade ((websocket) Digunakan untuk pelaksanaan protokol Websocket berdasarkan protokol Http, menukarctxobjek konteks kepada protokol Websocket; mengembalikan nilai Boolean (benar) jika suis berjaya, dan nilai Boolean (salah) jika gagal.
  • ctx.read ((timeout_ms) Digunakan untuk pelaksanaan protokol Websocket / protokol TCP berdasarkan protokol Http, membaca data sambungan Websocket dan sambungan TCP.readanda boleh menentukan parameter timeouttimeout_msdalam milidetik.
  • ctx.write (s) Digunakan untuk protokol HTTP/TCP, digunakan untuk menulis data rentetan.JSON.stringify()untuk mengkod objek JSON ke dalam rentetan dan kemudian menulisnya.WebSocketProtokol, anda boleh menggunakan kaedah ini untuk lulus rentetan dikodkan kepada pelanggan.

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

_G

Secara berterusan menyimpan data, fungsi ini melaksanakan fungsi kamus global yang boleh disimpan. Struktur data adalah jadual KV yang disimpan secara kekal dalam fail pangkalan data tempatan docker.

Data nilai kunci yang disimpan secara berterusan dalamk-vpasangan kunci-nilai. rentetan, nombor, bool, objek, array, nilai sifar

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

Parameterkadalah nama kunci dalam pasangan kunci-nilai yang disimpan, dan tidak sensitif huruf besar. k palsu rentetan, nilai sifar Parametervadalah nilai kunci dalam pasangan kunci-nilai yang disimpan, yang boleh menjadi sebarang data yang bolehJSONDikirim secara seriali. v palsu rentetan, nombor, bool, objek, array, nilai sifar

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

Sebuah pangkalan data yang berasingan untuk setiap dagangan langsung, data yang disimpan oleh_G()fungsi akan sentiasa ada jika strategi dimulakan semula atau docker berhenti berjalan. Jika backtesting selesai, data yang disimpan dalam sistem backtesting oleh_G()Apabila menggunakan_G()fungsi untuk mengekalkan data yang disimpan, ia harus digunakan dengan munasabah mengikut memori dan ruang cakera keras peranti perkakasan, dan tidak boleh disalahgunakan. Apabila memanggil_G()fungsi dalam perdagangan langsung dan tiada parameter yang lulus,_G()fungsi mengembalikanIdPerdagangan langsung semasa._G()fungsi, parametervdilewatkan sebagai null untuk menunjukkan penghapusank-vApabila memanggil_G()fungsi, hanya parameterkadalah diluluskan dalam rentetan, dan_G()fungsi mengembalikan nilai kunci yang sepadan dengan parameter yang disimpank. Apabila memanggil_G()fungsi, hanya parameterkadalah dihantar dalam nilai sifar, menunjukkan bahawa semua rekodk-vPasangan kunci-nilai dipadamkan.k-vpasangan kunci-nilai telah disimpan berterusan,_G()fungsi dipanggil lagi, lulus dalam nama kunci yang telah disimpan secara berterusan sebagai parameterk. Menerbitkan nilai kunci baru sebagai parametervakan mengemas kini bahawak-vPasangan kunci-nilai.

{@fun/Global/DBExec DBExec}

_D

Mengubah timestamp milidetik atauDateobjek untuk senar masa.

String masa. senar

_D() _ D (timestamp) _D ((timestamp, fmt)

Stempel masa milidetik atauDateobjek. Stempel masa palsu Nombor, objek Format rentetan,JavaScriptFormat lalai bahasa:yyyy-MM-dd hh:mm:ss; PythonFormat lalai bahasa:%Y-%m-%d %H:%M:%S; C++Format lalai bahasa:%Y-%m-%d %H:%M:%S. fmt palsu senar

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

Dapatkan dan cetak rentetan masa semasa:

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

Stempel masa adalah 1574993606000, menggunakan penukaran kod:

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
}

Format dengan parameterfmtadalah berbeza untukJavaScript, Python, danC++bahasa, seperti yang ditunjukkan dalam contoh berikut:

Mengembalikan rentetan masa semasa tanpa lulus mana-mana parameter._D()fungsi dalamPythonstrategi, anda perlu sedar bahawa parameter yang diteruskan adalah timestamps peringkat kedua (timestamps tahap milidetik dalam strategi JavaScript dan C ++, di mana 1 saat sama dengan 1000 milidetik)._D()fungsi untuk menganalisis rentetan masa dengan cap masa yang boleh dibaca dalam perdagangan langsung, anda perlu memberi perhatian kepada zon waktu dan tetapan masa sistem operasi di mana program docker terletak._D()fungsi menganalisis stempel masa ke dalam rentetan masa yang boleh dibaca bergantung pada masa sistem dockers.

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

_N

Formatkan nombor koma terapung.

Nombor koma terapung yang diformat mengikut tetapan ketepatan. nombor

_N() _ N (n) _N (num, ketepatan)

Nombor koma terapung yang perlu diformat. nombor betul nombor Tetapan ketepatan untuk pemformatan, parameterprecisionadalah bilangan bulat, dan parameterprecisionlalai kepada 4. ketepatan palsu nombor

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

Sebagai contoh,_N(3.1415, 2)akan memadamkan nilai selepas3.1415dua tempat perpuluhan dan fungsi kembali3.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);
}

Jika anda perlu menukar semua N digit di sebelah kiri titik perpuluhan kepada 0, anda boleh menulisnya seperti ini:

Parameterprecisionboleh menjadi bilangan bulat positif, bilangan bulat negatif.

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

_C

Cuba semula fungsi untuk toleransi ralat antara muka.

Nilai pulangan fungsi panggilan balik apabila dilaksanakan. Semua jenis disokong oleh sistem kecualinilai logik palsudannilai null.

_C (((pfn) _C ((pfn,...args)

Parameterpfnadalah rujukan fungsi, yang merupakanFungsi callback. pfn betul fungsi Parameter kepadaFungsi panggilan balik, mungkin terdapat lebih daripada satu parameterarg. Jenis dan bilangan parameterargbergantung kepada parameterFungsi callback. arg palsu string, nombor, bool, objek, susunan, fungsi, semua jenis disokong oleh sistem, seperti nilai sifar

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

Untuk fungsi toleransi ralat tanpa parameter:

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

Untuk fungsi dengan parameter yang toleransi ralat:

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

Ia juga boleh digunakan untuk toleransi ralat fungsi tersuai:

Peraturan_C()fungsi akan terus memanggil fungsi yang ditentukan sehingga ia kembali dengan berjaya (fungsi dirujuk oleh parameterpfnpengembaliantiadaataupalsuApabila dipanggil akan cuba memanggil semulapfnSebagai contoh:_C(exchange.GetTicker). Jangkaan cubaan semula lalai adalah 3 saat, anda boleh memanggil_CDelay()fungsi untuk menetapkan selang cubaan semula._CDelay(1000)bermaksud untuk mengubah selang percubaan semula_C()fungsi ke 1 saat. Toleransi ralat boleh dilakukan untuk, tetapi tidak terhad kepada, fungsi berikut:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()Semua boleh dipanggil oleh_C()fungsi untuk toleransi ralat._C()fungsi tidak terhad kepada toleransi kesalahan fungsi yang disenaraikan di atas, parameterpfnadalah rujukan fungsi dan bukannya panggilan fungsi. Perhatikan bahawa ia adalah_C(exchange.GetTicker), tidak_C(exchange.GetTicker()).

_Silang

Mengembalikan bilangan tempoh persimpangan arrayarr1dan susunanarr2.

Bilangan tempoh silang arrayarr1dan susunanarr2. nombor

_Silang ((arr1, arr2)

Elemen adalah pelbagai jenisnumber. arr1 betul Array Elemen adalah pelbagai jenisnumber. arr2 betul Array

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

Satu set data boleh disimulasikan untuk menguji fungsi _Cross ((Arr1, Arr2):

Jika nilai pulangan_Cross()fungsi adalah nombor positif, ia menunjukkan tempoh penembusan ke atas, jika ia adalah nombor negatif, ia menunjukkan tempoh penembusan ke bawah, 0 bermaksud sama dengan harga semasa.Analisis dan arahan penggunaan mengenai fungsi terbina dalam _Cross.

JSONParse

FungsiJSONParse()digunakan untuk menganalisisJSON strings.

JSONobjek. objek

JSONParse (s)

JSONtali. s betul senar

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

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

JSON rentetan dengan nilai besar boleh dianalisis dengan betul, dan ia akan dianalisis nilai besar sebagai jenis rentetan.JSONParse()fungsi tidak disokong dalam sistem backtest.

Log