输入/搜索内容
内置函数
Global
Version
Sleep
IsVirtual
Mail
Mail_Go
SetErrorFilter
GetPid
GetLastError
GetCommand
GetMeta
Dial
HttpQuery
HttpQuery_Go
Encode
UnixNano
Unix
GetOS
MD5
DBExec
UUID
EventLoop
__Serve
_G
_D
_N
_C
_Cross
JSON.parse
JSON.stringify
SetChannelData
GetChannelData
Log
Market
Trade
Account
Futures
Threads
threading
Thread
getThread
mainThread
currentThread
Lock
Condition
Event
Dict
pending
Thread
ThreadLock
ThreadEvent
ThreadCondition
ThreadDict
TA
Talib
talib.CDL2CROWS
talib.CDL3BLACKCROWS
talib.CDL3INSIDE
talib.CDL3LINESTRIKE
talib.CDL3OUTSIDE
talib.CDL3STARSINSOUTH
talib.CDL3WHITESOLDIERS
talib.CDLABANDONEDBABY
talib.CDLADVANCEBLOCK
talib.CDLBELTHOLD
talib.CDLBREAKAWAY
talib.CDLCLOSINGMARUBOZU
talib.CDLCONCEALBABYSWALL
talib.CDLCOUNTERATTACK
talib.CDLDARKCLOUDCOVER
talib.CDLDOJI
talib.CDLDOJISTAR
talib.CDLDRAGONFLYDOJI
talib.CDLENGULFING
talib.CDLEVENINGDOJISTAR
talib.CDLEVENINGSTAR
talib.CDLGAPSIDESIDEWHITE
talib.CDLGRAVESTONEDOJI
talib.CDLHAMMER
talib.CDLHANGINGMAN
talib.CDLHARAMI
talib.CDLHARAMICROSS
talib.CDLHIGHWAVE
talib.CDLHIKKAKE
talib.CDLHIKKAKEMOD
talib.CDLHOMINGPIGEON
talib.CDLIDENTICAL3CROWS
talib.CDLINNECK
talib.CDLINVERTEDHAMMER
talib.CDLKICKING
talib.CDLKICKINGBYLENGTH
talib.CDLLADDERBOTTOM
talib.CDLLONGLEGGEDDOJI
talib.CDLLONGLINE
talib.CDLMARUBOZU
talib.CDLMATCHINGLOW
talib.CDLMATHOLD
talib.CDLMORNINGDOJISTAR
talib.CDLMORNINGSTAR
talib.CDLONNECK
talib.CDLPIERCING
talib.CDLRICKSHAWMAN
talib.CDLRISEFALL3METHODS
talib.CDLSEPARATINGLINES
talib.CDLSHOOTINGSTAR
talib.CDLSHORTLINE
talib.CDLSPINNINGTOP
talib.CDLSTALLEDPATTERN
talib.CDLSTICKSANDWICH
talib.CDLTAKURI
talib.CDLTASUKIGAP
talib.CDLTHRUSTING
talib.CDLTRISTAR
talib.CDLUNIQUE3RIVER
talib.CDLUPSIDEGAP2CROWS
talib.CDLXSIDEGAP3METHODS
talib.AD
talib.ADOSC
talib.OBV
talib.ACOS
talib.ASIN
talib.ATAN
talib.CEIL
talib.COS
talib.COSH
talib.EXP
talib.FLOOR
talib.LN
talib.LOG10
talib.SIN
talib.SINH
talib.SQRT
talib.TAN
talib.TANH
talib.MAX
talib.MAXINDEX
talib.MIN
talib.MININDEX
talib.MINMAX
talib.MINMAXINDEX
talib.SUM
talib.HT_DCPERIOD
talib.HT_DCPHASE
talib.HT_PHASOR
talib.HT_SINE
talib.HT_TRENDMODE
talib.ATR
talib.NATR
talib.TRANGE
talib.BBANDS
talib.DEMA
talib.EMA
talib.HT_TRENDLINE
talib.KAMA
talib.MA
talib.MAMA
talib.MIDPOINT
talib.MIDPRICE
talib.SAR
talib.SAREXT
talib.SMA
talib.T3
talib.TEMA
talib.TRIMA
talib.WMA
talib.LINEARREG
talib.LINEARREG_ANGLE
talib.LINEARREG_INTERCEPT
talib.LINEARREG_SLOPE
talib.STDDEV
talib.TSF
talib.VAR
talib.ADX
talib.ADXR
talib.APO
talib.AROON
talib.AROONOSC
talib.BOP
talib.CCI
talib.CMO
talib.DX
talib.MACD
talib.MACDEXT
talib.MACDFIX
talib.MFI
talib.MINUS_DI
talib.MINUS_DM
talib.MOM
talib.PLUS_DI
talib.PLUS_DM
talib.PPO
talib.ROC
talib.ROCP
talib.ROCR
talib.ROCR100
talib.RSI
talib.STOCH
talib.STOCHF
talib.STOCHRSI
talib.TRIX
talib.ULTOSC
talib.WILLR
talib.AVGPRICE
talib.MEDPRICE
talib.TYPPRICE
talib.WCLPRICE
OS
结构体
内置变量

返回系统当前版本号。

Version()

示例

javascript
function main() { Log("version:", Version()) }
python
def main(): Log("version:", Version())
c++
void main() { Log("version:", Version()); }

返回值

类型描述

string

当前系统版本号,例如:3.6

备注

系统版本号即托管者程序的版本号。

休眠函数,用于使程序暂停执行指定的时间。

Sleep(millisecond)

示例

javascript
function main() { Sleep(1000 * 10) // 等待10秒钟 Log("等待了10秒钟") }
python
def main(): Sleep(1000 * 10) Log("等待了10秒钟")
c++
void main() { Sleep(1000 * 10); Log("等待了10秒钟"); }

参数

名称类型必填描述

millisecond

number

millisecond参数用于设置休眠时长,单位为毫秒。

备注

例如执行Sleep(1000)函数时,程序将休眠1秒。支持小于1毫秒的休眠时间,例如设置Sleep(0.1)。支持的最小参数值为0.000001,即纳秒级休眠,1纳秒等于1e-6毫秒。

在使用Python语言编写策略时,对于轮询间隔、时间等待等操作应使用Sleep(millisecond)函数。不建议使用Pythontime库中的time.sleep(second)函数。因为在策略中使用time.sleep(second)函数会在回测时让策略程序实际等待相应时间(而非在回测系统的时间序列上跳过),从而导致策略回测速度极慢。

判断策略的运行环境是否为回测系统。

IsVirtual()

示例

javascript
function main() { if (IsVirtual()) { Log("当前为回测系统环境。") } else { Log("当前为实盘环境。") } }
python
def main(): if IsVirtual(): Log("当前为回测系统环境。") else: Log("当前为实盘环境。")
c++
void main() { if (IsVirtual()) { Log("当前为回测系统环境。"); } else { Log("当前为实盘环境。"); } }

返回值

类型描述

bool

策略运行在回测系统环境时返回真值,例如:true。策略运行在实盘环境时返回假值,例如:false

备注

判断当前运行环境是否为回测系统,用于兼容回测与实盘环境的差异。

发送邮件。

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)

示例

javascript
function main(){ Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body") }
python
def main(): Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
c++
void main() { Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body"); }

返回值

类型描述

bool

邮件发送成功返回true,发送失败返回false

参数

名称类型必填描述

smtpServer

string

指定邮件发送方的SMTP服务地址。

smtpUsername

string

指定邮件发送方的邮箱地址。

smtpPassword

string

邮件发送方邮箱的SMTP密码。

mailTo

string

指定邮件接收方的邮箱地址。

title

string

邮件标题。

body

string

邮件正文。

参考

备注

smtpPassword参数设置的是SMTP服务密码,而非邮箱登录密码。

设置smtpServer参数时,如需更改端口可直接在参数smtpServer中添加端口号。例如:QQ邮箱smtp.qq.com:587(该端口已测试可用)。

如果出现错误提示:unencryped connection,需要修改Mail函数的smtpServer参数格式为:ssl://xxx.com:xxx,例如QQ邮箱的SMTP SSL方式:ssl://smtp.qq.com:465smtp://xxx.com:xxx

在回测系统中不生效。

Mail函数的异步版本。

Mail_Go(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)

示例

javascript
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) }
python
# 不支持
c++
// 不支持

返回值

类型描述

object

Mail_Go函数立即返回一个并发对象,可以使用该并发对象的wait方法获取邮件发送结果。邮件发送成功返回真值(例如:true),发送失败返回假值(例如:false)。

参数

名称类型必填描述

smtpServer

string

用于指定邮件发送方的SMTP服务地址。

smtpUsername

string

用于指定邮件发送方的邮箱地址。

smtpPassword

string

邮件发送方邮箱的SMTP密码。

mailTo

string

用于指定邮件接收方的邮箱地址。

title

string

邮件标题。

body

string

邮件正文。

参考

备注

在回测系统中不起作用。

过滤错误日志。

SetErrorFilter(filters)

示例

  • 过滤常见错误。

    javascript
    function main() { SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused") }
    python
    def main(): SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
    c++
    void main() { SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused"); }
  • 过滤特定接口的错误信息。

    javascript
    function main() { // 鉴于测试代码,不使用商品期货策略一般架构,这里仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 随意查询一个不存在的订单,ID为123,故意让接口报错 var order = exchange.GetOrder("123") Log(order) // 过滤HTTP 502错误、GetOrder接口错误,设置错误过滤后,第二次调用GetOrder不再报错 SetErrorFilter("502:|GetOrder") order = exchange.GetOrder("123") Log(order) }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") order = exchange.GetOrder("123") Log(order) SetErrorFilter("502:|GetOrder") order = exchange.GetOrder("123") Log(order)
    c++
    void main() { while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); TId orderId; Order order = exchange.GetOrder(orderId); Log(order); SetErrorFilter("502:|GetOrder"); order = exchange.GetOrder(orderId); Log(order); }

参数

名称类型必填描述

filters

string

正则表达式字符串。

备注

被此正则表达式匹配的错误日志将不会上传到日志系统,可多次调用(无次数限制)设置多个过滤条件。多次设置的正则表达式会累积生效。可通过设置空字符串来重置错误日志过滤的正则表达式:SetErrorFilter("")

被过滤的日志不再写入托管者目录下对应实盘ID的数据库文件中,防止频繁报错导致数据库文件过度膨胀。

获取实盘进程ID。

GetPid()

示例

javascript
function main(){ var id = GetPid() Log(id) }
python
def main(): id = GetPid() Log(id)
c++
void main() { auto id = GetPid(); Log(id); }

返回值

类型描述

string

返回实盘进程ID。

获取最近一次的错误信息。

GetLastError()

示例

javascript
function main(){ // 鉴于测试代码,不使用商品期货策略的通用架构,这里仅判断exchange.IO("status")函数,在连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") // 因为不存在编号为123的订单,所以会产生错误 exchange.GetOrder("123") var error = GetLastError() Log(error) }
python
def main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.GetOrder("123") error = GetLastError() Log(error)
c++
void main() { while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); // 订单ID类型:TId,因此不能传入字符串,我们下一个不符合交易所规范的订单来触发错误 exchange.GetOrder(exchange.Buy(1, 1)); auto error = GetLastError(); Log(error); }

返回值

类型描述

string

最近一次的错误信息。

备注

在回测系统中不起作用。

获取策略交互命令。

GetCommand()

示例

  • 检测交互命令,并在检测到交互命令时使用Log函数输出交互命令。

    javascript
    function main(){ while(true) { var cmd = GetCommand() if (cmd) { Log(cmd) } Sleep(1000) } }
    python
    def main(): while True: cmd = GetCommand() if cmd: Log(cmd) Sleep(1000)
    c++
    void main() { while(true) { auto cmd = GetCommand(); if(cmd != "") { Log(cmd); } Sleep(1000); } }
  • 例如,在策略交互控件中添加了一个不带输入框的控件,交互控件命名为:buy,控件描述信息为:买入,这是一个按钮控件。继续添加一个带输入框的控件,交互控件名为:sell,控件描述信息为:卖出,这是一个由按钮和输入框组合而成的交互控件。

    策略中设计交互代码来响应不同的交互控件:

    javascript
    function main() { while (true) { LogStatus(_D()) var cmd = GetCommand() if (cmd) { Log("cmd:", cmd) var arr = cmd.split(":") if (arr[0] == "buy") { Log("买入,该控件不带数量") } else if (arr[0] == "sell") { Log("卖出,该控件带数量:", arr[1]) } else { Log("其它控件触发:", arr) } } Sleep(1000) } }
    python
    def main(): while True: LogStatus(_D()) cmd = GetCommand() if cmd: Log("cmd:", cmd) arr = cmd.split(":") if arr[0] == "buy": Log("买入,该控件不带数量") elif arr[0] == "sell": Log("卖出,该控件带数量:", arr[1]) else: Log("其它控件触发:", arr) Sleep(1000)
    c++
    #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("买入,该控件不带数量"); } else if (arr[0] == "sell") { Log("卖出,该控件带数量:", arr[1]); } else { Log("其它控件触发:", arr); } } Sleep(1000); } }

返回值

类型描述

string

返回的命令格式为ControlName:DataControlName是控件名称,Data是控件中输入的数据。如果交互控件没有输入框、下拉框等组件(例如:不带输入框的按钮控件),则返回的命令格式为ControlName,仅返回控件名称。

备注

在回测系统中不起作用。

获取生成策略注册码时写入的Meta值。

GetMeta()

示例

应用场景示例:使用Meta限制策略可操作的资产数量。

javascript
function main() { // 策略允许的计价币最大资产数值 var maxBaseCurrency = null // 获取创建注册码时的元数据 var level = GetMeta() // 检测Meta对应的条件 if (level == "level1") { // -1为不限制 maxBaseCurrency = -1 } else if (level == "level2") { maxBaseCurrency = 10 } else if (level == "level3") { maxBaseCurrency = 1 } else { maxBaseCurrency = 0.5 } // 鉴于测试代码,不使用商品期货策略一般架构,这里仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") while(true) { Sleep(1000) var ticker = exchange.GetTicker() // 检测资产数值 var acc = exchange.GetAccount() if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Balance + acc.FrozenBalance) { // 停止执行策略交易逻辑 LogStatus(_D(), "level:", level, "持仓超过注册码的使用限制,不再执行策略交易逻辑!") continue } // 其它交易逻辑 // 正常输出状态栏信息 LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker) } }
python
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 not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") while True: Sleep(1000) ticker = exchange.GetTicker() acc = exchange.GetAccount() if maxBaseCurrency != -1 and maxBaseCurrency < acc["Balance"] + acc["FrozenBalance"]: LogStatus(_D(), "level:", level, "持仓超过注册码的使用限制,不再执行策略交易逻辑!") continue # 其它交易逻辑 # 正常输出状态栏信息 LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker)
c++
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(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); while(true) { Sleep(1000); auto ticker = exchange.GetTicker(); auto acc = exchange.GetAccount(); if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Balance + acc.FrozenBalance) { // 停止执行策略交易逻辑 LogStatus(_D(), "level:", level, "持仓超过注册码的使用限制,不再执行策略交易逻辑!"); continue; } // 其它交易逻辑 // 正常输出状态栏信息 LogStatus(_D(), "level:", level, "策略正常运行!ticker数据:\n", ticker); } }

返回值

类型描述

string

Meta数据。

备注

应用场景:对不同的策略租用者进行资金限制。生成注册码时设置的Meta值长度不能超过190个字符,GetMeta()函数仅支持实盘。

如果生成策略注册码时未设置元数据(Meta),GetMeta()函数将返回空值。

在回测系统中不生效。

用于原始的Socket访问,支持tcpudptlsunix协议。

支持4种流行的通信协议:mqttnatsamqpkafka

支持连接数据库,支持的数据库包括:sqlite3mysqlpostgresclickhouse

Dial(address)
Dial(address, timeout)
Dial(address, options)

示例

  • Dial函数调用示例:

    javascript
    function main(){ // Dial支持tcp://、udp://、tls://、unix://协议,可添加一个参数指定超时秒数 var client = Dial("tls://www.baidu.com:443") if (client) { // write可再添加一个数字参数指定超时,write返回成功发送的字节数 client.write("GET / HTTP/1.1\nConnection: Closed\n\n") while (true) { // read可再添加一个数字参数指定超时,单位:毫秒。返回null表示错误、超时或socket已关闭 var buf = client.read() if (!buf) { break } Log(buf) } client.close() } }
    python
    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()
    c++
    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(); } }
  • Dial函数连接数据库时返回的连接对象具有2个独有的方法:

    - exec(sqlString): 用于执行SQL语句,使用方式类似于DBExec()函数。

    - fd(): fd()函数返回一个句柄(例如:句柄变量为handle),用于其他线程重连(即使Dial创建的对象已经执行close()函数关闭连接),将句柄传入Dial()函数,例如:Dial(handle)重用连接。

    以下是Dial函数连接sqlite3数据库的示例。

    javascript
    var client = null function main() { // client = Dial("sqlite3://:memory:") // 使用内存数据库 client = Dial("sqlite3://test1.db") // 打开/连接托管者所在目录的数据库文件 // 记录句柄 var sqlite3Handle = client.fd() Log("sqlite3Handle:", sqlite3Handle) // 查询数据库中的表 var ret = client.exec("SELECT name FROM sqlite_master WHERE type='table'") Log(ret) } function onexit() { Log("执行client.close()") client.close() }
    python
    // 不支持
    c++
    // 不支持

返回值

类型描述

object

如果超时,Dial()函数返回空值。正常调用时返回一个连接对象,该对象包含三个方法:readwritecloseread方法用于读取数据,write方法用于发送数据,close方法用于关闭连接。read方法支持以下参数:

  • 不传参数时,阻塞直到接收到消息后返回。例如:ws.read()
  • 传入参数时,单位为毫秒,指定消息等待超时时间。例如:ws.read(2000)指定超时时间为2秒(2000毫秒)。
  • 以下两个参数仅对WebSocket有效:
    传入参数-1时,无论是否有消息,函数都立即返回。例如:ws.read(-1)
    传入参数-2时,无论是否有消息,函数都立即返回,但只返回最新的消息,缓冲区中的其他消息将被丢弃。例如:ws.read(-2)read()函数缓冲区说明:

WebSocket协议推送的数据,如果策略中read()函数调用的时间间隔过长,可能会造成数据累积。这些数据存储在缓冲区中,缓冲区的数据结构为队列,上限为2000条。超过2000条后,最新的数据进入缓冲区,最旧的数据将被清除。

场景无参数参数:-1参数:-2参数:2000,单位是毫秒
缓冲区已有数据立即返回最旧数据立即返回最旧数据立即返回最新数据立即返回最旧数据
缓冲区无数据阻塞直到有数据时返回立即返回空值立即返回空值等待2000毫秒,无数据返回空值,有数据则返回
WebSocket连接断开或底层重连时read()函数返回空字符串,即:"",write()函数返回0。检测到该情况后,可以使用close()函数关闭连接。如果设置了自动重连,则无需关闭,系统底层会自动重连。---

参数

名称类型必填描述

address

string

请求地址。

timeout

number

超时时间(秒)。

options

object

配置选项。

备注

address参数的详细说明:在标准地址wss://xxx.xxx.xxx:10441/websocket?compress后,使用|符号作为分隔符。如果参数字符串中包含|字符,则使用||作为分隔符。分隔符后的部分为功能参数设置,各参数之间使用&字符连接。

例如,同时设置socks5代理和压缩参数时可以写作:

Dial("wss://baidu.com/stream|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")

Dial函数的address参数支持的功能参数说明
WebSocket协议数据压缩相关的参数:compress=参数值compress为压缩方式,compress参数可选gzip_raw、gzip等。如果gzip方式为非标准gzip,可以使用扩展方式:gzip_raw
WebSocket协议数据压缩相关的参数:mode=参数值mode为压缩模式,mode参数可选dual、send、recv三种。dual为双向压缩,发送和接收压缩数据。send为仅发送压缩数据。recv为仅接收压缩数据,本地进行解压缩。
WebSocket协议启用compression设置:enableCompression=true使用enableCompression=false关闭该设置,默认不启用。
WebSocket协议设置底层自动重连相关的参数:reconnect=参数值reconnect用于设置是否重连,reconnect=true为启用重连。不设置该参数时默认不重连。
WebSocket协议设置底层自动重连相关的参数:interval=参数值interval为重试时间间隔,单位为毫秒,interval=10000表示重试间隔为10秒,不设置时默认为1秒,即interval=1000。
WebSocket协议设置底层自动重连相关的参数:payload=参数值payload为WebSocket重连时需要发送的订阅消息,例如:payload=okok。
socks5代理的相关参数:proxy=参数值proxy为socks5代理设置,参数值格式:socks5://name:pwd@192.168.0.1:1080,其中name为socks5服务端用户名,pwd为socks5服务端登录密码,1080为socks5服务端口。

Dial()函数仅支持实盘环境。

使用Dial函数连接数据库时,连接字符串的编写请参考各数据库的Go语言驱动项目。

支持的数据库驱动项目连接字符串(Connection String)备注
sqlite3github.com/mattn/go-sqlite3sqlite3://file:test.db?cache=shared&mode=memorysqlite3://前缀表示使用sqlite3数据库,调用示例:Dial("sqlite3://test1.db")
mysqlgithub.com/go-sql-driver/mysqlmysql://username:yourpassword@tcp(localhost:3306)/yourdatabase?charset=utf8mb4--
postgresgithub.com/lib/pqpostgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword host=localhost port=5432--
clickhousegithub.com/ClickHouse/clickhouse-goclickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase--

目前仅JavaScript语言支持Dial函数中使用mqttnatsamqpkafka通信协议。以下为JavaScript语言策略代码示例,展示mqttnatsamqpkafka四种协议的使用方法:

javascript
// 需要先配置、部署完成各个协议的代理服务器 // 为了便于演示,主题test_topic的订阅(read操作)、发布(write操作)都在当前这个策略中进行 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] // 写数据 conn.write(name + ", time: " + _D() + ", test msg.") // 读数据 var readMsg = conn.read(1000) Log(name + " readMsg: ", readMsg, "#FF0000") } Sleep(1000) } } function onexit() { for (var i in arrConn) { arrConn[i].close() Log("关闭", arrName[i], "连接") } }

Dial函数用于访问WebSocket接口时,支持设置WSS请求头:

javascript
let options = {"headers": {"Authorization": "Bearer token123"}} let conn = Dial("wss://api.example.com/ws", options)
python
options = {"headers": {"Authorization": "Bearer token123"}} conn = Dial("wss://api.example.com/ws", options)
c++
// 暂不支持

发送HTTP请求。

HttpQuery(url)
HttpQuery(url, options)

示例

HttpQuery函数使用代理设置。

javascript
function main() { // 本次设置代理并发送http请求,无用户名,无密码,此次http请求会通过代理发送 HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/") // 本次设置代理并发送http请求,输入用户名和密码,仅HttpQuery当前调用生效,之后再次调用HttpQuery("http://www.baidu.com")这样不会使用代理 HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/") }
python
# HttpQuery不支持Python,可以使用Python的urllib2库
c++
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/"); }

返回值

类型描述

string / object

返回请求的响应数据。如果返回值为JSON字符串,JavaScript语言的策略中可以使用JSON.parse()函数解析,C++语言的策略中可以使用json::parse()函数解析。

参数options结构中如果debug设置为true,返回值为对象(JSON);如果debug设置为false,返回值为字符串。

参数

名称类型必填描述

url

string

HTTP请求的URL地址。

options

object

HTTP请求相关配置参数,可以使用以下结构:

json
{ method: "POST", body: "a=10&b=20&c=30", charset: "UTF-8", cookie: "session_id=12345; lang=en", debug: false, headers: {"TEST-HTTP-QUERY": "123"}, timeout: 1000 }
  • method: 设置请求方法(GET、POST、PUT等)。
  • body: 设置请求体内容,通常用于POST、PUT等请求。
  • cookie: 设置请求中的Cookie,用于携带身份验证信息或会话标识。
  • headers: 设置请求头信息,可指定内容类型、身份验证信息等。
  • debug: 设置为true时,此次HttpQuery函数调用返回完整的响应报文。设置为false时仅返回响应报文Body中的数据。
  • timeout: 超时设置,单位为毫秒。例如设置1000表示1秒超时。
  • charset: 支持对响应数据进行字符编码转换,例如:GB18030。支持常用编码格式。

此结构中的所有字段均为可选参数,例如可以不设置headers字段。

参考

备注

HttpQuery()函数仅支持JavaScriptC++语言,Python语言可以使用urllib库直接发送HTTP请求。
回测系统中可以使用HttpQuery()发送请求(仅支持GET请求)获取数据。
回测时限制访问不同URL的次数为20次,并且HttpQuery()访问会缓存数据,
相同的URL第二次访问时HttpQuery()函数将返回缓存数据,不再发起实际的网络请求。

发送HTTP请求,是HttpQuery函数的异步版本。

HttpQuery_Go(url)
HttpQuery_Go(url, options)

示例

HttpQuery_Go()函数使用示例:

javascript
function main() { // 创建第一个异步线程 var r1 = HttpQuery_Go("https://xxx.xxx.xxx") // https://xxx.xxx.xxx 仅为演示地址,可以是某个数据源 // 创建第二个异步线程 var r2 = HttpQuery_Go("https://xxx.xxx.xxx") // 获取第一个异步线程调用的返回值 var tickers1 = r1.wait() // 获取第二个异步线程调用的返回值 var tickers2 = r2.wait() // 打印结果 Log("tickers1:", tickers1) Log("tickers2:", tickers2) }
python
# 不支持
c++
// 不支持

返回值

类型描述

object

HttpQuery_Go()函数立即返回一个并发对象,可以使用该并发对象的wait方法获取HTTP请求的结果。
JavaScript语言的策略中可以使用JSON.parse()函数解析返回的数据。

参数

名称类型必填描述

url

string

HTTP请求的URL地址。

options

object

HTTP请求相关配置参数,可以使用以下结构:

json
{ method: "POST", body: "a=10&b=20&c=30", charset: "UTF-8", cookie: "session_id=12345; lang=en", debug: false, headers: {"TEST-HTTP-QUERY": "123"}, timeout: 1000 }
  • debug:设置为true时,此次HttpQuery_Go函数调用返回完整的响应报文。设置为false时仅返回响应报文Body中的数据。
  • timeout:超时设置,设置1000表示1秒超时。

此结构中的所有字段均为可选字段,例如可以不设置headers字段。
HttpQuery_Go函数的options参数与HttpQuery函数的options参数保持一致。

参考

备注

HttpQuery_Go()函数仅支持JavaScript语言,Python语言可以使用urllib库直接发送HTTP请求。
HttpQuery_Go()主要用于访问交易所无需签名的接口,例如行情信息等公共接口。回测系统不支持HttpQuery_Go函数。

该函数根据传入的参数对数据进行编码。

Encode(algo, inputFormat, outputFormat, data)
Encode(algo, inputFormat, outputFormat, data, keyFormat, key)

示例

  • Encode函数调用示例。

    javascript
    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 }
    python
    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
    c++
    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 }
  • 参数 algo 还支持以下值:"text.encoder.utf8"、"text.decoder.utf8"、"text.encoder.gbk"、"text.decoder.gbk",用于对字符串进行编码和解码。

    javascript
    function main(){ var ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好") // e4bda0e5a5bd Log(ret1) var ret2 = Encode("text.decoder.utf8", "hex", "string", ret1) Log(ret2) var ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好") // c4e3bac3 Log(ret3) var ret4 = Encode("text.decoder.gbk", "hex", "string", ret3) Log(ret4) }
    python
    def main(): ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好", "", "") # e4bda0e5a5bd Log(ret1) ret2 = Encode("text.decoder.utf8", "hex", "string", ret1, "", "") Log(ret2) ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好", "", "") # c4e3bac3 Log(ret3) ret4 = Encode("text.decoder.gbk", "hex", "string", ret3, "", "")
    c++
    void main(){ auto ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好"); // e4bda0e5a5bd Log(ret1); auto ret2 = Encode("text.decoder.utf8", "hex", "string", ret1); Log(ret2); auto ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好"); // c4e3bac3 Log(ret3); auto ret4 = Encode("text.decoder.gbk", "hex", "string", ret3); Log(ret4); }

返回值

类型描述

string

Encode函数返回编码、加密后的数据。

参数

名称类型必填描述

algo

string

参数algo指定编码计算时使用的算法。

支持的算法包括:"raw"(不使用算法)、"sign"、"signTx"、"md4"、"md5"、"sha256"、"sha512"、"sha1"、"keccak256"、"sha3.224"、"sha3.256"、"sha3.384"、"sha3.512"、"sha3.keccak256"、"sha3.keccak512"、"sha512.384"、"sha512.256"、"sha512.224"、"ripemd160"、"blake2b.256"、"blake2b.512"、"blake2s.128"、"blake2s.256"。

参数algo还支持文本编解码:"text.encoder.utf8"、"text.decoder.utf8"、"text.encoder.gbk"、"text.decoder.gbk",用于字符串的编码和解码。

参数algo还支持"ed25519"算法。可以使用不同的哈希算法,例如:"ed25519.md5"、"ed25519.sha512"等。同时支持ed25519.seed计算。

inputFormat

string

指定data参数的数据格式。inputFormat参数可设置为:"raw"、"hex"、"base64"、"string"之一。"raw"表示原始数据,"hex"表示hex编码,"base64"表示base64编码,"string"表示字符串。

outputFormat

string

指定输出的数据格式。outputFormat参数可设置为:"raw"、"hex"、"base64"、"string"之一。"raw"表示原始数据,"hex"表示hex编码,"base64"表示base64编码,"string"表示字符串。

data

string

参数data为需要处理的数据。

keyFormat

string

指定key参数的数据格式。keyFormat参数可设置为:"raw"、"hex"、"base64"、"string"之一。"raw"表示原始数据,"hex"表示hex编码,"base64"表示base64编码,"string"表示字符串。

key

string

参数keyHMAC加密时使用的密钥。

当参数algo设置为"sign"或"signTx"时,需要提供key参数。

当参数algo设置为"raw"时,不会使用key参数进行HMAC加密(因为HMAC加密必须指定算法)。

备注

Encode()函数仅支持实盘。如果不传入keykeyFormat参数,则不使用密钥加密。

获取当前时刻的纳秒级时间戳。

UnixNano()

示例

如需获取毫秒级时间戳,可使用以下代码:

javascript
function main() { var time = UnixNano() / 1000000 Log(_N(time, 0)) }
python
def main(): time = UnixNano() Log(time)
c++
void main() { auto time = UnixNano(); Log(time); }

返回值

类型描述

number

UnixNano()函数返回纳秒级时间戳。

参考

获取当前时刻的秒级时间戳。

Unix()

示例

javascript
function main() { var t = Unix() Log(t) }
python
def main(): t = Unix() Log(t)
c++
void main() { auto t = Unix(); Log(t); }

返回值

类型描述

number

返回秒级时间戳。

参考

获取托管者所在设备的操作系统信息。

GetOS()

示例

javascript
function main() { Log("GetOS:", GetOS()) }
python
def main(): Log("GetOS:", GetOS())
c++
void main() { Log("GetOS:", GetOS()); }

返回值

类型描述

string

操作系统信息字符串。

备注

例如,在Mac OS操作系统下运行的托管者,调用GetOS()函数可能返回:darwin/amd64。这是因为苹果电脑有多种硬件架构。darwinMac OS系统的内核名称。

计算参数data的MD5哈希值。

MD5(data)

示例

javascript
function main() { Log("MD5", MD5("hello world")) }
python
def main(): Log("MD5", MD5("hello world"))
c++
void main() { Log("MD5", MD5("hello world")); }

返回值

类型描述

string

MD5哈希值。

参数

名称类型必填描述

data

string

需要进行MD5哈希计算的数据。

参考

备注

调用MD5("hello world")函数,返回值为:5eb63bbbe01eeed093cb22bb8f5acdc3

数据库接口函数。

DBExec(sql)

示例

  • 支持内存数据库。对于DBExec函数的参数,如果sql语句以:开头,则在内存数据库中执行操作,无需写入文件,执行速度更快。

    适用于无需持久化保存的数据库操作场景,例如:

    javascript
    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) // 增加一条数据 Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")) // 查询数据 Log(DBExec(":SELECT * FROM TEST_TABLE;")) }
    python
    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) # 增加一条数据 Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")) # 查询数据 Log(DBExec(":SELECT * FROM TEST_TABLE;"))
    c++
    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); // 增加一条数据 Log(DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")); // 查询数据 Log(DBExec(":SELECT * FROM TEST_TABLE;")); }
  • 创建数据表。

    javascript
    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) }
    python
    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)
    c++
    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); }
  • 数据表记录的增删查改操作。

    javascript
    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)) // 增加一条数据 Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")) // 查询数据 Log(DBExec("SELECT * FROM TEST_TABLE;")) // 修改数据 Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000)) // 删除数据 Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110)) }
    python
    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)) # 增加一条数据 Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")) # 查询数据 Log(DBExec("SELECT * FROM TEST_TABLE;")) # 修改数据 Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000)) # 删除数据 Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110))
    c++
    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)); // 增加一条数据 Log(DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);")); // 查询数据 Log(DBExec("SELECT * FROM TEST_TABLE;")); // 修改数据 Log(DBExec("UPDATE TEST_TABLE SET HIGH=? WHERE TS=?", 110, 1518970320000)); // 删除数据 Log(DBExec("DELETE FROM TEST_TABLE WHERE HIGH=?", 110)); }

返回值

类型描述

object

包含SQL语句执行结果的对象,例如:

json
{"columns":["TS","HIGH","OPEN","LOW","CLOSE","VOLUME"],"values":[[1518970320000,100,99.1,90,100,12345.6]]}

参数

名称类型必填描述

sql

string

SQL语句字符串。

参考

备注

函数DBExec()通过传入参数,可以操作实盘数据库(SQLite数据库),实现对实盘数据库中数据的增、删、查、改等操作,支持SQLite语法。实盘数据库中的系统保留表包括:kvdbcfglogprofitchart,请勿对这些表进行操作。目前不支持事务操作,不建议执行此类操作,以免引起系统冲突。DBExec()函数仅支持实盘环境。

创建一个UUID。

UUID()

示例

javascript
function main() { var uuid1 = UUID() var uuid2 = UUID() Log(uuid1, uuid2) }
python
def main(): uuid1 = UUID() uuid2 = UUID() Log(uuid1, uuid2)
c++
void main() { auto uuid1 = UUID(); auto uuid2 = UUID(); Log(uuid1, uuid2); }

返回值

类型描述

string

返回32位的UUID字符串。

备注

UUID()函数仅支持实盘环境。

监听事件,当有任意事件发生时返回。

EventLoop()
EventLoop(timeout)

示例

javascript
function main(){ while(true){ // 需要在判断exchange.IO("status")函数返回true,即为真值时才可调用行情、交易等函数 if(exchange.IO("status")){ exchange.SetContractType("rb888") LogStatus(_D(), "已经连接CTP !") var msg = EventLoop() Log(msg) } else { LogStatus(_D(), "未连接CTP !") } } }
python
# 不支持EventLoop函数
c++
// 不支持EventLoop函数

返回值

类型描述

object

返回的对象如果不为空值,则返回内容中包含的Event为事件触发类型。例如以下返回值结构:

json
{"Seq":10,"Event":"tick","ThreadId":0,"Index":0,"Nano":1689216222796834300,"Symbol":"rb2311","Ticker": {...}}

参数

名称类型必填描述

timeout

number

参数timeout为超时设置,单位为毫秒。

参数timeout如果设置为0则等待直到有事件发生才返回,如果大于0则设置事件等待超时时间,小于0则立即返回最近的事件。

参考

备注

代码中第一次调用EventLoop()函数时才会初始化事件监听机制,如果在事件回调之后才首次调用EventLoop(),将会错过之前的事件。底层系统封装的队列结构会缓存最多500个事件回调,如果程序执行过程中没有及时调用EventLoop()函数取出事件,超出500个缓存的后续事件回调将会丢失。EventLoop()函数的调用不会影响系统底层WebSocket的缓存队列。

对于这些缓存数据仍需要使用各自的方法取出。对于在EventLoop()函数返回之前已经取出的数据,不会在EventLoop()函数中产生返回事件。EventLoop()函数的主要用途是通知策略层系统底层接收到了新的网络数据,以事件驱动整个策略。当EventLoop()函数返回事件时,只需遍历所有数据源即可。
EventLoop()函数仅支持实盘交易。

在主函数main()中调用时,监听主线程的事件。在JavaScript语言编写的策略中,通过threading.Thread()函数创建的线程,在线程的执行函数中也可以调用,用于监听当前线程的事件。

__Serve函数用于创建Http服务、TCP服务、Websocket服务(基于Http协议)。

__Serve(serveURI, handler)
__Serve(serveURI, handler, ...args)

示例

javascript
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) } }
python
# 不支持
c++
// 不支持

返回值

类型描述

string

返回一个字符串,记录创建的服务的IP地址、端口。例如:127.0.0.1:8088[::]:8089

参数

名称类型必填描述

serveURI

string

serveURI参数用于配置服务绑定的协议、IP地址、端口等设置,例如:http://0.0.0.0:8088?gzip=true,或:http://:8088?gzip=true

  • TCP协议
    serveURI参数设置例如:tcp://127.0.0.1:6666?tls=true;可以添加证书、私钥,例如:tls=true&cert_pem=xxxx&cert_key_pem=xxxx
  • Http协议
    serveURI参数设置例如:http://127.0.0.1:6666?gzip=true;可以设置压缩选项:gzip=true
    serveURI参数用于Https,例如:https://127.0.0.1:6666?tls=true&gzip=true;可以加入cert_pemcert_key_pem参数来加载证书。

handler

function

handler参数用于传入路由处理函数(Http协议)、消息处理函数(TCP协议)、Stream处理函数(Websocket)。参数handler传入的回调函数可以定义多个参数,第一个参数为ctx对象(上下文对象)。

arg

string / number / bool / object / array / function / any (系统支持的所有类型)

作为参数handler传入的回调函数的参数的实参,参数arg可能有多个,例如:

javascript
__Serve("http://:8088", function(ctx, a, b, c) { Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c) }, 1, 2, 3)

调用__Serve()函数时传入的参数1, 2, 3对应传入回调函数的参数a, b, c

参考

备注

  • 该函数仅支持JavaScript语言策略。

    • 服务线程与全局作用域隔离,因此不支持闭包或引用外部变量、自定义函数等;但是可以调用平台所有的API函数。

    • Websocket服务基于Http协议实现,可以在path中设置一个路由分支,设计Websocket消息订阅/推送的实现代码,可以参考本节范例代码。

参数handler传入的回调处理函数接收一个ctx参数。ctx参数为一个上下文对象,用于获取数据和写入数据,有以下方法:

  • ctx.proto()
    适用于Http/TCP协议,调用时返回协议名称。例如:HTTP/1.1tcp
  • ctx.host()
    适用于Http协议,调用时返回主机信息:IP地址、端口。
  • ctx.path()
    适用于Http协议,调用时返回请求路径。
  • ctx.query(key)
    适用于Http协议,调用时返回请求中query查询中key对应的值。例如发送的请求为:http://127.0.0.1:8088?num=123,参数handler传入的回调处理函数中ctx.query("num")调用时返回"123"
  • ctx.rawQuery()
    适用于Http协议,调用时返回请求中的原始查询(Http请求的query)。
    • ctx.headers()
      适用于Http协议,调用时返回请求中的请求头信息。
  • ctx.header(key)
    适用于Http协议,调用时返回指定的请求头中的某个key对应的值。例如获取当前请求的headers中的User-Agentctx.header("User-Agent")
  • ctx.method()
    适用于Http协议,调用时返回请求方法,例如GETPOST等。
    • ctx.body()
      适用于Http协议的POST请求,调用时返回请求的正文。
  • ctx.setHeader(key, value)
    适用于Http协议,设置应答报文的请求头信息。
    • ctx.setStatus(code)
      适用于Http协议,设置Http报文状态码,通常在路由分支最后设置Http状态码,默认为200。
  • ctx.remoteAddr()
    适用于Http/TCP协议,调用时返回请求中的远程客户端地址、端口。
  • ctx.localAddr()
    适用于Http/TCP协议,调用时返回服务本地地址、端口。
    • ctx.upgrade("websocket")
      适用于基于Http协议的Websocket协议实现,切换ctx上下文对象为Websocket协议;切换成功返回布尔值(真),失败返回布尔值(假)。
    • ctx.read(timeout_ms)
      适用于基于Http协议的Websocket协议实现/TCP协议,读取Websocket连接的数据,TCP连接的数据,普通Http协议中不支持使用该read方法;可以指定超时时间参数timeout_ms,单位毫秒。
    • ctx.write(s)
      适用于Http/TCP协议,用于写入字符串数据,可以使用JSON.stringify()编码JSON对象为字符串之后写入。对于WebSocket协议,可以使用该方法将编码后的字符串传递给客户端。

持久化保存数据,该函数实现了一个可保存的全局字典功能。数据结构为键值对表,永久保存在托管者本地数据库文件中。

_G()
_G(k)
_G(k, v)

示例

javascript
// 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main(){ // 设置一个全局变量num,值为1 _G("num", 1) // 更改一个全局变量num,值为字符串ok _G("num", "ok") // 删除全局变量num _G("num", null) // 返回全局变量num的值 Log(_G("num")) // 删除所有全局变量 _G(null) // 返回实盘ID var robotId = _G() }
python
def main(): _G("num", 1) _G("num", "ok") _G("num", None) Log(_G("num")) _G(None) robotId = _G()
c++
void main() { _G("num", 1); _G("num", "ok"); _G("num", NULL); Log(_G("num")); _G(NULL); // 不支持 auto robotId = _G(); }

返回值

类型描述

string / number / bool / object / array / 空值

持久化保存的k-v键值对中的键值数据。

参数

名称类型必填描述

k

string / 空值

参数k为保存的键值对中的键名,不区分大小写。

v

string / number / bool / object / array / 空值

参数v为保存的键值对中的键值,可以是任何可JSON序列化的数据。

参考

备注

每个实盘拥有独立的数据库,策略重启或托管者停止运行后,_G()函数保存的数据将持续存在。如果是回测结束后,_G()函数在回测系统中保存的数据会被清除。使用_G()函数持久化保存数据时,应根据硬件设备的内存、硬盘空间合理使用,避免滥用。

在实盘运行中,当调用_G()函数且不传入任何参数时,_G()函数返回当前实盘的Id

调用_G()函数时,参数v传入空值表示删除该k-v键值对。

调用_G()函数时,仅传入参数k(字符串类型),_G()函数返回保存的参数k对应的键值。

调用_G()函数时,仅参数k传入空值,表示删除所有记录的k-v键值对。

k-v键值对已经持久化保存后,再次调用_G()函数,传入已持久化保存的键名作为参数k,传入新的键值作为参数v,将更新该k-v键值对。

以实盘Id为123456为例,使用_G()函数持久化保存的键值对数据存储在实盘(即策略实例程序)所属托管者目录下的/logs/storage/123456/123456.db3数据库文件中,数据记录在kvdb表中。

将毫秒时间戳或Date对象转换为时间字符串。

_D()
_D(timestamp)
_D(timestamp, fmt)

示例

  • 获取并打印当前时间字符串:

    javascript
    // 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main(){ var time = _D() Log(time) }
    python
    def main(): strTime = _D() Log(strTime)
    c++
    void main() { auto strTime = _D(); Log(strTime); }
  • 将时间戳1574993606000转换为时间字符串:

    javascript
    // 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main() { Log(_D(1574993606000)) }
    python
    def main(): # 北京时间的服务器上运行:2019-11-29 10:13:26 ,另一台其它地区的服务器上的托管者运行此代码结果则为:2019-11-29 02:13:26 Log(_D(1574993606))
    c++
    void main() { Log(_D(1574993606000)); }
  • 使用参数fmt进行格式化,JavaScript、Python、C++语言的格式化字符串有所不同,请参考以下示例:

    javascript
    function main() { Log(_D(1574993606000, "yyyy--MM--dd hh--mm--ss")) // 2019--11--29 10--13--26 }
    python
    def main(): # 1574993606为秒级别时间戳 Log(_D(1574993606, "%Y--%m--%d %H--%M--%S")) # 2019--11--29 10--13--26
    c++
    void main() { Log(_D(1574993606000, "%Y--%m--%d %H--%M--%S")); // 2019--11--29 10--13--26 }

返回值

类型描述

string

时间字符串。

参数

名称类型必填描述

timestamp

number / object

毫秒时间戳或Date对象。

fmt

string

格式化字符串,默认格式为:yyyy-MM-dd hh:mm:ss

参考

备注

不传递任何参数时返回当前时间字符串。Python策略中使用_D()函数时,需要注意传入的参数为秒级时间戳(JavaScript、C++策略中为毫秒级时间戳,1秒等于1000毫秒)。

在实盘中使用_D()函数解析时间戳为可读时间字符串时,需要注意托管者程序所在操作系统的时区和时间设置。_D()函数解析时间戳为可读时间字符串是基于托管者系统的时间设置。

格式化浮点数。

_N()
_N(num)
_N(num, precision)

示例

  • 例如_N(3.1415, 2)将删除3.1415小数点后两位以外的数值,函数返回3.14

    javascript
    // 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main() { var i = 3.1415 Log(i) var ii = _N(i, 2) Log(ii) }
    python
    def main(): i = 3.1415 Log(i) ii = _N(i, 2) Log(ii)
    c++
    void main() { auto i = 3.1415; Log(i); auto ii = _N(i, 2); Log(ii); }
  • 如需将小数点左边的N位数字置为0,可以使用负数精度:

    javascript
    // 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main() { var i = 1300 Log(i) var ii = _N(i, -3) // 查看日志得知为1000 Log(ii) }
    python
    def main(): i = 1300 Log(i) ii = _N(i, -3) Log(ii)
    c++
    void main() { auto i = 1300; Log(i); auto ii = _N(i, -3); Log(ii); }

返回值

类型描述

number

根据精度设置格式化后的浮点数。

参数

名称类型必填描述

num

number

需要格式化的浮点数。

precision

number

格式化的精度设置,参数precision为整数,默认值为4。

参考

备注

参数precision可以为正整数或负整数。

重试函数,用于接口调用的容错处理。

_C(pfn)
_C(pfn, ...args)

示例

  • 对于无参数函数的容错处理:

    javascript
    function main(){ // 鉴于测试代码,不使用商品期货策略的通用架构,此处仅判断exchange.IO("status")函数,在确认连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } // 测试代码部分 // 设置合约为rb888(螺纹钢主力连续合约),或设置股票代码 exchange.SetContractType("rb888") var ticker = _C(exchange.GetTicker) // 调整_C()函数的重试时间间隔为2秒 _CDelay(2000) var depth = _C(exchange.GetDepth) Log(ticker) Log(depth) }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") ticker = _C(exchange.GetTicker) _CDelay(2000) depth = _C(exchange.GetDepth) Log(ticker) Log(depth)
    c++
    void main() { while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); auto ticker = _C(exchange.GetTicker); _CDelay(2000); auto depth = _C(exchange.GetDepth); Log(ticker); Log(depth); }
  • 对于有参数函数的容错处理:

    javascript
    function main(){ // 鉴于测试代码,不使用商品期货策略的通用架构,此处仅判断exchange.IO("status")函数,在确认连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } // 测试代码部分 // 设置合约为rb888(螺纹钢主力连续合约),或设置股票代码 exchange.SetContractType("rb888") var records = _C(exchange.GetRecords, PERIOD_D1) Log(records) }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") records = _C(exchange.GetRecords, PERIOD_D1) Log(records)
    c++
    void main() { while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); auto records = _C(exchange.GetRecords, PERIOD_D1); Log(records); }
  • 也可用于自定义函数的容错处理:

    javascript
    var test = function(a, b){ var time = new Date().getTime() / 1000 if(time % b == 3){ Log("符合条件!", "#FF0000") return true } Log("重试!", "#FF0000") return false } function main(){ // 不使用接口获取数据的测试,无需使用exchange.IO("status")函数判断连接状态,也不必设置合约代码,因为此处仅用于测试自定义函数 var ret = _C(test, 1, 5) Log(ret) }
    python
    import time def test(a, b): ts = time.time() if ts % b == 3: Log("符合条件!", "#FF0000") return True Log("重试!", "#FF0000") return False def main(): ret = _C(test, 1, 5) Log(ret)
    c++
    // C++ 不支持此方式的自定义函数容错

返回值

类型描述

假值空值以外的所有平台支持类型(any)。

回调函数执行后的返回值。

参数

名称类型必填描述

pfn

function

参数pfn为函数引用,是一个回调函数

arg

string / number / bool / object / array / function / any (系统支持的所有类型)

回调函数的参数,参数arg可以有多个。参数arg的类型和数量取决于回调函数的参数定义。

备注

_C()函数会持续调用指定的函数直到成功返回(当参数pfn引用的函数返回空值假值时会重试调用pfn)。

例如_C(exchange.GetTicker)。默认重试间隔为3秒,可以调用_CDelay()函数来设置重试间隔。
例如_CDelay(1000),表示将_C()函数的重试间隔修改为1秒。

可以对以下函数进行容错处理(但不限于):

  • exchange.GetTicker()
  • exchange.GetDepth()
  • exchange.GetTrades()
  • exchange.GetRecords()
  • exchange.GetAccount()
  • exchange.GetOrders()
  • exchange.GetOrder()
  • exchange.GetPositions()

这些函数都可以通过_C()函数调用来实现容错。_C()函数不限于上述列出的函数,参数pfn是函数引用而非函数调用,请注意使用_C(exchange.GetTicker)而不是_C(exchange.GetTicker())

返回数组arr1与数组arr2的交叉周期数。

_Cross(arr1, arr2)

示例

可以模拟一组数据来测试_Cross(Arr1, Arr2)函数:

javascript
// 快线指标 var arr1 = [1,2,3,4,5,6,8,8,9] // 慢线指标 var arr2 = [2,3,4,5,6,7,7,7,7] // 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main(){ Log("_Cross(arr1, arr2) : ", _Cross(arr1, arr2)) Log("_Cross(arr2, arr1) : ", _Cross(arr2, arr1)) }
python
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))
c++
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)); }

返回值

类型描述

number

数组arr1与数组arr2的交叉周期数。

参数

名称类型必填描述

arr1

array

元素为number类型的数组。

arr2

array

元素为number类型的数组。

备注

_Cross()函数的返回值为正数时表示上穿的周期数,为负数时表示下穿的周期数,为0时表示当前价格相同。详细使用说明:内置函数_Cross分析及使用说明

JSON.parse函数是ECMAScript标准内置对象JSON的方法,用于解码(解析)JSON字符串。优宽量化交易平台对其扩展了一个safeStr参数。

JSON.parse(s)
JSON.parse(s, safeStr)

示例

解码(解析)包含大数值的JSON字符串。

javascript
function main() { let s1 = '{"num": 8754613216564987646512354656874651651358}' Log("JSON.parse:", JSON.parse(s1)) // JSON.parse: {"num":8.754613216564987e+39} Log("JSON.parse:", JSON.parse(s1, true)) // JSON.parse: {"num":"8754613216564987646512354656874651651358"} let s2 = '{"num": 123}' Log("JSON.parse:", JSON.parse(s2)) // JSON.parse: {"num":123} Log("JSON.parse:", JSON.parse(s2, true)) // JSON.parse: {"num":123} }
python
# 可以使用Python的第三方库处理大数值数据。
c++
// 可以使用其它方案处理。

返回值

类型描述

object

返回JSON对象。

参数

名称类型必填描述

s

string

需要解码(解析)的JSON字符串。

safeStr

bool

当此参数设置为true时,解析过程中若遇到可能超出精度范围的数值,将以字符串形式返回,以避免精度丢失或溢出问题。

备注

JSON.parse()函数可以正确解析包含大数值的JSON字符串,设置safeStr参数为true时,会将大数值解析为字符串类型。

safeStr参数也支持作为reviver参数使用,即:一个转换结果的函数,将为对象的每个成员调用此函数。详细信息请查阅相关资料。

仅支持JavaScript语言。

回测系统不支持JSON.parse()函数的safeStr参数功能。

JSON.stringify函数是ECMAScript标准内置对象JSON的方法,用于将JavaScript值编码为JSON字符串。

JSON.stringify(obj)

示例

编码一个对象,输出编码后的JSON字符串。

javascript
function main() { let s1 = {"num": "8754613216564987646512354656874651651358"} Log("JSON.stringify:", JSON.stringify(s1)) // JSON.stringify: {"num":"8754613216564987646512354656874651651358"} // JSON.stringify(s1) 返回的变量为一个字符串类型 }
python
// 略
c++
// 略

返回值

类型描述

string

返回编码后的JSON字符串。

参数

名称类型必填描述

obj

string / number / bool / object / array / function / any (平台支持的任意类型)

需要编码为JSON字符串的值。

备注

仅支持JavaScript语言。

在频道上发布最新状态数据。该函数用于实盘间通信,可以将当前实盘的状态数据广播到频道上,供其他实盘订阅获取。

SetChannelData(data)

示例

  • 频道广播端示例 - 发布市场行情数据

    javascript
    function main() { var updateId = 0 var robotId = _G() // 获取当前实盘ID while(true) { if (!exchange.IO("status")) { Sleep(1000) continue } // 获取实际市场价格 var ticker = exchange.GetTicker("rb888") if (!ticker) { Sleep(5000) continue } // 准备当前频道状态数据 var channelState = { robotId: robotId, updateId: ++updateId, timestamp: Date.now(), symbol: "rb888", lastPrice: ticker.Last, volume: ticker.Volume, high: ticker.High, low: ticker.Low } // 在频道上发布最新状态(覆盖旧状态) SetChannelData(channelState) // 显示当前频道状态 LogStatus("频道广播端 [实盘ID: " + robotId + "]\n" + "更新ID: #" + channelState.updateId + "\n" + "时间: " + _D(channelState.timestamp) + "\n" + "交易对: " + channelState.symbol + "\n" + "最新价: $" + channelState.lastPrice.toFixed(2) + "\n" + "成交量: " + channelState.volume.toFixed(4) + "\n" + "最高价: $" + channelState.high.toFixed(2) + "\n" + "最低价: $" + channelState.low.toFixed(2)) Sleep(60000) // 每分钟更新一次频道状态 } }
    python
    def main(): updateId = 0 robotId = _G() # 获取当前实盘ID while True: if not exchange.IO("status"): Sleep(1000) continue # 获取实际市场价格 ticker = exchange.GetTicker("rb888") if not ticker: Sleep(5000) continue # 准备当前频道状态数据 channelState = { "robotId": robotId, "updateId": updateId + 1, "timestamp": time.time() * 1000, "symbol": "rb888", "lastPrice": ticker["Last"], "volume": ticker["Volume"], "high": ticker["High"], "low": ticker["Low"] } updateId += 1 # 在频道上发布最新状态(覆盖旧状态) SetChannelData(channelState) # 显示当前频道状态 LogStatus("频道广播端 [实盘ID: {}]\n".format(robotId) + "更新ID: #{}\n".format(channelState["updateId"]) + "时间: {}\n".format(_D(channelState["timestamp"])) + "交易对: {}\n".format(channelState["symbol"]) + "最新价: ${:.2f}\n".format(channelState["lastPrice"]) + "成交量: {:.4f}\n".format(channelState["volume"]) + "最高价: ${:.2f}\n".format(channelState["high"]) + "最低价: ${:.2f}".format(channelState["low"])) Sleep(60000) # 每分钟更新一次频道状态
    c++
  • 跨平台发送示例 - 模拟外部平台(如TradingView)向优宽量化实盘发送数据

    javascript
    // 此示例演示如何使用HttpQuery发送HTTP POST请求,模拟外部平台向优宽量化实盘发送数据 // 实际场景中,外部平台(如TradingView的Webhook告警URL、第三方交易系统等)会直接调用优宽量化API端点 function main() { let uuid = "6BC42A119B5DBFA2188A8279DA3B5C30" let robotId = 123456 // 目标实盘ID(需要接收数据的实盘) let baseUrl = "https://www.youquant.com" while (true) { // 准备要发送的数据(可以是JSON、文本或其他格式) let sendData = { "action": "buy", "symbol": "rb888", "price": 3500, "timestamp": Date.now() } // 构造HTTP POST请求 let options = { method: "POST", body: JSON.stringify(sendData) // body可以是JSON字符串、普通文本等 } let url = `${baseUrl}/api/v1?method=pub&robot=${robotId}&channel=${uuid}` // 发送数据 let ret = HttpQuery(url, options) Log("Simulated external platform sending data, result:", ret) Sleep(10000) // 每10秒发送一次 } }
    python
    # 此示例演示如何使用HttpQuery发送HTTP POST请求,模拟外部平台向优宽量化实盘发送数据 # 实际场景中,外部平台(如TradingView的Webhook告警URL、第三方交易系统等)会直接调用优宽量化API端点 import json def main(): uuid = "6BC42A119B5DBFA2188A8279DA3B5C30" robotId = 123456 # 目标实盘ID(需要接收数据的实盘) baseUrl = "https://www.youquant.com" while True: # 准备要发送的数据(可以是JSON、文本或其他格式) sendData = { "action": "buy", "symbol": "rb888", "price": 3500, "timestamp": time.time() * 1000 } # 构造HTTP POST请求 options = { "method": "POST", "body": json.dumps(sendData) # body可以是JSON字符串、普通文本等 } url = "{}/api/v1?method=pub&robot={}&channel={}".format(baseUrl, robotId, uuid) # 发送数据 ret = HttpQuery(url, options) Log("Simulated external platform sending data, result:", ret) Sleep(10000) # 每10秒发送一次
    c++

返回值

类型描述

空值

函数无返回值。

参数

名称类型必填描述

data

object / array / string / number / bool / 空值

需要发布到频道的数据,可以是任何可以JSON序列化的数据结构,通常为包含实盘状态信息的对象。

参考

备注

SetChannelData()函数是非阻塞调用,调用后立即返回,不会等待数据传输完成。

每个实盘都有一个独立的频道,频道ID即为实盘ID(可通过_G()函数获取)。

频道上只保存最新的状态数据,每次调用SetChannelData()会覆盖之前发布的数据,而非追加历史消息。

频道数据可以跨实盘、跨托管者、跨服务器进行广播,多个实盘可以订阅同一个频道。

订阅端使用GetChannelData()函数订阅频道数据。

频道通信适用于实盘环境,回测系统中该功能可能受限。

传入的数据参数data在JSON序列化后的字节长度不得超过1024字节,超出限制可能导致数据发布失败。建议仅传输必要的状态信息,避免传输过大的数据对象。

发布的数据应根据硬件设备的内存和网络带宽合理使用,避免发布过大的数据对象。

SetChannelData()函数发布的数据除了可以被优宽量化平台内的其他实盘订阅,还支持跨平台数据发送功能。外部平台(如TradingView的Webhook告警、第三方交易系统、监控软件等)可以通过HTTP POST请求向指定的优宽量化实盘发送数据。

**跨平台发送数据的方式:**外部系统通过HTTP POST请求发送数据到优宽量化平台API端点:https://www.youquant.com/api/v1?method=pub&robot={robotId}&channel={uuid},其中robotId为目标实盘ID,uuid为32位字符的频道标识符。发送的数据在请求body中传递,可以是JSON格式、文本或其他格式。注意:必须先有实盘订阅该UUID频道,外部系统才能成功发送数据;广播的数据会发送到robotId实盘所在托管者下的所有实盘,同一托管者下订阅了该UUID频道的实盘都可以接收数据。

订阅指定实盘的频道数据。该函数用于实盘间通信,可以获取其他实盘通过SetChannelData()函数发布的最新状态数据。

GetChannelData(channelId)

示例

  • 频道订阅端示例 - 订阅两个实盘的频道数据

    javascript
    function main() { // 需要订阅的两个频道ID(根据实际情况修改) var channelId1 = "632799" // 频道1的实盘ID var channelId2 = "632800" // 频道2的实盘ID while(true) { // 订阅频道1的当前状态 var state1 = GetChannelData(channelId1) // 订阅频道2的当前状态 var state2 = GetChannelData(channelId2) // 构建状态显示 var statusMsg = "频道订阅端 - 当前订阅状态\n\n" // 显示频道1状态 statusMsg += "═══ 频道1 [" + channelId1 + "] ═══\n" if (state1 !== null) { statusMsg += "更新ID: #" + state1.updateId + "\n" statusMsg += "时间: " + _D(state1.timestamp) + "\n" statusMsg += "交易对: " + state1.symbol + "\n" statusMsg += "最新价: $" + state1.lastPrice.toFixed(2) + "\n" statusMsg += "成交量: " + state1.volume.toFixed(4) + "\n" } else { statusMsg += "状态: 等待中...(首次调用返回 null)\n" } statusMsg += "\n" // 显示频道2状态 statusMsg += "═══ 频道2 [" + channelId2 + "] ═══\n" if (state2 !== null) { statusMsg += "更新ID: #" + state2.updateId + "\n" statusMsg += "时间: " + _D(state2.timestamp) + "\n" statusMsg += "交易对: " + state2.symbol + "\n" statusMsg += "最新价: $" + state2.lastPrice.toFixed(2) + "\n" statusMsg += "成交量: " + state2.volume.toFixed(4) + "\n" } else { statusMsg += "状态: 等待中...(首次调用返回 null)\n" } LogStatus(statusMsg) Sleep(5000) // 每5秒订阅一次频道 } }
    python
    def main(): # 需要订阅的两个频道ID(根据实际情况修改) channelId1 = "632799" # 频道1的实盘ID channelId2 = "632800" # 频道2的实盘ID while True: # 订阅频道1的当前状态 state1 = GetChannelData(channelId1) # 订阅频道2的当前状态 state2 = GetChannelData(channelId2) # 构建状态显示 statusMsg = "频道订阅端 - 当前订阅状态\n\n" # 显示频道1状态 statusMsg += "═══ 频道1 [{}] ═══\n".format(channelId1) if state1 is not None: statusMsg += "更新ID: #{}\n".format(state1["updateId"]) statusMsg += "时间: {}\n".format(_D(state1["timestamp"])) statusMsg += "交易对: {}\n".format(state1["symbol"]) statusMsg += "最新价: ${:.2f}\n".format(state1["lastPrice"]) statusMsg += "成交量: {:.4f}\n".format(state1["volume"]) else: statusMsg += "状态: 等待中...(首次调用返回 None)\n" statusMsg += "\n" # 显示频道2状态 statusMsg += "═══ 频道2 [{}] ═══\n".format(channelId2) if state2 is not None: statusMsg += "更新ID: #{}\n".format(state2["updateId"]) statusMsg += "时间: {}\n".format(_D(state2["timestamp"])) statusMsg += "交易对: {}\n".format(state2["symbol"]) statusMsg += "最新价: ${:.2f}\n".format(state2["lastPrice"]) statusMsg += "成交量: {:.4f}\n".format(state2["volume"]) else: statusMsg += "状态: 等待中...(首次调用返回 None)\n" LogStatus(statusMsg) Sleep(5000) # 每5秒订阅一次频道
    c++
  • 跨平台订阅示例 - 使用 UUID 订阅外部系统发送的数据

    javascript
    function main() { // 使用32位UUID作为频道标识符 let uuid = "6BC42A119B5DBFA2188A8279DA3B5C30" while (true) { // 订阅UUID频道的数据 let data = GetChannelData(uuid) if (data !== null) { Log("Received cross-platform data:", data) } else { Log("Waiting for data... (first call returns null)") } Sleep(10000) // 每10秒检查一次 } }
    python
    def main(): # 使用32位UUID作为频道标识符 uuid = "6BC42A119B5DBFA2188A8279DA3B5C30" while True: # 订阅UUID频道的数据 data = GetChannelData(uuid) if data is not None: Log("Received cross-platform data:", data) else: Log("Waiting for data... (first call returns None)") Sleep(10000) # 每10秒检查一次
    c++

返回值

类型描述

object / array / string / number / bool / 空值

返回订阅频道的最新状态数据。首次调用返回null,需要重试。数据结构由广播端发布的数据决定。

参数

名称类型必填描述

channelId

string / number

频道标识符,支持两种类型:

  1. 实盘ID:用于订阅其他实盘的频道数据(实盘间通信)。可以通过_G()函数获取实盘ID。
  2. 32位UUID:用于订阅跨平台发送的数据(外部系统通过HTTP API发送数据到优宽量化平台)。

参考

备注

GetChannelData()函数是非阻塞调用,调用后立即返回,不会等待数据接收完成。

首次调用GetChannelData()函数时会返回null,需要重试等待频道数据同步完成。

每次调用获取的都是频道上的最新状态数据,而非历史消息队列。

一个实盘可以同时订阅多个不同实盘的频道,只需多次调用GetChannelData()并传入不同的实盘ID。

当前实盘也可以订阅自己的频道,即robotId参数可以是当前实盘ID。

频道数据可以跨实盘、跨托管者、跨服务器进行传输。

广播端使用SetChannelData()函数发布频道数据。

频道通信适用于实盘环境,回测系统中该功能可能受限。

GetChannelData()函数支持跨平台订阅功能。使用32位UUID作为频道标识符时,可以接收来自优宽量化平台外部系统通过HTTP API发送的数据。外部系统需要指定实盘ID和UUID才能发送数据,同一托管者下的所有实盘都可以订阅该UUID频道的数据,不同托管者的实盘无法订阅。