Các nhà phát minh định lượng tài liệu API

Tác giả:Giấc mơ nhỏ, Tạo: 2017-11-27 09:05:08, Cập nhật: 2023-07-12 16:47:31

void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
  • MailPhiên bản không đồng bộ của hàmMail_GoChức năng: Cách sử dụng vàexchange.GoChức năng tương tự.

    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)
    }
    
    # 不支持
    
    // 不支持
    

Lưu ý: Máy chủ Ali Cloud có thể đóng một số cổng, khiến thư không thể được gửi đi. Nếu cần thay đổi cổng, bạn có thể thêm mã cổng trực tiếp trong tham số đầu tiên, ví dụ:smtp.qq.com:587, Các thử nghiệm cổng có sẵn. Nếu báo cáo sai:unencryped connectionNhững điều cần sửa đổiMailCác hàmsmtpServerCác tham số được định dạng như sau:ssl://xxx.com:xxxVí dụ như trong thư điện tử QQ.SMTPCách sử dụng SSL:ssl://smtp.qq.com:465Hoặcsmtp://xxx.com:xxx

SetErrorFilter(...)

SetErrorFilter(RegEx), Lưu mục lỗi lọc. Parameter value: type string. Các nhật ký lỗi được khớp với biểu thức chính thức này sẽ không được tải lên hệ thống nhật ký, và nhiều điều kiện lọc có thể được đặt ra nhiều lần (những nhật ký được lọc không được ghi vào các tập tin cơ sở dữ liệu tương ứng với ID đĩa thực trong thư mục chủ, ngăn chặn các lỗi thường xuyên gây ra sự bùng nổ của tập tin cơ sở dữ liệu).

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

Một số người dùng đang sử dụng các công cụ này để kiểm tra thông tin lỗi trên giao diện:

function main() {
    // 随便查询一个不存在的订单,id为123,故意让接口报错
    var order = exchange.GetOrder("123")
    Log(order)
    // 过滤http502错误、GetOrder接口错误,设置错误过滤之后,第二次调用GetOrder不再报错
    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(), Trả về ID quá trình đĩa thực. Trả về giá trị: kiểu chuỗi.

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

GetLastError()

GetLastError(), lấy thông tin lỗi gần đây. Thông thường không cần sử dụng vì chương trình sẽ tự động tải thông tin lỗi lên hệ thống nhật ký. Trả về giá trị: kiểu chuỗi.GetLastError()Chức năng sau đó sẽ xóa bộ nhớ cache lỗi này và không trả lại thông tin sai trong lần ghi trước khi gọi lại.

function main(){
    // 因为不存在编号为123的订单,所以会出错
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // 订单ID类型:TId,所以不能传入字符串,我们下一个不符合交易所规范的订单来触发
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

GetCommand()

GetCommand(), lấy chuỗi lệnh tương tác ((utf-8)); lấy lệnh từ giao diện tương tác chính sách và xóa bộ nhớ cache, không có lệnh trả về chuỗi trống; định dạng lệnh trả về là按钮名称:参数Nếu điều khiển tương tác không có tham số (ví dụ như điều khiển nút không có hộp đầu vào), lệnh là tên nút.

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

Hệ thống dưới cùng có một cấu trúc hàng rào ghi lại các lệnh tương tác khiGetCommand()Khi một hàm được gọi, nó lấy lệnh tương tác đầu tiên trong hàng (trở lại một chuỗi trống nếu không có lệnh tương tác).

Ví dụ về việc sử dụng điều khiển tương tác, giao diện chỉnh sửa chính sách thiết lập điều khiển tương tác.

img

Trong chiến lược, thiết kế mã tương tác:

function main() {
    while (true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)    
            var arr = cmd.split(":")
            if (arr[0] == "buy") {
                Log("买入,该控件不带数量")
            } else if (arr[0] == "sell") {
                Log("卖出,该控件带数量:", arr[1])
            } else {
                Log("其它控件触发:", arr)
            }
        }
        Sleep(1000)
    } 
}
def main():
    while True:
        LogStatus(_D())
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
            arr = cmd.split(":")
            if arr[0] == "buy":
                Log("买入,该控件不带数量")
            elif arr[0] == "sell":
                Log("卖出,该控件带数量:", arr[1])
            else:
                Log("其它控件触发:", 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("买入,该控件不带数量");
            } else if (arr[0] == "sell") {
                Log("卖出,该控件带数量:", arr[1]);
            } else {
                Log("其它控件触发:", arr);
            }
        }
        Sleep(1000);
    }
}

GetMeta()

GetMeta()Chức năng trả về mã đăng ký chính sách được viết khi tạoMetaCác giá trị của hàm này được trả về với kiểu chuỗi. Các tình huống áp dụng, ví dụ như chiến lược yêu cầu giới hạn tài chính cho các người thuê khác nhau. Lưu ý: Khi tạo mã đăng kýMetaKhông được dài hơn 190 ký tự, chỉ áp dụng cho ổ đĩa thực và cần sử dụng trình quản lý mới nhất. Nếu không thiết lập metadata khi tạo mã đăng ký chính sáchGetMeta()Trả về giá trị trống.

Thông tin liên quan đến việc sử dụng mô hình cảnh

function main() {
    // 策略允许的计价币最大资产数值
    var maxBaseCurrency = null
    
    // 获取创建注册码时的元数据
    var level = GetMeta()
    
    // 检测Meta对应的条件
    if (level == "level1") {
        // -1为不限制
        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()
        
        // 检测资产数值
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // 停止执行策略交易逻辑
            LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
            continue
        }
        
        // 其它交易逻辑
        
        // 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\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, "持仓超过注册码的使用限定,不再执行策略交易逻辑!")
            continue        
        
        # 其它交易逻辑
        
        # 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\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) {
            // 停止执行策略交易逻辑
            LogStatus(_D(), "level:", level, "持仓超过注册码的使用限定,不再执行策略交易逻辑!");
            continue;
        }
        
        // 其它交易逻辑
        
        // 正常输出状态栏信息
        LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker);
    }
}

Nhập số...

Dial(Address, Timeout), nguyên bảnSocketTruy cập, hỗ trợtcpudptlsunixCác thông tin về giao thức.AddressBạn có thể sử dụng các loại hình khác nhau.TimeOutLoại giá trị, đơn vị giá trị là giây, nếu quá giờDial(...)Chức năng trả về giá trị trống.

AddressCác thông số chi tiết:

Định nghĩa tham số
Thiết lậpDialCác tham số của chức năng Địa chỉ thông thường:wss://ws.okx.com:8443/ws/v5/publicSau đó|Chữ phân biệt nếu có một chuỗi số|Chữ được viết bằng||Sử dụng như một dấu phân cách.&Chữ kết nối. Ví dụ: ss5 đại diện và các tham số nén được đặt cùng nhau:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Các tham số liên quan đến nén dữ liệu khi sử dụng giao thức ws:compress=参数值 compress là chế độ nén, các tham số nén, tùy chọngzip_rawgzipVí dụ. Nếu gzip không phải là gzip tiêu chuẩn, bạn có thể sử dụng phương thức mở rộng:gzip_rawĐó là dấu phân vùng.|Sau đó thêm cài đặtcompress=gzip_raw, dùng&Các biểu tượng và các tham số mode tiếp theo được tách ra.
Các tham số liên quan đến nén dữ liệu khi sử dụng giao thức ws:mode=参数值 mode là mode, tùy chọndualsendrecvCó ba loại.dualĐối với hai chiều, gửi dữ liệu nén và nhận dữ liệu nén.sendĐể gửi dữ liệu nén.recvĐể nhận dữ liệu nén, giải nén tại địa phương.
Các tham số liên quan được sử dụng để thiết lập các đại lý socks5:proxy=参数值 Proxy được thiết lập cho các đại lý ss5, định dạng giá trị tham số:socks5://name:pwd@192.168.0.1:1080,name là tên người dùng của máy chủ ss5, pwd là mật khẩu đăng nhập của máy chủ ss5, và 1080 là cổng của dịch vụ ss5.
Khi sử dụng giao thức ws, hãy đặt các tham số liên quan đến liên kết tự động dưới cùng:reconnect=参数值 reconnect cho biết bạn có thiết lập kết nối lại hay không.reconnect=trueĐể bật nối lại. Nếu không đặt tham số này, mặc định không nối lại.
Khi sử dụng giao thức ws, hãy đặt các tham số liên quan đến liên kết tự động dưới cùng:interval=参数值 interval là khoảng thời gian thử lại, đơn vị mili giây,interval=10000Để thử lại trong khoảng thời gian 10 giây, không đặt mặc định là 1 giây, đó làinterval=1000
Khi sử dụng giao thức ws, hãy đặt các tham số liên quan đến liên kết tự động dưới cùng:payload=参数值 Payload là một thông báo đăng ký cần được gửi khi nối lại với ws, ví dụ:payload=okok
function main(){
    // Dial支持tcp://,udp://,tls://,unix://协议,可加一个参数指定超时的秒数
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // write可再跟一个数字参数指定超时,write返回成功发送的字节数
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while (true) {
            // read可再跟一个数字参数指定超时,单位:毫秒。返回null指出错或者超时或者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();
    }
}

readChức năng hỗ trợ các tham số sau:

  • Khi không truyền tham số, chặn cho đến khi có tin nhắn; ví dụ:ws.read()
  • Khi nhập tham số, đơn vị là millisecond, chỉ định thời gian chờ quá giờ của tin nhắn; ví dụ:ws.read(2000)Đặt thời gian trễ là hai giây ((2000 milliseconds) ).
  • Và sau đây là 2 tham số chỉ đúngwebsocketCó hiệu quả: Đưa vào tham số-1Một hàm trả về ngay lập tức cho dù có hoặc không có tin nhắn, ví dụ:ws.read(-1)❖ Đưa vào tham số-2Điều này có nghĩa là các hàm sẽ trả về ngay lập tức, dù không có tin nhắn, nhưng chỉ trả về tin nhắn mới nhất, và các tin nhắn trong vùng đệm sẽ bị loại bỏ; ví dụ:ws.read(-2)

read()Các vùng đệm hàm: Ws protocol đẩy dữ liệu đến nếu trong chính sáchread()Khoảng thời gian quá dài giữa các cuộc gọi hàm có thể gây ra sự tích lũy dữ liệu. Dữ liệu này được lưu trữ trong vùng đệm, cấu trúc dữ liệu vùng đệm là hàng, giới hạn là 2000. Sau khi vượt quá 2000, dữ liệu mới nhất được đưa vào vùng đệm, dữ liệu cũ nhất được xóa.

CảnhreadCác tham số của hàm Không tham số Các tham số: -1 Các tham số: -2 Các tham số: 2000 đơn vị là millisecond
Các vùng đệm đã có dữ liệu 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 cập 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 vùng đệm Chặn trở lại khi có dữ liệu Trả lại giá trị trống ngay lập tức Trả lại giá trị trống ngay lập tức Chờ 2000 millisecond, không có dữ liệu trả về giá trị trống, có dữ liệu trả về
ws khi kết nối bị ngắt hoặc kết nối lại dưới Chức năng read (()) trả về một chuỗi trống, tức là:"",write (()) trả về 0 và phát hiện ra tình huống này. Bạn có thể sử dụng chức năng close (()) để tắt kết nối, nếu thiết lập tự động nối lại thì không cần phải tắt, hệ thống sẽ tự động nối lại.
  • Hỗ trợ giao thức wss ((WebSocket) Các công ty khác cũng có thể truy cập vào Binance.

    function main() {
        LogStatus("正在连接...")
        // 访问币安的websocket接口
        var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if (!client) {
            Log("连接失败, 程序退出")
            return
        }
        
        while (true) {
            // read只返回调用read之后获取的数据
            var buf = client.read()      
            if (!buf) {
                break
            }
            var table = {
                type: 'table',
                title: '行情图表',
                cols: ['币种', '最高', '最低', '买一', '卖一', '最后成交价', '成交量', '更新时间'],
                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("正在连接...")
        client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if not client:
            Log("连接失败, 程序退出")
            return 
        
        while True:
            buf = client.read()
            if not buf:
                break
            table = {
                "type" : "table", 
                "title" : "行情图表", 
                "cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"], 
                "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("正在连接...");
        auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
        if(!client.Valid) {
            Log("连接失败, 程序退出");
            return;
        }
        
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            json table = R"({
                "type" : "table", 
                "title" : "行情图表", 
                "cols" : ["币种", "最高", "最低", "买一", "卖一", "最后成交价", "成交量", "更新时间"], 
                "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 vào giao diện websocket của OKX:

    var ws = null 
    function main(){
        var param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        // 在调用Dial函数时,指定reconnect=true即设置为重连模式,指定payload即为重连时发送的消息。在websocket连接断开后,会自动重连,自动发送消息
        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("发送 :ping", "#FF0000")
                }
                LogStatus("当前时间:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("退出")
    }
    
    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("发送:ping", "#FF0000")
                LogStatus("当前时间:", _D())
                Sleep(1000)  
    
    def onexit():
        ws.close()
        Log("退出")
    
    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("发送:ping", "#FF0000");
                }
                LogStatus("当前时间:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        objWS.close();
        Log("退出");
    }
    

    Các giao diện thị trường websocket để truy cập các token:

    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)
                // 响应心跳包操作
                try {
                    var jsonRet = JSON.parse(ret)
                    if(typeof(jsonRet.ping) == "number") {
                        var strPong = JSON.stringify({"pong" : jsonRet.ping})
                        ws.write(strPong)
                        Log("响应ping,发送pong:", strPong, "#FF0000")
                    }
                } catch(e) {
                    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                }
                
                LogStatus("当前时间:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("执行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)              
                # 响应心跳包操作
                try:
                    jsonRet = json.loads(ret)
                    if "ping" in jsonRet and type(jsonRet["ping"]) == int:
                        strPong = json.dumps({"pong" : jsonRet["ping"]})
                        ws.write(strPong)
                        Log("响应ping,发送pong:", strPong, "#FF0000")
                except Exception as e:
                    Log("e:", e)
                    
                LogStatus("当前时间:", _D())
                Sleep(1000)
        
    def onexit():
        ws.close()
        Log("执行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);              
                // 响应心跳包操作
                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("响应ping,发送pong:", strPong, "#FF0000");
                    }
                } catch(exception &e) 
                {
                    Log("e:", e.what());
                }
                
                LogStatus("当前时间:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        // ws.close();
        Log("执行ws.close()函数");
    }
    

    Truy cập vào OKX websocket authentication interface:

    function getLogin(pAccessKey, pSecretKey, pPassphrase) {
        // 签名函数,用于登录
        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() {
        // 因为read函数使用了超时设置,过滤超时的报错,否则会有冗余错误输出
        SetErrorFilter("timeout")
        
        // 持仓频道订阅信息
        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)  // 登录时,不能立即订阅私有频道,需要等待服务器反应
        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)
                }
                
                // 检测断开,重连
                if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
                    Log("检测到断开,关闭连接,重连")
                    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))
                }
                
                // 发送心跳包
                var nowPingTS = new Date().getTime()
                if (nowPingTS - lastPingTS > 10 * 1000) {
                    client_private.write("ping")
                    lastPingTS = nowPingTS
                }            
            }        
        }
    }    
    
    function onexit() {    
        var ret = client_private.close()
        Log("关闭连接!", 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("检测到断开,关闭连接,重连")
                    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("关闭连接!", 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("检测到断开,关闭连接,重连");
                        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("退出");
    }
    

HttpQuery(...)

HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader), truy cập URL mạng. Các giá trị tham số: tất cả là loại chuỗi.

Lưu ý:

  • HttpQuery(...)Chức năng chỉ hỗ trợJavaScriptNgôn ngữ.
  • PythonNgôn ngữ có thể được sử dụngurllibBạn có thể gửi 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 không cần chữ ký, chẳng hạn như giao diện công cộng như thông tin thị trường.

Ví dụ về giao diện API không cần chữ ký để truy cập OKX, trả về giá trịJSONDưới đây là một số hình ảnh.JavaScriptCác chiến lược ngôn ngữ được sử dụngJSON.parse()Phân tích hàm.

function main(){
    // 一个GET访问不带参数的例子
    var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
    Log(info)
    // 一个GET访问带参数的例子
    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不支持Python,可以使用urllib/urllib2库代替
    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);
}

Lấy nội dung trả về của một URL nếu tham số thứ haiPostDataDùng cho một chuỗia=1&b=2&c=abcHình thức làPOSTCách gửi.PUTNhững người tham gia vào cuộc họp nàyPostDataCác tham số là{method:'PUT', data:'a=1&b=2&c=abc'}PostDataVà các tham số có thể làJSONDòng chữ.

CookiesCác đối số này có hình thức:a=10; b=20Các tham số được đánh dấu bằng dấu chấm;Các bạn có thể đọc bài viết này.HeadersCác đối số này có hình thức:User-Agent: Mobile\nContent-Type: text/htmlCác tham số được thay thế bằng ký tự\nCác bạn có thể đọc bài viết này.

Điểm thứ haiPostDataCác phương pháp có thể được tùy chỉnh như:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'})Xin lưu ý:HttpQueryCác chức năng đặt thời gian trễ, có thể được sử dụng trong{method:'PUT', data:'a=1&b=2&c=abc'}Tham giatimeoutTham khảo thêm:

Đặt 1 giây trễ:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})

Giao thôngCookieDữ liệu này cần một đối số thứ ba, nhưng không cầnPOSTVui lòng đặt tham số thứ hai là không. Khi thử nghiệm mô phỏng, hàm sẽ trả về một chuỗi cố định vì không thể mô phỏng truy cập URL.Dummy DataBạn có thể sử dụng giao diện này để gửi tin nhắn văn bản hoặc tương tác với các giao diện API khác.

GETVí dụ về phương thức gọi:HttpQuery("http://www.baidu.com")POSTVí dụ về phương thức gọi:HttpQuery("http://www.163.com", "a=1&b=2&c=abc")

Trở lạiHeaderVí dụ:

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}
  • HttpQueryCác chức năng sử dụng cài đặt đại diện:

    function main() {
        // 本次设置代理并发送http请求,无用户名,无密码,此次http请求会通过代理发送
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
    
        // 本次设置代理并发送http请求,输入用户名和密码,仅HttpQuery当前调用生效,之后再次调用HttpQuery("http://www.baidu.com")这样不会使用代理
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
    }
    
    # HttpQuery不支持Python,可以使用Python的urllib2库
    
    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/");
    }
    
  • HttpQueryPhiên bản không đồng bộ của hàmHttpQuery_GoĐịa điểm: Cách sử dụng vàexchange.GoCác chức năng tương tự, ví dụ như truy cập không đồng bộ giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch giao dịch.

    function main() {
        // 创建第一个异步线程
        var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
        // 创建第二个异步线程
        var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
        
        // 获取第一个异步线程调用的返回值
        var tickers1 = r1.wait()
        // 获取第二个异步线程调用的返回值
        var tickers2 = r2.wait()
        
        // 打印结果
        Log("tickers1:", tickers1)
        Log("tickers2:", tickers2)
    }
    
    # 不支持
    
    // 不支持
    
  • Sử dụng trong hệ thống kiểm tra lạiHttpQuery(...)Chức năng: Có thể sử dụng trong hệ thống kiểm tra lạiHttpQuery(...)Gửi yêu cầu ((chỉ hỗ trợ)GETyêu cầu) thu thập dữ liệu; hạn chế sử dụng 20 lần truy cập URL khác nhau khi truy cập lại; vàHttpQuery(...)truy cập sẽ lưu dữ liệu, cùng một URL lần truy cập thứ haiHttpQuery(...)Chức năng trả về dữ liệu cache (không còn yêu cầu mạng thực tế nữa).

    Chúng ta có thể chạy một chương trình dịch vụ trên một máy chủ hoặc thiết bị để đáp ứng các chương trình chính sách.HttpQuery(...)Các ứng dụng dịch vụ ngôn ngữ Go được sử dụng để thử nghiệm các yêu cầu được gửi như sau:

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

    Sử dụng khi kiểm tra lại chiến lượcHttpQuery(...)Đơn xin gửi hàm:

    function main() {
        // 可以写自己运行服务程序所在设备的IP地址
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    
    # HttpQuery不支持Python,可以使用Python的urllib2库
    
    void main() {
        // 可以写自己运行服务程序所在设备的IP地址
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    

    img

  • Hỗ trợ chuyển mã dữ liệu trả lời yêu cầu, hỗ trợ mã hóa thông thường. ĐặtPostDataCác thông số:{method: "GET",charset:"GB18030"}, có thể thực hiện mã chuyển đổi dữ liệu đáp ứng ((GB18030)).

Mã hóa...

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string), hàm này mã hóa dữ liệu dựa trên các tham số được truyền. Trả về giá trị: kiểu chuỗi.

Các tham sốalgoCác thuật toán được sử dụng để tính toán mã hóa, hỗ trợ cài đặt là: raw (không sử dụng thuật toán), 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, ripemd160, blake2b.256, blake2b.512, blake2s.128, blake2s.256.Các tham số.dataNhững dữ liệu cần được xử lý.inputFormat/outputFormat/keyFormatHỗ trợ tham sốrawhexbase64stringCó cách mã hóa. NếukeyFormatNếu không là không, thì dùng tham sốkeySử dụng mã hóa (HMAC), nếu không sử dụng mặc địnhkeyParameteralgoĐặt thành"sign"Hoặc"signTx"Khi cần các tham sốkey

function main(){
    Log(Encode("md5", "raw", "hex", "hello"))
    Log(Encode("sha512", "raw", "base64", "hello"))
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"))

    Log(Encode("raw", "string", "hex", "example"))          // 6578616d706c65
    Log(Encode("raw", "hex", "string", "6578616d706c65"))   // example
}
def main():
    Log(Encode("md5", "raw", "hex", "hello", "", ""))
    Log(Encode("sha512", "raw", "base64", "hello", "", ""))
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)", "", ""))

    Log(Encode("raw", "string", "hex", "example", "", ""))
    Log(Encode("raw", "hex", "string", "6578616d706c65", "", ""))
void main(){
    Log(Encode("md5", "raw", "hex", "hello"));
    Log(Encode("sha512", "raw", "base64", "hello"));
    Log(Encode("keccak256", "raw", "hex", "unwrapWETH9(uint256,address)"));
    
    Log(Encode("raw", "string", "hex", "example"));          // 6578616d706c65
    Log(Encode("raw", "hex", "string", "6578616d706c65"));   // example
}

Các tham sốalgoVà cũng ủng hộ:text.encoder.utf8text.decoder.utf8text.encoder.gbktext.decoder.gbk, mã hóa, giải mã các chuỗi.

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

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

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

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

UnixNano ((()

UnixNano(), trả lại các bước thời gian ở cấp độ nanosecond, nếu bạn cần lấy các bước thời gian ở cấp độ millisecond, bạn có thể sử dụng mã sau:

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

Unix()

Unix(), Trở lại các bước thời gian ở cấp độ giây.

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

GetOS()

GetOS(), trả về thông tin về hệ thống của người quản lý.

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

Trên máy tính AppleMac OSLưu ý: Lưu ý:

GetOS:darwin/amd64

darwinCó nghĩa làMac OSTên của hệ thống.

MD5 ((String)

MD5(String), giá trị tham số: kiểu chuỗi.

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

Lưu ý:

MD5 5eb63bbbe01eeed093cb22bb8f5acdc3

DBExec ((...)

DBExec(), giá trị tham số: có thể là kiểu như chuỗi, giá trị số, giá trị boolean, giá trị trống. Giá trị trả về: đối tượng chứa kết quả thực thi của câu lệnh SQLite. Chức năng giao diện cơ sở dữ liệuDBExec()Thông qua các tham số nhập, bạn có thể điều hành cơ sở dữ liệu ổ đĩa (SQLite database) ; thực hiện các thao tác về việc thêm, xóa, kiểm tra, thay đổi dữ liệu trong cơ sở dữ liệu ổ đĩa, hỗ trợSQLiteHình ngữ. Các bảng lưu trữ hệ thống trong cơ sở dữ liệu thực:kvdbcfglogprofitchartBạn có thể sử dụng các biểu đồ này để làm việc trên các trang web của bạn, nhưng đừng sử dụng chúng.DBExec()Chức năng chỉ hỗ trợ ổ đĩa thực.

  • Hỗ trợ cơ sở dữ liệu trong bộ nhớ Đối vớiDBExecCác tham số của hàm nếusqlCâu nói là:Khởi đầu, hoạt động trong bộ nhớ cơ sở dữ liệu, không viết tài liệu, nhanh hơn; phù hợp với các hoạt động cơ sở dữ liệu không cần lưu trữ lâu dài, 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)
        
        // 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
        
        // 查询数据
        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)
        
        # 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
        
        # 查询数据
        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);
        
        // 增加一条数据
        Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
        
        // 查询数据
        Log(DBExec(":SELECT * FROM TEST_TABLE;"));
    }
    
  • Tạo bảng

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);
}
  • Hoạt động thêm, xóa, kiểm tra và thay đổi các bản ghi trong bảng
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))
    
    // 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    // 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    // 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))    
    
    // 删除数据
    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))
    
    # 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))
    
    # 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"))
    
    # 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000))
    
    # 删除数据
    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));

    // 增加一条数据
    Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"));
    
    // 查询数据
    Log(DBExec("SELECT * FROM TEST_TABLE;"));
    
    // 修改数据
    Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000));
    
    // 删除数据
    Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110));
}

UUID (()

UUID(), trả về một UUID duy nhất 32 bit, chỉ áp dụng cho ổ đĩa thực.

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

EventLoop ((timeout)

EventLoop(timeout)trong bất kỳwebsocketCó thể đọc hoặcexchange.GoHttpQuery_GoVâng, các nhiệm vụ đồng thời sẽ được trả về sau khi hoàn thành.timeoutTrả về chờ một sự kiện xảy ra nếu được đặt là 0, nếu lớn hơn 0 là đặt sự kiện chờ quá thời gian, và nhỏ hơn 0 ngay lập tức trả về sự kiện gần đây nhất. Trả về tương tự như nếu khôngnull, trả về nội dungEventLoại kích hoạt sự kiện. Chức năng này chỉ áp dụng cho ổ đĩa thực.

Lần gọi đầu tiên trong mãEventLoopCác công cụ nghe lén sẽ được khởi động sau khi một sự kiện được gọi lại, nếu bạn bắt đầu lần đầu tiên.EventLoopGọi, sẽ bỏ qua các sự kiện trước đó. cấu trúc hàng đợi được gói trong hệ thống cơ sở lưu trữ tối đa 500 cuộc gọi lại sự kiện nếu chương trình không được gọi kịp thời trong quá trình thực hiện.EventLoopNếu loại bỏ, sẽ mất 500 bộ nhớ cache và các cuộc gọi lại sự kiện sau đó.EventLoopViệc gọi hàm sẽ không ảnh hưởng đến hệ thốngwebsocketVà cũng không ảnh hưởng đếnexchange.GoCác bộ nhớ cache của các hàm song song như vậy vẫn cần sử dụng các phương pháp riêng để lấy dữ liệu.EventLoopVà nếu bạn không làm được điều đó, thì bạn sẽ không thể làm được điều đó.EventLoopMột hàm sẽ tạo ra một sự kiện trả về.

EventLoopMục đích chính của hàm là thông báo cho layer chính sách, tầng dưới của hệ thống nhận được dữ liệu mạng mới.EventLoopKhi hàm trả về sự kiện, chỉ cần đi qua tất cả các nguồn dữ liệu; ví dụ:websocketCác bạn có thể tham gia vào chương trình này.exchange.GoCác đối tượng được tạo cố gắng lấy dữ liệu.Liên kết thư viện

Trong hàm chínhmain()Trong khi gọi, nghe lén các sự kiện trên các đường dây chính.JavaScriptTrong chiến lược viết ngôn ngữ, bạn có thể sử dụng một số từ như:__Thread()Các chuỗi được tạo bởi các hàm, cũng có thể được gọi trong các hàm thực thi của các chuỗi để nghe các sự kiện của các chuỗi hiện tại.

function main() {
    var routine_getTicker = exchange.Go("GetTicker")
    var routine_getDepth = exchange.Go("GetDepth")
    var routine_getTrades = exchange.Go("GetTrades")
    
    // Sleep(2000),如果这里使用Sleep语句,会导致之后的EventLoop函数错过之前的事件,因为等待了2秒,并发的函数

Thêm nữa

qq89520Có một vấn đề là hàm C sẽ luôn thử lại hay chỉ thử lại một lần

Ồ, ôi._C ((function, args...) là mặc định là 3s? Có thể thay đổi mặc định để đặt trực tiếp _CDelay ((1000) trước _C ((function, args...)?

ăn trưaCluster: Nếu bạn tạo ra 1000 robot đồng thời và không có áp lực, bạn có thể tạo ra nhiều người quản lý để phân tán nhiệm vụ Có ví dụ mã để xây dựng các tập hợp? Làm thế nào để xây dựng nhiều quản trị viên để phân tán nhiệm vụ

Wangjy1Log ((talib.help (('MACD')); chỉ được sử dụng trong js, Python không có tài sản talib.help...

cjz140Tôi nghĩ rằng tất cả những thứ này đều có nghĩa là chờ đợi để thử lại

3263243yLàm thế nào để xóa ErrorFilter sau khi SetErrorFilter? Không lọc thông báo lỗi.

qq47898077Có cách nào để sử dụng thư viện của bên thứ ba không?

qq47898077Nếu bạn muốn kế thừa các đối tượng giao dịch định nghĩa lớp mới, lớp cha nên điền vào gì?

ethanwuCó công cụ chỉnh sửa bản địa không?

PenglihengBạn có biết exange.IO (("status")?) không?

PenglihengTại sao hàm sell màu xám, có phải hàm đại diện không còn sử dụng được không?by có sẵn, vậy làm thế nào để bán?

PenglihengTại sao hàm sell màu xám, có phải hàm đại diện không còn sử dụng được không?by có sẵn, vậy làm thế nào để bán?

PenglihengTôi không biết tiếng Anh, haha, tôi muốn hỏi về sự hỗ trợ của es6.

PenglihengTôi không biết tiếng Anh, haha, tôi muốn hỏi về sự hỗ trợ của es6.

Don.Vậy, chúng ta viết đường trung bình của Volume như thế nào?

con rùaNếu không thành công, bạn sẽ được trả gì nếu mua trên exchange.Buy.1000 theo giá thị trường?

Ông NinhPhong cách mới này rất đẹp.

cá mậpMạng lưới thử nghiệm của Bitmex ((testnet.bitmex.com) cũng có giao diện API, nhưng hiện tại sàn giao dịch chỉ có thể chọn trạm chủ của Bitmex, địa chỉ tài liệu API là https://testnet.bitmex.com/app/apiOverview Làm thế nào để hỗ trợ?

cxjijinvar ret1 = exchanges[0].IO (("api", "future_estimated_price", "symbol=btc_usd"); Log (('ok tương lai dự kiến giao dịch giá', ret1); https://dn-filebox.qbox.me/d1ed268c1e75753c5d289447d279aa9d81e41b5f.png Tại sao lại gọi giao diện giao dịch khác và viết thông báo sai?

allenfrostlineBạn có muốn biết sự khác biệt giữa realTicker và Ticker không? gần đây đã viết lại các chiến lược của bộ sưu tập và xuất hiện cùng một lúc nhưng không có sự đề cập nào trong API trước đây.

hình ảnhXin chào, với tư cách là một nhà phát triển Python, bạn nghĩ tài liệu API của bạn viết gì?

allenfrostlineGetAccount: [EAPI: Rate limit exceeded] Bạn muốn hỏi làm thế nào để giải quyết vấn đề này?

zhjx2314Không hỗ trợ StochRSI, có thể thêm sớm không?

yhfggTrong khi đó, bạn có thể sử dụng các ứng dụng khác nhau để tạo ra các ứng dụng khác nhau.

yhfggPhiên bản nào của python?

ừmĐịnh nghĩa của GetFee được cho là trả về một cấu trúc Fee.

zkwapCó cách nào để gọi talib bằng js không?

yhfggTìm tài liệu python

wmjbs123Có thể làm cho nền mã của các biên tập viên chiến lược có màu đen không?

Don.Làm thế nào để thiết lập bản tóm tắt trong WeChat của robot?

Số: điênBạn có thể thêm một trường giao dịch bằng giá trong cấu trúc Order không?

Nhỏ béGetOrders: lấy tất cả các đơn đặt hàng chưa hoàn thành, trả về một cấu trúc Array Order, giao dịch Bitcoin ETH ở Trung Quốc, chỉ trả về 10 mục gần đây nhất.

yhfggCác chức năng toán học cần được sử dụng trong xác suất thống kê ở đâu?

jiebangGiá trị trả về của hàm $.Cross ((x, y) có nghĩa là gì?

Mẹ tôi gọiLogReset sẽ xóa tất cả các nhật ký và có thể có một số tham số để xác định số lượng lưu trữ. Làm thế nào để loại bỏ một vài nhật ký mới nhất?

edwardgywCó phải talib đã bị bỏ qua hoặc không được chuyển nhượng?

Quảng trường Phúc GiangCó vẻ như không có chức năng tham khảo chỉ số!

NhỏTôi không hiểu, quá dài một, giải quyết được, cảm ơn bạn

NhỏCách viết số trong mảng là như thế nào, tôi sử dụng records.remove ((records[0])

SnakeayuTuy nhiên, một số ứng dụng khác cũng được sử dụng, trong đó có ứng dụng ATR.

SnakeayuTuy nhiên, một số ứng dụng khác cũng được sử dụng, trong đó có ứng dụng ATR.

57278863Hãy học cách lấy giá và đặt mua các hợp đồng tương lai truyền thống, xin lỗi, nền tảng rất mỏng.

KirinMột số người cho rằng, "Điều này là một sự thay đổi lớn trong kinh tế".

Nhỏzero, bạn có thể viết một ví dụ về giao dịch tương lai truyền thống không?

NhỏKhi giữ nhiều đơn vị trống cùng một lúc, làm thế nào để in trạng thái giữ, cách in của tôi là [object object], làm thế nào để có được trạng thái giữ nhiều đơn vị và đơn vị trống, và cũng có GetTicker ((), làm thế nào để có được giá trong tuần, tuần sau và quý trong tuần đó, trong vòng eo trong tuần đó, tuần sau và quý tôi đã viết.

cxjijinCác sàn giao dịch tương lai có thể lấy thị trường bằng GetTicker (); trả về thị trường hợp đồng kiểu đó (; tuần trước, tuần sau...)?

Bán lớnBạn có thể nói thêm về StochRSI không?

momoxCancelOrder ((orderId) hủy một đơn đặt hàng dựa trên số đơn đặt hàng, trả về true hoặc false, hãy hỏi true= đơn hàng đã được hủy thành công, phải không?

momox_G(K, V) có thể lưu bảng từ điển toàn cầu Cách lưu biến toàn cầu có thể được sử dụng để chia sẻ dữ liệu giữa các chính sách khác nhau không?

flufy3dSự nổi tiếng

KhôngBạn có thể đặt lại nhật ký thu nhập bằng cách sử dụng LogProfitReset.

xcyCó thể sao chép trực tiếp EA để sử dụng nó không?

sjironmanTôi cảm thấy nền tảng này thật tuyệt vời.

NhỏĐây là ngôn ngữ nào, có tài liệu nào để học không?

jxhbtcData error 1 tuần không kết nối robot

dhyhuChỉ số TA, chỉ tính giá đóng cửa?

btcrobotChào thế giới.

Giấc mơ nhỏChức năng _C sẽ thử lại một lần nữa cho đến khi có kết quả thành công.

Giấc mơ nhỏTalib của python cần cài đặt.https://www.botvs.com/bbs-topic/669 bạn có thể xem bài viết này.

Giấc mơ nhỏSleep là trình không làm gì, chờ đợi các tham số được thiết lập trong số milliseconds, và _C là hàm gọi lại một lần tham số.

Giấc mơ nhỏKhông cần thừa kế, JS trực tiếp được gói trong đối tượng {name: "new object", old_exchange : exchange[0],...... }

Giấc mơ nhỏCó bản địa biên tập viên đồng bộ từ xa plugin, cơ bản là biên tập bản địa điều chỉnh từ xa.

Giấc mơ nhỏBạn có thể tham gia nhóm QQ,^^ dễ dàng thảo luận~

Giấc mơ nhỏTrong tài liệu API, màu xám có nghĩa là hàm này không có giải thích mở rộng quá nhiều, chỉ hiển thị màu xám, đại diện màu xanh có nhiều giải thích hơn, đó là tất cả.

Giấc mơ nhỏES6 không hỗ trợ, ^^

Giấc mơ nhỏBạn có thể đến nhóm QQ, tôi, mô tả vấn đề, tôi sẽ trả lời ^^

Giấc mơ nhỏSau khi trả lại một lỗi, bạn sẽ không đặt hàng (thực sự là mua, không đủ tiền!).

con rùaVí dụ, OKCoin, nếu số tiền mua nhiều hơn số tiền được nắm giữ, nó sẽ trở lại như thế nào?

Giấc mơ nhỏTrong khi đó, một số nhà đầu tư khác cũng cho biết họ sẽ trả lại một số đơn đặt hàng cho các sàn giao dịch này.

KhôngĐã hỗ trợ chuyển đổi giao dịch khi chạy, cần tải xuống trình quản lý mới nhất. Hỗ trợ Bter/Poloniex chi tiết tài liệu API mô tả các chức năng giao dịch bên dưới ((trước khi xóa cache trình duyệt, hãy cập nhật nếu không thấy)

Giấc mơ nhỏTôi sẽ giúp bạn tìm ra câu hỏi.

Gia đình nuôi con nghề nghiệpBạn cần thiết lập danh sách trắng, tôi đặt IP của máy chủ?

Giấc mơ nhỏĐây là liên kết dưới cùng không được thiết lập Máy chủ không phản hồi. Có đặt địa chỉ IP khi yêu cầu API KEY?

Gia đình nuôi con nghề nghiệpPost http://api.btc38.com/v1/getMyBalance.php: read tcp 192.168.0.227:58596->211.149.148.144:80: wsarecv: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 2017-05-23 21:08:24 Thời đại Bitcoin lỗi GetAccount: timeout 2017-05-23 21:08:02 Thời đại Bitcoin lỗi GetAccount: timeout 2017-05-23 21:07:40 Thời đại BitTorrent 2017-05-23 21:07:20 Hoạt động bắt đầu lại Có phải đó là vấn đề danh sách trắng IP???

Giấc mơ nhỏCác máy chủ của sàn giao dịch không phản hồi, giao thức TCP không được thiết lập sau ba lần bắt tay.

Gia đình nuôi con nghề nghiệpA connection attempt failed because the connected party did not properly respond after a period of time (Một nỗ lực kết nối đã thất bại vì bên kết nối đã không phản hồi đúng cách sau một khoảng thời gian)

Giấc mơ nhỏXin chào! Đây là hàm exchange.IO ((api, ApiName, Args) không được hỗ trợ, xem https://www.botvs.com/bbs-topic/812

Gia đình nuôi con nghề nghiệpMột nỗ lực kết nối đã thất bại bởi vì bên kết nối đã không phản hồi đúng cách sau một khoảng thời gian,

Gia đình nuôi con nghề nghiệpThời đại Bitcoin không hỗ trợ

Giấc mơ nhỏhttps://dn-filebox.qbox.me/a709b30c6cc0a3565234b9e0c99b073f7ba8b454.png Có lẽ là được rồi.

Ông NinhVí dụ, tôi muốn giao dịch toàn đồng tiền của poloniex, nhưng chỉ có một vài đồng tiền được hỗ trợ bởi BOTvs, và exchange.IO dường như không hỗ trợ mạng P.

Giấc mơ nhỏBạn có thể gọi exchange.IO.

Ông NinhVậy API cần xác minh tài khoản là gì?

Giấc mơ nhỏNếu API không yêu cầu xác minh tài khoản có thể được sử dụng bằng httpQuery (xem tài liệu BotVS chi tiết hơn), API giao dịch thực tế cần truy cập.

Giấc mơ nhỏCác tham số API có thể được truyền qua HttpQuery: https://www.okcoin.com/api/v1/future_estimated_price.do?symbol=btc_usd. Bài viết: https://www.botvs.com/bbs-topic/850

hình ảnhXin cảm ơn, mong đợi một tài liệu API hoàn hảo.

Giấc mơ nhỏBạn có thể hỏi tôi xem API của realTicker được thấy ở đâu không?

Giấc mơ nhỏhttps://dn-filebox.qbox.me/fe1a6f5563ed43a5357f858ecf8a50239619228e.png Tài liệu API là ngôn ngữ JavaScript. Mô tả, phiên bản python mô tả các bài đăng được đặt ở đầu trang trang của cộng đồng chat chat. Nếu bạn có câu hỏi cụ thể, vui lòng gửi ý kiến.

KhôngXin chào, cảm ơn đã đề xuất, tài liệu API đang được xây dựng lại.

Giấc mơ nhỏXin chào - hiển thị rằng truy cập đã vượt quá giới hạn. https://dn-filebox.qbox.me/a09498920d04cac62624b7438a058d2098d8fb00.png Có sử dụng chức năng Sleep ((1000) trong chính sách không?, 1000 là cho chương trình tạm dừng một giây mỗi vòng, có thể tự đặt, mục đích là để kiểm soát chương trình truy cập API tần suất, vì một số sàn giao dịch đã đặt giới hạn truy cập tối đa, một thời gian nhất định vượt quá một số lần truy cập nhất định sẽ từ chối truy cập, khóa địa chỉ IP.

Giấc mơ nhỏhttps://dn-filebox.qbox.me/c29ab7fc279e1b758355f137907cf52dc8257df6.png Cá nhân tôi đã viết rằng chỉ số STOCHRSI đã được so sánh với OK, đồng ý rằng tốc độ hơi chậm và cần được tối ưu hóa, tạm thời có thể sử dụng.

KhôngBạn có thể tự chọn xem botvs cung cấp máy chủ hay chủ nhà của bạn, phiên bản là 2.7.5

Giấc mơ nhỏCác bạn có thể tham gia vào chương trình này.

Giấc mơ nhỏBây giờ bạn có thể tự cấu hình phong cách nền của mình.

Giấc mơ nhỏCác tài liệu python đang được viết.

Giấc mơ nhỏCó thể sử dụng tài khoản talib hỗ trợ.

hzzgood48 https://www.botvs.com/bbs-topic/276

Giấc mơ nhỏCó một ví dụ ở quảng trường chiến lược: https://www.botvs.com/strategy/15098

KhôngTruy cập vào tính chất AvgPrice của Order, các sàn giao dịch hỗ trợ được, các sàn giao dịch không hỗ trợ sẽ luôn luôn là 0 tính năng này

yhfggLàm thế nào để trích dẫn các tài liệu của bên thứ ba?

KhôngMathjs không thể đáp ứng yêu cầu của mình, nó chỉ có thể tìm kiếm các chính sách sao chép nhập thư viện của bên thứ ba. Để có thể biên dịch nhanh hơn, hệ thống chỉ tích hợp một số ít thư viện.

Giấc mơ nhỏCó một số người nói rằng họ có thể tìm thấy một người bạn trên mạng mà không phải là một người bạn của họ.

jiebangCảm ơn.

Giấc mơ nhỏBạn có thể xem phần giải thích của thư mục phân tích thư viện giao dịch tiền kỹ thuật số, trong đó có phần giải thích về hàm $.Cross.

KhôngKhông thể xóa mới nhất, chỉ giữ lại một vài bài mới nhất... xóa tất cả bài cũ trước đó.

KirinĐể lấy mỗi vị trí với vị trí [i], vị trí là một mảng

Ông Ninhexchange.GetRecords ((PERIOD_D1));

KirinTôi đã từng dùng một giao dịch tương lai truyền thống để báo cáo với GetAccount: not login, password không sai, không đăng nhập.

KhôngTheo mặc định, SetContractType được yêu cầu trước để có được mục SetContractType.

KhôngBạn có thể thấy, đây là giá trị trả về hành động hủy lệnh mà sàn giao dịch trả về, nhưng thực sự hủy không hủy, tùy thuộc vào cách xử lý bên trong sàn giao dịch.

momox3q

KhôngChưa bao giờ, nó bị tách biệt.

xuanxuanTất nhiên là không, đó là MT4 riêng.

KhôngJavascript là một tài liệu phổ biến trên mạng.

Bán lớnVấn đề của bạn đã được giải quyết chưa?

KhôngPhần lớn là, dữ liệu được truyền vào có thể là một bản ghi trực tiếp hoặc một mảng giá thuần túy.