Retorna o número de versão atual do sistema.
Número da versão actual do sistema, como:3.6
- Não.
cordel
Versão (((
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
O número de versão do sistema é o número de versão do programa do docker.
A função de sono, fazendo com que o programa pare por um período de tempo.
Sono (milissegundos)
Omillisecond
O parâmetro é utilizado para definir a duração do sono e o número de milissegundos.
milissegundos
verdade
Número
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");
}
Por exemplo, ao executar oSleep(1000)
Função, o programa irá dormir por 1 segundo.Sleep(0.1)
Suporta um parâmetro mínimo de0.000001
, ou seja, hibernação de nanossegundos, onde 1 nanossegundo é igual a1e-6
milissegundos.
Quando se escreve estratégias noPython
A linguagem, oSleep(millisecond)
A função de intervalo de sondagem deve ser utilizada para operações de tempo de espera.time.sleep(second)
função dePython
É...time
Isto é porque usando otime.sleep(second)
função em uma estratégia faz o programa de estratégia esperar por um período de tempo na verdade quando backtesting (não pulando sobre a série de tempo do sistema de backtesting), por isso faz com que a estratégia para backtest muito lentamente.
Determinar se o ambiente de execução da estratégia é um sistema de backtesting.
A estratégia retorna um valor verdadeiro, por exemplo:true
Quando executado no ambiente do sistema de backtesting, a estratégia retorna um valor falso, por exemplo:false
quando executado num ambiente de negociação em tempo real.
Bool
É Virtual?
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.");
}
}
Determinar se o ambiente em execução atual é um sistema de backtesting, utilizado para ser compatível com a diferença entre backtesting e negociação em tempo real.
Envia um e-mail.
Uma entrega bem-sucedida de e-mail retorna um valor verdadeiro, por exemplo,true
, e uma entrega falhada retorna um valor falso, por exemplo,false
- Não.
Bool
Correio ((smtpServidor, smtpUsuário, smtpPassword, mailTo, título, corpo)
Utilizado para especificar oSMTP
Endereço de serviço do remetente do correio electrónico.
SmtpServer
verdade
cordel
Usado para especificar o endereço de e-mail do remetente.
Nome do usuário
verdade
cordel
OSMTP
palavra-passe para a caixa de correio do remetente do email.
SmtpPassword
verdade
cordel
Usado para especificar o endereço de e-mail do destinatário do e-mail.
mailTo
verdade
cordel
Endereço de email.
Título
verdade
cordel
Corpo de e-mail.
corpo
verdade
cordel
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");
}
OsmtpPassword
Parâmetro define a palavra-passe para oSMTP
serviço, não a senha da caixa de correio.
Ao definir osmtpServer
Parâmetro, se você precisa mudar a porta, você pode adicionar o número da porta diretamente no parâmetrosmtpServer
Por exemplo: QQ mailsmtp.qq.com:587
, disponível para ensaio.
Em caso de erro:unencryped connection
, você precisa modificar osmtpServer
doMail
Função. O formato do parâmetro é:ssl://xxx.com:xxx
, por exemplo, ossl
método deSMTP
para correio QQ:ssl://smtp.qq.com:465
ousmtp://xxx.com:xxx
- Não.
Não funciona no sistema de backtesting.
Não, não, não, não.
Versão assíncrona doMail
function.
OMail_Go
função retorna um objeto simultâneo imediatamente, e você pode usar owait
Um método de que o objeto concorrente para obter o resultado da entrega de correio. uma entrega de correio bem sucedida retorna um valor verdadeiro, por exemplo,true
, e uma entrega falhada retorna um valor falso, por exemplo,false
- Não.
Objeto
Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, título, corpo)
É utilizado para especificar oSMTP
Endereço de serviço do remetente do correio electrónico.
SMTPServer
verdade
cordel
É usado para especificar o endereço de e-mail do remetente do e-mail.
Nome do usuário
verdade
cordel
OSMTP
palavra-passe para a caixa de correio do remetente do email.
SmtpPassword
verdade
cordel
É usado para especificar o endereço de e-mail do destinatário do e-mail.
E-mail para
verdade
cordel
Endereço de email.
Título
verdade
cordel
Corpo do email.
corpo
verdade
cordel
function main() {
var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var ret1 = r1.wait()
var ret2 = r2.wait()
Log("ret1:", ret1)
Log("ret2:", ret2)
}
# Not supported.
// Not supported.
Não funciona no sistema de backtesting.
Não, não, não.
Registros de erros de filtragem.
SetErrorFilter (filtros)
Estringência de expressão regular. filtros verdade cordel
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");
}
Filtrar erros comuns.
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);
}
Filtrar uma mensagem de erro de interface.
Os registros de erros correspondentes a esta expressão regular não serão carregados no sistema de registros. Você pode chamá-lo várias vezes (sem limite no número de vezes) para definir várias condições de filtro. As expressões regulares definidas várias vezes serão acumuladas e entrarão em vigor ao mesmo tempo. Você pode definir uma cadeia vazia para redefinir a expressão regular usada para filtrar registros de erros:SetErrorFilter("")
Os registos filtrados não são mais escritos no arquivo de banco de dados correspondente ao ID de negociação ao vivo no diretório do docker para evitar que os relatórios de erros frequentes inchaçam o arquivo de banco de dados.
Obtenha a identificação do processo de negociação.
Retornar a identificação do processo de negociação em tempo real. cordel
GetPid ((()
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
Recebi a última mensagem de erro.
Última mensagem. cordel
GetLastError (()
function main(){
// Because the order number 123 does not exist, so there will be an error.
exchange.GetOrder("123")
var error = GetLastError()
Log(error)
}
def main():
exchange.GetOrder("123")
error = GetLastError()
Log(error)
void main() {
// Order ID type: TId, so you can't pass in a string, we place an order that doesn't meet the exchange specification to trigger
exchange.GetOrder(exchange.Buy(1, 1));
auto error = GetLastError();
Log(error);
}
Não funciona no sistema de backtesting.
Recebe o comando de interação estratégica.
O formato do comando retornado éControlName:Data
. ControlName
é o nome do controlo, eData
Se o comando interativo não tiver caixas de entrada, caixas suspensas e outros componentes (por exemplo, um comando de botão sem caixas de entrada), então o formato do comando retornado éControlName
, que retorna apenas o nome do controlo.
cordel
Obter Comando ((()
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);
}
}
Detecta o comando de interação e utiliza oLog
Função para emitir o comando de interação quando detectado.
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);
}
}
Por exemplo, o controle interativo estratégia adiciona um controle sem uma caixa de entrada, o controle interativo é chamado:buy
, a informação relativa à descrição do controlo é:buy
, que é um controle de botão. Continue adicionando um controle com uma caixa de entrada. O controle interativo é chamado:sell
e a mensagem de descrição do controlo é:sell
O código de interação é projetado na estratégia para responder aos diferentes controles de interação:
Não funciona no sistema de backtesting.
Obter o valor de Meta escrito ao gerar o código de registro estratégia.
Meta
dados.
cordel
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);
}
}
Exemplo de cenário de aplicação: utilizaçãoMeta
Limitar o montante dos activos geridos pela estratégia.
O cenário de aplicação: necessidade de fazer limites de capital para diferentes locatários estratégicos.Meta
O valor definido para a geração do código de registo não pode exceder 190 caracteres e oGetMeta()
A função só suporta a negociação em tempo real.Meta
) é definido no momento da geração de um código de registo de estratégia, oGetMeta()
Função retorna nulo. Não funciona no sistema de backtesting.
Para primitivoSocket
acesso, apoiotcp
, udp
, tls
, unix
Suporte a 4 protocolos de comunicação populares:mqtt
, nats
, amqp
, kafka
- Suporte para ligação a bases de dados:sqlite3
, mysql
, postgres
, clickhouse
.
ODial()
Uma chamada normal retorna um objeto de conexão que tem três métodos:read
, write
eclose
. Oread
O método é utilizado para ler os dados, owrite
O método é utilizado para enviar dados e oclose
método é utilizado para fechar a ligação.
Oread
O método suporta os seguintes parâmetros:
ws.read()
.ws.read(2000)
Especifica um timeout de dois segundos (2000 milissegundos).-1
significa que a função retorna imediatamente, independentemente da presença ou ausência de mensagens, por exemplo:ws.read(-1)
- Não.
Passando o parâmetro-2
significa que a função retorna imediatamente com ou sem uma mensagem, mas apenas a mensagem mais recente é devolvida e a mensagem tamponada é descartada.ws.read(-2)
.read()
Descrição do buffer de funções:
Os dados recebidos empurrados pelo protocolo WebSocket podem causar acúmulo de dados se o intervalo de tempo entre a estratégiaread()
Os dados são armazenados no buffer, que tem uma estrutura de dados de uma fila com um máximo de 2000.
Scenário | Nenhum parâmetro | Parâmetro: -1 | Parâmetro: -2 | Parâmetro: 2000, em milissegundos |
---|---|---|---|---|
Dados já no buffer | Retorne os dados mais antigos imediatamente | Retorne os dados mais antigos imediatamente | Retorna os dados mais recentes imediatamente | Retorne os dados mais antigos imediatamente |
Não há dados no buffer | Retornar quando bloqueado para dados | Retorne nulo imediatamente | Retorne nulo imediatamente | Esperar 2000 ms, retornar nulo se não houver dados, retornar nulo se houver dados |
A conexão WebSocket é desconectada ou reconectada pelo subjacente | read() função retorna a cadeia vazia, ou seja: |
Objeto
Marque (adressos) Marque (endereço, tempo limite)
Endereço solicitado. Endereço verdade cordel segundos de tempo de espera, tempo de espera Falso Número
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();
}
}
Exemplo de chamada de função 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();
}
Para acessar a interface WebSocket do 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");
}
Acesso à interface do ticker do WebSocket OKX
var ws = null
function main(){
var param = {"sub": "market.btcusdt.detail", "id": "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
while(1){
var ret = ws.read()
Log("ret:", ret)
// Respond to heartbeat packet operations
try {
var jsonRet = JSON.parse(ret)
if(typeof(jsonRet.ping) == "number") {
var strPong = JSON.stringify({"pong" : jsonRet.ping})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
}
} catch(e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("Execute the ws.close() function")
}
import json
ws = None
def main():
global ws
param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
while True:
ret = ws.read()
Log("ret:", ret)
# Respond to heartbeat packet operations
try:
jsonRet = json.loads(ret)
if "ping" in jsonRet and type(jsonRet["ping"]) == int:
strPong = json.dumps({"pong" : jsonRet["ping"]})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
except Exception as e:
Log("e:", e)
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("Execute the ws.close() function")
using namespace std;
void main() {
json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
if(ws.Valid) {
while(true) {
auto ret = ws.read();
Log("ret:", ret);
// Respond to heartbeat packet operations
try
{
auto jsonRet = json::parse(ret);
if(jsonRet["ping"].is_number()) {
json pong = R"({"pong" : 0})"_json;
pong["pong"] = jsonRet["ping"];
auto strPong = pong.dump();
ws.write(strPong);
Log("Respond to ping, send pong:", strPong, "#FF0000");
}
} catch(exception &e)
{
Log("e:", e.what());
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
// ws.close();
Log("Execute the ws.close() function");
}
Acesso à interface do ticker do WebSocket da Huobi:
function getLogin(pAccessKey, pSecretKey, pPassphrase) {
// Signature function for login
var ts = (new Date().getTime() / 1000).toString()
var login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey) // exchange.HMAC has been deprecated and is temporarily supported. Please use the latest exchange.Encode function instead.
}]
}
return login
}
var client_private = null
function main() {
// Because the read function uses a timeout setting, filtering the timeout reports errors that would otherwise be output with redundant errors
SetErrorFilter("timeout")
// Position channel subscription information
var posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
var accessKey = "xxx"
var secretKey = "xxx"
var passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000) // When logging in, you cannot subscribe to private channels immediately, you need to wait for server response
client_private.write(JSON.stringify(posSubscribe))
if (client_private) {
var lastPingTS = new Date().getTime()
while (true) {
var buf = client_private.read(-1)
if (buf) {
Log(buf)
}
// Detect disconnection, reconnect
if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
Log("Disconnection detected, close connection, reconnect")
client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(JSON.stringify(posSubscribe))
}
// Send heartbeat packets
var nowPingTS = new Date().getTime()
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping")
lastPingTS = nowPingTS
}
}
}
}
function onexit() {
var ret = client_private.close()
Log("Close the connection!", ret)
}
import json
import time
def getLogin(pAccessKey, pSecretKey, pPassphrase):
ts = str(time.time())
login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
}]
}
return login
client_private = None
def main():
global client_private
SetErrorFilter("timeout")
posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
accessKey = "xxx"
secretKey = "xxx"
passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
if client_private:
lastPingTS = time.time() * 1000
while True:
buf = client_private.read(-1)
if buf:
Log(buf)
if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
Log("Disconnection detected, close connection, reconnect")
ret = client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
nowPingTS = time.time() * 1000
if nowPingTS - lastPingTS > 10 * 1000:
client_private.write("ping")
lastPingTS = nowPingTS
def onexit():
ret = client_private.close()
Log("Close the connection!", ret)
auto client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
json getLogin(string pAccessKey, string pSecretKey, string pPassphrase) {
auto ts = std::to_string(Unix());
json login = R"({
"op": "login",
"args": [{
"apiKey": "",
"passphrase": "",
"timestamp": "",
"sign": ""
}]
})"_json;
login["args"][0]["apiKey"] = pAccessKey;
login["args"][0]["passphrase"] = pPassphrase;
login["args"][0]["timestamp"] = ts;
login["args"][0]["sign"] = exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey);
return login;
}
void main() {
SetErrorFilter("timeout");
json posSubscribe = R"({
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
})"_json;
auto accessKey = "xxx";
auto secretKey = "xxx";
auto passphrase = "xxx";
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
if (client_private.Valid) {
uint64_t lastPingTS = Unix() * 1000;
while (true) {
auto buf = client_private.read(-1);
if (buf != "") {
Log(buf);
}
if (buf == "") {
if (client_private.write(posSubscribe.dump()) == 0) {
Log("Disconnection detected, close connection, reconnect");
client_private.close();
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
}
}
uint64_t nowPingTS = Unix() * 1000;
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping");
lastPingTS = nowPingTS;
}
}
}
}
void onexit() {
client_private.close();
Log("exit");
}
Para acessar a interface de autenticação do 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
O objeto de conexão devolvido pela função Dial quando se conecta a um banco de dados tem duas funções de método que são exclusivas para ele:
exec(sqlString)
: Usado para executar instruções SQL de uma forma semelhante aoDBExec()
function.fd()
Ofd()
função retorna uma manipulação (por exemplo, a variável manipulação é manipulação) a ser usada por outros fios para reconectar (mesmo que o objeto criado por Dial já tenha sido fechado pela execução doclose()
A função de fechar a ligação) passando a alça para oDial()
função, por exemplo,Dial(handle)
Conexão de reutilização.
O seguinte é um exemplo da função Dial ligando a umsqlite3
database.Detalhes doaddress
Parâmetro, separado pelo|
símbolo após o endereço normal:wss://ws.okx.com:8443/ws/v5/public
Se houver|
caracteres na cadeia de parâmetros, então||
A parte depois disso é algumas configurações de parâmetros de função, e cada parâmetro está conectado com&
A primeira é a dess5
Os parâmetros de substituição e de compressão podem ser definidos em conjunto do seguinte modo:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Funções suportadas pelo parâmetro de endereço da função Dial | Descrição do parâmetro |
---|---|
Parâmetros relacionados com a compressão de dados do protocolo WebSocket: compress=parâmetro valor | compress é o método de compressão, comprimir opções de parâmetros são: gzip_raw, gzip, etc. Se o método gzip não é padrão gzip, você pode usar o método estendido: gzip_raw |
Parâmetros relacionados com a compressão de dados do protocolo WebSocket: mode=valor do parâmetro | modo é o modo de compressão, o parâmetro de modo pode ser duplo, enviar, recv. dual é compressão bidirecional, enviar dados comprimidos, receber dados comprimidos. enviar é enviar dados comprimidos. recv é receber dados comprimidos, descompressão local. |
O protocolo WebSocket define os parâmetros de auto-reconexão relacionados: reconnect=valor do parâmetro | reconnect é se deve definir reconnect, reconnect=true é para habilitar reconnect. O padrão é não reconnect quando este parâmetro não é definido. |
O protocolo WebSocket define os parâmetros de auto-reconexão subjacentes: intervalo=valor do parâmetro | o intervalo é o intervalo de tentativa de reinicialização, em milissegundos, o intervalo=10000 é o intervalo de tentativa de reinicialização de 10 segundos, o padrão é de 1 segundo quando não está definido, ou seja, o intervalo=1000. |
O protocolo WebSocket define os parâmetros relacionados com a reconexão automática subjacente: carga útil=valor do parâmetro | A carga útil é a mensagem de assinatura que precisa ser enviada quando o WebSocket é reconectado, por exemplo: payload=okokok. |
Parâmetros relacionados com calças5 proxy: proxy=valor do parâmetro | proxy é a configuração de proxy ss5, formato de valor do parâmetro: socks5://name:pwd@192.168.0.1:1080, nome é o nome de usuário do servidor ss5, pwd é a senha de login do servidor ss5, 1080 é a porta de serviço ss5. |
ODial()
A função só é suportada para negociação ao vivo.
Ao se conectar a um banco de dados usando a função Dial, a cadeia de conexão é escrita com referência ao projeto de driver de linguagem go para cada banco de dados.
Base de dados suportadas | Projetos de impulso | Corda de ligação | Observações |
---|---|---|---|
Sqlite3 | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=shared&mode=memory | Osqlite3:// Prefixo indica que está a ser utilizado um banco de dados sqlite3, exemplo de chamada:Dial("sqlite3://test1.db") |
mysql | github.com/go-sql-driver/mysql | mysql://username:yourpassword@tcp(localhost:3306)/a sua base de dados?charset=utf8mb4 | – |
Postgres | github.com/lib/pq | postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432 | – |
Cliquehouse | github.com/ClickHouse/clickhouse-go | - Não, não, não, não. | – |
Por favor, note que quando opayload
O conteúdo definido noaddress
Parâmetro contém caracteres=
ou outros caracteres especiais, pode afetar a análise doaddress
Parâmetro doDial
função, como o exemplo a seguir.
Exemplo de chamada de interface privada do 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×tamp=" + 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}}")
}
A seguinte chamada no código funciona bem:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Se você escrever isso diretamente empayload
, não funcionará corretamente, por exemplo:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
Atualmente, apenas o JavaScript suporta o uso domqtt
, nats
, amqp
, ekafka
O código de estratégia da linguagem JavaScript é usado como exemplo para mostrar o uso dos quatro protocolos:mqtt
, nats
, amqp
, ekafka
:
// 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")
}
}
Referência de documentação pormenorizada:Explorando FMZ: Prática do protocolo de comunicação entre as estratégias de negociação ao vivo
Envie um pedido HTTP.
Retorna os dados de resposta da solicitação.JSON
string, ele pode ser analisado peloJSON.parse()
função naJavaScript
A estratégia linguística, e pelajson::parse()
função naC++
Se o depuração for definido como verdadeiro na estrutura de opções, o valor de retorno é um objeto (JSON); se o depuração for definido como falso, o valor de retorno é uma cadeia.
cadeia, objeto
HttpQuery (URL) HttpQuery ((url, opções)
URL de solicitação HTTP. URL do endereço verdade cordel As configurações relacionadas com solicitações HTTP, por exemplo, podem ser estruturadas da seguinte forma:
{
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
impressões digitais.
As configurações suportadas incluem as seguintes opções:
Chrome_:"chrome_103"
, "chrome_104"
, "chrome_105"
, "chrome_106"
, "chrome_107"
, "chrome_108"
, "chrome_109"
, "chrome_110"
, "chrome_111"
, "chrome_112"
, "chrome_117"
- Não.
Safari_:"safari_15_6_1"
, "safari_16_0"
, "safari_ipad_15_6"
, "safari_ios_15_5"
, "safari_ios_15_6"
, "safari_ios_16_0"
- Não.
Firefox_:"firefox_102"
, "firefox_104"
, "firefox_105"
, "firefox_106"
, "firefox_108"
, "firefox_110"
, "firefox_117"
- Não.
Opera_:"opera_89"
, "opera_90"
, "opera_91"
- Não.
- Não, não, não."zalando_android_mobile"
, "zalando_ios_mobile"
- Não.
- Não."nike_ios_mobile"
, "nike_android_mobile"
- Não.
arranha-céus:"cloudscraper"
- Não.
- Sim, sim."mms_ios"
- Não.
mesh_:"mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
- Não.
Confirmado:"confirmed_ios"
, "confirmed_android"
- Não.
Está bem."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, oHttpQuery
chamada de função retorna a mensagem de resposta completa.false
, apenas os dados doBody
da mensagem de resposta é devolvida.profile
campo pode ser deixado de fora.opções Falso Objeto
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);
}
Um exemplo de acesso à interface API de ticker pública 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/");
}
A função HttpQuery usa configurações de proxy.
OHttpQuery()
Função só suportaJavaScript
, C++
linguagem,Python
A linguagem pode utilizar ourllib
A biblioteca para enviar solicitações HTTP diretamente.HttpQuery()
O sistema é utilizado principalmente para aceder às interfaces da troca que não requerem uma assinatura, como as interfaces públicas como as informações do ticker.HttpQuery()
O sistema de backtesting pode ser utilizado para enviar solicitações (apenasGET
O backtesting limita-se a utilizar 20 visitas a diferentesURLs
, eHttpQuery()
As visitas cacharão os dados.URL
A segunda vez em que se acede aoHttpQuery()
A função retorna os dados em cache e não ocorrem mais solicitações reais de rede.
Não, não, não, não.
Envia uma solicitação HTTP, uma versão assíncrona doHttpQuery
function.
OHttpQuery_Go()
função imediatamente retorna um objeto concorrente que pode ser usado para obter o resultado de uma solicitação HTTP usando owait
Método deJSON.parse()
função pode ser usado para analisar oJSON.parse()
função naJavaScript
estratégia linguística.
Objeto
HttpQuery_Go (URL) HttpQuery_Go ((url, opções)
URL de solicitação HTTP. URL do endereço verdade cordel As configurações relacionadas com solicitações HTTP, por exemplo, podem ser estruturadas da seguinte forma:
{
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.true
, esteHttpQuery_Go
chamada de função retorna a mensagem de resposta completa.false
, apenas os dados doBody
da mensagem de resposta é devolvida.profile
campo pode ser deixado de fora.opções Falso Objeto
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
Acesso assíncrono à interface pública da bolsa para dados agregados de ticker.
OHttpQuery_Go()
Função só suportaJavaScript
, oPython
A linguagem pode ser utilizada com ourllib
A biblioteca para enviar solicitações HTTP diretamente.HttpQuery_Go()
O sistema de transferência de dados é utilizado principalmente para aceder a interfaces que não requerem uma assinatura na bolsa, tais como interfaces públicas como informações de ticker.HttpQuery_Go
função não é suportada no sistema de backtesting.
Não, não, não, não.
Esta função codifica os dados de acordo com os parâmetros transmitidos.
OEncode
Função que retorna os dados após codificação e criptografia.
cordel
Encode ((algo, inputFormat, outputFormat, dados) Encode ((algo, inputFormat, outputFormat, dados, chaveFormat, chave)
O parâmetroalgo
é o algoritmo utilizado no cálculo da codificação.raw
(não é utilizado algoritmo), o"sinal", algo
também suporta: algo
também suporta: algo
pode ser escrito como ed25519.seed
Calculo.
algo
verdade
cordel
Utilizado para especificar o formato de dados dodata
Parâmetro.inputFormat
O parâmetro pode ser definido como um dos seguintes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, e outputFormat
O parâmetro pode ser definido como um dos seguintes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, e data
são os dados a processar.
dados
verdade
cordel
Utilizado para especificar o formato de dados dokey
Parâmetro.key
O parâmetro pode ser definido como um dos seguintes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, e key
é a chave secreta usada paraHMAC
O parâmetrokey
é exigido quando o parâmetroalgo
está definido emsign
ousignTx
. Okey
Parâmetro não utilizado paraHMAC
criptografia quando oalgo
O parâmetro é definido como
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
}
Exemplo de chamada de função 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);
}
O parâmetroalgo
também suporta:
OEncode()
A função só é suportada para negociação ao vivo.key
ekeyFormat
Os parâmetros não são transmitidos, entãokey
Não se utiliza encriptação.
Obtenha o carimbo de tempo do momento atual.
OUnixNano()
A função retorna o selo de tempo do nanossegundo.
Número
UnixNano ((()
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Se precisar de marcas de tempo de milissegundos, pode usar o seguinte código:
Não, não, não.
Obtenha o carimbo do momento atual no segundo nível.
Devolve a marca de tempo de segundo nível. Número
Unix ((()
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
Não, não, não, não.
Obter as informações do sistema do dispositivo onde o docker está localizado.
Informações do sistema. cordel
GetOS ((()
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Por exemplo, uma chamada para oGetOS()
função para um docker em execução noMac OSsistema operacional pode retornar:darwin/amd64
Porque os computadores da Apple têm várias arquiteturas de hardware.darwin
é o nome doMac OS system.
Computa o hash MD5 do parâmetrodata
.
Valor hash MD5. cordel
MD5 (dados)
Os dados que requerem cálculo MD5. dados verdade cordel
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
Chamando oMD5("hello world")
função, o valor de retorno é:5eb63bbbe01eeed093cb22bb8f5acdc3
.
Não, não, não, não.
Funções de interface de banco de dados.
Um objeto que contém o resultado da execução de umQuadradodeclaração, por exemplo:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
Objeto
DBExec ((sql)
Quadradocadeia de instruções. Quadrado verdade cordel
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;"));
}
Suporte de base de dados em memória, paraDBExec
Parâmetros funcionais, se:Quadradodeclaração começa com:
É adequado para operações de banco de dados que não requerem salvação persistente, por exemplo:
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);
}
Crie uma mesa.
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));
}
Adicionar, excluir, verificar e alterar os registos na tabela.
A funçãoDBExec()
Pode operar o banco de dados de negociação ao vivo (base de dados SQLite) através da passagem de parâmetros.SQLiteO sistema reservou tabelas na base de dados de negociação ao vivo:kvdb
, cfg
, log
, profit
, chart
, não operar nessas mesas.TransaçõesO sistema de gestão de dados não é suportado e não é recomendado executar tais operações, que podem causar conflitos no sistema.DBExec()
A função só é suportada para negociação ao vivo.
Não, não, não.
Crie um UUID.
UUID de 32 bits. cordel
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);
}
OUUID()
A função suporta apenas negociação ao vivo.
Ouça para os eventos, ele retorna quando há qualquerWebSocket
dados legíveis ou tarefas simultâneas, tais como:exchange.Go()
, HttpQuery_Go()
, etc. são concluídas.
Se o objeto devolvido não for um valor nulo, oEvent
O conteúdo do retorno é o tipo de desencadeador de evento.
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
Objeto
EventLoop ((() EventLoop (Timeout)
O parâmetrotimeout
é a definição de timeout, em milissegundos.timeout
espera que um evento ocorra antes de retornar se for definido como 0. Se for maior que 0, define o evento para esperar por um timeout e retorna o evento mais recente imediatamente se for menor que 0.
tempo de espera
Falso
Número
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);
}
A primeira chamada para oEventLoop()
função no código inicializa o mecanismo para o evento ouvido, e se o primeiroEventLoop()
O sistema subjacente envolve uma estrutura de fila que cacheia um máximo de 500 chamadas de evento.EventLoop()
função não é chamada a tempo de tirá-los durante a execução do programa, mais tarde eventos callbacks fora do 500 cache serão perdidos.EventLoop()
função não afetam a fila de cache do sistema WebSocket subjacente ou os caches de funções simultâneas, tais comoexchange.Go()
Para estes caches, ainda é necessário usar os respectivos métodos para recuperar os dados.EventLoop()
função para dados que foram recuperados antes doEventLoop()
A função retorna os resultados.EventLoop()
A estratégia é baseada em eventos, que são gerados por eventos, que são gerados por eventos, que são gerados por eventos.EventLoop()
função retorna um evento, apenas atravessa todas as fontes de dados.exchange.Go()
tentam obter dados.EventLoop()
A função suporta apenas negociação ao vivo.
Ouça os eventos no thread principal quando chamado da função principalmain()
. nas estratégias escritas noJavaScript
A linguagem, othreading.Thread()
função cria um thread, que também pode ser chamado na função de execução do thread
{@fun/Global/Dial Dial}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
O__Serve
A função é usada para criar o serviço HTTP, o serviço TCP e o serviço Websocket (baseado no protocolo HTTP).
Retorna uma cadeia que registra o endereço IP e a porta do serviço criado.127.0.0.1:8088
, [::]:8089
.
cordel
__Serve ((serveURI, manipulador) __Serve ((serveURI, manipulador,...args)
OserveURI
O parâmetro é usado para configurar o protocolo, endereço IP, porta e outras configurações da ligação do serviço, tais comohttp://0.0.0.0:8088?gzip=true
, isto é,http://:8088?gzip=true
.
serveURI
definição de parâmetros, tais comotcp://127.0.0.1:6666?tls=true
; pode adicionar certificados e chaves privadas, tais comotls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
configurações de parâmetros, tais como:http://127.0.0.1:6666?gzip=true
; pode definir as configurações de compressão:gzip=true
- Não.
OserveURI
Parâmetro é usado para Https, tais comohttps://127.0.0.1:6666?tls=true&gzip=true
Pode acrescentarcert_pem
ecert_key_pem
Parâmetros para carregar o certificado.ServirURI
verdade
cordel
Ohandler
O parâmetro é usado para passar na função de processamento de roteamento (protocolo HTTP), função de processamento de mensagens (protocolo TCP) e função de processamento de fluxo (Websocket).
A função de chamada de volta transmitida pelo parâmetrohandler
Pode definir vários parâmetros, o primeiro parâmetro é o objeto ctx (objeto de contexto).
manipulador
verdade
função
O parâmetro real da função callback passado como o parâmetrohandler
Pode haver vários parâmetrosarg
, por exemplo:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Os parâmetros1
, 2
, 3
Passado em quando chamar o__Serve()
função correspondem aos parâmetrosa
, b
, c
Passado na função de chamada de volta.
arg Falso cadeia, número, bool, objeto, matriz, função, valor nulo e outros tipos suportados pelo sistema
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
Websocket
Você pode definir um ramo de roteamento no caminho e projetar o código de implementação paraWebsocket
Pode consultar o código de exemplo nesta secção.A função de chamada de volta transmitida pelo parâmetrohandler
recebe umctx
Parâmetro.ctx
Parâmetro é um objeto de contexto utilizado para obter e escrever dados, com os seguintes métodos:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, e a função de processamento de chamada de retorno transmitida pelo parâmetrohandler
retorno"123"
Quando?ctx.query("num")
é chamado.User-Agent
nos cabeçalhos do presente pedido:ctx.header("User-Agent")
.GET
, POST
, etc.ctx
objeto de contexto para o protocolo Websocket; devolvendo um valor booleano (verdadeiro) se a mudança for bem-sucedida e um valor booleano (falso) se falhar.read
método não é suportado no protocolo HTTP comum. Você pode especificar o parâmetro timeouttimeout_ms
em milissegundos.JSON.stringify()
para codificar o objeto JSON em uma cadeia de caracteres e, em seguida, escrevê-lo.WebSocket
protocolo, você pode usar este método para passar a cadeia codificada para o cliente.{@fun/Global/HttpQuery HttpQuery}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
A estrutura de dados é uma tabela KV que é salvada permanentemente no arquivo de banco de dados local do docker.
Dados de valores-chave salvos de forma persistentek-v
pares de chaves e valores.
cadeia, número, bool, objeto, matriz, valor nulo
_G() _G(k) _G(k, v)
O parâmetrok
é o nome da chave no par chave-valor guardado e não é sensível a minúsculas e minúsculas.
k
Falso
string, valor nulo
O parâmetrov
é o valor chave no par chave-valor salvo, que pode ser qualquer dado que possa serJSON
serializado.
v
Falso
cadeia, número, bool, objeto, matriz, valor nulo
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();
}
Uma base de dados separada para cada negociação em tempo real, os dados salvos pelo_G()
A função estará sempre lá se a estratégia for reiniciada ou o docker parar de funcionar._G()
Quando se utiliza o_G()
Função para persistir os dados salvos, deve ser usado razoavelmente de acordo com a memória e espaço no disco rígido do dispositivo de hardware, e não deve ser abusado.
Ao ligar para o_G()
A função é executada em uma negociação ao vivo e não são passados parâmetros, o_G()
função retorna oId
O número de transacções em tempo real._G()
função, o parâmetrov
é passado como nulo para indicar a exclusão dok-v
Quando se chama o_G()
função, apenas o parâmetrok
é passado na cadeia, e o_G()
função retorna o valor da chave correspondente ao parâmetro guardadok
. Ao ligar para o_G()
função, apenas o parâmetrok
é passado em um valor nulo, indicando que todos os registos dok-v
Quando o par de chaves-valores é excluído.k-v
Os pares chave-valor foram salvos persistentemente, o_G()
função é chamada novamente, passando no nome da chave que foi salvada persistentemente como parâmetrok
. Passando o novo valor da chave como parâmetrov
Vou atualizar isso.k-v
Pares chave-valor.
Não, não, não, não.
Converte marcas de tempo de milissegundos ouDate
Objetos para cordas de tempo.
Uma cadeia de tempo. cordel
_D() _D (horário) _D (horário, fmt)
Marca de tempo de milissegundos ouDate
Objeto.
Marca de data e hora
Falso
Número, objeto
Formatar string,JavaScript
formato padrão da língua:yyyy-MM-dd hh:mm:ss
; Python
formato padrão da língua:%Y-%m-%d %H:%M:%S
; C++
formato padrão da língua:%Y-%m-%d %H:%M:%S
- Não.
fmt
Falso
cordel
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Obter e imprimir a cadeia de tempo atual:
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));
}
O carimbo de data e hora é 1574993606000, utilizando a conversão de código:
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
}
Formatação com o parâmetrofmt
é diferente paraJavaScript
, Python
, eC++
línguas, conforme indicado nos seguintes exemplos:
Retorna a cadeia de tempo atual sem passar quaisquer parâmetros._D()
função naPython
estratégia, você precisa estar ciente de que os parâmetros passados são carimbos de tempo de segundo nível (carimbos de tempo de nível de milissegundos nas estratégias JavaScript e C ++, onde 1 segundo é igual a 1000 milissegundos)._D()
Função para analisar uma cadeia de tempo com uma marca de tempo legível na negociação ao vivo, você precisa prestar atenção ao fuso horário e configuração de hora do sistema operacional onde o programa docker está localizado._D()
A função analisa um carimbo de tempo em uma cadeia de tempo legível dependendo do tempo do sistema docker.
Não, não, não, não.
Formatar um número com vírgula flutuante.
O número de vírgula flutuante formatado de acordo com a definição de precisão. Número
_N() _N (número) _N (número, precisão)
O número de vírgula flutuante que precisa ser formatado.
Número
verdade
Número
A definição de precisão para a formatação, o parâmetroprecision
é um inteiro, e o parâmetroprecision
padrões para 4.
precisão
Falso
Número
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);
}
Por exemplo,_N(3.1415, 2)
eliminará o valor após3.1415
duas casas decimais e a função retorna3.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);
}
Se você precisa mudar todos os dígitos N à esquerda do ponto decimal para 0, você pode escrever assim:
O parâmetroprecision
Pode ser um número inteiro positivo, negativo inteiro.
{@fun/Trade/exchange.SetPrecision exchange.SetPrecision}
Tente novamente a função de tolerância a falhas da interface.
Valor de retorno da função de chamada de retorno quando executada. Todos os tipos são suportados pelo sistema excetovalor lógico falsoevalor nulo.
_C (((pfn) - Não, não, não.
O parâmetropfn
é uma referência de função, que é umaFunção de recallback- Não.
pfn
verdade
função
Parâmetros paraFunções de recallback, pode haver mais de um parâmetroarg
Tipo e número de parâmetrosarg
Depende dos parâmetros doFunção de recallback- Não.
arg
Falso
string, number, bool, object, array, function, todos os tipos são suportados pelo sistema, como valores nulos
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);
}
Para funções tolerantes a erros sem parâmetros:
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);
}
Para funções com parâmetros tolerantes a erros:
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
Também pode ser usado para tolerância a falhas de funções personalizadas:
O_C()
função continuará a chamar a função especificada até que retorne com sucesso (a função referenciada pelo parâmetropfn
retornozeroouFalsoQuando for chamado, tentará ligar novamente.pfn
Por exemplo:_C(exchange.GetTicker)
. O intervalo de tentativa de reinicialização padrão é de 3 segundos, você pode chamar o_CDelay()
função para definir o intervalo de reatendimento._CDelay(1000)
A utilização de um dispositivo de ensaio para alterar o intervalo de ensaio_C()
Função para 1 segundo.
A tolerância de falhas pode ser feita para, mas não se limita a, as seguintes funções:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Todos podem ser chamados pelo_C()
A função de tolerância a falhas._C()
a função não é limitada à tolerância de falha da função acima listada, o parâmetropfn
é uma referência de função em vez de uma chamada de função.
Observe que é_C(exchange.GetTicker)
, não_C(exchange.GetTicker())
.Retorna o número de períodos de intersecção da matrizarr1
e a matrizarr2
.
Número de períodos transversais da matrizarr1
e a matrizarr2
- Não.
Número
_Cross ((arr1, arr2)
Os elementos são matrizes de tiponumber
- Não.
arr1
verdade
matriz
Os elementos são matrizes de tiponumber
- Não.
arr2
verdade
matriz
// 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));
}
Um conjunto de dados pode ser simulado para testar a função _Cross ((Arr1, Arr2):
Se o valor de retorno do_Cross()
Se a função é um número positivo, indica o período de penetração ascendente, se é um número negativo, indica o período de penetração descendente, 0 significa o mesmo que o preço atual.Análise e instruções de utilização sobre a função integrada.
A funçãoJSONParse()
é usado para analisarJSON
strings.
JSON
Objeto.
Objeto
JSONParse (s)
JSON
A corda.
s
verdade
cordel
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.
}
As cadeias de caracteres JSON com grandes valores podem ser analisadas corretamente, e ele irá analisar grandes valores como tipos de cadeia.JSONParse()
função não é suportada no sistema de backtest.