Sumber dimuat naik... memuat...

Arahan FMZ API

Penulis:Sifar, Dicipta: 2020-04-20 10:19:00, Dikemas kini: 2023-04-12 14:44:56

pengiktirafan pesanan dagangan Harga: 1000, // Harga pesanan; perhatikan atribut pesanan pasaran ini mungkin 0 atau -1 Jumlah: 10, // Jumlah pesanan; perhatikan atribut ini pesanan pasaran mungkin jumlah wang, bukan nombor syiling DealAmount : 10, // Volume yang dilaksanakan; jika antara muka platform tidak menyediakan data jenis ini, mungkin menggunakan 0 untuk mengisi AvgPrice : 1000, // Harga purata yang dilaksanakan; perhatikan beberapa platform tidak menyediakan data ini. Status: 1, // Status pesanan; merujuk kepada status pesanan dalam pelarasan, seperti ORDER_STATE_CLOSED Jenis: 0, // Jenis pesanan; merujuk kepada jenis pesanan dalam pelarasan, seperti ORDER_TYPE_BUY Offset: 0 // Arah pesanan terbuka dan dekat dalam data pesanan niaga hadapan mata wang kripto;ORDER_OFFSET_OPEN adalah kedudukan terbuka, sementara ORDER_OFFSET_CLOSE adalah arah dekat ContractType : // Atribut ini adalah untuk pesanan segera, iaitu rentetan sifar; Sifat pesanan niaga hadapan adalah kod kontrak tertentu { C: $ 00FFFF }


##### 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 pasaran 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
}
Akaun

Maklumat akaun, dikembalikan oleh fungsiexchange.GetAccount()Data yang dikembalikan dalam struktur berkaitan dengan pasangan dagangan dan kod kontrak yang ditetapkan pada masa ini.

{
    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
}
Kedudukan

Untuk maklumat mengenai kedudukan yang dipegang dalam dagangan niaga hadapan,Arraydaripada 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 niaga hadapan cryptocurrency, memberi perhatian kepadaPositionarray struktur dikembalikan oleh fungsiexchange.GetPosition(). Bagi sifat dalam struktur data kedudukan, sepertiFrozenAmount, ProfitdanMargin, definisi data yang berbeza mungkin dikembalikan oleh objek pertukaran yang berbeza, apabila mereka memanggilexchange.GetPosition()Antara muka, untuk platform yang berbeza memberikan data yang berbeza.FrozenAmountadalah 0. Jika perlu mengira beberapa data, anda boleh menggunakan data sumber dalam atributInfountuk pengiraan dan analisis.

Fungsi Global

Versi ((()

Version()mengembalikan nombor versi semasa sistem; nilai balik: jenis rentetan.

Tidur ((Millisecond)

Sleep(Millisecond), fungsi tidur, membuat program berhenti untuk tempoh masa.Millisecondadalah jenis nombor. Unit parameter adalah milidetik, contohnya:Sleep(1000)Maksudnya tidur selama satu saat. Operasi sokongan dengan masa tidur kurang daripada 1 milisaat, seperti menetapkanSleep (0.1). Parameter minimum disokong adalah0.000001Satu nanosegund sama dengan1e-6 milliseconds.

Nota: Apabila anda menulis strategi dalamPythonBahasa, fungsiSleep(Millisecond)Ia tidak disyorkan untuk menggunakan fungsi ini.time.time(second)daripadatimeperpustakaan diPythonKerana apabila menggunakan fungsitime.time(second)dalam strategi, program strategi sebenarnya akan menunggu untuk beberapa saat (parametersecondadalah nombor kedua tetapan jeda), yang akan membawa kepada strategi yang sangat perlahan backtest.

IsVirtual ((()

IsVirtual(), untuk menentukan sama ada ia adalah backtest yang disimulasikan. Status backtest yang disimulasikan kembalitrue, dan bot sebenar kembalifalse.

Surat ((...)

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)adalah fungsi penghantaran mel. Nilai parameter: semua adalah jenis rentetan. Nilai pulangan: jenis bool;truedikembalikan selepas penghantaran yang berjaya.smtpServerBerkhidmat untuk peti mel penghantaransmtp; smtpUsernameadalah akaun peti mel;smtpPasswordadalah kata laluan STMP kotak mel;mailToadalah akaun peti mel penerima;titleadalah tajuk surat yang dihantar;bodyadalah kandungan surat yang dihantar, contohnya:

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 tidak selari fungsiMail: Penggunaannya sama 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
    

Nota: Alibaba Cloud pelayan mungkin menyekat beberapa port, supaya e-mel tidak boleh dihantar. jika anda perlu menukar port, anda boleh menambah nombor port dalam parameter pertama secara langsung, sebagai contoh,smtp.qq.com:587(QQmail), pelabuhan tersedia untuk ujian. Jika berlaku kesilapan:unencrypted connection, anda perlu menukar format parametersmtpServerdalam fungsiMailkepada:ssl://xxxxx.com:xxxSebagai contoh, kaedah SMTP ssl QQmail:ssl://smtp.qq.com:465atausmtp://xxxxx.com:xxx.

SetErrorFilter(...)

ErrorFilter(RegEx), penapisan log ralat. Nilai parameter: jenis rentetan. Kesalahan yang sepadan dengan ungkapan biasa ini tidak akan dimuat naik ke sistem log, dan ia boleh dipanggil beberapa kali (log disaring tidak akan ditulis ke fail pangkalan data ID bot yang sepadan dalam log / bot dalam kandungan docker, untuk mengelakkan pengembangan fail pangkalan data yang disebabkan oleh pelaporan ralat yang kerap).

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

Menapis maklumat ralat antara muka:

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. Nilai balik: jenis rentetan.

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

GetLastError()

GetLastError()mendapatkan maklumat ralat terkini; secara amnya, ia tidak perlu digunakan, kerana program akan memuat naik maklumat ralat ke sistem log secara automatik.GetLastError(), cache ralat akan dibersihkan; apabila dipanggil semula, maklumat ralat yang direkodkan kali terakhir 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);
}

DapatkanCommand()

GetCommand()mendapat perintah interaktif (utf-8). Ia mendapat perintah yang dihantar oleh antara muka interaktif strategi dan membersihkan cache; jika tidak ada perintah, ia mengembalikan rentetan kosong. Format perintah yang dikembalikan adalahbutton name: parameter; jika tidak ada parameter dalam kawalan interaktif (contohnya, kawalan butang tanpa kotak input), perintah adalah nama butang.

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 asas mempunyai struktur antrian untuk merakam arahan interaktif.GetCommand()dipanggil, perintah interaktif yang pertama masuk dalam barisan akan diambil (jika tidak ada perintah interaktif, rentetan kosong).

Contoh penggunaan kawalan interaktif; menetapkan kawalan interaktif pada antara muka penyuntingan strategi:

img

Reka bentuk kod 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 apabila token strategi dihasilkan, nilai pulangan fungsi adalah jenis rentetan. Aplikasi: contohnya, strategi perlu membuat had aset untuk penyewa yang berbeza. Nota: apabila token strategi dihasilkan, panjangMetatidak boleh melebihi 190 rentetan; fungsi, hanya terpakai untuk perdagangan sebenar dan memerlukan docker terbaru.GetMeta()Mengembalikan null.

Maklumat berkaitan yang ditunjukkan oleh permohonan

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 soket asal, sokongantcp, udp, tlsdanunixNilai parameter:Addressadalah jenis rentetan; unit adalah kedua; jika masa keluar, fungsiDial(...)mengembalikan nilai kosong.

Penerangan terperinciAddressParameter:

Perincian Parameter
Parameter untuk menetapkan fungsiDial Pisahkan dengan menambah|simbol selepas alamat biasa:wss://ws.okx.com:8443/ws/v5/public; jika ada|aksara dalam rentetan parameter, penggunaan||Sambungkan setiap parameter dengan&; contohnya, parameter proxy dan mampatan 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 yang berkaitan dengan mampatan data:compress=parameter value memampatkan adalah kaedah mampatan; parameter mampatan boleh dipilih darigzip_rawdangzip, dan lain-lain Jika kaedah gzip adalah gzip bukan standard, anda boleh menggunakan kaedah sambungan:gzip_raw, iaitu, menambah tetapancompress=gzip_rawselepas pemisah|, dan gunakan&simbol dan parameter mod seterusnya untuk dipisahkan.
Dalam protokol ws, parameter yang berkaitan dengan mampatan data:mode=parameter value mod adalah mod, termasuk tiga pilihan, iaitudual, senddanrecv. dualadalah dua arah, menghantar dan menerima data terdesak.sendadalah untuk menghantar data terdesak.recvadalah untuk menerima data yang dimampatkan dan mendekompresnya secara tempatan.
Parameter yang berkaitan untuk menetapkan stoking5 proxy:proxy=parameter value proxy adalah tetapan proxy ss5; format nilai parameter:socks5://name:pwd@192.168.0.1:1080; nama adalah nama pengguna pelayan ss5; pwd adalah kata laluan masuk pelayan ss5; 1080 adalah port pelayan ss5
Dalam protokol ws, parameter yang berkaitan untuk menetapkan auto-reconnect asas:reconnect=parameter value menyambung semula bermaksud sama ada untuk menetapkan menyambung semula;reconnect=trueadalah untuk memanggil sambungan semula; tetapan lalai adalah untuk tidak menyambung semula.
Dalam protokol ws, parameter yang berkaitan untuk menetapkan auto-reconnect asas:interval=parameter value interval ialah selang percubaan semula dalam milidetik,interval=10000adalah selang percubaan semula 10 saat, dan tetapan lalai adalah 1 saat, iaitu,interval=1000.
Dalam protokol ws, parameter yang berkaitan untuk menetapkan auto-reconnect asas:payload= parameter value muatan berguna adalah mesej langganan yang akan dihantar apabila ws menyambung semula, contohnya: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();
    }
}

Fungsireadmenyokong parameter berikut:

  • Apabila tiada parameter yang diteruskan, ia menyekat sehingga ada mesej, sepertiws.read().
  • Apabila menyampaikan parameter, tentukan masa lapang untuk mesej menunggu dalam unit milidetik; contohnya:ws.read(2000)menetapkan masa lapang menjadi dua saat (2000 milidetik).
  • Dua parameter berikut hanya sah untukwebsocket: Memindahkan parameter-1bermaksud untuk kembali dengan segera tanpa mengira sama ada ada ada mesej, sepertiws.read(-1). Memindahkan parameter-2bermaksud untuk kembali dengan segera tanpa mengira sama ada ada ada mesej, tetapi hanya mesej terbaru yang dikembalikan, dan mesej dalam penyangga akan dibuang, sepertiws.read(-2).

Fungsiread()Penerangan penyangga: Jika data yang didorong oleh protokol ws adalah selang lama antara strategiread()Struktur data buffer adalah antrian, dengan had atas 2000. Selepas melebihi 2000, data terkini dimasukkan ke dalam buffer, dan data tertua dihapuskan.

SenarioReadParameter fungsi Tiada parameter Parameter: -1 Parameter: -2 Parameter: 2000 (unit: ms)
Buffer sudah mempunyai data Kembalikan data tertua dengan segera Kembalikan data tertua dengan segera Kembalikan data terkini dengan segera. Kembalikan data tertua dengan segera
Tiada data dalam buffer Kembalikan data apabila terdapat data yang disekat Kembalikan null dengan segera Kembalikan null dengan segera Tunggu untuk 2000ms, pulangkan null jika tidak ada data, pulangkan data jika ada data
Sambungan Ws diputuskan atau lapisan bawah disambungkan semula Fungsi read() mengembalikan null, iaitu: , dan fungsi write() mengembalikan 0. Jika keadaan ini dikesan, fungsi close() boleh digunakan untuk menutup sambungan. Jika menetapkan sambungan semula secara automatik, ia tidak perlu ditutup, dan lapisan bawah sistem akan menyambung semula secara automatik
  • Sokongan protokol wss (WebSocket) Akses antara muka pasaran websocket Binance:

    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 pasaran antara muka:

    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 pasaran antara muka:

    var ws = null   
    
    function main(){
        var param = {"sub": "market.btcusdt.detail", "id": "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            while(1){
                var ret = ws.read()
                Log("ret:", ret)
                // Respond to heartbeat
                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()");
    }
    

    Antara muka pengesahan antara muka 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 log masuk = R"({ op: login, args: [{ apiKey: , passphrase: , stempel masa: , tanda: {y: i} }) "_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); log masuk balik; { C: $ 00FFFF }

kosong utama() { SetErrorFilter ((timeout); json posSubscribe = R"({ op: langganan, args: saluran: posisi, instType: any {y: i} }) "_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 satu eksit ((() { client_private.close(); Log ((keluar); {C:$0000FF}


#### 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 kandungan pulangan URL, jika parameter keduaPostDataadalah dalam bentuk rentetana=1&b=2&c=abc, dikemukakan olehPOST, yang lain olehPUT; parameterPostDataadalah{method:'PUT', data:'a=1&b=2&c=abc'}.

PeraturanPostDataparameter juga boleh menjadiJSON string.

Format parameterCookiesialah:a=10; b=20; dengan setiap parameter dipisahkan dengan titik koma;. Format parameterHeadersialah:User-Agent: Mobile\nContent-Type: text/html; dengan setiap parameter dipisahkan oleh watak baris baru\n.

Parameter kedua,PostData, boleh disesuaikan, sebagai contoh:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})Nota: jika anda perlu menetapkan masa lapang untukHttpQueryfungsi, anda boleh menambahtimeoutatribut dalam{method:'put',data:'a=1&B=2&C=ABC'}(default adalah 60 saat).

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

Parameter ketiga diperlukan untuk lulus rentetanCookie, tetapiPOSTtidak diperlukan untuk menetapkan parameter kedua kepada sifar. Semasa ujian simulasi, kerana URL tidak boleh disimulasikan, fungsi mengembalikan rentetan tetapDummy Data. Anda boleh menggunakan antara muka ini untuk menghantar mesej teks atau berinteraksi dengan antara muka API lain.

GETcontoh panggilan kaedah:HttpQuery("http://www.baidu.com"). POSTcontoh panggilan kaedah: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 tetapan proksi:

    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/");
    }
    
  • FungsiHttpQueryversi asynchronousHttpQuery_Go: Kaedah penggunaan adalah sama dengan fungsiexchange.Go, seperti mengakses antara muka awam bursa secara asynchronous untuk mendapatkan data pasaran 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 boleh diperoleh dengan menggunakanHttpQuery(...)untuk menghantar permintaan (hanya sokonganGETPermintaan) dalam sistem backtest.HttpQuery(...)akses akan cache data, manakala fungsiHttpQuery(...)mengembalikan data yang disimpan pada akses kedua ke URL yang sama (tidak lagi permintaan web sebenar).

    Kita boleh menjalankan program perkhidmatan pada pelayan atau peranti yang menjawab permintaan yang dihantar olehHttpQuery(...)dalam program strategi, dan program perkhidmatan dalam bahasa Go untuk ujian ditunjukkan seperti 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 menghantar permintaan semasa pengujian 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

    Ia menyokong transcoding data tindak balas dalam permintaan, dan ia juga menyokong pengekodan biasa. MenentukanPostDataParameter:{method: "GET", charset: "GB18030"}boleh merealisasikan transkoding data tindak balas (GB18030).

Enkod ((...)

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string), fungsi mengkodkan data mengikut parameter yang dilewatkan, dan mengembalikan nilai rentetan.

Parameteralgoadalah algoritma yang digunakan untuk pengiraan pengekodan, yang boleh ditetapkan kepada: raw (tanpa 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, ripke2b.256, blake2b.512, blake2s.1288, blake2s.256dataadalah data yang akan diproses.inputFormat/outputFormat/keyFormatparameter menyokong kaedah pengekodan sepertiraw, hex, base64danstring. JikakeyFormatparameter tidak kosong,keyparameter digunakan untuk penyulitan (HMAC), jika tidak lalaikeydigunakan. Apabila ```alg


Lebih lanjut