Trả về số phiên bản hiện tại của hệ thống.
Số phiên bản hệ thống hiện tại, chẳng hạn như:3.6
.
chuỗi
Phiên bản
function main() {
Log("version:", Version())
}
def main():
Log("version:", Version())
void main() {
Log("version:", Version());
}
Số phiên bản hệ thống là số phiên bản của chương trình docker.
Chức năng ngủ, khiến chương trình dừng lại trong một khoảng thời gian.
Giấc ngủ ((millisecond)
Cácmillisecond
tham số được sử dụng để thiết lập thời gian ngủ và số milliseconds.
millisecond
đúng
số
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");
}
Ví dụ, khi thực hiệnSleep(1000)
Nó hỗ trợ các hoạt động với thời gian ngủ dưới 1 millisecond, ví dụ như cài đặtSleep(0.1)
Nó hỗ trợ một tham số tối thiểu của0.000001
, tức là ngủ đông nanosecond, nơi 1 nanosecond bằng với1e-6
hàng triệu giây.
Khi viết các chiến lược trongPython
ngôn ngữ,Sleep(millisecond)
không được khuyến cáo sử dụng cáctime.sleep(second)
chức năng củaPython
Ừ.time
Đây là bởi vì sử dụng cáctime.sleep(second)
chức năng trong một chiến lược làm cho chương trình chiến lược chờ đợi trong một khoảng thời gian thực sự khi backtesting (không bỏ qua các chuỗi thời gian của hệ thống backtesting), vì vậy nó làm cho chiến lược để backtest rất chậm.
Xác định xem môi trường chạy của chiến lược có phải là một hệ thống backtesting không.
Chiến lược trả về một giá trị thực, ví dụ:true
khi chạy trong môi trường hệ thống backtesting. Chiến lược trả về một giá trị sai, ví dụ:false
khi chạy trong môi trường giao dịch trực tiếp.
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.");
}
}
Xác định xem môi trường chạy hiện tại là một hệ thống backtesting, được sử dụng để tương thích với sự khác biệt giữa backtesting và giao dịch trực tiếp.
Gửi email.
Một giao hàng email thành công trả về một giá trị thực sự, ví dụ:true
, và một giao hàng thất bại trả về một giá trị sai, ví dụ:false
.
bool
Mail ((smtpServer, smtpUsername, smtpPassword, mailTo, tiêu đề, phần thân)
Sử dụng để xác địnhSMTP
địa chỉ dịch vụ của người gửi email.
SMTPServer
đúng
chuỗi
Được sử dụng để chỉ định địa chỉ email của người gửi email.
smtpUsername
đúng
chuỗi
CácSMTP
mật khẩu cho hộp thư của người gửi email.
smtpPassword
đúng
chuỗi
Sử dụng để chỉ định địa chỉ email của người nhận email.
mailTo
đúng
chuỗi
Tên email.
tiêu đề
đúng
chuỗi
Thư điện tử.
cơ thể
đúng
chuỗi
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");
}
CácsmtpPassword
tham số thiết lập mật khẩu choSMTP
dịch vụ, không phải mật khẩu hộp thư.
Khi thiết lậpsmtpServer
tham số, nếu bạn cần thay đổi cổng, bạn có thể thêm số cổng trực tiếp trong tham sốsmtpServer
Ví dụ: QQ mailsmtp.qq.com:587
, có sẵn để thử nghiệm.
Nếu báo cáo lỗi:unencryped connection
, bạn cần phải sửa đổismtpServer
củaMail
định dạng tham số là:ssl://xxx.com:xxx
, ví dụ:ssl
phương phápSMTP
đối với thư từ QQ:ssl://smtp.qq.com:465
hoặcsmtp://xxx.com:xxx
.
Nó không hoạt động trong hệ thống backtesting.
{@fun/Global/Mail_Go Mail_Go}
Phiên bản không đồng bộ củaMail
function.
CácMail_Go
hàm trả về một đối tượng đồng thời ngay lập tức, và bạn có thể sử dụngwait
Một giao hàng thư thành công trả về một giá trị thực, ví dụ,true
, và một giao hàng thất bại trả về một giá trị sai, ví dụ:false
.
đối tượng
Mail_Go ((smtpServer, smtpUsername, smtpPassword, mailTo, tiêu đề, phần thân)
Nó được sử dụng để xác địnhSMTP
địa chỉ dịch vụ của người gửi email.
SMTPServer
đúng
chuỗi
Nó được sử dụng để chỉ định địa chỉ email của người gửi email.
smtpUsername
đúng
chuỗi
CácSMTP
mật khẩu cho hộp thư của người gửi email.
smtpPassword
đúng
chuỗi
Nó được sử dụng để chỉ định địa chỉ email của người nhận email.
mailTo
đúng
chuỗi
Tên email.
tiêu đề
đúng
chuỗi
Thư điện tử.
cơ thể
đúng
chuỗi
function main() {
var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
var ret1 = r1.wait()
var ret2 = r2.wait()
Log("ret1:", ret1)
Log("ret2:", ret2)
}
# Not supported.
// Not supported.
Nó không hoạt động trong hệ thống backtesting.
{@fun/Global/Mail Mail}
Lưu trữ lỗi lọc.
SetErrorFilter ((filter)
Dòng biểu thức thông thường. bộ lọc đúng chuỗi
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");
}
lọc các lỗi phổ biến.
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);
}
lọc thông báo lỗi giao diện.
Các nhật ký lỗi phù hợp với biểu thức thường này sẽ không được tải lên hệ thống nhật ký. Bạn có thể gọi nó nhiều lần (không giới hạn số lần) để đặt nhiều điều kiện lọc. Các biểu thức thường được đặt nhiều lần sẽ được tích lũy và có hiệu lực cùng một lúc. Bạn có thể đặt một chuỗi trống để đặt lại biểu thức thường được sử dụng để lọc nhật ký lỗi:SetErrorFilter("")
. Các nhật ký được lọc không còn được ghi vào tệp cơ sở dữ liệu tương ứng với ID giao dịch trực tiếp trong thư mục docker để ngăn chặn báo cáo lỗi thường xuyên từ việc phồng lên tệp cơ sở dữ liệu.
Nhận ID giao dịch trực tiếp.
Trả lại ID quá trình giao dịch trực tiếp. chuỗi
GetPid ((()
function main(){
var id = GetPid()
Log(id)
}
def main():
id = GetPid()
Log(id)
void main() {
auto id = GetPid();
Log(id);
}
Nhận được thông báo lỗi cuối cùng.
Thông báo lỗi cuối cùng. chuỗi
GetLastError()
function main(){
// Because the order number 123 does not exist, so there will be an error.
exchange.GetOrder("123")
var error = GetLastError()
Log(error)
}
def main():
exchange.GetOrder("123")
error = GetLastError()
Log(error)
void main() {
// Order ID type: TId, so you can't pass in a string, we place an order that doesn't meet the exchange specification to trigger
exchange.GetOrder(exchange.Buy(1, 1));
auto error = GetLastError();
Log(error);
}
Nó không hoạt động trong hệ thống backtesting.
Nhận lệnh tương tác chiến lược.
Định dạng của lệnh trả về làControlName:Data
. ControlName
là tên của kiểm soát, vàData
là dữ liệu được nhập vào điều khiển. Nếu điều khiển tương tác không có hộp đầu vào, hộp thả xuống và các thành phần khác (ví dụ như một điều khiển nút không có hộp đầu vào) thì định dạng lệnh được trả về làControlName
, chỉ trả về tên điều khiển.
chuỗi
GetCommand()
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);
}
}
Khám phá lệnh tương tác và sử dụngLog
chức năng để xuất lệnh tương tác khi nó được phát hiện.
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);
}
}
Ví dụ, điều khiển tương tác chiến lược thêm một điều khiển mà không có hộp đầu vào, điều khiển tương tác được đặt tên là:buy
, thông tin mô tả kiểm soát là:buy
, đó là một điều khiển nút. Tiếp tục bằng cách thêm một điều khiển với một hộp đầu vào. Điều khiển tương tác được đặt tên là:sell
và thông báo mô tả kiểm soát là:sell
, đó là một điều khiển tương tác là sự kết hợp của một nút và một hộp đầu vào. Mã tương tác được thiết kế trong chiến lược để đáp ứng các điều khiển tương tác khác nhau:
Nó không hoạt động trong hệ thống backtesting.
Nhận giá trị của Meta được viết khi tạo mã đăng ký chiến lược.
Meta
dữ liệu.
chuỗi
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);
}
}
Ví dụ kịch bản ứng dụng: Sử dụngMeta
để hạn chế số lượng tài sản được điều hành bởi chiến lược.
kịch bản ứng dụng: cần phải làm vốn giới hạn cho các nhà thuê chiến lược khác nhau.Meta
Giá trị được đặt khi tạo mã đăng ký không thể vượt quá 190 ký tự vàGetMeta()
Nếu không có siêu dữ liệu (Meta
) được đặt khi tạo mã đăng ký chiến lược,GetMeta()
hàm trả về null. Nó không hoạt động trong hệ thống backtesting.
Đối với nguyên thủySocket
tiếp cận, hỗ trợtcp
, udp
, tls
, unix
Hỗ trợ 4 giao thức truyền thông phổ biến:mqtt
, nats
, amqp
, kafka
. Hỗ trợ kết nối với cơ sở dữ liệu:sqlite3
, mysql
, postgres
, clickhouse
.
CácDial()
hàm trả về null nếu nó hết thời gian. Một cuộc gọi bình thường trả về một đối tượng kết nối có ba phương thức:read
, write
vàclose
.read
phương pháp được sử dụng để đọc dữ liệu,write
phương pháp được sử dụng để gửi dữ liệu vàclose
phương pháp được sử dụng để đóng kết nối.
Cácread
phương pháp hỗ trợ các thông số sau:
ws.read()
.ws.read(2000)
chỉ định thời gian nghỉ là hai giây (2000 millisecond).-1
có nghĩa là chức năng trả về ngay lập tức, bất kể có hoặc không có tin nhắn, ví dụ:ws.read(-1)
.
Chuyển parameter-2
có nghĩa là hàm trả về ngay lập tức với hoặc không có tin nhắn, nhưng chỉ có tin nhắn mới nhất được trả về, và tin nhắn đệm được loại bỏ. Ví dụ:ws.read(-2)
.read()
Mô tả bộ đệm chức năng:
Dữ liệu đến được đẩy bởi giao thức WebSocket có thể gây tích lũy dữ liệu nếu khoảng thời gian giữa chiến lượcread()
Dữ liệu này được lưu trữ trong bộ đệm, có cấu trúc dữ liệu của một hàng đợi với tối đa 2000.
Kịch bản | Không có tham số | Parameter: -1 | Parameter: -2 | Parameter: 2000, trong millisecond |
---|---|---|---|---|
Dữ liệu đã ở trong bộ đệm | Trả lại dữ liệu cũ nhất ngay lập tức | Trả lại dữ liệu cũ nhất ngay lập tức | Trả lại dữ liệu mới nhất ngay lập tức | Trả lại dữ liệu cũ nhất ngay lập tức |
Không có dữ liệu trong bộ đệm | Trở lại khi bị chặn dữ liệu | Trả về null ngay lập tức | Trả về null ngay lập tức | Chờ 2000 ms, trả về null nếu không có dữ liệu, trả về null nếu có dữ liệu |
Kết nối WebSocket bị ngắt kết nối hoặc kết nối lại bởi cơ sở | Read () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () |
đối tượng
Nhập số (địa chỉ) Nhập (địa chỉ, thời gian)
Địa chỉ yêu cầu. địa chỉ đúng chuỗi giây thời gian nghỉ, thời gian nghỉ sai số
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();
}
}
Ví dụ về một cuộc gọi hàm 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();
}
Để truy cập giao diện WebSocket ticker của 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");
}
Truy cập vào giao diện ticker WebSocket OKX
var ws = null
function main(){
var param = {"sub": "market.btcusdt.detail", "id": "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
while(1){
var ret = ws.read()
Log("ret:", ret)
// Respond to heartbeat packet operations
try {
var jsonRet = JSON.parse(ret)
if(typeof(jsonRet.ping) == "number") {
var strPong = JSON.stringify({"pong" : jsonRet.ping})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
}
} catch(e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("Execute the ws.close() function")
}
import json
ws = None
def main():
global ws
param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
while True:
ret = ws.read()
Log("ret:", ret)
# Respond to heartbeat packet operations
try:
jsonRet = json.loads(ret)
if "ping" in jsonRet and type(jsonRet["ping"]) == int:
strPong = json.dumps({"pong" : jsonRet["ping"]})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
except Exception as e:
Log("e:", e)
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("Execute the ws.close() function")
using namespace std;
void main() {
json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
if(ws.Valid) {
while(true) {
auto ret = ws.read();
Log("ret:", ret);
// Respond to heartbeat packet operations
try
{
auto jsonRet = json::parse(ret);
if(jsonRet["ping"].is_number()) {
json pong = R"({"pong" : 0})"_json;
pong["pong"] = jsonRet["ping"];
auto strPong = pong.dump();
ws.write(strPong);
Log("Respond to ping, send pong:", strPong, "#FF0000");
}
} catch(exception &e)
{
Log("e:", e.what());
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
// ws.close();
Log("Execute the ws.close() function");
}
Truy cập vào giao diện ticker WebSocket của 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");
}
Để truy cập giao diện xác thực WebSocket OKX
var client = null
function main() {
// client = Dial("sqlite3://:memory:") // Using an in-memory database
client = Dial("sqlite3://test1.db") // Open/connect to the database file in the docker's directory
// record handle
var sqlite3Handle = client.fd()
Log("sqlite3Handle:", sqlite3Handle)
// Querying tables in the database
var ret = client.exec("SELECT name FROM sqlite_master WHERE type='table'")
Log(ret)
}
function onexit() {
Log("Execute client.close()")
client.close()
}
// Not supported
// Not supported
Đối tượng kết nối được trả về bởi hàm Dial khi kết nối với cơ sở dữ liệu có hai hàm phương thức độc đáo cho nó:
exec(sqlString)
: Được sử dụng để thực thi lệnh SQL theo cách tương tự nhưDBExec()
function.fd()
: Cácfd()
hàm trả về một xử lý (ví dụ, biến xử lý là xử lý) để được sử dụng bởi các luồng khác để kết nối lại (ngay cả khi đối tượng được tạo bởi Dial đã được đóng bởi việc thực hiệnclose()
chức năng để đóng kết nối) bằng cách đi tay cầm vàoDial()
chức năng, ví dụ,Dial(handle)
Kết nối tái sử dụng.
Sau đây là một ví dụ về chức năng Dial kết nối với mộtsqlite3
database.Thông tin chi tiếtaddress
tham số, tách biệt với|
ký hiệu sau địa chỉ thông thường:wss://ws.okx.com:8443/ws/v5/public
Nếu có.|
ký tự trong chuỗi tham số, sau đó||
Phần sau đó là một số cài đặt tham số chức năng, và mỗi tham số được kết nối với&
Ví dụ, cácss5
Các thông số thay thế và nén có thể được đặt cùng nhau như sau:Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
Các chức năng được hỗ trợ bởi tham số địa chỉ của chức năng Dial | Mô tả tham số |
---|---|
Các tham số liên quan đến nén dữ liệu giao thức WebSocket: compress=parameter value | compress là phương pháp nén, các tùy chọn tham số nén là: gzip_raw, gzip, vv Nếu phương pháp gzip không phải là gzip tiêu chuẩn, bạn có thể sử dụng phương pháp mở rộng: gzip_raw |
Các tham số liên quan đến nén dữ liệu giao thức WebSocket: mode=parameter value | chế độ là chế độ nén, tham số chế độ có thể là kép, gửi, recv. kép là nén hai chiều, gửi dữ liệu nén, nhận dữ liệu nén. gửi là gửi dữ liệu nén. recv là nhận dữ liệu nén, giải nén cục bộ. |
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: reconnect=parameter value | reconnect là đặt reconnect, reconnect=true là bật reconnect. mặc định là không reconnect khi tham số này không được đặt. |
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: interval=parameter value | interval là khoảng thời gian thử lại, trong milliseconds, interval=10000 là khoảng thời gian thử lại 10 giây, mặc định là 1 giây khi nó không được thiết lập, tức là interval=1000. |
Giao thức WebSocket thiết lập các thông số liên quan đến tự động kết nối: payload=parameter value | payload là thông báo đăng ký cần được gửi khi WebSocket được kết nối lại, ví dụ: payload=okokok. |
Các tham số liên quan đến vớ5 proxy: proxy=giá trị tham số | proxy là cài đặt proxy ss5, định dạng giá trị tham số: socks5://name:pwd@192.168.0.1:1080, tên là tên người dùng máy chủ ss5, pwd là mật khẩu đăng nhập máy chủ ss5, 1080 là cổng dịch vụ ss5. |
CácDial()
chức năng chỉ được hỗ trợ cho giao dịch trực tiếp.
Khi kết nối với cơ sở dữ liệu bằng chức năng Dial, chuỗi kết nối được viết với tham chiếu đến dự án trình điều khiển ngôn ngữ go cho mỗi cơ sở dữ liệu.
Cơ sở dữ liệu được hỗ trợ | Các dự án thúc đẩy | Dây kết nối | Nhận xét |
---|---|---|---|
sqlite3 | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=shared&mode=memory | Cácsqlite3:// tiền tố chỉ ra rằng một cơ sở dữ liệu sqlite3 đang được sử dụng, ví dụ gọi:Dial("sqlite3://test1.db") |
MySQL | github.com/go-sql-driver/mysql | mysql://username:yourpassword@tcp(localhost:3306) / cơ sở dữ liệu của bạn?charset=utf8mb4 | – |
sau | github.com/lib/pq | postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432 | – |
clickhouse | github.com/ClickHouse/clickhouse-go | clickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase | – |
Xin lưu ý rằng khipayload
nội dung được đặt trongaddress
tham số chứa ký tự=
hoặc các ký tự đặc biệt khác, nó có thể ảnh hưởng đến việc phân tích củaaddress
tham số củaDial
chức năng, chẳng hạn như ví dụ sau.
ví dụ gọi backPack Exchange websocket giao diện riêng:
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}}")
}
Các cuộc gọi sau trong mã hoạt động tốt:
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
Nếu bạn viết nó trực tiếp vàopayload
, nó sẽ không hoạt động đúng cách, ví dụ:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
Hiện tại, chỉ có JavaScript hỗ trợ việc sử dụngmqtt
, nats
, amqp
, vàkafka
Mã chiến lược ngôn ngữ JavaScript được sử dụng như một ví dụ để hiển thị việc sử dụng bốn giao thức:mqtt
, nats
, amqp
, vàkafka
:
// 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")
}
}
Tài liệu chi tiết:Khám phá FMZ: Thực hành giao thức giao tiếp giữa các chiến lược giao dịch trực tiếp
Gửi yêu cầu HTTP.
Trả về dữ liệu phản hồi của yêu cầu.JSON
string, nó có thể được phân tích bởi cácJSON.parse()
chức năng trongJavaScript
chiến lược ngôn ngữ,json::parse()
chức năng trongC++
Nếu debug được đặt thành true trong cấu trúc tùy chọn, giá trị trả về là một đối tượng (JSON); nếu debug được đặt thành false, giá trị trả về là một chuỗi.
chuỗi, đối tượng
HttpQuery ((url) HttpQuery ((url, tùy chọn)
URL yêu cầu HTTP. url đúng chuỗi Ví dụ, cài đặt liên quan đến yêu cầu HTTP có thể được cấu trúc như sau:
{
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
dấu vân tay.
Các cài đặt được hỗ trợ bao gồm các tùy chọn sau:
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"
nhà chọc mây:"cloudscraper"
mms_:"mms_ios"
mesh_:"mesh_ios"
, "mesh_ios_1"
, "mesh_ios_2"
, "mesh_android"
, "mesh_android_1"
, "mesh_android_2"
xác nhận:"confirmed_ios"
, "confirmed_android"
Được rồi."okhttp4_android_7"
, "okhttp4_android_8"
, "okhttp4_android_9"
, "okhttp4_android_10"
, "okhttp4_android_11"
, "okhttp4_android_12"
, "okhttp4_android_13"
,true
, cácHttpQuery
function call trả về toàn bộ tin nhắn trả lời.false
, chỉ có dữ liệu trongBody
của tin nhắn trả lời được trả về.profile
trường có thể bị bỏ qua.các lựa chọn sai đối tượng
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);
}
Một ví dụ về việc truy cập giao diện API ticker công khai 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/");
}
Chức năng HttpQuery sử dụng cài đặt proxy.
CácHttpQuery()
chỉ hỗ trợ chức năngJavaScript
, C++
ngôn ngữ,Python
ngôn ngữ có thểurllib
thư viện để gửi các yêu cầu HTTP trực tiếp.HttpQuery()
chủ yếu được sử dụng để truy cập các giao diện của sàn giao dịch không yêu cầu chữ ký, chẳng hạn như giao diện công khai như thông tin ticker.HttpQuery()
có thể được sử dụng trong hệ thống backtesting để gửi yêu cầu (chỉGET
Các yêu cầu được hỗ trợ) để thu thập dữ liệu.URLs
, vàHttpQuery()
khi cùng mộtURL
được truy cập lần thứ hai,HttpQuery()
chức năng trả về dữ liệu được lưu trong bộ nhớ cache và không có yêu cầu mạng thực tế nào xảy ra.
{@fun/Global/HttpQuery_Go HttpQuery_Go}
Gửi một yêu cầu HTTP, một phiên bản không đồng bộ củaHttpQuery
function.
CácHttpQuery_Go()
hàm ngay lập tức trả về một đối tượng đồng thời có thể được sử dụng để có được kết quả của một yêu cầu HTTP sử dụngwait
phương pháp củaJSON.parse()
chức năng có thể được sử dụng để phân tích cácJSON.parse()
chức năng trongJavaScript
chiến lược ngôn ngữ
đối tượng
HttpQuery_Go ((url) HttpQuery_Go ((url, tùy chọn)
URL yêu cầu HTTP. url đúng chuỗi Ví dụ, cài đặt liên quan đến yêu cầu HTTP có thể được cấu trúc như sau:
{
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
, cái nàyHttpQuery_Go
function call trả về toàn bộ tin nhắn trả lời.false
, chỉ có dữ liệu trongBody
của tin nhắn trả lời được trả về.profile
trường có thể bị bỏ qua.các lựa chọn sai đối tượng
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
Truy cập không đồng bộ vào giao diện công khai của sàn giao dịch cho dữ liệu ticker tổng hợp.
CácHttpQuery_Go()
chỉ hỗ trợ chức năngJavaScript
, cácPython
ngôn ngữ có thể được sử dụng vớiurllib
thư viện để gửi các yêu cầu HTTP trực tiếp.HttpQuery_Go()
chủ yếu được sử dụng để truy cập các giao diện không yêu cầu chữ ký trên sàn giao dịch, chẳng hạn như giao diện công khai như thông tin ticker.HttpQuery_Go
không được hỗ trợ trong hệ thống backtesting.
{@fun/Global/HttpQuery HttpQuery}
Chức năng này mã hóa dữ liệu theo các thông số được truyền vào.
CácEncode
chức năng trả về dữ liệu sau khi mã hóa và mã hóa.
chuỗi
Mã hóa ((algo, inputFormat, outputFormat, data) Mã hóa ((algo, inputFormat, outputFormat, data, keyFormat, key)
Các thông sốalgo
là thuật toán được sử dụng trong tính toán mã hóa.raw
(không sử dụng thuật toán), "dấu hiệu", algo
cũng hỗ trợ: algo
cũng hỗ trợ: thuật toán algo
có thể được viết như ed25519.seed
tính toán.
algo
đúng
chuỗi
Sử dụng để xác định định dạng dữ liệu củadata
các tham số.inputFormat
tham số có thể được thiết lập như một trong những điều sau:raw
, hex
, base64
, string
. hex
được mã hóa, base64
được mã hóa, và outputFormat
tham số có thể được thiết lập như một trong những điều sau:raw
, hex
, base64
, string
. hex
được mã hóa, base64
được mã hóa, và data
là dữ liệu được xử lý.
dữ liệu
đúng
chuỗi
Sử dụng để xác định định dạng dữ liệu củakey
các tham số.key
tham số có thể được thiết lập như một trong những điều sau:raw
, hex
, base64
, string
. hex
được mã hóa, base64
được mã hóa, và key
là khóa bí mật được sử dụng choHMAC
mã hóa.key
được yêu cầu khi tham sốalgo
được thiết lập thànhsign
hoặcsignTx
.key
tham số không được sử dụng choHMAC
mã hóa khialgo
tham số được đặt thành
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
}
Ví dụ về gọi hàm mã hóa.
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);
}
Các thông sốalgo
cũng hỗ trợ:
CácEncode()
chức năng chỉ được hỗ trợ cho giao dịch trực tiếp.key
vàkeyFormat
các thông số không được vượt qua, sau đókey
mã hóa không được sử dụng.
Hãy lấy dấu thời gian nanosecond của khoảnh khắc hiện tại.
CácUnixNano()
hàm trả về dấu thời gian nanosecond.
số
UnixNano ((()
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
def main():
time = UnixNano()
Log(time)
void main() {
auto time = UnixNano();
Log(time);
}
Nếu bạn cần lấy dấu thời gian millisecond, bạn có thể sử dụng mã sau:
{@fun/Global/Unix Unix}
Nhận thời gian của khoảnh khắc hiện tại ở tầng hai.
Trả lại dấu thời gian cấp hai. số
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}
Nhận thông tin hệ thống của thiết bị nơi docker nằm.
Thông tin hệ thống. chuỗi
GetOS()
function main() {
Log("GetOS:", GetOS())
}
def main():
Log("GetOS:", GetOS())
void main() {
Log("GetOS:", GetOS());
}
Ví dụ, một cuộc gọi đếnGetOS()
chức năng cho một docker chạy trênMac OShệ điều hành có thể trả về:darwin/amd64
Bởi vì máy tính Apple có nhiều kiến trúc phần cứng.darwin
là tên củaMac OS system.
Tính toán MD5 hash của tham sốdata
.
Giá trị hash của MD5. chuỗi
MD5 (dữ liệu)
Dữ liệu đòi hỏi tính toán MD5. dữ liệu đúng chuỗi
function main() {
Log("MD5", MD5("hello world"))
}
def main():
Log("MD5", MD5("hello world"))
void main() {
Log("MD5", MD5("hello world"));
}
Gọi choMD5("hello world")
hàm, giá trị trả về là:5eb63bbbe01eeed093cb22bb8f5acdc3
.
{@fun/Global/Encode Encode}
Các chức năng giao diện cơ sở dữ liệu.
Một đối tượng chứa kết quả của việc thực hiện mộtsqltuyên bố, ví dụ:
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}
đối tượng
DBExec ((sql)
sqlchuỗi lệnh. sql đúng chuỗi
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;"));
}
Hỗ trợ cơ sở dữ liệu trong bộ nhớDBExec
Các thông số chức năng, nếusqltuyên bố bắt đầu với:
Nó phù hợp với các hoạt động cơ sở dữ liệu không yêu cầu lưu liên tục, ví dụ:
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);
}
Tạo một cái bàn.
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));
}
Thêm, xóa, kiểm tra và thay đổi các bản ghi trong bảng.
Chức năngDBExec()
có thể vận hành cơ sở dữ liệu giao dịch trực tiếp (SQLite cơ sở dữ liệu) bằng cách đi qua các tham số.SQLiteHệ thống lưu trữ bảng trong cơ sở dữ liệu giao dịch trực tiếp:kvdb
, cfg
, log
, profit
, chart
, không được sử dụng trên những bàn này.Giao dịchkhông được hỗ trợ và không nên thực hiện các hoạt động như vậy, có thể gây ra xung đột trong hệ thống.DBExec()
chức năng chỉ được hỗ trợ cho giao dịch trực tiếp.
{@fun/Global/_G _G}
Tạo một UUID.
32 bit UUID. chuỗi
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);
}
CácUUID()
chức năng chỉ hỗ trợ giao dịch trực tiếp.
Nghe cho các sự kiện, nó trở lại khi có bất kỳWebSocket
dữ liệu có thể đọc hoặc các nhiệm vụ đồng thời, chẳng hạn như:exchange.Go()
, HttpQuery_Go()
, v.v. được hoàn thành.
Nếu đối tượng được trả về không phải là giá trị null,Event
chứa trong nội dung trả về là loại kích hoạt sự kiện. Ví dụ: cấu trúc giá trị trả về sau:
{"Seq":1,"Event":"Exchange_GetTrades","ThreadId":0,"Index":3,"Nano":1682068771309583400}
đối tượng
EventLoop ((() EventLoop ((timeout)
Các thông sốtimeout
là thiết lập timeout, trong milliseconds.timeout
chờ cho một sự kiện xảy ra trước khi trả về nếu nó được thiết lập là 0. Nếu nó lớn hơn 0, nó đặt sự kiện để chờ đợi thời gian hết, và trả về sự kiện gần đây nhất ngay lập tức nếu nó nhỏ hơn 0.
thời gian nghỉ
sai
số
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);
}
Cuộc gọi đầu tiên đếnEventLoop()
chức năng trong mã khởi tạo cơ chế cho sự kiện nghe, và nếu đầu tiênEventLoop()
gọi bắt đầu sau khi callback sự kiện, nó sẽ bỏ lỡ các sự kiện trước đó. Hệ thống cơ bản gói một cấu trúc hàng đợi lưu trữ tối đa 500 callback sự kiện.EventLoop()
chức năng không được gọi trong thời gian để lấy chúng ra trong quá trình thực thi chương trình, sau đó callback sự kiện bên ngoài bộ nhớ cache 500 sẽ bị mất.EventLoop()
chức năng không ảnh hưởng đến hàng đợi bộ nhớ cache của hệ thống WebSocket cơ bản hoặc bộ nhớ cache của các chức năng đồng thời nhưexchange.Go()
Đối với các bộ nhớ cache này, vẫn cần phải sử dụng các phương pháp tương ứng để lấy dữ liệu.EventLoop()
chức năng cho dữ liệu đã được truy xuất trước khiEventLoop()
Mục đích chính củaEventLoop()
Các hoạt động của hệ thống mạng được xác định bởi các sự kiện.EventLoop()
function trả về một sự kiện, chỉ đi qua tất cả các nguồn dữ liệu. ví dụ, kết nối WebSocket, đối tượng được tạo ra bởiexchange.Go()
cố gắng lấy dữ liệu.EventLoop()
chức năng chỉ hỗ trợ giao dịch trực tiếp.
Nghe cho các sự kiện trong chủ đề chủ đề khi được gọi từ chức năng chínhmain()
Trong các chiến lược được viết trongJavaScript
ngôn ngữ,threading.Thread()
function tạo ra một thread, mà cũng có thể được gọi trong hàm thực thi thread
{@fun/Global/Dial Dial}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
Các__Serve
chức năng được sử dụng để tạo dịch vụ HTTP, dịch vụ TCP và dịch vụ Websocket (dựa trên giao thức HTTP).
Trả về một chuỗi ghi lại địa chỉ IP và cổng của dịch vụ được tạo. Ví dụ:127.0.0.1:8088
, [::]:8089
.
chuỗi
__Serve ((serveURI, xử lý) __Serve ((serveURI, xử lý,...args)
CácserveURI
tham số được sử dụng để cấu hình giao thức, địa chỉ IP, cổng và các thiết lập khác của việc ràng buộc dịch vụ, chẳng hạn nhưhttp://0.0.0.0:8088?gzip=true
, nghĩa là,http://:8088?gzip=true
.
serveURI
thiết lập tham số, chẳng hạn nhưtcp://127.0.0.1:6666?tls=true
; bạn có thể thêm chứng chỉ và khóa riêng, chẳng hạn nhưtls=true&cert_pem=xxxx&cert_key_pem=xxxx
.serveURI
cài đặt tham số, chẳng hạn nhưhttp://127.0.0.1:6666?gzip=true
; bạn có thể thiết lập cài đặt nén:gzip=true
.
CácserveURI
tham số được sử dụng cho HTTP, chẳng hạn nhưhttps://127.0.0.1:6666?tls=true&gzip=true
; bạn có thể thêmcert_pem
vàcert_key_pem
các tham số để tải giấy chứng nhận.serveURI
đúng
chuỗi
Cáchandler
tham số được sử dụng để truyền trong chức năng xử lý định tuyến (protocol HTTP), chức năng xử lý tin nhắn (protocol TCP), và chức năng xử lý luồng (Websocket).
Chức năng gọi lại được chuyển vào bởi tham sốhandler
có thể xác định nhiều tham số, tham số đầu tiên là đối tượng ctx ( đối tượng ngữ cảnh).
người xử lý
đúng
chức năng
Các tham số thực tế của hàm gọi lại được truyền như các tham sốhandler
Có thể có nhiều thông sốarg
Ví dụ:
__Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)
Các thông số1
, 2
, 3
qua khi gọi cho__Serve()
chức năng tương ứng với các thông sốa
, b
, c
được thông qua trong chức năng gọi lại.
arg sai chuỗi, số, bool, đối tượng, mảng, hàm, giá trị null và các loại khác được hỗ trợ bởi hệ thống
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
Dịch vụ được thực hiện dựa trên giao thức HTTP. Bạn có thể thiết lập một nhánh định tuyến trong đường dẫn và thiết kế mã thực hiện choWebsocket
Bạn có thể tham khảo mẫu mã trong phần này.Chức năng gọi lại được truyền vào bởi tham sốhandler
nhận được mộtctx
các tham số.ctx
tham số là một đối tượng ngữ cảnh được sử dụng để lấy và ghi dữ liệu, với các phương pháp sau:
HTTP/1.1
, tcp
.http://127.0.0.1:8088?num=123
, và chức năng xử lý gọi lại được truyền vào bởi các thông sốhandler
trả lại"123"
khi nàoctx.query("num")
được gọi là.User-Agent
trong tiêu đề của yêu cầu hiện tại:ctx.header("User-Agent")
.GET
, POST
, vvctx
đối tượng ngữ cảnh đến giao thức Websocket; trả về giá trị Boolean (true) nếu chuyển đổi thành công, và giá trị Boolean (false) nếu nó thất bại.read
Phương pháp này không được hỗ trợ trong giao thức HTTP thông thường. Bạn có thể chỉ định tham số timeouttimeout_ms
trong vài mili giây.JSON.stringify()
để mã hóa đối tượng JSON vào một chuỗi và sau đó viết nó.WebSocket
giao thức, bạn có thể sử dụng phương pháp này để truyền chuỗi mã hóa cho khách hàng.{@fun/Global/HttpQuery HttpQuery}, {@fun/Global/HttpQuery_Go HttpQuery_Go}
Tiếp tục lưu dữ liệu, chức năng thực hiện một chức năng từ điển toàn cầu có thể được lưu.
Dữ liệu giá trị khóa được lưu liên tục trongk-v
các cặp giá trị khóa.
chuỗi, số, bool, đối tượng, mảng, giá trị không
_G() _G(k) _G(k, v)
Các thông sốk
là tên của khóa trong cặp khóa-giá trị được lưu, và không nhạy cảm với chữ cái lớn.
k
sai
chuỗi, giá trị không
Các thông sốv
là giá trị khóa trong cặp giá trị khóa được lưu, có thể là bất kỳ dữ liệu nào có thể đượcJSON
được phân phối.
v
sai
chuỗi, số, bool, đối tượng, mảng, giá trị không
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();
}
Một cơ sở dữ liệu riêng biệt cho mỗi giao dịch trực tiếp, dữ liệu được lưu trữ bởi_G()
chức năng sẽ luôn luôn ở đó nếu chiến lược được khởi động lại hoặc docker ngừng chạy. Nếu backtesting được hoàn thành, dữ liệu được lưu trong hệ thống backtesting bởi_G()
Khi sử dụng các_G()
chức năng để duy trì dữ liệu được lưu, nó nên được sử dụng hợp lý theo bộ nhớ và không gian đĩa cứng của thiết bị phần cứng, và không nên bị lạm dụng.
Khi gọi cho_G()
chức năng trong một giao dịch trực tiếp và không có thông số được vượt qua,_G()
hàm trả vềId
của giao dịch trực tiếp hiện tại_G()
chức năng, tham sốv
được thông qua như là không để chỉ ra việc xóak-v
Khi gọi các_G()
chức năng, chỉ các thông sốk
được truyền trong chuỗi, và_G()
hàm trả về giá trị khóa tương ứng với tham số được lưuk
Khi gọi điện cho_G()
chức năng, chỉ các thông sốk
được truyền trong một giá trị null, cho thấy rằng tất cả các bản ghi củak-v
khi các cặp key-value được xóa.k-v
Các cặp key-value đã được lưu liên tục,_G()
chức năng được gọi một lần nữa, đi qua trong tên của khóa đã được lưu liên tục như là tham sốk
. Đưa vào giá trị khóa mới như một tham sốv
sẽ cập nhật rằngk-v
cặp giá trị khóa.
{@fun/Global/DBExec DBExec}
Chuyển đổi dấu thời gian millisecond hoặcDate
đối tượng với chuỗi thời gian.
Dây thời gian. chuỗi
_D() _D (đánh dấu thời gian) _D ((đũa thời gian, fmt)
Dấu thời gian millisecondDate
đối tượng.
dấu thời gian
sai
Số, mục đích
Định dạng chuỗi,JavaScript
Định dạng ngôn ngữ mặc định:yyyy-MM-dd hh:mm:ss
; Python
Định dạng ngôn ngữ mặc định:%Y-%m-%d %H:%M:%S
; C++
Định dạng ngôn ngữ mặc định:%Y-%m-%d %H:%M:%S
.
fmt
sai
chuỗi
function main(){
var time = _D()
Log(time)
}
def main():
strTime = _D()
Log(strTime)
void main() {
auto strTime = _D();
Log(strTime);
}
Nhận và in chuỗi thời gian hiện tại:
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));
}
Mẫu thời gian là 1574993606000, sử dụng chuyển đổi mã:
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
}
Định dạng bằng tham sốfmt
là khác nhau choJavaScript
, Python
, vàC++
ngôn ngữ, như được thể hiện trong các ví dụ sau:
Trả về chuỗi thời gian hiện tại mà không cần thông qua bất kỳ thông số._D()
chức năng trongPython
chiến lược, bạn cần phải nhận thức được rằng các tham số được truyền là dấu thời gian cấp hai (các dấu thời gian cấp millisecond trong các chiến lược JavaScript và C ++, nơi 1 giây bằng 1000 milliseconds)._D()
chức năng để phân tích một chuỗi thời gian với một dấu thời gian có thể đọc trong giao dịch trực tiếp, bạn cần phải chú ý đến múi giờ và thiết lập thời gian của hệ điều hành nơi chương trình docker nằm._D()
hàm phân tích dấu thời gian thành một chuỗi thời gian có thể đọc tùy thuộc vào thời gian của hệ thống docker
{@fun/Global/UnixNano UnixNano}, {@fun/Global/Unix Unix}
Định dạng một số dấu phẩy động.
Số dấu phẩy động được định dạng theo cài đặt chính xác. số
_N() _N(num) _N ((num, chính xác)
Số dấu phẩy động cần phải được định dạng.
số
đúng
số
Cài đặt độ chính xác cho định dạng, tham sốprecision
là một số nguyên, và các tham sốprecision
mặc định là 4.
độ chính xác
sai
số
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);
}
Ví dụ,_N(3.1415, 2)
sẽ xóa giá trị sau3.1415
hai vị trí thập phân và hàm trả về3.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);
}
Nếu bạn cần thay đổi tất cả các chữ số N bên trái của dấu thập phân thành 0, bạn có thể viết nó như thế này:
Các thông sốprecision
có thể là một số nguyên dương, số nguyên âm.
{@fun/Trade/exchange.SetPrecision exchange.SetPrecision}
Thử lại chức năng cho dung nạp lỗi giao diện.
Giá trị trả về của hàm callback khi nó được thực hiện. Tất cả các loại được hỗ trợ bởi hệ thống ngoại trừgiá trị sai logicvàgiá trị null.
_C (((pfn) _C ((pfn,...args)
Các thông sốpfn
là một tham chiếu chức năng, đó là mộtChức năng gọi lại.
pfn
đúng
chức năng
Các thông số đếnChức năng gọi lại, có thể có nhiều hơn một tham sốarg
Loại và số lượng các thông sốarg
phụ thuộc vào các thông số củaChức năng gọi lại.
arg
sai
chuỗi, số, bool, đối tượng, mảng, hàm, tất cả các loại được hỗ trợ bởi hệ thống, chẳng hạn như giá trị null
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);
}
Đối với các hàm dung nạp lỗi không có tham số:
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);
}
Đối với các hàm có tham số chịu lỗi:
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
Nó cũng có thể được sử dụng cho khả năng chịu lỗi của các chức năng tùy chỉnh:
Các_C()
function sẽ tiếp tục gọi hàm được chỉ định cho đến khi nó trả về thành công (chức năng được tham chiếu bởi tham sốpfn
trả lạikhônghoặcsaikhi được gọi sẽ thử gọi lạipfn
Ví dụ:_C(exchange.GetTicker)
. Khoảng thời gian thử lại mặc định là 3 giây, bạn có thể gọi_CDelay()
chức năng để thiết lập khoảng thời gian thử lại._CDelay(1000)
có nghĩa là để thay đổi khoảng thời gian thử lại của_C()
chức năng 1 giây.
Sự dung nạp lỗi có thể được thực hiện cho, nhưng không giới hạn ở, các chức năng sau:
exchange.GetTicker()
exchange.GetDepth()
exchange.GetTrades()
exchange.GetRecords()
exchange.GetAccount()
exchange.GetOrders()
exchange.GetOrder()
exchange.GetPositions()
Tất cả có thể được gọi bởi các_C()
chức năng cho dung nạp lỗi._C()
chức năng không giới hạn trong chức năng được liệt kê ở trên dung nạp lỗi, tham sốpfn
là một tham chiếu hàm hơn là một cuộc gọi hàm.
Lưu ý rằng nó_C(exchange.GetTicker)
, không_C(exchange.GetTicker())
.Trả về số lần giao nhau của mảngarr1
và mảngarr2
.
Số lần chéo của mảngarr1
và mảngarr2
.
số
_Cross ((arr1, arr2)
Các phần tử là mảng kiểunumber
.
arr1
đúng
mảng
Các phần tử là mảng kiểunumber
.
arr2
đúng
mảng
// 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));
}
Một bộ dữ liệu có thể được mô phỏng để kiểm tra hàm _Cross ((Arr1, Arr2):
Nếu giá trị trả về của_Cross()
hàm là một con số dương tính, nó chỉ ra thời gian thâm nhập tăng, nếu nó là một con số âm tính, nó chỉ ra thời gian thâm nhập giảm, 0 có nghĩa là tương tự như giá hiện tại.Phân tích và hướng dẫn sử dụng về chức năng tích hợp.
Chức năngJSONParse()
được sử dụng để phân tíchJSON
strings.
JSON
đối tượng.
đối tượng
JSONParse (s)
JSON
dây.
s
đúng
chuỗi
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.
}
Các chuỗi JSON với các giá trị lớn có thể được phân tích chính xác, và nó sẽ phân tích các giá trị lớn như các loại chuỗi.JSONParse()
chức năng không được hỗ trợ trong hệ thống backtest.