Devuelve el número de versión actual del sistema.
Número de versión del sistema actual, por ejemplo:3.6
- ¿ Por qué?
la cuerda
Versión
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
El número de versión del sistema es el número de versión del programa docker.
La función de sueño, haciendo que el programa se detenga por un período de tiempo.
El sueño (millisegundo)
Elmillisecond
Parámetro utilizado para establecer la duración del sueño y el número de milisegundos.
milisegundos
verdadero
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 ejemplo, al ejecutar elSleep(1000)
Función, el programa permanecerá en reposo durante 1 segundo.Sleep(0.1)
Apoya un parámetro mínimo de0.000001
, es decir, hibernación de nanosegundos, donde 1 nanosegundo es igual a1e-6
milisegundos.
Cuando se escriben estrategias en elPython
La lenguaSleep(millisecond)
No se recomienda el uso de la función de intervalo de votación, las operaciones de tiempo de espera.time.sleep(second)
Función dePython
¿ Qué?time
Esto se debe a que el uso de latime.sleep(second)
función en una estrategia hace que el programa de estrategia espere por un período de tiempo en realidad cuando backtesting (no saltando en la serie de tiempo del sistema de backtesting), por lo que hace que la estrategia para backtesting muy lentamente.
Determinar si el entorno de ejecución de la estrategia es un sistema de backtesting.
La estrategia devuelve un valor verdadero, por ejemplo:true
La estrategia devuelve un valor falso, por ejemplo:false
cuando se ejecuta en un entorno de negociación en vivo.
- ¿ Qué?
¿Es 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 si el entorno de funcionamiento actual es un sistema de backtesting, que se utiliza para ser compatible con la diferencia entre backtesting y trading en vivo.
Envía un correo electrónico.
Una entrega de correo electrónico exitosa devuelve un valor verdadero, por ejemplo,true
, y una entrega fallida devuelve un valor falso, por ejemplo,false
- ¿ Por qué?
- ¿ Qué?
Correo ((smtpServidor, smtpNombre de usuario, smtpPalabra de seguridad, mailTo, título, cuerpo)
Se utiliza para especificar elSMTP
dirección de servicio del remitente del correo electrónico.
Es un servidor.
verdadero
la cuerda
Se utiliza para especificar la dirección de correo electrónico del remitente.
Nombre de usuario
verdadero
la cuerda
ElSMTP
contraseña para el buzón del remitente.
¿ Qué pasa?
verdadero
la cuerda
Se utiliza para especificar la dirección de correo electrónico del destinatario.
Envío de correo
verdadero
la cuerda
Título de correo electrónico.
Título
verdadero
la cuerda
El cuerpo del correo electrónico.
cuerpo
verdadero
la cuerda
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");
}
ElsmtpPassword
Parámetro establece la contraseña para elSMTP
servicio, no la contraseña del buzón.
Al ajustar elsmtpServer
Parámetro, si necesita cambiar el puerto, puede añadir el número de puerto directamente en el parámetrosmtpServer
Por ejemplo: correo QQsmtp.qq.com:587
, que está disponible para su ensayo.
En caso de error:unencryped connection
, usted necesita para modificar elsmtpServer
de lasMail
El formato del parámetro es:ssl://xxx.com:xxx
, por ejemplo, elssl
método deSMTP
para el correo QQ:ssl://smtp.qq.com:465
o biensmtp://xxx.com:xxx
- ¿ Por qué?
No funciona en el sistema de backtesting.
¿Por qué no lo haces?
Versión asíncrona delMail
function.
ElMail_Go
función devuelve un objeto concurrente inmediatamente, y se puede utilizar elwait
Un correo entregado con éxito devuelve un valor verdadero, por ejemplo,true
, y una entrega fallida devuelve un valor falso, por ejemplo,false
- ¿ Por qué?
Objeto
Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, título, cuerpo)
Se utiliza para especificar elSMTP
dirección de servicio del remitente del correo electrónico.
Es un servidor
verdadero
la cuerda
Se utiliza para especificar la dirección de correo electrónico del remitente.
Nombre de usuario
verdadero
la cuerda
ElSMTP
contraseña para el buzón del remitente.
- ¿ Qué pasa?
verdadero
la cuerda
Se utiliza para especificar la dirección de correo electrónico del destinatario del correo electrónico.
Envío de correo
verdadero
la cuerda
Título de correo electrónico.
Título
verdadero
la cuerda
Corpo del correo electrónico.
cuerpo
verdadero
la cuerda
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.
No funciona en el sistema de backtesting.
¿Por qué no lo haces?
Registros de errores de filtro.
ConfigurarErrorFilter (filtros)
Una cadena de expresiones regulares. filtros verdadero la cuerda
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");
}
Filtración de errores comunes.
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 un mensaje de error de interfaz.
Los registros de errores que coincidan con esta expresión regular no se cargarán en el sistema de registros. Puede llamarlo varias veces (sin límite en el número de veces) para establecer varias condiciones de filtro. Las expresiones regulares establecidas varias veces se acumularán y entrarán en vigencia al mismo tiempo. Puede establecer una cadena vacía para restablecer la expresión regular utilizada para filtrar los registros de errores:SetErrorFilter("")
. Los registros filtrados ya no se escriben en el archivo de base de datos correspondiente a la ID de comercio en vivo en el directorio docker para evitar que los informes de errores frecuentes se hinchen en el archivo de base de datos.
Obtener el proceso de comercio en vivo ID.
Retorno de la identificación del proceso de negociación en vivo. la cuerda
¿ Qué te parece?
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
Recibe el último mensaje de error.
Último mensaje de error. la cuerda
Obtenga el último error
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);
}
No funciona en el sistema de backtesting.
Obtiene el comando de interacción estratégica.
El formato del comando devuelto esControlName:Data
. ControlName
es el nombre del control, yData
Si el control interactivo no tiene cajas de entrada, cajas desplegables y otros componentes (por ejemplo, un control de botón sin cajas de entrada), entonces el formato de comando devuelto esControlName
, que devuelve sólo el nombre del control.
la cuerda
Obtener el 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 el comando de interacción y utiliza elLog
Función para emitir el comando de interacción cuando se detecta.
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 ejemplo, el control interactivo de estrategia agrega un control sin un cuadro de entrada, el control interactivo se llama:buy
, la información de descripción del control es:buy
, que es un control de botón. Continúe añadiendo un control con un cuadro de entrada. El control interactivo se llama:sell
y el mensaje de descripción del control es:sell
, que es un control interactivo que es una combinación de un botón y un cuadro de entrada.
No funciona en el sistema de backtesting.
Obtener el valor de Meta escrito al generar el código de registro de la estrategia.
Meta
los datos.
la cuerda
Obtener Meta()
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);
}
}
Ejemplo de escenario de aplicación: usoMeta
limitar el importe de los activos gestionados por la estrategia.
Escenario de aplicación: necesidad de hacer límites de capital para los diferentes arrendatarios de estrategia.Meta
el valor fijado al generar el código de registro no podrá exceder de 190 caracteres, yGetMeta()
Si no hay metadatos (Meta
) se establece al generar un código de registro de la estrategia, el código de registro de la estrategiaGetMeta()
No funciona en el sistema de backtesting.
Para el primitivoSocket
acceso, apoyotcp
, udp
, tls
, unix
Soporte para 4 protocolos de comunicación populares:mqtt
, nats
, amqp
, kafka
Apoyo para conectar a bases de datos:sqlite3
, mysql
, postgres
, clickhouse
.
ElDial()
Una llamada normal devuelve un objeto de conexión que tiene tres métodos:read
, write
yclose
El.read
El método se utiliza para leer los datos, elwrite
El método se utiliza para enviar datos y elclose
El método se utiliza para cerrar la conexión.
Elread
el método admite los siguientes parámetros:
ws.read()
.ws.read(2000)
especifica un tiempo de espera de dos segundos (2000 milisegundos).-1
significa que la función devuelve inmediatamente, independientemente de la presencia o ausencia de mensajes, por ejemplo:ws.read(-1)
- ¿ Por qué?
Pasando el parámetro-2
significa que la función devuelve inmediatamente con o sin un mensaje, pero sólo el último mensaje se devuelve, y el mensaje tamponado se descarta.ws.read(-2)
.read()
Descripción del búfer de función:
Los datos entrantes empujados por el protocolo WebSocket pueden causar acumulación de datos si el intervalo de tiempo entre la estrategiaread()
Estos datos se almacenan en el búfer, que tiene una estructura de datos de una cola con un máximo de 2000.
Escenario | No hay parámetro | Parámetro: -1 | Parámetro: -2 | Parámetro: 2000, en milisegundos |
---|---|---|---|---|
Datos ya en el búfer | Devuelva los datos más antiguos inmediatamente | Devuelva los datos más antiguos inmediatamente | Devuelva los últimos datos inmediatamente. | Devuelva los datos más antiguos inmediatamente |
No hay datos en el búfer | Regresar cuando se bloquea a los datos | Devuelva nulo inmediatamente | Devuelva nulo inmediatamente | Espera 2000 ms, devuelve nulo si no hay datos, devuelve nulo si hay datos |
La conexión WebSocket se desconecta o se vuelve a conectar por el subyacente | read() devuelve la cadena vacía, es decir: |
objetos
Número de teléfono y dirección Número de teléfono (dirección, tiempo límite)
Solicita la dirección. Dirección verdadero la cuerda segundos de tiempo de espera, tiempo de espera falsos 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();
}
}
Ejemplo de llamada de la función 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 acceder a la interfaz WebSocket de 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");
}
Acceso a la interfaz del ticker de WebSocket de 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");
}
Acceso a la interfaz de ticker de WebSocket de 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 acceder a la interfaz de autenticación de WebSocket de 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
El objeto de conexión devuelto por la función Dial al conectarse a una base de datos tiene dos funciones de método que son únicas para él:
exec(sqlString)
: Se utiliza para ejecutar instrucciones SQL de una manera similar a laDBExec()
function.fd()
Elfd()
función devuelve un mango (por ejemplo, la variable mango es mango) para ser utilizado por otros hilos para reconectar (incluso si el objeto creado por Dial ya ha sido cerrado por la ejecución de laclose()
La función de cierre de la conexión) mediante el paso de la manija en elDial()
función, por ejemplo,Dial(handle)
Conexión de reutilización.
El siguiente es un ejemplo de la función Dial que se conecta a unsqlite3
database.Detalles de laaddress
Parámetro, separado por el|
símbolo después de la dirección normal:wss://ws.okx.com:8443/ws/v5/public
Si hay|
caracteres en la cadena de parámetros, entonces||
La parte después de eso es algunas configuraciones de parámetros de función, y cada parámetro está conectado con&
Por ejemplo, elss5
Los parámetros de sustitución y compresión se pueden establecer de la siguiente manera:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Funciones soportadas por el parámetro de dirección de la función Dial | Descripción del parámetro |
---|---|
Parámetros relacionados con la compresión de datos del protocolo WebSocket: compress=valor del parámetro | comprimir es el método de compresión, las opciones de parámetros comprimir son: gzip_raw, gzip, etc. Si el método gzip no es gzip estándar, se puede utilizar el método extendido: gzip_raw |
Parámetros relacionados con la compresión de datos del protocolo WebSocket: modo=valor del parámetro | el modo es el modo de compresión, el parámetro de modo puede ser dual, enviar, recv. dual es compresión bidireccional, enviar datos comprimidos, recibir datos comprimidos. enviar es enviar datos comprimidos. recv es recibir datos comprimidos, descompresión local. |
El protocolo WebSocket establece los parámetros relacionados con la auto-reconexión subyacente: reconnect=valor del parámetro | reconnect es si se debe configurar reconnect, reconnect=true es para habilitar reconnect. |
El protocolo WebSocket establece los parámetros subyacentes relacionados con la reconexión automática: intervalo=valor del parámetro | el intervalo es el intervalo de reintentos, en milisegundos, el intervalo=10000 es el intervalo de reintentos de 10 segundos, el valor predeterminado es 1 segundo cuando no está establecido, es decir, el intervalo=1000. |
El protocolo WebSocket establece los parámetros subyacentes relacionados con la reconexión automática: carga útil=valor del parámetro | carga útil es el mensaje de suscripción que debe enviarse cuando se vuelve a conectar el WebSocket, por ejemplo: carga útil=okokok. |
Parámetros relacionados con los calcetines5 proxy: proxy=valor del parámetro | Proxy es el ajuste de proxy ss5, formato de valor del parámetro: socks5://name:pwd@192.168.0.1:1080, el nombre es el nombre de usuario del servidor ss5, pwd es la contraseña de inicio de sesión del servidor ss5, 1080 es el puerto de servicio ss5. |
ElDial()
La función solo es compatible con el comercio en vivo.
Al conectarse a una base de datos utilizando la función Dial, la cadena de conexión se escribe con referencia al proyecto de controlador de lenguaje go para cada base de datos.
Bases de datos soportadas | Proyectos impulsores | Cuadrícula de conexión | Las observaciones |
---|---|---|---|
el mismo | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=compartido y modo=memoria | Elsqlite3:// Prefijo indica que se está utilizando una base de datos sqlite3, ejemplo de llamada:Dial("sqlite3://test1.db") |
¿ Qué quieres decir con eso? | github.com/go-sql-driver/mysql | mysql://nombre de usuario:su contraseña@tcp(localhost:3306) / tu base de datos? | – |
las plantas herbáceas | github.com/lib/pq | el nombre de la base de datos sslmode=disable password=yourpassword host=localhost port=5432 | – |
La casa de click | github.com/ClickHouse/clickhouse-go | clickhouse://tcp://host:9000?nombre de usuario=nombre de usuario& contraseña=tu contraseña& base de datos=youdatabase | – |
Por favor, tenga en cuenta que cuando elpayload
contenido establecido en eladdress
Parámetro contiene caracteres=
o otros caracteres especiales, puede afectar al análisis de laaddress
Parámetro delDial
Función, como el siguiente ejemplo.
Ejemplo de llamada de interfaz privada del websocket de 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}}")
}
La siguiente llamada en el código funciona bien:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Si lo escribe directamente enpayload
, no funcionará correctamente, por ejemplo:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
Actualmente, sólo JavaScript admite el uso de lamqtt
, nats
, amqp
, ykafka
El código de estrategia del lenguaje JavaScript se utiliza como ejemplo para mostrar el uso de los cuatro protocolos:mqtt
, nats
, amqp
, ykafka
:
// 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")
}
}
Referencia de la documentación detallada:Explorando FMZ: Práctica del protocolo de comunicación entre las estrategias de negociación en vivo
Envía una solicitud Http.
Devuelve los datos de respuesta de la solicitud.JSON
string, puede ser analizado por elJSON.parse()
La función en elJavaScript
La estrategia lingüística, y por eljson::parse()
La función en elC++
Si el depuración está configurado en true en la estructura de opciones, el valor de retorno es un objeto (JSON); si el depuración está configurado en false, el valor de retorno es una cadena.
cadena, objeto
HttpQuery ((url) HttpQuery ((url, opciones)
URL de solicitud de HTTP. - ¿ Qué pasa? verdadero la cuerda Por ejemplo, las configuraciones relacionadas con las solicitudes HTTP pueden estructurarse de la siguiente manera:
{
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
Las huellas.
Los ajustes admitidos incluyen las siguientes opciones:
¿ Por qué no?"chrome_103"
, "chrome_104"
, "chrome_105"
, "chrome_106"
, "chrome_107"
, "chrome_108"
, "chrome_109"
, "chrome_110"
, "chrome_111"
, "chrome_112"
, "chrome_117"
- ¿ Por qué?
¿Qué quieres decir?"safari_15_6_1"
, "safari_16_0"
, "safari_ipad_15_6"
, "safari_ios_15_5"
, "safari_ios_15_6"
, "safari_ios_16_0"
- ¿ Por qué?
¿ Qué haces?"firefox_102"
, "firefox_104"
, "firefox_105"
, "firefox_106"
, "firefox_108"
, "firefox_110"
, "firefox_117"
- ¿ Por qué?
¿ Qué quieres decir?"opera_89"
, "opera_90"
, "opera_91"
- ¿ Por qué?
¿ Qué haces?"zalando_android_mobile"
, "zalando_ios_mobile"
- ¿ Por qué?
No lo sé."nike_ios_mobile"
, "nike_android_mobile"
- ¿ Por qué?
rascacielos:"cloudscraper"
- ¿ Por qué?
¿ Qué es eso?"mms_ios"
- ¿ Por qué?
- ¿ Por qué no?"mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
- ¿ Por qué?
Confirmado"confirmed_ios"
, "confirmed_android"
- ¿ Por qué?
Está bien."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, elHttpQuery
La llamada de la función devuelve el mensaje de respuesta completo.false
, sólo los datos en elBody
del mensaje de respuesta se devuelve.profile
el campo puede ser dejado fuera.opciones falsos 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);
}
Un ejemplo de acceso a la interfaz 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/");
}
La función HttpQuery utiliza la configuración de proxy.
ElHttpQuery()
Función sólo soportaJavaScript
, C++
el lenguaje,Python
El lenguaje puede utilizar elurllib
la biblioteca para enviar peticiones HTTP directamente.HttpQuery()
El sistema de intercambio de datos se utiliza principalmente para acceder a las interfaces del intercambio que no requieren una firma, como las interfaces públicas como la información del ticker.HttpQuery()
El sistema de backtesting puede utilizarse para enviar solicitudes (sóloGET
Las pruebas de retroceso se limitan a utilizar 20 visitas a diferentesURLs
, yHttpQuery()
Las visitas cacharán los datos.URL
Se puede acceder por segunda vez, elHttpQuery()
La función devuelve los datos almacenados en caché y no se producen más solicitudes reales de red.
¿Por qué no lo haces?
Envía una solicitud HTTP, una versión asíncrona delHttpQuery
function.
ElHttpQuery_Go()
función devuelve inmediatamente un objeto concurrente que se puede utilizar para obtener el resultado de una solicitud HTTP utilizando elwait
El método deJSON.parse()
Función puede ser utilizado para analizar elJSON.parse()
La función en elJavaScript
La estrategia del lenguaje.
objetos
HttpQuery_Go ((url) HttpQuery_Go ((url, opciones)
URL de solicitud de HTTP. - ¿ Qué pasa? verdadero la cuerda Por ejemplo, las configuraciones relacionadas con las solicitudes HTTP pueden estructurarse de la siguiente manera:
{
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
, estoHttpQuery_Go
La llamada de la función devuelve el mensaje de respuesta completo.false
, sólo los datos en elBody
del mensaje de respuesta se devuelve.profile
el campo puede ser dejado fuera.opciones falsos 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
Acceso asíncrono a la interfaz pública de la bolsa para datos agregados de ticker.
ElHttpQuery_Go()
Función sólo soportaJavaScript
, elPython
El lenguaje puede utilizarse con elurllib
la biblioteca para enviar peticiones HTTP directamente.HttpQuery_Go()
El sistema de intercambio de datos se utiliza principalmente para acceder a interfaces que no requieren una firma en el intercambio, como las interfaces públicas como la información del ticker.HttpQuery_Go
Función no soportada en el sistema de backtesting.
¿Por qué no lo haces?
Esta función codifica los datos según los parámetros transmitidos.
ElEncode
función devuelve los datos después de codificación y cifrado.
la cuerda
Encódigo ((algo, inputFormat, outputFormat, datos) Encódigo ((algo, inputFormat, outputFormat, datos, claveFormat, clave)
El parámetroalgo
es el algoritmo utilizado en el cálculo de la codificación.raw
(no se utiliza algoritmo), el"signo", algo
también admite: algo
también admite: algo
puede escribirse como ed25519.seed
el cálculo.
algo
verdadero
la cuerda
Se utiliza para especificar el formato de datos deldata
el parámetro.inputFormat
el parámetro puede establecerse como uno de los siguientes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, y outputFormat
el parámetro puede establecerse como uno de los siguientes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, y data
es los datos a tratar.
datos
verdadero
la cuerda
Se utiliza para especificar el formato de datos delkey
el parámetro.key
el parámetro puede establecerse como uno de los siguientes:raw
, hex
, base64
, string
. hex
codificado, base64
codificado, y key
es la clave secreta utilizada paraHMAC
El parámetrokey
se requiere cuando el parámetroalgo
está configurado para:sign
o biensignTx
El.key
el parámetro no se utiliza paraHMAC
cifrado cuando elalgo
el parámetro está establecido en
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
}
Ejemplo de llamada de función de codificación.
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);
}
El parámetroalgo
También admite:
ElEncode()
la función sólo se admite para el comercio en vivo.key
ykeyFormat
los parámetros no se pasan, entonceskey
no se utiliza el cifrado.
Obtenga la marca de tiempo del nanosegundo del momento actual.
ElUnixNano()
La función devuelve la marca de tiempo del nanosegundo.
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);
}
Si necesita obtener marcas de tiempo de milisegundos, puede usar el siguiente código:
¿Qué quieres decir con eso?
Obtenga la fecha del momento actual en el segundo nivel.
Devuelve la marca de tiempo de segundo nivel. Número
Unix ((()
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
¿Por qué no lo haces?
Obtener la información del sistema del dispositivo donde se encuentra el docker.
Información del sistema. la cuerda
¿Qué quieres decir?
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Por ejemplo, una llamada a laGetOS()
Función para un docker que se ejecuta en elMac OSel sistema operativo puede devolver:darwin/amd64
Porque las computadoras de Apple tienen múltiples arquitecturas de hardware.darwin
es el nombre de laMac OS system.
Computa el hash MD5 del parámetrodata
.
Valor hash de MD5. la cuerda
MD5 (datos)
Los datos que requieren el cálculo MD5. datos verdadero la cuerda
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
Llamando alMD5("hello world")
función, el valor de retorno es:5eb63bbbe01eeed093cb22bb8f5acdc3
.
¿Por qué no lo haces?
Funciones de interfaz de base de datos.
Objeto que contiene el resultado de la ejecución de unCuadradouna declaración, por ejemplo:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
objetos
DBExec (sql)
Cuadradola cadena de instrucciones. Cuadrado verdadero la cuerda
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;"));
}
Apoyo a la base de datos en memoria, paraDBExec
parámetros de función, siCuadradola declaración comienza con:
Es adecuado para operaciones de base de datos que no requieren de un almacenamiento persistente, por ejemplo:
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);
}
Crea una 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));
}
Añadir, borrar, comprobar y cambiar los registros en la tabla.
La funciónDBExec()
Puede operar la base de datos de operaciones en vivo (base de datos SQLite) mediante el paso de parámetros.Es muy bueno.El sistema reservó tablas en la base de datos de operaciones en vivo:kvdb
, cfg
, log
, profit
, chart
, no opere en estas mesas.Las transaccionesLas funciones de control de los datos no son compatibles y no se recomienda realizar tales operaciones, que pueden causar conflictos en el sistema.DBExec()
La función solo es compatible con el comercio en vivo.
¿Por qué no lo haces?
Crear un UUID.
UUID de 32 bits. la cuerda
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);
}
ElUUID()
La función soporta sólo el comercio en vivo.
Escucha los acontecimientos, que vuelve cuando hay algunaWebSocket
datos legibles o tareas concurrentes, como por ejemplo:exchange.Go()
, HttpQuery_Go()
, etc. se han completado.
Si el objeto devuelto no es un valor nulo, elEvent
el contenido de la devolución es el tipo de activador de eventos. Por ejemplo, la siguiente estructura de valor de devolución:
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
objetos
Loop de evento EventLoop (tiempo muerto)
El parámetrotimeout
es la configuración de tiempo de espera, en milisegundos.timeout
espera que ocurra un evento antes de devolverlo si está establecido en 0, si es mayor que 0, establece el evento para esperar un tiempo de espera, y devuelve el evento más reciente inmediatamente si es menor que 0.
tiempo de espera
falsos
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);
}
La primera llamada a laEventLoop()
función en el código inicializa el mecanismo para ese evento escuchado, y si el primeroEventLoop()
El sistema subyacente envuelve una estructura de cola que almacena en caché un máximo de 500 devoluciones de llamada de eventos.EventLoop()
La función no se llama a tiempo para sacarlos durante la ejecución del programa, las llamadas posteriores de eventos fuera de la caché 500 se perderán.EventLoop()
función no afectan a la cola de caché del sistema subyacente WebSocket o las caché de funciones concurrentes tales comoexchange.Go()
. Para estos cachés, todavía es necesario utilizar los métodos respectivos para recuperar los datos.EventLoop()
Función para los datos que se han recuperado antes de laEventLoop()
El objetivo principal de laEventLoop()
La función principal de la red es la de notificar a la capa de estrategia que los nuevos datos de red han sido recibidos por el sistema subyacente.EventLoop()
Por ejemplo, conexiones WebSocket, objetos creados porexchange.Go()
Los datos de laEventLoop()
La función soporta sólo el comercio en vivo.
Escuchar eventos en el hilo principal cuando se llama desde la función principalmain()
En las estrategias escritas en elJavaScript
La lenguathreading.Thread()
función crea un hilo, que también puede ser llamado en la función de ejecución del hilo
En el caso de las empresas que se encuentran en una situación de riesgo, la información que se proporciona es la siguiente:
El__Serve
La función se utiliza para crear el servicio HTTP, el servicio TCP y el servicio Websocket (basado en el protocolo HTTP).
Devuelve una cadena que registra la dirección IP y el puerto del servicio creado. Por ejemplo:127.0.0.1:8088
, [::]:8089
.
la cuerda
__Servir (servirURI, manejador de datos) __Service ((serveURI, manejador,...args)
ElserveURI
El parámetro se utiliza para configurar el protocolo, dirección IP, puerto y otras configuraciones del servicio de vinculación, tales comohttp://0.0.0.0:8088?gzip=true
, es decir,http://:8088?gzip=true
.
serveURI
configuración de parámetros, comotcp://127.0.0.1:6666?tls=true
; puede añadir certificados y claves privadas, tales comotls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
configuración de parámetros, tales comohttp://127.0.0.1:6666?gzip=true
; puede configurar la configuración de compresión:gzip=true
- ¿ Por qué?
ElserveURI
El parámetro se utiliza para Https, comohttps://127.0.0.1:6666?tls=true&gzip=true
; puede añadircert_pem
ycert_key_pem
los parámetros para cargar el certificado.servicioURI
verdadero
la cuerda
Elhandler
El parámetro se utiliza para pasar en la función de procesamiento de enrutamiento (protocolo HTTP), la función de procesamiento de mensajes (protocolo TCP) y la función de procesamiento de flujo (Websocket).
La función de devolución de llamada transmitida por el parámetrohandler
puede definir múltiples parámetros, el primer parámetro es el objeto ctx (objeto de contexto).
manipuladora
verdadero
Función
El parámetro real de la función de devolución de llamada pasado como el parámetrohandler
Puede haber varios parámetros.arg
, por ejemplo:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Los parámetros1
, 2
, 3
En el momento de llamar a la__Serve()
función corresponde a los parámetrosa
, b
, c
Pasado en la función de devolución de llamada.
el falsos cadena, número, bool, objeto, matriz, función, valor nulo y otros tipos compatibles con el 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
el servicio se implementa basado en el protocolo Http. Puede establecer una rama de enrutamiento en la ruta y diseñar el código de implementación paraWebsocket
Se puede consultar el código de muestra en esta sección.La función de devolución de llamada transmitida por el parámetrohandler
recibe unactx
el parámetro.ctx
Parámetro es un objeto de contexto utilizado para obtener y escribir datos, con los siguientes métodos:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, y la función de procesamiento de devoluciones de llamada transmitida por el parámetrohandler
las devoluciones"123"
¿Cuándo?ctx.query("num")
se llama.User-Agent
en los encabezados de la solicitud actual:ctx.header("User-Agent")
.GET
, POST
, etc.ctx
objeto de contexto al protocolo Websocket; devolviendo un valor booleano (verdadero) si el cambio es exitoso, y un valor booleano (falso) si falla.read
método no es compatible en el protocolo HTTP ordinario. Puede especificar el parámetro de tiempo de esperatimeout_ms
en milisegundos.JSON.stringify()
para codificar el objeto JSON en una cadena y luego escribirlo.WebSocket
Protocolo, se puede utilizar este método para pasar la cadena codificada al cliente.En el caso de las aplicaciones que se utilicen para la búsqueda de datos, el número de páginas que se utilicen para la búsqueda de datos es el número de páginas que se utilicen para la búsqueda de datos.
La estructura de datos es una tabla KV que se guarda permanentemente en el archivo de base de datos local del docker.
Datos de valores clave guardados de forma persistente enk-v
las parejas clave-valor.
cadena, número, bool, objeto, matriz, valor nulo
- ¿Qué quieres decir? _G(k) - ¿Por qué no?
El parámetrok
es el nombre de la clave en el par clave-valor guardado y no es sensible a mayúsculas y minúsculas.
el
falsos
cadena, valor cero
El parámetrov
es el valor clave en el par clave-valor guardado, que puede ser cualquier dato que pueda serJSON
en serie.
V
falsos
cadena, 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();
}
Una base de datos separada para cada operación en vivo, los datos guardados por el_G()
La función siempre estará allí si se reinicia la estrategia o si el docker deja de funcionar._G()
Cuando se utilice el_G()
Función para persistir los datos guardados, debe ser utilizado razonablemente de acuerdo con la memoria y el espacio en disco duro del dispositivo de hardware, y no debe ser mal utilizado.
Cuando se llama a la_G()
En el caso de las transacciones en vivo y no se pasan parámetros, el_G()
Función devuelve elId
En el caso de las transacciones en vivo._G()
función, el parámetrov
se pasa como nulo para indicar la eliminación de lak-v
Cuando se llama el_G()
función, sólo el parámetrok
se pasa en la cadena, y el_G()
función devuelve el valor de clave correspondiente al parámetro guardadok
Cuando llamas a la_G()
función, sólo el parámetrok
se pasa en un valor nulo, lo que indica que todos los registros de lak-v
Cuando el par de valores clave se elimina.k-v
Los pares de valores clave se han guardado de forma persistente, el_G()
la función se llama de nuevo, pasando en el nombre de la clave que se ha guardado persistentemente como parámetrok
. Pasando el nuevo valor clave como parámetrov
Lo actualizaremos.k-v
el par clave-valor.
¿Por qué no lo haces?
Convierte marcas de tiempo de milisegundos oDate
objetos a las cadenas de tiempo.
Una cadena de tiempo. la cuerda
¿Qué es esto? _D (tiempo) _D (tiempo, fmt)
Marca de tiempo de milisegundos oDate
Objeto.
el sello de tiempo
falsos
Número, objeto
El formato de la cadena,JavaScript
formato predeterminado del idioma:yyyy-MM-dd hh:mm:ss
; Python
formato predeterminado del idioma:%Y-%m-%d %H:%M:%S
; C++
formato predeterminado del idioma:%Y-%m-%d %H:%M:%S
- ¿ Por qué?
Fmt también
falsos
la cuerda
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Obtener e imprimir la cadena de tiempo actual:
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));
}
La marca de tiempo es 1574993606000, utilizando la conversión 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
}
Formato con el parámetrofmt
es diferente paraJavaScript
, Python
, yC++
lenguas, como se muestra en los siguientes ejemplos:
Devuelve la cadena de tiempo actual sin pasar ningún parámetro._D()
La función en elPython
estrategia, usted necesita ser consciente de que los parámetros pasados son marcas de tiempo de segundo nivel (marcas de tiempo de nivel de milisegundos en las estrategias JavaScript y C ++, donde 1 segundo es igual a 1000 milisegundos)._D()
función para analizar una cadena de tiempo con una marca de tiempo legible en el comercio en vivo, usted necesita prestar atención a la zona horaria y la configuración de tiempo del sistema operativo donde se encuentra el programa docker._D()
La función analiza una marca de tiempo en una cadena de tiempo legible dependiendo del tiempo del sistema docker.
¿Por qué no lo haces?
Formate un número con coma flotante.
El número de coma flotante formateado de acuerdo con el ajuste de precisión. Número
_N() _N (número) _N (número, precisión)
El número de coma flotante que debe ser formateado.
No
verdadero
Número
El ajuste de precisión para el formato, el parámetroprecision
es un número entero, y el parámetroprecision
por defecto a 4.
Precisión
falsos
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 ejemplo,_N(3.1415, 2)
borrará el valor después3.1415
dos decimales y la función devuelve3.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);
}
Si necesitas cambiar todos los dígitos N a la izquierda del punto decimal a 0, puedes escribirlo así:
El parámetroprecision
puede ser un número entero positivo, negativo.
¿Por qué no lo haces?
Intentar de nuevo la función de tolerancia a fallas de la interfaz.
El valor de retorno de la función de llamada de retorno cuando se ejecuta. Todos los tipos son compatibles con el sistema exceptovalor lógico falsoyvalor nulo.
- ¿Qué es eso? - ¿Por qué no lo haces?
El parámetropfn
es una referencia de función, que es unFunción de devolución de llamada- ¿ Por qué?
Pfn
verdadero
Función
Parámetros paraLas funciones de devolución de llamada, puede haber más de un parámetroarg
Tipo y número de parámetrosarg
dependerá de los parámetros de laFunción de devolución de llamada¿ Qué pasa?
el
falsos
cadena, número, bool, objeto, matriz, función, todos los tipos son compatibles con el 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 las funciones tolerantes a errores sin 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 las funciones con parámetros tolerantes a errores:
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
También se puede utilizar para la tolerancia a fallos de las funciones personalizadas:
El_C()
función seguirá llamando a la función especificada hasta que devuelva con éxito (la función a la que se refiere el parámetropfn
las devolucionesNo hay nadao bien- No es cierto.Cuando lo llamen, volverá a llamar.pfn
Por ejemplo:_C(exchange.GetTicker)
El intervalo de reintentos predeterminado es de 3 segundos, puede llamar al_CDelay()
Función para establecer el intervalo de reintentos._CDelay(1000)
El uso de un dispositivo de control de la velocidad es un medio para cambiar el intervalo de repetición de las pruebas de_C()
Función a 1 segundo.
La tolerancia a fallos puede realizarse para, entre otras cosas, las siguientes funciones:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Todos pueden ser llamados por el_C()
La función de tolerancia a fallos_C()
la función no se limita a la función de tolerancia a fallas mencionada anteriormente, el parámetropfn
es una referencia de función en lugar de una llamada de función.
Observe que es_C(exchange.GetTicker)
, no_C(exchange.GetTicker())
.Devuelve el número de períodos de intersección de la matrizarr1
y la matrizarr2
.
El número de períodos transversales de la matrizarr1
y la matrizarr2
- ¿ Por qué?
Número
_Cruz ((arr1, arr2)
Los elementos son matrices de tiponumber
- ¿ Por qué?
Arr1
verdadero
el conjunto
Los elementos son matrices de tiponumber
- ¿ Por qué?
arr2
verdadero
el conjunto
// 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));
}
Se puede simular un conjunto de datos para probar la función _Cross ((Arr1, Arr2):
Si el valor de retorno de la_Cross()
Si la función es un número positivo, indica el período de penetración ascendente, si es un número negativo, indica el período de penetración descendente, 0 significa lo mismo que el precio actual.Análisis e instrucciones de uso sobre la función integrada _Cross.
La funciónJSONParse()
se utiliza para analizarJSON
strings.
JSON
Objeto.
Objeto
JSONParse (s)
JSON
la cuerda.
el
verdadero
la cuerda
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.
}
Las cadenas JSON con valores grandes se pueden analizar correctamente, y analizará los valores grandes como tipos de cadena.JSONParse()
Función no soportada en el sistema de backtest.