Mengembalikan nombor versi semasa sistem.
Nombor versi sistem semasa, seperti:3.6
.
senar
Versi ((()
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
Nombor versi sistem adalah nombor versi program docker.
Fungsi tidur, menyebabkan program berhenti untuk tempoh masa.
Tidur (millisecond)
Peraturanmillisecond
Parameter digunakan untuk menetapkan tempoh tidur dan bilangan milidetik.
Milisaat
betul
nombor
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");
}
Sebagai contoh, apabila melaksanakanSleep(1000)
Ia menyokong operasi dengan waktu tidur kurang daripada 1 milisaat, contohnya menetapkanSleep(0.1)
. Ia menyokong parameter minimum0.000001
, iaitu hibernasi nanosegund, di mana 1 nanosegund sama dengan1e-6
Milisaat.
Apabila menulis strategi dalamPython
Bahasa,Sleep(millisecond)
fungsi harus digunakan untuk pengundian selang, masa-ke-menunggu operasi.time.sleep(second)
fungsiPython
...time
Perpustakaan. Ini kerana menggunakantime.sleep(second)
fungsi dalam strategi membuat program strategi menunggu untuk tempoh masa sebenarnya apabila backtesting (tidak melangkau pada siri masa sistem backtesting), jadi ia menyebabkan strategi untuk backtesting sangat perlahan.
Tentukan sama ada persekitaran menjalankan strategi adalah sistem backtesting.
Strategi mengembalikan nilai sebenar, contohnya:true
apabila dijalankan dalam persekitaran sistem backtesting. Strategi mengembalikan nilai palsu, contohnya:false
apabila dijalankan dalam persekitaran perdagangan langsung.
bool
IsVirtual ((()
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.");
}
}
Tentukan sama ada persekitaran semasa adalah sistem backtesting, yang digunakan untuk serasi dengan perbezaan antara backtesting dan perdagangan langsung.
Hantar e-mel.
Penghantaran e-mel yang berjaya mengembalikan nilai sebenar, contohnya,true
, dan penghantaran gagal mengembalikan nilai palsu, contohnya,false
.
bool
Mail ((smtpServer, smtpUsername, smtpPassword, mailTo, tajuk, badan)
Digunakan untuk menentukanSMTP
alamat perkhidmatan penghantar e-mel.
smtpServer
betul
senar
Digunakan untuk menentukan alamat e-mel penghantar e-mel.
smtpNama pengguna
betul
senar
PeraturanSMTP
kata laluan untuk peti mel penghantar e-mel.
smtpPassword
betul
senar
Digunakan untuk menentukan alamat e-mel penerima e-mel.
mailTo
betul
senar
Alamat e-mel.
tajuk
betul
senar
Email badan.
badan
betul
senar
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");
}
PeraturansmtpPassword
parameter menetapkan kata laluan untukSMTP
Perkhidmatan, bukan kata laluan kotak mel.
Apabila menetapkansmtpServer
parameter, jika anda perlu menukar port, anda boleh menambah nombor port terus dalam parametersmtpServer
Contohnya: QQ mailsmtp.qq.com:587
, yang tersedia untuk ujian.
Jika kesalahan dilaporkan:unencryped connection
, anda perlu mengubahsuaismtpServer
daripadaMail
Format parameter adalah:ssl://xxx.com:xxx
, contohnya,ssl
kaedahSMTP
untuk surat QQ:ssl://smtp.qq.com:465
atausmtp://xxx.com:xxx
.
Ia tidak berfungsi dalam sistem backtesting.
{@fun/Global/Mail_Go Mail_Go}
Versi asinkronMail
function.
PeraturanMail_Go
fungsi mengembalikan objek serentak dengan serta-merta, dan anda boleh menggunakanwait
kaedah objek serentak itu untuk mendapatkan hasil penghantaran mel. Penghantaran mel yang berjaya mengembalikan nilai yang benar, contohnya,true
, dan penghantaran gagal mengembalikan nilai palsu, contohnya,false
.
objek
Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, tajuk, badan)
Ia digunakan untuk menentukanSMTP
alamat perkhidmatan penghantar e-mel.
smtpServer
betul
senar
Ia digunakan untuk menentukan alamat e-mel penghantar e-mel.
smtpNama pengguna
betul
senar
PerkhidmatanSMTP
kata laluan untuk peti mel penghantar e-mel.
smtpPassword
betul
senar
Ia digunakan untuk menentukan alamat e-mel penerima e-mel.
mailTo
betul
senar
Alamat e-mel.
tajuk
betul
senar
E-mel badan.
badan
betul
senar
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.
Ia tidak berfungsi dalam sistem backtesting.
{@fun/Global/Mail Mail}
Log ralat penapis.
SetErrorFilter ((filter)
Senar ungkapan biasa. penapis betul senar
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");
}
Menyaring kesilapan biasa.
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);
}
Menapis mesej ralat antara muka.
Log ralat yang sepadan dengan ungkapan biasa ini tidak akan dimuat naik ke sistem log. Anda boleh memanggilnya beberapa kali (tidak ada had pada bilangan kali) untuk menetapkan pelbagai syarat penapis. Ungkapan biasa yang ditetapkan beberapa kali akan terkumpul dan berkuat kuasa pada masa yang sama. Anda boleh menetapkan rentetan kosong untuk menetapkan semula ungkapan biasa yang digunakan untuk menapis log ralat:SetErrorFilter("")
. log disaring tidak lagi ditulis ke fail pangkalan data yang sepadan dengan ID perdagangan hidup dalam direktori docker untuk mengelakkan laporan ralat yang kerap dari membengkak fail pangkalan data.
Dapatkan ID proses dagangan secara langsung.
Kembalikan ID proses dagangan secara langsung. senar
GetPid ((()
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
Dapatkan mesej ralat terakhir.
Mesej ralat terakhir. senar
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);
}
Ia tidak berfungsi dalam sistem backtesting.
Dapatkan arahan strategi interaksi.
Format arahan yang dikembalikan adalahControlName:Data
. ControlName
adalah nama kawalan, danData
adalah data yang dimasukkan ke dalam kawalan. Jika kawalan interaktif tidak mempunyai kotak input, kotak drop-down dan komponen lain (contohnya kawalan butang tanpa kotak input) maka format arahan yang dikembalikan adalahControlName
, yang mengembalikan nama kawalan sahaja.
senar
DapatkanCommand()
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);
}
}
Mengesan arahan interaksi dan menggunakanLog
fungsi untuk mengeluarkan arahan interaksi apabila dikesan.
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);
}
}
Sebagai contoh, kawalan interaktif strategi menambah kawalan tanpa kotak input, kawalan interaktif dinamakan:buy
, maklumat deskripsi kawalan adalah:buy
, yang merupakan kawalan butang. Lanjutkan dengan menambah kawalan dengan kotak input. Kawalan interaktif dinamakan:sell
dan mesej penerangan kawalan adalah:sell
, yang merupakan kawalan interaktif yang merupakan gabungan butang dan kotak input. Kod interaksi direka dalam strategi untuk bertindak balas terhadap kawalan interaksi yang berbeza:
Ia tidak berfungsi dalam sistem backtesting.
Dapatkan nilai Meta ditulis apabila menjana kod pendaftaran strategi.
Meta
data.
senar
DapatkanMeta
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);
}
}
Contoh senario aplikasi: PenggunaanMeta
untuk mengehadkan jumlah aset yang dikendalikan oleh strategi.
Senario permohonan: perlu melakukan had modal untuk penyewa strategi yang berbeza.Meta
nilai yang ditetapkan apabila menjana kod pendaftaran tidak boleh melebihi 190 aksara danGetMeta()
Jika tiada metadata (Meta
) ditetapkan semasa menjana kod pendaftaran strategi,GetMeta()
fungsi mengembalikan null. Ia tidak berfungsi dalam sistem backtesting.
Untuk primitifSocket
akses, menyokongtcp
, udp
, tls
, unix
Sokong 4 protokol komunikasi popular:mqtt
, nats
, amqp
, kafka
. Sokongan untuk menyambung ke pangkalan data:sqlite3
, mysql
, postgres
, clickhouse
.
PeraturanDial()
fungsi mengembalikan null jika ia masa keluar. panggilan biasa mengembalikan objek sambungan yang mempunyai tiga kaedah:read
, write
danclose
.read
kaedah digunakan untuk membaca data,write
kaedah digunakan untuk menghantar data danclose
kaedah digunakan untuk menutup sambungan.
Peraturanread
kaedah menyokong parameter berikut:
ws.read()
.ws.read(2000)
menentukan masa lapang dua saat (2000 milidetik).-1
bermaksud bahawa fungsi mengembalikan dengan serta-merta, tanpa mengira kehadiran atau ketiadaan mesej, contohnya:ws.read(-1)
.
Memindahkan parameter-2
bermaksud bahawa fungsi kembali dengan atau tanpa mesej, tetapi hanya mesej terkini yang dikembalikan, dan mesej yang dipaparkan dibuang.ws.read(-2)
.read()
Penerangan penyangga fungsi:
Data masuk yang didorong oleh protokol WebSocket boleh menyebabkan pengumpulan data jika selang masa antara strategiread()
Panggilan fungsi terlalu lama. Data ini disimpan dalam penyangga, yang mempunyai struktur data antrian dengan maksimum 2000. Selepas 2000 melebihi, data terbaru dimasukkan ke dalam penyangga dan data tertua dibersihkan.
Senario | Tiada parameter | Parameter: -1 | Parameter: -2 | Parameter: 2000, dalam milidetik |
---|---|---|---|---|
Data yang sudah dalam penyangga | Kembalikan data tertua dengan segera | Kembalikan data tertua dengan segera | Kembalikan data terkini dengan segera | Kembalikan data tertua dengan segera |
Tiada data dalam buffer | Kembali apabila disekat ke data | Kembalikan null dengan segera | Kembalikan null dengan segera | Tunggu 2000 ms, pulangkan null jika tiada data, pulangkan null jika ada data |
Sambungan WebSocket diputuskan atau disambungkan semula oleh asas | read() fungsi mengembalikan rentetan kosong, iaitu: |
objek
Panggil (alamat) Panggil (alamat, masa lapang)
Alamat permintaan. alamat betul senar detik masa henti, masa lapang palsu nombor
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();
}
}
Contoh panggilan fungsi 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();
}
Untuk mengakses antara muka ticker WebSocket Binance:
var ws = null
function main(){
var param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
// When calling Dial function, specify reconnect=true to set reconnection mode and payload to be the message sent when reconnecting. When the WebSocket connection is disconnected, it will reconnect and send messages automatically.
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
var pingCyc = 1000 * 20
var lastPingTime = new Date().getTime()
while(true){
var nowTime = new Date().getTime()
var ret = ws.read()
Log("ret:", ret)
if(nowTime - lastPingTime > pingCyc){
var retPing = ws.write("ping")
lastPingTime = nowTime
Log("Send : ping", "#FF0000")
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("exit")
}
import json
import time
ws = None
def main():
global ws
param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
pingCyc = 1000 * 20
lastPingTime = time.time() * 1000
while True:
nowTime = time.time() * 1000
ret = ws.read()
Log("ret:", ret)
if nowTime - lastPingTime > pingCyc:
retPing = ws.write("ping")
lastPingTime = nowTime
Log("Send: ping", "#FF0000")
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("exit")
auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");
void main() {
json param = R"({
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
})"_json;
objWS.write(param.dump());
if(objWS.Valid) {
uint64_t pingCyc = 1000 * 20;
uint64_t lastPingTime = Unix() * 1000;
while(true) {
uint64_t nowTime = Unix() * 1000;
auto ret = objWS.read();
Log("ret:", ret);
if(nowTime - lastPingTime > pingCyc) {
auto retPing = objWS.write("ping");
lastPingTime = nowTime;
Log("Send: ping", "#FF0000");
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
objWS.close();
Log("exit");
}
Akses kepada 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");
}
Akses kepada 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");
}
Untuk mengakses 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
Objek sambungan yang dikembalikan oleh fungsi Dial apabila menyambung ke pangkalan data mempunyai dua fungsi kaedah yang unik kepadanya:
exec(sqlString)
: Digunakan untuk melaksanakan pernyataan SQL dengan cara yang sama denganDBExec()
function.fd()
: Pertubuhanfd()
fungsi mengembalikan pegangan (contohnya, pembolehubah pegangan adalah pegangan) untuk digunakan oleh utas lain untuk menyambung semula (walaupun objek yang dicipta oleh Dial telah ditutup dengan pelaksanaanclose()
fungsi untuk menutup sambungan) dengan melewati pemegang ke dalamDial()
fungsi, sebagai contoh,Dial(handle)
Sambungan penggunaan semula.
Berikut adalah contoh fungsi Dial yang menyambung kesqlite3
database.Perincianaddress
parameter, dipisahkan oleh|
simbol selepas alamat biasa:wss://ws.okx.com:8443/ws/v5/public
Jika ada.|
aksara dalam rentetan parameter, kemudian||
digunakan sebagai tanda pemisah. Bahagian selepas itu adalah beberapa tetapan parameter fungsi, dan setiap parameter disambungkan dengan&
contohnya,ss5
Parameter proxy dan mampatan boleh ditetapkan bersama-sama seperti berikut:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Fungsi yang disokong oleh parameter alamat fungsi Dial | Penerangan parameter |
---|---|
Parameter yang berkaitan dengan pemampatan data protokol WebSocket: compress=parameter value | memampatkan adalah kaedah mampatan, pilihan parameter mampatan adalah: gzip_raw, gzip, dan lain-lain Jika kaedah gzip bukan gzip standard, anda boleh menggunakan kaedah lanjutan: gzip_raw |
Parameter yang berkaitan dengan pemampatan data protokol WebSocket: mod=nilai parameter | mod adalah mod mampatan, parameter mod boleh menjadi dua, menghantar, recv. dual adalah mampatan dua hala, menghantar data mampat, menerima data mampat. menghantar adalah menghantar data mampat. recv adalah menerima data mampat, dekompresi tempatan. |
Protokol WebSocket menetapkan parameter yang berkaitan dengan sambungan semula automatik yang mendasari: reconnect=nilai parameter | reconnect adalah sama ada untuk menetapkan reconnect, reconnect=true adalah untuk membolehkan reconnect. lalai adalah tidak reconnect apabila parameter ini tidak ditetapkan. |
Protokol WebSocket menetapkan parameter yang berkaitan dengan auto-reconnect yang mendasari: interval=nilai parameter | interval adalah selang percubaan semula, dalam milidetik, interval=10000 adalah selang percubaan semula 10 saat, lalai adalah 1 saat apabila ia tidak ditetapkan, iaitu interval=1000. |
Protokol WebSocket menetapkan parameter yang berkaitan dengan auto-reconnect yang mendasari: payload=nilai parameter | payload adalah mesej langganan yang perlu dihantar apabila WebSocket disambungkan semula, contohnya: payload=okokok. |
Parameter yang berkaitan dengan stoking5 proxy: proxy=nilai parameter | proxy adalah persediaan proxy ss5, format nilai parameter: socks5://name:pwd@192.168.0.1:1080, nama adalah nama pengguna pelayan ss5, pwd adalah kata laluan masuk pelayan ss5, 1080 adalah port perkhidmatan ss5. |
PeraturanDial()
Fungsi hanya disokong untuk perdagangan langsung.
Apabila menyambung ke pangkalan data menggunakan fungsi Dial, rentetan sambungan ditulis dengan merujuk kepada projek pemandu bahasa go untuk setiap pangkalan data.
Pangkalan data disokong | Projek Pemacu | Tali sambungan | Catatan |
---|---|---|---|
Sqlite3 | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=shared&mode=memory | Peraturansqlite3:// awalan menunjukkan bahawa pangkalan data sqlite3 sedang digunakan, contoh panggilan:Dial("sqlite3://test1.db") |
MySQL | github.com/go-sql-driver/mysql | mysql://username:yourpassword@tcp(localhost:3306)/database anda?charset=utf8mb4 | – |
Pelancongan | github.com/lib/pq | postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432 | – |
rumah klik | github.com/ClickHouse/clickhouse-go | klikhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase | – |
Sila ambil perhatian bahawa apabilapayload
kandungan yang ditetapkan dalamaddress
parameter mengandungi aksara=
atau ciri khas lain, ia boleh menjejaskan analisisaddress
parameterDial
fungsi, seperti contoh berikut.
contoh panggilan antara muka peribadi websocket backPack Exchange:
var client = null
function main() {
// Base64-encoded public key of the key pair, i.e. the access key configured on FMZ
var base64ApiKey = "xxx"
var ts = String(new Date().getTime())
var data = "instruction=subscribe×tamp=" + ts + "&window=5000"
// Since signEd25519 returns a base64 encoding, it contains the character "="
var signature = signEd25519(data)
// The payload may contain the character "=" after being encoded by JSON
payload = {
"method": "SUBSCRIBE",
"params": ["account.orderUpdate"],
"signature": [base64ApiKey, signature, ts, "5000"]
}
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
if (!client) {
Log("Connection failed, program exited")
return
}
while (true) {
var buf = client.read()
Log(buf)
}
}
function onexit() {
client.close()
}
function signEd25519(data) {
return exchange.Encode("ed25519.seed", "raw", "base64", data, "base64", "{{secretkey}}")
}
Panggilan berikut dalam kod berfungsi dengan baik:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Jika anda menulisnya terus ke dalampayload
, ia tidak akan berfungsi dengan baik, sebagai contoh:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
Pada masa ini, hanya JavaScript menyokong penggunaanmqtt
, nats
, amqp
, dankafka
Kod strategi bahasa JavaScript digunakan sebagai contoh untuk menunjukkan penggunaan empat protokol:mqtt
, nats
, amqp
, dankafka
:
// 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")
}
}
Rujukan dokumentasi terperinci:Menjelajah FMZ: Amalan Protokol Komunikasi Antara Strategi Dagangan Langsung
Kirim permintaan HTTP.
Mengembalikan data tindak balas permintaan.JSON
string, ia boleh dianalisis olehJSON.parse()
fungsi dalamJavaScript
strategi bahasa, dan olehjson::parse()
fungsi dalamC++
Jika debug ditetapkan kepada benar dalam struktur pilihan, nilai pulangan adalah objek (JSON); jika debug ditetapkan kepada palsu, nilai pulangan adalah rentetan.
senar, objek
HttpQuery ((url) HttpQuery ((url, pilihan)
URL permintaan HTTP. url betul senar Seting yang berkaitan dengan permintaan HTTP, misalnya, boleh disusun seperti berikut:
{
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
cap jari.
Tetapan yang disokong termasuk pilihan berikut:
chrome_:"chrome_103"
, "chrome_104"
, "chrome_105"
, "chrome_106"
, "chrome_107"
, "chrome_108"
, "chrome_109"
, "chrome_110"
, "chrome_111"
, "chrome_112"
, "chrome_117"
...
Safari_:"safari_15_6_1"
, "safari_16_0"
, "safari_ipad_15_6"
, "safari_ios_15_5"
, "safari_ios_15_6"
, "safari_ios_16_0"
...
Firefox_:"firefox_102"
, "firefox_104"
, "firefox_105"
, "firefox_106"
, "firefox_108"
, "firefox_110"
, "firefox_117"
...
Opera_:"opera_89"
, "opera_90"
, "opera_91"
...
Zalando:"zalando_android_mobile"
, "zalando_ios_mobile"
...
Nike_:"nike_ios_mobile"
, "nike_android_mobile"
...
pencakar awan:"cloudscraper"
...
mms_:"mms_ios"
...
mesh_:"mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
...
Diperakui:"confirmed_ios"
, "confirmed_android"
...
ok."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, yangHttpQuery
panggilan fungsi mengembalikan mesej jawapan penuh.false
, hanya data dalamBody
daripada mesej jawapan dikembalikan.profile
medan boleh ditinggalkan.pilihan palsu objek
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);
}
Contoh mengakses antara muka API ticker awam 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/");
}
Fungsi HttpQuery menggunakan tetapan proksi.
PeraturanHttpQuery()
fungsi hanya menyokongJavaScript
, C++
bahasa,Python
bahasa boleh menggunakanurllib
perpustakaan untuk menghantar permintaan Http secara langsung.HttpQuery()
digunakan terutamanya untuk mengakses antara muka pertukaran yang tidak memerlukan tandatangan, seperti antara muka awam seperti maklumat ticker.HttpQuery()
boleh digunakan dalam sistem backtesting untuk menghantar permintaan (hanyaGET
Percubaan belakang terhad kepada menggunakan 20 lawatan keURLs
, danHttpQuery()
kunjungan akan cache data.URL
diperolehi untuk kali kedua,HttpQuery()
fungsi mengembalikan data yang disimpan dan tiada lagi permintaan rangkaian sebenar berlaku.
{@fun/Global/HttpQuery_Go HttpQuery_Go}
Menghantar permintaan HTTP, versi asynchronousHttpQuery
function.
PeraturanHttpQuery_Go()
fungsi segera mengembalikan objek serentak yang boleh digunakan untuk mendapatkan hasil permintaan Http menggunakanwait
kaedahJSON.parse()
fungsi boleh digunakan untuk menganalisisJSON.parse()
fungsi dalamJavaScript
strategi bahasa.
objek
HttpQuery_Go (url) HttpQuery_Go ((url, pilihan)
URL permintaan HTTP. url betul senar Seting yang berkaitan dengan permintaan HTTP, misalnya, boleh disusun seperti berikut:
{
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
, iniHttpQuery_Go
panggilan fungsi mengembalikan mesej jawapan penuh.false
, hanya data dalamBody
daripada mesej jawapan dikembalikan.profile
medan boleh ditinggalkan.pilihan palsu objek
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
Akses asynchronous ke antara muka awam pertukaran untuk data ticker agregat.
PeraturanHttpQuery_Go()
fungsi hanya menyokongJavaScript
, yangPython
bahasa boleh digunakan denganurllib
perpustakaan untuk menghantar permintaan Http secara langsung.HttpQuery_Go()
digunakan terutamanya untuk mengakses antara muka yang tidak memerlukan tandatangan di bursa, seperti antara muka awam seperti maklumat ticker.HttpQuery_Go
fungsi tidak disokong dalam sistem backtesting.
{@fun/Global/HttpQuery HttpQuery}
Fungsi ini mengkodkan data mengikut parameter yang dihantar.
PeraturanEncode
fungsi mengembalikan data selepas pengekodan dan penyulitan.
senar
Encode ((algo, inputFormat, outputFormat, data) Encode ((algo, inputFormat, outputFormat, data, kunciFormat, kunci)
Parameteralgo
adalah algoritma yang digunakan dalam pengiraan pengekodan. Tetapan sokongan adalah:raw
(tidak ada algoritma yang digunakan), "tanda", algo
juga menyokong: algo
juga menyokong: algo
boleh ditulis sebagai ed25519.seed
pengiraan.
sesuatu
betul
senar
Digunakan untuk menentukan format datadata
parameter.inputFormat
parameter boleh ditetapkan sebagai salah satu daripada berikut:raw
, hex
, base64
, string
. hex
dikodkan, base64
dikodkan, dan outputFormat
parameter boleh ditetapkan sebagai salah satu daripada berikut:raw
, hex
, base64
, string
. hex
dikodkan, base64
dikodkan, dan data
adalah data yang akan diproses.
data
betul
senar
Digunakan untuk menentukan format datakey
parameter.key
parameter boleh ditetapkan sebagai salah satu daripada berikut:raw
, hex
, base64
, string
. hex
dikodkan, base64
dikodkan, dan key
adalah kunci rahsia yang digunakan untukHMAC
Parameterkey
diperlukan apabila parameteralgo
ditetapkan kepadasign
atausignTx
.key
parameter tidak digunakan untukHMAC
penyulitan apabilaalgo
parameter ditetapkan kepada
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
}
Contoh panggilan fungsi 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);
}
Parameteralgo
juga menyokong:
PeraturanEncode()
fungsi hanya disokong untuk perdagangan langsung.key
dankeyFormat
parameter tidak lulus, makakey
penyulitan tidak digunakan.
Dapatkan cap masa nanodetik saat ini.
PeraturanUnixNano()
Fungsi mengembalikan cap masa nanodetik.
nombor
UnixNano ((()
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Jika anda perlu mendapatkan stempel masa milidetik, anda boleh menggunakan kod berikut:
{@fun/Global/Unix Unix}
Dapatkan cap masa saat ini di peringkat kedua.
Mengembalikan cap masa peringkat kedua. nombor
Unix ((()
function main() {
var t = Unix()
Log(t)
}
def main():
t = Unix()
Log(t)
void main() {
auto t = Unix();
Log(t);
}
{@fun/Global/UnixNano UnixNano}
Dapatkan maklumat sistem peranti di mana docker terletak.
Maklumat sistem. senar
GetOS()
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Sebagai contoh, panggilan kepadaGetOS()
fungsi untuk pelabuhan yang berjalan padaMac OSsistem operasi mungkin kembali:darwin/amd64
Kerana komputer Apple mempunyai pelbagai seni bina perkakasan.darwin
adalah namaMac OS system.
Mengira hash MD5 parameterdata
.
Nilai hash MD5. senar
MD5 (data)
Data yang memerlukan pengiraan MD5. data betul senar
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
MenghubungiMD5("hello world")
fungsi, nilai pulangan adalah:5eb63bbbe01eeed093cb22bb8f5acdc3
.
{@fun/Global/Encode Encode}
Fungsi antara muka pangkalan data.
Objek yang mengandungi hasil pelaksanaansqlpernyataan, contohnya:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
objek
DBExec ((sql)
sqlString arahan. sql betul senar
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;"));
}
Sokongan pangkalan data dalam memori, untukDBExec
parameter fungsi, jikasqlpernyataan bermula dengan:
Ia sesuai untuk operasi pangkalan data yang tidak memerlukan simpanan berterusan, contohnya:
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);
}
Buat meja.
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));
}
Tambah, hapuskan, periksa dan ubah rekod dalam jadual.
FungsiDBExec()
dapat mengendalikan pangkalan data perdagangan langsung (pangkalan data SQLite) dengan menyampaikan parameter.SQLiteSistem disediakan jadual dalam pangkalan data perdagangan langsung:kvdb
, cfg
, log
, profit
, chart
, jangan beroperasi di atas meja ini.Transaksitidak disokong dan tidak disyorkan untuk melakukan operasi tersebut, yang boleh menyebabkan konflik dalam sistem.DBExec()
Fungsi hanya disokong untuk perdagangan langsung.
{@fun/Global/_G _G}
Buat UUID.
UUID 32-bit. senar
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);
}
PeraturanUUID()
Fungsi ini hanya menyokong perdagangan langsung.
Dengarkan untuk peristiwa, ia kembali apabila ada apa-apaWebSocket
data yang boleh dibaca atau tugas serentak, seperti:exchange.Go()
, HttpQuery_Go()
, dan lain-lain telah selesai.
Jika objek yang dikembalikan bukan nilai sifar,Event
yang terkandung dalam kandungan pulangan adalah jenis pemicu peristiwa. Sebagai contoh, struktur nilai pulangan berikut:
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
objek
EventLoop ((() EventLoop (timeout)
Parametertimeout
adalah tetapan masa lapang, dalam mili saat.timeout
menanti sesuatu peristiwa berlaku sebelum kembali jika ia ditetapkan kepada 0. Jika ia lebih besar daripada 0, ia menetapkan peristiwa untuk menunggu masa lapang, dan mengembalikan peristiwa yang paling baru dengan serta-merta jika ia kurang daripada 0.
masa lapang
palsu
nombor
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);
}
Panggilan pertama kepadaEventLoop()
Fungsi dalam kod menghidupkan mekanisme untuk peristiwa yang didengar, dan jika yang pertamaEventLoop()
panggilan bermula selepas callback peristiwa, ia akan terlepas peristiwa sebelumnya. sistem yang mendasari membungkus struktur antrian yang menyimpan maksimum 500 callback peristiwa.EventLoop()
fungsi tidak dipanggil pada masa untuk mengambil mereka keluar semasa pelaksanaan program, kemudian panggilan balik acara di luar 500 cache akan hilang.EventLoop()
fungsi tidak mempengaruhi barisan cache sistem asas WebSocket atau cache fungsi serentak sepertiexchange.Go()
. Untuk cache ini, ia masih perlu menggunakan kaedah masing-masing untuk mendapatkan data.EventLoop()
fungsi untuk data yang telah diambil sebelumEventLoop()
fungsi kembali.EventLoop()
fungsi adalah untuk memaklumkan lapisan strategi bahawa data rangkaian baru telah diterima oleh sistem yang mendasari. keseluruhan strategi didorong oleh peristiwa.EventLoop()
fungsi mengembalikan peristiwa, hanya melintasi semua sumber data.exchange.Go()
cuba untuk mendapatkan data.EventLoop()
Fungsi ini hanya menyokong perdagangan langsung.
Dengarkan peristiwa dalam benang utama apabila dipanggil dari fungsi utamamain()
. Dalam strategi yang ditulis dalamJavaScript
Bahasa,threading.Thread()
fungsi mencipta thread, yang juga boleh dipanggil dalam fungsi pelaksanaan thread
{@fun/Global/Dial Dial}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
Peraturan__Serve
fungsi digunakan untuk membuat perkhidmatan Http, perkhidmatan TCP, dan perkhidmatan Websocket (berdasarkan protokol Http).
Mengembalikan rentetan yang merekodkan alamat IP dan pelabuhan perkhidmatan yang dicipta.127.0.0.1:8088
, [::]:8089
.
senar
__Serve (serveURI, pengendali) __Serve ((serveURI, pengendali,...args)
PeraturanserveURI
parameter digunakan untuk mengkonfigurasi protokol, alamat IP, pelabuhan dan tetapan lain yang mengikat perkhidmatan, sepertihttp://0.0.0.0:8088?gzip=true
, iaitu,http://:8088?gzip=true
.
serveURI
tetapan parameter, sepertitcp://127.0.0.1:6666?tls=true
; anda boleh menambah sijil dan kunci peribadi, sepertitls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
tetapan parameter, sepertihttp://127.0.0.1:6666?gzip=true
; anda boleh menetapkan tetapan mampatan:gzip=true
.
PeraturanserveURI
parameter digunakan untuk Https, sepertihttps://127.0.0.1:6666?tls=true&gzip=true
; anda boleh menambahcert_pem
dancert_key_pem
parameter untuk memuat sijil.berkhidmatURI
betul
senar
Peraturanhandler
Parameter digunakan untuk lulus dalam fungsi pemprosesan laluan (protokol HTTP), fungsi pemprosesan mesej (protokol TCP), dan fungsi pemprosesan aliran (Websocket).
Fungsi panggilan balik yang dihantar oleh parameterhandler
boleh menentukan beberapa parameter, parameter pertama adalah objek ctx (objek konteks).
pengendali
betul
fungsi
Parameter sebenar fungsi callback yang dihantar sebagai parameterhandler
Mungkin ada pelbagai parameter.arg
Contohnya:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Parameter1
, 2
, 3
telah berlalu dalam apabila memanggil__Serve()
fungsi sepadan dengan parametera
, b
, c
dilewatkan dalam fungsi panggilan balik.
arg palsu rentetan, nombor, bool, objek, susunan, fungsi, nilai sifar dan jenis lain yang disokong oleh sistem
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
Perkhidmatan ini dilaksanakan berdasarkan protokol Http. Anda boleh menetapkan cawangan penghala dalam laluan dan merancang kod pelaksanaan untukWebsocket
Anda boleh merujuk kepada contoh kod di bahagian ini.Fungsi callback yang dihantar oleh parameterhandler
menerimactx
parameter.ctx
parameter adalah objek konteks yang digunakan untuk mendapatkan dan menulis data, dengan kaedah berikut:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, dan fungsi pemprosesan panggilan balik yang dihantar oleh parameterhandler
pengembalian"123"
bila?ctx.query("num")
dipanggil.User-Agent
Dalam tajuk permintaan semasa:ctx.header("User-Agent")
.GET
, POST
, dan lain-lainctx
objek konteks kepada protokol Websocket; mengembalikan nilai Boolean (benar) jika suis berjaya, dan nilai Boolean (salah) jika gagal.read
anda boleh menentukan parameter timeouttimeout_ms
dalam milidetik.JSON.stringify()
untuk mengkod objek JSON ke dalam rentetan dan kemudian menulisnya.WebSocket
Protokol, anda boleh menggunakan kaedah ini untuk lulus rentetan dikodkan kepada pelanggan.{@fun/Global/HttpQuery HttpQuery}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
Secara berterusan menyimpan data, fungsi ini melaksanakan fungsi kamus global yang boleh disimpan. Struktur data adalah jadual KV yang disimpan secara kekal dalam fail pangkalan data tempatan docker
Data nilai kunci yang disimpan secara berterusan dalamk-v
pasangan kunci-nilai.
rentetan, nombor, bool, objek, array, nilai sifar
_G() _G(k) _G(k, v)
Parameterk
adalah nama kunci dalam pasangan kunci-nilai yang disimpan, dan tidak sensitif huruf besar.
k
palsu
rentetan, nilai sifar
Parameterv
adalah nilai kunci dalam pasangan kunci-nilai yang disimpan, yang boleh menjadi sebarang data yang bolehJSON
Dikirim secara seriali.
v
palsu
rentetan, nombor, bool, objek, array, nilai sifar
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();
}
Sebuah pangkalan data yang berasingan untuk setiap dagangan langsung, data yang disimpan oleh_G()
fungsi akan sentiasa ada jika strategi dimulakan semula atau docker berhenti berjalan. Jika backtesting selesai, data yang disimpan dalam sistem backtesting oleh_G()
Apabila menggunakan_G()
fungsi untuk mengekalkan data yang disimpan, ia harus digunakan dengan munasabah mengikut memori dan ruang cakera keras peranti perkakasan, dan tidak boleh disalahgunakan.
Apabila memanggil_G()
fungsi dalam perdagangan langsung dan tiada parameter yang lulus,_G()
fungsi mengembalikanId
Perdagangan langsung semasa._G()
fungsi, parameterv
dilewatkan sebagai null untuk menunjukkan penghapusank-v
Apabila memanggil_G()
fungsi, hanya parameterk
adalah diluluskan dalam rentetan, dan_G()
fungsi mengembalikan nilai kunci yang sepadan dengan parameter yang disimpank
. Apabila memanggil_G()
fungsi, hanya parameterk
adalah dihantar dalam nilai sifar, menunjukkan bahawa semua rekodk-v
Pasangan kunci-nilai dipadamkan.k-v
pasangan kunci-nilai telah disimpan berterusan,_G()
fungsi dipanggil lagi, lulus dalam nama kunci yang telah disimpan secara berterusan sebagai parameterk
. Menerbitkan nilai kunci baru sebagai parameterv
akan mengemas kini bahawak-v
Pasangan kunci-nilai.
{@fun/Global/DBExec DBExec}
Mengubah timestamp milidetik atauDate
objek untuk senar masa.
String masa. senar
_D() _ D (timestamp) _D ((timestamp, fmt)
Stempel masa milidetik atauDate
objek.
Stempel masa
palsu
Nombor, objek
Format rentetan,JavaScript
Format lalai bahasa:yyyy-MM-dd hh:mm:ss
; Python
Format lalai bahasa:%Y-%m-%d %H:%M:%S
; C++
Format lalai bahasa:%Y-%m-%d %H:%M:%S
.
fmt
palsu
senar
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Dapatkan dan cetak rentetan masa semasa:
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));
}
Stempel masa adalah 1574993606000, menggunakan penukaran kod:
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
}
Format dengan parameterfmt
adalah berbeza untukJavaScript
, Python
, danC++
bahasa, seperti yang ditunjukkan dalam contoh berikut:
Mengembalikan rentetan masa semasa tanpa lulus mana-mana parameter._D()
fungsi dalamPython
strategi, anda perlu sedar bahawa parameter yang diteruskan adalah timestamps peringkat kedua (timestamps tahap milidetik dalam strategi JavaScript dan C ++, di mana 1 saat sama dengan 1000 milidetik)._D()
fungsi untuk menganalisis rentetan masa dengan cap masa yang boleh dibaca dalam perdagangan langsung, anda perlu memberi perhatian kepada zon waktu dan tetapan masa sistem operasi di mana program docker terletak._D()
fungsi menganalisis stempel masa ke dalam rentetan masa yang boleh dibaca bergantung pada masa sistem docker
{@fun/Global/UnixNano UnixNano}, {@fun/Global/Unix Unix}
Formatkan nombor koma terapung.
Nombor koma terapung yang diformat mengikut tetapan ketepatan. nombor
_N() _ N (n) _N (num, ketepatan)
Nombor koma terapung yang perlu diformat.
nombor
betul
nombor
Tetapan ketepatan untuk pemformatan, parameterprecision
adalah bilangan bulat, dan parameterprecision
lalai kepada 4.
ketepatan
palsu
nombor
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);
}
Sebagai contoh,_N(3.1415, 2)
akan memadamkan nilai selepas3.1415
dua tempat perpuluhan dan fungsi kembali3.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);
}
Jika anda perlu menukar semua N digit di sebelah kiri titik perpuluhan kepada 0, anda boleh menulisnya seperti ini:
Parameterprecision
boleh menjadi bilangan bulat positif, bilangan bulat negatif.
{@fun/Trade/exchange.SetPrecision exchange.SetPrecision}
Cuba semula fungsi untuk toleransi ralat antara muka.
Nilai pulangan fungsi panggilan balik apabila dilaksanakan. Semua jenis disokong oleh sistem kecualinilai logik palsudannilai null.
_C (((pfn) _C ((pfn,...args)
Parameterpfn
adalah rujukan fungsi, yang merupakanFungsi callback.
pfn
betul
fungsi
Parameter kepadaFungsi panggilan balik, mungkin terdapat lebih daripada satu parameterarg
. Jenis dan bilangan parameterarg
bergantung kepada parameterFungsi callback.
arg
palsu
string, nombor, bool, objek, susunan, fungsi, semua jenis disokong oleh sistem, seperti nilai sifar
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);
}
Untuk fungsi toleransi ralat tanpa 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);
}
Untuk fungsi dengan parameter yang toleransi ralat:
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
Ia juga boleh digunakan untuk toleransi ralat fungsi tersuai:
Peraturan_C()
fungsi akan terus memanggil fungsi yang ditentukan sehingga ia kembali dengan berjaya (fungsi dirujuk oleh parameterpfn
pengembaliantiadaataupalsuApabila dipanggil akan cuba memanggil semulapfn
Sebagai contoh:_C(exchange.GetTicker)
. Jangkaan cubaan semula lalai adalah 3 saat, anda boleh memanggil_CDelay()
fungsi untuk menetapkan selang cubaan semula._CDelay(1000)
bermaksud untuk mengubah selang percubaan semula_C()
fungsi ke 1 saat.
Toleransi ralat boleh dilakukan untuk, tetapi tidak terhad kepada, fungsi berikut:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Semua boleh dipanggil oleh_C()
fungsi untuk toleransi ralat._C()
fungsi tidak terhad kepada toleransi kesalahan fungsi yang disenaraikan di atas, parameterpfn
adalah rujukan fungsi dan bukannya panggilan fungsi.
Perhatikan bahawa ia adalah_C(exchange.GetTicker)
, tidak_C(exchange.GetTicker())
.Mengembalikan bilangan tempoh persimpangan arrayarr1
dan susunanarr2
.
Bilangan tempoh silang arrayarr1
dan susunanarr2
.
nombor
_Silang ((arr1, arr2)
Elemen adalah pelbagai jenisnumber
.
arr1
betul
Array
Elemen adalah pelbagai jenisnumber
.
arr2
betul
Array
// 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));
}
Satu set data boleh disimulasikan untuk menguji fungsi _Cross ((Arr1, Arr2):
Jika nilai pulangan_Cross()
fungsi adalah nombor positif, ia menunjukkan tempoh penembusan ke atas, jika ia adalah nombor negatif, ia menunjukkan tempoh penembusan ke bawah, 0 bermaksud sama dengan harga semasa.Analisis dan arahan penggunaan mengenai fungsi terbina dalam _Cross.
FungsiJSONParse()
digunakan untuk menganalisisJSON
strings.
JSON
objek.
objek
JSONParse (s)
JSON
tali.
s
betul
senar
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 rentetan dengan nilai besar boleh dianalisis dengan betul, dan ia akan dianalisis nilai besar sebagai jenis rentetan.JSONParse()
fungsi tidak disokong dalam sistem backtest.