Tài nguyên đang được tải lên... tải...

Toàn cầu

Phiên bản

Trả về số phiên bản hiện tại của hệ thống.

Số phiên bản hệ thống hiện tại, chẳng hạn như:3.6. chuỗi

Phiên bản

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

Số phiên bản hệ thống là số phiên bản của chương trình docker.

Ngủ đi

Chức năng ngủ, khiến chương trình dừng lại trong một khoảng thời gian.

Giấc ngủ ((millisecond)

Cácmillisecondtham số được sử dụng để thiết lập thời gian ngủ và số milliseconds. millisecond đúng số

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

Ví dụ, khi thực hiệnSleep(1000)Nó hỗ trợ các hoạt động với thời gian ngủ dưới 1 millisecond, ví dụ như cài đặtSleep(0.1)Nó hỗ trợ một tham số tối thiểu của0.000001, tức là ngủ đông nanosecond, nơi 1 nanosecond bằng với1e-6hàng triệu giây. Khi viết các chiến lược trongPythonngôn ngữ,Sleep(millisecond)không được khuyến cáo sử dụng cáctime.sleep(second)chức năng củaPythonỪ.timeĐây là bởi vì sử dụng cáctime.sleep(second)chức năng trong một chiến lược làm cho chương trình chiến lược chờ đợi trong một khoảng thời gian thực sự khi backtesting (không bỏ qua các chuỗi thời gian của hệ thống backtesting), vì vậy nó làm cho chiến lược để backtest rất chậm.

IsVirtual

Xác định xem môi trường chạy của chiến lược có phải là một hệ thống backtesting không.

Chiến lược trả về một giá trị thực, ví dụ:truekhi chạy trong môi trường hệ thống backtesting. Chiến lược trả về một giá trị sai, ví dụ:falsekhi chạy trong môi trường giao dịch trực tiếp. bool

IsVirtual ((()

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

Xác định xem môi trường chạy hiện tại là một hệ thống backtesting, được sử dụng để tương thích với sự khác biệt giữa backtesting và giao dịch trực tiếp.

Bưu điện

Gửi email.

Một giao hàng email thành công trả về một giá trị thực sự, ví dụ:true, và một giao hàng thất bại trả về một giá trị sai, ví dụ:false. bool

Mail ((smtpServer, smtpUsername, smtpPassword, mailTo, tiêu đề, phần thân)

Sử dụng để xác địnhSMTPđịa chỉ dịch vụ của người gửi email. SMTPServer đúng chuỗi Được sử dụng để chỉ định địa chỉ email của người gửi email. smtpUsername đúng chuỗi CácSMTPmật khẩu cho hộp thư của người gửi email. smtpPassword đúng chuỗi Sử dụng để chỉ định địa chỉ email của người nhận email. mailTo đúng chuỗi Tên email. tiêu đề đúng chuỗi Thư điện tử. cơ thể đúng chuỗi

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

CácsmtpPasswordtham số thiết lập mật khẩu choSMTPdịch vụ, không phải mật khẩu hộp thư. Khi thiết lậpsmtpServertham số, nếu bạn cần thay đổi cổng, bạn có thể thêm số cổng trực tiếp trong tham sốsmtpServerVí dụ: QQ mailsmtp.qq.com:587, có sẵn để thử nghiệm. Nếu báo cáo lỗi:unencryped connection, bạn cần phải sửa đổismtpServercủaMailđịnh dạng tham số là:ssl://xxx.com:xxx, ví dụ:sslphương phápSMTPđối với thư từ QQ:ssl://smtp.qq.com:465hoặcsmtp://xxx.com:xxx. Nó không hoạt động trong hệ thống backtesting.

{@fun/Global/Mail_Go Mail_Go}

Mail_Go

Phiên bản không đồng bộ củaMail function.

CácMail_Gohàm trả về một đối tượng đồng thời ngay lập tức, và bạn có thể sử dụngwaitMột giao hàng thư thành công trả về một giá trị thực, ví dụ,true, và một giao hàng thất bại trả về một giá trị sai, ví dụ:false. đối tượng

Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, tiêu đề, phần thân)

Nó được sử dụng để xác địnhSMTPđịa chỉ dịch vụ của người gửi email. SMTPServer đúng chuỗi Nó được sử dụng để chỉ định địa chỉ email của người gửi email. smtpUsername đúng chuỗi CácSMTPmật khẩu cho hộp thư của người gửi email. smtpPassword đúng chuỗi Nó được sử dụng để chỉ định địa chỉ email của người nhận email. mailTo đúng chuỗi Tên email. tiêu đề đúng chuỗi Thư điện tử. cơ thể đúng chuỗi

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

Nó không hoạt động trong hệ thống backtesting.

{@fun/Global/Mail Mail}

SetErrorFilter

Lưu trữ lỗi lọc.

SetErrorFilter ((filter)

Dòng biểu thức thông thường. bộ lọc đúng chuỗi

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

lọc các lỗi phổ biến.

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

lọc thông báo lỗi giao diện.

Các nhật ký lỗi phù hợp với biểu thức thường này sẽ không được tải lên hệ thống nhật ký. Bạn có thể gọi nó nhiều lần (không giới hạn số lần) để đặt nhiều điều kiện lọc. Các biểu thức thường được đặt nhiều lần sẽ được tích lũy và có hiệu lực cùng một lúc. Bạn có thể đặt một chuỗi trống để đặt lại biểu thức thường được sử dụng để lọc nhật ký lỗi:SetErrorFilter(""). Các nhật ký được lọc không còn được ghi vào tệp cơ sở dữ liệu tương ứng với ID giao dịch trực tiếp trong thư mục docker để ngăn chặn báo cáo lỗi thường xuyên từ việc phồng lên tệp cơ sở dữ liệu.

GetPid

Nhận ID giao dịch trực tiếp.

Trả lại ID quá trình giao dịch trực tiếp. chuỗi

GetPid ((()

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

GetLastError

Nhận được thông báo lỗi cuối cùng.

Thông báo lỗi cuối cùng. chuỗi

GetLastError()

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

Nó không hoạt động trong hệ thống backtesting.

GetCommand

Nhận lệnh tương tác chiến lược.

Định dạng của lệnh trả về làControlName:Data. ControlNamelà tên của kiểm soát, vàDatalà dữ liệu được nhập vào điều khiển. Nếu điều khiển tương tác không có hộp đầu vào, hộp thả xuống và các thành phần khác (ví dụ như một điều khiển nút không có hộp đầu vào) thì định dạng lệnh được trả về làControlName, chỉ trả về tên điều khiển. chuỗi

GetCommand()

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

Khám phá lệnh tương tác và sử dụngLogchức năng để xuất lệnh tương tác khi nó được phát hiện.

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

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

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

Ví dụ, điều khiển tương tác chiến lược thêm một điều khiển mà không có hộp đầu vào, điều khiển tương tác được đặt tên là:buy, thông tin mô tả kiểm soát là:buy, đó là một điều khiển nút. Tiếp tục bằng cách thêm một điều khiển với một hộp đầu vào. Điều khiển tương tác được đặt tên là:sellvà thông báo mô tả kiểm soát là:sell, đó là một điều khiển tương tác là sự kết hợp của một nút và một hộp đầu vào. Mã tương tác được thiết kế trong chiến lược để đáp ứng các điều khiển tương tác khác nhau:

Nó không hoạt động trong hệ thống backtesting.

GetMeta

Nhận giá trị của Meta được viết khi tạo mã đăng ký chiến lược.

Metadữ liệu. chuỗi

GetMeta()

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

Ví dụ kịch bản ứng dụng: Sử dụngMetađể hạn chế số lượng tài sản được điều hành bởi chiến lược.

kịch bản ứng dụng: cần phải làm vốn giới hạn cho các nhà thuê chiến lược khác nhau.MetaGiá trị được đặt khi tạo mã đăng ký không thể vượt quá 190 ký tự vàGetMeta()Nếu không có siêu dữ liệu (Meta) được đặt khi tạo mã đăng ký chiến lược,GetMeta()hàm trả về null. Nó không hoạt động trong hệ thống backtesting.

Nhập

Đối với nguyên thủySockettiếp cận, hỗ trợtcp, udp, tls, unixHỗ trợ 4 giao thức truyền thông phổ biến:mqtt, nats, amqp, kafka. Hỗ trợ kết nối với cơ sở dữ liệu:sqlite3, mysql, postgres, clickhouse.

CácDial()hàm trả về null nếu nó hết thời gian. Một cuộc gọi bình thường trả về một đối tượng kết nối có ba phương thức:read, writeclose.readphương pháp được sử dụng để đọc dữ liệu,writephương pháp được sử dụng để gửi dữ liệu vàclosephương pháp được sử dụng để đóng kết nối. Cácreadphương pháp hỗ trợ các thông số sau:

  • Khi không có tham số nào được truyền, nó chặn cho đến khi một thông báo có sẵn và trả về, chẳng hạn nhưws.read().
  • Khi được truyền vào như một tham số, đơn vị là milliseconds, xác định thời gian chờ tin nhắn. Ví dụ:ws.read(2000)chỉ định thời gian nghỉ là hai giây (2000 millisecond).
  • Hai tham số sau đây chỉ có giá trị cho WebSocket: Chuyển parameter-1có nghĩa là chức năng trả về ngay lập tức, bất kể có hoặc không có tin nhắn, ví dụ:ws.read(-1). Chuyển parameter-2có nghĩa là hàm trả về ngay lập tức với hoặc không có tin nhắn, nhưng chỉ có tin nhắn mới nhất được trả về, và tin nhắn đệm được loại bỏ. Ví dụ:ws.read(-2).

read()Mô tả bộ đệm chức năng: Dữ liệu đến được đẩy bởi giao thức WebSocket có thể gây tích lũy dữ liệu nếu khoảng thời gian giữa chiến lượcread()Dữ liệu này được lưu trữ trong bộ đệm, có cấu trúc dữ liệu của một hàng đợi với tối đa 2000.

Kịch bản Không có tham số Parameter: -1 Parameter: -2 Parameter: 2000, trong millisecond
Dữ liệu đã ở trong bộ đệm Trả lại dữ liệu cũ nhất ngay lập tức Trả lại dữ liệu cũ nhất ngay lập tức Trả lại dữ liệu mới nhất ngay lập tức Trả lại dữ liệu cũ nhất ngay lập tức
Không có dữ liệu trong bộ đệm Trở lại khi bị chặn dữ liệu Trả về null ngay lập tức Trả về null ngay lập tức Chờ 2000 ms, trả về null nếu không có dữ liệu, trả về null nếu có dữ liệu
Kết nối WebSocket bị ngắt kết nối hoặc kết nối lại bởi cơ sở Read () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () ()

đối tượng

Nhập số (địa chỉ) Nhập (địa chỉ, thời gian)

Địa chỉ yêu cầu. địa chỉ đúng chuỗi giây thời gian nghỉ, thời gian nghỉ sai số

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

Ví dụ về một cuộc gọi hàm Dial:

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

Để truy cập giao diện WebSocket ticker của Binance:

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

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

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

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

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

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

Truy cập vào giao diện ticker WebSocket OKX:

var ws = null               

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

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

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

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

Truy cập vào giao diện ticker WebSocket của Huobi:

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

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

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

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

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

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

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

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

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

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

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

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

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

Để truy cập giao diện xác thực WebSocket OKX:

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

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

Đối tượng kết nối được trả về bởi hàm Dial khi kết nối với cơ sở dữ liệu có hai hàm phương thức độc đáo cho nó:

  • exec(sqlString): Được sử dụng để thực thi lệnh SQL theo cách tương tự nhưDBExec() function.
  • fd(): Cácfd()hàm trả về một xử lý (ví dụ, biến xử lý là xử lý) để được sử dụng bởi các luồng khác để kết nối lại (ngay cả khi đối tượng được tạo bởi Dial đã được đóng bởi việc thực hiệnclose()chức năng để đóng kết nối) bằng cách đi tay cầm vàoDial()chức năng, ví dụ,Dial(handle)Kết nối tái sử dụng. Sau đây là một ví dụ về chức năng Dial kết nối với mộtsqlite3 database.

Thông tin chi tiếtaddresstham số, tách biệt với|ký hiệu sau địa chỉ thông thường:wss://ws.okx.com:8443/ws/v5/publicNếu có.|ký tự trong chuỗi tham số, sau đó||Phần sau đó là một số cài đặt tham số chức năng, và mỗi tham số được kết nối với&Ví dụ, cácss5Các thông số thay thế và nén có thể được đặt cùng nhau như sau:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Các chức năng được hỗ trợ bởi tham số địa chỉ của chức năng Dial Mô tả tham số
Các tham số liên quan đến nén dữ liệu giao thức WebSocket: compress=parameter value compress là phương pháp nén, các tùy chọn tham số nén là: gzip_raw, gzip, vv Nếu phương pháp gzip không phải là gzip tiêu chuẩn, bạn có thể sử dụng phương pháp mở rộng: gzip_raw
Các tham số liên quan đến nén dữ liệu giao thức WebSocket: mode=parameter value chế độ là chế độ nén, tham số chế độ có thể là kép, gửi, recv. kép là nén hai chiều, gửi dữ liệu nén, nhận dữ liệu nén. gửi là gửi dữ liệu nén. recv là nhận dữ liệu nén, giải nén cục bộ.
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: reconnect=parameter value reconnect là đặt reconnect, reconnect=true là bật reconnect. mặc định là không reconnect khi tham số này không được đặt.
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: interval=parameter value interval là khoảng thời gian thử lại, trong milliseconds, interval=10000 là khoảng thời gian thử lại 10 giây, mặc định là 1 giây khi nó không được thiết lập, tức là interval=1000.
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: payload=parameter value payload là thông báo đăng ký cần được gửi khi WebSocket được kết nối lại, ví dụ: payload=okokok.
Các tham số liên quan đến vớ5 proxy: proxy=giá trị tham số proxy là cài đặt proxy ss5, định dạng giá trị tham số: socks5://name:pwd@192.168.0.1:1080, tên là tên người dùng máy chủ ss5, pwd là mật khẩu đăng nhập máy chủ ss5, 1080 là cổng dịch vụ ss5.

CácDial()chức năng chỉ được hỗ trợ cho giao dịch trực tiếp. Khi kết nối với cơ sở dữ liệu bằng chức năng Dial, chuỗi kết nối được viết với tham chiếu đến dự án trình điều khiển ngôn ngữ go cho mỗi cơ sở dữ liệu.

Cơ sở dữ liệu được hỗ trợ Các dự án thúc đẩy Dây kết nối Nhận xét
sqlite3 github.com/mattn/go-sqlite3 sqlite3://file:test.db?cache=shared&mode=memory Cácsqlite3://tiền tố chỉ ra rằng một cơ sở dữ liệu sqlite3 đang được sử dụng, ví dụ gọi:Dial("sqlite3://test1.db")
MySQL github.com/go-sql-driver/mysql mysql://username:yourpassword@tcp(localhost:3306) / cơ sở dữ liệu của bạn?charset=utf8mb4
sau github.com/lib/pq postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432
clickhouse github.com/ClickHouse/clickhouse-go clickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase

Xin lưu ý rằng khipayloadnội dung được đặt trongaddresstham số chứa ký tự=hoặc các ký tự đặc biệt khác, nó có thể ảnh hưởng đến việc phân tích củaaddresstham số củaDialchức năng, chẳng hạn như ví dụ sau.

ví dụ gọi backPack Exchange websocket giao diện riêng:

var client = null

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

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

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

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

function onexit() {
    client.close()
}

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

Các cuộc gọi sau trong mã hoạt động tốt:

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

Nếu bạn viết nó trực tiếp vàopayload, nó sẽ không hoạt động đúng cách, ví dụ:

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

Hiện tại, chỉ có JavaScript hỗ trợ việc sử dụngmqtt, nats, amqp, vàkafkaMã chiến lược ngôn ngữ JavaScript được sử dụng như một ví dụ để hiển thị việc sử dụng bốn giao thức:mqtt, nats, amqp, vàkafka:

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

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

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

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

        Sleep(1000)
    }
}

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

Tài liệu chi tiết:Khám phá FMZ: Thực hành giao thức giao tiếp giữa các chiến lược giao dịch trực tiếp

HttpQuery

Gửi yêu cầu HTTP.

Trả về dữ liệu phản hồi của yêu cầu.JSONstring, nó có thể được phân tích bởi cácJSON.parse()chức năng trongJavaScriptchiến lược ngôn ngữ,json::parse()chức năng trongC++Nếu debug được đặt thành true trong cấu trúc tùy chọn, giá trị trả về là một đối tượng (JSON); nếu debug được đặt thành false, giá trị trả về là một chuỗi. chuỗi, đối tượng

HttpQuery ((url) HttpQuery ((url, tùy chọn)

URL yêu cầu HTTP. url đúng chuỗi Ví dụ, cài đặt liên quan đến yêu cầu HTTP có thể được cấu trúc như sau:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    profile: "chrome_103",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • profile: Được sử dụng để mô phỏng trình duyệttlsdấu vân tay. Các cài đặt được hỗ trợ bao gồm các tùy chọn sau: chrome_:"chrome_103", "chrome_104", "chrome_105", "chrome_106", "chrome_107", "chrome_108", "chrome_109", "chrome_110", "chrome_111", "chrome_112", "chrome_117" Safari_:"safari_15_6_1", "safari_16_0", "safari_ipad_15_6", "safari_ios_15_5", "safari_ios_15_6", "safari_ios_16_0" Firefox_:"firefox_102", "firefox_104", "firefox_105", "firefox_106", "firefox_108", "firefox_110", "firefox_117" opera_:"opera_89", "opera_90", "opera_91" Zalando:"zalando_android_mobile", "zalando_ios_mobile" Nike_:"nike_ios_mobile", "nike_android_mobile" nhà chọc mây:"cloudscraper" mms_:"mms_ios" mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2" xác nhận:"confirmed_ios", "confirmed_android" Được rồi."okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • debug: Khi nó được thiết lập thànhtrue, cácHttpQueryfunction call trả về toàn bộ tin nhắn trả lời.false, chỉ có dữ liệu trongBodycủa tin nhắn trả lời được trả về.
  • Thời gian dừng: cài đặt thời gian dừng, đặt 1000 có nghĩa là thời gian dừng 1 giây.
  • Charset: Nó hỗ trợ chuyển mã dữ liệu phản hồi được yêu cầu, chẳng hạn như GB18030. Tất cả các trường trong cấu trúc này là tùy chọn, ví dụ:profiletrường có thể bị bỏ qua.

các lựa chọn sai đối tượng

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

Một ví dụ về việc truy cập giao diện API ticker công khai OKX.

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

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

Chức năng HttpQuery sử dụng cài đặt proxy.

CácHttpQuery()chỉ hỗ trợ chức năngJavaScript, C++ngôn ngữ,Pythonngôn ngữ có thểurllibthư viện để gửi các yêu cầu HTTP trực tiếp.HttpQuery()chủ yếu được sử dụng để truy cập các giao diện của sàn giao dịch không yêu cầu chữ ký, chẳng hạn như giao diện công khai như thông tin ticker.HttpQuery()có thể được sử dụng trong hệ thống backtesting để gửi yêu cầu (chỉGETCác yêu cầu được hỗ trợ) để thu thập dữ liệu.URLs, vàHttpQuery()khi cùng mộtURLđược truy cập lần thứ hai,HttpQuery()chức năng trả về dữ liệu được lưu trong bộ nhớ cache và không có yêu cầu mạng thực tế nào xảy ra.

{@fun/Global/HttpQuery_Go HttpQuery_Go}

HttpQuery_Go

Gửi một yêu cầu HTTP, một phiên bản không đồng bộ củaHttpQuery function.

CácHttpQuery_Go()hàm ngay lập tức trả về một đối tượng đồng thời có thể được sử dụng để có được kết quả của một yêu cầu HTTP sử dụngwaitphương pháp củaJSON.parse()chức năng có thể được sử dụng để phân tích cácJSON.parse()chức năng trongJavaScriptchiến lược ngôn ngữ
đối tượng

HttpQuery_Go ((url) HttpQuery_Go ((url, tùy chọn)

URL yêu cầu HTTP. url đúng chuỗi Ví dụ, cài đặt liên quan đến yêu cầu HTTP có thể được cấu trúc như sau:

{
    method: "POST",
    body: "a=10&b=20&c=30",
    charset: "UTF-8",
    cookie: "session_id=12345; lang=en",
    // profile: "",
    debug: false,
    headers: {"TEST-HTTP-QUERY": "123"},
    timeout: 1000
}
  • profile: Được sử dụng để mô phỏng trình duyệttls fingerprints.
  • debug: Khi nó được thiết lập thànhtrue, cái nàyHttpQuery_Gofunction call trả về toàn bộ tin nhắn trả lời.false, chỉ có dữ liệu trongBodycủa tin nhắn trả lời được trả về.
  • Thời gian dừng: cài đặt thời gian dừng, đặt 1000 có nghĩa là thời gian dừng 1 giây. Tất cả các trường trong cấu trúc này là tùy chọn, ví dụ:profiletrường có thể bị bỏ qua.

các lựa chọn sai đối tượng

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

Truy cập không đồng bộ vào giao diện công khai của sàn giao dịch cho dữ liệu ticker tổng hợp.

CácHttpQuery_Go()chỉ hỗ trợ chức năngJavaScript, cácPythonngôn ngữ có thể được sử dụng vớiurllibthư viện để gửi các yêu cầu HTTP trực tiếp.HttpQuery_Go()chủ yếu được sử dụng để truy cập các giao diện không yêu cầu chữ ký trên sàn giao dịch, chẳng hạn như giao diện công khai như thông tin ticker.HttpQuery_Gokhông được hỗ trợ trong hệ thống backtesting.

{@fun/Global/HttpQuery HttpQuery}

Mã hóa

Chức năng này mã hóa dữ liệu theo các thông số được truyền vào.

CácEncodechức năng trả về dữ liệu sau khi mã hóa và mã hóa. chuỗi

Mã hóa ((algo, inputFormat, outputFormat, data) Mã hóa ((algo, inputFormat, outputFormat, data, keyFormat, key)

Các thông sốalgolà thuật toán được sử dụng trong tính toán mã hóa.raw(không sử dụng thuật toán), "dấu hiệu", 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, emdrip160, blake2b.256, 2b.512, blake2s.128, blake2s.256 Các thông số.algocũng hỗ trợ: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk, mã hóa và giải mã chuỗi.algocũng hỗ trợ: thuật toán ed25519. Hỗ trợ sử dụng các thuật toán băm khác nhau, ví dụ như tham sốalgocó thể được viết như ed25519.md5, ed25519.sha512, v.v. Nó hỗ trợed25519.seedtính toán. algo đúng chuỗi Sử dụng để xác định định dạng dữ liệu củadatacác tham số.inputFormattham số có thể được thiết lập như một trong những điều sau:raw, hex, base64, string. raw nghĩa là dữ liệu là dữ liệu thô, hex nghĩa là dữ liệu làhexđược mã hóa, base64 có nghĩa là dữ liệu làbase64được mã hóa, và string có nghĩa là dữ liệu là một chuỗi. inputFormat đúng chuỗi Sử dụng để xác định định dạng dữ liệu của đầu ra.outputFormattham số có thể được thiết lập như một trong những điều sau:raw, hex, base64, string. raw nghĩa là dữ liệu là dữ liệu thô, hex nghĩa là dữ liệu làhexđược mã hóa, base64 có nghĩa là dữ liệu làbase64được mã hóa, và string có nghĩa là dữ liệu là một chuỗi. outputFormat đúng chuỗi Các thông sốdatalà dữ liệu được xử lý. dữ liệu đúng chuỗi Sử dụng để xác định định dạng dữ liệu củakeycác tham số.keytham số có thể được thiết lập như một trong những điều sau:raw, hex, base64, string. raw nghĩa là dữ liệu là dữ liệu thô, hex nghĩa là dữ liệu làhexđược mã hóa, base64 có nghĩa là dữ liệu làbase64được mã hóa, và string có nghĩa là dữ liệu là một chuỗi. keyFormat sai chuỗi Các thông sốkeylà khóa bí mật được sử dụng choHMACmã hóa.keyđược yêu cầu khi tham sốalgođược thiết lập thànhsignhoặcsignTx.keytham số không được sử dụng choHMACmã hóa khialgotham số được đặt thành raw (vì thuật toán phải được chỉ định cho mã hóa HMAC). chìa khóa sai chuỗi

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

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

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

Ví dụ về gọi hàm mã hóa.

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

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

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

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

Các thông sốalgocũng hỗ trợ: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk để mã hóa và giải mã chuỗi.

CácEncode()chức năng chỉ được hỗ trợ cho giao dịch trực tiếp.keykeyFormatcác thông số không được vượt qua, sau đókeymã hóa không được sử dụng.

UnixNano

Hãy lấy dấu thời gian nanosecond của khoảnh khắc hiện tại.

CácUnixNano()hàm trả về dấu thời gian nanosecond. số

UnixNano ((()

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

Nếu bạn cần lấy dấu thời gian millisecond, bạn có thể sử dụng mã sau:

{@fun/Global/Unix Unix}

Unix

Nhận thời gian của khoảnh khắc hiện tại ở tầng hai.

Trả lại dấu thời gian cấp hai. số

Unix()

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

{@fun/Global/UnixNano UnixNano}

GetOS

Nhận thông tin hệ thống của thiết bị nơi docker nằm.

Thông tin hệ thống. chuỗi

GetOS()

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

Ví dụ, một cuộc gọi đếnGetOS()chức năng cho một docker chạy trênMac OShệ điều hành có thể trả về:darwin/amd64Bởi vì máy tính Apple có nhiều kiến trúc phần cứng.darwinlà tên củaMac OS system.

MD5

Tính toán MD5 hash của tham sốdata.

Giá trị hash của MD5. chuỗi

MD5 (dữ liệu)

Dữ liệu đòi hỏi tính toán MD5. dữ liệu đúng chuỗi

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

Gọi choMD5("hello world")hàm, giá trị trả về là:5eb63bbbe01eeed093cb22bb8f5acdc3.

{@fun/Global/Encode Encode}

DBExec

Các chức năng giao diện cơ sở dữ liệu.

Một đối tượng chứa kết quả của việc thực hiện mộtsqltuyên bố, ví dụ:


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

đối tượng

DBExec ((sql)

sqlchuỗi lệnh. sql đúng chuỗi

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

Hỗ trợ cơ sở dữ liệu trong bộ nhớDBExecCác thông số chức năng, nếusqltuyên bố bắt đầu với:Nó phù hợp với các hoạt động cơ sở dữ liệu không yêu cầu lưu liên tục, ví dụ:

function main() {
    var strSql = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ].join("")
    var ret = DBExec(strSql)
    Log(ret)
}
def main():
    arr = [
        "CREATE TABLE TEST_TABLE(", 
        "TS INT PRIMARY KEY NOT NULL,",
        "HIGH REAL NOT NULL,", 
        "OPEN REAL NOT NULL,", 
        "LOW REAL NOT NULL,", 
        "CLOSE REAL NOT NULL,", 
        "VOLUME REAL NOT NULL)"
    ]
    strSql = ""
    for i in range(len(arr)):
        strSql += arr[i]
    ret = DBExec(strSql)
    Log(ret)
void main() {
    string strSql = "CREATE TABLE TEST_TABLE(\
        TS INT PRIMARY KEY NOT NULL,\
        HIGH REAL NOT NULL,\
        OPEN REAL NOT NULL,\
        LOW REAL NOT NULL,\
        CLOSE REAL NOT NULL,\
        VOLUME REAL NOT NULL)";
    auto ret = DBExec(strSql);
    Log(ret);
}

Tạo một cái bàn.

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

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

Thêm, xóa, kiểm tra và thay đổi các bản ghi trong bảng.

Chức năngDBExec()có thể vận hành cơ sở dữ liệu giao dịch trực tiếp (SQLite cơ sở dữ liệu) bằng cách đi qua các tham số.SQLiteHệ thống lưu trữ bảng trong cơ sở dữ liệu giao dịch trực tiếp:kvdb, cfg, log, profit, chart, không được sử dụng trên những bàn này.Giao dịchkhông được hỗ trợ và không nên thực hiện các hoạt động như vậy, có thể gây ra xung đột trong hệ thống.DBExec()chức năng chỉ được hỗ trợ cho giao dịch trực tiếp.

{@fun/Global/_G _G}

UUID

Tạo một UUID.

32 bit UUID. chuỗi

UUID (()

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

CácUUID()chức năng chỉ hỗ trợ giao dịch trực tiếp.

EventLoop

Nghe cho các sự kiện, nó trở lại khi có bất kỳWebSocketdữ liệu có thể đọc hoặc các nhiệm vụ đồng thời, chẳng hạn như:exchange.Go(), HttpQuery_Go(), v.v. được hoàn thành.

Nếu đối tượng được trả về không phải là giá trị null,Eventchứa trong nội dung trả về là loại kích hoạt sự kiện. Ví dụ: cấu trúc giá trị trả về sau:

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

đối tượng

EventLoop ((() EventLoop ((timeout)

Các thông sốtimeoutlà thiết lập timeout, trong milliseconds.timeoutchờ cho một sự kiện xảy ra trước khi trả về nếu nó được thiết lập là 0. Nếu nó lớn hơn 0, nó đặt sự kiện để chờ đợi thời gian hết, và trả về sự kiện gần đây nhất ngay lập tức nếu nó nhỏ hơn 0. thời gian nghỉ sai số

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

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

Cuộc gọi đầu tiên đếnEventLoop()chức năng trong mã khởi tạo cơ chế cho sự kiện nghe, và nếu đầu tiênEventLoop()gọi bắt đầu sau khi callback sự kiện, nó sẽ bỏ lỡ các sự kiện trước đó. Hệ thống cơ bản gói một cấu trúc hàng đợi lưu trữ tối đa 500 callback sự kiện.EventLoop()chức năng không được gọi trong thời gian để lấy chúng ra trong quá trình thực thi chương trình, sau đó callback sự kiện bên ngoài bộ nhớ cache 500 sẽ bị mất.EventLoop()chức năng không ảnh hưởng đến hàng đợi bộ nhớ cache của hệ thống WebSocket cơ bản hoặc bộ nhớ cache của các chức năng đồng thời nhưexchange.Go()Đối với các bộ nhớ cache này, vẫn cần phải sử dụng các phương pháp tương ứng để lấy dữ liệu.EventLoop()chức năng cho dữ liệu đã được truy xuất trước khiEventLoop()Mục đích chính củaEventLoop()Các hoạt động của hệ thống mạng được xác định bởi các sự kiện.EventLoop()function trả về một sự kiện, chỉ đi qua tất cả các nguồn dữ liệu. ví dụ, kết nối WebSocket, đối tượng được tạo ra bởiexchange.Go()cố gắng lấy dữ liệu.EventLoop()chức năng chỉ hỗ trợ giao dịch trực tiếp. Nghe cho các sự kiện trong chủ đề chủ đề khi được gọi từ chức năng chínhmain()Trong các chiến lược được viết trongJavaScriptngôn ngữ,threading.Thread()function tạo ra một thread, mà cũng có thể được gọi trong hàm thực thi threads, để nghe các sự kiện trong thread hiện tại.

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

__Hãy phục vụ

Các__Servechức năng được sử dụng để tạo dịch vụ HTTP, dịch vụ TCP và dịch vụ Websocket (dựa trên giao thức HTTP).

Trả về một chuỗi ghi lại địa chỉ IP và cổng của dịch vụ được tạo. Ví dụ:127.0.0.1:8088, [::]:8089.

chuỗi

__Serve ((serveURI, xử lý) __Serve ((serveURI, xử lý,...args)

CácserveURItham số được sử dụng để cấu hình giao thức, địa chỉ IP, cổng và các thiết lập khác của việc ràng buộc dịch vụ, chẳng hạn nhưhttp://0.0.0.0:8088?gzip=true, nghĩa là,http://:8088?gzip=true.

  • Giao thức TCPserveURIthiết lập tham số, chẳng hạn nhưtcp://127.0.0.1:6666?tls=true; bạn có thể thêm chứng chỉ và khóa riêng, chẳng hạn nhưtls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Giao thức HTTPserveURIcài đặt tham số, chẳng hạn nhưhttp://127.0.0.1:6666?gzip=true; bạn có thể thiết lập cài đặt nén:gzip=true. CácserveURItham số được sử dụng cho HTTP, chẳng hạn nhưhttps://127.0.0.1:6666?tls=true&gzip=true; bạn có thể thêmcert_pemcert_key_pemcác tham số để tải giấy chứng nhận.

serveURI đúng chuỗi Cáchandlertham số được sử dụng để truyền trong chức năng xử lý định tuyến (protocol HTTP), chức năng xử lý tin nhắn (protocol TCP), và chức năng xử lý luồng (Websocket). Chức năng gọi lại được chuyển vào bởi tham sốhandlercó thể xác định nhiều tham số, tham số đầu tiên là đối tượng ctx ( đối tượng ngữ cảnh).

người xử lý đúng chức năng Các tham số thực tế của hàm gọi lại được truyền như các tham sốhandlerCó thể có nhiều thông sốargVí dụ:

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

Các thông số1, 2, 3qua khi gọi cho__Serve()chức năng tương ứng với các thông sốa, b, cđược thông qua trong chức năng gọi lại.

arg sai chuỗi, số, bool, đối tượng, mảng, hàm, giá trị null và các loại khác được hỗ trợ bởi hệ thống

function main() {
    let httpServer = __Serve("http://:8088?gzip=true", function (ctx) {
        Log("http connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        let path = ctx.path()
        if (path == "/") {
            ctx.write(JSON.stringify({
                path: ctx.path(),
                method: ctx.method(),
                headers: ctx.headers(),
                cookie: ctx.header("Cookie"),
                remote: ctx.remoteAddr(),
                query: ctx.rawQuery()
            }))
        } else if (path == "/tickers") {
            let ret = exchange.GetTickers()
            if (!ret) {
                ctx.setStatus(500)
                ctx.write(GetLastError())
            } else {
                ctx.write(JSON.stringify(ret))
            }
        } else if (path == "/wss") {
            if (ctx.upgrade("websocket")) { // upgrade to websocket
                while (true) {
                    let r = ctx.read(10)
                    if (r == "") {
                        break
                    } else if (r) {
                        if (r == "ticker") {
                            ctx.write(JSON.stringify(exchange.GetTicker()))
                        } else {
                            ctx.write("not support")
                        }
                    }
                }
                Log("websocket closed", ctx.remoteAddr())
            }
        } else {
            ctx.setStatus(404)
        }
    })
    let echoServer = __Serve("tcp://:8089", function (ctx) {
        Log("tcp connect from: ", ctx.remoteAddr(), "->", ctx.localAddr())
        while (true) {
            let d = ctx.read()
            if (!d) {
                break
            }
            ctx.write(d)
        }
        Log("connect closed")
    })
    Log("http serve on", httpServer, "tcp serve on", echoServer)
    
    for (var i = 0; i < 5; i++) {
        if (i == 2) {
            // test Http
            var retHttp = HttpQuery("http://127.0.0.1:8088?num=123&limit=100", {"debug": true})
            Log("retHttp:", retHttp)
        } else if (i == 3) {
            // test TCP
            var tcpConn = Dial("tcp://127.0.0.1:8089")
            tcpConn.write("Hello TCP Server")
            var retTCP = tcpConn.read()
            Log("retTCP:", retTCP)
        } else if (i == 4) {
            // test Websocket
            var wsConn = Dial("ws://127.0.0.1:8088/wss|compress=gzip")
            wsConn.write("ticker")
            var retWS = wsConn.read(1000)
            Log("retWS:", retWS)
            // no depth
            wsConn.write("depth")
            retWS = wsConn.read(1000)
            Log("retWS:", retWS)
        }
        Sleep(1000)
    }
}
# Unsupported
// Unsupported
  • Chức năng này chỉ hỗ trợ các chiến lược ngôn ngữ JavaScript.
  • Các chủ đề dịch vụ được cô lập khỏi phạm vi toàn cầu, vì vậy nó không hỗ trợ đóng hoặc tham chiếu đến các biến bên ngoài, các hàm tùy chỉnh, v.v.; tuy nhiên, nó có thể gọi tất cả các hàm API nền tảng.
  • CácWebsocketDịch vụ được thực hiện dựa trên giao thức HTTP. Bạn có thể thiết lập một nhánh định tuyến trong đường dẫn và thiết kế mã thực hiện choWebsocketBạn có thể tham khảo mẫu mã trong phần này.

Chức năng gọi lại được truyền vào bởi tham sốhandlernhận được mộtctxcác tham số.ctxtham số là một đối tượng ngữ cảnh được sử dụng để lấy và ghi dữ liệu, với các phương pháp sau:

  • ctx.proto ((() Được áp dụng cho giao thức Http/TCP, trả về tên giao thức khi được gọi. Ví dụ:HTTP/1.1, tcp.
  • ctx.host() Được áp dụng cho giao thức HTTP, nó trả về thông tin máy chủ khi gọi địa chỉ IP và cổng.
  • ctx.path ((() Được áp dụng cho giao thức HTTP, trả về đường dẫn yêu cầu khi được gọi.
  • ctx.query ((key)) Được áp dụng cho giao thức HTTP, trả về giá trị tương ứng với khóa trong truy vấn trong yêu cầu khi được gọi. Ví dụ, yêu cầu được gửi là:http://127.0.0.1:8088?num=123, và chức năng xử lý gọi lại được truyền vào bởi các thông sốhandlertrả lại"123"khi nàoctx.query("num")được gọi là.
  • ctx.rawQuery() Được áp dụng cho giao thức Http, khi được gọi, trả về truy vấn ban đầu trong yêu cầu (quy vấn của yêu cầu Http).
  • ctx.headers ((() Áp dụng cho giao thức HTTP, và trả về thông tin tiêu đề yêu cầu trong yêu cầu khi được gọi.
  • ctx.header ((key)) Áp dụng giao thức HTTP, nó trả về giá trị của một khóa trong tiêu đề yêu cầu được chỉ định khi được gọi.User-Agenttrong tiêu đề của yêu cầu hiện tại:ctx.header("User-Agent").
  • ctx.method (() Áp dụng cho giao thức HTTP, trả về phương thức yêu cầu khi được gọi, chẳng hạn nhưGET, POST, vv
  • ctx.body ((() Áp dụng để yêu cầu POST của giao thức HTTP, và trả về cơ thể của yêu cầu khi được gọi.
  • ctx.setHeader ((key, value) Áp dụng giao thức HTTP để thiết lập thông tin tiêu đề yêu cầu của tin nhắn phản hồi.
  • ctx.setStatus (định mã) Được áp dụng cho giao thức Http, đặt mã trạng thái tin nhắn Http. Thông thường, mã trạng thái Http được đặt ở cuối nhánh định tuyến. Giá trị mặc định là 200.
  • ctx.remoteAddr ((() Được áp dụng cho giao thức Http / TCP, trả về địa chỉ khách hàng từ xa và cổng trong yêu cầu khi được gọi.
  • ctx.localAddr() Được áp dụng cho giao thức Http / TCP, trả về địa chỉ địa phương và cổng của dịch vụ khi được gọi.
  • ctx.upgrade ((websocket) Áp dụng để thực hiện giao thức Websocket dựa trên giao thức HTTP, chuyển đổictxđối tượng ngữ cảnh đến giao thức Websocket; trả về giá trị Boolean (true) nếu chuyển đổi thành công, và giá trị Boolean (false) nếu nó thất bại.
  • ctx.read ((timeout_ms) Áp dụng để thực hiện giao thức Websocket / giao thức TCP dựa trên giao thức HTTP, đọc dữ liệu của kết nối Websocket và kết nối TCP.readPhương pháp này không được hỗ trợ trong giao thức HTTP thông thường. Bạn có thể chỉ định tham số timeouttimeout_mstrong vài mili giây.
  • ctx.write ((s) Được áp dụng cho giao thức HTTP/TCP, được sử dụng để viết dữ liệu chuỗi.JSON.stringify()để mã hóa đối tượng JSON vào một chuỗi và sau đó viết nó.WebSocketgiao thức, bạn có thể sử dụng phương pháp này để truyền chuỗi mã hóa cho khách hàng.

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

_G

Tiếp tục lưu dữ liệu, chức năng thực hiện một chức năng từ điển toàn cầu có thể được lưu.

Dữ liệu giá trị khóa được lưu liên tục trongk-vcác cặp giá trị khóa. chuỗi, số, bool, đối tượng, mảng, giá trị không

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

Các thông sốklà tên của khóa trong cặp khóa-giá trị được lưu, và không nhạy cảm với chữ cái lớn. k sai chuỗi, giá trị không Các thông sốvlà giá trị khóa trong cặp giá trị khóa được lưu, có thể là bất kỳ dữ liệu nào có thể đượcJSONđược phân phối. v sai chuỗi, số, bool, đối tượng, mảng, giá trị không

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

Một cơ sở dữ liệu riêng biệt cho mỗi giao dịch trực tiếp, dữ liệu được lưu trữ bởi_G()chức năng sẽ luôn luôn ở đó nếu chiến lược được khởi động lại hoặc docker ngừng chạy. Nếu backtesting được hoàn thành, dữ liệu được lưu trong hệ thống backtesting bởi_G()Khi sử dụng các_G()chức năng để duy trì dữ liệu được lưu, nó nên được sử dụng hợp lý theo bộ nhớ và không gian đĩa cứng của thiết bị phần cứng, và không nên bị lạm dụng. Khi gọi cho_G()chức năng trong một giao dịch trực tiếp và không có thông số được vượt qua,_G()hàm trả vềIdcủa giao dịch trực tiếp hiện tại_G()chức năng, tham sốvđược thông qua như là không để chỉ ra việc xóak-vKhi gọi các_G()chức năng, chỉ các thông sốkđược truyền trong chuỗi, và_G()hàm trả về giá trị khóa tương ứng với tham số được lưukKhi gọi điện cho_G()chức năng, chỉ các thông sốkđược truyền trong một giá trị null, cho thấy rằng tất cả các bản ghi củak-vkhi các cặp key-value được xóa.k-vCác cặp key-value đã được lưu liên tục,_G()chức năng được gọi một lần nữa, đi qua trong tên của khóa đã được lưu liên tục như là tham sốk. Đưa vào giá trị khóa mới như một tham sốvsẽ cập nhật rằngk-vcặp giá trị khóa.

{@fun/Global/DBExec DBExec}

_D

Chuyển đổi dấu thời gian millisecond hoặcDateđối tượng với chuỗi thời gian.

Dây thời gian. chuỗi

_D() _D (đánh dấu thời gian) _D ((đũa thời gian, fmt)

Dấu thời gian millisecondDateđối tượng. dấu thời gian sai Số, mục đích Định dạng chuỗi,JavaScriptĐịnh dạng ngôn ngữ mặc định:yyyy-MM-dd hh:mm:ss; PythonĐịnh dạng ngôn ngữ mặc định:%Y-%m-%d %H:%M:%S; C++Định dạng ngôn ngữ mặc định:%Y-%m-%d %H:%M:%S. fmt sai chuỗi

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

Nhận và in chuỗi thời gian hiện tại:

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

Mẫu thời gian là 1574993606000, sử dụng chuyển đổi mã:

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

Định dạng bằng tham sốfmtlà khác nhau choJavaScript, Python, vàC++ngôn ngữ, như được thể hiện trong các ví dụ sau:

Trả về chuỗi thời gian hiện tại mà không cần thông qua bất kỳ thông số._D()chức năng trongPythonchiến lược, bạn cần phải nhận thức được rằng các tham số được truyền là dấu thời gian cấp hai (các dấu thời gian cấp millisecond trong các chiến lược JavaScript và C ++, nơi 1 giây bằng 1000 milliseconds)._D()chức năng để phân tích một chuỗi thời gian với một dấu thời gian có thể đọc trong giao dịch trực tiếp, bạn cần phải chú ý đến múi giờ và thiết lập thời gian của hệ điều hành nơi chương trình docker nằm._D()hàm phân tích dấu thời gian thành một chuỗi thời gian có thể đọc tùy thuộc vào thời gian của hệ thống dockers.

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

_N

Định dạng một số dấu phẩy động.

Số dấu phẩy động được định dạng theo cài đặt chính xác. số

_N() _N(num) _N ((num, chính xác)

Số dấu phẩy động cần phải được định dạng. số đúng số Cài đặt độ chính xác cho định dạng, tham sốprecisionlà một số nguyên, và các tham sốprecisionmặc định là 4. độ chính xác sai số

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

Ví dụ,_N(3.1415, 2)sẽ xóa giá trị sau3.1415hai vị trí thập phân và hàm trả về3.14.

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

Nếu bạn cần thay đổi tất cả các chữ số N bên trái của dấu thập phân thành 0, bạn có thể viết nó như thế này:

Các thông sốprecisioncó thể là một số nguyên dương, số nguyên âm.

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

_C

Thử lại chức năng cho dung nạp lỗi giao diện.

Giá trị trả về của hàm callback khi nó được thực hiện. Tất cả các loại được hỗ trợ bởi hệ thống ngoại trừgiá trị sai logicgiá trị null.

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

Các thông sốpfnlà một tham chiếu chức năng, đó là mộtChức năng gọi lại. pfn đúng chức năng Các thông số đếnChức năng gọi lại, có thể có nhiều hơn một tham sốargLoại và số lượng các thông sốargphụ thuộc vào các thông số củaChức năng gọi lại. arg sai chuỗi, số, bool, đối tượng, mảng, hàm, tất cả các loại được hỗ trợ bởi hệ thống, chẳng hạn như giá trị null

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

Đối với các hàm dung nạp lỗi không có tham số:

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

Đối với các hàm có tham số chịu lỗi:

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

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

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

Nó cũng có thể được sử dụng cho khả năng chịu lỗi của các chức năng tùy chỉnh:

Các_C()function sẽ tiếp tục gọi hàm được chỉ định cho đến khi nó trả về thành công (chức năng được tham chiếu bởi tham sốpfntrả lạikhônghoặcsaikhi được gọi sẽ thử gọi lạipfnVí dụ:_C(exchange.GetTicker). Khoảng thời gian thử lại mặc định là 3 giây, bạn có thể gọi_CDelay()chức năng để thiết lập khoảng thời gian thử lại._CDelay(1000)có nghĩa là để thay đổi khoảng thời gian thử lại của_C()chức năng 1 giây. Sự dung nạp lỗi có thể được thực hiện cho, nhưng không giới hạn ở, các chức năng sau:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()Tất cả có thể được gọi bởi các_C()chức năng cho dung nạp lỗi._C()chức năng không giới hạn trong chức năng được liệt kê ở trên dung nạp lỗi, tham sốpfnlà một tham chiếu hàm hơn là một cuộc gọi hàm. Lưu ý rằng nó_C(exchange.GetTicker), không_C(exchange.GetTicker()).

_ Chữ thập

Trả về số lần giao nhau của mảngarr1và mảngarr2.

Số lần chéo của mảngarr1và mảngarr2. số

_Cross ((arr1, arr2)

Các phần tử là mảng kiểunumber. arr1 đúng mảng Các phần tử là mảng kiểunumber. arr2 đúng mảng

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

Một bộ dữ liệu có thể được mô phỏng để kiểm tra hàm _Cross ((Arr1, Arr2):

Nếu giá trị trả về của_Cross()hàm là một con số dương tính, nó chỉ ra thời gian thâm nhập tăng, nếu nó là một con số âm tính, nó chỉ ra thời gian thâm nhập giảm, 0 có nghĩa là tương tự như giá hiện tại.Phân tích và hướng dẫn sử dụng về chức năng tích hợp.

JSONParse

Chức năngJSONParse()được sử dụng để phân tíchJSON strings.

JSONđối tượng. đối tượng

JSONParse (s)

JSONdây. s đúng chuỗi

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

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

Các chuỗi JSON với các giá trị lớn có thể được phân tích chính xác, và nó sẽ phân tích các giá trị lớn như các loại chuỗi.JSONParse()chức năng không được hỗ trợ trong hệ thống backtest.

Ký hiệu