Gibt die aktuelle Versionnummer des Systems zurück.
Aktuelle Systemversionsnummer, z. B.3.6
- Ich weiß.
String
Ausgabe ((()
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
Die Systemversionsnummer ist die Versionsnummer des Docker
Die Schlaffunktion, wodurch das Programm für eine gewisse Zeit pausiert.
Schlaf (Millisekunde)
Diemillisecond
Der Parameter wird verwendet, um die Schlafdauer und die Anzahl der Millisekunden festzulegen.
Millisekunde
- Das stimmt.
Zahl
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");
}
Zum Beispiel bei der Ausführung derSleep(1000)
Es unterstützt Operationen mit einer Schlafzeit von weniger als 1 Millisekunde, z. B. Einstellung vonSleep(0.1)
. Es unterstützt einen Mindestparameter von0.000001
, d.h. Nanosekunden-Wachstum, wobei 1 Nanosekunde gleich ist1e-6
Millisekunden.
Bei der Erstellung von Strategien inPython
Sprache, dieSleep(millisecond)
Es wird nicht empfohlen, dietime.sleep(second)
Funktion derPython
Das ist...time
Das ist, weil die Verwendung dertime.sleep(second)
Funktion in einer Strategie lässt das Strategieprogramm für einen Zeitraum warten, tatsächlich beim Backtesting (nicht überspringen auf die Zeitreihen des Backtesting-Systems), so dass es die Strategie verursacht, um sehr langsam zu backtest.
Bestimmen Sie, ob die laufende Umgebung der Strategie ein Backtesting-System ist.
Die Strategie gibt einen wahren Wert zurück, z. B.:true
Die Strategie gibt einen falschen Wert zurück, z. B.:false
wenn sie in einer Live-Handelsumgebung ausgeführt werden.
Boole
Ist virtuell?
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.");
}
}
Bestimmen Sie, ob die aktuelle laufende Umgebung ein Backtesting-System ist, das mit dem Unterschied zwischen Backtesting und Live-Handel kompatibel ist.
Schicken Sie eine E-Mail.
Eine erfolgreiche E-Mail-Zustellung gibt einen wahren Wert zurück, z. B.true
, und eine fehlgeschlagene Lieferung gibt einen falschen Wert zurück, z. B.false
- Ich weiß.
Boole
Mail ((smtpServer, smtpBenutzername, smtpPasswort, mailTo, Titel, Körper)
Verwendet zur Angabe derSMTP
Dienstadresse des E-Mail-Senders.
SmtpServer
wahr
String
Wird verwendet, um die E-Mail-Adresse des E-Mail-Senders anzugeben.
Sms-Benutzername
wahr
String
DieSMTP
Passwort für das Postfach des E-Mail-Senders.
Smp Passwort
wahr
String
Verwendet zur Angabe der E-Mail-Adresse des E-Mail-Empfängers.
Nachrichten
wahr
String
E-Mail-Adresse.
Titel
wahr
String
E-Mail Körper.
Körper
wahr
String
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");
}
DiesmtpPassword
Parameter setzt das Passwort für dieSMTP
Service, nicht das Postfach-Passwort.
Bei Einstellung dersmtpServer
Parameter, wenn Sie den Port ändern müssen, können Sie die Portnummer direkt in Parameter hinzufügensmtpServer
. Zum Beispiel: QQ-Mailsmtp.qq.com:587
, die zur Prüfung zur Verfügung steht.
Wenn ein Fehler gemeldet wird:unencryped connection
, müssen Sie diesmtpServer
derMail
Das Parameterformat lautet:ssl://xxx.com:xxx
, zum Beispiel diessl
Verfahren derSMTP
für QQ-Mail:ssl://smtp.qq.com:465
odersmtp://xxx.com:xxx
- Ich weiß.
Es funktioniert nicht im Backtesting-System.
Ich bin nicht derjenige, der dich anspricht.
Asynchrone Version derMail
function.
DieMail_Go
Funktion gibt ein gleichzeitiges Objekt sofort zurück, und Sie können diewait
Eine erfolgreiche Postlieferung gibt einen wahren Wert zurück, z. B.true
, und eine fehlgeschlagene Lieferung gibt einen falschen Wert zurück, z. B.false
- Ich weiß.
Gegenstand
Mail_Go ((smtpServer, smtpBenutzername, smtpPasswort, mailTo, Titel, Körper)
Es wird verwendet, um dieSMTP
Dienstadresse des E-Mail-Senders.
SmtpServer
- Das stimmt.
String
Es wird verwendet, um die E-Mail-Adresse des E-Mail-Senders anzugeben.
Sms-Benutzername
- Das stimmt.
String
DieSMTP
Passwort für das Postfach des E-Mail-Senders.
SmtpPasswort
- Das stimmt.
String
Es dient zur Angabe der E-Mail-Adresse des E-Mail-Empfängers.
Nachrichten
- Das stimmt.
String
E-Mail-Adresse.
Titel
- Das stimmt.
String
E-Mail Körper.
Körper
- Das stimmt.
String
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.
Es funktioniert nicht im Backtesting-System.
Ich bin nicht hier.
Filterfehlerprotokolle.
SetErrorFilter (Filter)
Regelmäßige Ausdrucksfolge. Filter wahr String
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");
}
Filtern von häufigen Fehlern.
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);
}
Filtern Sie eine Schnittstellenfehlermeldung.
Fehlerprotokolle, die mit diesem regulären Ausdruck übereinstimmen, werden nicht in das Protokollsystem hochgeladen. Sie können ihn mehrmals (ohne Begrenzung der Anzahl der Zeiten) aufrufen, um mehrere Filterbedingungen festzulegen. Regelmäßige Ausdrücke, die mehrmals gesetzt wurden, werden angesammelt und wirken gleichzeitig. Sie können eine leere Zeichenfolge festlegen, um den regulären Ausdruck, der zum Filtern von Fehlerprotokollen verwendet wird, zurückzusetzen:SetErrorFilter("")
. Die gefilterten Protokolle werden nicht mehr in die Datenbankdatei geschrieben, die der Live-Trading-ID im Docker-Verzeichnis entspricht, um zu verhindern, dass häufige Fehlermeldungen die Datenbankdatei aufblähen.
Holen Sie sich die Live-Handelsprozess-ID.
Rückgabe der Live-Handelsprozess-ID. String
GetPid (siehe unten)
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
Erhaltet die letzte Fehlermeldung.
Letzte Fehlermeldung. String
GetLastError()
function main(){
// Because the order number 123 does not exist, so there will be an error.
exchange.GetOrder("123")
var error = GetLastError()
Log(error)
}
def main():
exchange.GetOrder("123")
error = GetLastError()
Log(error)
void main() {
// Order ID type: TId, so you can't pass in a string, we place an order that doesn't meet the exchange specification to trigger
exchange.GetOrder(exchange.Buy(1, 1));
auto error = GetLastError();
Log(error);
}
Es funktioniert nicht im Backtesting-System.
Erhält den Strategie-Interaktionsbefehl.
Das Format des zurückgegebenen Befehls istControlName:Data
. ControlName
ist der Name der Kontrolle undData
ist das in die Steuerung eingegebene Datenformat. Wenn die interaktive Steuerung keine Eingabeboxen, Dropdown-Boxen und andere Komponenten (z. B. eine Tastensteuerung ohne Eingabeboxen) hat, wird das zurückgegebene BefehlformatControlName
, die nur den Kontrollnamen zurückgibt.
String
GetCommand (siehe unten)
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);
}
}
Ermittelt den Interaktionsbefehl und verwendet dieLog
Funktion zur Ausgabe des Interaktionsbefehls, wenn er erkannt wird.
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);
}
}
Zum Beispiel fügt die Strategie-Interaktionssteuerung eine Steuerung ohne Eingabebox hinzu, die interaktive Steuerung heißt:buy
, sind die Angaben zur Kontrollbeschreibung:buy
, das eine Tastensteuerung ist. Führen Sie fort, indem Sie eine Steuerung mit einem Eingabefeld hinzufügen. Die interaktive Steuerung heißt:sell
und die Beschreibungsmeldung für die Kontrolle lautet:sell
Der Interaktionscode ist in der Strategie so konzipiert, dass er auf die verschiedenen Interaktionssteuerungen reagiert:
Es funktioniert nicht im Backtesting-System.
Erhalten Sie den Wert von Meta geschrieben, wenn die Strategie Registrierungscode generiert.
Meta
Daten.
String
GetMeta()
function main() {
// The maximum asset value of the denominated currency allowed by the strategy.
var maxBaseCurrency = null
// Get the metadata when creating the registration code.
var level = GetMeta()
// Detecting the conditions corresponding to Meta.
if (level == "level1") {
// -1 for unrestricted
maxBaseCurrency = -1
} else if (level == "level2") {
maxBaseCurrency = 10
} else if (level == "level3") {
maxBaseCurrency = 1
} else {
maxBaseCurrency = 0.5
}
while(1) {
Sleep(1000)
var ticker = exchange.GetTicker()
// Detect asset values
var acc = exchange.GetAccount()
if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
// Stop executing strategy trading logic
LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!")
continue
}
// Other trading logic
// Normal output of status bar information
LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker)
}
}
def main():
maxBaseCurrency = null
level = GetMeta()
if level == "level1":
maxBaseCurrency = -1
elif level == "level2":
maxBaseCurrency = 10
elif level == "level3":
maxBaseCurrency = 1
else:
maxBaseCurrency = 0.5
while True:
Sleep(1000)
ticker = exchange.GetTicker()
acc = exchange.GetAccount()
if maxBaseCurrency != -1 and maxBaseCurrency < acc["Stocks"] + acc["FrozenStocks"]:
LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!")
continue
# Other trading logic
# Normal output of status bar information
LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker)
void main() {
auto maxBaseCurrency = 0.0;
auto level = GetMeta();
if (level == "level1") {
maxBaseCurrency = -1;
} else if (level == "level2") {
maxBaseCurrency = 10;
} else if (level == "level3") {
maxBaseCurrency = 1;
} else {
maxBaseCurrency = 0.5;
}
while(1) {
Sleep(1000);
auto ticker = exchange.GetTicker();
auto acc = exchange.GetAccount();
if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
// Stop execution strategy trading logic.
LogStatus(_D(), "level:", level, "Positions exceeding the usage limit of the registration code will no longer execute the strategy trading logic!");
continue;
}
// Other trading logic
// Normal output of status bar information
LogStatus(_D(), "level:", level, "The strategy is working properly! ticker data: \n", ticker);
}
}
Beispiel für die Anwendung: VerwendungMeta
die Höhe der von der Strategie betriebenen Vermögenswerte zu begrenzen.
Anwendungsszenario: müssen Kapitallimits für verschiedene Strategie Mieter.Meta
der bei der Erstellung des Registrierungscodes festgelegte Wert darf 190 Zeichen nicht überschreiten, undGetMeta()
Die Funktion unterstützt nur Live-Handel.Meta
) wird bei der Erstellung eines Strategie-Registrierungscodes, derGetMeta()
Die Funktion gibt null zurück. Sie funktioniert nicht im Backtesting System.
Für primitiveSocket
Zugang, Unterstützungtcp
, udp
, tls
, unix
Unterstützung von 4 gängigen Kommunikationsprotokollen:mqtt
, nats
, amqp
, kafka
Unterstützung für die Verbindung zu Datenbanken:sqlite3
, mysql
, postgres
, clickhouse
.
DieDial()
Ein normaler Aufruf gibt ein Verbindungsobjekt zurück, das drei Methoden hat:read
, write
undclose
. Dieread
Die Methode wird zur Ablesung der Daten verwendet.write
Daten zu senden und dieclose
Methode verwendet wird, um die Verbindung zu schließen.
Dieread
Die Methode unterstützt folgende Parameter:
ws.read()
.ws.read(2000)
eine Zeitraffer von zwei Sekunden (2000 Millisekunden) angibt.-1
bedeutet, dass die Funktion unabhängig vom Vorhandensein oder Fehlen von Nachrichten sofort zurückgibt, z. B.:ws.read(-1)
- Ich weiß.
Übergabe des Parameters-2
bedeutet, dass die Funktion sofort mit oder ohne eine Nachricht zurückgibt, aber nur die letzte Nachricht zurückgegeben wird, und die pufferte Nachricht wird entsorgt.ws.read(-2)
.read()
Beschreibung des Funktionspuffers:
Die eingehenden Daten, die durch das WebSocket-Protokoll geschoben werden, können eine Datenauflagerung verursachen, wenn das Zeitintervall zwischenread()
Diese Daten werden in dem Puffer gespeichert, der eine Datengestaltung einer Warteschlange mit maximal 2000 hat.
Szenario | Keine Parameter | Parameter: -1 | Parameter: -2 | Parameter: 2000, in Millisekunden |
---|---|---|---|---|
Daten bereits im Puffer | Sofortige Rückgabe der ältesten Daten | Sofortige Rückgabe der ältesten Daten | Sofort die neuesten Daten zurückgeben | Sofortige Rückgabe der ältesten Daten |
Keine Daten im Puffer | Zurückkehren, wenn Daten blockiert sind | Null sofort zurückgeben | Null sofort zurückgeben | Warten Sie 2000 ms, Null zurückgeben, wenn keine Daten, Null zurückgeben, wenn es Daten gibt |
Die WebSocket-Verbindung wird vom zugrunde liegenden | read() Funktion gibt die leere Zeichenfolge zurück, d.h.: |
Gegenstand
Wählen Sie (Adresse) Wählen Sie (Adresse, Zeitverzögerung)
Anfrageadresse. Anschrift wahr String Zeitraffer Sekunden, Zeitverzögerung falsche Zahl
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();
}
}
Beispiel für einen Aufruf der Funktion "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();
}
Zugriff auf die WebSocket-Ticker-Schnittstelle von 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");
}
Zugriff auf die 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");
}
Zugriff auf Huobi's WebSocket Tickerschnittstelle:
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");
}
Zugriff auf die WebSocket-Authentifizierungsoberfläche von 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
Das Verbindungsobjekt, das bei der Verbindung zu einer Datenbank durch die Funktion Dial zurückgegeben wird, hat zwei Methodenfunktionen, die einzigartig sind:
exec(sqlString)
: Wird verwendet, um SQL-Anweisungen ähnlich wie dieDBExec()
function.fd()
Diefd()
Funktion gibt einen Handler zurück (z. B. die Handlervariable ist Handler), der von anderen Threads zur Wiederverbindung verwendet wird (auch wenn das von Dial erstellte Objekt bereits durch die Ausführung desclose()
Funktion, um die Verbindung zu schließen) durch dasDial()
Funktion, zum Beispiel,Dial(handle)
Wiederverwendungsanschluss.
Das folgende ist ein Beispiel für die Dial-Funktion, die eine Verbindung zu einemsqlite3
database.Einzelheiten deraddress
Parameter, getrennt durch die|
Symbol nach der normalen Adresse:wss://ws.okx.com:8443/ws/v5/public
Wenn es welche gibt.|
Zeichen in der Parameterzeile, dann||
Der Teil danach sind einige Funktionsparameter-Einstellungen, und jeder Parameter ist mit&
Siehe auch:ss5
Proxy- und Kompressionsparameter können wie folgt zusammengestellt werden:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Funktionen, die durch den Adressparameter der Dial-Funktion unterstützt werden | Beschreibung der Parameter |
---|---|
Parameter im Zusammenhang mit der Datenkomprimierung des WebSocket-Protokolls: compress=Parameterwert | compress ist die Komprimierungsmethode, die Komprimierungsparameteroptionen sind: gzip_raw, gzip usw. Wenn die gzip-Methode nicht gzip ist, können Sie die erweiterte Methode verwenden: gzip_raw |
Parameter im Zusammenhang mit der Datenkomprimierung des WebSocket-Protokolls: Mode=Parameterwert | Modus ist der Komprimierungsmodus, Modusparameter kann dual sein, send, recv. dual ist Zwei-Wege-Komprimierung, send komprimierte Daten, empfangen komprimierte Daten. send send komprimierte Daten. recv empfangen komprimierte Daten, lokale Dekomprimierung. |
Das WebSocket-Protokoll legt die zugrunde liegenden Parameter für die automatische Wiederverbindung fest: reconnect=Parameterwert | reconnect ist, ob reconnect gesetzt wird, reconnect=true ist, ob reconnect aktiviert wird. |
Das WebSocket-Protokoll setzt die zugrunde liegenden Parameter für die automatische Wiederverbindung: interval=Parameterwert | Intervall ist das Wiederversuchsintervall, in Millisekunden, interval=10000 ist das Wiederversuchsintervall von 10 Sekunden, der Standardwert ist 1 Sekunde, wenn es nicht eingestellt ist, d. h. interval=1000. |
Das WebSocket-Protokoll legt die zugrunde liegenden Parameter für die automatische Wiederverbindung fest: Nutzlast=Parameterwert | Payload ist die Abonnementnachricht, die gesendet werden muss, wenn die WebSocket wieder verbunden wird, z. B.: payload=okokok. |
Parameter im Zusammenhang mit socks5 proxy: proxy=Parameterwert | Proxy ist die Proxy-Einstellung ss5, Parameterwertformat: socks5://name:pwd@192.168.0.1:1080, Name ist SS5-Server-Benutzername, pwd ist SS5-Server-Login-Passwort, 1080 ist SS5-Service-Port. |
DieDial()
Die Funktion wird nur für den Live-Handel unterstützt.
Bei der Verbindung mit einer Datenbank mit der Dial-Funktion wird die Verbindungszeile mit Bezug auf das Go-Sprachtreiberprojekt für jede Datenbank geschrieben.
Unterstützte Datenbanken | Antriebsprojekte | Verbindungsstring | Anmerkungen |
---|---|---|---|
Schnitt 3 | github.com/mattn/go-sqlite3 | sqlite3://Datei:test.db?Cache=shared&mode=Speicher | Diesqlite3:// Prefix zeigt an, dass eine sqlite3-Datenbank verwendet wird, Beispielruf:Dial("sqlite3://test1.db") |
MySQL | github.com/go-sql-driver/mysql | Ich bin nicht derjenige, der das Problem hat, aber ich bin derjenige, der das Problem hat.localhost:3306) / Ihre Datenbank? Charset=utf8mb4 | – |
Nachwuchs | github.com/lib/pq | Postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432 | – |
Klickhaus | github.com/ClickHouse/clickhouse-go | Sie müssen sich an die Datenbank wenden, die Sie benötigen. | – |
Bitte beachten Sie, daß diepayload
Inhalte in deraddress
Parameter enthält Zeichen=
oder andere Sonderzeichen, kann es die Parsierung deraddress
Parameter derDial
Funktion, wie zum Beispiel im folgenden Beispiel.
Beispiel für den Aufruf der privaten Schnittstelle von backPack Exchange websocket:
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}}")
}
Der folgende Anruf im Code funktioniert:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Wenn Sie es direkt inpayload
, wird es nicht richtig funktionieren, zum Beispiel:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
Derzeit unterstützt nur JavaScript die Verwendung dermqtt
, nats
, amqp
, undkafka
Der JavaScript-Strategiekode wird als Beispiel verwendet, um die Verwendung der vier Protokolle zu zeigen:mqtt
, nats
, amqp
, undkafka
:
// 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")
}
}
Ausführliche Dokumentation:Erforschung von FMZ: Praxis des Kommunikationsprotokolls zwischen Live-Handelsstrategien
Senden Sie eine Http-Anfrage.
Gibt die Antwortdaten der Anfrage zurück.JSON
String, es kann durch dieJSON.parse()
Funktion imJavaScript
Die Europäische Kommissionjson::parse()
Funktion imC++
Wenn Debug in der Optionsstruktur auf true gesetzt ist, ist der zurückgegebene Wert ein Objekt (JSON); wenn Debug auf false gesetzt ist, ist der zurückgegebene Wert eine Zeichenfolge.
String, Objekt
HttpQuery (URL) HttpQuery (URL, Optionen)
Http-Anfrage-URL. Url - Das stimmt. String Http-Anfrage-bezogene Einstellungen können beispielsweise wie folgt strukturiert werden:
{
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
Fingerabdrücke.
Die unterstützten Einstellungen umfassen folgende Optionen:
- Ich weiß nicht."chrome_103"
, "chrome_104"
, "chrome_105"
, "chrome_106"
, "chrome_107"
, "chrome_108"
, "chrome_109"
, "chrome_110"
, "chrome_111"
, "chrome_112"
, "chrome_117"
- Ich weiß.
Safari_:"safari_15_6_1"
, "safari_16_0"
, "safari_ipad_15_6"
, "safari_ios_15_5"
, "safari_ios_15_6"
, "safari_ios_16_0"
- Ich weiß.
Firefox_:"firefox_102"
, "firefox_104"
, "firefox_105"
, "firefox_106"
, "firefox_108"
, "firefox_110"
, "firefox_117"
- Ich weiß.
- Ich weiß nicht."opera_89"
, "opera_90"
, "opera_91"
- Ich weiß.
Ich habe ihn nicht gesehen."zalando_android_mobile"
, "zalando_ios_mobile"
- Ich weiß.
- Ich weiß nicht."nike_ios_mobile"
, "nike_android_mobile"
- Ich weiß.
Wolkenkratzer:"cloudscraper"
- Ich weiß.
- Ich weiß nicht."mms_ios"
- Ich weiß.
Sieh mal an:"mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
- Ich weiß.
Bestätigt:"confirmed_ios"
, "confirmed_android"
- Ich weiß.
Ok. Das ist alles."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, dieHttpQuery
Funktionsanruf gibt die vollständige Antwort zurück.false
, nur die Daten inBody
der Antwortnachricht zurückgegeben wird.profile
Das Feld kann ausgeschlossen werden.Optionen falsche Gegenstand
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);
}
Ein Beispiel für den Zugriff auf die öffentliche OKX-Ticker-API-Schnittstelle.
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/");
}
Die HttpQuery-Funktion verwendet Proxy-Einstellungen.
DieHttpQuery()
Funktion nur unterstütztJavaScript
, C++
Sprache,Python
Sprache kann dieurllib
Die Web-Library ist für den direkten Versand von HTTP-Anfragen geeignet.HttpQuery()
Die Anwendungsmöglichkeiten sind in der Regel für den Zugriff auf die Schnittstellen der Börse, die keine Signatur erfordern, wie z. B. öffentliche Schnittstellen wie Tickerinformationen.HttpQuery()
kann im Backtesting-System verwendet werden, um Anfragen (nurGET
Das Backtesting beschränkt sich auf die Verwendung von 20 Besuchen in verschiedenenURLs
, undHttpQuery()
Die Daten werden von den Besuchern im Cache gespeichert.URL
Der zweite Zugriff erfolgtHttpQuery()
Funktion gibt die zwischengespeicherten Daten zurück und es werden keine tatsächlichen Netzwerkanfragen mehr erfolgen.
Ich bin nicht derjenige, der das Problem hat.
Sendet eine HTTP-Anfrage, eine asynchrone Version desHttpQuery
function.
DieHttpQuery_Go()
Funktion gibt sofort ein gleichzeitiges Objekt zurück, das verwendet werden kann, um das Ergebnis einer HTTP-Anfrage mit demwait
Verfahren derJSON.parse()
Funktion kann verwendet werden, um dieJSON.parse()
Funktion imJavaScript
Sprachenstrategie.
Gegenstand
HttpQuery_Go (URL) HttpQuery_Go (URL, Optionen)
Http-Anfrage-URL. Url - Das stimmt. String Http-Anfrage-bezogene Einstellungen können beispielsweise wie folgt strukturiert werden:
{
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
Das ist...HttpQuery_Go
Funktionsanruf gibt die vollständige Antwort zurück.false
, nur die Daten inBody
der Antwortnachricht zurückgegeben wird.profile
Das Feld kann ausgeschlossen werden.Optionen falsche Gegenstand
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
Asynchroner Zugriff auf die öffentliche Schnittstelle der Börse für aggregierte Tickerdaten.
DieHttpQuery_Go()
Funktion nur unterstütztJavaScript
, diePython
Die Sprache kann mit derurllib
Die Web-Library ist für den direkten Versand von HTTP-Anfragen geeignet.HttpQuery_Go()
Die Anwendungsmöglichkeiten sind in der Regel in der Form von Anwendungen, die für den Zugang zu Schnittstellen verwendet werden, die keine Unterschrift auf der Börse erfordern, z. B. öffentliche Schnittstellen wie Tickerinformationen.HttpQuery_Go
Funktion nicht im Backtesting-System unterstützt.
Ich bin nicht derjenige, der das Problem hat.
Diese Funktion kodiert die Daten nach den eingegebenen Parametern.
DieEncode
Funktion gibt die Daten nach der Verschlüsselung und Verschlüsselung zurück.
String
Code (algo, inputFormat, outputFormat, Daten) Code ((algo, inputFormat, outputFormat, Daten, SchlüsselFormat, Schlüssel)
Der Parameteralgo
ist der Algorithmus, der bei der Codierung berechnet wird.raw
(Kein Algorithmus wird verwendet), das"Zeichen", algo
Unterstützt auch: algo
unterstützt auch: algo
kann als ed25519.seed
Berechnung.
etwas
wahr
String
Verwendet zur Festlegung des Datenformats derdata
DieinputFormat
Der Parameter kann als einer der folgenden Einstellungen festgelegt werden:raw
, hex
, base64
, string
. hex
kodiert, base64
und outputFormat
Der Parameter kann als einer der folgenden Einstellungen festgelegt werden:raw
, hex
, base64
, string
. hex
kodiert, base64
und data
ist die zu verarbeitende Daten.
Daten
wahr
String
Verwendet zur Festlegung des Datenformats derkey
Diekey
Der Parameter kann als einer der folgenden Einstellungen festgelegt werden:raw
, hex
, base64
, string
. hex
kodiert, base64
und key
ist der geheime Schlüssel, der fürHMAC
Der Parameterkey
ist erforderlich, wenn der Parameteralgo
ist aufsign
odersignTx
. Diekey
Parameter wird nicht fürHMAC
Verschlüsselung, wennalgo
Der Parameter ist auf
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
}
Beispiel für den Aufruf der Funktion "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);
}
Der Parameteralgo
Unterstützt auch:
DieEncode()
Die Funktion wird nur für den Live-Handel unterstützt.key
undkeyFormat
Parameter werden nicht übergeben, dannkey
Verschlüsselung wird nicht verwendet.
Holen Sie sich den Nanosekunden-Zeitstempel des aktuellen Moments.
DieUnixNano()
Die Funktion gibt den Nanosekundenzeitstempel zurück.
Zahl
UnixNano (siehe unten)
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Wenn Sie Millisekundenzeitstempel benötigen, können Sie den folgenden Code verwenden:
Ich bin nicht derjenige.
Holen Sie sich den Zeitstempel des aktuellen Moments auf der zweiten Ebene.
Gibt den Zeitstempel der zweiten Ebene zurück. Zahl
Unix()
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
Ich bin nicht derjenige, der das Problem hat.
Holen Sie sich die Systeminformationen des Geräts, wo sich der Docker befindet.
Systeminformationen. String
GetOS()
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Zum Beispiel ein Anruf an dieGetOS()
Funktion für einen Docker, der auf derMac-BetriebssystemDas Betriebssystem könnte zurückkehren:darwin/amd64
Weil Apple-Computer mehrere Hardware-Architekturen haben.darwin
ist der Name derMac-Betriebssystem system.
Berechnet den MD5-Hash des Parametersdata
.
MD5-Hashwert. String
MD5 (Daten)
Die Daten, die eine MD5-Berechnung erfordern. Daten wahr String
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
Ich rufe dieMD5("hello world")
Funktion, der Rückgabewert beträgt:5eb63bbbe01eeed093cb22bb8f5acdc3
.
Ich bin nicht derjenige.
Datenbank-Schnittstellenfunktionen
Ein Objekt, das das Ergebnis der Ausführung einesQuadratkilometerAngabe, zum Beispiel:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
Gegenstand
DBExec (sql)
QuadratkilometerAnweisungsstring. Quadratkilometer wahr String
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;"));
}
Unterstützung der Datenbank im Speicher fürDBExec
Funktionsparameter, wennQuadratkilometerBeginnt mit:
Es ist für Datenbankoperationen geeignet, die kein ständiges Speichern erfordern, zum Beispiel:
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);
}
Machen Sie einen Tisch.
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));
}
Hinzufügen, Löschen, Überprüfen und Ändern der Datensätze in der Tabelle.
Die FunktionDBExec()
kann die Live-Trading-Datenbank (SQLite-Datenbank) bedienen, indem Parameter eingegeben werden.SQLiteDas System reservierte Tabellen in der Live-Handelsdatenbank:kvdb
, cfg
, log
, profit
, chart
Sie dürfen auf diesen Tischen nicht arbeiten.TransaktionenDiese Funktionen werden nicht unterstützt und es wird nicht empfohlen, solche Operationen durchzuführen, da sie Konflikte im System verursachen können.DBExec()
Die Funktion wird nur für den Live-Handel unterstützt.
Ich bin nicht derjenige, der das Problem hat.
Erstellen Sie eine UUID.
32-Bit-UID. String
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);
}
DieUUID()
Die Funktion unterstützt nur Live-Handel.
Hören Sie auf die Ereignisse, es kommt zurück, wenn es irgendwelcheWebSocket
Lesbare Daten oder gleichzeitige Aufgaben wieexchange.Go()
, HttpQuery_Go()
, etc. sind abgeschlossen.
Wenn das zurückgegebene Objekt kein Nullwert ist, wird dieEvent
Der in der Rückgabe enthaltenen Inhalt ist der Ereignis-Trigger-Typ. Zum Beispiel die folgende Rückgabewertstruktur:
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
Gegenstand
EventLoop (siehe unten) EventLoop (Zeitrahmen)
Der Parametertimeout
ist die Einstellung der Ausfallzeit in Millisekunden.timeout
wartet, bis ein Ereignis auftritt, bevor es zurückgegeben wird, wenn es auf 0 gesetzt ist. Wenn es größer als 0 ist, setzt es das Ereignis auf einen Timeout und gibt das jüngste Ereignis sofort zurück, wenn es kleiner als 0 ist.
Zeitverzögerung
falsche
Zahl
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);
}
Der erste Anruf an dieEventLoop()
Funktion im Code initialisiert den Mechanismus für das zugehörte Ereignis, und wenn die ersteEventLoop()
Wenn ein Call nach dem Ereignis-Callback beginnt, wird es die vorherigen Ereignisse verpassen. Das zugrunde liegende System wickelt eine Warteschlange, die maximal 500 Ereignis-Callbacks speichert.EventLoop()
Wenn die Funktion nicht rechtzeitig aufgerufen wird, um sie während der Programmdurchführung zu entfernen, werden spätere Ereignisrückrufe außerhalb des 500-Cache verloren gehen.EventLoop()
Funktion beeinflussen nicht die Cache-Warteschlange des zugrunde liegenden Systems WebSocket oder die Caches von gleichzeitigen Funktionen wieexchange.Go()
. Für diese Caches ist es immer noch notwendig, die jeweiligen Methoden zu verwenden, um die Daten abzurufen.EventLoop()
Funktion für Daten, die vor demEventLoop()
Der Hauptzweck derEventLoop()
Die Funktion der Strategie-Schicht besteht darin, die Strategie-Schicht darüber zu informieren, dass neue Netzdaten vom zugrunde liegenden System empfangen wurden.EventLoop()
Funktion gibt ein Ereignis zurück, durchläuft einfach alle Datenquellen.exchange.Go()
Versuchen Sie, Daten zu erhalten.EventLoop()
Die Funktion unterstützt nur Live-Handel.
Hören Sie auf Ereignisse im Hauptthread, wenn Sie von der Hauptfunktion aufgerufen werdenmain()
. in den in derJavaScript
Sprache, diethreading.Thread()
Funktion erstellt einen Thread, der auch in der Ausführungsfunktion des Threads aufgerufen werden kann, um auf Ereignisse im aktuellen Thread zu hören.
Das bedeutet, dass wir uns nicht mehr auf die Frage konzentrieren müssen.
Die__Serve
Funktion wird verwendet, um Http-Dienst, TCP-Dienst und Websocket-Dienst (basierend auf Http-Protokoll) zu erstellen.
Gibt eine Zeichenfolge zurück, die die IP-Adresse und den Port des erstellten Dienstes aufzeichnet.127.0.0.1:8088
, [::]:8089
.
String
__Serve (ServeURI, Handler) __Serve ((serveURI, Handler,...args)
DieserveURI
Parameter wird verwendet, um das Protokoll, die IP-Adresse, den Port und andere Einstellungen der Dienstbindung zu konfigurieren, wiehttp://0.0.0.0:8088?gzip=true
, d. h.http://:8088?gzip=true
.
serveURI
Einstellung von Parametern wietcp://127.0.0.1:6666?tls=true
Sie können z. B. Zertifikate und private Schlüssel hinzufügentls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
Einstellungen von Parametern wiehttp://127.0.0.1:6666?gzip=true
; Sie können Komprimierungseinstellungen einstellen:gzip=true
- Ich weiß.
DieserveURI
Parameter wird für Https verwendet, wiehttps://127.0.0.1:6666?tls=true&gzip=true
; Sie können hinzufügencert_pem
undcert_key_pem
Parameter zum Laden des Zertifikats.ServiceURI
wahr
String
Diehandler
Der Parameter wird verwendet, um in der Routing-Verarbeitungsfunktion (Http-Protokoll), der Nachrichtenverarbeitungsfunktion (TCP-Protokoll) und der Stream-Verarbeitungsfunktion (Websocket) zu übergeben.
Die von dem Parameter übermittelte Rückruffunktionhandler
kann mehrere Parameter definieren, der erste Parameter ist das ctx-Objekt (Kontextobjekt).
Handler
wahr
Funktion
Der tatsächliche Parameter der Rückruffunktion wird als Parameter übergebenhandler
Es kann mehrere Parameter geben.arg
, zum Beispiel:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Die Parameter1
, 2
, 3
Sie ist bei der Anrufung der__Serve()
Funktion entsprechen den Parameterna
, b
, c
in der Rückruffunktion übergeben.
Arg falsche String, Zahl, bool, Objekt, Array, Funktion, Nullwert und andere vom System unterstützte Typen
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
Sie können einen Routing-Zweig in den Pfad setzen und den Implementierungscode fürWebsocket
Sie können sich auf den Mustercode in diesem Abschnitt beziehen.Die von dem Parameter übermittelte Rückruffunktionhandler
erhält einectx
Diectx
Parameter ist ein Kontextobjekt, das zur Erfassung und Schreibung von Daten mit folgenden Methoden verwendet wird:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, und die von dem Parameter übermittelte Funktion für die Rückrufverarbeitunghandler
Erträge"123"
Wann?ctx.query("num")
ist genannt.User-Agent
in den Überschriften des vorliegenden Antrags:ctx.header("User-Agent")
.GET
, POST
, usw.ctx
Kontextobjekt zum Websocket-Protokoll; Gibt einen Boolean-Wert (true) zurück, wenn der Switch erfolgreich ist, und einen Boolean-Wert (false), wenn er fehlschlägt.read
Sie können den Timeout-Parameter angeben.timeout_ms
in Millisekunden.JSON.stringify()
Das JSON-Objekt in eine Zeichenkette zu kodieren und dann zu schreiben.WebSocket
Protokoll, Sie können diese Methode verwenden, um die verschlüsselte Zeichenfolge an den Client weiterzugeben.Das ist eine sehr schwierige Aufgabe.
Die Datenstruktur ist eine KV-Tabelle, die dauerhaft in der lokalen Datenbankdatei des Dockers gespeichert wird.
Dauerhaft gespeicherte Schlüsselwertdaten ink-v
Schlüssel-Wert-Paare.
String, Zahl, bool, Objekt, Array, Nullwert
_G() _G(k) _G(k, v)
Der Parameterk
ist der Name des Schlüssels im gespeicherten Schlüssel-Wert-Paar und ist nicht groß- oder kleinbuchstabenbezogen.
k
falsche
String, Nullwert
Der Parameterv
ist der Schlüsselwert im gespeicherten Schlüssel-Wert-Paar, das alle Daten sein kann, die gespeichert werden könnenJSON
Sie ist in Serie.
v
falsche
String, Zahl, bool, Objekt, Array, Nullwert
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();
}
Eine getrennte Datenbank für jeden Live-Handel, die von der_G()
Wenn das Backtesting abgeschlossen ist, werden die Daten, die im Backtesting-System gespeichert werden, von der_G()
Wenn Sie die Funktion_G()
Funktion, um die gespeicherten Daten aufrechtzuerhalten, sollte sie entsprechend dem Speicher- und Festplattenraum der Hardwareinrichtung vernünftig verwendet werden und nicht missbraucht werden.
Bei Anrufen der_G()
Funktion in einem Live-Handel und keine Parameter übergeben werden, die_G()
Funktion gibt dieId
Der aktuelle Live-Handel._G()
Funktion, der Parameterv
wird als null übergeben, um die Löschung derk-v
Bei Aufrufen der_G()
Funktion, nur der Parameterk
wird in der Zeichenfolge übergeben, und die_G()
Funktion gibt den Schlüsselwert zurück, der dem gespeicherten Parameter entsprichtk
. Wenn Sie die_G()
Funktion, nur der Parameterk
wird in einem Nullwert übergeben, der anzeigt, dass alle Datensätze derk-v
Das Key-Value-Paar wird gelöscht.k-v
die Schlüssel-Wert-Paare wurden dauerhaft gespeichert,_G()
Funktion wird erneut aufgerufen, indem der Name des Schlüssels, der als Parameter aufrechterhalten wurde, weitergegeben wirdk
. Das neue Schlüsselwert als Parameter gebenv
Wir werden das aktualisieren.k-v
Schlüssel-Wert-Paar.
Ich bin nicht derjenige.
Konvertiert Millisekundenzeitstempel oderDate
Gegenstände zu Zeitfolgen.
Zeitstring. String
_D() Zeitstempel _BAR_ Zeitstempel, fmt)
Zeitstempel in Millisekunden oderDate
Gegenstand.
Zeitstempel
falsche
Nummer, Gegenstand
Formatierung der Zeichenkette,JavaScript
Sprache Standardformat:yyyy-MM-dd hh:mm:ss
; Python
Sprache Standardformat:%Y-%m-%d %H:%M:%S
; C++
Sprache Standardformat:%Y-%m-%d %H:%M:%S
- Ich weiß.
fmt
falsche
String
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Erhalten und drucken Sie die aktuelle Zeitfolge:
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));
}
Der Zeitstempel lautet 1574993606000, wobei der Code umgerechnet wird:
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
}
Formatierung mit dem Parameterfmt
ist fürJavaScript
, Python
, undC++
Sprachen, wie in den folgenden Beispielen gezeigt:
Gibt die aktuelle Zeitfolge zurück, ohne Parameter zu übergeben._D()
Funktion imPython
Sie müssen sich bewusst sein, dass die übergebenen Parameter Zeitstempel der zweiten Ebene sind (Zeitstempel auf Millisekundenebene in den JavaScript- und C++-Strategien, bei denen 1 Sekunde 1000 Millisekunden entspricht)._D()
Die Funktion, um eine Zeitkette mit einem lesbaren Zeitstempel im Live-Handel zu analysieren, müssen Sie auf die Zeitzone und die Zeiteinstellung des Betriebssystems, in dem sich das Docker-Programm befindet, achten._D()
Die Funktion analysiert einen Zeitstempel in eine lesbare Zeitfolge, abhängig von der Zeit des Docker
Das ist nicht nur ein Spiel, sondern auch ein Spiel.
Formatieren Sie eine Fließkomma.
Die nach der Präzisionseinstellung formatierte Zahl mit schwebender Komma. Zahl
_N() _N (Nummer) _N (Nummer, Präzision)
Die zu formatierende Zahl mit schwebender Komma.
Zahl
wahr
Zahl
Die Präzisionseinstellung für die Formatierung, der Parameterprecision
ist eine ganze Zahl, und der Parameterprecision
Standardeinstellungen 4.
Präzision
falsche
Zahl
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);
}
Zum Beispiel:_N(3.1415, 2)
wird den Wert nach3.1415
Zwei Dezimalstellen und die Funktion gibt zurück3.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);
}
Wenn Sie alle N-Zahlen links vom Dezimalpunkt auf 0 ändern müssen, können Sie es so schreiben:
Der Parameterprecision
kann eine positive oder negative ganze Zahl sein.
Ich bin nicht derjenige, der das Problem hat.
Wiederholen Sie die Funktion für die Schnittstellenfehlertoleranz.
Der Rückgabewert der Rückruffunktion bei Ausführung. Alle Typen werden vom System unterstützt, außerlogischer falscher WertundNull-Wert.
_C (((pfn) - Ich bin nicht derjenige.
Der Parameterpfn
ist eine Funktionsreferenz, die eineRückruffunktion- Ich weiß.
Pfn
wahr
Funktion
Parameter bisRückruffunktionen, kann es mehr als einen Parameter gebenarg
. Art und Anzahl der Parameterarg
Die Ergebnisse der StudieRückruffunktion- Ich weiß.
Arg
falsche
String, Zahl, bool, Objekt, Array, Funktion, alle Typen werden vom System unterstützt, z. B. Nullwerte
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);
}
Für fehlertolerante Funktionen ohne Parameter:
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);
}
Für Funktionen mit fehlertoleranten Parametern:
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
Es kann auch für die Fehlerverträglichkeit von benutzerdefinierten Funktionen verwendet werden:
Die_C()
function wird die angegebene Funktion aufrufen, bis sie erfolgreich zurückgegeben wird (die Funktion, auf die der Parameter verweistpfn
ErträgeNulloderfalscheWenn Sie angerufen werden, versuchen Sie es erneut.pfn
) Zum Beispiel_C(exchange.GetTicker)
. Das Standard-Wiederversuchsintervall beträgt 3 Sekunden, Sie können die_CDelay()
Funktion, um das Wiederholungsintervall festzulegen._CDelay(1000)
Mittel zur Änderung des Wiederversuchsintervalls der_C()
Funktion auf 1 Sekunde.
Die Fehlertoleranz kann für folgende Funktionen durchgeführt werden, jedoch nicht auf diese beschränkt:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Alle können von der_C()
Die Funktion der Fehlerverträglichkeit_C()
Die Funktion ist nicht auf die oben aufgeführte Funktion Fehlertoleranz beschränkt, der Parameterpfn
ist eine Funktionsreferenz und nicht ein Funktionsanruf.
Beachten Sie, dass es_C(exchange.GetTicker)
, nicht_C(exchange.GetTicker())
.Gibt die Anzahl der Schnittpunkte des Arrays zurückarr1
und das Arrayarr2
.
Anzahl der Querschnittsperioden des Arraysarr1
und das Arrayarr2
- Ich weiß.
Zahl
_Kreuzung ((arr1, arr2)
Elemente sind Arrays von Typnumber
- Ich weiß.
Arr1
wahr
Reihenfolge
Elemente sind Arrays von Typnumber
- Ich weiß.
Arr2
wahr
Reihenfolge
// 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));
}
Eine Datenmenge kann simuliert werden, um die _Cross ((Arr1, Arr2) -Funktion zu testen:
Wenn der Rückgabewert der_Cross()
Wenn die Funktion eine positive Zahl ist, gibt sie die Periode des Aufwärtstrends an, wenn sie eine negative Zahl ist, gibt sie die Periode des Abwärtstrends an, 0 entspricht dem aktuellen Preis.Analyse und Gebrauchsanweisung über die eingebaute Funktion.
Die FunktionJSONParse()
wird zur Parsierung verwendetJSON
strings.
JSON
Gegenstand.
Gegenstand
JSONParse (s)
JSON
Sieht aus wie eine Schnur.
s
wahr
String
function main() {
let s1 = '{"num": 8754613216564987646512354656874651651358}'
Log("JSON.parse:", JSON.parse(s1)) // JSON.parse: {"num":8.754613216564988e+39}
Log("JSONParse:", JSONParse(s1)) // JSONParse: {"num":"8754613216564987646512354656874651651358"}
let s2 = '{"num": 123}'
Log("JSON.parse:", JSON.parse(s2)) // JSON.parse: {"num":123}
Log("JSONParse:", JSONParse(s2)) // JSONParse: {"num":123}
}
import json
def main():
s1 = '{"num": 8754613216564987646512354656874651651358}'
Log("json.loads:", json.loads(s1)) # json.loads: map[num:8.754613216564987e+39]
Log("JSONParse:", JSONParse(s1)) # JSONParse: map[num:8754613216564987646512354656874651651358]
s2 = '{"num": 123}'
Log("json.loads:", json.loads(s2)) # json.loads: map[num:123]
Log("JSONParse:", JSONParse(s2)) # JSONParse: map[num:123]
void main() {
auto s1 = "{\"num\":8754613216564987646512354656874651651358}";
Log("json::parse:", json::parse(s1));
// Log("JSONParse:", JSONParse(s1)); // The function is not supported.
auto s2 = "{\"num\":123}";
Log("json::parse:", json::parse(s2));
// Log("JSONParse:", JSONParse(s2)); // The function is not supported.
}
JSON-Strings mit großen Werten können korrekt analysiert werden, und es wird große Werte als Stringtypen analysieren.JSONParse()
Funktion wird im Backtestsystem nicht unterstützt.