В процессе загрузки ресурсов... загрузка...

Глобальный

Версия

Возвращает номер текущей версии системы.

Номер текущей версии системы, например:3.6- Да. строка

Версия ((()

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

Номер версии системы - это номер версии программы Dockers.

Спать.

Функция сна, вызывающая паузу программы на некоторое время.

Сон ((миллисекунда)

ВmillisecondПараметр используется для установки продолжительности сна и количества миллисекунд. миллисекунды Истинно Номер

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

Например, при выполненииSleep(1000)Он поддерживает операции с временем сна менее 1 миллисекунды, например, настройкаSleep(0.1). Он поддерживает минимальный параметр0.000001, т.е. наносекундная спячка, где 1 наносекунда равна1e-6миллисекунд. При написании стратегий вPythonязык,Sleep(millisecond)Не рекомендуется использовать эту функцию для выборов с интервалом, операций с временем ожидания.time.sleep(second)ФункцияPythonЭто...timeЭто потому, что использованиеtime.sleep(second)функция в стратегии заставляет программу стратегии ждать определенный период времени фактически при обратном тестировании (не пропуская временные ряды системы обратного тестирования), поэтому она заставляет стратегию проводить обратное тестирование очень медленно.

IsVirtual

Определить, является ли среда управления стратегией системой обратного тестирования.

Стратегия возвращает истинное значение, например:trueпри запуске в среде системы обратного тестирования стратегия возвращает ложное значение, например:falseпри работе в среде реального трейдинга. Буль

Виртуальная?

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

Определить, является ли текущая рабочая среда системой обратного тестирования, которая используется для совместимости с разницей между обратным тестированием и живой торговлей.

Почта

Отправь мне письмо.

Успешная доставка электронной почты возвращает истинное значение, например,true, и неудачная доставка возвращает ложное значение, например,false- Да. Буль

Почта ((smtpСервер, smtpИмя пользователя, smtpПароль, mailTo, заголовок, тело)

Используется для определенияSMTPадрес обслуживания отправителя электронной почты. smtpServer неправда строка Используется для указания адреса электронной почты отправителя. smtpUsername (имя пользователя) неправда строка ВSMTPпароль для почтового ящика отправителя электронной почты. smtpPassword (пароль) неправда строка Используется для указания адреса электронной почты получателя. mailTo неправда строка Заголовок электронной почты. Заголовок неправда строка Корпус почты. тело неправда строка

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

ВsmtpPasswordпараметр устанавливает пароль дляSMTPСервис, а не пароль почтового ящика. При установкеsmtpServerпараметр, если вам нужно изменить порт, вы можете добавить номер порта прямо в параметреsmtpServerНапример: QQ mailsmtp.qq.com:587, который доступен для тестирования. Если сообщается ошибка:unencryped connection, вам нужно изменитьsmtpServerВ соответствии сMailФормат параметра:ssl://xxx.com:xxx, например,sslМетодSMTPдля почты QQ:ssl://smtp.qq.com:465илиsmtp://xxx.com:xxx- Да. Это не работает в системе обратного тестирования.

{@fun/Global/Mail_Go Mail_Go} Я не знаю.

Mail_Go

Асинхронная версияMail function.

ВMail_GoФункция возвращает одновременный объект сразу, и вы можете использоватьwaitУспешная доставка почты возвращает истинное значение, например,true, и неудачная доставка возвращает ложное значение, например,false- Да. объект

Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, название, корпус)

Он используется для определенияSMTPсервисный адрес отправителя электронной почты. smtpServer Истинно строка Он используется для указания адреса электронной почты отправителя электронной почты. smtpUsername (имя пользователя) Истинно строка ВSMTPпароль для почтового ящика отправителя электронной почты. smtpPassword (пароль) Истинно строка Используется для указания адреса электронной почты получателя электронной почты. mailTo Истинно строка Заголовок электронной почты. Заголовок Истинно строка Корпус почты. тело Истинно строка

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.

Это не работает в системе обратного тестирования.

{@fun/Global/Mail Mail} Я не знаю.

НастроитьErrorFilter

Профиль ошибок.

УстановитеErrorFilter (фильтр)

Регулярная строка выражений. фильтры неправда строка

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

Фильтрация распространенных ошибок.

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

Отфильтровать сообщение об ошибке интерфейса.

Регистрации ошибок, совпадающие с этим регулярным выражением, не будут загружены в систему журналов. Вы можете вызвать его несколько раз (без ограничения на количество раз), чтобы установить несколько условий фильтра. Регулярные выражения, установленные несколько раз, будут накапливаться и вступать в силу одновременно. Вы можете установить пустую строку для сброса регулярного выражения, используемого для фильтрации журналов ошибок:SetErrorFilter("")Фильтрованные журналы больше не записываются в файл базы данных, соответствующий идентификатору торговли в каталоге Docker, чтобы предотвратить частое сообщение об ошибках от раздутия файла базы данных.

GetPid

Получите идентификатор торгового процесса.

Возвращение идентификатора торгового процесса. строка

GetPid ((()

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

ПолучитьLastError

Получил последнее сообщение об ошибке.

Последнее сообщение об ошибке. строка

ПолучитьLastError()

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

Это не работает в системе обратного тестирования.

Получить команду

Получает команду стратегического взаимодействия.

Формат возвращенной команды:ControlName:Data. ControlNameэто название контрольного элемента, иDataЕсли интерактивный элемент управления не имеет входных ящиков, выпадающих ящиков и других компонентов (например, кнопка управления без входных ящиков), то возвращенный формат командыControlName, который возвращает только название элемента управления. строка

Получить команду ((()

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

Выявляет команду взаимодействия и используетLogФункция вывода команды взаимодействия при ее обнаружении.

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

Например, стратегия интерактивного управления добавляет контроль без поля ввода, интерактивный контроль называется:buy, информация о описании контроля:buyПродолжайте добавлением элемента управления с окном ввода. Интерактивный элемент управления называется:sellи сообщение о описании контроля:sellКод взаимодействия разработан в стратегии для ответа на различные элементы управления взаимодействием:

Это не работает в системе обратного тестирования.

GetMeta

Получить значение мета написано при генерации кода регистрации стратегии.

Metaданные. строка

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

Пример сценария применения: использованиеMetaограничить объем активов, которыми управляет стратегия.

Сценарий применения: необходимо сделать капитальные лимиты для разных стратегических арендаторов.Metaзначение, установленное при генерации регистрационного кода, не может превышать 190 символов, аGetMeta()Если нет метаданных (Meta) устанавливается при генерировании кода регистрации стратегии,GetMeta()Функция возвращает null. Она не работает в системе обратного тестирования.

Назначьте

Для примитивныхSocketДоступ, поддержкаtcp, udp, tls, unixПоддержка 4 популярных протоколов связи:mqtt, nats, amqp, kafkaПоддержка подключения к базам данных:sqlite3, mysql, postgres, clickhouse.

ВDial()Обычный вызов возвращает объект соединения, который имеет три метода:read, writeиclose.readДля считывания данных используетсяwriteС помощью этого метода передаются данные иcloseметод используется для закрытия соединения. Вreadметод поддерживает следующие параметры:

  • Когда параметры не передаются, он блокирует до тех пор, пока сообщение не будет доступно и вернется, например:ws.read().
  • При передаче в качестве параметра единица составляет миллисекунды, указывая время ожидания сообщения.ws.read(2000)указывает время задержки в две секунды (2000 миллисекунд).
  • Следующие два параметра действительны только для WebSocket: Передача параметра-1означает, что функция возвращает сообщения немедленно, независимо от наличия или отсутствия сообщений, например:ws.read(-1)- Да. Передача параметра-2означает, что функция возвращает сразу с сообщением или без него, но возвращается только последнее сообщение, а буферизированное сообщение отбрасывается.ws.read(-2).

read()описание буфера функции: Входящие данные, отправляемые протоколом WebSocket, могут вызывать накопление данных, если временной интервал между стратегиейread()Эти данные хранятся в буфере, который имеет структуру данных очереди с максимальным числом 2000.

Сценарий Нет параметра Параметр: -1 Параметр: -2 Параметр: 2000, в миллисекундах
Данные уже в буфере Немедленно верните старые данные Немедленно верните старые данные Немедленно верните последние данные Немедленно верните старые данные
Нет данных в буфере Возвращение при блокировке данных Немедленно верните нуль Немедленно верните нуль Подождите 2000 мс, верните null, если нет данных, верните null, если есть данные
Соединение WebSocket отключено или повторно подключено базовым read() функция возвращает пустую строку, т.е.: , и write() функция возвращает 0. Ситуация обнаружена. Вы можете закрыть соединение с помощью функции close(), или если вы настроили автоматическое воссоединение, вам не нужно его закрывать, основной система автоматически воссоединит его.

объект

Выбрать адрес Назови (адрес, время выхода)

Адрес запроса. Адрес неправда строка секунды таймаута, Тайм-аут ложное Номер

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

Пример вызова функции 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();
}

Для доступа к интерфейсу WebSocket Binance:

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

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

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

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

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

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

Доступ к интерфейсу OKX WebSocket:

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

Доступ к интерфейсу Huobi's WebSocket:

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

Для доступа к интерфейсу аутентификации 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

Объект соединения, возвращаемый функцией Dial при подключении к базе данных, имеет две уникальные для него функции метода:

  • exec(sqlString): Используется для выполнения SQL заявлений таким же образом, какDBExec() function.
  • fd():fd()функция возвращает ручку (например, переменная ручка является рукой), которая будет использоваться другими потоками для повторного подключения (даже если объект, созданный Dial, уже был закрыт при исполненииclose()с функцией закрытия соединения) путем прохождения ручки вDial()функция, например,Dial(handle)Подключение для повторного использования. Ниже приведен пример функции Dial, соединяющейsqlite3 database.

Подробная информацияaddressпараметр, разделенный|символ после обычного адреса:wss://ws.okx.com:8443/ws/v5/publicЕсли есть.|символы в строке параметров, затем||Часть после этого - некоторые параметры параметров функции, и каждый параметр связан с&Например,ss5параметры прокси и сжатия могут быть установлены вместе следующим образом:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Функции, поддерживаемые параметром адреса функции Dial Описание параметров
Параметры, связанные с сжатием данных протокола WebSocket: compress=value parameter compress - это метод сжатия, параметры сжатия: gzip_raw, gzip и т. д. Если метод gzip не является стандартным gzip, вы можете использовать расширенный метод: gzip_raw
Параметры, относящиеся к сжатию данных протокола WebSocket: mode=value parameter режим - это режим сжатия, параметр режима может быть двойным, отправка, recv. dual - это двустороннее сжатие, отправка сжатых данных, прием сжатых данных. отправка - это отправка сжатых данных. recv - это прием сжатых данных, локальная декомпрессия.
Протокол WebSocket устанавливает базовые параметры, связанные с автоматическим воссоединением: reconnect=значение параметра reconnect означает установить reconnect, reconnect=true означает включить reconnect. По умолчанию reconnect отсутствует, если этот параметр не установлен.
Протокол WebSocket устанавливает базовые параметры, связанные с автоматическим воссоединением: interval=value parameter интервал - это интервал повторных попыток, в миллисекундах, интервал=10000 - это интервал повторных попыток 10 секунд, по умолчанию 1 секунда, когда он не установлен, то есть интервал=1000.
Протокол WebSocket устанавливает базовые параметры, связанные с автоматическим воссоединением: полезная нагрузка=значение параметра полезная нагрузка - это сообщение подписки, которое необходимо отправить при повторном подключении WebSocket, например: полезная нагрузка=okokok.
Параметры, относящиеся к носкам5 прокси: proxy=значение параметра Прокси - это настройка прокси ss5, формат значения параметра: socks5://name:pwd@192.168.0.1:1080, имя - это имя пользователя сервера ss5, pwd - это пароль входа на сервер ss5, 1080 - это порт службы ss5.

ВDial()Функция поддерживается только для торговли в реальном времени. При подключении к базе данных с помощью функции Dial строка подключения записывается со ссылкой на проект драйвера языка go для каждой базы данных.

Базы данных поддерживаются Движущие проекты Соединительная строка Примечания
Склайт3 github.com/mattn/go-sqlite3 sqlite3://файл:test.db?cache=shared&mode=memory Вsqlite3://Префикс указывает, что используется база данных sqlite3, пример вызова:Dial("sqlite3://test1.db")
mysql github.com/go-sql-driver/mysql mysql://username:yourpassword@tcp(localhost:3306)/yourdatabase?charset=utf8mb4
послерост github.com/lib/pq postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432
Кликхаус github.com/ClickHouse/clickhouse-go clickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase

Пожалуйста, обратите внимание, что когдаpayloadсодержание, установленное вaddressпараметр содержит символы=или других специальных символов, это может повлиять на анализaddressпараметрDialфункция, например следующий пример.

Пример вызова частного интерфейса websocket backPack Exchange:

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

Следующий вызов в коде работает нормально:

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

Если вы напишете это прямо вpayload, он будет работать неправильно, например:

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

В настоящее время только JavaScript поддерживает использованиеmqtt, nats, amqp, иkafkaКод стратегии языка JavaScript используется в качестве примера, чтобы показать использование четырех протоколов:mqtt, nats, amqp, и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")
    }
}

Подробная документация:Исследование FMZ: Практика протокола связи между стратегиями торговли в режиме реального времени

HttpQuery

Отправьте запрос на http.

Возвращает данные ответа запроса.JSONstring, он может быть проанализированJSON.parse()Функция вJavaScriptязыковой стратегии,json::parse()Функция вC++Если в структуре опций значение отладки установлено на true, возвращаемое значение является объектом (JSON); если значение отладки установлено на false, возвращаемое значение является строкой. строка, объект

HttpQuery ((url) HttpQuery ((url, параметры)

URL-адрес запроса HTTP. URL-адрес Истинно строка Например, настройки, связанные с запросом HTTP, могут быть структурированы следующим образом:

{
    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
}
  • профиль: используется для моделирования браузераtlsОтпечатки пальцев. Поддерживаемые настройки включают следующие параметры: chrome_:"chrome_103", "chrome_104", "chrome_105", "chrome_106", "chrome_107", "chrome_108", "chrome_109", "chrome_110", "chrome_111", "chrome_112", "chrome_117"... Сафари:"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_89", "opera_90", "opera_91"... Заландо:"zalando_android_mobile", "zalando_ios_mobile"... Ники."nike_ios_mobile", "nike_android_mobile"... Облакостроитель:"cloudscraper"... Мммм."mms_ios"... mesh_:"mesh_ios", "mesh_ios_1", "mesh_ios_2", "mesh_android", "mesh_android_1", "mesh_android_2"... Подтверждение:"confirmed_ios", "confirmed_android"... Хорошо."okhttp4_android_7", "okhttp4_android_8", "okhttp4_android_9", "okhttp4_android_10", "okhttp4_android_11", "okhttp4_android_12", "okhttp4_android_13",
  • Debug: когда он настроен наtrue,HttpQueryПризыв функции возвращает полное сообщение ответа.false, только данные вBodyсообщения ответа возвращается.
  • Тайм-аут: настройка тайм-аута, установленная на 1000 означает 1 секунду тайм-аута.
  • Charset: поддерживает транскодирование запрошенных данных ответа, таких как GB18030. Все поля в этой структуре являются необязательными, например,profileполе может быть оставлено в стороне.

варианты ложное объект

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

Пример доступа к интерфейсу API публичного тикера 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/");
}

Функция HttpQuery использует настройки прокси.

ВHttpQuery()Функция поддерживает толькоJavaScript, C++язык,Pythonязык может использоватьurllibБиблиотека для отправки запросов Http напрямую.HttpQuery()используется в основном для доступа к интерфейсам биржи, которые не требуют подписи, например, общедоступным интерфейсам, таким как информация о тикерах.HttpQuery()может использоваться в системе обратного тестирования для отправки запросов (толькоGETДля получения данных, используемые в рамках реактестирования, используется 20 посещений различныхURLs, иHttpQuery()Когда те же самыеURLВторой раз,HttpQuery()Функция возвращает кэшированные данные, и больше не возникает фактических сетевых запросов.

{@fun/Global/HttpQuery_Go]

HttpQuery_Go

Отправляет запрос HTTP, асинхронную версиюHttpQuery function.

ВHttpQuery_Go()Функция немедленно возвращает одновременный объект, который может быть использован для получения результата запроса HTTP с использованиемwaitМетодJSON.parse()Функция может быть использована для анализаJSON.parse()Функция вJavaScriptязыковой стратегии.
объект

HttpQuery_Go ((url) HttpQuery_Go ((url, параметры)

URL-адрес запроса HTTP. URL-адрес Истинно строка Например, настройки, связанные с запросом HTTP, могут быть структурированы следующим образом:

{
    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
}
  • профиль: используется для моделирования браузераtls fingerprints.
  • Debug: когда он настроен наtrue, этоHttpQuery_GoПризыв функции возвращает полное сообщение ответа.false, только данные вBodyсообщения ответа возвращается.
  • Тайм-аут: настройка тайм-аута, установленная на 1000 означает 1 секунду тайм-аута. Все поля в этой структуре являются необязательными, например,profileполе может быть оставлено в стороне.

варианты ложное объект

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

Асинхронный доступ к общественному интерфейсу биржи для агрегированных данных тикеров.

ВHttpQuery_Go()Функция поддерживает толькоJavaScript,Pythonязык может быть использован сurllibБиблиотека для отправки запросов Http напрямую.HttpQuery_Go()используется в основном для доступа к интерфейсам, которые не требуют подписи на бирже, таким как общедоступные интерфейсы, такие как информация о тикерах.HttpQuery_GoФункция не поддерживается системой обратного тестирования.

{@fun/Global/HttpQuery HttpQuery} (См. также:

Кодировать

Эта функция кодирует данные в соответствии с введенными параметрами.

ВEncodeфункция возвращает данные после кодирования и шифрования. строка

Зашифровка ((algo, inputFormat, outputFormat, data) Зашифровка ((algo, inputFormat, outputFormat, data, keyФормат, ключ)

Параметрalgo- алгоритм, используемый при расчете кодирования.raw(не используется алгоритм), "знак", 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, 2b.512, blake2s.128, blake2s.256 Параметр.algoтакже поддерживает: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk, закодировать и декодировать строки. Параметрalgoтакже поддерживает: алгоритм ed25519. Поддерживает использование различных хеш-алгоритмов, например, параметрalgoможет быть написано как ed25519.md5, ed25519.sha512 и т. д. Он поддерживаетed25519.seedрасчеты. что-то неправда строка Используется для определения формата данныхdataпараметр.inputFormatпараметр может быть установлен как один из следующих:raw, hex, base64, string. raw означает, что данные являются сырыми данными, hex означает, что данныеhexbase64 означает, что данныеbase64кодируется, и string означает, что данные являются строкой. ввод Формат Истинно строка Используется для указания формата данных вывода.outputFormatпараметр может быть установлен как один из следующих:raw, hex, base64, string. raw означает, что данные являются сырыми данными, hex означает, что данныеhexbase64 означает, что данныеbase64кодируется, и string означает, что данные являются строкой. Выход Формат Истинно строка Параметрdataэто данные, которые должны быть обработаны. данные неправда строка Используется для определения формата данныхkeyпараметр.keyпараметр может быть установлен как один из следующих:raw, hex, base64, string. raw означает, что данные являются сырыми данными, hex означает, что данныеhexbase64 означает, что данныеbase64кодируется, и string означает, что данные являются строкой. keyФормат ложное строка Параметрkeyсекретный ключ, используемый дляHMACПараметрkeyтребуется, когда параметрalgoУстановлено наsignилиsignTx.keyпараметр не используется дляHMACшифрование, когдаalgoпараметр установлен на raw (поскольку алгоритм должен быть определен для шифрования HMAC). Ключ ложное строка

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
}

Пример вызова функции Encode.

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

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

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

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

Параметрalgoтакже поддерживает: text.encoder.utf8, text.decoder.utf8, text.encoder.gbk, text.decoder.gbk для кодирования и декодирования строк.

ВEncode()Функция поддерживается только для живой торговли.keyиkeyFormatпараметры не переданы, тоkeyшифрование не используется.

UnixNano

Получите наносекундную временную отметку текущего момента.

ВUnixNano()Функция возвращает наносекундный временной штемпель. Номер

UnixNano ((()

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

Если вам нужно получить миллисекундные временные отметки, вы можете использовать следующий код:

{@fun/Global/Unix Unix}

Unix

Получите временную отметку текущего момента на втором уровне.

Возвращает временную отметку второго уровня. Номер

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

Получить информацию о устройстве, где расположен докер.

Информация о системе. строка

GetOS ((()

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

Например, призыв кGetOS()функция для докера, работающего наMac OSоперационная система может вернуть:darwin/amd64Потому что компьютеры Apple имеют несколько аппаратных архитектур.darwinэто названиеMac OS system.

MD5

Вычисляет хеш MD5 параметраdata.

Хэш-значение MD5. строка

MD5 (данные)

Данные, требующие вычисления MD5. данные неправда строка

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

ЗвонитьMD5("hello world")функция, возвращаемое значение:5eb63bbbe01eeed093cb22bb8f5acdc3.

{@fun/Global/EncodeEncode} - Я не знаю.

DBExec

Функции интерфейса базы данных.

Объект, содержащий результат выполнениякв. мзаявление, например:


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

объект

DBExec ((sql)

кв. мстрока заявлений. кв. м неправда строка

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

Поддержка базы данных в памяти дляDBExecпараметры функции, если:кв. мЗаявление начинается с:Он подходит для операций с базами данных, которые не требуют постоянного сохранения, например:

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

Создайте стол.

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

Добавить, удалить, проверить и изменить записи в таблице.

ФункцияDBExec()может работать с базой данных торговли в режиме реального времени (SQLite database) путем передачи параметров.SQLiteСистема зарезервировала таблицы в базе данных торгов:kvdb, cfg, log, profit, chart, не используйте эти столы.СделкиНе рекомендуется выполнять такие операции, которые могут вызвать конфликты в системе.DBExec()Функция поддерживается только для торговли в режиме реального времени.

{@fun/Global/_G _G}

UUID

Создайте UUID.

32-разрядный UUID. строка

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

ВUUID()Функция поддерживает только прямую торговлю.

Событие Loop

Слушайте события, он возвращается, когда есть какие-либоWebSocketчитаемые данные или одновременные задачи, такие как:exchange.Go(), HttpQuery_Go(), и т. д. завершены.

Если возвращенный объект не является нулевым,Eventсодержится в содержании возврата - тип запуска события. Например, следующая структура значения возврата:

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

объект

EventLoop ((() СобытиеLoop ((Timeout)

Параметрtimeoutэто время выхода, в миллисекундах.timeoutждет, пока событие произойдет, прежде чем вернется, если оно установлено на 0, если оно больше 0, оно устанавливает событие, чтобы ждать задержки, и возвращает самое последнее событие сразу, если оно меньше 0. Тайм-аут ложное Номер

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

Первый звонокEventLoop()Функция в коде инициирует механизм для этого прослушиваемого события, и если первыйEventLoop()призыв начинается после обратного вызова события, он пропустит предыдущие события.EventLoop()если функция не вызвана вовремя, чтобы вывести их во время выполнения программы, последующие вызовы событий за пределами кэша 500 будут потеряны.EventLoop()функция не влияет на кэш очереди базовой системы WebSocket или кэши одновременных функций, таких какexchange.Go()Для этих кэшей все еще необходимо использовать соответствующие методы для извлечения данных.EventLoop()Функция для данных, которые были получены доEventLoop()Основная цельEventLoop()В этом случае, если вы хотите, чтобы ваша система получила новые сетевые данные, вы должны установить, что эта система получает новые сетевые данные.EventLoop()функция возвращает событие, просто проходит через все источники данных.exchange.Go()Попробуйте получить данные.EventLoop()Функция поддерживает только прямую торговлю. Слушать события в главной нитке при вызове из главной функцииmain()В стратегиях, написанных вJavaScriptязык,threading.Thread()функция создает нить, которая также может быть вызвана в функции выполнения threads, для прослушивания событий в текущей нитке.

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

__Сервировать

В__ServeФункция используется для создания службы HTTP, службы TCP и службы Websocket (на основе протокола HTTP).

Возвращает строку, которая записывает IP-адрес и порт созданной службы.127.0.0.1:8088, [::]:8089.

строка

__Serve ((serveURI, обработчик) __Serve ((serveURI, обработчик,...args)

ВserveURIпараметр используется для настройки протокола, IP-адреса, порта и других настроек связи службы, таких какhttp://0.0.0.0:8088?gzip=true, то есть,http://:8088?gzip=true.

  • Протокол TCPserveURIнастройка параметров, таких какtcp://127.0.0.1:6666?tls=true; вы можете добавить сертификаты и частные ключи, такие какtls=true&cert_pem=xxxx&cert_key_pem=xxxx.
  • Протокол HTTPserveURIнастройки параметров, например:http://127.0.0.1:6666?gzip=true; вы можете установить настройки сжатия:gzip=true- Да. ВserveURIпараметр используется для Https, напримерhttps://127.0.0.1:6666?tls=true&gzip=true; вы можете добавитьcert_pemиcert_key_pemпараметры для загрузки сертификата.

служитьURI неправда строка ВhandlerПараметр используется для передачи в функции обработки маршрутизации (протокол HTTP), функции обработки сообщений (протокол TCP) и функции обработки потока (Websocket). Функция обратного вызова, передаваемая параметромhandlerможет определять несколько параметров, первым параметром является объект ctx (контекстный объект).

управляющий неправда Функция Фактический параметр функции обратного вызова передается как параметрhandler. Может быть несколько параметровarg, например:

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

Параметры1, 2, 3прошел в, когда звонить__Serve()функция соответствует параметрамa, b, cпрошел в функции обратного вызова.

арг ложное string, number, bool, object, array, function, null value и другие типы, поддерживаемые системой

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
  • Эта функция поддерживает только стратегии языка JavaScript.
  • Служебная нить изолирована от глобального объема, поэтому она не поддерживает закрытия или ссылки на внешние переменные, пользовательские функции и т. Д.; однако она может вызвать все функции API платформы.
  • ВWebsocketВы можете установить ветвь маршрутизации в пути и разработать код реализации дляWebsocketВы можете ознакомиться с образцом кода в этом разделе.

Функция обратного вызова, передаваемая параметромhandlerполучаетctxпараметр.ctxпараметр - это контекстный объект, используемый для получения и записи данных, с следующими методами:

  • ctx.proto ((() Применяется к протоколу Http/TCP, возвращает имя протокола при вызове.HTTP/1.1, tcp.
  • ctx.host() Применяется к протоколу Http, он возвращает информацию хоста при вызове IP-адреса и порта.
  • ctx.path ((() Применяется к протоколу HTTP, возвращает путь запроса при вызове.
  • ctx.query (ключ) Применяется к протоколу Http, возвращает значение, соответствующее ключу в запросе при вызове.http://127.0.0.1:8088?num=123, и функция обработки обратного вызова, передаваемая параметромhandlerдоходы"123"когдаctx.query("num")называется.
  • ctx.rawQuery() Применяется к протоколу HTTP, при вызове возвращает исходный запрос в запросе (запрос запроса HTTP).
  • ctx.headers (включая заголовки) Применяется к протоколу HTTP и возвращает информацию заголовка запроса в запросе при вызове.
  • ctx.header (ключ) Применяется к протоколу HTTP, он возвращает значение ключа в заголовке запроса при вызове.User-Agentв заголовках текущей просьбы:ctx.header("User-Agent").
  • ctx.method (() Применяется к протоколу Http, возвращает метод запроса при вызове, напримерGET, POST, и т.д.
  • ctx.body ((() Применяется к запросу POST протокола HTTP и возвращает тело запроса при вызове.
  • ctx.setHeader ((ключ, значение) Применяется к протоколу Http для настройки запроса заголовка информации ответа сообщения.
  • ctx.setСтатус (код) Применяется к протоколу Http, устанавливается код состояния сообщения Http. Обычно код состояния Http устанавливается в конце ветви маршрутизации. Значение по умолчанию - 200.
  • ctx.remoteAddr ((() Применяется к протоколу HTTP/TCP, возвращает удаленный адрес клиента и порт в запросе при вызове.
  • ctx.localAddr() Применяется к протоколу HTTP/TCP, возвращает локальный адрес и порт службы при вызове.
  • ctx.upgrade ((websocket) Применяется для реализации протокола Websocket на основе протокола Http, переключаяctxКонтекстный объект к протоколу Websocket; возвращение булевого значения (правда), если переключение удалось, и булевого значения (ложь), если оно не удалось.
  • ctx.read ((timeout_ms) Применяется для реализации протокола Websocket/протокола TCP на основе протокола HTTP, считывает данные соединения Websocket и соединения TCP.readМетод не поддерживается в обычном протоколе HTTP. Вы можете указать параметр задержкиtimeout_msв миллисекундах.
  • ctx.write ((s) Применяется к протоколу HTTP/TCP, используется для записи строки данных.JSON.stringify()чтобы закодировать объект JSON в строку и затем написать его.WebSocketпротокол, вы можете использовать этот метод для передачи зашифрованной строки клиенту.

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

_G

Функция выполняет глобальную функцию словаря, которая может быть сохранена.

Постоянно сохраненные данные ключевых значений вk-vпары ключевых значений. строка, число, bool, объект, массив, нулевое значение

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

Параметрkявляется именем ключа в сохраненной паре ключей и значений и не чувствителен к большим и малым буквам. k ложное строка, нулевое значение Параметрvявляется ключевым значением в сохраненной паре ключей-значений, которая может быть любыми данными, которые могут бытьJSONсериализирована. v ложное строка, число, bool, объект, массив, нулевое значение

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

Отдельная база данных для каждой торговли в режиме реального времени, данные, сохраненные_G()В случае завершения обратного тестирования, данные, сохраненные в системе обратного тестирования_G()При использовании_G()Функция сохранения сохраненных данных должна использоваться разумно в соответствии с памятью и жестким диском аппаратного устройства и не должна злоупотребляться. При звонке_G()в режиме реального времени и никаких параметров не передается,_G()функция возвращаетIdПри звонке на_G()функция, параметрvпередается как NULL, чтобы указать на удалениеk-vПри вызове_G()функция, только параметрkпроходит в строке, и_G()функция возвращает значение ключа, соответствующее сохраненному параметруkКогда звонишь_G()функция, только параметрkпередается в нулевом значении, что указывает на то, что все записиk-vпара ключевых значений удаляется.k-vпары ключей-значений были сохранены постоянно,_G()функция вызвана снова, передавая имя ключа, который был сохранен постоянно в качестве параметраk. Передача нового значения ключа в качестве параметраvОбновлю это.k-vпара ключевых значений.

{@fun/Global/DBExec DBExec}

_D

Преобразует миллисекундные временные отметки илиDateОбъекты для временных строк.

Временная цепь. строка

_D ((() _D (отметка времени) _D ((часовой штамп, fmt)

Миллисекундная временная марка илиDateОбъект. Временная печать ложное Номер, предмет Форматировать строку,JavaScriptформат языка по умолчанию:yyyy-MM-dd hh:mm:ss; Pythonформат языка по умолчанию:%Y-%m-%d %H:%M:%S; C++формат языка по умолчанию:%Y-%m-%d %H:%M:%S- Да. ФМТ ложное строка

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

Получить и распечатать текущую временную строку:

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

Время - 1574993606000, с использованием кода конверсии:

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
}

Форматирование с параметромfmtотличается отJavaScript, Python, иC++языки, как показано в следующих примерах:

Возвращает текущую временную строку без прохождения любых параметров._D()Функция вPythonСтратегия, вы должны знать, что параметры прошли временные отметки второго уровня (миллисекундного уровня временных отметки в JavaScript и C ++ стратегии, где 1 секунда равна 1000 миллисекунд)._D()функция для анализа временной последовательности с читаемой временной меткой в живой торговли, вы должны обратить внимание на часовой пояс и время настройки операционной системы, где расположена программа Docker._D()функция анализирует временную метку в читаемую временную строку в зависимости от времени системы докера.

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

_N

Форматируйте число с плавающей запятой.

Форматированное число с плавающей запятой в соответствии с настройкой точности. Номер

_N() _N(num) _N ((num, точность)

Номер с плавающей запятой, который нужно отформатировать. число неправда Номер Настройка точности форматирования, параметрprecisionявляется целым числом, и параметрprecisionПо умолчанию 4. точность ложное Номер

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

Например,_N(3.1415, 2)удалит значение после3.1415два знака за десятичной запятой и функция возвращает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 слева от запятой на 0, вы можете написать это так:

Параметрprecisionможет быть положительным целым числом, отрицательным целым числом.

{@fun/Trade/exchange.SetPrecision exchange.SetPrecision} - Я не знаю.

_C

Попробуйте заново функцию допустимости ошибок интерфейса.

Возвратное значение функции обратного вызова при ее выполнении. Все типы поддерживаются системой, кромеЛогическое ложное значениеинулевое значение.

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

Параметрpfnявляется функцией ссылки, которая являетсяфункция обратного вызова- Да. пфн неправда Функция Параметры дофункции обратного вызова, может быть более одного параметраarg. Тип и количество параметровargзависит от параметровфункция обратного вызова- Да. арг ложное строка, число, bool, объект, массив, функция, все типы поддерживаются системой, такие как нулевые значения

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

Для ошибочно-толерантных функций без параметров:

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

Для функций с параметрами, которые допускают ошибки:

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

Он также может быть использован для отказоустойчивости пользовательских функций:

В_C()function будет продолжать вызвать указанную функцию, пока она не вернется успешно (функция, на которую ссылается параметрpfnдоходынулевойилиложныйкогда вызовут, перепробует вызватьpfnНапример,_C(exchange.GetTicker). Интервал повторного попытки по умолчанию составляет 3 секунды, вы можете вызвать_CDelay()функция для установки интервала повторных попыток._CDelay(1000)средства для изменения интервала повторных попыток_C()Функция на 1 секунду. Пропускная способность к ошибкам может быть выполнена для, но не ограничивается, следующими функциями:

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()Все могут быть вызваны_C()Функция допустимости неисправностей_C()функция не ограничивается вышеперечисленной функцией допустимости неисправности, параметромpfnявляется ссылкой на функцию, а не вызовом функции. Заметьте, что это_C(exchange.GetTicker), нет_C(exchange.GetTicker()).

_Кросс

Возвращает количество периодов пересечения массиваarr1и массивarr2.

Количество перекрестных периодов массиваarr1и массивarr2- Да. Номер

_Кросс ((arr1, arr2)

Элементы - это массивы типаnumber- Да. Arr1 неправда массив Элементы - это массивы типаnumber- Да. arr2 неправда массив

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

Набор данных может быть смоделирован для проверки функции _Cross ((Arr1, Arr2):

Если возвращение значения_Cross()Если функция является положительным числом, она указывает на период восходящего проникновения, если она является отрицательным числом, она указывает на период нисходящего проникновения, 0 означает то же самое, что текущая цена.Анализ и инструкции по использованию встроенной функции _Кросс.

JSONParse

ФункцияJSONParse()используется для анализаJSON strings.

JSONОбъект. объект

JSONParse ((s)

JSONСтрока. с неправда строка

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

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

Строки JSON с большими значениями можно правильно анализировать, и это будет анализировать большие значения в виде типов строки.JSONParse()функция не поддерживается в системе обратного тестирования.

Логотип