notifikasi pesanan perdagangan Harga: 1000, // Harga pemesanan; perhatikan atribut pesanan pasar ini mungkin 0 atau -1 Jumlah: 10, // Jumlah pemesanan; perhatikan atribut ini dari pesanan pasar mungkin jumlah uang, bukan nomor koin DealAmount : 10, // Volume yang dieksekusi; jika antarmuka platform tidak memberikan jenis data ini, mungkin menggunakan 0 untuk mengisi AvergPrice : 1000, // Harga rata-rata yang dilaksanakan; perhatikan beberapa platform tidak memberikan data ini. Status: 1, // Status order; merujuk pada status order dalam konstanta, seperti ORDER_STATE_CLOSED Tipe: 0, // Tipe order; merujuk pada tipe order dalam konstanta, seperti ORDER_TYPE_BUY Offset: 0 // Orde terbuka dan arah penutupan dalam data pesanan berjangka cryptocurrency;ORDER_OFFSET_OPEN adalah posisi terbuka, sementara ORDER_OFFSET_CLOSE adalah arah penutupan ContractType : // Atribut ini adalah untuk pesanan spot, yaitu string nol; Properti pesanan berjangka adalah kode kontrak tertentu {\cH00FFFF}


##### MarketOrder

Market depth order, that is, ```exchange.GetDepth()``` returns the data structure of the elements in the **Bids** and **Asks** arrays in the data.

```javascript
{
    Price   : 1000,              // Price
    Amount  : 1                  // Volume
}
Kedalaman

kedalaman pasar dikembalikan oleh fungsiexchange.GetDepth().

{
    Asks    : [...],             // The array of sell orders, namely MarketOrder array, sorted by price from low to high
    Bids    : [...],             // The array of buy orders, namely MarketOrder array, sorted by price from high to low
    Time    : 1567736576000      // Millisecond-level timestamp
}
Rekening

Informasi akun, dikembalikan oleh fungsiexchange.GetAccount()Data yang dikembalikan dalam struktur terkait dengan pasangan perdagangan dan kode kontrak yang saat ini ditetapkan.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    Balance         : 1000,      // The available amount of quote currency; if the trading pair is BTC_USDT in the spot trading, "balance" refers to the current USDT amount. In the USDT-margined futures contract, "balance" refers to the available margin amount in USDT
    FrozenBalance   : 0,         // Here "balance" refers to the frozen amount of the assets for pending orders
    Stocks          : 1,         // The available amount of base currency; if the trading pair is BTC_USDT in the spot trading, "stocks" refers to the current BTC amount. In the crypto-margined futures contract, "stocks" refers to the available margin amount (base currency)
    FrozenStocks    : 0          // Here "stocks" refers to the frozen amount of the assets for pending orders
}
Posisi

Untuk informasi tentang posisi yang dipegang dalam perdagangan berjangka,Arraydari iniPositionstruktur dikembalikan oleh fungsiexchange.GetPosition() function.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    MarginLevel     : 10,        // The leverage size of positions; if this data is not provided by the platform interface, fill in the data by calculation, possibly with errors
    Amount          : 100,       // Position volume; the contract quantity of positions is normally positive integer. Notice every platform might have different contract specifications, such as contract multiplier and value, etc., so the rules for ordering might be different; for example, Binance contract might order by 0.1
    FrozenAmount    : 0,         // The quantity of frozen positions, used as the number of temporary position freeze when close positions and pending orders
    Price           : 10000,     // Average position price; in principle, the attribute is the average price of the entire position (which does not involve in the settlement); if the platform interface does not provide the data, use the existing average position price of the platform to fill in (which involves in the settlement)
    Profit          : 0,         // Position floating profit and loss, namely the failure of realizing position profit and loss. If the platform interface does not provide the data, use other profit and loss data from the interface to fill in; the unit of the profit and loss values is the same as the unit of the current contract margin 

    Type            : 0,         // PD_LONG is a long position, while PD_SHORT is a short position
    ContractType    : "quarter", // Contract code; for more details, refer to the transmitted parameters in the description of the function "SetContractType"
    Margin          : 1          // Margin occupied by positions; if the platform interface does not provide the data, use 0 to fill in
}

Untuk cryptocurrency berjangka, perhatikanPositionstruktur array dikembalikan oleh fungsiexchange.GetPosition()Untuk atribut dalam struktur data posisinya, sepertiFrozenAmount, ProfitdanMargin, definisi data yang berbeda mungkin dikembalikan oleh objek pertukaran yang berbeda, ketika mereka memanggilexchange.GetPosition()Misalnya, beberapa bursa tidak termasuk data posisi beku, yang menunjukkanFrozenAmountadalah 0. Jika perlu menghitung beberapa data, Anda dapat menggunakan data sumber dalam atributInfountuk perhitungan dan analisis.

Fungsi Global

Versi ((()

Version()mengembalikan nomor versi sistem saat ini; nilai yang dikembalikan: jenis string.

Tidur ((Millisecond)

Sleep(Millisecond), fungsi tidur, membuat program berhenti untuk jangka waktu tertentu.Millisecondadalah jenis bilangan. Satuan parameter adalah milidetik, misalnya:Sleep(1000)berarti tidur selama satu detik. Operasi pendukung dengan waktu tidur kurang dari 1 milidetik, seperti pengaturanSleep (0.1). Parameter minimum yang didukung adalah0.000001Satu nanodetik sama dengan1e-6 milliseconds.

Catatan: Ketika Anda menulis strategi dalamPythonbahasa, fungsiSleep(Millisecond)digunakan untuk operasi, seperti interval jajak pendapat dan waktu menunggu.time.time(second)daritimeperpustakaan diPythonKarena ketika menggunakan fungsitime.time(second)dalam strategi, program strategi akan benar-benar menunggu untuk sejumlah detik tertentu (parametersecondadalah angka kedua dari pengaturan jeda), yang akan menyebabkan strategi backtest yang sangat lambat.

Apakah Virtual ((()

IsVirtual(), untuk menentukan apakah itu adalah backtest simulasi. Status backtest yang disimulasikan kembalitrue, dan robot sejati kembalifalse.

Surat ((...)

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)adalah fungsi mengirim surat. Nilai parameter: semua adalah jenis string. Nilai pengembalian: jenis bool;truedikembalikan setelah pengiriman berhasil.smtpServerberfungsi untuk mengirim kotak suratsmtp; smtpUsernameadalah akun kotak surat;smtpPasswordadalah kata sandi STMP dari kotak surat;mailToadalah akun kotak surat penerima;titleadalah judul surat yang dikirim;bodyadalah isi surat yang dikirim, misalnya:

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");
}
  • PeraturanMail_Gofungsi adalah versi asinkron dari fungsiMail: Penggunaannya mirip dengan fungsiexchange.Go.

    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
    

Catatan: Server Alibaba Cloud mungkin memblokir beberapa port, sehingga email tidak dapat dikirim. Jika Anda perlu mengubah port, Anda dapat menambahkan nomor port di parameter pertama langsung, misalnya,smtp.qq.com:587(QQmail), port tersedia untuk pengujian. Jika terjadi kesalahan:unencrypted connection, Anda perlu memodifikasi format parametersmtpServerdalam fungsiMailuntuk:ssl://xxxxx.com:xxxMisalnya, metode SMTP ssl dari QQmail:ssl://smtp.qq.com:465atausmtp://xxxxx.com:xxx.

SetErrorFilter ((...)

ErrorFilter(RegEx), menyaring log kesalahan. Nilai parameter: jenis string. Kesalahan yang dicocokkan dengan ekspresi reguler ini tidak akan diunggah ke sistem log, dan dapat dipanggil beberapa kali (log yang disaring tidak akan ditulis ke file database ID bot yang sesuai dalam log / bot dalam konten docker, untuk mencegah ekspansi file database yang disebabkan oleh laporan kesalahan yang sering terjadi).

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

function main() {
    // Randomly check a non-existent order with ID 123; intentionally make the interface report an error
    var order = exchange.GetOrder("123")
    Log(order)
    // Filter http502 errors and GetOrder interface errors; after set the error filter, the second time to call GetOrder no longer reports 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);
}

GetPid ((()

GetPid()mengembalikan ID proses bot. Mengembalikan nilai: jenis string.

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

GetLastError ((()

GetLastError()mendapatkan informasi kesalahan terbaru; umumnya, tidak perlu digunakan, karena program akan mengunggah informasi kesalahan ke sistem log secara otomatis.GetLastError(), cache kesalahan akan dihapus; ketika dipanggil lagi, informasi kesalahan yang dicatat terakhir kali tidak akan dikembalikan.

function main(){
    // Because the order with ID number of 123 does not exist, an error is reported
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // The type of order ID: TId; so no string can be passed in, and we can trigger it by placing an order that does not meet the exchange specifications
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

GetCommand ((()

GetCommand()mendapatkan perintah interaktif (utf-8). Ini mendapatkan perintah yang dikirim oleh antarmuka interaktif strategi dan menghapus cache; jika tidak ada perintah, itu mengembalikan string kosong. Format perintah yang dikembalikan adalahbutton name: parameter; jika tidak ada parameter dalam kontrol interaktif (misalnya, kontrol tombol tanpa kotak input), perintahnya adalah nama tombol.

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

Sistem yang mendasari memiliki struktur antrian untuk merekam perintah interaktif.GetCommand()disebut, perintah interaktif yang pertama masuk ke antrian akan diambil (jika tidak ada perintah interaktif, string kosong).

Contoh penggunaan kontrol interaktif; mengatur kontrol interaktif pada antarmuka pengeditan strategi:

img

Desain kode interaktif dalam strategi:

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 quantity")
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity: ", 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 quantity")
            elif arr[0] == "sell":
                Log("Sell, the control with quantity:", 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 quantity");
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity:", arr[1]);
            } else {
                Log("Other controls trigger:", arr);
            }
        }
        Sleep(1000);
    }
}

DapatkanMeta

FungsiGetMeta()Mengembalikan nilaiMetaditulis ketika token strategi dihasilkan, nilai balik fungsi adalah dari jenis string. Aplikasi: misalnya, strategi perlu membuat batasan aset untuk penyewa yang berbeda. Catatan: ketika token strategi dihasilkan, panjangMetatidak dapat melebihi 190 string; fungsi, hanya berlaku untuk perdagangan aktual dan membutuhkan docker terbaru.GetMeta()Mengembalikan null.

informasi terkait yang ditunjukkan oleh aplikasi

function main() {
    // The largest assets value of quote currency allowed by the strategy
    
    // Get the metadata generated when the strategy token is established
    var level = GetMeta()
    
    // Check the corresponding conditions of "Meta"
    if (level == "level1") {
        // "-1" indicates no limitation 
        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()
        
        // Check the assets value
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop the execution of the strategy trading logic 
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! 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, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue        
        
        # Other trading logic
        
        # Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! 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 the execution of the strategy trading logic
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!");
            continue;
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker);
    }
}

Pilih ((...)

Dial(Address, Timeout), akses Socket asli, dukungantcp, udp, tlsdanunixNilai parameter:Addressadalah jenis string; unit adalah kedua; jika waktu keluar, fungsiDial(...)Mengembalikan nilai kosong.

Deskripsi rinciAddressParameter:

Rincian Parameter
Parameter untuk mengatur fungsiDial Memisahkan dengan menambahkan|simbol setelah alamat normal:wss://ws.okx.com:8443/ws/v5/publicJika ada|karakter dalam string parameter, gunakan||Menghubungkan setiap parameter dengan&; misalnya, parameter proxy dan kompresi ss5 ditetapkan bersama:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv").
Dalam protokol ws, parameter terkait kompresi data:compress=parameter value kompresi adalah metode kompresi; parameter kompresi dapat dipilih darigzip_rawdangzip, dll Jika metode gzip adalah gzip non-standar, Anda dapat menggunakan metode ekstensi:gzip_raw, yaitu, tambahkan pengaturancompress=gzip_rawsetelah pemisah|, dan gunakan&simbol dan parameter mode berikutnya untuk dipisahkan.
Dalam protokol ws, parameter terkait kompresi data:mode=parameter value mode adalah mode, termasuk tiga pilihan, yaitudual, senddanrecv. dualadalah bidirectional, mengirim dan menerima data terkompresi.sendadalah untuk mengirim data terkompresi.recvadalah untuk menerima data terkompresi dan dekompresi secara lokal.
Parameter terkait untuk pengaturan kaus kaki5 proxy:proxy=parameter value proxy adalah pengaturan proxy ss5; format nilai parameter:socks5://name:pwd@192.168.0.1:1080; name adalah nama pengguna server ss5; pwd adalah password login server ss5; 1080 adalah port server ss5
Dalam protokol ws, parameter terkait untuk mengatur auto-reconnect yang mendasari:reconnect=parameter value menyambungkan kembali berarti apakah untuk mengatur menyambungkan kembali;reconnect=trueadalah untuk memanggil koneksi ulang; pengaturan default adalah untuk tidak menghubungkan kembali.
Dalam protokol ws, parameter terkait untuk mengatur auto-reconnect yang mendasari:interval=parameter value interval adalah interval percobaan ulang dalam milidetik,interval=10000adalah interval percobaan ulang 10 detik, dan pengaturan default adalah 1 detik, yaitu,interval=1000.
Dalam protokol ws, parameter terkait untuk mengatur auto-reconnect yang mendasari:payload= parameter value muatan adalah pesan langganan yang akan dikirim saat ws terhubung kembali, misalnya:payload=okok.
function main(){
    // Dial supports tcp://, udp://, tls://, unix:// protocol, so you can add a parameter to specify the number of seconds to timeout
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // "Write" can be followed by a numeric parameter to specify the timeout, and "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 to specify the timeout, in millisecond. Return null to indicate error, timeout or closed socket
            var buf = client.read()
            if (!buf) {
                 break
            }
            Log(buf)
        }
        client.close()
    }
}
def main():
    client = Dial("tls://www.baidu.com:443")
    if client:
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while True:
            buf = client.read()
            if not buf:
                break
            Log(buf)
        client.close()
void main() {
    auto client = Dial("tls://www.baidu.com:443");
    if(client.Valid) {
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            Log(buf);
        }
        client.close();
    }
}

Fungsireadmendukung parameter berikut:

  • Ketika tidak ada parameter yang diteruskan, itu memblokir sampai ada pesan, sepertiws.read().
  • Saat menyampaikan parameter, tentukan timeout untuk pesan menunggu dalam satuan milidetik; misalnya:ws.read(2000)menentukan timeout menjadi dua detik (2000 millisecond).
  • Dua parameter berikut hanya berlaku untukwebsocket: Mengirim parameter-1berarti untuk segera kembali terlepas dari apakah ada pesan, sepertiws.read(-1)Aku tidak tahu. Mengirim parameter-2berarti untuk kembali segera terlepas dari apakah ada pesan, tetapi hanya pesan terbaru yang dikembalikan, dan pesan di buffer akan dibuang, sepertiws.read(-2).

Fungsiread()deskripsi buffer: Jika data yang didorong oleh protokol ws adalah dari interval panjang antara strategiread()Struktur data buffer adalah antrian, dengan batas atas 2000. Setelah melebihi 2000, data terbaru masuk ke buffer, dan data tertua dihapus.

Skenario \ReadParameter fungsi Tidak ada parameter Parameter: -1 Parameter: -2 Parameter: 2000 (unit: ms)
Buffer sudah memiliki data Kembalikan data tertua segera Kembalikan data tertua segera Kembalikan data terbaru segera Kembalikan data tertua segera
Tidak ada data di buffer Kembalikan data ketika ada data yang diblokir Kembali null segera Kembali null segera Tunggu 2000ms, kembali null jika tidak ada data, kembali data jika ada data
Ws koneksi terputus atau lapisan bawah dihubungkan kembali Fungsi read() mengembalikan null, yaitu: , dan fungsi write() mengembalikan 0. Jika situasi ini terdeteksi, fungsi close() dapat digunakan untuk menutup koneksi.
  • Dukungan protokol wss (WebSocket) Akses Binance websocket pasar antarmuka:

    function main() {
        LogStatus("connecting...")
        // Access Binance websocket interface
        var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if (!client) {
            Log("connection failed, program exited")
            return
        }
        
        while (true) {
            // "read" only returns the obtained data after call "read" 
            var buf = client.read()      
            if (!buf) {
                break
            }
            var table = {
                type: 'table',
                title: 'Quote Chart',
                cols: ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed 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" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed 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" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed 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();
    }
    

    Akses OKX websocket market interface:

    var ws = null 
    function main(){
          var param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        // When call the function "Dial", specify "reconnect=true" and set to reconnect; specify "payload" as the message to be sent when reconnect. When websocket closes the connection, it will automatically reconnect and send the message
        ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            ws.write(JSON.stringify(param))
            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": ["spot/ticker:ETH-USDT"]})"_json;
             "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 Huobi websocket pasar antarmuka:

    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
                try {
                    var jsonRet = JSON.parse(ret)
                    if(typeof(jsonRet.ping) == "number") {
                        var strPong = JSON.stringify({"pong" : jsonRet.ping})
                        ws.write(strPong)
                        Log("respond 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 function ws.close()")
    }
    
    import json
    ws = None  
    
    def main():
        global ws
        param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
        if ws:
            while True:
                ret = ws.read()
                Log("ret:", ret)              
                # Respond to heartbeat 
                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 ping, send pong:", strPong, "#FF0000")
                except Exception as e:
                    Log("e:", e)
                    
                LogStatus("current time: ", _D())
                Sleep(1000)
        
    def onexit():
        ws.close()
        Log("execute function ws.close()")  
    
    using namespace std;
    void main() {
        json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
        auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
        if(ws.Valid) {
            while(true) {
                auto ret = ws.read();
                Log("ret:", ret);              
                // Respond to heartbeat
                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 ping, send pong:", strPong, "#FF0000");
                    }
                } catch(exception &e) 
                {
                    Log("e:", e.what());
                }
                
                LogStatus("current time:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        // ws.close();
        Log("execute function ws.close()");
    }
    

    Verifikasi antarmuka antarmuka websocket yang mengakses OKX:

      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)
            }]
        }    
        return login
    }    
    
    var client_private = null 
    function main() {
        // Because the read function adopts the timeout setting, the timeout error is filtered, otherwise there will be redundant error output
        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, we cannot subscribe to private channels immediately, we 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, connection closed, 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, connection closed, 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: , stamp waktu: , tanda : Aku tidak tahu. }) "_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); kembali login; {\cH00FFFF}

kosong utama (() { SetErrorFilter ((timeout); Json posSubscribe = R"({ op: langganan, args: [{ saluran: posisi, instType: any Aku tidak tahu. }) "_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, connection closed, 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;
        }
    }
}

}

tidak sah onexit (() { client_private.close ((); Log ((keluar); {\cH00FFFF}


#### HttpQuery(...)

```HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader)``` is an access of web URL. Parameter value: all are of string types.

Note:
* The ```HttpQuery(...)``` function only supports ```JavaScript``` language.
* For the ```Python``` language, you can use ```urllib``` to send http requests directly.

```HttpQuery(...)``` is mainly used to access the exchange interfaces that do not require signatures, such as public interfaces including market information.
An example of an API that does not require a signature to access OKX: the return value is a ```JSON``` string, which can be parsed by using the function ```JSON.parse()``` in JavaScript language strategies.

```js
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 urllib/urllib2 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);
}

Untuk mendapatkan konten kembali dari URL, jika parameter keduaPostDataadalah dalam bentuk stringa=1&b=2&c=abc, dikemukakan olehPOST, yang lain olehPUT; parameter dariPostDataadalah{method:'PUT', data:'a=1&b=2&c=abc'}.

PeraturanPostDataparameter juga bisa menjadiJSON string.

Format parameterCookiesadalah:a=10; b=20; dengan setiap parameter dipisahkan oleh titik koma;Aku tidak tahu. Format parameterHeadersadalah:User-Agent: Mobile\nContent-Type: text/html; dengan setiap parameter dipisahkan oleh karakter baris baru\n.

Parameter kedua,PostData, dapat disesuaikan, misalnya:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})Catatan: jika Anda perlu mengatur waktu untukHttpQueryfungsi, Anda dapat menambahkantimeoutatribut dalam{method:'put',data:'a=1&B=2&C=ABC'}(default adalah 60 detik).

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

Parameter ketiga diperlukan untuk melewati stringCookie, tapiPOSTtidak diperlukan untuk mengatur parameter kedua menjadi nol. Selama tes simulasi, karena URL tidak dapat disimulasikan, fungsi mengembalikan string tetapDummy DataAnda dapat menggunakan antarmuka ini untuk mengirim pesan teks atau berinteraksi dengan antarmuka API lainnya.

GETcontoh panggilan metode:HttpQuery("http://www.baidu.com"). POSTcontoh panggilan metode:HttpQuery("http://www.163.com", "a=1&b=2&c=abc").

Contoh panggilan untuk mengembalikanHeader:

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

    function main() {
        // This time, set proxy and send http request; without username and password, this http request will be sent through the proxy
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
    
        // Set the proxy and send http request this time, enter the user name and password, only the current call of HttpQuery takes effect, then call HttpQuery ("http://www.baidu.com") again so that the proxy will not be used
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    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/");
    }
    
  • FungsiHttpQueryadalah versi asinkronHttpQuery_Go: Metode penggunaan mirip dengan fungsiexchange.Go, seperti mengakses antarmuka publik bursa secara asinkron untuk memperoleh data pasar agregat.

    function main() {
        // Set up the first asyncthread
        var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
        // Set up the second asyncthread
        var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
        
        // Get the return value of the first asyncthread
        var tickers1 = r1.wait()
        // Get the return value of the second asyncthread
        var tickers2 = r2.wait()
        
        // Print result
        Log("tickers1:", tickers1)
        Log("tickers2:", tickers2)
    }
    
    # Not supported
    
    // Not supported
    
  • Penggunaan fungsiHttpQuery(...)dalam sistem backtest: Data dapat diperoleh dengan menggunakanHttpQuery(...)untuk mengirim permintaan (hanya dukunganGETPermintaan) dalam sistem backtest. batas 20 kali dikenakan dalam backtest danHttpQuery(...)akses akan cache data, sementara fungsiHttpQuery(...)Mengembalikan data cache pada akses kedua ke URL yang sama (tidak ada lagi permintaan web yang sebenarnya).

    Kita dapat menjalankan program layanan pada server atau perangkat yang menanggapi permintaan yang dikirim olehHttpQuery(...)dalam program strategi, dan program layanan dalam bahasa Go untuk pengujian ditampilkan sebagai berikut:

    package main
    import (
        "fmt"
        "net/http"
        "encoding/json"
    )
    
    func Handle (w http.ResponseWriter, r *http.Request) {
        defer func() {
            fmt.Println("req:", *r)
            ret := map[string]interface{}{
                "schema" : []string{"time","open","high","low","close","vol"},
                "data" : []interface{}{
                    []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                    []int64{1564316100000,9495160,9495160,9474260,9489460,338},
                },
            }
            b, _ := json.Marshal(ret)
            w.Write(b)
        }()
    }
    
    func main () {
        fmt.Println("listen http://localhost:9090")
        http.HandleFunc("/data", Handle)
        http.ListenAndServe(":9090", nil)
    }
    

    Gunakan fungsiHttpQuery(...)untuk mengirim permintaan selama backtesting strategi:

    function main() {
        // You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    void main() {
        //  You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    

    img

    Ini mendukung transcoding data respons dalam permintaan, dan juga mendukung pengkodean umum. MenentukanPostDataParameter:{method: "GET", charset: "GB18030"}dapat mewujudkan transcoding data respons (GB18030).

Mengenkode...

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string), fungsi mengkodekan data sesuai dengan parameter yang dilewati, dan mengembalikan nilai string.

Parameteralgoadalah algoritma yang digunakan untuk perhitungan pengkodean, yang dapat ditetapkan sebagai: raw (tidak ada algoritma), sign, signTx, md4, md5, sha256, sha512, sha1, keccak256, sha3.224, sha3.256, sha3.384, sha3.512, sha3.keccak256, sha3.keccak512, sha512.384, sha512.256, sha512.224, emd160, blake2rip2b.256, blake2b.512, blake2s.1288, blake2s.256dataadalah data yang akan diproses.inputFormat/outputFormat/keyFormatparameter mendukung metode pengkodean sepertiraw, hex, base64danstringAku tidak tahu. JikakeyFormatparameter tidak kosong,keyparameter digunakan untuk enkripsi (HMAC), jika tidak defaultkeydigunakan. Ketika ```alg