Renvoie le numéro de version actuel du système.
Numéro de version du système actuel, tel que3.6
- Je ne sais pas.
chaîne
Version (en)
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
Le numéro de version du système est le numéro de version du programme du docker.
La fonction de sommeil, provoquant la pause du programme pendant une période de temps.
Le sommeil (milliseconde)
Lemillisecond
Le paramètre est utilisé pour définir la durée du sommeil et le nombre de millisecondes.
milliseconde
vrai
Numéro
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");
}
Par exemple, lors de l'exécution duSleep(1000)
Il prend en charge les opérations avec un temps de sommeil inférieur à 1 milliseconde, par exemple le réglageSleep(0.1)
Il prend en charge un paramètre minimum de0.000001
, c'est-à-dire l'hibernation en nanoseconde, où 1 nanoseconde est égale à1e-6
Des millisecondes.
Lors de l'écriture de stratégies dans lePython
La langue, leSleep(millisecond)
Il n'est pas recommandé d'utiliser letime.sleep(second)
fonction dePython
C' est...time
C'est parce qu'en utilisant letime.sleep(second)
fonction dans une stratégie fait attendre le programme de stratégie pendant une période de temps en fait lors du backtesting (pas sauter sur la série temporelle du système de backtesting), de sorte qu'il provoque la stratégie de backtest très lentement.
Déterminer si l'environnement de fonctionnement de la stratégie est un système de backtesting.
La stratégie renvoie une valeur réelle, par exemple:true
La stratégie renvoie une valeur fausse, par exemple:false
lorsqu'il est exécuté dans un environnement de négociation en direct.
Boole
C' est virtuel?
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.");
}
}
Déterminer si l'environnement en cours est un système de backtesting, qui est utilisé pour être compatible avec la différence entre le backtesting et le trading en direct.
Envoyez un courriel.
Une livraison réussie d'un e-mail renvoie une valeur réelle, par exemple,true
, et une livraison ratée renvoie une valeur fausse, par exemple,false
- Je ne sais pas.
Boole
Mail ((smtpServeur, smtpNom d'utilisateur, smtpCode d'accès, mailTo, titre, corps)
Utilisé pour spécifier leSMTP
l'adresse de service de l'expéditeur du courrier électronique.
Le serveur smtp
vrai
chaîne
Utilisé pour spécifier l'adresse e-mail de l'expéditeur.
Nom de l'utilisateur
vrai
chaîne
LeSMTP
mot de passe de la boîte aux lettres de l'expéditeur.
Le mot de passe
vrai
chaîne
Utilisé pour spécifier l'adresse e-mail du destinataire.
Envoyer par mailTo
vrai
chaîne
Titre de courriel.
titre
vrai
chaîne
Le corps de l'email.
corps
vrai
chaîne
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");
}
LesmtpPassword
paramètre définit le mot de passe pour leSMTP
le service, pas le mot de passe de la boîte aux lettres.
Lors du réglage dusmtpServer
paramètre, si vous avez besoin de changer le port, vous pouvez ajouter le numéro de port directement dans le paramètresmtpServer
Par exemple: courrier QQsmtp.qq.com:587
, qui est disponible pour les tests.
Si une erreur est signalée:unencryped connection
, vous devez modifier lesmtpServer
de l'annéeMail
Le format du paramètre est le suivant:ssl://xxx.com:xxx
, par exemple, lessl
méthode deSMTP
pour le courrier QQ:ssl://smtp.qq.com:465
ousmtp://xxx.com:xxx
- Je ne sais pas.
Il ne fonctionne pas dans le système de backtesting.
Je ne sais pas.
Version asynchrone duMail
function.
LeMail_Go
fonction renvoie un objet concurrent immédiatement, et vous pouvez utiliser lewait
Une livraison courriel réussie renvoie une valeur vraie, par exemple,true
, et une livraison ratée renvoie une valeur fausse, par exemple,false
- Je ne sais pas.
objet
Mail_Go ((smtpServeur, smtpNom d'utilisateur, smtpCode de passe, mailTo, titre, corps)
Il est utilisé pour spécifier leSMTP
l'adresse de service de l'expéditeur du courrier électronique.
Le serveur smtp
vrai
chaîne
Il est utilisé pour spécifier l'adresse e-mail de l'expéditeur.
Nom de l'utilisateur
vrai
chaîne
LeSMTP
mot de passe de la boîte aux lettres de l'expéditeur.
Le mot de passe
vrai
chaîne
Il est utilisé pour spécifier l'adresse e-mail du destinataire.
Envoyer par mailTo
vrai
chaîne
Titre de courriel.
titre
vrai
chaîne
Le corps de l'email.
corps
vrai
chaîne
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.
Il ne fonctionne pas dans le système de backtesting.
{@fun/Global/Mail Mail} Je ne peux pas le faire
Filtrez les journaux d'erreur.
FixerErrorFilter (les filtres)
Chaîne d'expressions régulières. filtres vrai chaîne
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");
}
Filtrer les erreurs courantes.
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);
}
Filtrer un message d'erreur d'interface.
Les journaux d'erreurs correspondant à cette expression régulière ne seront pas téléchargés dans le système de journaux. Vous pouvez l'appeler plusieurs fois (sans limite sur le nombre de fois) pour définir plusieurs conditions de filtre. Les expressions régulières définies plusieurs fois seront accumulées et prendront effet en même temps. Vous pouvez définir une chaîne vide pour réinitialiser l'expression régulière utilisée pour filtrer les journaux d'erreurs:SetErrorFilter("")
Les journaux filtrés ne sont plus écrits dans le fichier de base de données correspondant à l'identifiant de trading en direct dans le répertoire docker pour éviter que les rapports d'erreur fréquents ne gonflent le fichier de base de données.
Obtenez l'identifiant du processus de négociation en direct.
Retourner l'identifiant du processus de négociation en direct. chaîne
Je ne peux pas.
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
J'ai reçu le dernier message d'erreur.
Dernier message d'erreur. chaîne
Obtenez la dernière erreur
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);
}
Il ne fonctionne pas dans le système de backtesting.
Il reçoit la commande d'interaction stratégique.
Le format de la commande retournée estControlName:Data
. ControlName
est le nom du contrôle, etData
est les données entrées dans la commande. Si la commande interactive n'a pas de boîtes d'entrée, de boîtes déroulantes et d'autres composants (par exemple, une commande de bouton sans boîtes d'entrée), le format de commande retourné estControlName
, qui renvoie uniquement le nom du contrôle.
chaîne
Vous avez le commandement?
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);
}
}
Détecte la commande d'interaction et utilise leLog
fonction de sortie de la commande d'interaction lorsqu'elle est détectée.
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);
}
}
Par exemple, le contrôle interactif de stratégie ajoute un contrôle sans boîte d'entrée, le contrôle interactif est nommé:buy
, les informations relatives à la description du contrôle sont les suivantes:buy
, qui est une commande de bouton. Continuez en ajoutant une commande avec une boîte d'entrée. La commande interactive est nommée:sell
et le message de description du contrôle est le suivant:sell
Le code d'interaction est conçu dans la stratégie pour répondre aux différents contrôles d'interaction:
Il ne fonctionne pas dans le système de backtesting.
Obtenez la valeur de Meta écrite lors de la génération du code d'enregistrement de stratégie.
Meta
les données.
chaîne
Je suis désolée.
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);
}
}
Exemple de scénario d'application: utilisationMeta
limiter le montant des actifs exploités par la stratégie.
Scenario d'application: besoin de faire des limites de capital pour les différents locataires de stratégie.Meta
la valeur définie lors de la génération du code d'enregistrement ne doit pas dépasser 190 caractères et leGetMeta()
La fonction ne prend en charge que le trading en direct.Meta
) est défini lors de la génération d'un code d'enregistrement de stratégie,GetMeta()
La fonction renvoie null. Elle ne fonctionne pas dans le système de backtesting.
Pour le primitifSocket
l'accès, le soutientcp
, udp
, tls
, unix
Prise en charge de 4 protocoles de communication populaires:mqtt
, nats
, amqp
, kafka
. Prise en charge de la connexion aux bases de données:sqlite3
, mysql
, postgres
, clickhouse
.
LeDial()
une fonction renvoie null s'il s'éteint. Un appel normal renvoie un objet de connexion qui a trois méthodes:read
, write
etclose
Leread
La méthode est utilisée pour lire les données,write
La méthode est utilisée pour envoyer des données etclose
méthode est utilisée pour fermer la connexion.
Leread
la méthode prend en charge les paramètres suivants:
ws.read()
.ws.read(2000)
spécifie un temps d'arrêt de deux secondes (2000 millisecondes).-1
signifie que la fonction renvoie immédiatement, indépendamment de la présence ou de l'absence de messages, par exemple:ws.read(-1)
- Je ne sais pas.
Passer le paramètre-2
signifie que la fonction renvoie immédiatement avec ou sans message, mais que seul le dernier message est renvoyé, et le message tamponné est écarté.ws.read(-2)
.read()
Description du tampon de fonction:
Les données entrantes poussées par le protocole WebSocket peuvent entraîner une accumulation de données si l'intervalle de temps entre la stratégieread()
Ces données sont stockées dans le tampon, qui a une structure de données d'une file d'attente avec un maximum de 2000.
Scénario | Aucun paramètre | Paramètre: -1 | Paramètre: -2 | Paramètre: 2000, en millisecondes |
---|---|---|---|---|
Données déjà dans le tampon | Retournez les données les plus anciennes immédiatement | Retournez les données les plus anciennes immédiatement | Retournez les dernières données immédiatement | Retournez les données les plus anciennes immédiatement |
Aucune donnée dans le tampon | Retourner lorsque les données sont bloquées | Retourner nul immédiatement | Retourner nul immédiatement | Attendre 2000 ms, retourner nul si aucune donnée, retourner nul si des données sont disponibles |
La connexion WebSocket est déconnectée ou reconnectée par le sous-jacent | read() fonction renvoie la chaîne vide, c.-à-d.: |
objet
Numéro de téléphone (adresse) Numéro (adresse, délai d'attente)
Demandez une adresse. l'adresse vrai chaîne secondes de temps d'arrêt, temps d'arrêt faux Numéro
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();
}
}
Exemple d'appel à la fonction 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();
}
Pour accéder à l'interface 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");
}
Accès à l'interface du ticker WebSocket OKX
var ws = null
function main(){
var param = {"sub": "market.btcusdt.detail", "id": "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
while(1){
var ret = ws.read()
Log("ret:", ret)
// Respond to heartbeat packet operations
try {
var jsonRet = JSON.parse(ret)
if(typeof(jsonRet.ping) == "number") {
var strPong = JSON.stringify({"pong" : jsonRet.ping})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
}
} catch(e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("Execute the ws.close() function")
}
import json
ws = None
def main():
global ws
param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
while True:
ret = ws.read()
Log("ret:", ret)
# Respond to heartbeat packet operations
try:
jsonRet = json.loads(ret)
if "ping" in jsonRet and type(jsonRet["ping"]) == int:
strPong = json.dumps({"pong" : jsonRet["ping"]})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
except Exception as e:
Log("e:", e)
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("Execute the ws.close() function")
using namespace std;
void main() {
json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
if(ws.Valid) {
while(true) {
auto ret = ws.read();
Log("ret:", ret);
// Respond to heartbeat packet operations
try
{
auto jsonRet = json::parse(ret);
if(jsonRet["ping"].is_number()) {
json pong = R"({"pong" : 0})"_json;
pong["pong"] = jsonRet["ping"];
auto strPong = pong.dump();
ws.write(strPong);
Log("Respond to ping, send pong:", strPong, "#FF0000");
}
} catch(exception &e)
{
Log("e:", e.what());
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
// ws.close();
Log("Execute the ws.close() function");
}
Accès à l'interface du ticker 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");
}
Pour accéder à l'interface d'authentification 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
L'objet de connexion renvoyé par la fonction Dial lors de la connexion à une base de données possède deux fonctions de méthode qui lui sont propres:
exec(sqlString)
: Utilisé pour exécuter des instructions SQL de manière similaire à laDBExec()
function.fd()
Lefd()
fonction renvoie une poignée (par exemple, la variable poignée est poignée) à utiliser par d'autres threads pour se reconnecter (même si l'objet créé par Dial a déjà été fermé par l'exécution duclose()
La fonction de fermeture de la connexion) en passant la poignée dans leDial()
la fonction, par exemple,Dial(handle)
connexion de réutilisation.
Ce qui suit est un exemple de la fonction Dial se connectant à unsqlite3
database.Détails de laaddress
paramètre, séparé par le|
le symbole suivant l'adresse normale:wss://ws.okx.com:8443/ws/v5/public
S' il y en a|
les caractères dans la chaîne de paramètres, puis||
La partie après que ce sont quelques paramètres de paramètres de fonction, et chaque paramètre est connecté avec&
Il s'agit par exemple dess5
Les paramètres de substitution et de compression peuvent être définis ensemble comme suit:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Fonctions prises en charge par le paramètre d'adresse de la fonction Dial | Description du paramètre |
---|---|
Paramètres liés à la compression des données du protocole WebSocket: compress=valeur du paramètre | compresser est la méthode de compression, les options de paramètres compresser sont: gzip_raw, gzip, etc. Si la méthode gzip n'est pas gzip standard, vous pouvez utiliser la méthode étendue: gzip_raw |
Paramètres liés à la compression des données du protocole WebSocket: mode=valeur du paramètre | mode est le mode de compression, le paramètre de mode peut être double, envoyer, recv. double est la compression bidirectionnelle, envoyer des données compressées, recevoir des données compressées. envoyer est envoyer des données compressées. recv est recevoir des données compressées, décompression locale. |
Le protocole WebSocket définit les paramètres sous-jacents liés à la reconnexion automatique: reconnect=valeur du paramètre | reconnect est la définition de reconnect, reconnect=true est la définition de reconnect. |
Le protocole WebSocket définit les paramètres sous-jacents liés à la reconnexion automatique: interval=valeur du paramètre | l'intervalle est l'intervalle de réessayage, en millisecondes, l'intervalle=10000 est l'intervalle de réessayage de 10 secondes, la valeur par défaut est de 1 seconde lorsqu'il n'est pas réglé, c'est-à-dire l'intervalle=1000. |
Le protocole WebSocket définit les paramètres sous-jacents liés à la reconnexion automatique: charge utile=valeur du paramètre | payload est le message d'abonnement qui doit être envoyé lorsque le WebSocket est reconnecté, par exemple: payload=okokok. |
Paramètres liés aux chaussettes5 proxy: proxy=valeur du paramètre | Proxy est le paramètre de paramètre de configuration de proxy ss5: socks5://name:pwd@192.168.0.1:1080, le nom est le nom d'utilisateur du serveur ss5, pwd est le mot de passe de connexion du serveur ss5, 1080 est le port de service ss5. |
LeDial()
La fonction n'est prise en charge que pour le trading en direct.
Lors de la connexion à une base de données à l'aide de la fonction Dial, la chaîne de connexion est écrite en référence au projet de pilote de langage go pour chaque base de données.
Base de données prise en charge | Projets moteurs | Chaîne de connexion | Les commentaires |
---|---|---|---|
- Je ne sais pas. | github.com/mattn/go-sqlite3 | sqlite3://fichier:test.db?cache=partagé et mode=mémoire | Lesqlite3:// le préfixe indique qu'une base de données sqlite3 est utilisée, exemple d'appel:Dial("sqlite3://test1.db") |
Je vais essayer. | github.com/go-sql-driver/mysql | Je suis désolée.localhost:3306) /votre base de données?charset=utf8mb4 | – |
les produits de postgres | github.com/lib/pq | le nom de l'utilisateur et le nom de la base de données sslmode | – |
maison de jeu | github.com/ClickHouse/clickhouse-go | Cliquez sur le lien suivant: | – |
Veuillez noter que lorsque lepayload
contenus définis dans leaddress
paramètre contient des caractères=
ou d'autres caractères spéciaux, il peut affecter l'analyse de laaddress
paramètre duDial
fonction, comme dans l'exemple suivant.
Exemple d'appel à l'interface privée 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}}")
}
L'appel suivant dans le code fonctionne bien:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Si vous l'écrivez directement danspayload
, il ne fonctionnera pas correctement, par exemple:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
À l'heure actuelle, seul JavaScript prend en charge l'utilisation demqtt
, nats
, amqp
, etkafka
Le code de stratégie du langage JavaScript est utilisé comme exemple pour montrer l'utilisation des quatre protocoles:mqtt
, nats
, amqp
, etkafka
:
// 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")
}
}
Référence de la documentation détaillée:Exploration de FMZ: pratique du protocole de communication entre les stratégies de négociation en direct
Envoyez une demande Http.
Retourne les données de réponse de la requête.JSON
string, il peut être analysé par leJSON.parse()
fonction dans leJavaScript
La stratégie linguistique, et par lejson::parse()
fonction dans leC++
Si le débogage est réglé sur true dans la structure d'options, la valeur de retour est un objet (JSON); si le débogage est réglé sur false, la valeur de retour est une chaîne.
chaîne, objet
HttpQuery (URL) HttpQuery ((url, options)
L'URL de la demande HTTP. le nom de l'adresse vrai chaîne Par exemple, les paramètres liés aux requêtes HTTP peuvent être structurés comme suit:
{
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
Des empreintes digitales.
Les paramètres pris en charge comprennent les options suivantes:
Je ne sais pas."chrome_103"
, "chrome_104"
, "chrome_105"
, "chrome_106"
, "chrome_107"
, "chrome_108"
, "chrome_109"
, "chrome_110"
, "chrome_111"
, "chrome_112"
, "chrome_117"
Je suis désolée.
- Je ne sais pas."safari_15_6_1"
, "safari_16_0"
, "safari_ipad_15_6"
, "safari_ios_15_5"
, "safari_ios_15_6"
, "safari_ios_16_0"
Je suis désolée.
Je ne sais pas."firefox_102"
, "firefox_104"
, "firefox_105"
, "firefox_106"
, "firefox_108"
, "firefox_110"
, "firefox_117"
Je suis désolée.
- Je ne sais pas."opera_89"
, "opera_90"
, "opera_91"
Je suis désolée.
Je ne sais pas."zalando_android_mobile"
, "zalando_ios_mobile"
Je suis désolée.
Je suis désolée."nike_ios_mobile"
, "nike_android_mobile"
Je suis désolée.
le gratte-ciel:"cloudscraper"
Je suis désolée.
Je suis désolé."mms_ios"
Je suis désolée.
Je ne sais pas."mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
Je suis désolée.
Confirmé:"confirmed_ios"
, "confirmed_android"
Je suis désolée.
Ça va."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, leHttpQuery
l'appel de la fonction renvoie le message de réponse complet.false
, uniquement les donnéesBody
de la réponse est renvoyée.profile
le champ peut être laissé de côté.les options faux objet
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 exemple d'accès à l'interface API de ticker publique 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 fonction HttpQuery utilise des paramètres de proxy.
LeHttpQuery()
fonction ne supporte queJavaScript
, C++
le langage,Python
La langue peut être utiliséeurllib
La bibliothèque est utilisée pour envoyer directement des requêtes HTTP.HttpQuery()
Il est principalement utilisé pour accéder aux interfaces de l'échange qui ne nécessitent pas de signature, telles que les interfaces publiques telles que les informations des tickers.HttpQuery()
peut être utilisé dans le système de backtesting pour envoyer des demandes (uniquementGET
Les tests en arrière-plan sont limités à l'utilisation de 20 visites à desURLs
, etHttpQuery()
Les visites vont mettre en cache les données.URL
est consulté une deuxième fois, leHttpQuery()
La fonction renvoie les données mises en cache et aucune autre demande de réseau n'est effectuée.
Je ne sais pas si je peux le faire.
Envoie une requête HTTP, une version asynchrone duHttpQuery
function.
LeHttpQuery_Go()
fonction retourne immédiatement un objet concurrent qui peut être utilisé pour obtenir le résultat d'une requête HTTP en utilisant lewait
La méthodeJSON.parse()
fonction peut être utilisée pour analyser leJSON.parse()
fonction dans leJavaScript
La stratégie de la langue.
objet
HttpQuery_Go (URL) HttpQuery_Go (URL, options)
L'URL de la demande HTTP. le nom de l'adresse vrai chaîne Par exemple, les paramètres liés aux requêtes HTTP peuvent être structurés comme suit:
{
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
, ceciHttpQuery_Go
l'appel de la fonction renvoie le message de réponse complet.false
, uniquement les donnéesBody
de la réponse est renvoyée.profile
le champ peut être laissé de côté.les options faux objet
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
Accès asynchrone à l'interface publique de l'échange pour les données de ticker agrégées.
LeHttpQuery_Go()
fonction ne supporte queJavaScript
, lePython
La langue peut être utiliséeurllib
La bibliothèque est utilisée pour envoyer directement des requêtes HTTP.HttpQuery_Go()
Il est principalement utilisé pour accéder aux interfaces qui ne nécessitent pas de signature sur l'échange, telles que les interfaces publiques telles que les informations de ticker.HttpQuery_Go
fonction n'est pas prise en charge dans le système de backtesting.
{@fun/Global/HttpQuery HttpQuery} Je suis désolé
Cette fonction encode les données en fonction des paramètres transmis.
LeEncode
fonction renvoie les données après le codage et le cryptage.
chaîne
Encode ((algo, format d'entrée, format de sortie, données) Encode ((algo, inputFormat, outputFormat, données, cléFormat, clé)
Le paramètrealgo
est l'algorithme utilisé dans le calcul du codage.raw
(aucun algorithme n'est utilisé), le "signe", algo
Il prend également en charge: algo
supporte également: algo
peut être écrit comme ed25519.seed
le calcul.
quelque chose
vrai
chaîne
Utilisé pour spécifier le format de données dudata
Paramètre.inputFormat
le paramètre peut être défini comme l'un des paramètres suivants:raw
, hex
, base64
, string
. hex
codé, base64
encodé, et outputFormat
le paramètre peut être défini comme l'un des paramètres suivants:raw
, hex
, base64
, string
. hex
codé, base64
encodé, et data
est les données à traiter.
données
vrai
chaîne
Utilisé pour spécifier le format de données dukey
Paramètre.key
le paramètre peut être défini comme l'un des paramètres suivants:raw
, hex
, base64
, string
. hex
codé, base64
encodé, et key
est la clé secrète utilisée pourHMAC
Le paramètrekey
est nécessaire lorsque le paramètrealgo
est réglée sursign
ousignTx
Lekey
le paramètre n'est pas utilisé pourHMAC
le chiffrement lorsque lealgo
le paramètre est réglé sur
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
}
Exemple d'appel à la fonction 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);
}
Le paramètrealgo
Il prend également en charge:
LeEncode()
La fonction n'est prise en charge que pour le trading en direct.key
etkeyFormat
les paramètres ne sont pas passés, alorskey
le chiffrement n'est pas utilisé.
Obtenez l'horodatage nanoseconde du moment actuel.
LeUnixNano()
La fonction renvoie l'horodatage de la nanoseconde.
Numéro
UnixNano (en anglais)
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Si vous avez besoin d'obtenir des horodatages en millisecondes, vous pouvez utiliser le code suivant:
Je ne sais pas.
Obtenez l'horodatage du moment actuel au deuxième niveau.
Retourne l'horodatage de deuxième niveau. Numéro
Unix (()
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
Je ne sais pas si je peux vous aider.
Obtenez les informations du système de l'appareil où se trouve le dock.
Informations sur le système. chaîne
Je suis désolée.
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Par exemple, un appel à laGetOS()
fonction pour un docker exécuté sur leMac OSle système d'exploitation pourrait renvoyer:darwin/amd64
Parce que les ordinateurs Apple ont plusieurs architectures matérielles.darwin
est le nom de laMac OS system.
Calcule le hachage MD5 du paramètredata
.
Valeur de hachage MD5. chaîne
MD5 (données)
Les données qui nécessitent un calcul MD5. données vrai chaîne
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
On appelle leMD5("hello world")
fonction, la valeur de retour est:5eb63bbbe01eeed093cb22bb8f5acdc3
.
{@fun/Global/Encode Encode} Je suis désolé.
Fonctions d'interface de base de données.
Un objet contenant le résultat de l'exécution d'unLe secteurdéclaration, par exemple:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
objet
DBExec ((sql)
Le secteurune chaîne d'instructions. Le secteur vrai chaîne
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;"));
}
Prise en charge de la base de données en mémoire, pourDBExec
paramètres de fonction, siLe secteurLa déclaration commence par::
Il convient aux opérations de base de données qui ne nécessitent pas d'enregistrement persistant, par exemple:
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);
}
Créez une table.
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));
}
Ajouter, supprimer, vérifier et modifier les enregistrements dans le tableau.
La fonctionDBExec()
Il peut utiliser la base de données de négociation en direct (base de données SQLite) en passant des paramètres.SQLiteLe système a réservé des tables dans la base de données de négociation en direct:kvdb
, cfg
, log
, profit
, chart
Ne pas utiliser ces tables.Les opérationsIl n'est pas recommandé d'effectuer de telles opérations, car elles peuvent provoquer des conflits dans le système.DBExec()
La fonction n'est prise en charge que pour le trading en direct.
Je ne sais pas.
Créez un UUID.
Un UUID de 32 bits. chaîne
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);
}
LeUUID()
La fonction supporte uniquement le trading en direct.
Écoutez les événements, il revient quand il y a unWebSocket
données lisibles ou tâches simultanées, telles que:exchange.Go()
, HttpQuery_Go()
, etc. sont achevés.
Si l'objet retourné n'est pas une valeur nulle, leEvent
le type de déclencheur d'événement est contenu dans le contenu de retour.
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
objet
La boucle d'événement Le temps d'arrêt
Le paramètretimeout
est le paramètre de temps d'arrêt, en millisecondes.timeout
attend qu'un événement se produise avant de retourner s'il est défini sur 0, s'il est supérieur à 0, il définit l'événement en attendant un temps d'arrêt, et renvoie immédiatement l'événement le plus récent s'il est inférieur à 0.
Le temps mort
faux
Numéro
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);
}
Le premier appel à laEventLoop()
fonction dans le code initie le mécanisme pour cet événement écouté, et si le premierEventLoop()
Le système sous-jacent enveloppe une structure de file d'attente qui cache un maximum de 500 callbacks d'événements.EventLoop()
fonction n'est pas appelée à temps pour les retirer pendant l'exécution du programme, les appels ultérieurs d'événements en dehors du cache 500 seront perdus.EventLoop()
fonction n'affectent pas la file d'attente de cache du système WebSocket sous-jacent ou les caches de fonctions simultanées telles queexchange.Go()
Pour ces caches, il est toujours nécessaire d'utiliser les méthodes respectives pour récupérer les données.EventLoop()
fonction pour les données qui ont été récupérées avant leEventLoop()
Le but principal de l'analyse est deEventLoop()
La fonction principale de la stratégie est d'informer la couche de stratégie que de nouvelles données réseau ont été reçues par le système sous-jacent.EventLoop()
fonction renvoie un événement, passe juste à travers toutes les sources de données.exchange.Go()
- Je vais essayer d'obtenir des données.EventLoop()
La fonction supporte uniquement le trading en direct.
Écouter les événements dans le fil principal lorsqu'il est appelé depuis la fonction principalemain()
Dans les stratégies écrites dans leJavaScript
La langue, lethreading.Thread()
fonction crée un thread, qui peut également être appelé dans la fonction d'exécution du thread
{@fun/Global/Dial Dial}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
Le__Serve
fonction est utilisée pour créer le service Http, le service TCP et le service Websocket (basé sur le protocole Http).
Renvoie une chaîne qui enregistre l'adresse IP et le port du service créé.127.0.0.1:8088
, [::]:8089
.
une chaîne
__Serve (serveURI, traitement) __Service (serveURI, gestionnaire,... args)
LeserveURI
paramètre est utilisé pour configurer le protocole, l'adresse IP, le port et d'autres paramètres de la liaison de service, tels quehttp://0.0.0.0:8088?gzip=true
, c'est à dire,http://:8088?gzip=true
.
serveURI
réglage des paramètres tels quetcp://127.0.0.1:6666?tls=true
; vous pouvez ajouter des certificats et des clés privées, commetls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
paramètres, tels quehttp://127.0.0.1:6666?gzip=true
; vous pouvez définir les paramètres de compression:gzip=true
- Je ne sais pas.
LeserveURI
paramètre est utilisé pour Https, tels quehttps://127.0.0.1:6666?tls=true&gzip=true
; vous pouvez ajoutercert_pem
etcert_key_pem
les paramètres de chargement du certificat.serveURI
vrai
chaîne
Lehandler
Le paramètre est utilisé pour passer dans la fonction de traitement du routage (protocole HTTP), la fonction de traitement des messages (protocole TCP) et la fonction de traitement du flux (Websocket).
La fonction de rappel passée par le paramètrehandler
peut définir plusieurs paramètres, le premier paramètre étant l'objet ctx (objet contextuel).
le gestionnaire
vrai
fonction
Le paramètre réel de la fonction de rappel passé comme paramètrehandler
Il peut y avoir plusieurs paramètresarg
, par exemple:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Les paramètres1
, 2
, 3
Il est passé à l'appel__Serve()
fonction correspondent aux paramètresa
, b
, c
passé dans la fonction de rappel.
arg faux chaîne, nombre, bool, objet, tableau, fonction, valeur nulle et autres types pris en charge par le système
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
Vous pouvez définir une branche de routage dans le chemin et concevoir le code de mise en œuvre pourWebsocket
Vous pouvez consulter l'exemple de code dans cette section.La fonction de rappel passée par le paramètrehandler
Il reçoit unctx
Paramètre.ctx
paramètre est un objet contextuel utilisé pour obtenir et écrire des données, avec les méthodes suivantes:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, et la fonction de traitement de rappel passée par le paramètrehandler
rendements"123"
quand?ctx.query("num")
est appelé.User-Agent
dans les titres de la demande en cours:ctx.header("User-Agent")
.GET
, POST
, etc.ctx
objet de contexte au protocole Websocket; renvoie une valeur booléenne (true) si le commutateur est réussi, et une valeur booléenne (fausse) si elle échoue.read
Cette méthode n'est pas prise en charge dans le protocole HTTP ordinaire.timeout_ms
en millisecondes.JSON.stringify()
pour encoder l'objet JSON dans une chaîne de caractères et l'écrire.WebSocket
protocole, vous pouvez utiliser cette méthode pour passer la chaîne codée au client.{@fun/Global/HttpQuery HttpQuery}, {@fun/Global/HttpQuery_Go HttpQuery_Go} Vous pouvez utiliser le nom de domaine de l'utilisateur.
La structure de données est une table KV qui est sauvegardée en permanence dans le fichier de base de données locale du docker.
Les données de valeur de clé enregistrées en permanence dansk-v
les paires de valeurs-clés.
chaîne, nombre, bool, objet, tableau, valeur nulle
Je ne sais pas. Je ne sais pas. - Je ne sais pas.
Le paramètrek
est le nom de la clé dans la paire clé-valeur enregistrée et n'est pas sensible à la case.
K
faux
chaîne, valeur nulle
Le paramètrev
est la valeur clé dans la paire clé-valeur enregistrée, qui peut être n'importe quelle donnée qui peut êtreJSON
Il est en série.
v
faux
chaîne, nombre, bool, objet, tableau, valeur nulle
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();
}
Une base de données distincte pour chaque transaction en direct, les données enregistrées par le_G()
La fonction sera toujours présente si la stratégie est redémarrée ou si le docker cesse de fonctionner._G()
Lorsque vous utilisez le_G()
fonction de conserver les données enregistrées, il doit être utilisé de manière raisonnable en fonction de la mémoire et de l'espace disque dur du périphérique matériel, et ne doit pas être abusé.
Lorsque vous appelez le_G()
Les paramètres sont passés dans le cadre d'une fonction de trading en direct et aucun paramètre n'est passé, le_G()
Retourne leId
Les échanges en direct actuels._G()
fonction, le paramètrev
est passé comme nul pour indiquer la suppression de lak-v
Lorsque vous appelez le_G()
fonction, seulement le paramètrek
est passé dans la chaîne, et le_G()
fonction renvoie la valeur de clé correspondant au paramètre enregistrék
Lorsque vous appelez le_G()
fonction, seulement le paramètrek
est passé en valeur nulle, indiquant que tous les enregistrements de lak-v
Lorsque la clé-valeur est supprimée,k-v
les paires de clés-valeurs ont été sauvegardées de façon persistante,_G()
la fonction est appelée à nouveau, en passant le nom de la clé qui a été sauvegardée de manière persistante comme paramètrek
. Passer la nouvelle valeur de clé comme paramètrev
Je vais le mettre à jour.k-v
une paire clé-valeur.
Je ne sais pas.
Convertisse les horodatages en millisecondes ouDate
objets à des chaînes de temps.
Une chaîne temporelle. chaîne
Je suis désolé. _D (heure) _D (horodatage, fmt)
Marque d'heure en millisecondes ouDate
Je suis un objet.
l' étiquette
faux
Numéro, objet
Format de la chaîne,JavaScript
Format par défaut de la langue:yyyy-MM-dd hh:mm:ss
; Python
Format par défaut de la langue:%Y-%m-%d %H:%M:%S
; C++
Format par défaut de la langue:%Y-%m-%d %H:%M:%S
- Je ne sais pas.
fmt
faux
chaîne
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Obtenez et imprimez la chaîne de temps courante:
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));
}
L'horodatage est 1574993606000, en utilisant le code de conversion:
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
}
Formatage avec le paramètrefmt
est différente pourJavaScript
, Python
, etC++
les langues, comme indiqué dans les exemples suivants:
Retourne la chaîne de temps en cours sans passer de paramètres._D()
fonction dans lePython
Dans le cas d'une stratégie, vous devez être conscient que les paramètres passés sont des horodatages de deuxième niveau (horodatages de niveau milliseconde dans les stratégies JavaScript et C++, où 1 seconde équivaut à 1000 millisecondes)._D()
fonction pour analyser une chaîne d'heure avec un horodatage lisible dans le commerce en direct, vous devez faire attention au fuseau horaire et le réglage de l'heure du système d'exploitation où le programme docker est situé._D()
fonction analyse un horodatage dans une chaîne de temps lisible en fonction de l'heure du système docker
Je ne sais pas si je peux vous aider.
Formater un numéro en virgule flottante.
Le numéro en virgule flottante formaté selon le réglage de précision. Numéro
_N() Nombre _N (numéro, précision)
Le numéro à virgule flottante à formater.
Numéro
vrai
Numéro
Le paramètre de précision de mise en formeprecision
est un entier, et le paramètreprecision
par défaut à 4.
précision
faux
Numéro
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);
}
Par exemple,_N(3.1415, 2)
supprimera la valeur après3.1415
deux décimales et la fonction renvoie3.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 vous avez besoin de changer tous les N chiffres à gauche de la virgule à 0, vous pouvez l'écrire comme ceci:
Le paramètreprecision
peut être un entier positif, un entier négatif.
{@fun/Trade/exchange.SetPrecision échange.SetPrecision} Je suis désolé
Réessayez la fonction de tolérance à la défaillance de l'interface.
La valeur de retour de la fonction de rappel lorsqu'elle est exécutée. Tous les types sont pris en charge par le système saufvaleur logique fausseetvaleur nulle.
Je ne sais pas. Je ne sais pas.
Le paramètrepfn
est une référence de fonction, qui est unefonction de rappel- Je ne sais pas.
pfn
vrai
fonction
Paramètres àles fonctions de rappel, il peut y avoir plusieurs paramètresarg
. Le type et le nombre de paramètresarg
dépend des paramètres dufonction de rappelJe suis désolée.
arg
faux
chaîne, nombre, bool, objet, tableau, fonction, tous les types sont pris en charge par le système, tels que les valeurs nulles
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);
}
Pour les fonctions de tolérance à l'erreur sans paramètres:
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);
}
Pour les fonctions dont les paramètres sont tolérants aux erreurs:
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
Il peut également être utilisé pour la tolérance aux pannes des fonctions personnalisées:
Le_C()
fonction continuera à appeler la fonction spécifiée jusqu'à ce qu'elle renvoie avec succès (la fonction référencée par le paramètrepfn
rendementsNuloufauxQuand il est appelé, il recommence à appelerpfn
Par exemple:_C(exchange.GetTicker)
. L'intervalle de réessayer par défaut est de 3 secondes, vous pouvez appeler le_CDelay()
fonction pour régler l'intervalle de réessayage._CDelay(1000)
Les moyens de modifier l'intervalle de réessayage du_C()
fonction à 1 seconde.
La tolérance à la défaillance peut être effectuée pour, mais sans s'y limiter, les fonctions suivantes:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Tous peuvent être appelés par le_C()
La fonction de tolérance aux défauts_C()
la fonction n'est pas limitée à la fonction de tolérance à la défaillance énumérée ci-dessus, le paramètrepfn
est une référence de fonction plutôt qu'un appel de fonction.
Notez qu'il est_C(exchange.GetTicker)
, pas_C(exchange.GetTicker())
.Renvoie le nombre de périodes d'intersection du tableauarr1
et le tableauarr2
.
Le nombre de périodes transversales du tableauarr1
et le tableauarr2
- Je ne sais pas.
Numéro
_Cross ((arr1, arr2)
Les éléments sont des tableaux de typenumber
- Je ne sais pas.
Arr1
vrai
séquence
Les éléments sont des tableaux de typenumber
- Je ne sais pas.
Arr2
vrai
séquence
// 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));
}
Un ensemble de données peut être simulé pour tester la fonction _Cross ((Arr1, Arr2):
Si la valeur de retour du_Cross()
Si la fonction est un nombre positif, elle indique la période de pénétration ascendante, si elle est un nombre négatif, elle indique la période de pénétration descendante, 0 signifie la même chose que le prix actuel.Analyse et instructions d'utilisation concernant la fonction intégrée.
La fonctionJSONParse()
est utilisé pour analyserJSON
strings.
JSON
Je suis un objet.
objet
JSONParse (s)
JSON
Une corde.
s
vrai
chaîne
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.
}
Les chaînes JSON avec de grandes valeurs peuvent être analysées correctement, et il analysera de grandes valeurs comme des types de chaînes.JSONParse()
fonction n'est pas prise en charge dans le système de backtest.