Sumber daya yang dimuat... Pemuatan...

Global

Versi

Mengembalikan nomor versi sistem saat ini.

Nomor versi sistem saat ini, seperti3.6Aku tidak tahu. string

Versi ((()

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

Nomor versi sistem adalah nomor versi dari program docker.

Tidur

Fungsi tidur, menyebabkan program berhenti sejenak.

Tidur (millisecond)

Peraturanmillisecondparameter digunakan untuk mengatur durasi tidur dan jumlah milidetik. Milisekund benar nomor

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, ketika menjalankanSleep(1000)fungsi, program akan tidur selama 1 detik.Sleep(0.1). Ini mendukung parameter minimum dari0.000001, yaitu hibernasi nanodetik, di mana 1 nanodetik sama dengan1e-6Milisekund. Ketika menulis strategi diPythonbahasa,Sleep(millisecond)fungsi harus digunakan untuk intervall polling, waktu untuk menunggu operasi.time.sleep(second)fungsi dariPythonItu adalahtimeini karena menggunakantime.sleep(second)fungsi dalam strategi membuat program strategi menunggu untuk periode waktu sebenarnya ketika backtesting (tidak melewatkan seri waktu dari sistem backtesting), sehingga menyebabkan strategi untuk backtest sangat lambat.

IsVirtual

Tentukan apakah lingkungan operasi strategi adalah sistem backtesting.

Strategi mengembalikan nilai sebenarnya, misalnya:trueStrategi ini mengembalikan nilai palsu, misalnya:falseketika berjalan di lingkungan perdagangan langsung. bool

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

Tentukan apakah lingkungan berjalan saat ini adalah sistem backtesting, yang digunakan untuk kompatibel dengan perbedaan antara backtesting dan perdagangan langsung.

Surat

Kirim email.

Pengiriman email yang berhasil mengembalikan nilai yang sebenarnya, misalnya,true, dan pengiriman gagal mengembalikan nilai palsu, misalnya,falseAku tidak tahu. bool

Mail ((smtpServer, smtpUsername, smtpPassword, mailTo, judul, tubuh)

Digunakan untuk menentukanSMTPalamat layanan pengirim email. smtpServer benar string Digunakan untuk menentukan alamat email pengirim email. smtpNama pengguna benar string PeraturanSMTPkata sandi untuk kotak surat pengirim email. smtpPassword benar string Digunakan untuk menentukan alamat email penerima email. mailTo benar string Alamat email. Judul benar string Tubuh email. tubuh benar string

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

PeraturansmtpPasswordparameter menetapkan kata sandi untukSMTPlayanan, bukan kata sandi kotak surat. Saat mengatursmtpServerparameter, jika Anda perlu mengubah port, Anda dapat menambahkan nomor port langsung di parametersmtpServer. Misalnya: QQ mailsmtp.qq.com:587, yang tersedia untuk pengujian. Jika kesalahan dilaporkan:unencryped connection, Anda perlu memodifikasismtpServerdariMailFormat parameter adalah:ssl://xxx.com:xxx, misalnya,sslmetodeSMTPuntuk QQ mail:ssl://smtp.qq.com:465atausmtp://xxx.com:xxxAku tidak tahu. Ini tidak bekerja di sistem backtesting.

{@fun/Global/Mail_Go Mail_Go}

Mail_Go

Versi asinkron dariMail function.

PeraturanMail_Gofungsi mengembalikan objek bersamaan segera, dan Anda dapat menggunakanwaitmetode dari objek bersamaan untuk mendapatkan hasil pengiriman surat. pengiriman surat yang sukses mengembalikan nilai benar, misalnya,true, dan pengiriman gagal mengembalikan nilai palsu, misalnya,falseAku tidak tahu. objek

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

Ini digunakan untuk menentukanSMTPalamat layanan pengirim email. smtpServer benar string Ini digunakan untuk menentukan alamat email pengirim email. smtpNama pengguna benar string PeraturanSMTPkata sandi untuk kotak surat pengirim email. smtpPassword benar string Ini digunakan untuk menentukan alamat email penerima email. mailTo benar string Alamat email. Judul benar string Tubuh email. tubuh benar string

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

Ini tidak bekerja di sistem backtesting.

{@fun/Global/Mail Mail}

SetErrorFilter

Log kesalahan filter.

SetErrorFilter ((filter)

Senar ekspresi reguler. Filter benar string

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

Menyaring kesalahan umum.

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

Menyaring pesan kesalahan antarmuka.

Log kesalahan yang cocok dengan ekspresi reguler ini tidak akan diunggah ke sistem log. Anda dapat memanggilnya beberapa kali (tidak ada batasan jumlah kali) untuk mengatur beberapa kondisi filter. Ekspresi reguler yang ditetapkan beberapa kali akan dikumpulkan dan berlaku pada saat yang sama. Anda dapat mengatur string kosong untuk mengatur ulang ekspresi reguler yang digunakan untuk menyaring log kesalahan:SetErrorFilter(""). Log yang disaring tidak lagi ditulis ke file database yang sesuai dengan ID perdagangan langsung di direktori docker untuk mencegah laporan kesalahan yang sering dari membengkak file database.

GetPid

Dapatkan ID proses perdagangan langsung.

Kembalikan ID proses perdagangan langsung. string

GetPid ((()

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

GetLastError

Dapatkan pesan kesalahan terakhir.

Pesan kesalahan terakhir. string

GetLastError ((()

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

Ini tidak bekerja di sistem backtesting.

GetCommand

Dapatkan perintah interaksi strategi.

Format perintah kembali adalahControlName:Data. ControlNameadalah nama kontrol, danDataadalah data yang dimasukkan ke dalam kontrol. Jika kontrol interaktif tidak memiliki kotak input, kotak drop-down dan komponen lain (misalnya kontrol tombol tanpa kotak input) maka format perintah yang dikembalikan adalahControlName, yang hanya mengembalikan nama kontrol. string

GetCommand ((()

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

Mendeteksi perintah interaksi dan menggunakanLogfungsi untuk output perintah interaksi ketika terdeteksi.

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

Misalnya, strategi kontrol interaktif menambahkan kontrol tanpa kotak input, kontrol interaktif diberi nama:buy, informasi deskripsi kontrol adalah:buy, yang merupakan kontrol tombol. Lanjutkan dengan menambahkan kontrol dengan kotak input. Kontrol interaktif bernama:selldan pesan deskripsi kontrol adalah:sell, yang merupakan kontrol interaktif yang merupakan kombinasi dari tombol dan kotak input. kode interaksi dirancang dalam strategi untuk menanggapi kontrol interaksi yang berbeda:

Ini tidak bekerja di sistem backtesting.

GetMeta

Dapatkan nilai Meta ditulis saat menghasilkan kode pendaftaran strategi.

Metadata. string

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 skenario aplikasi: PenggunaanMetauntuk membatasi jumlah aset yang dioperasikan oleh strategi.

Skenario aplikasi: perlu melakukan batas modal untuk penyewa strategi yang berbeda.Metanilai yang ditetapkan saat menghasilkan kode pendaftaran tidak dapat melebihi 190 karakter danGetMeta()Jika tidak ada metadata (Meta) ditetapkan saat menghasilkan kode pendaftaran strategi,GetMeta()Fungsi ini tidak berfungsi di sistem backtesting.

Pilih

Untuk primitifSocketakses, mendukungtcp, udp, tls, unixMendukung 4 protokol komunikasi populer:mqtt, nats, amqp, kafka. Dukungan untuk menghubungkan ke database:sqlite3, mysql, postgres, clickhouse.

PeraturanDial()fungsi mengembalikan null jika waktu habis. panggilan normal mengembalikan objek koneksi yang memiliki tiga metode:read, writedanclose.readmetode digunakan untuk membaca data,writemetode digunakan untuk mengirim data danclosemetode digunakan untuk menutup koneksi. PeraturanreadMetode ini mendukung parameter berikut:

  • Ketika tidak ada parameter yang diteruskan, ia memblokir sampai pesan tersedia dan kembali, sepertiws.read().
  • Ketika diteruskan sebagai parameter, satuan adalah milidetik, menentukan periode waktu tunggu pesan.ws.read(2000)menentukan timeout dua detik (2000 millisecond).
  • Kedua parameter berikut hanya berlaku untuk WebSocket: Mengirim parameter-1berarti bahwa fungsi mengembalikan langsung, terlepas dari kehadiran atau tidak adanya pesan, misalnya:ws.read(-1)Aku tidak tahu. Mengirim parameter-2berarti bahwa fungsi mengembalikan segera dengan atau tanpa pesan, tetapi hanya pesan terbaru yang dikembalikan, dan pesan yang disimpen dibuang.ws.read(-2).

read()deskripsi buffer fungsi: Data masuk yang didorong oleh protokol WebSocket dapat menyebabkan akumulasi data jika interval waktu antara strategiread()Data ini disimpan di buffer, yang memiliki struktur data antrian dengan maksimum 2000. Setelah 2000 dilampaui, data terbaru dimasukkan ke buffer dan data tertua dihapus.

Skenario Tidak ada parameter Parameter: -1 Parameter: -2 Parameter: 2000, dalam milidetik
Data sudah di buffer Kembalikan data tertua segera Kembalikan data tertua segera Kembali data terbaru segera Kembalikan data tertua segera
Tidak ada data di buffer Kembali saat diblokir ke data Kembali null segera Kembali null segera Tunggu 2000 ms, kembali null jika tidak ada data, kembali null jika ada data
Koneksi WebSocket terputus atau dihubungkan kembali oleh yang mendasarinya read() function mengembalikan string kosong, yaitu: , dan write() function mengembalikan 0. Situasinya terdeteksi. Anda dapat menutup koneksi menggunakan fungsi close(), atau jika Anda telah mengatur koneksi ulang otomatis, Anda tidak perlu menutupnya, sistem yang mendasari akan menghubungkannya kembali secara otomatis.

objek

Pilih (Alamat) Pilih (alamat, waktu)

Alamat permintaan. alamat benar string detik timeout, timeout palsu Nomor

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

Akses ke antarmuka ticker WebSocket 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");
}

Untuk mengakses OKX WebSocket autentikasi antarmuka:

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 koneksi yang dikembalikan oleh fungsi Dial saat terhubung ke database memiliki dua fungsi metode yang unik untuknya:

  • exec(sqlString): Digunakan untuk mengeksekusi pernyataan SQL dengan cara yang mirip denganDBExec() function.
  • fd(): Thefd()fungsi mengembalikan pegangan (misalnya, variabel pegangan adalah pegangan) yang akan digunakan oleh thread lain untuk terhubung kembali (bahkan jika objek yang dibuat oleh Dial telah ditutup oleh pelaksanaanclose()fungsi untuk menutup koneksi) dengan melewati pegangan keDial()fungsi, misalnya,Dial(handle)Gunakan kembali koneksi. Berikut ini adalah contoh dari fungsi Dial menghubungkan kesqlite3 database.

Rincian dariaddressparameter, dipisahkan oleh|simbol setelah alamat normal:wss://ws.okx.com:8443/ws/v5/publicJika ada.|karakter dalam string parameter, kemudian||Bagian setelah itu adalah beberapa pengaturan parameter fungsi, dan setiap parameter terhubung dengan&karakter. Misalnya,ss5Parameter proxy dan kompresi dapat disatukan sebagai berikut:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Fungsi yang didukung oleh parameter alamat dari fungsi Dial Deskripsi parameter
Parameter yang terkait dengan kompresi data protokol WebSocket: compress=parameter value compress adalah metode kompresi, pilihan parameter compress adalah: gzip_raw, gzip, dll. Jika metode gzip tidak standar gzip, Anda dapat menggunakan metode diperpanjang: gzip_raw
Parameter yang terkait dengan kompresi data protokol WebSocket: mode=nilai parameter mode adalah mode kompresi, parameter mode dapat dual, send, recv. dual adalah kompresi dua arah, mengirim data terkompresi, menerima data terkompresi. send adalah mengirim data terkompresi. recv adalah menerima data terkompresi, dekompresi lokal.
Protokol WebSocket menetapkan parameter terkait auto-reconnect yang mendasari: reconnect=parameter value reconnect adalah apakah untuk mengatur reconnect, reconnect=true adalah untuk mengaktifkan reconnect.
Protokol WebSocket menetapkan parameter terkait auto-reconnect yang mendasari: interval=nilai parameter interval adalah interval percobaan ulang, dalam milidetik, interval=10000 adalah interval percobaan ulang 10 detik, default adalah 1 detik ketika tidak diatur, yaitu interval=1000.
Protokol WebSocket menetapkan parameter terkait auto-reconnect yang mendasari: payload=parameter value payload adalah pesan langganan yang perlu dikirim saat WebSocket dihubungkan kembali, misalnya: payload=okokok.
Parameter yang terkait dengan kaus kaki5 proxy: proxy=nilai parameter Proxy adalah pengaturan proxy ss5, format nilai parameter: socks5://name:pwd@192.168.0.1:1080, nama adalah nama pengguna server ss5, pwd adalah password login server ss5, 1080 adalah port layanan ss5.

PeraturanDial()Fungsi hanya didukung untuk perdagangan langsung. Saat terhubung ke database menggunakan fungsi Dial, string koneksi ditulis dengan referensi ke proyek driver bahasa go untuk setiap database.

Basis data yang didukung Proyek Penggerak Senar koneksi Pengamatan
Sqlite3 github.com/mattn/go-sqlite3 sqlite3://file:test.db?cache=shared&mode=memory Peraturansqlite3://Prefiks menunjukkan bahwa database 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
Tumbuh 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

Harap dicatat bahwa ketikapayloadkonten yang ditetapkan dalamaddressparameter berisi karakter=atau karakter khusus lainnya, dapat mempengaruhi analisis dariaddressparameter dariDialfungsi, seperti contoh berikut.

contoh panggilan backPack Exchange websocket private interface:

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 kode bekerja dengan baik:

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

Jika Anda menulisnya langsung dipayload, tidak akan berfungsi dengan baik, misalnya:

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

Saat ini, hanya JavaScript mendukung penggunaanmqtt, nats, amqp, dankafkakode 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")
    }
}

Referensi dokumentasi rinci:Menjelajahi FMZ: Praktik Protokol Komunikasi Antara Strategi Perdagangan Langsung

HttpQuery

Kirim permintaan Http.

Mengembalikan data respons dari permintaan. Jika nilai yang dikembalikan adalahJSONstring, itu dapat dianalisis olehJSON.parse()Fungsi dalamJavaScriptstrategi bahasa, dan olehjson::parse()Fungsi dalamC++Jika debug ditetapkan menjadi true dalam struktur opsi, nilai pengembalian adalah objek (JSON); jika debug ditetapkan menjadi false, nilai pengembalian adalah string. string, objek

HttpQuery (URL) HttpQuery ((url, opsi)

URL permintaan HTTP. Url benar string Pengaturan terkait permintaan HTTP, misalnya, dapat disusun sebagai 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 browsertlsSidik jari. Pengaturan yang didukung termasuk opsi 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"... gedung pencakar langit:"cloudscraper"... mms_:"mms_ios"... mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2"... Konfirmasi_:"confirmed_ios", "confirmed_android"... Oke."okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • debug: Ketika ditetapkan untuktrue, yangHttpQuerypanggilan fungsi mengembalikan pesan jawaban penuh.false, hanya data dalamBodydari pesan balasan dikembalikan.
  • timeout: pengaturan timeout, setting 1000 berarti 1 detik timeout.
  • Charset: Mendukung transkoding data respons yang diminta, seperti GB18030. Semua bidang dalam struktur ini bersifat opsional, misalnya,profilelapangan dapat dilewatkan.

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 antarmuka API ticker publik 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 pengaturan proxy.

PeraturanHttpQuery()Fungsi hanya mendukungJavaScript, C++bahasa,Pythonbahasa dapat menggunakanurllibPerpustakaan untuk mengirim permintaan Http langsung.HttpQuery()digunakan terutama untuk mengakses antarmuka pertukaran yang tidak memerlukan tanda tangan, seperti antarmuka publik seperti informasi ticker.HttpQuery()dapat digunakan dalam sistem backtesting untuk mengirim permintaan (hanyaGETBacktesting terbatas pada penggunaan 20 kunjungan ke berbagaiURLs, danHttpQuery()kunjungan akan cache data.URLdiakses untuk kedua kalinya,HttpQuery()fungsi mengembalikan data yang di-cache dan tidak ada lagi permintaan jaringan yang sebenarnya terjadi.

{@fun/Global/HttpQuery_Go HttpQuery_Go}

HttpQuery_Go

Mengirim permintaan HTTP, versi asinkron dariHttpQuery function.

PeraturanHttpQuery_Go()fungsi segera mengembalikan objek bersamaan yang dapat digunakan untuk mendapatkan hasil permintaan HTTP menggunakanwaitmetode dariJSON.parse()fungsi dapat digunakan untuk menganalisisJSON.parse()Fungsi dalamJavaScriptstrategi bahasa.
objek

HttpQuery_Go ((url) HttpQuery_Go ((url, opsi)

URL permintaan HTTP. Url benar string Pengaturan terkait permintaan HTTP, misalnya, dapat disusun sebagai 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 browsertls fingerprints.
  • debug: Ketika ditetapkan untuktrue, iniHttpQuery_Gopanggilan fungsi mengembalikan pesan jawaban penuh.false, hanya data dalamBodydari pesan balasan dikembalikan.
  • timeout: pengaturan timeout, setting 1000 berarti 1 detik timeout. Semua bidang dalam struktur ini bersifat opsional, misalnya,profilelapangan dapat dilewatkan.

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 asinkron ke antarmuka publik pertukaran untuk data ticker agregat.

PeraturanHttpQuery_Go()Fungsi hanya mendukungJavaScript, yangPythonbahasa dapat digunakan denganurllibPerpustakaan untuk mengirim permintaan Http langsung.HttpQuery_Go()digunakan terutama untuk mengakses antarmuka yang tidak memerlukan tanda tangan di bursa, seperti antarmuka publik seperti informasi ticker.HttpQuery_Gofungsi tidak didukung dalam sistem backtesting.

{@fun/Global/HttpQuery HttpQuery}

Mengenkode

Fungsi ini mengkodekan data sesuai dengan parameter yang diteruskan.

PeraturanEncodefungsi mengembalikan data setelah pengkodean dan enkripsi. string

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

Parameteralgoadalah algoritma yang digunakan dalam perhitungan pengkodean. Pengaturan dukungan 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 mendukung: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk, mengenkode dan mendekode string.algojuga mendukung: ed25519 algoritma. Mendukung penggunaan algoritma hash yang berbeda, misalnya parameteralgodapat ditulis sebagai ed25519.md5, ed25519.sha512, dll.ed25519.seedperhitungan. sesuatu benar string Digunakan untuk menentukan format data daridataparameter.inputFormatparameter dapat ditetapkan sebagai salah satu dari berikut:raw, hex, base64, string. raw berarti data adalah data mentah, hex berarti data adalahhexdikodekan, base64 berarti data adalahbase64dikodekan, dan string berarti data adalah string. inputFormat benar string Digunakan untuk menentukan format data output.outputFormatparameter dapat ditetapkan sebagai salah satu dari berikut:raw, hex, base64, string. raw berarti data adalah data mentah, hex berarti data adalahhexdikodekan, base64 berarti data adalahbase64dikodekan, dan string berarti data adalah string. outputFormat benar string Parameterdataadalah data yang akan diproses. data benar string Digunakan untuk menentukan format data darikeyparameter.keyparameter dapat ditetapkan sebagai salah satu dari berikut:raw, hex, base64, string. raw berarti data adalah data mentah, hex berarti data adalahhexdikodekan, base64 berarti data adalahbase64dikodekan, dan string berarti data adalah string. keyFormat palsu string Parameterkeyadalah kunci rahasia yang digunakan untukHMACEnkripsi.keydiperlukan ketika parameteralgodiatur untuksignatausignTx.keyparameter tidak digunakan untukHMACEnkripsi ketikaalgoparameter ditetapkan menjadi raw (karena algoritma harus ditentukan untuk enkripsi HMAC). kunci palsu string

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

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

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

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 mendukung: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk untuk mengenkode dan mendekode string.

PeraturanEncode()fungsi hanya didukung untuk perdagangan langsung.keydankeyFormatparameter tidak lulus, makakeyEnkripsi tidak digunakan.

UnixNano

Dapatkan tanda waktu nanodetik saat ini.

PeraturanUnixNano()Fungsi mengembalikan tanda waktu nanodetik. Nomor

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 time stamp millisecond, Anda dapat menggunakan kode berikut:

{@fun/Global/Unix Unix}

Unix

Dapatkan time stamp saat ini di tingkat kedua.

Mengembalikan timestamp tingkat dua. Nomor

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 informasi sistem dari perangkat di mana docker terletak.

Informasi sistem. string

GetOS()

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

Sebagai contoh, panggilan keGetOS()fungsi untuk docker yang berjalan padaMac OSsistem operasi mungkin kembali:darwin/amd64Karena komputer Apple memiliki beberapa arsitektur hardware.darwinadalah nama dariMac OS system.

MD5

Menghitung hash MD5 dari parameterdata.

Nilai hash MD5. string

MD5 (data)

Data yang membutuhkan perhitungan MD5. data benar string

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

MenelponMD5("hello world")fungsi, nilai yang dikembalikan adalah:5eb63bbbe01eeed093cb22bb8f5acdc3.

{@fun/Global/Encode Encode}

DBExec

Fungsi antarmuka database.

Sebuah objek yang berisi hasil dari eksekusiSqlpernyataan, misalnya:


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

objek

DBExec ((sql)

Sqlstring pernyataan. Sql benar string

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

Dukungan database di memori, untukDBExecparameter fungsi, jikaSqlpernyataan dimulai dengan:kemudian dioperasikan dalam database in-memory, akan lebih cepat tanpa menulis file.

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

Tambahkan, hapus, periksa dan ubah catatan dalam tabel.

FungsiDBExec()dapat mengoperasikan database perdagangan langsung (database SQLite) dengan melewati parameter.SQLiteSistem cadangan tabel di basis data perdagangan langsung:kvdb, cfg, log, profit, chart, jangan bekerja di meja ini.Transaksitidak didukung dan tidak dianjurkan untuk melakukan operasi tersebut, yang dapat menyebabkan konflik dalam sistem.DBExec()Fungsi hanya didukung untuk perdagangan langsung.

{@fun/Global/_G _G}

UUID

Buat UUID.

UUID 32 bit. string

UUID ((()

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

PeraturanUUID()Fungsi hanya mendukung perdagangan langsung.

EventLoop

Dengarkan untuk peristiwa, itu kembali ketika adaWebSocketdata yang dapat dibaca atau tugas bersamaan, sepertiexchange.Go(), HttpQuery_Go(), dll telah selesai.

Jika objek yang dikembalikan bukan nilai nol,Eventyang terkandung dalam konten pengembalian adalah jenis pemicu peristiwa. Misalnya struktur nilai pengembalian berikut:

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

objek

EventLoop ((() EventLoop (timeout)

Parametertimeoutadalah pengaturan timeout, dalam milidetik.timeoutmenunggu suatu peristiwa terjadi sebelum kembali jika ditetapkan menjadi 0. Jika lebih besar dari 0, mengatur peristiwa untuk menunggu waktu habis, dan mengembalikan peristiwa terbaru segera jika kurang dari 0. timeout palsu nomor

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 untukEventLoop()fungsi dalam kode menginisialisasi mekanisme untuk acara yang didengarkan, dan jika yang pertamaEventLoop()call dimulai setelah event callback, itu akan melewatkan acara sebelumnya. sistem yang mendasari membungkus struktur antrian yang cache maksimum 500 callback acara.EventLoop()fungsi tidak dipanggil pada waktunya untuk mengambil mereka keluar selama eksekusi program, kemudian callback acara di luar 500 cache akan hilang.EventLoop()fungsi tidak mempengaruhi antrian cache dari sistem dasar WebSocket atau cache fungsi bersamaan sepertiexchange.Go()Untuk cache ini, masih perlu menggunakan metode masing-masing untuk mengambil data.EventLoop()fungsi untuk data yang telah diambil sebelumEventLoop()Tujuan utama dariEventLoop()fungsi adalah untuk memberi tahu lapisan strategi bahwa data jaringan baru telah diterima oleh sistem yang mendasari.EventLoop()fungsi mengembalikan suatu peristiwa, hanya melintasi semua sumber data.exchange.Go()mencoba untuk mendapatkan data.EventLoop()Fungsi hanya mendukung perdagangan langsung. Dengarkan acara di thread utama ketika dipanggil dari fungsi utamamain(). Dalam strategi yang ditulis dalamJavaScriptbahasa,threading.Thread()fungsi membuat thread, yang juga dapat dipanggil dalam fungsi eksekusi threads, untuk mendengarkan peristiwa di thread saat ini.

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

__Servis

Peraturan__Servefungsi digunakan untuk membuat layanan HTTP, layanan TCP, dan layanan Websocket (berdasarkan protokol HTTP).

Mengembalikan string yang mencatat alamat IP dan port dari layanan yang dibuat.127.0.0.1:8088, [::]:8089.

string

__Serve (serveURI, pengelola) __Serve ((serveURI, handler,...args)

PeraturanserveURIparameter digunakan untuk mengkonfigurasi protokol, alamat IP, port dan pengaturan lain dari layanan mengikat, sepertihttp://0.0.0.0:8088?gzip=true, yaitu,http://:8088?gzip=true.

  • Protokol TCPserveURIpengaturan parameter, sepertitcp://127.0.0.1:6666?tls=true; Anda dapat menambahkan sertifikat dan kunci pribadi, sepertitls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Protokol HttpserveURIpengaturan parameter, sepertihttp://127.0.0.1:6666?gzip=true; Anda dapat mengatur pengaturan kompresi:gzip=trueAku tidak tahu. PeraturanserveURIparameter digunakan untuk Https, sepertihttps://127.0.0.1:6666?tls=true&gzip=true; Anda dapat menambahkancert_pemdancert_key_pemparameter untuk memuat sertifikat.

melayaniURI benar string PeraturanhandlerParameter digunakan untuk lulus dalam fungsi pemrosesan routing (Http protokol), fungsi pemrosesan pesan (TCP protokol), dan fungsi pemrosesan Stream (Websocket). Fungsi callback yang diteruskan oleh parameterhandlerdapat mendefinisikan beberapa parameter, parameter pertama adalah objek ctx (objek konteks).

pengelola benar fungsi Parameter sebenarnya dari fungsi callback yang dilewati sebagai parameterhandlerMungkin ada beberapa parameter.arg, misalnya:

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

Parameter1, 2, 3melewati saat memanggil__Serve()fungsi sesuai dengan parametera, b, cdilewati dalam fungsi callback.

arg palsu string, number, bool, object, array, function, null value dan tipe lain yang didukung 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 hanya mendukung strategi bahasa JavaScript.
  • Thread layanan terisolasi dari ruang lingkup global, sehingga tidak mendukung penutupan atau referensi ke variabel eksternal, fungsi kustom, dll.; Namun, dapat memanggil semua fungsi API platform.
  • PeraturanWebsocketlayanan diimplementasikan berdasarkan protokol Http. Anda dapat mengatur cabang routing di jalur dan merancang kode implementasi untukWebsocketAnda dapat melihat contoh kode di bagian ini.

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

  • ctx.proto ((() Terapan pada protokol Http/TCP, mengembalikan nama protokol saat dipanggil.HTTP/1.1, tcp.
  • ctx.host() Diterapkan pada protokol Http, ini mengembalikan informasi host ketika dipanggil alamat IP dan port.
  • ctx.path ((() Terapkan pada protokol Http, mengembalikan jalur permintaan saat dipanggil.
  • ctx.query (kunci) Diterapkan pada protokol Http, mengembalikan nilai yang sesuai dengan kunci dalam kueri dalam permintaan ketika dipanggil.http://127.0.0.1:8088?num=123, dan fungsi pemrosesan callback yang diteruskan oleh parameterhandlerkembali"123"kapan?ctx.query("num")disebut.
  • ctx.rawQuery() Terapan pada protokol Http, ketika dipanggil, mengembalikan kueri asli dalam permintaan (kueri permintaan Http).
  • ctx.headers ((() Terapan pada protokol Http, dan mengembalikan informasi request header dalam request saat dipanggil.
  • ctx.header (kunci) Diterapkan pada protokol Http, mengembalikan nilai kunci di header permintaan yang ditentukan ketika dipanggil.User-Agentdalam judul permintaan saat ini:ctx.header("User-Agent").
  • ctx.metode (() Terapkan pada protokol Http, mengembalikan metode permintaan saat dipanggil, sepertiGET, POST, dll.
  • Ctx.body (dalam bahasa Inggris) Terapkan pada permintaan POST dari protokol Http, dan mengembalikan tubuh permintaan saat dipanggil.
  • ctx.setHeader (kunci, nilai) Digunakan pada protokol Http untuk mengatur informasi request header dari pesan respons.
  • ctx.setStatus (kode) Aplikasi untuk protokol Http, mengatur kode status pesan Http. Biasanya, kode status Http ditetapkan di akhir cabang routing. Nilai default adalah 200.
  • ctx.remoteAddr() Terapan pada protokol Http/TCP, mengembalikan alamat klien jarak jauh dan port dalam permintaan saat dipanggil.
  • ctx.localAddr() Terapan pada protokol Http/TCP, mengembalikan alamat lokal dan port layanan saat dipanggil.
  • ctx.upgrade ((websocket) diterapkan pada implementasi protokol Websocket berdasarkan protokol Http, beralihctxobjek konteks ke protokol Websocket; mengembalikan nilai Boolean (benar) jika switch berhasil, dan nilai Boolean (palsu) jika gagal.
  • ctx.read ((timeout_ms) Terapkan pada implementasi protokol Websocket / protokol TCP berdasarkan protokol Http, membaca data koneksi Websocket dan koneksi TCP.readmetode tidak didukung dalam protokol HTTP biasa. Anda dapat menentukan parameter timeouttimeout_msdalam milidetik.
  • ctx.write (s) Dilakukan pada protokol Http/TCP, digunakan untuk menulis data string.JSON.stringify()untuk mengenkode objek JSON ke dalam string dan kemudian menulisnya.WebSocketprotokol, Anda dapat menggunakan metode ini untuk melewati string yang dienkode ke klien.

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

_G

Fungsi ini mengimplementasikan fungsi kamus global yang dapat disimpan. Struktur data adalah tabel KV yang secara permanen disimpan di file database lokal docker.

Data nilai kunci yang disimpan secara permanen dik-vPasangan kunci-nilai. string, nomor, bool, objek, array, nilai nol

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

Parameterkadalah nama kunci dalam pasangan kunci-nilai yang disimpan, dan tidak sensitif huruf besar. k palsu string, nilai nol Parametervadalah nilai kunci dalam pasangan kunci-nilai yang disimpan, yang bisa menjadi data apa pun yang dapatJSONSerial. v palsu string, nomor, bool, objek, array, nilai nol

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 database terpisah untuk setiap perdagangan langsung, data yang disimpan oleh_G()fungsi akan selalu ada jika strategi dimulai kembali atau docker berhenti berjalan._G()Saat menggunakan_G()fungsi untuk mempertahankan data yang disimpan, harus digunakan secara wajar sesuai dengan memori dan ruang hard disk perangkat keras, dan tidak boleh disalahgunakan. Saat menelepon_G()fungsi dalam perdagangan hidup dan tidak ada parameter yang dilewati,_G()fungsi mengembalikanIdsaat ini perdagangan langsung._G()fungsi, parametervdilewatkan sebagai nol untuk menunjukkan penghapusank-vKetika memanggil_G()fungsi, hanya parameterkditeruskan dalam string, dan_G()fungsi mengembalikan nilai kunci yang sesuai dengan parameter yang disimpank. Ketika memanggil_G()fungsi, hanya parameterkdiberikan dalam nilai nol, menunjukkan bahwa semua catatan darik-vkey-value pair dihapus.k-vpasangan kunci-nilai telah disimpan terus menerus,_G()fungsi dipanggil lagi, lulus dalam nama kunci yang telah disimpan terus-menerus sebagai parameterk. Mengirim nilai kunci baru sebagai parametervakan memperbarui ituk-vPasangan kunci-nilai.

{@fun/Global/DBExec DBExec}

_D

Mengkonversi millisecond timestamps atauDateobjek untuk string waktu.

String waktu. string

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

Stempel waktu milidetik atauDateobjek. Stempel waktu palsu Nomor, objek Format string,JavaScriptFormat bahasa default:yyyy-MM-dd hh:mm:ss; PythonFormat bahasa default:%Y-%m-%d %H:%M:%S; C++Format bahasa default:%Y-%m-%d %H:%M:%SAku tidak tahu. fmt palsu string

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

Dapatkan dan cetak string waktu saat ini:

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 waktu adalah 1574993606000, menggunakan konversi kode:

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 parameterfmtberbeda untukJavaScript, Python, danC++bahasa, seperti yang ditunjukkan dalam contoh berikut:

Mengembalikan string waktu saat ini tanpa melewati parameter._D()Fungsi dalamPythonstrategi, Anda perlu menyadari bahwa parameter yang dilewatkan adalah timestamps tingkat kedua (timestamps tingkat milidetik dalam strategi JavaScript dan C ++, di mana 1 detik sama dengan 1000 milidetik)._D()fungsi untuk menganalisis string waktu dengan timestamp yang dapat dibaca dalam perdagangan langsung, Anda perlu memperhatikan zona waktu dan pengaturan waktu dari sistem operasi di mana program docker terletak._D()Fungsi ini menganalisis timestamp ke dalam string waktu yang dapat dibaca tergantung pada waktu dari sistem docker.

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

_N

Formatkan nomor tanda gerak.

Nomor koma mengambang yang diformat sesuai dengan pengaturan presisi. nomor

_N() _N(nomor) _N ((num, presisi)

Nomor tanda mengapung yang perlu diformat. Nomor benar Nomor Pengaturan presisi untuk pemformatan, parameterprecisionadalah bilangan bulat, dan parameterprecisiondefault ke 4. Keakuratan palsu Nomor

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 menghapus nilai setelah3.1415dua tempat desimal 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 mengubah semua N digit ke kiri dari titik desimal ke 0, Anda dapat menulisnya seperti ini:

Parameterprecisionbisa menjadi bilangan bulat positif, bilangan bulat negatif.

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

_C

Coba lagi fungsi untuk toleransi kesalahan antarmuka.

Nilai yang dikembalikan dari fungsi callback saat dijalankan. Semua tipe didukung oleh sistem kecualinilai logis palsudannilai nol.

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

Parameterpfnadalah referensi fungsi, yang merupakanFungsi callbackAku tidak tahu. pfn benar fungsi Parameter untukfungsi callback, mungkin ada lebih dari satu parameterarg. Jenis dan jumlah parameterargtergantung pada parameter dariFungsi callbackAku tidak tahu. arg palsu string, number, bool, object, array, function, semua jenis didukung oleh sistem, seperti nilai nol

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 kesalahan 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 kesalahan:

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

Hal ini juga dapat digunakan untuk toleransi kesalahan fungsi kustom:

Peraturan_C()fungsi akan terus memanggil fungsi yang ditentukan sampai kembali dengan sukses (fungsi yang dirujuk oleh parameterpfnkembalinolataupalsuketika dipanggil akan mencoba memanggil lagipfnMisalnya:_C(exchange.GetTicker). Interval uji ulang default adalah 3 detik, Anda dapat memanggil_CDelay()fungsi untuk mengatur interval percobaan ulang._CDelay(1000)berarti untuk mengubah interval percobaan ulang dari_C()fungsi ke 1 detik. Toleransi kesalahan dapat dilakukan untuk, namun tidak terbatas pada, fungsi berikut:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()Semua dapat dipanggil oleh_C()fungsi untuk toleransi kesalahan._C()fungsi tidak terbatas pada fungsi yang tercantum di atas toleransi kesalahan, parameterpfnadalah referensi fungsi daripada panggilan fungsi. Perhatikan bahwa itu_C(exchange.GetTicker), tidak_C(exchange.GetTicker()).

_Silang

Mengembalikan jumlah titik persimpangan arrayarr1dan arrayarr2.

Jumlah periode silang dari arrayarr1dan arrayarr2Aku tidak tahu. Nomor

_Cross ((arr1, arr2)

Elemen adalah array tipenumberAku tidak tahu. arr1 benar Array Elemen adalah array tipenumberAku tidak tahu. arr2 benar 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 dapat disimulasikan untuk menguji fungsi _Cross ((Arr1, Arr2):

Jika nilai pengembalian_Cross()fungsi adalah angka positif, ini menunjukkan periode penetrasi ke atas, jika ini adalah angka negatif, ini menunjukkan periode penetrasi ke bawah, 0 berarti sama dengan harga saat ini.Analisis dan instruksi penggunaan tentang fungsi bawaan _Cross.

JSONParse

FungsiJSONParse()digunakan untuk menganalisisJSON strings.

JSONobjek. objek

JSONParse (s)

JSONtali. s benar string

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

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

JSON string dengan nilai besar dapat dianalisis dengan benar, dan akan dianalisis nilai besar sebagai jenis string.JSONParse()fungsi tidak didukung dalam sistem backtest.

Log