内置函数
Global
Version
返回系统当前的版本号。
Version()示例
javascript
function main() {
Log("version:", Version())
}
python
def main():
Log("version:", Version())
rust
fn main() {
Log!("version:", Version());
}
c++
void main() {
Log("version:", Version());
}返回值
| 类型 | 描述 |
string | 当前系统的版本号,例如: |
备注
系统版本号即托管者程序的版本号。
Sleep
休眠函数,使程序暂停运行一段时间。
Sleep(millisecond)示例
javascript
function main() {
Sleep(1000 * 10) // 等待10秒钟
Log("等待了10秒钟")
}
python
def main():
Sleep(1000 * 10)
Log("等待了10秒钟")
rust
fn main() {
Sleep(1000 * 10); // 等待10秒钟
Log!("等待了10秒钟");
}
c++
void main() {
Sleep(1000 * 10);
Log("等待了10秒钟");
}参数
| 名称 | 类型 | 必填 | 描述 |
millisecond | number | 是 |
|
备注
例如,执行Sleep(1000)函数时,程序将休眠1秒。该函数支持小于1毫秒的休眠操作,例如Sleep(0.1);支持的最小参数为0.000001,即纳秒级休眠,1纳秒等于1e-6毫秒。
在使用Python语言编写策略时,对于轮询间隔、时间等待等操作,应当使用Sleep(millisecond)函数,而不建议使用Python中time库的time.sleep(second)函数。因为在回测时,策略中的time.sleep(second)函数会使策略程序实际等待相应的时间(而非在回测系统的时间序列上跳过),从而导致回测速度非常缓慢。
IsVirtual
判断策略当前的运行环境是否为回测系统。
IsVirtual()示例
javascript
function main() {
if (IsVirtual()) {
Log("当前为回测系统环境。")
} else {
Log("当前为实盘环境。")
}
}
python
def main():
if IsVirtual():
Log("当前为回测系统环境。")
else:
Log("当前为实盘环境。")
rust
fn main() {
if IsVirtual() {
Log!("当前为回测系统环境。");
} else {
Log!("当前为实盘环境。");
}
}
c++
void main() {
if (IsVirtual()) {
Log("当前为回测系统环境。");
} else {
Log("当前为实盘环境。");
}
}返回值
| 类型 | 描述 |
bool | 当策略运行在回测系统环境时返回真值,例如: |
备注
用于判断当前运行环境是否为回测系统,以便兼容回测与实盘之间的差异。
Mail
发送邮件。
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")
rust
fn 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 | 邮件发送成功时返回真值,例如: |
参数
| 名称 | 类型 | 必填 | 描述 |
smtpServer | string | 是 | 用于指定邮件发送方的 |
smtpUsername | string | 是 | 用于指定邮件发送方的邮箱地址。 |
smtpPassword | string | 是 | 用于指定邮件发送方邮箱的 |
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:465,或者smtp://xxx.com:xxx。
该函数在回测系统中不起作用。
Mail_Go
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 |
|
参数
| 名称 | 类型 | 必填 | 描述 |
smtpServer | string | 是 | 用于指定邮件发送方的 |
smtpUsername | string | 是 | 用于指定邮件发送方的邮箱地址。 |
smtpPassword | string | 是 | 邮件发送方邮箱的 |
mailTo | string | 是 | 用于指定邮件接收方的邮箱地址。 |
title | string | 是 | 邮件标题。 |
body | string | 是 | 邮件正文。 |
参考
备注
在回测系统中不起作用。
SetErrorFilter
过滤错误日志。
SetErrorFilter(filters)示例
-
过滤常见错误信息。
javascriptfunction main() { SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused") }pythondef main(): SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")rustfn 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"); } -
过滤某个接口的错误信息。
javascriptfunction 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) }pythondef 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)rustfn main() { // 由于这是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断是否成功连接期货公司前置机,连接成功后立即执行测试代码。股票、证券交易无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 查询一个不存在的订单(id 为 123),故意触发接口报错 let orderId = OrderId { S: "123".to_string(), ..Default::default() }; let order = exchange.GetOrder(&orderId); Log!(order); // 过滤 http 502 错误及 GetOrder 接口错误;设置错误过滤后,再次调用 GetOrder 将不再报错 SetErrorFilter("502:|GetOrder"); let order = exchange.GetOrder(&orderId); 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 的数据库文件中,从而避免因频繁报错导致数据库文件膨胀。
GetPid
获取实盘进程的 Id。
GetPid()示例
javascript
function main(){
var id = GetPid()
Log(id)
}
python
def main():
id = GetPid()
Log(id)
rust
fn main() {
let id = GetPid();
Log!(id);
}
c++
void main() {
auto id = GetPid();
Log(id);
}返回值
| 类型 | 描述 |
string | 返回实盘进程的 Id。 |
GetLastError
获取最近一次的错误信息。
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)
rust
fn main() {
// 由于这是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票、证券交易无需使用 exchange.IO("status") 判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
exchange.SetContractType("rb888").unwrap();
// 由于不存在编号为 123 的订单,因此会触发错误
let id = OrderId { S: "123".to_string(), ..Default::default() };
let _ = exchange.GetOrder(&id);
let 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
获取策略的交互命令。
GetCommand()示例
-
检测交互命令,并在检测到交互命令时使用
Log函数输出该交互命令。javascriptfunction main(){ while(true) { var cmd = GetCommand() if (cmd) { Log(cmd) } Sleep(1000) } }pythondef main(): while True: cmd = GetCommand() if cmd: Log(cmd) Sleep(1000)rustfn main() { loop { if let Some(cmd) = GetCommand(0) { Log!(cmd); } Sleep(1000); } }c++void main() { while(true) { auto cmd = GetCommand(); if(cmd != "") { Log(cmd); } Sleep(1000); } } -
例如,在策略交互控件中添加一个不带输入框的控件,将交互控件命名为:
buy,控件描述信息设置为:买入,这是一个按钮控件。接着再添加一个带输入框的控件,将交互控件命名为:sell,控件描述信息设置为:卖出,这是一个由按钮和输入框组合而成的交互控件。在策略中编写交互代码,以响应不同的交互控件:
javascriptfunction 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) } }pythondef 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)rustfn main() { loop { LogStatus!(_D(None)); if let Some(cmd) = GetCommand(0) { Log!("cmd:", cmd); let arr: Vec<&str> = cmd.split(':').collect(); if arr[0] == "buy" { Log!("买入,该控件不带数量"); } else if 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 | 返回的命令格式为 |
备注
该函数在回测系统中不起作用。
GetMeta
获取生成策略注册码时写入的 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)
rust
fn main() {
// 策略允许的计价币最大资产数量
let maxBaseCurrency;
// 获取创建注册码时的元数据
let meta = GetMeta();
let level = meta.as_str().unwrap_or("");
// 检测 Meta 对应的条件
if level == "level1" {
// -1 表示不限制
maxBaseCurrency = -1.0;
} else if level == "level2" {
maxBaseCurrency = 10.0;
} else if level == "level3" {
maxBaseCurrency = 1.0;
} else {
maxBaseCurrency = 0.5;
}
// 鉴于此为测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断连接期货公司前置机成功后,立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
exchange.SetContractType("rb888").unwrap();
loop {
Sleep(1000);
let ticker = exchange.GetTicker(None).unwrap();
// 检测资产数值
let acc = exchange.GetAccount().unwrap();
if maxBaseCurrency != -1.0 && maxBaseCurrency < acc.Balance + acc.FrozenBalance {
// 停止执行策略交易逻辑
LogStatus!(_D(None), "level:", level, "持仓超过注册码的使用限制,不再执行策略交易逻辑!");
continue;
}
// 其他交易逻辑
// 正常输出状态栏信息
LogStatus!(_D(None), "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值长度不能超过 190 个字符,GetMeta()函数仅支持实盘环境。
如果生成策略注册码时未设置元数据(Meta),则GetMeta()函数返回空值。
该函数在回测系统中不起作用。
Dial
用于原始的Socket访问,支持tcp、udp、tls、unix协议。
支持 4 种主流的通信协议:mqtt、nats、amqp、kafka。
支持连接数据库,可连接的数据库包括:sqlite3、mysql、postgres、clickhouse。
Dial(address)
Dial(address, timeout)
Dial(address, options)示例
-
Dial 函数调用示例:
javascriptfunction 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() } }pythondef 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()rustfn main() { // Dial 支持 tcp://、udp://、tls://、unix:// 协议,可使用 Dial::new(addr, timeout) 指定超时的秒数 let mut client = Dial("tls://www.baidu.com:443"); if client.Valid() { // write 的第二个数字参数指定超时,write 返回成功发送的字节数 client.write("GET / HTTP/1.1\nConnection: Closed\n\n", 0); loop { // read 的数字参数指定超时,单位:毫秒。返回空字符串表示出错、超时或 socket 已关闭 let buf = client.read(0); if 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数据库的示例。javascriptvar 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// 不支持rustfn main() { // let mut client = Dial("sqlite3://:memory:"); // 使用内存数据库 let mut client = Dial("sqlite3://test1.db"); // 打开/连接托管者所在目录的数据库文件 // Rust 的连接对象不支持 fd() 方法 // 查询数据库中的表 let ret = client.exec("SELECT name FROM sqlite_master WHERE type='table'"); Log!(format!("{:?}", ret)); Log!("执行client.close()"); client.close(); }c++// 不支持
返回值
| 类型 | 描述 | ||||||||||||||||||||
object | 如果连接超时,
WebSocket协议推送过来的数据,如果策略中两次
|
参数
| 名称 | 类型 | 必填 | 描述 |
address | string | 是 | 请求地址。 |
timeout | number | 否 | 超时时间,单位为秒。 |
options | object | 否 | 连接配置选项。 |
备注
address参数的详细说明:在标准地址wss://xxx.xxx.xxx:10441/websocket?compress之后,以|符号进行分隔。如果参数字符串中包含|字符,则使用||作为分隔符。分隔符之后的部分为功能参数设置,各参数之间使用&字符连接。
例如,同时设置ss5代理与压缩参数时,可写作:
Dial("wss://baidu.com/stream|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
| Dial函数的address参数支持的功能 | 参数说明 |
|---|---|
| WebSocket协议数据压缩相关的参数:compress=参数值 | compress用于指定压缩方式,可选值包括gzip_raw、gzip等。如果所用的gzip并非标准gzip,可使用扩展方式:gzip_raw |
| WebSocket协议数据压缩相关的参数: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用于设置ss5代理,参数值格式为:socks5://name:pwd@192.168.0.1:1080,其中name为ss5服务端用户名,pwd为ss5服务端登录密码,1080为ss5服务的端口。 |
Dial()函数仅支持实盘。
使用Dial函数连接数据库时,连接字符串的编写可参考各数据库的Go语言驱动项目。
| 支持的数据库 | 驱动项目 | 连接字符串(Connection String) | 备注 |
|---|
| sqlite3 | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=shared&mode=memory
| sqlite3://前缀表示使用sqlite3数据库,调用示例:Dial("sqlite3://test1.db") |
| mysql |
|---|
| postgres | github.com/lib/pq | postgres://user=postgres dbname=yourdatabase sslmode=disable
password=yourpassword host=localhost port=5432 | -- |
| clickhouse |
|---|
目前仅JavaScript语言支持在Dial函数中使用mqtt、nats、amqp、kafka通信协议。以下以JavaScript语言的策略代码为例,展示mqtt、nats、amqp、kafka四种协议的使用示例:
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++
// 暂不支持
HttpQuery
发送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库
rust
fn main() {
// 本次设置代理并发送http请求,无用户名,无密码,此次http请求会通过代理发送
let ret1: String = HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/", None);
// 本次设置代理并发送http请求,输入用户名和密码,仅HttpQuery当前调用生效,之后再次调用HttpQuery("http://www.baidu.com")这样不会使用代理
let ret2: String = HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/", None);
}
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 | 返回请求的应答数据。如果返回值为 在参数 |
参数
| 名称 | 类型 | 必填 | 描述 |
url | string | 是 | Http请求的url。 |
options | object | 否 | Http请求的相关设置,例如可以是以下结构:
此结构中的所有字段均为可选,例如可以不设置 |
参考
备注
HttpQuery()函数仅支持JavaScript、C++语言;Python语言可以使用urllib库,直接发送Http请求。
回测系统中可以使用HttpQuery()发送请求(仅支持GET请求)以获取数据。
回测时限制访问20个不同的URL,并且HttpQuery()访问会缓存数据,
相同的URL第二次访问时,HttpQuery()函数将返回缓存数据,不再发起实际的网络请求。
HttpQuery_Go
发送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 |
|
参数
| 名称 | 类型 | 必填 | 描述 |
url | string | 是 | HTTP请求的URL地址。 |
options | object | 否 | HTTP请求相关配置参数,可以使用以下结构:
此结构中的所有字段均为可选字段,例如可以不设置 |
参考
备注
HttpQuery_Go()函数仅支持JavaScript语言,Python语言可以使用urllib库直接发送HTTP请求。
HttpQuery_Go()主要用于访问交易所无需签名的接口,例如行情信息等公共接口。回测系统不支持HttpQuery_Go函数。
Encode
此函数根据传入的参数对数据进行编码。
Encode(algo, inputFormat, outputFormat, data)
Encode(algo, inputFormat, outputFormat, data, keyFormat, key)示例
-
Encode 函数调用示例。
javascriptfunction 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 }pythondef 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")) # 698d54f0494528a759f19c8e87a9f99e75a5881b9267ee3926bcf62c992d84barustfn 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",用于对字符串进行编码和解码。javascriptfunction 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) }pythondef 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, "", "") Log(ret4)rustfn main() { let ret1 = Encode("text.encoder.utf8", "raw", "hex", "你好", "", ""); // e4bda0e5a5bd Log!(ret1); let ret2 = Encode("text.decoder.utf8", "hex", "string", &ret1, "", ""); Log!(ret2); let ret3 = Encode("text.encoder.gbk", "raw", "hex", "你好", "", ""); // c4e3bac3 Log!(ret3); let ret4 = Encode("text.decoder.gbk", "hex", "string", &ret3, "", ""); Log!(ret4); }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 |
|
参数
| 名称 | 类型 | 必填 | 描述 |
algo | string | 是 | 参数 支持设置为:"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"。 参数 参数 |
inputFormat | string | 是 | 用于指定 |
outputFormat | string | 是 | 用于指定输出的数据格式。 |
data | string | 是 | 参数 |
keyFormat | string | 否 | 用于指定 |
key | string | 否 | 参数 当参数 当参数 |
备注
Encode()函数仅支持实盘。若不传入key、keyFormat参数,则不使用key进行加密。
UnixNano
获取当前时刻的纳秒级时间戳。
UnixNano()示例
如需获取毫秒级时间戳,可参考以下代码:
javascript
function main() {
var time = UnixNano() / 1000000
Log(_N(time, 0))
}
python
def main():
time = UnixNano()
Log(time)
rust
fn main() {
let time = UnixNano() / 1000000;
Log!(time);
}
c++
void main() {
auto time = UnixNano();
Log(time);
}返回值
| 类型 | 描述 |
number |
|
参考
Unix
获取当前时刻的秒级时间戳。
Unix()示例
javascript
function main() {
var t = Unix()
Log(t)
}
python
def main():
t = Unix()
Log(t)
rust
fn main() {
let t = Unix();
Log!(t);
}
c++
void main() {
auto t = Unix();
Log(t);
}返回值
| 类型 | 描述 |
number | 返回秒级时间戳。 |
参考
GetOS
获取托管者所在设备的操作系统信息。
GetOS()示例
javascript
function main() {
Log("GetOS:", GetOS())
}
python
def main():
Log("GetOS:", GetOS())
rust
fn main() {
Log!("GetOS:", GetOS());
}
c++
void main() {
Log("GetOS:", GetOS());
}返回值
| 类型 | 描述 |
string | 操作系统信息。 |
备注
例如,运行在 Mac OS 操作系统上的托管者,调用 GetOS() 函数可能返回:darwin/amd64。由于苹果电脑采用多种硬件架构,返回值中会一并包含具体的架构信息。其中 darwin 即 Mac OS 系统的名称。
MD5
计算参数data的MD5哈希值。
MD5(data)示例
javascript
function main() {
Log("MD5", MD5("hello world"))
}
python
def main():
Log("MD5", MD5("hello world"))
rust
fn main() {
Log!("MD5", MD5("hello world"));
}
c++
void main() {
Log("MD5", MD5("hello world"));
}返回值
| 类型 | 描述 |
string | MD5哈希值。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | string | 是 | 需要进行MD5计算的数据。 |
参考
备注
调用MD5("hello world")函数后,返回值为:5eb63bbbe01eeed093cb22bb8f5acdc3。
DBExec
数据库接口函数。
DBExec(sql)示例
-
支持内存数据库。对于
DBExec函数的参数,如果sql语句以:开头,则在内存数据库中执行操作,无需写入文件,速度更快。适用于无需持久化保存的数据库操作,例如:
javascriptfunction 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;")) }pythondef 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;"))rustfn main() { let 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)", ]; let strSql = arr.join(""); let ret = DBExec(&strSql); Log!(format!("{:?}", ret)); // 增加一条数据 Log!(format!("{:?}", DBExec(":INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))); // 查询数据 Log!(format!("{:?}", 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;")); } -
创建数据表。
javascriptfunction 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) }pythondef 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)rustfn main() { let 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)", ]; let strSql = arr.join(""); let ret = DBExec(&strSql); Log!(format!("{:?}", 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); } -
对数据表中记录进行增、删、改、查(增删改查)操作。
javascriptfunction 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)) }pythondef 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))rustfn main() { let 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)", ]; let strSql = arr.join(""); Log!(format!("{:?}", DBExec(&strSql))); // 增加一条数据 Log!(format!("{:?}", DBExec("INSERT INTO TEST_TABLE (TS, HIGH, OPEN, LOW, CLOSE, VOLUME) VALUES (1518970320000, 100, 99.1, 90, 100, 12345.6);"))); // 查询数据 Log!(format!("{:?}", DBExec("SELECT * FROM TEST_TABLE;"))); // 修改数据,Rust 的 DBExec() 函数只接受单个 SQL 语句字符串参数,不支持 ? 占位符传参,参数值需直接写入语句中 Log!(format!("{:?}", DBExec("UPDATE TEST_TABLE SET HIGH=110 WHERE TS=1518970320000;"))); // 删除数据 Log!(format!("{:?}", 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 语法。实盘数据库中的系统保留表包括 kvdb、cfg、log、profit、chart,请勿对这些表进行任何操作。目前不支持事务,不建议执行此类操作,否则会引发系统冲突。
DBExec() 函数仅支持实盘。
UUID
生成一个 UUID。
UUID()示例
javascript
function main() {
var uuid1 = UUID()
var uuid2 = UUID()
Log(uuid1, uuid2)
}
python
def main():
uuid1 = UUID()
uuid2 = UUID()
Log(uuid1, uuid2)
rust
fn main() {
let uuid1 = UUID();
let uuid2 = UUID();
Log!(uuid1, uuid2);
}
c++
void main() {
auto uuid1 = UUID();
auto uuid2 = UUID();
Log(uuid1, uuid2);
}返回值
| 类型 | 描述 |
string | 32 位的 UUID 字符串。 |
备注
UUID() 函数仅支持在实盘中使用。
EventLoop
监听事件,当有任意事件发生时返回。
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函数
rust
fn main() {
loop {
// 需要在判断exchange.IO("status")函数返回true,即为真值时才可调用行情、交易等函数
if exchange.IO("status").unwrap_or_default() == "true" {
exchange.SetContractType("rb888").unwrap();
LogStatus!(_D(None), "已经连接CTP !");
let msg = EventLoop(0);
Log!(msg);
} else {
LogStatus!(_D(None), "未连接CTP !");
}
}
}
c++
// 不支持EventLoop函数返回值
| 类型 | 描述 |
object | 如果返回的对象不为空值,则返回内容中包含的
|
参数
| 名称 | 类型 | 必填 | 描述 |
timeout | number | 否 | 参数 |
参考
备注
只有在代码中第一次调用EventLoop()函数时,才会初始化该事件监听机制。如果在事件回调发生之后才首次调用EventLoop()函数,则会错过此前发生的事件。底层系统封装的队列结构最多可缓存500个事件回调,如果程序运行过程中未及时调用EventLoop()函数取出,超出500个缓存容量的较晚事件回调将会丢失。EventLoop()函数的调用不会影响系统底层WebSocket的缓存队列。
对于这些缓存,仍需使用各自对应的方法取出数据。对于在EventLoop()函数返回之前已经取出的数据,不会在EventLoop()函数中产生返回事件。EventLoop()函数的主要用途是通知策略层:系统底层已接收到新的网络数据,从而以事件驱动整个策略。当EventLoop()函数返回事件时,只需遍历所有数据来源即可。EventLoop()函数仅支持实盘。
在主函数main()中调用时,监听主线程的事件。在使用JavaScript语言编写的策略中,对于由threading.Thread()函数创建的线程,也可以在其执行函数中调用该函数,以监听当前线程的事件。
__Serve
__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地址、端口。例如: |
参数
| 名称 | 类型 | 必填 | 描述 |
serveURI | string | 是 |
|
handler | function | 是 |
|
arg | string / number / bool / object / array / function / any (系统支持的所有类型) | 否 | 作为参数
调用 |
参考
备注
-
该函数仅支持JavaScript语言策略。
-
服务线程与全局作用域隔离,因此不支持闭包或引用外部变量、自定义函数等;但是可以调用平台所有的API函数。
-
Websocket服务基于Http协议实现,可以在path中设置一个路由分支,设计Websocket消息订阅/推送的实现代码,可以参考本节范例代码。
-
参数handler传入的回调处理函数接收一个ctx参数。ctx参数为一个上下文对象,用于获取数据和写入数据,有以下方法:
- ctx.proto()
适用于Http/TCP协议,调用时返回协议名称。例如:HTTP/1.1、tcp。 - 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.headers()
- ctx.header(key)
适用于Http协议,调用时返回指定的请求头中的某个key对应的值。例如获取当前请求的headers中的User-Agent:ctx.header("User-Agent")。 - ctx.method()
适用于Http协议,调用时返回请求方法,例如GET、POST等。- ctx.body()
适用于Http协议的POST请求,调用时返回请求的正文。
- ctx.body()
- ctx.setHeader(key, value)
适用于Http协议,设置应答报文的请求头信息。- ctx.setStatus(code)
适用于Http协议,设置Http报文状态码,通常在路由分支最后设置Http状态码,默认为200。
- ctx.setStatus(code)
- 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协议,可以使用该方法将编码后的字符串传递给客户端。
- ctx.upgrade("websocket")
_G
该函数用于持久化保存数据,实现了一个可保存的全局字典功能。数据以键值对(KV)表的结构存储,并永久保存在托管者的本地数据库文件中。
_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()
rust
fn main() {
// 设置一个全局变量num,值为1
_G!("num", 1);
// 更改一个全局变量num,值为字符串ok
_G!("num", "ok");
// 删除全局变量num
_G!("num", null);
// 返回全局变量num的值
Log!(_G!("num"));
// Rust 不支持 _G!(null) 删除所有全局变量的形式
// 返回实盘ID
let 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 | string / 空值 | 否 | 参数 |
v | string / number / bool / object / array / 空值 | 否 | 参数 |
参考
备注
每个实盘单独使用一个数据库。策略重启或托管者停止运行后,_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()函数持久化保存的K-V键值数据存储在实盘(即策略实例程序)所属托管者目录下的/logs/storage/123456/123456.db3数据库文件中(123456.db3),数据记录在kvdb表中。
_D
将毫秒时间戳或Date对象转换为时间字符串。
_D()
_D(timestamp)
_D(timestamp, fmt)示例
-
获取并打印当前时间字符串:
javascript// 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main(){ var time = _D() Log(time) }pythondef main(): strTime = _D() Log(strTime)rustfn main() { let strTime = _D(None); Log!(strTime); }c++void main() { auto strTime = _D(); Log(strTime); } -
时间戳为1574993606000,使用代码进行转换:
javascript// 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 function main() { Log(_D(1574993606000)) }pythondef main(): # 北京时间的服务器上运行:2019-11-29 10:13:26 ,另一台其它地区的服务器上的托管者运行此代码结果则为:2019-11-29 02:13:26 Log(_D(1574993606))rustfn main() { Log!(_D(1574993606000)); }c++void main() { Log(_D(1574993606000)); } -
使用参数
fmt进行格式化,JavaScript、Python、C++语言的格式化字符串有所不同,具体请参看以下示例:javascriptfunction main() { Log(_D(1574993606000, "yyyy--MM--dd hh--mm--ss")) // 2019--11--29 10--13--26 }pythondef main(): # 1574993606为秒级别时间戳 Log(_D(1574993606, "%Y--%m--%d %H--%M--%S")) # 2019--11--29 10--13--26rustfn main() { // Rust 的 _D() 函数不支持 fmt 参数,仅支持默认格式:yyyy-MM-dd hh:mm:ss Log!(_D(1574993606000)); // 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 | 否 | 毫秒时间戳或 |
fmt | string | 否 | 格式化字符串,默认格式为: |
参考
备注
若不传入任何参数,则返回当前时间字符串。在Python策略中使用_D()函数时,需要注意传入的参数为秒级别时间戳(在JavaScript、C++策略中为毫秒级别时间戳,1秒等于1000毫秒)。
在实盘中使用_D()函数将时间戳解析为可读的时间字符串时,需要注意托管者程序所在操作系统的时区与时间设置。_D()函数将时间戳解析为可读时间字符串时,是依据托管者系统的时间而定的。
_N
格式化浮点数。
_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) }pythondef main(): i = 3.1415 Log(i) ii = _N(i, 2) Log(ii)rust// 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 fn main() { let i = 3.1415; Log!(i); let 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) }pythondef main(): i = 1300 Log(i) ii = _N(i, -3) Log(ii)rust// 不使用接口获取数据的测试,就无需使用exchange.IO("status")函数判断连接状态,也不用设置合约代码,因为这里仅仅是测试 fn main() { let i = 1300; Log!(i); let ii = _N(i, -3); // 查看日志得知为1000 Log!(ii); }c++void main() { auto i = 1300; Log(i); auto ii = _N(i, -3); Log(ii); }
返回值
| 类型 | 描述 |
number | 根据精度设置格式化后的浮点数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
num | number | 是 | 需要格式化的浮点数。 |
precision | number | 否 | 用于设置格式化精度,参数 |
参考
备注
参数precision可以为正整数,也可以为负整数。
_C
容错重试函数,用于对接口调用进行容错处理。
_C(pfn)
_C(pfn, ...args)示例
-
针对无参数函数的容错处理:
javascriptfunction 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) }pythondef 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)rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过exchange.IO("status")函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 测试代码部分 // 将合约设置为rb888,即螺纹钢主力连续合约;或设置为股票代码 exchange.SetContractType("rb888").unwrap(); let ticker = _C!(exchange.GetTicker(None)); // 将_C!()宏的重试时间间隔调整为2秒 _CDelay(2000); let depth = _C!(exchange.GetDepth(None)); 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); } -
针对有参数函数的容错处理:
javascriptfunction 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) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") records = _C(exchange.GetRecords, PERIOD_D1) Log(records)rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } exchange.SetContractType("rb888").unwrap(); let records = _C!(exchange.GetRecords(None, PERIOD_D1, None)); Log!(records); }c++void main() { while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); auto records = _C(exchange.GetRecords, PERIOD_D1); Log(records); } -
也可用于自定义函数的容错处理:
javascriptvar 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) }pythonimport 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)rustfn test(a: i64, b: i64) -> Result<bool> { let time = Unix(); if time % b == 3 { Log!("符合条件!", "#FF0000"); return Ok(true); } Log!("重试!", "#FF0000"); Err(Error::Api("retry".to_string())) } fn main() { // 此测试不通过接口获取数据,因此无需调用 exchange.IO("status") 函数判断连接状态,也无需设置合约代码,因为这里仅用于测试自定义函数 // 在 Rust 中,自定义函数返回 Result 类型即可使用 _C! 宏进行容错,返回 Err 时会自动重试 let ret = _C!(test(1, 5)); Log!(ret); }c++// C++ 不支持以这种方式对自定义函数进行容错处理
返回值
| 类型 | 描述 |
除假值和空值以外的所有平台支持类型(any)。 | 回调函数执行后的返回值。 |
参数
| 名称 | 类型 | 必填 | 描述 |
pfn | function | 是 | 参数 |
arg | string / number / bool / object / array / function / any (系统支持的所有类型) | 否 | 回调函数的参数,参数 |
备注
_C()函数会反复调用指定的函数,直到其成功返回为止(当参数pfn所引用的函数返回空值或假值时,_C()会重试调用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())。
_Cross
返回数组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))
rust
fn main() {
// 快线指标
let arr1 = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 8.0, 9.0];
// 慢线指标
let arr2 = [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 7.0, 7.0, 7.0];
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 | array | 是 | 元素为 |
arr2 | array | 是 | 元素为 |
备注
_Cross()函数的返回值为正数时表示上穿的周期数,为负数时表示下穿的周期数,为0时表示当前价格相等。详细使用说明请参阅:内置函数_Cross分析及使用说明。
JSON.parse
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 的第三方库处理大数值数据。
rust
fn main() {
let s1 = r#"{"num": 8754613216564987646512354656874651651358}"#;
Log!("JSONParse:", JSONParse(s1).unwrap()); // JSONParse: {"num":8.754613216564987e+39}
// Rust 的 JSONParse() 函数不支持 safeStr 参数,大数值可使用第三方库处理
let s2 = r#"{"num": 123}"#;
Log!("JSONParse:", JSONParse(s2).unwrap()); // JSONParse: {"num":123}
}
c++
// 可以使用其它方案处理。返回值
| 类型 | 描述 |
object | 返回值为 |
参数
| 名称 | 类型 | 必填 | 描述 |
s | string | 是 | 该参数为需要解码(解析)的 |
safeStr | bool | 否 | 当该参数设置为 |
备注
JSON.parse() 函数可以正确解析包含较大数值的 JSON 字符串;当 safeStr 参数设置为真值时,会将较大的数值解析为字符串类型。
safeStr 参数位也支持作为 reviver 参数使用,即一个用于转换解析结果的函数,该函数会为对象的每个成员被调用。具体用法可查阅相关资料,此处不再赘述。
仅支持 JavaScript 语言。
回测系统中不支持 JSON.parse() 函数的 safeStr 参数功能。
JSON.stringify
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 | 返回编码后的 |
参数
| 名称 | 类型 | 必填 | 描述 |
obj | string / number / bool / object / array / function / any (平台支持的任意类型) | 是 | 需要编码为JSON字符串的值。 |
备注
仅支持JavaScript语言。
SetChannelData
在频道上发布最新的状态数据。该函数用于实盘之间的通信,可将当前实盘的状态数据广播到频道上,供其他实盘订阅获取。
SetChannelData(data)示例
-
频道广播端示例 - 发布市场行情数据
javascriptfunction 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) // 每分钟更新一次频道状态 } }pythondef 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) # 每分钟更新一次频道状态rustfn main() { let mut updateId = 0; let robotId = _G!(); // 获取当前实盘ID loop { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); continue; } // 获取实时市场价格 let ticker = match exchange.GetTicker("rb888") { Ok(t) => t, Err(_) => { Sleep(5000); continue; } }; // 构建当前频道状态数据 updateId += 1; let timestamp = Unix() * 1000; let channelState = format!( r#"{{"robotId": {}, "updateId": {}, "timestamp": {}, "symbol": "rb888", "lastPrice": {}, "volume": {}, "high": {}, "low": {}}}"#, robotId, updateId, timestamp, ticker.Last, ticker.Volume, ticker.High, ticker.Low ); // 向频道发布最新状态(覆盖旧状态) SetChannelData(&channelState); // 显示当前频道状态 LogStatus!(format!( "频道广播端 [实盘ID: {}]\n更新ID: #{}\n时间: {}\n交易对: rb888\n最新价: ${:.2}\n成交量: {:.4}\n最高价: ${:.2}\n最低价: ${:.2}", robotId, updateId, _D(timestamp), ticker.Last, ticker.Volume, ticker.High, ticker.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 秒发送一次rust// 本示例演示如何使用 HttpQuery 发送 HTTP POST 请求,模拟外部平台向优宽量化实盘发送数据 // 在实际场景中,外部平台(如 TradingView 的 Webhook 告警 URL、第三方交易系统等)会直接调用优宽量化 API 端点 fn main() { let uuid = "6BC42A119B5DBFA2188A8279DA3B5C30"; let robotId = 123456; // 目标实盘 ID(即需要接收数据的实盘) let baseUrl = "https://www.youquant.com"; loop { // 准备要发送的数据(可以是 JSON、文本或其他格式) let sendData = format!( r#"{{"action": "buy", "symbol": "rb888", "price": 3500, "timestamp": {}}}"#, Unix() * 1000 ); // 构造 HTTP POST 请求 let options = format!(r#"{{"method": "POST", "body": {:?}}}"#, sendData); let url = format!("{}/api/v1?method=pub&robot={}&channel={}", baseUrl, robotId, uuid); // 发送数据 let ret: String = HttpQuery(&url, options.as_str()); Log!("Simulated external platform sending data, result:", ret); Sleep(10000); // 每 10 秒发送一次 } }c++
返回值
| 类型 | 描述 |
空值 | 此函数无返回值。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | object / array / string / number / bool / 空值 | 是 | 需要发布到频道的数据,可以是任何能够通过 |
参考
备注
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频道的实盘均可接收数据。
GetChannelData
订阅指定实盘的频道数据。该函数用于实盘间通信,可获取其他实盘通过SetChannelData()函数发布的最新状态数据。
GetChannelData(channelId)示例
-
频道订阅端示例 - 订阅两个实盘的频道数据
javascriptfunction 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秒读取一次频道数据 } }pythondef 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秒读取一次频道数据rustfn main() { // Rust 的 GetChannelData() 函数不接受频道 ID 参数,只能读取当前实盘自身频道 // (即本实盘通过 SetChannelData() 发布)的最新数据,无法订阅其它实盘或 UUID 频道 loop { // 读取频道的当前状态 let state = GetChannelData(); // 构建状态显示内容 let mut statusMsg = String::from("频道订阅端 - 当前订阅状态\n\n"); if !state.is_null() { statusMsg += &format!("更新ID: #{}\n", state["updateId"].as_i64().unwrap_or(0)); statusMsg += &format!("时间: {}\n", _D(state["timestamp"].as_i64().unwrap_or(0))); statusMsg += &format!("交易对: {}\n", state["symbol"].as_str().unwrap_or("")); statusMsg += &format!("最新价: ${:.2}\n", state["lastPrice"].as_f64().unwrap_or(0.0)); statusMsg += &format!("成交量: {:.4}\n", state["volume"].as_f64().unwrap_or(0.0)); } else { statusMsg += "状态: 等待中... (首次调用返回 null)\n"; } LogStatus!(statusMsg); Sleep(5000); // 每5秒读取一次频道数据 } }c++ -
跨平台订阅示例 —— 使用 UUID 订阅外部系统发送的数据
javascriptfunction 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 秒检查一次 } }pythondef 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 秒检查一次rustfn main() { // Rust 的 GetChannelData() 函数不接受频道 ID 参数,只能读取当前实盘自身频道 // (即本实盘通过 SetChannelData() 发布)的最新数据,无法订阅其它实盘或 UUID 频道 loop { // 订阅当前频道的数据 let data = GetChannelData(); if !data.is_null() { Log!("Received cross-platform data:", data); } else { Log!("Waiting for data... (first call returns null)"); } Sleep(10000); // 每 10 秒检查一次 } }c++
返回值
| 类型 | 描述 |
object / array / string / number / bool / 空值 | 返回所订阅频道的最新状态数据。首次调用返回 |
参数
| 名称 | 类型 | 必填 | 描述 |
channelId | string / number | 是 | 频道标识符,支持两种类型:
|
参考
备注
GetChannelData()函数为非阻塞调用,调用后立即返回,不会等待数据接收完成。
首次调用GetChannelData()函数时会返回null,需重试以等待频道数据同步完成。
每次调用获取的均为频道上的最新状态数据,而非历史消息队列。
一个实盘可同时订阅多个不同实盘的频道,只需多次调用GetChannelData()并传入不同的实盘ID即可。
当前实盘也可订阅自身的频道,即robotId参数可为当前实盘ID。
频道数据可跨实盘、跨托管者、跨服务器进行传输。
广播端使用SetChannelData()函数发布频道数据。
频道通信适用于实盘环境,在回测系统中该功能可能受限。
GetChannelData()函数支持跨平台订阅功能。当使用32位UUID作为频道标识符时,可接收来自优宽量化平台外部系统通过HTTP API发送的数据。外部系统需同时指定实盘ID和UUID才能发送数据;同一托管者下的所有实盘均可订阅该UUID频道的数据,而不同托管者的实盘则无法订阅。
Log
Log
输出日志信息。
Log(...msgs)示例
-
可以传入多个
msg参数:javascriptfunction main() { Log("msg1", "msg2", "msg3") }pythondef main(): Log("msg1", "msg2", "msg3")rustfn main() { Log!("msg1", "msg2", "msg3"); }c++void main() { Log("msg1", "msg2", "msg3"); } -
支持设置输出消息的颜色。如果需要同时设置颜色与推送,需先设置颜色,最后使用
@字符启用推送。javascriptfunction main() { Log("优宽量化你好 !@") Sleep(1000 * 5) // 字符串内加入#ff0000,打印日志显示为红色,并且推送消息 Log("你好, #ff0000@") }pythondef main(): Log("优宽量化你好 !@") Sleep(1000 * 5) Log("你好, #ff0000@")rustfn main() { Log!("优宽量化你好 !@"); Sleep(1000 * 5); // 字符串内加入#ff0000,打印日志显示为红色,并且推送消息 Log!("你好, #ff0000@"); }c++void main() { Log("优宽量化你好 !@"); Sleep(1000 * 5); Log("你好, #ff0000@"); } -
Log()函数支持打印经base64编码的图片,以`开头、以`结尾,例如:javascriptfunction main() { Log("`data:image/png;base64,AAAA`") }pythondef main(): Log("`data:image/png;base64,AAAA`")rustfn main() { Log!("`data:image/png;base64,AAAA`"); }c++void main() { Log("`data:image/png;base64,AAAA`"); } -
Log()函数支持直接打印Python的matplotlib.pyplot对象。只要对象包含savefig方法,即可直接使用Log函数打印,例如:pythonimport matplotlib.pyplot as plt def main(): plt.plot([3,6,2,4,7,1]) Log(plt) -
Log()函数支持语言切换。Log()函数输出的文本会根据平台页面的语言设置自动切换为对应的语言,例如:javascriptfunction main() { Log("[trans]中文|abc[/trans]") }pythondef main(): Log("[trans]中文|abc[/trans]")rustfn main() { Log!("[trans]中文|abc[/trans]"); }c++void main() { Log("[trans]中文|abc[/trans]"); }
参数
| 名称 | 类型 | 必填 | 描述 |
msg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 参数 |
参考
备注
Log()函数在实盘或回测系统的日志区域输出一条日志信息,实盘运行时该日志会保存至实盘数据库中。
若Log()函数输出的内容以@字符结尾,则该条日志会进入消息推送队列。
消息将推送到当前优宽量化交易平台账号推送设置中配置的邮箱、WebHook地址等。调试工具与回测系统不支持消息推送。消息推送存在频率限制,具体规则如下:在一个实盘的20秒周期内,仅保留并推送最后一条推送消息,其余消息将被过滤而不予推送(通过 Log 函数输出的推送日志仍会正常打印显示在日志区域)。
若Log()函数输出的内容以&字符结尾,则该条日志将被标记为私密日志。当实盘公开展示时,该条日志对其他用户隐藏,但在实盘拥有者账户视角下不隐藏。可用于记录API密钥、账户余额等敏感信息。例如:Log("私密信息", "&")。
关于WebHook推送,可以使用Golang编写服务程序:
golang
package main
import (
"fmt"
"net/http"
)
func Handle (w http.ResponseWriter, r *http.Request) {
defer func() {
fmt.Println("req:", *r)
}()
}
func main () {
fmt.Println("listen http://localhost:9090")
http.HandleFunc("/data", Handle)
http.ListenAndServe(":9090", nil)
}
在推送设置中设置WebHook地址:http://XXX.XX.XXX.XX:9090/data?data=Hello_youquant。运行编写好的Golang服务程序后,启动策略进行实盘运行。以下为使用JavaScript语言编写的策略,策略运行时会执行Log()函数并推送消息:
javascript
function main() {
Log("msg", "@")
}
Golang语言编写的服务程序接收到推送后,打印如下信息:
text
listen http://localhost:9090
req: {GET /data?data=Hello_youquant HTTP/1.1 1 1
map[User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.x.xxxx.xxx
Safari/537.36] Accept-Encoding:[gzip]] {} <nil> 0 [] false
1XX.XX.X.XX:9090 map[] map[] <nil> map[] XXX.XX.XXX.XX:4xxx2
/data?data=Hello_youquant <nil> <nil> <nil> 0xc420056300
LogProfit
记录并打印盈亏数值,并根据盈亏数值绘制收益曲线。
LogProfit(profit)
LogProfit(profit, ...args)示例
LogProfit函数的参数如果以字符&结尾,则不将日志写入数据库,仅更新收益图表。使用&参数可以避免频繁的收益记录产生大量日志,从而保持日志清爽。例如:
javascript
function main() {
// 在收益图表上打印30个点
for(var i = 0; i < 30; i++) {
LogProfit(i, '&')
Sleep(500)
}
}
python
def main():
for i in range(30):
LogProfit(i, '&')
Sleep(500)
rust
fn main() {
// 在收益图表上打印30个点
// Rust 中 LogProfit 只接受收益数值参数,不支持 '&' 等扩展参数
for i in 0..30 {
LogProfit(i);
Sleep(500);
}
}
c++
void main() {
for(int i = 0; i < 30; i++) {
LogProfit(i, '&');
Sleep(500);
}
}参数
| 名称 | 类型 | 必填 | 描述 |
profit | number | 是 | 参数 |
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,用于向这条收益日志中输出附带信息, |
参考
LogProfitReset
清空所有收益日志与收益图表。
LogProfitReset()
LogProfitReset(remain)示例
在收益图表上打印30个数据点,然后重置,仅保留最后10个数据点。
javascript
function main() {
// 在收益图表上打印30个点,然后重置,只保留最后10个点
for(var i = 0; i < 30; i++) {
LogProfit(i)
Sleep(500)
}
LogProfitReset(10)
}
python
def main():
for i in range(30):
LogProfit(i)
Sleep(500)
LogProfitReset(10)
rust
fn main() {
// 在收益图表上打印30个点,然后重置,只保留最后10个点
for i in 0..30 {
LogProfit(i);
Sleep(500);
}
LogProfitReset(10);
}
c++
void main() {
for(int i = 0; i < 30; i++) {
LogProfit(i);
Sleep(500);
}
LogProfitReset(10);
}参数
| 名称 | 类型 | 必填 | 描述 |
remain | number | 否 |
|
参考
LogStatus
在回测系统或实盘页面的状态栏中输出信息。
LogStatus(...msgs)示例
-
支持设置输出内容的颜色:
javascriptfunction main() { LogStatus('这是一个普通的状态提示') LogStatus('这是一个红色字体的状态提示#ff0000') LogStatus('这是一个多行的状态信息\n我是第二行') }pythondef main(): LogStatus('这是一个普通的状态提示') LogStatus('这是一个红色字体的状态提示#ff0000') LogStatus('这是一个多行的状态信息\n我是第二行')rustfn main() { LogStatus!("这是一个普通的状态提示"); LogStatus!("这是一个红色字体的状态提示#ff0000"); LogStatus!("这是一个多行的状态信息\n我是第二行"); }c++void main() { LogStatus("这是一个普通的状态提示"); LogStatus("这是一个红色字体的状态提示#ff0000"); LogStatus("这是一个多行的状态信息\n我是第二行"); } -
以下是在状态栏中输出数据的示例:
javascriptfunction main() { var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} // 将 JSON 序列化后,在字符串两端加上 ` 字符,即可将其识别为一种复杂消息格式(当前支持表格) LogStatus('`' + JSON.stringify(table) + '`') // 表格信息也可以出现在多行文本中 LogStatus('第一行消息\n`' + JSON.stringify(table) + '`\n第三行消息') // 支持同时显示多个表格,它们将以 TAB 形式归为一组显示 LogStatus('`' + JSON.stringify([table, table]) + '`') // 也可以在表格中构造按钮,策略通过 GetCommand 接收 cmd 属性的内容 var table = { type: 'table', title: '持仓操作', cols: ['列1', '列2', 'Action'], rows: [ ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': '平仓'}] ] } LogStatus('`' + JSON.stringify(table) + '`') // 或者构造一个独立的按钮 LogStatus('`' + JSON.stringify({'type':'button', 'cmd': 'coverAll', 'name': '平仓'}) + '`') // 可以自定义按钮样式(Bootstrap 的按钮属性) LogStatus('`' + JSON.stringify({'type':'button', 'class': 'btn btn-xs btn-danger', 'cmd': 'coverAll', 'name': '平仓'}) + '`') }pythonimport json def main(): table = {"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]} LogStatus('`' + json.dumps(table) + '`') LogStatus('第一行消息\n`' + json.dumps(table) + '`\n第三行消息') LogStatus('`' + json.dumps([table, table]) + '`') table = { "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] } LogStatus('`' + json.dumps(table) + '`') LogStatus('`' + json.dumps({"type": "button", "cmd": "coverAll", "name": "平仓"}) + '`') LogStatus('`' + json.dumps({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"}) + '`')rustfn main() { let table = r#"{"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; // 在 JSON 字符串两端加上 ` 字符,即可将其识别为一种复杂消息格式(当前支持表格) LogStatus!(format!("`{}`", table)); // 表格信息也可以出现在多行文本中 LogStatus!(format!("第一行消息\n`{}`\n第三行消息", table)); // 支持同时显示多个表格,它们将以 TAB 形式归为一组显示 LogStatus!(format!("`[{},{}]`", table, table)); // 也可以在表格中构造按钮,策略通过 GetCommand 接收 cmd 属性的内容 let table = r#"{"type": "table", "title": "持仓操作", "cols": ["列1", "列2", "Action"], "rows": [["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}]]}"#; LogStatus!(format!("`{}`", table)); // 或者构造一个独立的按钮 LogStatus!(r#"`{"type": "button", "cmd": "coverAll", "name": "平仓"}`"#); // 可以自定义按钮样式(Bootstrap 的按钮属性) LogStatus!(r#"`{"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"}`"#); }c++void main() { json table = R"({"type": "table", "title": "持仓信息", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; LogStatus("`" + table.dump() + "`"); LogStatus("第一行消息\n`" + table.dump() + "`\n第三行消息"); json arr = R"([])"_json; arr.push_back(table); arr.push_back(table); LogStatus("`" + arr.dump() + "`"); table = R"({ "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] })"_json; LogStatus("`" + table.dump() + "`"); LogStatus("`" + R"({"type": "button", "cmd": "coverAll", "name": "平仓"})"_json.dump() + "`"); LogStatus("`" + R"({"type": "button", "class": "btn btn-xs btn-danger", "cmd": "coverAll", "name": "平仓"})"_json.dump() + "`"); } -
支持在状态栏中设计按钮控件(旧版按钮结构):
javascriptfunction main() { var table = { type: "table", title: "状态栏按钮样式", cols: ["默认", "原始", "成功", "信息", "警告", "危险"], rows: [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] } LogStatus("`" + JSON.stringify(table) + "`") }pythonimport json def main(): table = { "type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] } LogStatus("`" + json.dumps(table) + "`")rustfn main() { let table = String::from(r#"{"type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [["#) + r#"{"type": "button", "class": "btn btn-xs btn-default", "name": "默认"},"# + r#"{"type": "button", "class": "btn btn-xs btn-primary", "name": "原始"},"# + r#"{"type": "button", "class": "btn btn-xs btn-success", "name": "成功"},"# + r#"{"type": "button", "class": "btn btn-xs btn-info", "name": "信息"},"# + r#"{"type": "button", "class": "btn btn-xs btn-warning", "name": "告警"},"# + r#"{"type": "button", "class": "btn btn-xs btn-danger", "name": "危险"}"# + r#"]]}"#; LogStatus!(format!("`{}`", table)); }c++void main() { json table = R"({ "type": "table", "title": "状态栏按钮样式", "cols": ["默认", "原始", "成功", "信息", "警告", "危险"], "rows": [ [ {"type":"button", "class": "btn btn-xs btn-default", "name": "默认"}, {"type":"button", "class": "btn btn-xs btn-primary", "name": "原始"}, {"type":"button", "class": "btn btn-xs btn-success", "name": "成功"}, {"type":"button", "class": "btn btn-xs btn-info", "name": "信息"}, {"type":"button", "class": "btn btn-xs btn-warning", "name": "告警"}, {"type":"button", "class": "btn btn-xs btn-danger", "name": "危险"} ] ] })"_json; LogStatus("`" + table.dump() + "`"); } -
设置状态栏按钮的禁用及描述功能(旧版按钮结构):
javascriptfunction main() { var table = { type: "table", title: "状态栏按钮的禁用、描述功能测试", cols: ["列1", "列2", "列3"], rows: [] } var button1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} var button2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true} var button3 = {"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false} table.rows.push([button1, button2, button3]) LogStatus("`" + JSON.stringify(table) + "`") }pythonimport json def main(): table = { "type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [] } button1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} button2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": True} button3 = {"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": False} table["rows"].append([button1, button2, button3]) LogStatus("`" + json.dumps(table) + "`")rustfn main() { let button1 = r#"{"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"}"#; let button2 = r#"{"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true}"#; let button3 = r#"{"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false}"#; let table = format!( r#"{{"type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [[{}, {}, {}]]}}"#, button1, button2, button3 ); LogStatus!(format!("`{}`", table)); }c++void main() { json table = R"({ "type": "table", "title": "状态栏按钮的禁用、描述功能测试", "cols": ["列1", "列2", "列3"], "rows": [] })"_json; json button1 = R"({"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"})"_json; json button2 = R"({"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮,设置为禁用", "disabled": true})"_json; json button3 = R"({"type": "button", "name": "按钮3", "cmd": "button3", "description": "这是第三个按钮,设置为启用", "disabled": false})"_json; json arr = R"([])"_json; arr.push_back(button1); arr.push_back(button2); arr.push_back(button3); table["rows"].push_back(arr); LogStatus("`" + table.dump() + "`"); } -
结合
GetCommand()函数,构造状态栏按钮的交互功能(旧版按钮结构):javascriptfunction test1() { Log("调用自定义函数") } function main() { while (true) { var table = { type: 'table', title: '操作', cols: ['列1', '列2', 'Action'], rows: [ ['a', '1', { 'type': 'button', 'cmd': "CoverAll", 'name': '平仓' }], ['b', '1', { 'type': 'button', 'cmd': 10, 'name': '发送数值' }], ['c', '1', { 'type': 'button', 'cmd': _D(), 'name': '调用函数' }], ['d', '1', { 'type': 'button', 'cmd': 'test1', 'name': '调用自定义函数' }] ] } LogStatus(_D(), "\n", '`' + JSON.stringify(table) + '`') var str_cmd = GetCommand() if (str_cmd) { Log("接收到的交互数据 str_cmd:", "类型:", typeof(str_cmd), "值:", str_cmd) if(str_cmd == "test1") { test1() } } Sleep(500) } }pythonimport json def test1(): Log("调用自定义函数") def main(): while True: table = { "type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": [ ["a", "1", { "type": "button", "cmd": "CoverAll", "name": "平仓" }], ["b", "1", { "type": "button", "cmd": 10, "name": "发送数值" }], ["c", "1", { "type": "button", "cmd": _D(), "name": "调用函数" }], ["d", "1", { "type": "button", "cmd": "test1", "name": "调用自定义函数" }] ] } LogStatus(_D(), "\n", "`" + json.dumps(table) + "`") str_cmd = GetCommand() if str_cmd: Log("接收到的交互数据 str_cmd", "类型:", type(str_cmd), "值:", str_cmd) if str_cmd == "test1": test1() Sleep(500)rustfn test1() { Log!("调用自定义函数"); } fn main() { loop { let table = String::from(r#"{"type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": ["#) + r#"["a", "1", {"type": "button", "cmd": "CoverAll", "name": "平仓"}],"# + r#"["b", "1", {"type": "button", "cmd": 10, "name": "发送数值"}],"# + &format!(r#"["c", "1", {{"type": "button", "cmd": "{}", "name": "调用函数"}}],"#, _D(None)) + r#"["d", "1", {"type": "button", "cmd": "test1", "name": "调用自定义函数"}]"# + r#"]}"#; LogStatus!(_D(None), "\n", format!("`{}`", table)); if let Some(str_cmd) = GetCommand(0) { Log!("接收到的交互数据 str_cmd:", "类型:", "String", "值:", &str_cmd); if str_cmd == "test1" { test1(); } } Sleep(500); } }c++void test1() { Log("调用自定义函数"); } void main() { while(true) { json table = R"({ "type": "table", "title": "操作", "cols": ["列1", "列2", "Action"], "rows": [ ["a", "1", { "type": "button", "cmd": "CoverAll", "name": "平仓" }], ["b", "1", { "type": "button", "cmd": 10, "name": "发送数值" }], ["c", "1", { "type": "button", "cmd": "", "name": "调用函数" }], ["d", "1", { "type": "button", "cmd": "test1", "name": "调用自定义函数" }] ] })"_json; table["rows"][2][2]["cmd"] = _D(); LogStatus(_D(), "\n", "`" + table.dump() + "`"); auto str_cmd = GetCommand(); if(str_cmd != "") { Log("接收到的交互数据 str_cmd", "类型:", typeid(str_cmd).name(), "值:", str_cmd); if(str_cmd == "test1") { test1(); } } Sleep(500); } } -
在构造状态栏按钮进行交互时,同样支持输入数据,交互指令最终由
GetCommand()函数捕获。在状态栏按钮控件的数据结构中增加
input项(旧版按钮结构)。例如,为{"type": "button", "cmd": "open", "name": "开仓"}增加:"input": {"name": "开仓数量", "type": "number", "defValue": 1},即可使该按钮在被点击时弹出一个带输入框控件的弹窗(输入框中的默认值为1,即defValue所设置的数据),从而在输入一个数据后与按钮命令一起发送。例如运行以下测试代码,点击「开仓」按钮后会弹出一个带输入框的弹窗,在输入框中输入111并点击「确定」,GetCommand()函数便会捕获到消息:open:111。javascriptfunction main() { var tbl = { type: "table", title: "操作", cols: ["列1", "列2"], rows: [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] } LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`") while (true) { var cmd = GetCommand() if (cmd) { Log("cmd:", cmd) } Sleep(1000) } }pythonimport json def main(): tbl = { "type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] } LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`") while True: cmd = GetCommand() if cmd: Log("cmd:", cmd) Sleep(1000)rustfn main() { let tbl = String::from(r#"{"type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": ["#) + r#"["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}],"# + r#"["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}]"# + r#"]}"#; LogStatus!(_D(None), "\n", format!("`{}`", tbl)); loop { if let Some(cmd) = GetCommand(0) { Log!("cmd:", cmd); } Sleep(1000); } }c++void main() { json tbl = R"({ "type": "table", "title": "操作", "cols": ["列1", "列2"], "rows": [ ["开仓操作", {"type": "button", "cmd": "open", "name": "开仓", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}], ["平仓操作", {"type": "button", "cmd": "coverAll", "name": "全部平仓"}] ] })"_json; LogStatus(_D(), "\n", "`" + tbl.dump() + "`"); while(true) { auto cmd = GetCommand(); if(cmd != "") { Log("cmd:", cmd); } Sleep(1000); } } -
支持分组按钮控件(旧版按钮结构),其功能与支持输入数据的状态栏按钮(使用"input"字段设置)一致。交互指令最终由
GetCommand()函数捕获。区别在于:分组按钮控件通过"group"字段进行设置,当点击按钮触发交互时,页面弹出的对话框中会显示预先设置好的一组输入控件,可以一次性输入一组数据。关于状态栏按钮控件与分组按钮控件结构中的
"group"字段,需要注意以下几点:- group中
type属性仅支持以下4种类型,defValue属性用于设置默认值。
"selected":下拉框控件,设置下拉框的各个选项时使用|符号分隔。
"number":数值输入框控件。
"string":字符串输入框控件。
"boolean":勾选框控件,勾选表示(布尔值)真,不勾选表示(布尔值)假。 - 交互输入时的控件支持依赖设置:
例如以下例子中的"name": "tradePrice@orderType==1"设置,使交易价格(tradePrice)输入控件仅在下单方式(orderType)下拉框控件选择为挂单时可用。 - 交互输入时的控件名称支持双语设置:
例如以下例子中的"description": "下单方式|order type"设置,使用|符号分隔中英文描述内容。 - group中的
name、description与按钮结构中的name、description虽然字段名一致,但定义并不相同:
group中的name与input中的name定义也不相同。 - 分组按钮控件触发后,发送的交互内容格式为:按钮的cmd字段值,加上group字段的相关数据。例如以下例子测试时
Log("cmd:", cmd)语句输出的内容:
cmd: open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true},即发生交互操作时GetCommand()函数返回的内容:open:{"orderType":1,"tradePrice":99,"orderAmount":"99","boolean":true}。 - 按钮控件的
type属性仅支持"button":
支持输入数据的按钮控件,即设置了input属性的控件,其input字段的配置信息中的type属性支持多种控件类型。
参考以下例子:
javascriptfunction main() { var tbl = { type: "table", title: "演示分组按钮控件", cols: ["操作"], rows: [] } // 创建分组按钮控件结构 var groupBtn = { type: "button", cmd: "open", name: "开仓", group: [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true} ] } // 测试按钮1 var testBtn1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} var testBtn2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}} // 在tbl中添加groupBtn tbl.rows.push([groupBtn]) // 支持状态栏表格的一个单元格内设置多个按钮,即一个单元格内的数据为一个按钮结构数组:[testBtn1, testBtn2] tbl.rows.push([[testBtn1, testBtn2]]) while (true) { LogStatus("`" + JSON.stringify(tbl) + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + JSON.stringify(groupBtn) + "`") var cmd = GetCommand() if (cmd) { Log("cmd:", cmd) } Sleep(5000) } }pythonimport json def main(): tbl = { "type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [] } groupBtn = { "type": "button", "cmd": "open", "name": "开仓", "group": [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": True} ] } testBtn1 = {"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"} testBtn2 = {"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}} tbl["rows"].append([groupBtn]) tbl["rows"].append([[testBtn1, testBtn2]]) while True: LogStatus("`" + json.dumps(tbl) + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + json.dumps(groupBtn) + "`") cmd = GetCommand() if cmd: Log("cmd:", cmd) Sleep(5000)rustfn main() { // 创建分组按钮控件结构 let group_btn = String::from(r#"{"type": "button", "cmd": "open", "name": "开仓", "group": ["#) + r#"{"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"},"# + r#"{"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100},"# + r#"{"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100},"# + r#"{"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true}"# + r#"]}"#; // 测试按钮1、测试按钮2 let test_btn1 = r#"{"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"}"#; let test_btn2 = r#"{"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}}"#; // 在tbl中添加groupBtn;支持状态栏表格的一个单元格内设置多个按钮,即一个单元格内的数据为一个按钮结构数组:[testBtn1, testBtn2] let tbl = format!( r#"{{"type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [[{}], [[{}, {}]]]}}"#, group_btn, test_btn1, test_btn2 ); loop { LogStatus!(format!("`{}`", tbl), "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", format!("`{}`", group_btn)); if let Some(cmd) = GetCommand(0) { Log!("cmd:", cmd); } Sleep(5000); } }c++void main() { json tbl = R"({ "type": "table", "title": "演示分组按钮控件", "cols": ["操作"], "rows": [] })"_json; json groupBtn = R"({ "type": "button", "name": "开仓", "cmd": "open", "group": [ {"name": "orderType", "description": "下单方式|order type", "type": "selected", "defValue": "市价单|挂单"}, {"name": "tradePrice@orderType==1", "description": "交易价格|trade price", "type": "number", "defValue": 100}, {"name": "orderAmount", "description": "委托数量|order amount", "type": "string", "defValue": 100}, {"name": "boolean", "description": "是/否|boolean", "type": "boolean", "defValue": true} ]})"_json; json testBtn1 = R"({"type": "button", "name": "按钮1", "cmd": "button1", "description": "这是第一个按钮"})"_json; json testBtn2 = R"({"type": "button", "name": "按钮2", "cmd": "button2", "description": "这是第二个按钮", "input": {"name": "开仓数量", "type": "number", "defValue": 1}})"_json; tbl["rows"].push_back({groupBtn}); tbl["rows"].push_back({{testBtn1, testBtn2}}); while(true) { LogStatus("`" + tbl.dump() + "`", "\n", "分组按钮控件除了设置在状态栏表格中,也可以直接设置在状态栏上:", "`" + groupBtn.dump() + "`"); auto cmd = GetCommand(); if(cmd != "") { Log("cmd:", cmd); } Sleep(5000); } } - group中
-
当状态栏分组按钮控件(通过设置
group字段实现)与状态栏按钮控件(通过设置input字段实现)被点击触发交互时(旧版按钮结构),页面弹出对话框中的下拉框控件同样支持多选。以下示例演示如何设计包含多选选项的下拉框控件:javascriptfunction main() { // 状态栏按钮控件(通过设置input字段实现)中,testBtn1按钮触发页面的下拉框控件通过options字段设置选项,并通过defValue字段设置默认选项。此方式区别于本章其它示例中直接使用defValue设置选项的做法。 var testBtn1 = { type: "button", name: "testBtn1", cmd: "cmdTestBtn1", input: {name: "testBtn1ComboBox", type: "selected", options: ["A", "B"], defValue: 1} } /* 状态栏按钮控件(通过设置input字段实现)中,testBtn2按钮触发页面的下拉框控件通过options字段设置选项。options字段中的选项不仅支持字符串, 也支持使用```{text: "描述", value: "值"}```结构。defValue字段用于设置默认选项,默认选项可以为多选(通过数组结构实现多选)。多选时需额外将multiple字段设置为真值(true)。 */ var testBtn2 = { type: "button", name: "testBtn2", cmd: "cmdTestBtn2", input: { name: "testBtn2MultiComboBox", type: "selected", description: "实现下拉框多选", options: [{text: "选项A", value: "A"}, {text: "选项B", value: "B"}, {text: "选项C", value: "C"}], defValue: ["A", "C"], multiple: true } } // 状态栏分组按钮控件(通过设置group字段实现)中,testBtn3按钮触发页面的下拉框控件通过options字段设置选项,也支持直接使用defValue设置选项。 var testBtn3 = { type: "button", name: "testBtn3", cmd: "cmdTestBtn3", group: [ {name: "comboBox1", label: "labelComboBox1", description: "下拉框1", type: "selected", defValue: 1, options: ["A", "B"]}, {name: "comboBox2", label: "labelComboBox2", description: "下拉框2", type: "selected", defValue: "A|B"}, {name: "comboBox3", label: "labelComboBox3", description: "下拉框3", type: "selected", defValue: [0, 2], multiple: true, options: ["A", "B", "C"]}, { name: "comboBox4", label: "labelComboBox4", description: "下拉框4", type: "selected", defValue: ["A", "C"], multiple: true, options: [{text: "选项A", value: "A"}, {text: "选项B", value: "B"}, {text: "选项C", value: "C"}, {text: "选项D", value: "D"}] } ] } while (true) { LogStatus("`" + JSON.stringify(testBtn1) + "`\n", "`" + JSON.stringify(testBtn2) + "`\n", "`" + JSON.stringify(testBtn3) + "`\n") var cmd = GetCommand() if (cmd) { Log(cmd) } Sleep(5000) } }pythonimport json def main(): testBtn1 = { "type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1} } testBtn2 = { "type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": { "name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选", "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}], "defValue": ["A", "C"], "multiple": True } } testBtn3 = { "type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": [ {"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, {"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"}, {"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": True, "options": ["A", "B", "C"]}, { "name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": True, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}] } ] } while True: LogStatus("`" + json.dumps(testBtn1) + "`\n", "`" + json.dumps(testBtn2) + "`\n", "`" + json.dumps(testBtn3) + "`\n") cmd = GetCommand() if cmd: Log(cmd) Sleep(5000)rustfn main() { // 状态栏按钮控件(通过设置input字段实现)中,testBtn1按钮触发页面的下拉框控件通过options字段设置选项,并通过defValue字段设置默认选项。此方式区别于本章其它示例中直接使用defValue设置选项的做法。 let test_btn1 = r#"{"type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1}}"#; /* 状态栏按钮控件(通过设置input字段实现)中,testBtn2按钮触发页面的下拉框控件通过options字段设置选项。options字段中的选项不仅支持字符串, 也支持使用{"text": "描述", "value": "值"}结构。defValue字段用于设置默认选项,默认选项可以为多选(通过数组结构实现多选)。多选时需额外将multiple字段设置为真值(true)。 */ let test_btn2 = String::from(r#"{"type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": {"#) + r#""name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选","# + r#""options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}],"# + r#""defValue": ["A", "C"], "multiple": true}}"#; // 状态栏分组按钮控件(通过设置group字段实现)中,testBtn3按钮触发页面的下拉框控件通过options字段设置选项,也支持直接使用defValue设置选项。 let test_btn3 = String::from(r#"{"type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": ["#) + r#"{"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]},"# + r#"{"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"},"# + r#"{"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": true, "options": ["A", "B", "C"]},"# + r#"{"name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": true, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}]}"# + r#"]}"#; loop { LogStatus!(format!("`{}`\n", test_btn1), format!("`{}`\n", test_btn2), format!("`{}`\n", test_btn3)); if let Some(cmd) = GetCommand(0) { Log!(cmd); } Sleep(5000); } }c++void main() { json testBtn1 = R"({ "type": "button", "name": "testBtn1", "cmd": "cmdTestBtn1", "input": {"name": "testBtn1ComboBox", "type": "selected", "options": ["A", "B"], "defValue": 1} })"_json; json testBtn2 = R"({ "type": "button", "name": "testBtn2", "cmd": "cmdTestBtn2", "input": { "name": "testBtn2MultiComboBox", "type": "selected", "description": "实现下拉框多选", "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}], "defValue": ["A", "C"], "multiple": true } })"_json; json testBtn3 = R"({ "type": "button", "name": "testBtn3", "cmd": "cmdTestBtn3", "group": [ {"name": "comboBox1", "label": "labelComboBox1", "description": "下拉框1", "type": "selected", "defValue": 1, "options": ["A", "B"]}, {"name": "comboBox2", "label": "labelComboBox2", "description": "下拉框2", "type": "selected", "defValue": "A|B"}, {"name": "comboBox3", "label": "labelComboBox3", "description": "下拉框3", "type": "selected", "defValue": [0, 2], "multiple": true, "options": ["A", "B", "C"]}, { "name": "comboBox4", "label": "labelComboBox4", "description": "下拉框4", "type": "selected", "defValue": ["A", "C"], "multiple": true, "options": [{"text": "选项A", "value": "A"}, {"text": "选项B", "value": "B"}, {"text": "选项C", "value": "C"}, {"text": "选项D", "value": "D"}] } ] })"_json; while (true) { LogStatus("`" + testBtn1.dump() + "`\n", "`" + testBtn2.dump() + "`\n", "`" + testBtn3.dump() + "`\n"); auto cmd = GetCommand(); if (cmd != "") { Log(cmd); } Sleep(5000); } } -
使用当前最新的按钮结构,在状态栏表格中构造按钮;点击按钮触发交互时,会弹出一个包含多个控件的弹窗。
详细内容请参阅:用户指南-状态栏中的交互控件。
javascriptvar symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"] function createBtn(tmp, group) { var btn = JSON.parse(JSON.stringify(tmp)) _.each(group, function(eleByGroup) { btn["group"].unshift(eleByGroup) }) return btn } function main() { var arrManager = [] _.each(symbols, function(symbol) { arrManager.push({ "symbol": symbol, }) }) // Btn var tmpBtnOpen = { "type": "button", "cmd": "open", "name": "开仓下单", "group": [{ "type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": { "options": ["市价单", "限价单"], "required": true, } }, { "type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": { "render": "segment", "required": true, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}], } }, { "type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": { "required": true, } }, { "type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": { "required": true, } }], } while (true) { var tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []} _.each(arrManager, function(m) { var btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "交易品种", "default": m["symbol"], "settings": {"required": true}}]) tbl["rows"].push([m["symbol"], btnOpen]) }) var cmd = GetCommand() if (cmd) { Log("收到交互:", cmd) // 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} // 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 var arrCmd = cmd.split(":", 2) if (arrCmd[0] == "open") { var msg = JSON.parse(cmd.slice(5)) Log("交易品种:", msg["symbol"], ",交易方向:", msg["direction"], ",订单类型:", msg["tradeType"] == 0 ? "市价单" : "限价单", msg["tradeType"] == 0 ? ",订单价格:当前市价" : ",订单价格:" + msg["price"], ",订单数量:", msg["amount"]) } } LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`") Sleep(1000) } }pythonimport json symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"] def createBtn(tmp, group): btn = json.loads(json.dumps(tmp)) for eleByGroup in group: btn["group"].insert(0, eleByGroup) return btn def main(): arrManager = [] for symbol in symbols: arrManager.append({"symbol": symbol}) # Btn tmpBtnOpen = { "type": "button", "cmd": "open", "name": "开仓下单", "group": [{ "type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": { "options": ["市价单", "限价单"], "required": True, } }, { "type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": { "render": "segment", "required": True, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}], } }, { "type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": { "required": True, } }, { "type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": { "required": True, } }], } while True: tbl = {"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": []} for m in arrManager: btnOpen = createBtn(tmpBtnOpen, [{"type": "string", "name": "symbol", "label": "交易品种", "default": m["symbol"], "settings": {"required": True}}]) tbl["rows"].append([m["symbol"], btnOpen]) cmd = GetCommand() if cmd != "" and cmd != None: Log("收到交互:", cmd) # 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} # 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 arrCmd = cmd.split(":") if arrCmd[0] == "open": msg = json.loads(cmd[5:]) Log("交易品种:", msg["symbol"], ",交易方向:", msg["direction"], ",订单类型:", "市价单" if msg["tradeType"] == 0 else "限价单", ",订单价格:当前市价" if msg["tradeType"] == 0 else ",订单价格:" + str(msg["price"]), ",订单数量:", msg["amount"]) # 输出状态栏信息 LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`") Sleep(1000)rustfn main() { let symbols = ["rb2410", "MA501", "hc2501", "i2501", "TA888"]; // Btn:按钮模板,"group"的第一个元素为交易品种控件,__SYMBOL__为占位符,构造按钮时替换 let tmp_btn_open = String::from(r#"{"type": "button", "cmd": "open", "name": "开仓下单", "group": ["#) + r#"{"type": "string", "name": "symbol", "label": "交易品种", "default": "__SYMBOL__", "settings": {"required": true}},"# + r#"{"type": "selected", "name": "tradeType", "label": "下单类型", "description": "市价单、限价单", "default": 0, "group": "交易设置", "settings": {"options": ["市价单", "限价单"], "required": true}},"# + r#"{"type": "selected", "name": "direction", "label": "交易方向", "description": "买入、卖出", "default": "buy", "group": "交易设置", "settings": {"render": "segment", "required": true, "options": [{"name": "买入", "value": "buy"}, {"name": "卖出", "value": "sell"}]}},"# + r#"{"type": "number", "name": "price", "label": "价格", "description": "订单的价格", "group": "交易设置", "filter": "tradeType==1", "settings": {"required": true}},"# + r#"{"type": "number", "name": "amount", "label": "下单量", "description": "订单的下单量", "group": "交易设置", "settings": {"required": true}}"# + r#"]}"#; loop { let mut rows: Vec<String> = Vec::new(); for symbol in &symbols { let btn_open = tmp_btn_open.replace("__SYMBOL__", symbol); rows.push(format!(r#"["{}", {}]"#, symbol, btn_open)); } let tbl = format!(r#"{{"type": "table", "title": "dashboard", "cols": ["symbol", "actionOpen"], "rows": [{}]}}"#, rows.join(",")); if let Some(cmd) = GetCommand(0) { Log!("收到交互:", &cmd); // 解析交互消息: open:{"symbol":"TA888","tradeType":0,"direction":"buy","amount":111} // 根据第一个冒号:之前的指令判断是哪种按钮模板触发的消息 if cmd.starts_with("open:") { let msg = JSONParse(&cmd[5..]).unwrap(); let trade_type = msg["tradeType"].as_i64().unwrap_or(0); Log!("交易品种:", msg["symbol"].as_str().unwrap_or(""), ",交易方向:", msg["direction"].as_str().unwrap_or(""), ",订单类型:", if trade_type == 0 { "市价单" } else { "限价单" }, if trade_type == 0 { ",订单价格:当前市价".to_string() } else { format!(",订单价格:{}", msg["price"].as_f64().unwrap_or(0.0)) }, ",订单数量:", msg["amount"].as_f64().unwrap_or(0.0)); } } LogStatus!(_D(None), "\n", format!("`{}`", tbl)); Sleep(1000); } }c++// 略... -
横向合并
LogStatus()函数绘制的表格中的单元格:javascriptfunction main() { var table = { type: 'table', title: '持仓操作', cols: ['列1', '列2', 'Action'], rows: [ ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': '平仓'}] ] } // 由于是测试代码,未采用商品期货策略的通用架构,此处仅判断 exchange.IO("status") 函数 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") var ticker = exchange.GetTicker() // 添加一行数据,将第一个和第二个单元格合并,并在合并后的单元格内输出 ticker 变量 table.rows.push([{body : JSON.stringify(ticker), colspan : 2}, "abc"]) LogStatus('`' + JSON.stringify(table) + '`') }pythonimport json def main(): table = { "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] } while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") ticker = exchange.GetTicker() table["rows"].append([{"body": json.dumps(ticker), "colspan": 2}, "abc"]) LogStatus("`" + json.dumps(table) + "`")rustfn main() { let table_tpl = String::from(r#"{"type": "table", "title": "持仓操作", "cols": ["列1", "列2", "Action"], "rows": ["#) + r#"["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}],"# + r#"__ROW2__"# + r#"]}"#; // 由于是测试代码,未采用商品期货策略的通用架构,此处仅判断 exchange.IO("status") 函数 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } exchange.SetContractType("rb888").unwrap(); let ticker = exchange.GetTicker(None).unwrap(); let json_ticker = format!( r#"{{"Buy": {}, "Sell": {}, "High": {}, "Low": {}, "Volume": {}, "Last": {}, "Time": {}}}"#, ticker.Buy, ticker.Sell, ticker.High, ticker.Low, ticker.Volume, ticker.Last, ticker.Time ); // 添加一行数据,将第一个和第二个单元格合并,并在合并后的单元格内输出 ticker 数据 let row2 = format!(r#"[{{"body": {}, "colspan": 2}}, "abc"]"#, json_ticker); let table = table_tpl.replace("__ROW2__", &row2); LogStatus!(format!("`{}`", table)); }c++void main() { json table = R"({ "type" : "table", "title" : "持仓操作", "cols" : ["列1", "列2", "Action"], "rows" : [ ["abc", "def", {"type": "button", "cmd": "coverAll", "name": "平仓"}] ] })"_json; while(exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); auto ticker = exchange.GetTicker(); json jsonTicker = R"({"Buy": 0, "Sell": 0, "High": 0, "Low": 0, "Volume": 0, "Last": 0, "Time": 0})"_json; jsonTicker["Buy"] = ticker.Buy; jsonTicker["Sell"] = ticker.Sell; jsonTicker["Last"] = ticker.Last; jsonTicker["Volume"] = ticker.Volume; jsonTicker["Time"] = ticker.Time; jsonTicker["High"] = ticker.High; jsonTicker["Low"] = ticker.Low; json arr = R"([{"body": {}, "colspan": 2}, "abc"])"_json; arr[0]["body"] = jsonTicker; table["rows"].push_back(arr); LogStatus("`" + table.dump() + "`"); } -
纵向合并
LogStatus()函数绘制的表格中的单元格:javascriptfunction main() { var table = { type: 'table', title: '表格演示', cols: ['列A', '列B', '列C'], rows: [ ['A1', 'B1', {'type':'button', 'cmd': 'coverAll', 'name': 'C1'}] ] } // 由于是测试代码,此处不采用商品期货策略的通用架构 while(!exchange.IO("status")) { Sleep(1000) } exchange.SetContractType("rb888") var ticker = exchange.GetTicker() var name = exchange.GetName() table.rows.push([{body : "A2 + B2:" + JSON.stringify(ticker), colspan : 2}, "C2"]) table.rows.push([{body : "A3 + A4 + A5:" + name, rowspan : 3}, "B3", "C3"]) // A3 被上一行的第一个单元格合并 table.rows.push(["B4", "C4"]) // A2 被上一行的第一个单元格合并 table.rows.push(["B5", "C5"]) table.rows.push(["A6", "B6", "C6"]) LogStatus('`' + JSON.stringify(table) + '`') }pythonimport json def main(): table = { "type" : "table", "title" : "表格演示", "cols" : ["列A", "列B", "列C"], "rows" : [ ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}] ] } while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") ticker = exchange.GetTicker() name = exchange.GetName() table["rows"].append([{"body": "A2 + B2:" + json.dumps(ticker), "colspan": 2}, "C2"]) table["rows"].append([{"body": "A3 + A4 + A5:" + name, "rowspan": 3}, "B3", "C3"]) table["rows"].append(["B4", "C4"]) table["rows"].append(["B5", "C5"]) table["rows"].append(["A6", "B6", "C6"]) LogStatus("`" + json.dumps(table) + "`")rustfn main() { // 为了便于测试,代码力求简短易读,此处使用构造的数据 let json_ticker = r#"{"High": 0, "Low": 0, "Buy": 0, "Sell": 0, "Last": 0, "Time": 0, "Volume": 0}"#; let name = exchange.GetName(); let mut rows: Vec<String> = Vec::new(); rows.push(String::from(r#"["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}]"#)); // body 为字符串,其中的引号需转义后再嵌入 JSON let body = format!("A2 + B2:{}", json_ticker).replace('"', "\\\""); rows.push(format!(r#"[{{"body": "{}", "colspan": 2}}, "C2"]"#, body)); rows.push(format!(r#"[{{"body": "A3 + A4 + A5:{}", "rowspan": 3}}, "B3", "C3"]"#, name)); // A3 被上一行的第一个单元格合并 rows.push(String::from(r#"["B4", "C4"]"#)); // A4 被合并 rows.push(String::from(r#"["B5", "C5"]"#)); rows.push(String::from(r#"["A6", "B6", "C6"]"#)); let table = format!(r#"{{"type": "table", "title": "表格演示", "cols": ["列A", "列B", "列C"], "rows": [{}]}}"#, rows.join(",")); LogStatus!(format!("`{}`", table)); }c++void main() { json table = R"({ "type" : "table", "title" : "表格演示", "cols" : ["列A", "列B", "列C"], "rows" : [ ["A1", "B1", {"type": "button", "cmd": "coverAll", "name": "C1"}] ] })"_json; // 为了便于测试,代码力求简短易读,此处使用构造的数据 json jsonTicker = R"({"High": 0, "Low": 0, "Buy": 0, "Sell": 0, "Last": 0, "Time": 0, "Volume": 0})"_json; auto name = exchange.GetName(); json arr1 = R"([{"body": "", "colspan": 2}, "C2"])"_json; arr1[0]["body"] = "A2 + B2:" + jsonTicker.dump(); json arr2 = R"([{"body": "", "rowspan": 3}, "B3", "C3"])"_json; arr2[0]["body"] = "A3 + A4 + A5:" + name; table["rows"].push_back(arr1); table["rows"].push_back(arr2); table["rows"].push_back(R"(["B4", "C4"])"_json); table["rows"].push_back(R"(["B5", "C5"])"_json); table["rows"].push_back(R"(["A6", "B6", "C6"])"_json); LogStatus("`" + table.dump() + "`"); } -
状态栏表格分页显示:
javascriptfunction main() { var table1 = {type: 'table', title: 'table1', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} var table2 = {type: 'table', title: 'table2', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]} LogStatus('`' + JSON.stringify([table1, table2]) + '`') }pythonimport json def main(): table1 = {"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]} table2 = {"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]} LogStatus("`" + json.dumps([table1, table2]) + "`")rustfn main() { let table1 = r#"{"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; let table2 = r#"{"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [["abc", "def"], ["ABC", "support color #ff0000"]]}"#; LogStatus!(format!("`[{},{}]`", table1, table2)); }c++void main() { json table1 = R"({"type": "table", "title": "table1", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; json table2 = R"({"type": "table", "title": "table2", "cols": ["列1", "列2"], "rows": [ ["abc", "def"], ["ABC", "support color #ff0000"]]})"_json; json arr = R"([])"_json; arr.push_back(table1); arr.push_back(table2); LogStatus("`" + arr.dump() + "`"); } -
除了可以分页显示表格外,还可以将多个表格自上而下排列显示:
javascriptfunction main(){ var tab1 = { type : "table", title : "表格1", cols : ["1", "2"], rows : [] } var tab2 = { type : "table", title : "表格2", cols : ["1", "2", "3"], rows : [] } var tab3 = { type : "table", title : "表格3", cols : ["A", "B", "C"], rows : [] } tab1.rows.push(["jack", "lucy"]) tab2.rows.push(["A", "B", "C"]) tab3.rows.push(["A", "B", "C"]) LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n' + '`' + JSON.stringify(tab3) + '`') Log("exit") }pythonimport json def main(): tab1 = { "type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [] } tab2 = { "type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [] } tab3 = { "type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [] } tab1["rows"].append(["jack", "lucy"]) tab2["rows"].append(["A", "B", "C"]) tab3["rows"].append(["A", "B", "C"]) LogStatus("`" + json.dumps(tab1) + "`\n" + "`" + json.dumps(tab2) + "`\n" + "`" + json.dumps(tab3) + "`")rustfn main() { // Rust 中直接把行数据写入JSON字符串中 let tab1 = r#"{"type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [["jack", "lucy"]]}"#; let tab2 = r#"{"type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [["A", "B", "C"]]}"#; let tab3 = r#"{"type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [["A", "B", "C"]]}"#; LogStatus!(format!("`{}`\n`{}`\n`{}`", tab1, tab2, tab3)); }c++void main() { json tab1 = R"({ "type": "table", "title": "表格1", "cols": ["1", "2"], "rows": [] })"_json; json tab2 = R"({ "type": "table", "title": "表格2", "cols": ["1", "2", "3"], "rows": [] })"_json; json tab3 = R"({ "type": "table", "title": "表格3", "cols": ["A", "B", "C"], "rows": [] })"_json; tab1["rows"].push_back(R"(["jack", "lucy"])"_json); tab2["rows"].push_back(R"(["A", "B", "C"])"_json); tab3["rows"].push_back(R"(["A", "B", "C"])"_json); LogStatus("`" + tab1.dump() + "`\n" + "`" + tab2.dump() + "`\n" + "`" + tab3.dump() + "`"); } -
支持设置状态栏表格的横向、纵向滚动模式。将
scroll属性设置为"auto"后,当状态栏表格的纵向行数超过20行时,内容将自动滚动显示;当横向列数超出页面显示范围时,将进行横向滚动显示。使用scroll属性可以缓解实盘运行时状态栏中因大量写入数据而导致的卡顿问题。请参考以下测试示例:javascriptfunction main() { var tbl = { type : "table", title : "test scroll", scroll : "auto", cols : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], rows : [] } for (var i = 1 ; i < 100 ; i++) { tbl.rows.push([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i]) } LogStatus("`" + JSON.stringify(tbl) + "`") }pythonimport json def main(): tbl = { "type" : "table", "title" : "test scroll", "scroll" : "auto", "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], "rows" : [] } for index in range(1, 100): i = str(index) tbl["rows"].append([i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i]) LogStatus("`" + json.dumps(tbl) + "`")rustfn main() { let tbl_tpl = String::from(r#"{"type": "table", "title": "test scroll", "scroll": "auto", "cols": ["#) + r#""col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10","# + r#""col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20""# + r#"], "rows": [__ROWS__]}"#; let mut rows: Vec<String> = Vec::new(); for index in 1..100 { let i = index.to_string(); rows.push(format!( r#"["{}", "1,{}", "2,{}", "3,{}", "4,{}", "5,{}", "6,{}", "7,{}", "8,{}", "9,{}", "10,{}", "11,{}", "12,{}", "13,{}", "14,{}", "15,{}", "16,{}", "17,{}", "18,{}", "19,{}", "20,{}"]"#, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i )); } let tbl = tbl_tpl.replace("__ROWS__", &rows.join(",")); LogStatus!(format!("`{}`", tbl)); }c++void main() { json table = R"({ "type" : "table", "title" : "test scroll", "scroll" : "auto", "cols" : ["col 0", "col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9", "col 10", "col 11", "col 12", "col 13", "col 14", "col 15", "col 16", "col 17", "col 18", "col 19", "col 20"], "rows" : [] })"_json; for (int index = 1; index < 100; ++index) { std::string i = std::to_string(index); table["rows"].push_back({i, "1," + i, "2," + i, "3," + i, "4," + i, "5," + i, "6," + i, "7," + i, "8," + i, "9," + i, "10," + i, "11," + i, "12," + i, "13," + i, "14," + i, "15," + i, "16," + i, "17," + i, "18," + i, "19," + i, "20," + i}); } LogStatus("`" + table.dump() + "`"); }
参数
| 名称 | 类型 | 必填 | 描述 |
msg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 参数 |
参考
备注
实盘运行时,LogStatus()函数输出的信息不会保存到实盘数据库中,仅更新当前实盘状态栏的内容。
LogStatus()函数支持打印经过base64编码的图片,图片数据需以`开头,并以`结尾。例如:LogStatus("`data:image/png;base64,AAAA`")。
LogStatus()函数支持直接传入Python的matplotlib.pyplot对象。只要对象包含savefig方法,即可作为参数传入LogStatus()函数,例如:
python
import matplotlib.pyplot as plt
def main():
plt.plot([3,6,2,4,7,1])
LogStatus(plt)
策略实盘运行时,若在实盘页面翻看历史记录,状态栏会进入休眠状态并停止更新;只有当日志停留在第一页时,状态栏数据才会刷新。状态栏支持输出经过base64编码的图片,也支持在状态栏显示的表格中输出经过base64编码的图片。由于编码后的图片字符串数据通常很长,因此此处不再展示范例代码。
EnableLog
启用或关闭订单信息的日志记录。
EnableLog(enable)示例
关闭订单信息的日志记录。
javascript
function main() {
EnableLog(false)
}
python
def main():
EnableLog(False)
rust
fn main() {
EnableLog(false);
}
c++
void main() {
EnableLog(false);
}参数
| 名称 | 类型 | 必填 | 描述 |
enable | bool | 是 | 当 |
参考
Chart
用于自定义绘制图表的函数。
Chart(options)示例
-
多图表绘制配置:
extension.layout属性
若将该属性设置为 "single",则图表不会叠加显示(即不以分页标签的方式显示),而是独立平铺显示。extension.height属性
该属性用于设置图表的高度,取值可以为数值类型,也可以采用 "300px" 的形式设置。extension.col属性
该属性用于设置图表的宽度。页面宽度共划分为 12 个单元,设置为 8 即表示该图表占用 8 个单元的宽度。
javascriptfunction main() { var cfgA = { extension: { layout: 'single', // 不参与分组,单独显示,默认为分组 'group' height: 300, // 指定高度 }, title: { text: '盘口图表' }, xAxis: { type: 'datetime' }, series: [{ name: '买一', data: [], }, { name: '卖一', data: [], }] } var cfgB = { title: { text: '差价图' }, xAxis: { type: 'datetime' }, series: [{ name: '差价', type: 'column', data: [], }] } var cfgC = { __isStock: false, title: { text: '饼图' }, series: [{ type: 'pie', name: 'one', data: [ ["A", 25], ["B", 25], ["C", 25], ["D", 25], ] // 指定初始数据后无需使用 add 函数更新,直接更改图表配置即可更新序列 }] }; var cfgD = { extension: { layout: 'single', col: 8, // 指定宽度所占的单元值,总值为 12 height: '300px', }, title: { text: '盘口图表' }, xAxis: { type: 'datetime' }, series: [{ name: '买一', data: [], }, { name: '卖一', data: [], }] } var cfgE = { __isStock: false, extension: { layout: 'single', col: 4, height: '300px', }, title: { text: '饼图2' }, series: [{ type: 'pie', name: 'one', data: [ ["A", 25], ["B", 25], ["C", 25], ["D", 25], ] }] }; var chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE]); chart.reset() // 为饼图追加一个数据点,add 只能更新通过 add 方式添加的数据点,内置的数据点无法后期更新 chart.add(3, { name: "ZZ", y: Math.random() * 100 }); while (true) { Sleep(1000) exchange.SetContractType("rb888") var ticker = exchange.GetTicker() if (!ticker) { continue; } var diff = ticker.Sell - ticker.Buy cfgA.subtitle = { text: '买一 ' + ticker.Buy + ', 卖一 ' + ticker.Sell, }; cfgB.subtitle = { text: '价差 ' + diff, }; chart.add([0, [new Date().getTime(), ticker.Buy]]); chart.add([1, [new Date().getTime(), ticker.Sell]]); // 相当于更新第二个图表的第一个数据序列 chart.add([2, [new Date().getTime(), diff]]); chart.add(4, [new Date().getTime(), ticker.Buy]); chart.add(5, [new Date().getTime(), ticker.Buy]); cfgC.series[0].data[0][1] = Math.random() * 100; cfgE.series[0].data[0][1] = Math.random() * 100; // update 实际上等于重置图表的配置 chart.update([cfgA, cfgB, cfgC, cfgD, cfgE]); } }pythonimport random import time def main(): cfgA = { "extension" : { "layout" : "single", "height" : 300, "col" : 8 }, "title" : { "text" : "盘口图表" }, "xAxis" : { "type" : "datetime" }, "series" : [{ "name" : "买一", "data" : [] }, { "name" : "卖一", "data" : [] }] } cfgB = { "title" : { "text" : "差价图" }, "xAxis" : { "type" : "datetime", }, "series" : [{ "name" : "差价", "type" : "column", "data" : [] }] } cfgC = { "__isStock" : False, "title" : { "text" : "饼图" }, "series" : [{ "type" : "pie", "name" : "one", "data" : [ ["A", 25], ["B", 25], ["C", 25], ["D", 25], ] }] } cfgD = { "extension" : { "layout" : "single", "col" : 8, "height" : "300px" }, "title" : { "text" : "盘口图表" }, "series" : [{ "name" : "买一", "data" : [] }, { "name" : "卖一", "data" : [] }] } cfgE = { "__isStock" : False, "extension" : { "layout" : "single", "col" : 4, "height" : "300px" }, "title" : { "text" : "饼图2" }, "series" : [{ "type" : "pie", "name" : "one", "data" : [ ["A", 25], ["B", 25], ["C", 25], ["D", 25] ] }] } chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE]) chart.reset() chart.add(3, { "name" : "ZZ", "y" : random.random() * 100 }) while True: Sleep(1000) exchange.SetContractType("rb888") ticker = exchange.GetTicker() if not ticker : continue diff = ticker["Sell"] - ticker["Buy"] cfgA["subtitle"] = { "text" : "买一" + str(ticker["Buy"]) + "卖一" + str(ticker["Sell"]) } cfgB["subtitle"] = { "text" : "价差 " + str(diff) } chart.add(0, [time.time() * 1000, ticker["Buy"]]) chart.add(1, [time.time() * 1000, ticker["Sell"]]) chart.add(2, [time.time() * 1000, diff]) chart.add(4, [time.time() * 1000, ticker["Buy"]]) chart.add(5, [time.time() * 1000, ticker["Buy"]]) cfgC["series"][0]["data"][0][1] = random.random() * 100 cfgE["series"][0]["data"][0][1] = random.random() * 100rustfn main() { // Rust 中图表配置为 JSON 字符串,可变部分使用占位符表示,更新时替换占位符重新构建配置 let cfg_a_tpl = r#"{ "extension": { "layout": "single", "height": 300, "col": 8 }, "title": {"text": "盘口图表"}, "subtitle": {"text": "__SUBTITLE__"}, "xAxis": {"type": "datetime"}, "series": [{"name": "买一", "data": []}, {"name": "卖一", "data": []}] }"#; let cfg_b_tpl = r#"{ "title": {"text": "差价图"}, "subtitle": {"text": "__SUBTITLE__"}, "xAxis": {"type": "datetime"}, "series": [{"name": "差价", "type": "column", "data": []}] }"#; let cfg_c_tpl = r#"{ "__isStock": false, "title": {"text": "饼图"}, "series": [{ "type": "pie", "name": "one", "data": [["A", __Y__], ["B", 25], ["C", 25], ["D", 25]] }] }"#; let cfg_d = r#"{ "extension": { "layout": "single", "col": 8, "height": "300px" }, "title": {"text": "盘口图表"}, "xAxis": {"type": "datetime"}, "series": [{"name": "买一", "data": []}, {"name": "卖一", "data": []}] }"#; let cfg_e_tpl = r#"{ "__isStock": false, "extension": { "layout": "single", "col": 4, "height": "300px" }, "title": {"text": "饼图2"}, "series": [{ "type": "pie", "name": "one", "data": [["A", __Y__], ["B", 25], ["C", 25], ["D", 25]] }] }"#; let cfg_a = cfg_a_tpl.replace("__SUBTITLE__", ""); let cfg_b = cfg_b_tpl.replace("__SUBTITLE__", ""); let cfg_c = cfg_c_tpl.replace("__Y__", "25"); let cfg_e = cfg_e_tpl.replace("__Y__", "25"); let chart = Chart::new(&format!("[{},{},{},{},{}]", cfg_a, cfg_b, cfg_c, cfg_d, cfg_e)); chart.reset(0); // 为饼图追加一个数据点,add 只能更新通过 add 方式添加的数据点,内置的数据点无法后期更新 let y = (UnixNano() % 100) as f64; // 用时间戳模拟随机数 chart.add(3, &format!(r#"{{"name": "ZZ", "y": {}}}"#, y), -1); loop { Sleep(1000); let _ = exchange.SetContractType("rb888"); let ticker = match exchange.GetTicker(None) { Ok(t) => t, Err(_) => continue, }; let diff = ticker.Sell - ticker.Buy; let cfg_a = cfg_a_tpl.replace("__SUBTITLE__", &format!("买一 {}, 卖一 {}", ticker.Buy, ticker.Sell)); let cfg_b = cfg_b_tpl.replace("__SUBTITLE__", &format!("价差 {}", diff)); let now = Unix() * 1000; chart.add(0, &format!("[{}, {}]", now, ticker.Buy), -1); chart.add(1, &format!("[{}, {}]", now, ticker.Sell), -1); // 相当于更新第二个图表的第一个数据序列 chart.add(2, &format!("[{}, {}]", now, diff), -1); chart.add(4, &format!("[{}, {}]", now, ticker.Buy), -1); chart.add(5, &format!("[{}, {}]", now, ticker.Buy), -1); let cfg_c = cfg_c_tpl.replace("__Y__", &format!("{}", (UnixNano() % 100) as f64)); let cfg_e = cfg_e_tpl.replace("__Y__", &format!("{}", (UnixNano() % 100) as f64)); // update 实际上等于重置图表的配置 chart.update(&format!("[{},{},{},{},{}]", cfg_a, cfg_b, cfg_c, cfg_d, cfg_e)); } }c++void main() { json cfgA = R"({ "extension" : { "layout" : "single", "height" : 300, "col" : 8 }, "title" : { "text" : "盘口图表" }, "xAxis" : { "type" : "datetime" }, "series" : [{ "name" : "买一", "data" : [] }, { "name" : "卖一", "data" : [] }] })"_json; json cfgB = R"({ "title" : { "text" : "差价图" }, "xAxis" : { "type" : "datetime" }, "series" : [{ "name" : "差价", "type" : "column", "data" : [] }] })"_json; json cfgC = R"({ "__isStock" : false, "title" : { "text" : "饼图" }, "series" : [{ "type" : "pie", "name" : "one", "data" : [ ["A", 25], ["B", 25], ["C", 25], ["D", 25] ] }] })"_json; json cfgD = R"({ "extension" : { "layout" : "single", "col" : 8, "height" : "300px" }, "title" : { "text" : "盘口图表" }, "series" : [{ "name" : "买一", "data" : [] }, { "name" : "卖一", "data" : [] }] })"_json; json cfgE = R"({ "__isStock" : false, "extension" : { "layout" : "single", "col" : 4, "height" : "300px" }, "title" : { "text" : "饼图2" }, "series" : [{ "type" : "pie", "name" : "one", "data" : [ ["A", 25], ["B", 25], ["C", 25], ["D", 25] ] }] })"_json; auto chart = Chart({cfgA, cfgB, cfgC, cfgD, cfgE}); chart.reset(); json zz = R"({ "name" : "ZZ", "y" : 0 })"_json; zz["y"] = rand() % 100; chart.add(3, zz); while(true) { Sleep(1000); exchange.SetContractType("rb888"); auto ticker = exchange.GetTicker(); if(!ticker.Valid) { continue; } auto diff = ticker.Sell - ticker.Buy; json cfgASubTitle = R"({"text" : ""})"_json; cfgASubTitle["text"] = str_format("买一 %f , 卖一 %f", ticker.Buy, ticker.Sell); cfgA["subtitle"] = cfgASubTitle; json cfgBSubTitle = R"({"text" : ""})"_json; cfgBSubTitle["text"] = str_format("价差 %f", diff); cfgB["subtitle"] = cfgBSubTitle; chart.add(0, {Unix() * 1000, ticker.Buy}); chart.add(1, {Unix() * 1000, ticker.Sell}); chart.add(2, {Unix() * 1000, diff}); chart.add(4, {Unix() * 1000, ticker.Buy}); chart.add(5, {Unix() * 1000, ticker.Buy}); cfgC["series"][0]["data"][0][1] = rand() % 100; cfgE["series"][0]["data"][0][1] = rand() % 100; chart.update({cfgA, cfgB, cfgC, cfgD, cfgE}); } } -
简单的绘图示例:
javascript// 在 JavaScript 中,chart 是一个对象。在调用 Chart 函数之前,我们需要先声明一个用于配置图表的对象变量 chart var chart = { // 该字段标记图表是否为普通图表,感兴趣的话可以改成 false 运行看看 __isStock: true, // 工具提示 tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // 标题 title : { text : '差价分析图'}, // 范围选择器 rangeSelector: { buttons: [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}], selected: 0, inputEnabled: false }, // 横坐标轴(即 x 轴),当前设置的类型为时间 xAxis: { type: 'datetime'}, // 纵坐标轴(即 y 轴),默认数值随数据大小自动调整 yAxis : { // 标题 title: {text: '差价'}, // 是否启用右侧纵轴 opposite: false }, // 数据系列,该属性保存各个数据系列(折线、K 线图、标签等) series : [ // 索引为 0,data 数组内存放的是该索引系列的数据 {name : "line1", id : "线1,buy1Price", data : []}, // 索引为 1,设置了 dashStyle: 'shortdash',即设置为虚线 {name : "line2", id : "线2,lastPrice", dashStyle : 'shortdash', data : []} ] } function main(){ // 调用 Chart 函数,初始化图表 var ObjChart = Chart(chart) // 清空 ObjChart.reset() while(true){ // 判断是否成功连接期货公司前置机。股票、证券无需使用 exchange.IO("status") 判断连接状态 if (!exchange.IO("status")) { Sleep(1000) continue } exchange.SetContractType("rb888") // 获取本次轮询的时间戳(毫秒级),用于确定写入图表的 X 轴位置 var nowTime = new Date().getTime() // 获取行情数据 var ticker = _C(exchange.GetTicker) // 从行情数据的返回值中取得买一价 var buy1Price = ticker.Buy // 取得最新成交价,为了使两条线不重合,这里加 1 var lastPrice = ticker.Last + 1 // 以时间戳作为 X 值、买一价作为 Y 值,传入索引 0 的数据序列 ObjChart.add(0, [nowTime, buy1Price]) // 同上 ObjChart.add(1, [nowTime, lastPrice]) Sleep(2000) } }pythonimport time chart = { "__isStock" : True, "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"}, "title" : {"text" : "差价分析图"}, "rangeSelector" : { "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], "selected": 0, "inputEnabled": False }, "xAxis": {"type": "datetime"}, "yAxis": { "title": {"text": "差价"}, "opposite": False }, "series": [{ "name": "line1", "id": "线1,buy1Price", "data": [] }, { "name": "line2", "id": "线2,lastPrice", "dashStyle": "shortdash", "data": [] }] } def main(): ObjChart = Chart(chart) ObjChart.reset() while True: if not exchange.IO("status"): Sleep(1000) continue exchange.SetContractType("rb888") nowTime = time.time() * 1000 ticker = exchange.GetTicker() buy1Price = ticker["Buy"] lastPrice = ticker["Last"] + 1 ObjChart.add(0, [nowTime, buy1Price]) ObjChart.add(1, [nowTime, lastPrice]) Sleep(2000)rustfn main() { // 在 Rust 中图表配置为 JSON 字符串,在使用 Chart::new 之前先定义配置内容 let chart = r#"{ "__isStock": true, "tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S, %A"}, "title": {"text": "差价分析图"}, "rangeSelector": { "buttons": [{"type": "hour", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], "selected": 0, "inputEnabled": false }, "xAxis": {"type": "datetime"}, "yAxis": { "title": {"text": "差价"}, "opposite": false }, "series": [{ "name": "line1", "id": "线1,buy1Price", "data": [] }, { "name": "line2", "id": "线2,lastPrice", "dashStyle": "shortdash", "data": [] }] }"#; // 调用 Chart::new 函数,初始化图表 let obj_chart = Chart::new(chart); // 清空 obj_chart.reset(0); loop { // 判断是否成功连接期货公司前置机。股票、证券无需使用 exchange.IO("status") 判断连接状态 if exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); continue; } let _ = exchange.SetContractType("rb888"); // 获取本次轮询的时间戳(毫秒级),用于确定写入图表的 X 轴位置 let now_time = Unix() * 1000; // 获取行情数据 let ticker = _C!(exchange.GetTicker(None)); // 从行情数据的返回值中取得买一价 let buy1_price = ticker.Buy; // 取得最新成交价,为了使两条线不重合,这里加 1 let last_price = ticker.Last + 1.0; // 以时间戳作为 X 值、买一价作为 Y 值,传入索引 0 的数据序列 obj_chart.add(0, &format!("[{}, {}]", now_time, buy1_price), -1); // 同上 obj_chart.add(1, &format!("[{}, {}]", now_time, last_price), -1); Sleep(2000); } }c++void main() { // 使用 C++ 编写策略时,尽量不要声明非基础类型的全局变量,因此图表配置对象声明在 main 函数内 json chart = R"({ "__isStock" : true, "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"}, "title" : {"text" : "差价分析图"}, "rangeSelector" : { "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], "selected": 0, "inputEnabled": false }, "xAxis": {"type": "datetime"}, "yAxis": { "title": {"text": "差价"}, "opposite": false }, "series": [{ "name": "line1", "id": "线1,buy1Price", "data": [] }, { "name": "line2", "id": "线2,lastPrice", "dashStyle": "shortdash", "data": [] }] })"_json; auto ObjChart = Chart(chart); ObjChart.reset(); while(true) { if (exchange.IO("status") == 0) { Sleep(1000); continue; } exchange.SetContractType("rb888"); auto nowTime = Unix() * 1000; auto ticker = exchange.GetTicker(); auto buy1Price = ticker.Buy; auto lastPrice = ticker.Last + 1.0; ObjChart.add(0, {nowTime, buy1Price}); ObjChart.add(1, {nowTime, lastPrice}); Sleep(2000); } } -
三角函数曲线绘图示例:
javascript// 用于初始化图表的配置对象 var chart = { // 图表标题 title: {text: "line数值触发 plotLines 值"}, // Y 轴相关设置 yAxis: { // 垂直于 Y 轴的水平线,用作触发线;这是一个结构数组,可以设置多条触发线 plotLines: [{ // 触发线的值,设置为多少,该触发线就显示在对应的数值位置 value: 0, // 设置触发线的颜色 color: 'red', // 宽度 width: 2, // 显示的标签 label: { // 标签文本 text: '触发值', // 标签位置居中 align: 'center' } }] }, // X 轴相关设置,此处将类型设置为时间轴 xAxis: {type: "datetime"}, series: [ {name: "sin", type: "spline", data: []}, // 这是较为重要的数据系列,可以设置多个数据系列,通过数组索引进行控制 {name: "cos", type: "spline", data: []} ] } function main(){ // 圆周率 var pi = 3.1415926535897 // 用于记录时间戳的变量 var time = 0 // 角度 var angle = 0 // 坐标 y 值,用于接收正弦值或余弦值 var y = 0 // 调用 API 接口,使用 chart 对象初始化图表 var objChart = Chart(chart) // 初始化时清空图表 objChart.reset() // 将触发线的值设置为 1 chart.yAxis.plotLines[0].value = 1 // 循环 while(true){ // 获取当前时刻的时间戳 time = new Date().getTime() // 每 5 秒将角度 angle 增加 5 度,并计算正弦值 y = Math.sin(angle * 2 * pi / 360) // 将计算得到的 y 值写入图表中对应索引的数据系列;add 函数的第一个参数为指定的数据系列索引 objChart.add(0, [time, y]) // 计算余弦值 y = Math.cos(angle * 2 * pi / 360) objChart.add(1, [time, y]) // 角度增加 5 度 angle += 5 // 暂停 5 秒,避免绘图过于频繁、数据增长过快 Sleep(5000) } }pythonimport math import time chart = { "title": {"text": "line数值触发 plotLines 值"}, "yAxis": { "plotLines": [{ "value": 0, "color": "red", "width": 2, "label": { "text": "触发值", "align": "center" } }] }, "xAxis": {"type": "datetime"}, "series": [{"name": "sin", "type": "spline", "data": []}, {"name": "cos", "type": "spline", "data": []}] } def main(): pi = 3.1415926535897 ts = 0 angle = 0 y = 0 objChart = Chart(chart) objChart.reset() chart["yAxis"]["plotLines"][0]["value"] = 1 while True: ts = time.time() * 1000 y = math.sin(angle * 2 * pi / 360) objChart.add(0, [ts, y]) y = math.cos(angle * 2 * pi / 360) objChart.add(1, [ts, y]) angle += 5 Sleep(5000)rustfn main() { // 用于初始化图表的 JSON 配置字符串,触发线的值在配置中直接设置为 1 let chart = r#"{ "title": {"text": "line数值触发 plotLines 值"}, "yAxis": { "plotLines": [{ "value": 1, "color": "red", "width": 2, "label": { "text": "触发值", "align": "center" } }] }, "xAxis": {"type": "datetime"}, "series": [{"name": "sin", "type": "spline", "data": []}, {"name": "cos", "type": "spline", "data": []}] }"#; // 圆周率 let pi = 3.1415926535897_f64; // 角度 let mut angle = 0.0_f64; // 调用 API 接口,使用 chart 配置初始化图表 let obj_chart = Chart::new(chart); // 初始化时清空图表 obj_chart.reset(0); // 循环 loop { // 获取当前时刻的毫秒时间戳 let ts = Unix() * 1000; // 每 5 秒将角度 angle 增加 5 度,并计算正弦值 let mut y = (angle * 2.0 * pi / 360.0).sin(); // 将计算得到的 y 值写入图表中对应索引的数据系列;add 函数的第一个参数为指定的数据系列索引 obj_chart.add(0, &format!("[{}, {}]", ts, y), -1); // 计算余弦值 y = (angle * 2.0 * pi / 360.0).cos(); obj_chart.add(1, &format!("[{}, {}]", ts, y), -1); // 角度增加 5 度 angle += 5.0; // 暂停 5 秒,避免绘图过于频繁、数据增长过快 Sleep(5000); } }c++void main() { json chart = R"({ "title": {"text": "line数值触发 plotLines 值"}, "yAxis": { "plotLines": [{ "value": 0, "color": "red", "width": 2, "label": { "text": "触发值", "align": "center" } }] }, "xAxis": {"type": "datetime"}, "series": [{"name": "sin", "type": "spline", "data": []}, {"name": "cos", "type": "spline", "data": []}] })"_json; auto pi = 3.1415926535897; auto ts = 0; auto angle = 0.0; auto y = 0.0; auto objChart = Chart(chart); objChart.reset(); chart["yAxis"]["plotLines"][0]["value"] = 1; while(true) { ts = Unix() * 1000; y = sin(angle * 2 * pi / 360); objChart.add(0, {ts, y}); y = cos(angle * 2 * pi / 360); objChart.add(1, {ts, y}); angle += 5; Sleep(5000); } } -
使用混合图表的复杂示例:
javascriptvar chartCfg = { subtitle: { text: "subtitle", }, yAxis: [{ height: "40%", lineWidth: 2, title: { text: 'PnL', }, tickPixelInterval: 20, minorGridLineWidth: 1, minorTickWidth: 0, opposite: true, labels: { align: "right", x: -3, } }, { title: { text: 'Profit', }, top: "42%", height: "18%", offset: 0, lineWidth: 2 }, { title: { text: 'Vol', }, top: '62%', height: '18%', offset: 0, lineWidth: 2 }, { title: { text: 'Asset', }, top: '82%', height: '18%', offset: 0, lineWidth: 2 }], series: [{ name: 'PnL', data: [], id: 'primary', tooltip: { xDateFormat: '%Y-%m-%d %H:%M:%S' }, yAxis: 0 }, { type: 'column', lineWidth: 2, name: 'Profit', data: [], yAxis: 1, }, { type: 'column', name: 'Trade', data: [], yAxis: 2 }, { type: 'area', step: true, lineWidth: 0, name: 'Long', data: [], yAxis: 2 }, { type: 'area', step: true, lineWidth: 0, name: 'Short', data: [], yAxis: 2 }, { type: 'line', step: true, color: '#5b4b00', name: 'Asset', data: [], yAxis: 3 }, { type: 'pie', innerSize: '70%', name: 'Random', data: [], center: ['3%', '6%'], size: '15%', dataLabels: { enabled: false }, startAngle: -90, endAngle: 90, }], }; function main() { let c = Chart(chartCfg); let preTicker = null; while (true) { if (!exchange.IO("status")) { Sleep(1000) continue } exchange.SetContractType("rb888") let t = exchange.GetTicker(); c.add(0, [t.Time, t.Last]); // PnL c.add(1, [t.Time, preTicker ? t.Last - preTicker.Last : 0]); // profit let r = Math.random(); var pos = parseInt(t.Time/86400); c.add(2, [t.Time, pos/2]); // Vol c.add(3, [t.Time, r > 0.8 ? pos : null]); // Long c.add(4, [t.Time, r < 0.8 ? -pos : null]); // Short c.add(5, [t.Time, Math.random() * 100]); // Asset // update pie chartCfg.series[chartCfg.series.length-1].data = [ ["A", Math.random()*100], ["B", Math.random()*100], ]; c.update(chartCfg) preTicker = t; } }pythonimport random chartCfg = { "subtitle": { "text": "subtitle" }, "yAxis": [{ "height": "40%", "lineWidth": 2, "title": { "text": 'PnL' }, "tickPixelInterval": 20, "minorGridLineWidth": 1, "minorTickWidth": 0, "opposite": True, "labels": { "align": "right", "x": -3 } }, { "title": { "text": 'Profit' }, "top": "42%", "height": "18%", "offset": 0, "lineWidth": 2 }, { "title": { "text": 'Vol' }, "top": '62%', "height": '18%', "offset": 0, "lineWidth": 2 }, { "title": { "text": 'Asset' }, "top": '82%', "height": '18%', "offset": 0, "lineWidth": 2 }], "series": [{ "name": 'PnL', "data": [], "id": 'primary', "tooltip": { "xDateFormat": '%Y-%m-%d %H:%M:%S' }, "yAxis": 0 }, { "type": 'column', "lineWidth": 2, "name": 'Profit', "data": [], "yAxis": 1 }, { "type": 'column', "name": 'Trade', "data": [], "yAxis": 2 }, { "type": 'area', "step": True, "lineWidth": 0, "name": 'Long', "data": [], "yAxis": 2 }, { "type": 'area', "step": True, "lineWidth": 0, "name": 'Short', "data": [], "yAxis": 2 }, { "type": 'line', "step": True, "color": '#5b4b00', "name": 'Asset', "data": [], "yAxis": 3 }, { "type": 'pie', "innerSize": '70%', "name": 'Random', "data": [], "center": ['3%', '6%'], "size": '15%', "dataLabels": { "enabled": False }, "startAngle": -90, "endAngle": 90 }] } def main(): c = Chart(chartCfg) preTicker = None while True: if not exchange.IO("status"): Sleep(1000) continue exchange.SetContractType("rb888") t = exchange.GetTicker() c.add(0, [t["Time"], t["Last"]]) profit = t["Last"] - preTicker["Last"] if preTicker else 0 c.add(1, [t["Time"], profit]) r = random.random() pos = t["Time"] / 86400 c.add(2, [t["Time"], pos / 2]) long = pos if r > 0.8 else None c.add(3, [t["Time"], long]) short = -pos if r < 0.8 else None c.add(4, [t["Time"], short]) c.add(5, [t["Time"], random.random() * 100]) # update pie chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [ ["A", random.random() * 100], ["B", random.random() * 100] ] c.update(chartCfg) preTicker = trustfn main() { // 在 Rust 中,图表配置为 JSON 字符串;饼图数据使用占位符 __PIE_DATA__ 表示,更新时替换该占位符后重建配置 let chart_cfg_tpl = r##"{ "subtitle": {"text": "subtitle"}, "yAxis": [{ "height": "40%", "lineWidth": 2, "title": {"text": "PnL"}, "tickPixelInterval": 20, "minorGridLineWidth": 1, "minorTickWidth": 0, "opposite": true, "labels": {"align": "right", "x": -3} }, { "title": {"text": "Profit"}, "top": "42%", "height": "18%", "offset": 0, "lineWidth": 2 }, { "title": {"text": "Vol"}, "top": "62%", "height": "18%", "offset": 0, "lineWidth": 2 }, { "title": {"text": "Asset"}, "top": "82%", "height": "18%", "offset": 0, "lineWidth": 2 }], "series": [{ "name": "PnL", "data": [], "id": "primary", "tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S"}, "yAxis": 0 }, { "type": "column", "lineWidth": 2, "name": "Profit", "data": [], "yAxis": 1 }, { "type": "column", "name": "Trade", "data": [], "yAxis": 2 }, { "type": "area", "step": true, "lineWidth": 0, "name": "Long", "data": [], "yAxis": 2 }, { "type": "area", "step": true, "lineWidth": 0, "name": "Short", "data": [], "yAxis": 2 }, { "type": "line", "step": true, "color": "#5b4b00", "name": "Asset", "data": [], "yAxis": 3 }, { "type": "pie", "innerSize": "70%", "name": "Random", "data": __PIE_DATA__, "center": ["3%", "6%"], "size": "15%", "dataLabels": {"enabled": false}, "startAngle": -90, "endAngle": 90 }] }"##; let c = Chart::new(&chart_cfg_tpl.replace("__PIE_DATA__", "[]")); let mut pre_ticker: Option<Ticker> = None; loop { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); continue; } let _ = exchange.SetContractType("rb888"); let t = exchange.GetTicker(None).unwrap(); c.add(0, &format!("[{}, {}]", t.Time, t.Last), -1); // PnL let profit = if let Some(p) = &pre_ticker { t.Last - p.Last } else { 0.0 }; c.add(1, &format!("[{}, {}]", t.Time, profit), -1); // profit let r = (UnixNano() % 100) as f64 / 100.0; // 使用时间戳模拟随机数 let pos = (t.Time / 86400) as f64; c.add(2, &format!("[{}, {}]", t.Time, pos / 2.0), -1); // Vol c.add(3, &format!("[{}, {}]", t.Time, if r > 0.8 { pos.to_string() } else { "null".to_string() }), -1); // Long c.add(4, &format!("[{}, {}]", t.Time, if r < 0.8 { (-pos).to_string() } else { "null".to_string() }), -1); // Short c.add(5, &format!("[{}, {}]", t.Time, (UnixNano() % 10000) as f64 / 100.0), -1); // Asset // update pie let pie = format!(r#"[["A", {}], ["B", {}]]"#, (UnixNano() % 100) as f64, (UnixNano() % 100) as f64); c.update(&chart_cfg_tpl.replace("__PIE_DATA__", &pie)); pre_ticker = Some(t); } }c++void main() { json chartCfg = R"({ "subtitle": { "text": "subtitle" }, "yAxis": [{ "height": "40%", "lineWidth": 2, "title": { "text": "PnL" }, "tickPixelInterval": 20, "minorGridLineWidth": 1, "minorTickWidth": 0, "opposite": true, "labels": { "align": "right", "x": -3 } }, { "title": { "text": "Profit" }, "top": "42%", "height": "18%", "offset": 0, "lineWidth": 2 }, { "title": { "text": "Vol" }, "top": "62%", "height": "18%", "offset": 0, "lineWidth": 2 }, { "title": { "text": "Asset" }, "top": "82%", "height": "18%", "offset": 0, "lineWidth": 2 }], "series": [{ "name": "PnL", "data": [], "id": "primary", "tooltip": { "xDateFormat": "%Y-%m-%d %H:%M:%S" }, "yAxis": 0 }, { "type": "column", "lineWidth": 2, "name": "Profit", "data": [], "yAxis": 1 }, { "type": "column", "name": "Trade", "data": [], "yAxis": 2 }, { "type": "area", "step": true, "lineWidth": 0, "name": "Long", "data": [], "yAxis": 2 }, { "type": "area", "step": true, "lineWidth": 0, "name": "Short", "data": [], "yAxis": 2 }, { "type": "line", "step": true, "color": "#5b4b00", "name": "Asset", "data": [], "yAxis": 3 }, { "type": "pie", "innerSize": "70%", "name": "Random", "data": [], "center": ["3%", "6%"], "size": "15%", "dataLabels": { "enabled": false }, "startAngle": -90, "endAngle": 90 }] })"_json; Chart c = Chart(chartCfg); Ticker preTicker; while(true) { if (exchange.IO("status") != 0) { Sleep(1000); continue; } exchange.SetContractType("rb888"); auto t = exchange.GetTicker(); c.add(0, {t.Time, t.Last}); auto profit = preTicker.Valid ? t.Last - preTicker.Last : 0; c.add(1, {t.Time, profit}); auto r = rand() % 100; auto pos = t.Time / 86400.0; c.add(2, {t.Time, pos / 2.0}); auto longPos = r > 0.8 ? pos : NULL; c.add(3, {t.Time, longPos}); auto shortPos = r < 0.8 ? -pos : NULL; c.add(4, {t.Time, shortPos}); c.add(5, {t.Time, rand() % 100}); // update pie json pie = R"([["A", 0], ["B", 0]])"_json; pie[0][1] = rand() % 100; pie[1][1] = rand() % 100; chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie; c.update(chartCfg); preTicker = t; } } -
图表中
pie类型的图表没有时间轴,更新数据时需要直接更新图表配置。例如上述范例中的代码,更新数据后调用c.update(chartCfg)更新图表,如下所示:javascript// update pie chartCfg.series[chartCfg.series.length-1].data = [ ["A", Math.random()*100], ["B", Math.random()*100], ]; c.update(chartCfg)python# update pie chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [ ["A", random.random() * 100], ["B", random.random() * 100] ] c.update(chartCfg)rust// update pie // Rust 中图表配置为 JSON 字符串,重建包含新数据的配置后调用 update 更新图表 let pie = format!(r#"[["A", {}], ["B", {}]]"#, (UnixNano() % 100) as f64, (UnixNano() % 100) as f64); c.update(&chart_cfg_tpl.replace("__PIE_DATA__", &pie));c++// update pie json pie = R"([["A", 0], ["B", 0]])"_json; pie[0][1] = rand() % 100; pie[1][1] = rand() % 100; chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie; c.update(chartCfg);
返回值
| 类型 | 描述 |
object | 图表对象。 |
参数
| 名称 | 类型 | 必填 | 描述 |
options | object / object数组 | 是 |
如果将 如果将 更多信息可查阅HighStocks图表库。 |
参考
备注
Chart()函数返回一个图表对象,该对象包含4个方法:add()、reset()、update()、del()。
- 1、
update()方法:
update()方法用于更新图表配置信息,其参数为Chart图表配置对象(JSON)。 - 2、
del()方法:
del()方法可根据传入的series参数,删除指定索引的数据系列。 - 3、
add()方法:
add()方法用于向图表中写入数据,参数依次为:series:用于设置数据系列索引,为整数。data:用于设置写入的具体数据,为一个数组。index(可选):用于设置数据索引,为整数,指定要修改数据的具体索引位置,支持使用负数表示,设置为-1表示数据集的最后一个数据。
例如画线时,若要修改线上最后一个点的数据:chart.add(0, [1574993606000, 13.5], -1),即更改图表series[0].data中倒数第一个点的数据。不设置index参数则表示向当前数据系列(series)末尾添加数据。
- 4、
reset()方法:
reset()方法用于清空图表数据,该方法可传入一个参数remain,用于指定保留数据的条数。不传入remain参数则表示清除全部数据。
KLineChart
该函数用于采用类似Pine语言的绘图方式,在策略运行时进行自定义绘图。
KLineChart(options)示例
-
若需在策略的自定义画图区域进行绘图,必须先创建图表控制对象,使用
KLineChart()函数创建该对象。KLineChart()函数的参数为一个图表配置结构,参考代码中使用的图表配置结构非常简单:{overlay: true}。该图表配置结构仅将绘图内容输出到图表的主图上。如果将
overlay设置为假值(例如false),则图表内容将全部输出到副图上;如果需要指定某个画图函数在主图上绘制,也可以在该函数的调用中将参数overlay指定为真值(例如true)。javascriptfunction main() { // 调用KLineChart函数创建图表控制对象c let c = KLineChart({ overlay: true }) while(true) { if (exchange.IO("status")) { break } Sleep(1000) } exchange.SetContractType("rb888") // 获取K线 let bars = exchange.GetRecords() if (!bars) { return } bars.forEach(function(bar, index) { c.begin(bar) c.barcolor(bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.2)') if (bar.Close > bar.Open) { c.bgcolor('rgba(0, 255, 0, 0.5)') } let h = c.plot(bar.High, 'high') let l = c.plot(bar.Low, 'low') c.fill(h, l, { color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)' }) c.hline(bar.High) c.plotarrow(bar.Close - bar.Open) c.plotshape(bar.Low, { style: 'diamond' }) c.plotchar(bar.Close, { char: 'X' }) c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9) if (bar.Close > bar.Open) { // long/short/closelong/closeshort c.signal("long", bar.High, 1.5) } else if (bar.Close < bar.Open) { c.signal("closelong", bar.Low, 1.5) } c.close(bar) }) }pythondef main(): # 调用KLineChart函数创建图表控制对象c c = KLineChart({ "overlay": True }) while True: if exchange.IO("status"): break Sleep(1000) exchange.SetContractType("rb888") # 获取K线 bars = exchange.GetRecords() if not bars: return for bar in bars: c.begin(bar) c.barcolor('rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(0, 0, 0, 0.2)') if bar.Close > bar.Open: c.bgcolor('rgba(0, 255, 0, 0.5)') h = c.plot(bar.High, 'high') l = c.plot(bar.Low, 'low') c.fill(h, l, 'rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(255, 0, 0, 0.2)') c.hline(bar.High) c.plotarrow(bar.Close - bar.Open) c.plotshape(bar.Low, style = 'diamond') c.plotchar(bar.Close, char = 'X') c.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9) if bar.Close > bar.Open: # long/short/closelong/closeshort c.signal("long", bar.High, 1.5) elif bar.Close < bar.Open: c.signal("closelong", bar.Low, 1.5) c.close(bar)rustfn main() { // 调用KLineChart::new创建图表控制对象c let mut c = KLineChart::new(r#"{"overlay": true}"#); // 判断连接期货公司前置机是否成功 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } exchange.SetContractType("rb888").unwrap(); // 获取K线 let bars = exchange.GetRecords(None, None, None).unwrap(); for bar in &bars { c.begin(bar); c.barcolor(if bar.Close > bar.Open { "rgba(255, 0, 0, 0.2)" } else { "rgba(0, 0, 0, 0.2)" }, "{}"); if bar.Close > bar.Open { c.bgcolor("rgba(0, 255, 0, 0.5)", "{}"); } let h = c.plot(bar.High, r#"{"title": "high"}"#); let l = c.plot(bar.Low, r#"{"title": "low"}"#); c.fill(h, l, if bar.Close > bar.Open { r#"{"color": "rgba(255, 0, 0, 0.2)"}"# } else { r#"{"color": "rgba(255, 0, 0, 0.2)"}"# }); c.hline(bar.High, "{}"); c.plotarrow(bar.Close - bar.Open, "{}"); c.plotshape(bar.Low > 0.0, r#"{"style": "diamond"}"#); c.plotchar(bar.Close > 0.0, r#"{"char": "X"}"#); c.plotcandle(bar.Open * 0.9, bar.High * 0.9, bar.Low * 0.9, bar.Close * 0.9, "{}"); if bar.Close > bar.Open { // long/short/closelong/closeshort c.signal("long", bar.High, 1.5, "long"); } else if bar.Close < bar.Open { c.signal("closelong", bar.Low, 1.5, "closelong"); } c.close(); } }c++// 暂不支持 -
使用
pricePrecision和volumePrecision参数控制图表数据的显示精度。可根据实际需求设置价格与成交量的显示精度:例如,对于价格波动较大的品种,可将精度设置为 0 以显示整数;对于价格较为精细的品种,可设置为 2 或更高精度。javascriptfunction main() { // 创建图表控制对象,设置价格精度为 0(整数)、成交量精度为 0(整数) let c = KLineChart({ overlay: true, pricePrecision: 0, // 价格数据精度,例如设置为 2 即保留 2 位小数 volumePrecision: 0 // 成交量数据精度 }) // 等待交易所连接就绪 while (true) { if (exchange.IO("status")) { break } Sleep(1000) } // 设置合约类型(以螺纹钢主力合约为例) exchange.SetContractType("rb888") Log("Test symbol: rb888") // 获取 K 线数据 let bars = exchange.GetRecords() if (!bars) { return } // 遍历 K 线数据并绘制图表 bars.forEach(function(bar, index) { c.begin(bar) c.barcolor(bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.2)') c.plot(bar.High, 'high') c.plot(bar.Low, 'low') c.close(bar) }) }pythondef main(): # 创建图表控制对象,设置价格精度为 0(整数)、成交量精度为 0(整数) c = KLineChart({ "overlay": True, "pricePrecision": 0, # 价格数据精度,例如设置为 2 即保留 2 位小数 "volumePrecision": 0 # 成交量数据精度 }) # 等待交易所连接就绪 while True: if exchange.IO("status"): break Sleep(1000) # 设置合约类型(以螺纹钢主力合约为例) exchange.SetContractType("rb888") Log("Test symbol: rb888") # 获取 K 线数据 bars = exchange.GetRecords() if not bars: return # 遍历 K 线数据并绘制图表 for bar in bars: c.begin(bar) c.barcolor('rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(0, 0, 0, 0.2)') c.plot(bar.High, 'high') c.plot(bar.Low, 'low') c.close(bar)rustfn main() { // 创建图表控制对象,设置价格精度为 0(整数)、成交量精度为 0(整数) // pricePrecision 为价格数据精度,例如设置为 2 即保留 2 位小数;volumePrecision 为成交量数据精度 let mut c = KLineChart::new(r#"{"overlay": true, "pricePrecision": 0, "volumePrecision": 0}"#); // 等待交易所连接就绪 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约类型(以螺纹钢主力合约为例) exchange.SetContractType("rb888").unwrap(); Log!("Test symbol: rb888"); // 获取 K 线数据 let bars = exchange.GetRecords(None, None, None).unwrap(); // 遍历 K 线数据并绘制图表 for bar in &bars { c.begin(bar); c.barcolor(if bar.Close > bar.Open { "rgba(255, 0, 0, 0.2)" } else { "rgba(0, 0, 0, 0.2)" }, "{}"); c.plot(bar.High, r#"{"title": "high"}"#); c.plot(bar.Low, r#"{"title": "low"}"#); c.close(); } }c++// 暂不支持 -
画图操作中支持的
Pine语言画图接口函数如下:barcolor,用于设置K线颜色。barcolor(color, offset, editable, show_last, title, display)
display参数可选值:"none", "all"
javascriptc.barcolor(bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0.2)') // 使用本例中参考代码中的例子说明,不再赘述pythonc.barcolor('rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(0, 0, 0, 0.2)')rustc.barcolor(if bar.Close > bar.Open { "rgba(255, 0, 0, 0.2)" } else { "rgba(0, 0, 0, 0.2)" }, "{}"); // 使用本例中参考代码中的例子说明,不再赘述c++// 暂不支持 -
bgcolor,用于以指定颜色填充K线背景。bgcolor(color, offset, editable, show_last, title, display, overlay)
display参数可选值:"none", "all"
javascriptc.bgcolor('rgba(0, 255, 0, 0.5)')pythonc.bgcolor('rgba(0, 255, 0, 0.5)')rustc.bgcolor("rgba(0, 255, 0, 0.5)", "{}");c++// 暂不支持 -
plot,用于在图表上绘制一系列数据。plot(series, title, color, linewidth, style, trackprice, histbase, offset, join, editable, show_last, display)
style参数可选值:"stepline_diamond", "stepline", "cross", "areabr", "area", "circles", "columns", "histogram", "linebr", "line"
display参数可选值:"none", "all"
javascriptc.plot(bar.High, 'high') c.plot(bar.Open < bar.Close ? NaN : bar.Close, "Close", {style: "linebr"}) // 支持绘制不连续的数据线pythonh = c.plot(bar.High, 'high') h = c.plot(None if bar.Open < bar.Close else bar.Close, "Close", style = "linebr") # 支持绘制不连续的数据线rustlet h = c.plot(bar.High, r#"{"title": "high"}"#); c.plot(if bar.Open < bar.Close { f64::NAN } else { bar.Close }, r#"{"title": "Close", "style": "linebr"}"#); // 支持绘制不连续的数据线c++// 暂不支持 -
fill,使用指定的颜色填充两个绘图或hline之间的背景。fill(hline1, hline2, color, title, editable, fillgaps, display)
display 参数可选:"none", "all"
由于
JavaScript语言无法通过函数形参名称来指定所传入的参数,为解决这一问题,可以使用{key: value}结构为指定的形参名称传入参数。例如,参考代码中使用{color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)'}为fill函数的color参数赋值。如需连续为多个形参名称指定参数,可以使用
{key1: value1, key2: value2, key3: value3}。例如,在本例中额外指定一个title参数:{color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)', title: 'fill'}。颜色值既可以使用'rgba(255, 0, 0, 0.2)'的形式设置,也可以使用'#FF0000'的形式设置。javascriptlet h = c.plot(bar.High, 'high') let l = c.plot(bar.Low, 'low') c.fill(h, l, {color: bar.Close > bar.Open ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)'})pythonh = c.plot(bar.High, 'high') l = c.plot(bar.Low, 'low') c.fill(h, l, color = 'rgba(255, 0, 0, 0.2)' if bar.Close > bar.Open else 'rgba(255, 0, 0, 0.2)')rustlet h = c.plot(bar.High, r#"{"title": "high"}"#); let l = c.plot(bar.Low, r#"{"title": "low"}"#); c.fill(h, l, if bar.Close > bar.Open { r#"{"color": "rgba(255, 0, 0, 0.2)"}"# } else { r#"{"color": "rgba(255, 0, 0, 0.2)"}"# });c++// 暂不支持 -
hline,在给定的固定价格水平上绘制一条水平线。hline(price, title, color, linestyle, linewidth, editable, display)
linestyle 参数可选:"dashed", "dotted", "solid"
display 参数可选:"none", "all"
javascriptc.hline(bar.High)pythonc.hline(bar.High)rustc.hline(bar.High, "{}");c++// 暂不支持 -
plotarrow,在图表上绘制向上和向下的箭头。plotarrow(series, title, colorup, colordown, offset, minheight, maxheight, editable, show_last, display)
display 参数可选:"none", "all"
javascriptc.plotarrow(bar.Close - bar.Open)pythonc.plotarrow(bar.Close - bar.Open)rustc.plotarrow(bar.Close - bar.Open, "{}");c++// 暂不支持 -
plotshape,在图表上绘制可视化形状。plotshape(series, title, style, location, color, offset, text, textcolor, editable, size, show_last, display)
style参数可选值包括:"diamond", "square", "label_down", "label_up", "arrow_down", "arrow_up", "circle", "flag", "triangle_down", "triangle_up", "cross", "xcross"
location参数可选值包括:"abovebar", "belowbar", "top", "bottom", "absolute"
size参数可选值包括:"10px", "14px", "20px", "40px", "80px",分别对应Pine语言中的size.tiny、size.small、size.normal、size.large、size.huge
size.auto等同于size.small。
display参数可选值包括:"none", "all"
javascriptc.plotshape(bar.Low, {style: 'diamond'})pythonc.plotshape(bar.Low, style = 'diamond')rustc.plotshape(bar.Low > 0.0, r#"{"style": "diamond"}"#);c++// 暂不支持 -
plotchar,在图表上使用任意给定的Unicode字符绘制可视化形状。plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display)
location参数可选值包括:"abovebar", "belowbar", "top", "bottom", "absolute"
size参数可选值包括:"10px", "14px", "20px", "40px", "80px",分别对应Pine语言中的size.tiny、size.small、size.normal、size.large、size.huge
size.auto等同于size.small。
display参数可选值包括:"none", "all"
javascriptc.plotchar(bar.Close, {char: 'X'})pythonc.plotchar(bar.Close, char = 'X')rustc.plotchar(bar.Close > 0.0, r#"{"char": "X"}"#);c++// 暂不支持 -
plotcandle,在图表上绘制K线图。plotcandle(open, high, low, close, title, color, wickcolor, editable, show_last, bordercolor, display)
display参数可选值包括:"none", "all"
javascriptc.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)pythonc.plotcandle(bar.Open*0.9, bar.High*0.9, bar.Low*0.9, bar.Close*0.9)rustc.plotcandle(bar.Open * 0.9, bar.High * 0.9, bar.Low * 0.9, bar.Close * 0.9, "{}");c++// 暂不支持 -
signal是Pine语言中没有的函数,此处用于绘制买卖信号。signal(direction, price, qty, id)
参数"long"表示交易方向,可选值包括"long"、"closelong"、"short"、"closeshort"。参数
bar.High用于标记信号在Y轴上的位置。参数1.5表示信号的交易数量。可传入第四个参数以替换默认绘制的文本内容,信号标记的默认文本为交易方向,例如:"closelong"。
javascriptc.signal("long", bar.High, 1.5)pythonc.signal("long", bar.High, 1.5)rustc.signal("long", bar.High, 1.5, "long");c++// 暂不支持 -
reset是Pine语言中没有的函数,用于清空图表数据。reset(remain)
reset()方法可接受一个参数remain,用于指定需要保留的数据条数。若不传入remain参数,则表示清除全部数据。javascriptc.reset()pythonc.reset()rustc.reset(0);c++// 暂不支持
返回值
| 类型 | 描述 |
object | 图表对象。
|
参数
| 名称 | 类型 | 必填 | 描述 |
options | object / object数组 | 是 |
|
参考
备注
策略自定义绘图只能采用KLineChart()函数或Chart()函数两种方式中的一种。有关KLineChart()函数调用时所用的颜色、样式等设置,请参阅使用KLineChart函数画图的专题文章。
pricePrecision和volumePrecision参数用于控制图表中数据的显示精度。若不设置这些参数,图表将以默认精度显示数据。设置精度参数后,图表中的价格和成交量数据将按照指定的小数位数进行四舍五入显示,这有助于简化图表显示、提高可读性。
LogReset
清除日志。
LogReset(remain)示例
使用LogReset()函数清除日志。
javascript
function main() {
// 保留最近10条日志,清除其余日志
LogReset(10)
}
python
def main():
LogReset(10)
rust
fn main() {
// 保留最近10条日志,清除其余日志
LogReset(10);
}
c++
void main() {
LogReset(10);
}参数
| 名称 | 类型 | 必填 | 描述 |
remain | number | 否 |
|
参考
备注
策略实盘每次启动时的启动日志会计为一条,因此如果不传入参数,且策略启动时没有任何日志输出,日志将完全不显示,需等待托管者回传日志(此为正常现象,并非异常情况)。
LogVacuum
用于在调用LogReset()函数清除日志后,回收SQLite删除数据时所占用的存储空间。
LogVacuum()示例
测试LogVacuum()函数。
javascript
function main() {
LogReset()
LogVacuum()
}
python
def main():
LogReset()
LogVacuum()
rust
fn main() {
LogReset(0);
LogVacuum();
}
c++
void main() {
LogReset();
LogVacuum();
}参考
备注
由于SQLite在删除数据时不会自动回收所占用的空间,因此需要执行VACUUM命令来清理数据表并释放空间。该函数在调用时会执行文件移动操作,延迟较大,建议以合适的时间间隔进行调用。
console.log
用于在实盘页面的「调试信息」栏中输出调试信息。例如,实盘ID为123456时,console.log函数在实盘页面输出调试信息的同时,会在实盘所属托管者目录/logs/storage/123456/下创建一个扩展名为.log的日志文件并写入调试信息,文件名前缀为stdout_。
console.log(...msgs)示例
测试console.log()函数。
javascript
function main() {
console.log("test console.log")
}
python
# 不支持
c++
// 不支持参数
| 名称 | 类型 | 必填 | 描述 |
msg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 参数 |
参考
备注
注意事项:
- 仅
JavaScript语言支持此函数。 - 仅实盘环境支持此函数,「调试工具」和「回测系统」均不支持。
- 输出对象时会被转换为字符串
[object Object],因此建议输出可读的信息。
console.error
用于在实盘页面的「调试信息」栏中输出错误信息。例如,实盘ID为123456时,console.error函数在实盘页面输出错误信息的同时,会在实盘所属托管者目录/logs/storage/123456/下创建一个以stderr_为前缀、.log为扩展名的日志文件,并将错误信息写入该文件。
console.error(...msgs)示例
测试console.error()函数。
javascript
function main() {
console.error("test console.error")
}
python
# 不支持
c++
// 不支持参数
| 名称 | 类型 | 必填 | 描述 |
msg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 参数 |
参考
备注
注意事项:
- 仅
JavaScript语言支持此函数。 - 仅实盘环境支持此函数,「调试工具」和「回测系统」均不支持。
- 输出对象时会被转换为字符串
[object Object],因此建议输出可读性较好的信息。
Market
exchange.GetTicker
获取当前设置的交易对、合约代码对应的Ticker结构,即行情数据。GetTicker()函数是交易所对象exchange的成员函数,exchange对象的成员函数(方法)仅与exchange对象相关,后续文档中不再赘述。
exchange.GetTicker()
exchange.GetTicker(symbol)示例
测试 exchange.GetTicker() 函数:
javascript
function main(){
// 由于这是测试代码,此处不采用商品期货策略的通用架构,仅通过 exchange.IO("status") 函数判断成功连接期货公司前置机后,立即执行测试代码。股票证券则无需使用 exchange.IO("status") 判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
Log(exchange.SetContractType("rb888"))
var ticker = exchange.GetTicker()
Log("Symbol:", ticker.Symbol, "High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Open:", ticker.Open, "Volume:", ticker.Volume)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
Log(exchange.SetContractType("rb888"))
ticker = exchange.GetTicker()
Log("Symbol:", ticker["Symbol"], "High:", ticker["High"], "Low:", ticker["Low"], "Sell:", ticker["Sell"], "Buy:", ticker["Buy"], "Last:", ticker["Last"], "Open:", ticker.Open, "Volume:", ticker["Volume"])
rust
fn main() {
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
Log!(exchange.SetContractType("rb888"));
let ticker = exchange.GetTicker(None).unwrap();
Log!("Symbol:", ticker.Symbol, "High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Open:", ticker.Open, "Volume:", ticker.Volume);
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
Log(exchange.SetContractType("rb888"));
auto ticker = exchange.GetTicker();
Log("Symbol:", ticker.Symbol, "High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Open:", ticker.Open, "Volume:", ticker.Volume);
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
参考
备注
在回测系统中,exchange.GetTicker()函数返回的Ticker数据中,High、Low为模拟值,取自当时盘口的卖一价与买一价。
在商品期货策略实盘中,如果没有行情推送过来,exchange.GetTicker()函数会阻塞,等待行情推送。exchange.GetDepth()、exchange.GetTrades()、exchange.GetRecords()同理。如果不希望阻塞,可以通过切换行情模式来实现:
- exchange.IO("mode", 0)
立即返回模式。如果当前尚未接收到交易所最新的行情推送数据,则立即返回旧的行情数据;如果有新数据,则返回新数据。 - exchange.IO("mode", 1)
缓存模式(默认模式)。如果当前尚未收到交易所最新的行情数据(与上一次接口获取的数据相比较),则等待接收后再返回;如果在调用该函数之前已收到最新的行情数据,则立即返回最新数据。 - exchange.IO("mode", 2)
强制更新模式。进入等待状态,直到接收到交易所下一次推送的最新数据后再返回。
在实盘时(非回测),exchange.GetTicker()函数返回值中的Info属性存储接口调用时返回的原始数据。
- 商品期货
返回商品期货CTP协议/易盛协议接口的应答数据,以CTP协议为例:json{ "BidPrice4": 1.7976931348623157e+308, "AskVolume4": 0, "AskVolume5": 0, "Turnover": 26229625880, "OpenInterest": 1364847, // 持仓量 "ClosePrice": 1.7976931348623157e+308, "LowerLimitPrice": 3473, "BidPrice3": 1.7976931348623157e+308, "ExchangeID": "", "BidPrice2": 1.7976931348623157e+308, "BidPrice5": 1.7976931348623157e+308, "AveragePrice": 37323.89130239898, "BidVolume4": 0, "BidVolume5": 0, "ExchangeInstID": "", "LowestPrice": 3715, "Volume": 702757, "BidVolume3": 0, "AskPrice3": 1.7976931348623157e+308, "AskVolume3": 0, "ActionDay": "20200714", "PreClosePrice": 3739, "SettlementPrice": 1.7976931348623157e+308, "UpdateTime": "13:40:01", "BidPrice1": 3727, "AskPrice2": 1.7976931348623157e+308, "UpperLimitPrice": 3996, "CurrDelta": 1.7976931348623157e+308, "UpdateMillisec": 500, "AskVolume1": 154, "BidVolume2": 0, "PreOpenInterest": 1372843, "PreDelta": 0, "AskPrice1": 3728, "AskVolume2": 0, "TradingDay": "20200714", "InstrumentID": "rb2010", "LastPrice": 3727, "HighestPrice": 3749, "BidVolume1": 444, "PreSettlementPrice": 3735, "OpenPrice": 3740, "AskPrice4": 1.7976931348623157e+308, "AskPrice5": 1.7976931348623157e+308 }
exchange.GetDepth
获取当前设置的交易对、合约代码对应的Depth结构,即订单簿数据。
结构体Depth包含两个结构体数组,分别为Asks[]和Bids[]。Asks和Bids数组中的元素均包含以下结构体变量:
| 数据类型 | 变量名 | 说明 |
|---|---|---|
| number | Price | 价格 |
| number | Amount | 数量 |
exchange.GetDepth()
exchange.GetDepth(symbol)示例
测试exchange.GetDepth()函数:
javascript
function main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
Log(exchange.SetContractType("rb888"))
var depth = exchange.GetDepth()
var price = depth.Asks[0].Price
Log("卖一价为:", price)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
Log(exchange.SetContractType("rb888"))
depth = exchange.GetDepth()
price = depth["Asks"][0]["Price"]
Log("卖一价为:", price)
rust
fn main() {
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
Log!(exchange.SetContractType("rb888"));
let depth = exchange.GetDepth(None).unwrap();
let price = depth.Asks[0].Price;
Log!("卖一价为:", price);
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
Log(exchange.SetContractType("rb888"));
auto depth = exchange.GetDepth();
auto price = depth.Asks[0].Price;
Log("卖一价为:", price);
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
参考
备注
在回测系统中,使用模拟级 Tick回测时,exchange.GetDepth()函数返回数据的各档位均为模拟值。
在回测系统中,使用实盘级 Tick回测时,exchange.GetDepth()函数返回的数据为秒级别深度快照。
商品期货实盘交易时需要注意:
涨停时,卖单卖一的价格为涨停价格,订单量为 0;跌停时,买单买一的价格为跌停价格,订单量为 0。通过判断买一、卖一订单数据中的订单量,即可判断当前是否处于涨停或跌停状态。
exchange.GetTrades
获取当前设置的交易对、合约代码对应的Trade结构数组,即市场的成交数据。对于商品期货,通过算法根据行情数据(Tick 数据)推算出市场成交记录。
exchange.GetTrades()
exchange.GetTrades(symbol)示例
测试exchange.GetTrades()函数:
javascript
function main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
Log(exchange.SetContractType("rb888"))
var trades = exchange.GetTrades()
Log(trades)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
Log(exchange.SetContractType("rb888"))
trades = exchange.GetTrades()
Log(trades)
rust
fn main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
Log!(exchange.SetContractType("rb888"));
let trades = exchange.GetTrades(None).unwrap();
Log!(trades);
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
Log(exchange.SetContractType("rb888"));
auto trades = exchange.GetTrades();
Log(trades);
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
参考
备注
根据 Tick 数据推算成交记录的策略示例:
exchange.GetRecords
获取当前设置的交易对、合约代码所对应的Record结构数组,即K线数据。
exchange.GetRecords()
exchange.GetRecords(symbol)
exchange.GetRecords(symbol, period)
exchange.GetRecords(symbol, period, limit)
exchange.GetRecords(period)
exchange.GetRecords(period, limit)示例
-
对于 exchange.GetRecords(Period) 函数,商品期货的实盘与回测均支持自定义周期,参数 Period 的单位为秒。
javascriptfunction main() { // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断是否成功连接期货公司前置机,连接成功后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } Log(exchange.SetContractType("rb888")) // 打印周期为 120 秒(2 分钟)的 K 线数据 Log(exchange.GetRecords(60 * 2)) // 打印周期为 5 分钟的 K 线数据 Log(exchange.GetRecords(PERIOD_M5)) }pythondef main(): while not exchange.IO("status"): Sleep(1000) Log(exchange.SetContractType("rb888")) Log(exchange.GetRecords(60 * 2)) Log(exchange.GetRecords(PERIOD_M5))rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断是否成功连接期货公司前置机,连接成功后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } Log!(exchange.SetContractType("rb888")); // 打印周期为 120 秒(2 分钟)的 K 线数据 Log!(exchange.GetRecords(None, 60 * 2, None)); // 打印周期为 5 分钟的 K 线数据 Log!(exchange.GetRecords(None, PERIOD_M5, None)); }c++void main() { while(exchange.IO("status") == 0) { Sleep(1000); } Log(exchange.SetContractType("rb888")); Log(exchange.GetRecords(60 * 2)[0]); Log(exchange.GetRecords(PERIOD_M5)[0]); } -
输出 K 线柱数据:
javascriptfunction main(){ // 由于这是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断,在成功连接期货公司前置机后立即执行测试代码。股票、证券无需使用 exchange.IO("status") 判断连接状态 while(!exchange.IO("status")) { Sleep(1000) } Log(exchange.SetContractType("rb888")) var records = exchange.GetRecords(PERIOD_H1) Log("第一根 K 线数据为,Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High) Log("第二根 K 线数据为,Time:", records[1].Time ,"Close:", records[1].Close) Log("当前 K 线(最新)", records[records.length-1], "上一根 K 线", records[records.length-2]) }pythondef main(): while not exchange.IO("status"): Sleep(1000) Log(exchange.SetContractType("rb888")) records = exchange.GetRecords(PERIOD_H1) Log("第一根 K 线数据为,Time:", records[0]["Time"], "Open:", records[0]["Open"], "High:", records[0]["High"]) Log("第二根 K 线数据为,Time:", records[1]["Time"], "Close:", records[1]["Close"]) Log("当前 K 线(最新)", records[-1], "上一根 K 线", records[-2])rustfn main() { // 由于这是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断,在成功连接期货公司前置机后立即执行测试代码。股票、证券无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } Log!(exchange.SetContractType("rb888")); let records = exchange.GetRecords(None, PERIOD_H1, None).unwrap(); Log!("第一根 K 线数据为,Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High); Log!("第二根 K 线数据为,Time:", records[1].Time, "Close:", records[1].Close); Log!("当前 K 线(最新)", records[records.len() - 1], "上一根 K 线", records[records.len() - 2]); }c++void main() { while(exchange.IO("status") == 0) { Sleep(1000); } Log(exchange.SetContractType("rb888")); auto records = exchange.GetRecords(PERIOD_H1); Log("第一根 K 线数据为,Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High); Log("第二根 K 线数据为,Time:", records[1].Time, "Close:", records[1].Close); Log("当前 K 线(最新)", records[records.size() - 1], "上一根 K 线", records[records.size() - 2]); } -
通过指定具体的合约代码请求K线数据:
javascriptfunction main() { while(!exchange.IO("status")) { Sleep(1000) } var records = exchange.GetRecords("rb888") Log("当前K线(最新)", records[records.length - 1]) }pythondef main(): while not exchange.IO("status"): Sleep(1000) records = exchange.GetRecords("rb888") Log("当前K线(最新)", records[-1])rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } let records = exchange.GetRecords("rb888", None, None).unwrap(); Log!("当前K线(最新)", records[records.len() - 1]); }c++void main() { while(exchange.IO("status") == 0) { Sleep(1000); } auto records = exchange.GetRecords("rb888"); Log("当前K线(最新)", records[records.size() - 1]); }
返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
period | number | 否 | 参数 |
limit | string | 否 | 参数 |
参考
备注
默认K线周期可在回测、实盘页面进行设置。如果在调用exchange.GetRecords()函数时指定了参数,则获取的是该参数指定周期对应的K线数据;如果调用时未指定参数,则按照回测、实盘参数中设置的K线周期返回对应的K线数据。
返回值为Record结构数组,返回的K线数据会随时间累积,累积的K线柱数量上限受exchange.SetMaxBarLen()函数设置的影响,未设置时默认上限为5000个K线柱。当K线数据达到累积上限后,之后每更新加入一根K线柱的同时会删除时间最早的一根K线柱(类似队列的先进先出)。
初始调用GetRecords函数时获取的K线柱数量:
- 回测系统中会预先取回回测周期起始时刻之前的1000根K线柱,作为初始K线数据。
参数period设置为5,即表示请求获取以5秒为周期的K线数据。
如果period参数不能被60整除(即所代表的周期不是以分钟为单位的周期),系统底层则使用tick数据合成所需的K线数据。
如果period参数能被60整除,则最小使用1分钟K线数据(尽可能使用较大的周期)来合成所需的K线数据。
股票证券:
- 富途证券
在K线周期为日线周期以下时,调用GetRecords()函数返回的数据中,数组的每个元素为一根K线柱数据(即Record结构体),每根K线柱数据结构的Time属性为该周期的结束时间(毫秒级时间戳),而非起始时间(毫秒级时间戳)。
在K线周期为日线周期时,Record结构体的Time属性为该周期的起始时间(毫秒级时间戳)。
在回测系统的模拟级别回测中,由于需要设置底层K线周期(回测系统进行模拟级别回测时,会根据设置的底层K线周期使用对应的K线数据生成Tick数据),因此需要注意:策略中获取的K线数据周期不能小于底层K线周期。因为在模拟级别回测中,各个周期的K线数据在回测系统中都是通过底层K线周期对应的K线数据合成的。
在C++语言中,如果需要自行构造K线数据,可参考以下代码范例:
c++
#include <sstream>
void main() {
Records r;
r.Valid = true;
for (auto i = 0; i < 10; i++) {
Record ele;
ele.Time = i * 100000;
ele.High = i * 10000;
ele.Low = i * 1000;
ele.Close = i * 100;
ele.Open = i * 10;
ele.Volume = i * 1;
r.push_back(ele);
}
// 输出显示:Records[10]
Log(r);
auto ma = TA.MA(r,10);
// 输出显示:[nan,nan,nan,nan,nan,nan,nan,nan,nan,450]
Log(ma);
}
exchange.GetPeriod
获取在回测或实盘运行策略时,于优宽量化交易平台网页上所设置的K线周期,即调用exchange.GetRecords()函数且不传入参数时使用的默认K线周期。
exchange.GetPeriod()示例
获取当前默认的K线周期。
javascript
function main() {
// 例如,回测或实盘时在优宽量化交易平台网页上设置的K线周期为1小时
var period = exchange.GetPeriod()
Log("K线周期:", period / (60 * 60), "小时")
}
python
def main():
period = exchange.GetPeriod()
Log("K线周期:", period / (60 * 60), "小时")
rust
fn main() {
// 例如,回测或实盘时在优宽量化交易平台网页上设置的K线周期为1小时
let period = exchange.GetPeriod();
Log!("K线周期:", period as f64 / (60.0 * 60.0), "小时");
}
c++
void main() {
auto period = exchange.GetPeriod();
Log("K线周期:", period / (60 * 60.0), "小时");
}返回值
| 类型 | 描述 |
number | K线周期的长度,为整数数值,单位为秒。 |
参考
exchange.SetMaxBarLen
设置 K 线的最大长度。
exchange.SetMaxBarLen(n)示例
测试exchange.SetMaxBarLen()函数:
javascript
function main() {
// 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过exchange.IO("status")函数判断成功连接期货公司前置机后立即执行测试代码。股票证券策略无需使用exchange.IO("status")判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
exchange.SetMaxBarLen(50)
Log(exchange.SetContractType("rb888"))
var records = exchange.GetRecords()
Log(records.length, records)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
exchange.SetMaxBarLen(50)
Log(exchange.SetContractType("rb888"))
r = exchange.GetRecords()
Log(len(r), r)
rust
fn main() {
// 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过exchange.IO("status")函数判断成功连接期货公司前置机后立即执行测试代码。股票证券策略无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
exchange.SetMaxBarLen(50);
Log!(exchange.SetContractType("rb888"));
let records = exchange.GetRecords(None, None, None).unwrap();
Log!(records.len(), records);
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
exchange.SetMaxBarLen(50);
Log(exchange.SetContractType("rb888"));
auto r = exchange.GetRecords();
Log(r.size(), r[0]);
}参数
| 名称 | 类型 | 必填 | 描述 |
n | number | 是 | 参数 |
参考
备注
对于商品期货策略,exchange.SetMaxBarLen(Len)函数在运行时决定 K 线柱(BAR)数量的上限。
exchange.SetMaxBarLen函数必须在调用exchange.SetContractType函数之前执行,因为一旦调用exchange.SetContractType函数,系统底层便已开始处理 K 线数据。
exchange.GetRate
获取交易所对象当前设置的汇率。
exchange.GetRate()示例
获取交易所对象当前设置的汇率。
javascript
function main(){
Log(exchange.GetTicker())
// 设置汇率转换
exchange.SetRate(7)
Log(exchange.GetTicker())
Log("当前汇率:", exchange.GetRate())
}
python
def main():
Log(exchange.GetTicker())
exchange.SetRate(7)
Log(exchange.GetTicker())
Log("当前汇率:", exchange.GetRate())
rust
fn main() {
Log!(exchange.GetTicker(None));
// 设置汇率转换
exchange.SetRate(7);
Log!(exchange.GetTicker(None));
Log!("当前汇率:", exchange.GetRate());
}
c++
void main() {
Log(exchange.GetTicker());
exchange.SetRate(7);
Log(exchange.GetTicker());
Log("当前汇率:", exchange.GetRate());
}返回值
| 类型 | 描述 |
number | 交易所对象当前的汇率值。 |
参考
备注
如果没有调用exchange.SetRate()设置过转换汇率,exchange.GetRate()函数将返回默认汇率值1,即当前显示的计价货币(quoteCurrency)相关数据未经过汇率转换。
如果已使用exchange.SetRate()设置了汇率值(例如exchange.SetRate(7)),那么通过exchange交易所对象获取的行情、深度、下单价格等所有价格信息,都会乘以所设置的汇率7进行转换。
如果exchange对应的是以美元为计价货币的交易所,在调用exchange.SetRate(7)后,实盘中所有价格都会乘以7,转换为接近人民币(CNY)的价格。此时使用exchange.GetRate()获取的汇率值即为7。
exchange.SetData
exchange.SetData() 函数用于设置策略运行时所加载的数据。
exchange.SetData(key, value)示例
在策略中直接写入数据,数据格式需与以下示例中的data变量保持一致。运行以下测试代码时,程序会在对应的时间点获取相应的数据。可以看到,时间戳1579622400000对应的时间为2020-01-22 00:00:00。当策略程序运行到该时间之后、且在下一条数据的时间戳1579708800000(即时间2020-01-23 00:00:00)之前时,调用exchange.GetData(Source)函数获取数据,返回的均为[1579622400000, 123]这条数据的内容。随着程序继续运行、时间推移,即可依此类推逐条获取数据。
在以下示例中,运行时(回测或实盘)当前时刻到达或超过1579795200000这个时间戳时,调用exchange.GetData()函数,返回值为:{"Time":1579795200000,"Data":["abc",123,{"price":123}]}。其中"Time":1579795200000对应数据[1579795200000, ["abc", 123, {"price": 123}]]中的1579795200000;"Data":["abc",123,{"price":123}]对应数据[1579795200000, ["abc", 123, {"price": 123}]]中的["abc", 123, {"price": 123}]。
javascript
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
function main() {
var data = [
[1579536000000, "abc"],
[1579622400000, 123],
[1579708800000, {"price": 123}],
[1579795200000, ["abc", 123, {"price": 123}]]
]
exchange.SetData("test", data)
while(true) {
Log(exchange.GetData("test"))
Sleep(1000)
}
}
python
'''backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''
def main():
data = [
[1579536000000, "abc"],
[1579622400000, 123],
[1579708800000, {"price": 123}],
[1579795200000, ["abc", 123, {"price": 123}]]
]
exchange.SetData("test", data)
while True:
Log(exchange.GetData("test"))
Sleep(1000)
rust
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
fn main() {
let data = r#"[
[1579536000000, "abc"],
[1579622400000, 123],
[1579708800000, {"price": 123}],
[1579795200000, ["abc", 123, {"price": 123}]]
]"#;
exchange.SetData("test", data);
loop {
Log!(exchange.GetData("test"));
Sleep(1000);
}
}
c++
/*backtest
start: 2020-01-21 00:00:00
end: 2020-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
void main() {
json data = R"([
[1579536000000, "abc"],
[1579622400000, 123],
[1579708800000, {"price": 123}],
[1579795200000, ["abc", 123, {"price": 123}]]
])"_json;
exchange.SetData("test", data);
while(true) {
Log(exchange.GetData("test"));
Sleep(1000);
}
}返回值
| 类型 | 描述 |
number | 参数 |
参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 | 数据集合的名称。 |
value | array | 是 |
|
参考
备注
所加载的数据可以是任意经济指标、行业数据、相关指数等,用于策略量化考核各类可量化的信息。
exchange.GetData
exchange.GetData()函数用于获取由exchange.SetData()函数加载的数据,或外部链接提供的数据。
exchange.GetData(key)
exchange.GetData(key, timeout)示例
-
获取直接写入数据的调用方式示例。
javascript/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ function main() { exchange.SetData("test", [[1579536000000, _D(1579536000000)], [1579622400000, _D(1579622400000)], [1579708800000, _D(1579708800000)]]) while(true) { Log(exchange.GetData("test")) Sleep(1000 * 60 * 60 * 24) } }python'''backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' def main(): exchange.SetData("test", [[1579536000000, _D(1579536000000/1000)], [1579622400000, _D(1579622400000/1000)], [1579708800000, _D(1579708800000/1000)]]) while True: Log(exchange.GetData("test")) Sleep(1000 * 60 * 60 * 24)rust/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ fn main() { let data = format!( r#"[[1579536000000, "{}"], [1579622400000, "{}"], [1579708800000, "{}"]]"#, _D(1579536000000), _D(1579622400000), _D(1579708800000) ); exchange.SetData("test", &data); loop { Log!(exchange.GetData("test")); Sleep(1000 * 60 * 60 * 24); } }c++/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ void main() { json arr = R"([[1579536000000, ""], [1579622400000, ""], [1579708800000, ""]])"_json; arr[0][1] = _D(1579536000000); arr[1][1] = _D(1579622400000); arr[2][1] = _D(1579708800000); exchange.SetData("test", arr); while(true) { Log(exchange.GetData("test")); Sleep(1000 * 60 * 60 * 24); } } -
支持通过外部链接请求数据,请求返回的数据格式如下:
json{ "schema":["time","data"], "data":[ [1579536000000, "abc"], [1579622400000, 123], [1579708800000, {"price": 123}], [1579795200000, ["abc", 123, {"price": 123}]] ] }其中,
schema定义了数据主体中每条记录的数据格式,该格式固定为["time","data"],与data属性中每条数据的格式一一对应。
data属性中存储的是数据主体,每条数据由毫秒级时间戳和数据内容构成(数据内容可以是任何可 JSON 编码的数据)。以下为测试用的服务程序,使用 Go 语言编写:
golangpackage main import ( "fmt" "net/http" "encoding/json" ) func Handle (w http.ResponseWriter, r *http.Request) { defer func() { fmt.Println("req:", *r) ret := map[string]interface{}{ "schema": []string{"time","data"}, "data": []interface{}{ []interface{}{1579536000000, "abc"}, []interface{}{1579622400000, 123}, []interface{}{1579708800000, map[string]interface{}{"price":123}}, []interface{}{1579795200000, []interface{}{"abc", 123, map[string]interface{}{"price":123}}}, }, } b, _ := json.Marshal(ret) w.Write(b) }() } func main () { fmt.Println("listen http://localhost:9090") http.HandleFunc("/data", Handle) http.ListenAndServe(":9090", nil) }程序接收到请求后返回的应答数据:
json{ "schema":["time","data"], "data":[ [1579536000000, "abc"], [1579622400000, 123], [1579708800000, {"price": 123}], [1579795200000, ["abc", 123, {"price": 123}]] ] }测试策略代码如下:
javascript/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ function main() { while(true) { Log(exchange.GetData("http://xxx.xx.x.xx:9090/data")) Sleep(1000) } }python'''backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' def main(): while True: Log(exchange.GetData("http://xxx.xx.x.xx:9090/data")) Sleep(1000)rust/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ fn main() { loop { Log!(exchange.GetData("http://xxx.xx.x.xx:9090/data")); Sleep(1000); } }c++/*backtest start: 2020-01-21 00:00:00 end: 2020-02-12 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ void main() { while(true) { Log(exchange.GetData("http://xxx.xx.x.xx:9090/data")); Sleep(1000); } } -
获取外部链接数据的调用方式。
javascriptfunction main() { Log(exchange.GetData("http://xxx.xx.x.xx:9090/data")) }pythondef main(): Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))rustfn main() { Log!(exchange.GetData("http://xxx.xx.x.xx:9090/data")); }c++void main() { Log(exchange.GetData("http://xxx.xx.x.xx:9090/data")); } -
请求在datadata平台上创建的查询数据,要求应答的数据格式如下(schema中必须包含time、data字段的描述):
json{ "data": [], "schema": ["time", "data"] }其中"data"字段为所需的数据内容,且"data"字段中的数据需与"schema"中约定的字段保持一致。调用
exchange.GetData()函数时,将返回一个JSON对象,例如:{"Time":1579795200000, "Data":"..."}。javascriptfunction main() { // 链接中的xxx部分为查询数据的编码,此处xxx仅为示例。具体查询链接可登录datadata.cn平台创建,也可在优宽量化平台的「数据探索」页面创建 Log(exchange.GetData("https://www.datadata.cn/api/v1/query/xxx/data")) }pythondef main(): Log(exchange.GetData("https://www.datadata.cn/api/v1/query/xxx/data"))rustfn main() { // 链接中的xxx部分为查询数据的编码,此处xxx仅为示例。具体查询链接可登录datadata.cn平台创建,也可在优宽量化平台的「数据探索」页面创建 Log!(exchange.GetData("https://www.datadata.cn/api/v1/query/xxx/data")); }c++void main() { Log(exchange.GetData("https://www.datadata.cn/api/v1/query/xxx/data")); }
返回值
| 类型 | 描述 |
object | 数据集合中的记录。 |
参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 | 数据集合的名称。 |
timeout | number | 否 | 用于设置缓存超时时间,单位为毫秒。实盘时默认的缓存超时时间为一分钟。 |
参考
备注
回测时一次性获取全部数据,实盘时缓存一分钟的数据。
在回测系统中,当使用访问接口请求数据的方式时,回测系统会自动为请求添加from(时间戳,单位为秒)、to(时间戳,单位为秒)、period(底层K线周期,时间戳,单位为毫秒)等参数,用于确定所要获取数据的时间范围。
exchange.GetMarkets
exchange.GetMarkets()函数用于获取已订阅交易品种的市场信息。
exchange.GetMarkets()示例
在回测系统中调用 exchange.GetMarkets() 函数时,仅返回已订阅的合约信息。
javascript
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
function main() {
var arrSymbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"]
var tbl = {type: "table", title: "test markets", cols: ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"], rows: []}
for (var i = 0; i < 10; i++) {
if (exchange.IO("status")) {
for (var symbol of arrSymbol) {
exchange.SetContractType(symbol)
}
var markets = exchange.GetMarkets()
for (var symbol in markets) {
var market = markets[symbol]
tbl.rows.push([symbol, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize, market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal])
}
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
return
}
Sleep(1000)
}
}
python
'''backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''
import json
def main():
arrSymbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"]
tbl = {"type": "table", "title": "test markets", "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"], "rows": []}
for i in range(10):
if exchange.IO("status"):
for symbol in arrSymbol:
exchange.SetContractType(symbol)
markets = exchange.GetMarkets()
for symbol in markets:
market = markets[symbol]
tbl["rows"].append([symbol, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]])
LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`")
return
Sleep(1000)
rust
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
fn main() {
let arr_symbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"];
for _i in 0..10 {
if exchange.IO("status").unwrap_or_default() == "true" {
for symbol in arr_symbol {
exchange.SetContractType(symbol).unwrap();
}
// Rust 中直接拼接 JSON 字符串构造状态栏表格
let markets = exchange.GetMarkets();
let mut rows: Vec<String> = Vec::new();
for (key, market) in &markets {
rows.push(format!(
r#"["{}", "{}", "{}", "{}", {}, {}, {}, {}, {}, {}, {}, {}, {}]"#,
key, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize, market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal
));
}
let tbl = format!(
r#"{{"type": "table", "title": "test markets", "cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"], "rows": [{}]}}"#,
rows.join(", ")
);
LogStatus!(_D(None), "\n", format!("`{}`", tbl));
return;
}
Sleep(1000);
}
}
c++
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
void main() {
auto arrSymbol = {"rb2501", "MA888", "i2501", "p2501", "TA501"};
json tbl = R"({
"type": "table",
"title": "test markets",
"cols": ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"],
"rows": []
})"_json;
for (int i = 0; i < 10; i++) {
if (exchange.IO("status") == 1) {
for (const auto& symbol : arrSymbol) {
exchange.SetContractType(symbol);
}
auto markets = exchange.GetMarkets();
for (auto& [key, market] : markets.items()) {
json arrJson = {key, market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["TickSize"], market["AmountSize"], market["PricePrecision"], market["AmountPrecision"], market["MinQty"], market["MaxQty"], market["MinNotional"], market["MaxNotional"], market["CtVal"]};
tbl["rows"].push_back(arrJson);
}
LogStatus(_D(), "\n", "`" + tbl.dump() + "`");
return;
}
Sleep(1000);
}
}返回值
| 类型 | 描述 |
object | 包含 |
参考
备注
exchange.GetMarkets()函数的返回值为一个字典,其中键名为合约代码。例如:
json
{
"MA888": {
"AmountPrecision": 1,
"AmountSize": 1,
"BaseAsset": "FUTURES",
"CtVal": 10,
"CtValCcy": "FUTURES",
"MaxNotional": 10000000,
"MaxQty": 1000,
"MinNotional": 1,
"MinQty": 1,
"PricePrecision": 0,
"QuoteAsset": "CNY",
"Symbol": "MA888",
"TickSize": 1
}
// ...
}
-
exchange.GetMarkets()函数支持实盘交易与回测系统。exchange.GetMarkets()函数仅返回已订阅品种的相关数据。
exchange.GetTickers
exchange.GetTickers()函数用于获取已订阅交易品种的聚合行情数据(由Ticker结构组成的数组)。
exchange.GetTickers()示例
在回测系统中调用exchange.GetTickers()函数时,仅返回已订阅合约的聚合行情数据。
javascript
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
function main() {
var arrSymbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"]
var tbl = {type: "table", title: "test tickers", cols: ["Symbol", "Buy", "Sell", "Open", "Last", "High", "Low", "Volume", "Time", "OpenInterest"], rows: []}
for (var i = 0; i < 10; i++) {
if (exchange.IO("status")) {
for (var symbol of arrSymbol) {
exchange.SetContractType(symbol)
}
var tickers = exchange.GetTickers()
for (var ticker of tickers) {
tbl.rows.push([ticker.Symbol, ticker.Buy, ticker.Sell, ticker.Open, ticker.Last, ticker.High, ticker.Low, ticker.Volume, ticker.Time, ticker.OpenInterest])
}
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
return
}
Sleep(1000)
}
}
python
'''backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''
import json
def main():
arrSymbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"]
tbl = {"type": "table", "title": "test tickers", "cols": ["Symbol", "Buy", "Sell", "Open", "Last", "High", "Low", "Volume", "Time", "OpenInterest"], "rows": []}
for i in range(10):
if exchange.IO("status"):
for symbol in arrSymbol:
exchange.SetContractType(symbol)
tickers = exchange.GetTickers()
for ticker in tickers:
tbl["rows"].append([ticker["Symbol"], ticker["Buy"], ticker["Sell"], ticker["Open"], ticker["Last"], ticker["High"], ticker["Low"], ticker["Volume"], ticker["Time"], ticker["OpenInterest"]])
LogStatus(_D(), "\n", "`" + json.dumps(tbl) + "`")
return
Sleep(1000)
rust
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
fn main() {
let arr_symbol = ["rb2501", "MA888", "i2501", "p2501", "TA501"];
for _i in 0..10 {
if exchange.IO("status").unwrap_or_default() == "true" {
for symbol in arr_symbol {
exchange.SetContractType(symbol).unwrap();
}
// Rust 中直接拼接 JSON 字符串构造状态栏表格
let tickers = exchange.GetTickers().unwrap();
let mut rows: Vec<String> = Vec::new();
for ticker in &tickers {
rows.push(format!(
r#"["{}", {}, {}, {}, {}, {}, {}, {}, {}, {}]"#,
ticker.Symbol, ticker.Buy, ticker.Sell, ticker.Open, ticker.Last, ticker.High, ticker.Low, ticker.Volume, ticker.Time, ticker.OpenInterest
));
}
let tbl = format!(
r#"{{"type": "table", "title": "test tickers", "cols": ["Symbol", "Buy", "Sell", "Open", "Last", "High", "Low", "Volume", "Time", "OpenInterest"], "rows": [{}]}}"#,
rows.join(", ")
);
LogStatus!(_D(None), "\n", format!("`{}`", tbl));
return;
}
Sleep(1000);
}
}
c++
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
void main() {
auto arrSymbol = {"rb2501", "MA888", "i2501", "p2501", "TA501"};
json tbl = R"({
"type": "table",
"title": "test tickers",
"cols": ["Symbol", "Buy", "Sell", "Open", "Last", "High", "Low", "Volume", "Time", "OpenInterest"],
"rows": []
})"_json;
for (int i = 0; i < 10; i++) {
if (exchange.IO("status") == 1) {
for (const auto& symbol : arrSymbol) {
exchange.SetContractType(symbol);
}
auto tickers = exchange.GetTickers();
for (auto& ticker : tickers) {
json arrJson = {ticker.Symbol, ticker.Buy, ticker.Sell, ticker.Open, ticker.Last, ticker.High, ticker.Low, ticker.Volume, ticker.Time, ticker.OpenInterest};
tbl["rows"].push_back(arrJson);
}
LogStatus(_D(), "\n", "`" + tbl.dump() + "`");
return;
}
Sleep(1000);
}
}返回值
| 类型 | 描述 |
|
|
参考
备注
注意事项:
-
exchange.GetTickers()函数支持实盘交易与回测系统。 -
exchange.GetTickers()函数仅返回已订阅品种的相关数据。
Trade
exchange.Buy
exchange.Buy()函数用于下达买单。Buy()函数是交易所对象exchange的成员函数。
Buy()函数操作交易所对象exchange所绑定的交易所账户。exchange对象的成员函数(方法)的用途仅与exchange相关,后续文档中不再赘述。
exchange.Buy(price, amount)
exchange.Buy(price, amount, ...args)示例
-
exchange.Buy()返回的订单编号,可用于查询订单信息和撤销订单。javascriptfunction main() { // 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("buy") // 注意,此处的下单价格 100 仅为示例,实际测试时可自行设置和修改 var id = exchange.Buy(100, 1) Log("id:", id) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("buy") id = exchange.Buy(100, 1) Log("id:", id)rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("buy"); // 注意,此处的下单价格 100 仅为示例,实际测试时可自行设置和修改 let id = exchange.Buy(100, 1); Log!("id:", id); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("buy"); auto id = exchange.Buy(100, 1); Log("id:", id); } -
商品期货和股票证券除了可以使用市价单(价格参数传入 -1,实际上系统会使用一个较高的买入价或较低的卖出价来确保成交),还可以使用限价单方式下单。此时可以设置一个较大的滑点,以确保与对手盘成交,具体请参看
exchange.Sell中的范例。javascriptfunction main() { // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("buy") // 下单价格参数传入 -1 即为市价单 var id = exchange.Buy(-1, 1) Log("id:", id) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("buy") id = exchange.Buy(-1, 1) Log("id:", id)rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("buy"); // 下单价格参数传入 -1 即为市价单 let id = exchange.Buy(-1, 1); Log!("id:", id); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("buy"); auto id = exchange.Buy(-1, 1); Log("id:", id); }
返回值
| 类型 | 描述 |
string / 空值 | 下单成功时返回订单Id,下单失败时返回空值。 |
参数
| 名称 | 类型 | 必填 | 描述 |
price | number | 是 |
|
amount | number | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,可用于向该条下单日志中输出附带信息。 |
参考
备注
期货合约下单时,必须注意交易方向是否设置正确。如果交易方向与交易函数不匹配,将会报错。参考:exchange.SetDirection
参数price设置为-1时用于下达市价单,回测系统与实盘环境均支持市价单。
股票证券下单:
下单量为股票股数,而非股票手数(在股票证券交易所对象中,如无特殊说明,相关的量均指股票股数)。下单量需符合股票信息中的每手股数要求。例如,02333.HK为港股长城汽车,每手500股,下单量必须是500的整数倍;601633.SH为A股长城汽车,每手100股,下单量必须是100的整数倍。每手股数可以从SetContractType函数返回的数据结构中获取(VolumeMultiple字段),也可以从GetTicker()函数返回的数据结构的Info属性中获取(LotSize字段)。
exchange.Sell
exchange.Sell()函数用于下达卖单。
exchange.Sell(price, amount)
exchange.Sell(price, amount, ...args)示例
-
exchange.Sell()返回的订单编号,可用于查询订单信息及撤销订单。javascriptfunction main(){ // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("sell") // 注意,这里的下单价格100为举例,具体测试的时候可以自行设置、改动 var id = exchange.Sell(100, 1) Log("id:", id) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("sell") id = exchange.Sell(100, 1) Log("id:", id)rustfn main() { // 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("sell"); // 注意,这里的下单价格100为举例,具体测试的时候可以自行设置、改动 let id = exchange.Sell(100, 1); Log!("id:", id); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("sell"); auto id = exchange.Sell(100, 1); Log("id:", id); } -
商品期货除了可以使用市价单下单外,还可以使用限价单下单。此时可设置一个较大的滑价,以确保与对手盘成交。
javascriptfunction main() { while(true) { if (exchange.IO("status")) { // 设置当前合约为 rb2001,测试时请根据回测时间设置合适的合约 exchange.SetContractType("rb2001") exchange.SetDirection("buy") // 获取当前行情 var ticker = exchange.GetTicker() // 获取当前卖一价格 var currSell1Price = ticker.Sell // 加 50 元滑价,即以比卖一挂单价高 50 的价格买入 1 手 var id = exchange.Buy(currSell1Price + 50, 1) Log(exchange.GetOrder(id)) break } else { Log("未连接") } } }pythondef main(): while True: if exchange.IO("status"): exchange.SetContractType("rb2001") exchange.SetDirection("buy") ticker = exchange.GetTicker() currSell1Price = ticker["Sell"] id = exchange.Buy(currSell1Price + 50, 1) Log(exchange.GetOrder(id)) break else : Log("未连接")rustfn main() { loop { if exchange.IO("status").unwrap_or_default() == "true" { // 设置当前合约为 rb2001,测试时请根据回测时间设置合适的合约 let _ = exchange.SetContractType("rb2001"); let _ = exchange.SetDirection("buy"); // 获取当前行情 let ticker = exchange.GetTicker(None).unwrap(); // 获取当前卖一价格 let currSell1Price = ticker.Sell; // 加 50 元滑价,即以比卖一挂单价高 50 的价格买入 1 手 let id = exchange.Buy(currSell1Price + 50.0, 1).unwrap(); Log!(exchange.GetOrder(&id)); break; } else { Log!("未连接"); } } }c++void main() { while(true) { if(exchange.IO("status") == 1) { exchange.SetContractType("rb2001"); exchange.SetDirection("buy"); auto ticker = exchange.GetTicker(); auto currSell1Price = ticker.Sell; auto id = exchange.Buy(currSell1Price + 50, 1); Log(exchange.GetOrder(id)); break; } else { Log("未连接"); } } }
返回值
| 类型 | 描述 |
string / 空值 | 下单成功时返回订单Id,下单失败时返回空值。参考 |
参数
| 名称 | 类型 | 必填 | 描述 |
price | number | 是 |
|
amount | number | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,可用于将附带信息输出到该条下单日志中, |
参考
备注
期货合约下单时务必注意交易方向是否设置正确,若交易方向与交易函数不匹配将会报错。参考:exchange.SetDirection
参数price设置为-1时用于下达市价单,回测系统与实盘环境均支持市价单。
下单量为股票股数,而非股票手数(在股票证券交易所对象中,若无特殊说明,相关的量均指股票股数)。下单量需符合股票信息中每手股数的要求。参考exchange.Buy。
exchange.CreateOrder
exchange.CreateOrder()函数用于下单。
exchange.CreateOrder(symbol, side, price, amount)
exchange.CreateOrder(symbol, side, price, amount, ...args)示例
商品期货交易所对象调用exchange.CreateOrder()函数下单。
javascript
function main() {
while(!exchange.IO("status")) {
Sleep(1000)
}
// 调用CreateOrder函数下单
var id = exchange.CreateOrder("rb2410", "buy", 3500, 1)
Log(id)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
id = exchange.CreateOrder("rb2410", "buy", 3500, 1)
Log(id)
rust
fn main() {
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
// 调用CreateOrder函数下单
let id = exchange.CreateOrder("rb2410", "buy", 3500, 1);
Log!(id);
}
c++
void main() {
while (exchange.IO("status") == 0) {
Sleep(1000);
}
auto id = exchange.CreateOrder("rb2410", "buy", 3500, 1);
Log(id);
}返回值
| 类型 | 描述 |
string / 空值 | 下单成功时返回订单ID,下单失败时返回空值。 |
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 是 | 参数 |
side | string | 是 |
其中, |
price | number | 是 |
|
amount | number | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,用于向该条下单日志输出附带信息, |
参考
exchange.Buy exchange.Sell exchange.IO(API限流控制)
exchange.CancelOrder
exchange.CancelOrder()函数用于取消订单。
exchange.CancelOrder(orderId)
exchange.CancelOrder(orderId, ...args)示例
-
撤销订单。
javascriptfunction main(){ // 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断成功连接期货公司前置机后,立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("sell") // 下单价格仅为示例,价格过高将无法成交,订单会停留在订单簿中等待成交,具体测试时可自行调整价格 var id = exchange.Sell(99999, 1) exchange.CancelOrder(id) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("sell") id = exchange.Sell(99999, 1) exchange.CancelOrder(id)rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,此处仅通过 exchange.IO("status") 函数判断成功连接期货公司前置机后,立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("sell"); // 下单价格仅为示例,价格过高将无法成交,订单会停留在订单簿中等待成交,具体测试时可自行调整价格 let id = exchange.Sell(99999, 1).unwrap(); let _ = exchange.CancelOrder(&id); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("sell"); auto id = exchange.Sell(99999, 1); exchange.CancelOrder(id); } -
在优宽量化的API函数中,能够产生日志输出的函数(例如
Log(...)、exchange.Buy(Price, Amount)、exchange.CancelOrder(Id)等)均可在必要参数之后附加一些额外的输出参数。例如:
exchange.CancelOrder(orders[j].Id, orders[j]),即在取消Id为orders[j].Id的订单时,附带输出该订单的信息,也就是orders[j]这个Order结构。javascriptfunction main() { // 由于这是测试代码,未采用商品期货策略的一般架构,这里仅通过exchange.IO("status")函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票证券则无需使用exchange.IO("status")判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("sell") Log("数据1", "数据2", "数据3", "...") var data2 = 200 // 下单价格仅为示例,价格过高不会成交,订单会处于订单簿中等待成交状态,实际测试时可自行调整价格 var id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...") exchange.CancelOrder(id, "附带数据1", data2, "...") LogProfit(100, "附带数据1", data2, "...") }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("sell") Log("数据1", "数据2", "数据3", "...") data2 = 200 id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...") exchange.CancelOrder(id, "附带数据1", data2, "...") LogProfit(100, "附带数据1", data2, "...")rustfn main() { // 由于这是测试代码,未采用商品期货策略的一般架构,这里仅通过exchange.IO("status")函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票证券则无需使用exchange.IO("status")判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("sell"); Log!("数据1", "数据2", "数据3", "..."); let data2 = 200; // Rust 不支持在 exchange.Sell()、exchange.CancelOrder()、LogProfit() 等函数中传入附带输出参数,可使用 Log! 宏单独输出附带信息 // 下单价格仅为示例,价格过高不会成交,订单会处于订单簿中等待成交状态,实际测试时可自行调整价格 let id = exchange.Sell(100000, 0.1).unwrap(); Log!("附带数据1", data2, "..."); let _ = exchange.CancelOrder(&id); LogProfit(100); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("sell"); Log("数据1", "数据2", "数据3", "..."); int data2 = 200; auto id = exchange.Sell(100000, 0.1, "附带数据1", data2, "..."); exchange.CancelOrder(id, "附带数据1", data2, "..."); LogProfit(100, "附带数据1", data2, "..."); }
返回值
| 类型 | 描述 |
bool |
|
参数
| 名称 | 类型 | 必填 | 描述 |
orderId | string | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,用于向该撤单日志中输出附带信息, |
参考
备注
参数orderId为字符串类型。
exchange.GetOrder
exchange.GetOrder()函数用于获取订单信息。
exchange.GetOrder(orderId)示例
根据指定的订单Id查询订单的详细信息。
javascript
function main(){
// 由于此处为测试代码,未采用商品期货策略的通用架构,仅通过exchange.IO("status")函数判断是否成功连接期货公司前置机,连接成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while (!exchange.IO("status")) {
Sleep(1000)
}
// 设置合约代码
exchange.SetContractType("rb888")
// 设置下单方向
exchange.SetDirection("sell")
// 此处下单价格仅为示例,价格过高不会成交,订单将处于订单簿中的待成交状态,实际测试时可自行调整价格
var id = exchange.Sell(99999, 1)
// 参数id为订单号,需填入所要查询订单的订单号
var order = exchange.GetOrder(id)
Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
order.DealAmount, "Status:", order.Status, "Type:", order.Type)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
exchange.SetContractType("rb888")
exchange.SetDirection("sell")
id = exchange.Sell(99999, 1)
order = exchange.GetOrder(id)
Log("Id:", order["Id"], "Price:", order["Price"], "Amount:", order["Amount"], "DealAmount:",
order["DealAmount"], "Status:", order["Status"], "Type:", order["Type"])
rust
fn main() {
// 由于此处为测试代码,未采用商品期货策略的通用架构,仅通过exchange.IO("status")函数判断是否成功连接期货公司前置机,连接成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
// 设置合约代码
let _ = exchange.SetContractType("rb888");
// 设置下单方向
let _ = exchange.SetDirection("sell");
// 此处下单价格仅为示例,价格过高不会成交,订单将处于订单簿中的待成交状态,实际测试时可自行调整价格
let id = exchange.Sell(99999, 1).unwrap();
// 参数id为订单号,需填入所要查询订单的订单号
let order = exchange.GetOrder(&id).unwrap();
Log!("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
order.DealAmount, "Status:", order.Status, "Type:", order.Type);
}
c++
void main() {
while (exchange.IO("status") == 0) {
Sleep(1000);
}
exchange.SetContractType("rb888");
exchange.SetDirection("sell");
auto id = exchange.Sell(99999, 1);
auto order = exchange.GetOrder(id);
Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
order.DealAmount, "Status:", order.Status, "Type:", order.Type);
}返回值
| 类型 | 描述 |
| 根据订单号查询订单详情,查询成功时返回 |
参数
| 名称 | 类型 | 必填 | 描述 |
orderId | string | 是 |
|
参考
备注
返回值为Order结构。
exchange.GetOrders
exchange.GetOrders()函数用于获取所有合约当前未完成的订单,并支持查询指定合约的未完成订单。
exchange.GetOrders()
exchange.GetOrders(symbol)示例
-
以较高的价格下单,然后查询未成交订单的信息。
javascriptfunction main(){ // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过exchange.IO("status")函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while (!exchange.IO("status")) { Sleep(1000) } // 设置合约代码 exchange.SetContractType("rb888") // 设置下单方向 exchange.SetDirection("sell") // 此处的下单价格仅为示例,过高的价格不会成交,订单将处于订单簿中等待成交,实际测试时可自行调整价格 exchange.Sell(99999, 1) exchange.Sell(88888, 1) var orders = exchange.GetOrders() Log("未完成订单一的信息,ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount, "DealAmount:", orders[0].DealAmount, "Type:", orders[0].Type, "Symbol:", orders[0].Symbol) Log("未完成订单二的信息,ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount, "DealAmount:", orders[1].DealAmount, "Type:", orders[1].Type, "Symbol:", orders[1].Symbol) }pythondef main(): while not exchange.IO("status"): Sleep(1000) exchange.SetContractType("rb888") exchange.SetDirection("sell") exchange.Sell(99999, 1) exchange.Sell(88888, 1) orders = exchange.GetOrders() Log("未完成订单一的信息,ID:", orders[0]["Id"], "Price:", orders[0]["Price"], "Amount:", orders[0]["Amount"], "DealAmount:", orders[0]["DealAmount"], "Type:", orders[0]["Type"], "Symbol:", orders[0]["Symbol"]) Log("未完成订单二的信息,ID:", orders[1]["Id"], "Price:", orders[1]["Price"], "Amount:", orders[1]["Amount"], "DealAmount:", orders[1]["DealAmount"], "Type:", orders[1]["Type"], "Symbol:", orders[1]["Symbol"])rustfn main() { // 由于是测试代码,未采用商品期货策略的通用架构,这里仅通过exchange.IO("status")函数进行判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态 while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 设置合约代码 let _ = exchange.SetContractType("rb888"); // 设置下单方向 let _ = exchange.SetDirection("sell"); // 此处的下单价格仅为示例,过高的价格不会成交,订单将处于订单簿中等待成交,实际测试时可自行调整价格 let _ = exchange.Sell(99999, 1); let _ = exchange.Sell(88888, 1); let orders = exchange.GetOrders(None).unwrap(); Log!("未完成订单一的信息,ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount, "DealAmount:", orders[0].DealAmount, "Type:", orders[0].Type, "Symbol:", orders[0].Symbol); Log!("未完成订单二的信息,ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount, "DealAmount:", orders[1].DealAmount, "Type:", orders[1].Type, "Symbol:", orders[1].Symbol); }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } exchange.SetContractType("rb888"); exchange.SetDirection("sell"); exchange.Sell(99999, 1); exchange.Sell(88888, 1); auto orders = exchange.GetOrders(); Log("未完成订单一的信息,ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount, "DealAmount:", orders[0].DealAmount, "Type:", orders[0].Type, "Symbol:", orders[0].Symbol); Log("未完成订单二的信息,ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount, "DealAmount:", orders[1].DealAmount, "Type:", orders[1].Type, "Symbol:", orders[1].Symbol); } -
在商品期货和股票证券中,
exchange.GetOrders()函数获取的是所有未完成的订单。在商品期货中,exchange.GetOrders()函数获取的订单与当前设置的合约无关。可以使用以下示例进行回测、模拟盘和实盘测试。javascript/*backtest start: 2020-06-17 10:00:00 end: 2020-06-18 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ function main() { var contractTypeList = ["MA009", "rb2010", "i2009"] while (true) { if (exchange.IO("status")) { for (var i = 0; i < contractTypeList.length; i++) { var ret = exchange.SetContractType(contractTypeList[i]) var ticker = exchange.GetTicker() exchange.SetDirection("sell") var id = exchange.Sell(ticker.Sell + 5, 1) Log(contractTypeList[i], "开空仓订单ID:", id) } var orders = exchange.GetOrders() for (var j = 0; j < orders.length; j++) { Log(orders[j]) } break } else { LogStatus(_D(), "未连接") } } }python'''backtest start: 2020-06-17 10:00:00 end: 2020-06-18 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' def main(): contractTypeList = ["MA009", "rb2010", "i2009"] while True: if exchange.IO("status"): for i in range(len(contractTypeList)): ret = exchange.SetContractType(contractTypeList[i]) ticker = exchange.GetTicker() exchange.SetDirection("sell") id = exchange.Sell(ticker["Sell"] + 5, 1) Log(contractTypeList[i], "开空仓订单ID:", id) orders = exchange.GetOrders() for i in range(len(orders)): Log(orders[i]) break else: LogStatus(_D(), "未连接")rust/*backtest start: 2020-06-17 10:00:00 end: 2020-06-18 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ fn main() { let contractTypeList = ["MA009", "rb2010", "i2009"]; loop { if exchange.IO("status").unwrap_or_default() == "true" { for i in 0..contractTypeList.len() { let ret = exchange.SetContractType(contractTypeList[i]); let ticker = exchange.GetTicker(None).unwrap(); let _ = exchange.SetDirection("sell"); let id = exchange.Sell(ticker.Sell + 5.0, 1); Log!(contractTypeList[i], "开空仓订单ID:", id); } let orders = exchange.GetOrders(None).unwrap(); for j in 0..orders.len() { Log!(orders[j]); } break; } else { LogStatus!(_D(None), "未连接"); } } }c++/*backtest start: 2020-06-17 10:00:00 end: 2020-06-18 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ void main() { vector<string> contractTypeList = {"MA009", "rb2010", "i2009"}; while (true) { if (exchange.IO("status") == 1) { for (int i = 0 ; i < contractTypeList.size(); i++) { auto ret = exchange.SetContractType(contractTypeList[i]); auto ticker = exchange.GetTicker(); exchange.SetDirection("sell"); auto id = exchange.Sell(ticker.Sell + 5.0, 1); Log(contractTypeList[i], "开空仓订单ID:", id); } auto orders = exchange.GetOrders(); for (int j = 0; j < orders.size(); j++) { Log(orders[j]); } break; } else { LogStatus(_D(), "未完成"); } } }
返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
参考
备注
当交易所对象exchange所代表的账户没有挂单(即处于未成交状态的活动订单)时,调用exchange.GetOrders()函数将返回空数组,即:[]。
exchange.GetOrders()函数不依赖于当前的合约代码设置;当不传入symbol参数时,将获取所有合约的未完成订单。
exchange.GetHistoryOrders
exchange.GetHistoryOrders() 函数用于获取当前交易日内所有合约的历史订单,并支持查询指定合约的历史订单。
exchange.GetHistoryOrders()
exchange.GetHistoryOrders(symbol)示例
javascript
function main(){
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while (!exchange.IO("status")) {
Sleep(1000)
}
var orders = exchange.GetHistoryOrders()
Log(orders)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
orders = exchange.GetHistoryOrders()
Log(orders)
rust
fn main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
let orders = exchange.GetHistoryOrders(None, None, None);
Log!(orders);
}
c++
void main() {
while (exchange.IO("status") == 0) {
Sleep(1000);
}
auto orders = exchange.GetHistoryOrders();
Log(orders);
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 |
|
参考
备注
注意:exchange.GetHistoryOrders() 函数不依赖于当前合约代码的设置。未传入 symbol 参数时,获取当前交易日内所有合约的历史订单;传入 symbol 参数时,获取当前交易日内指定合约的历史订单。
exchange.SetPrecision
exchange.SetPrecision()函数用于设置exchange交易所对象的价格精度与下单量精度。设置后,系统会自动截断并忽略超出精度范围的多余部分。
exchange.SetPrecision(pricePrecision, amountPrecision)示例
设置价格精度与下单量精度。
javascript
function main(){
// 设置价格小数位精度为2位,品种下单量小数位精度为3位
exchange.SetPrecision(2, 3)
}
python
def main():
exchange.SetPrecision(2, 3)
rust
fn main() {
// 设置价格小数位精度为2位,品种下单量小数位精度为3位
exchange.SetPrecision(2, 3);
}
c++
void main() {
exchange.SetPrecision(2, 3);
}参数
| 名称 | 类型 | 必填 | 描述 |
pricePrecision | number | 是 |
|
amountPrecision | number | 是 |
|
参考
备注
回测系统不支持该函数,回测系统的数值精度会自动处理。pricePrecision和amountPrecision均必须为整型数值。
exchange.SetRate
设置交易所对象当前的汇率。
exchange.SetRate(rate)示例
设置交易所对象当前的汇率。
javascript
function main(){
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while (!exchange.IO("status")) {
Sleep(1000)
}
// 设置合约代码
exchange.SetContractType("rb888")
// 设置汇率之前打印行情数据
Log(exchange.GetTicker())
// 设置汇率转换
exchange.SetRate(7)
Log(exchange.GetTicker())
// 设置为1,不转换
exchange.SetRate(1)
Log(exchange.GetTicker())
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
exchange.SetContractType("rb888")
Log(exchange.GetTicker())
exchange.SetRate(7)
Log(exchange.GetTicker())
exchange.SetRate(1)
Log(exchange.GetTicker())
rust
fn main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
// 设置合约代码
let _ = exchange.SetContractType("rb888");
// 设置汇率之前打印行情数据
Log!(exchange.GetTicker(None));
// 设置汇率转换
exchange.SetRate(7);
Log!(exchange.GetTicker(None));
// 设置为1,不转换
exchange.SetRate(1);
Log!(exchange.GetTicker(None));
}
c++
void main() {
while (exchange.IO("status") == 0) {
Sleep(1000);
}
exchange.SetContractType("rb888");
Log(exchange.GetTicker());
exchange.SetRate(7);
Log(exchange.GetTicker());
exchange.SetRate(1);
Log(exchange.GetTicker());
}参数
| 名称 | 类型 | 必填 | 描述 |
rate | number | 是 |
|
参考
备注
如果使用exchange.SetRate()函数设置了汇率值(例如设置为7),那么当前exchange交易所对象所代表交易所的行情、深度、下单价格等所有价格信息,都会乘以所设置的汇率7进行转换。例如,exchange是以美元为计价货币的交易所,执行exchange.SetRate(7)之后,实盘中所有价格都会乘以7,转换为接近CNY计价的价格。
exchange.IO
exchange.IO()函数用于调用交易所对象相关的协议及其它接口。
exchange.IO(k, ...args)示例
-
使用 status 参数可判断与期货公司前置机的连接状态:
exchange.IO("status"),返回true表示与 CTP 的行情服务器和交易数据服务器均已正常连接。javascriptfunction main() { while (!exchange.IO("status")) { LogStatus("正在等待与交易服务器连接, " + new Date()) } }pythondef main(): while not exchange.IO("status"): LogStatus("正在等待与交易服务器连接, " + _D())rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { LogStatus!("正在等待与交易服务器连接,", _D(None)); } }c++void main() { while(exchange.IO("status") == 0) { LogStatus("正在等待与交易服务器连接, " + _D()); } } -
使用
wait参数设置阻塞:exchange.IO("wait", Timeout),仅当当前交易所有任意品种的行情信息更新或订单成交时才返回。可通过第二个参数(毫秒数)指定超时时间:超时返回空值,正常返回EventTick/OrderEvent结构。该函数需结合exchange.IO("mode", 0)一起使用,以便程序在有最新行情时及时响应并执行相应逻辑(使用exchange.IO("mode", 0)并不影响exchange.IO("wait"),其作用是使程序中调用exchange.GetTicker()等函数时不发生阻塞)。若Timeout参数设置为-1,该函数将立即返回,在没有新事件时返回空值;若Timeout参数设置为0,则阻塞等待最新事件,效果等同于不设置Timeout参数。需要注意的是,使用exchange.IO("wait")时,必须至少已订阅一个当前处于交易状态的合约(已交割的过期合约不再提供行情数据),否则由于没有任何行情或订单更新,程序将阻塞在该函数处。仅支持商品期货实盘。EventTick:{Event:"tick", Index:交易所索引, Nano:事件纳秒级时间, Symbol:合约名称, Ticker:行情数据}。OrderTick:{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息}。简单实现回调机制:
javascriptfunction on_tick(symbol, ticker) { Log("symbol:", symbol, "update") Log("ticker:", ticker) } function on_order(order) { Log("order update", order) } function main() { while(!exchange.IO("status")) { Sleep(10) } // 如果在程序中不使用诸如exchange.GetTicker()之类的获取行情的函数,可以不设置exchange.IO("mode", 0) exchange.IO("mode", 0) _C(exchange.SetContractType, "MA005") while(true) { var e = exchange.IO("wait") if(e) { if(e.Event == "tick") { on_tick(e.Symbol, e.Ticker) } else if(e.Event == "order") { on_order(e.Order) } } } }pythondef on_tick(symbol, ticker): Log("symbol:", symbol, "update") # 数据结构:https://www.youquant.com/api#ticker Log("ticker:", ticker) def on_order(order): Log("order update", order) def main(): # wait connect trade server while not exchange.IO("status"): Sleep(10) # switch push mode exchange.IO("mode", 0) # subscribe instrument _C(exchange.SetContractType, "MA001") while True: e = exchange.IO("wait") if e: if e.Event == "tick": on_tick(e['Symbol'], e['Ticker']) elif e.Event == "order": on_order(e['Order'])rustfn on_tick(symbol: &JsonValue, ticker: &JsonValue) { Log!("symbol:", *symbol, "update"); Log!("ticker:", *ticker); } fn on_order(order: &JsonValue) { Log!("order update", *order); } fn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(10); } // 如果在程序中不使用诸如exchange.GetTicker()之类的获取行情的函数,可以不设置exchange.IO("mode", 0) let _ = exchange.IO(("mode", 0)); _C!(exchange.SetContractType("MA005")); loop { // exchange.IO("wait")返回的是JSON文本,用JSONParse解析后处理 let e = exchange.IO("wait").unwrap_or_default(); if let Some(e) = JSONParse(&e) { if e["Event"].as_str() == Some("tick") { on_tick(&e["Symbol"], &e["Ticker"]); } else if e["Event"].as_str() == Some("order") { on_order(&e["Order"]); } } } }c++void on_tick(const string &symbol, json &ticker) { Log("symbol:", symbol, "update"); Log("ticker:", ticker); } void on_order(json &order) { Log("order update", order); } void main() { while(exchange.IO("status") == 0) { Sleep(10); } exchange.IO("mode", 0); _C(exchange.SetContractType, "rb2005"); while(true) { auto e = exchange.IO("wait"); if(e != false) { if(e["Event"] == "tick") { on_tick(e["Symbol"], e["Ticker"]); } else if(e["Event"] == "order") { on_order(e["Order"]); } } } } -
多品种回调示例:
javascriptfunction on_tick(symbol, ticker) { Log("symbol:", symbol, "update", "ticker:", ticker) } function main() { while(!exchange.IO("status")) { Sleep(10) } _C(exchange.SetContractType, "MA101") _C(exchange.SetContractType, "rb2101") _C(exchange.SetContractType, "i2101") while(true) { var e = exchange.IO("wait", -1) if(e) { if(e.Event == "tick") { on_tick(e.Symbol, e.Ticker) } } Sleep(10) } }pythondef on_tick(symbol, ticker): Log("symbol:", symbol, "update", "ticker:", ticker) def main(): while not exchange.IO("status"): Sleep(10) _C(exchange.SetContractType, "MA101") _C(exchange.SetContractType, "rb2101") _C(exchange.SetContractType, "i2101") while True: e = exchange.IO("wait", -1) if e: if e.Event == "tick": on_tick(e['Symbol'], e['Ticker']) Sleep(10)rustfn on_tick(symbol: &JsonValue, ticker: &JsonValue) { Log!("symbol:", *symbol, "update", "ticker:", *ticker); } fn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(10); } _C!(exchange.SetContractType("MA101")); _C!(exchange.SetContractType("rb2101")); _C!(exchange.SetContractType("i2101")); loop { let e = exchange.IO(("wait", -1)).unwrap_or_default(); if let Some(e) = JSONParse(&e) { if e["Event"].as_str() == Some("tick") { on_tick(&e["Symbol"], &e["Ticker"]); } } Sleep(10); } }c++void on_tick(const string &symbol, json &ticker) { Log("symbol:", symbol, "update", "ticker:", ticker); } void main() { while(exchange.IO("status") == 0) { Sleep(10); } _C(exchange.SetContractType, "MA101"); _C(exchange.SetContractType, "rb2101"); _C(exchange.SetContractType, "i2101"); while(true) { auto e = exchange.IO("wait", -1); if(e != false) { if(e["Event"] == "tick") { on_tick(e["Symbol"], e["Ticker"]); } } } } -
使用
instruments参数获取所有合约的列表数据:exchange.IO("instruments"),返回交易所全部合约的列表,仅支持实盘。javascriptfunction main() { while (!exchange.IO("status")) { LogStatus("正在等待与交易服务器连接, " + new Date()) } Log("开始获取所有合约") var instruments = _C(exchange.IO, "instruments") Log("合约列表获取成功") var len = 0 for (var instrumentId in instruments) { len++ } Log("合约列表长度为:",len) }pythondef main(): while not exchange.IO("status"): LogStatus("正在等待与交易服务器连接, " + _D()) Log("开始获取所有合约") instruments = _C(exchange.IO, "instruments") Log("合约列表获取成功") length = 0 for i in range(len(instruments)): length += 1 Log("合约列表长度为:", length)rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { LogStatus!("正在等待与交易服务器连接,", _D(None)); } Log!("开始获取所有合约"); let instruments = _C!(exchange.IO("instruments")); Log!("合约列表获取成功"); // 返回的是JSON文本,解析后统计合约个数 let parsed = JSONParse(&instruments).unwrap_or_default(); let mut len = 0; if let Some(obj) = parsed.as_object() { for _instrumentId in obj.keys() { len += 1; } } Log!("合约列表长度为:", len); }c++void main() { while(exchange.IO("status") == 0) { LogStatus("正在等待与交易服务器连接, " + _D()); } Log("开始获取所有合约"); auto instruments = _C(exchange.IO, "instruments"); Log("合约列表获取成功"); int length = 0; for(int i = 0; i < instruments.size(); i++) { length++; } Log("合约列表长度为:", length); } -
使用
products参数获取所有产品的列表数据:
exchange.IO("products"),返回交易所全部产品的列表,仅支持实盘。使用
subscribed参数获取已订阅的合约数据:
exchange.IO("subscribed"),返回已订阅行情的合约,仅支持实盘。使用
settlement参数获取结算单数据:
exchange.IO("settlement")用于查询结算单。若不传入第二个参数,默认返回上一个交易日的数据;若传入如20170317的参数,则返回日期为2017-03-17的结算单,仅支持实盘。使用api参数调用底层接口:
优宽量化的CTP(商品期货)终端提供了完整的全API实现。当发明者平台的API无法满足你所需的功能时,可以使用
exchange.IO函数进行更深层的系统调用,且完全兼容官方的API名称。CTP的IO直接扩展函数调用请求,将在收到第一个isLast标记为true的响应包后返回。CTP协议接口:CTP协议接口相关资料
以下通过几个简单的例子进行说明:
-
查询投资者信息:
javascriptfunction main() { while (!exchange.IO("status")) { LogStatus("正在等待与交易服务器建立连接, " + new Date()) } Log(exchange.IO("api", "ReqQryInvestor")) }pythondef main(): while not exchange.IO("status"): LogStatus("正在等待与交易服务器建立连接, " + _D()) Log(exchange.IO("api", "ReqQryInvestor"))rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { LogStatus!("正在等待与交易服务器建立连接,", _D(None)); } Log!(exchange.IO(("api", "ReqQryInvestor"))); }c++void main() { while(exchange.IO("status") == 0) { LogStatus("正在等待与交易服务器建立连接, " + _D()); } Log(exchange.IO("api", "ReqQryInvestor")); } -
修改密码:
javascriptfunction main() { // CTP 协议建立连接需要一定时间 Sleep(6000) exchange.IO("api", "ReqUserPasswordUpdate", {BrokerID: "9999", UserID: "11111", OldPassword: "oldpass", NewPassword: "newpass"}) }pythondef main(): Sleep(6000) exchange.IO("api", "ReqUserPasswordUpdate", {"BrokerID": "9999", "UserID": "11111", "OldPassword": "oldpass", "NewPassword": "newpass"})rustfn main() { // CTP 协议建立连接需要一定时间 Sleep(6000); let _ = exchange.IO(("api", "ReqUserPasswordUpdate", r#"{"BrokerID": "9999", "UserID": "11111", "OldPassword": "oldpass", "NewPassword": "newpass"}"#)); }c++void main() { Sleep(6000); exchange.IO("api", "ReqUserPasswordUpdate", R"({"BrokerID": "9999", "UserID": "11111", "OldPassword": "oldpass", "NewPassword": "newpass"})"_json); } -
复杂示例:
javascriptfunction main() { // CTP 协议建立连接需要一定时间 Sleep(6000) // 若增加一个值为 false 的参数,表示不等待返回值,仅发送请求;第三个参数只需填充所需的字段,也可省略此参数;若字段类型为 char,传入长度为 1 的字符串即可 var r = exchange.IO("api", "ReqQryProduct", {ProductID: "MA"}) // CTP 未登录时调用会失败 if (!r) { return } _.each(r, function(item) { // IO 请求可能返回多个数据包,因此以数组形式返回。遍历数据包中的所有数据类型;一个数据包可能包含多条具体数据,具体数据类型的名称请参阅 CTP 官方文档 http://www.sfit.com.cn/5_2_DocumentDown.htm _.each(item, function(f) { // 取出所需的数据,Name 为该数据的类型,Value 为该数据的值 if (f.Name == 'CThostFtdcProductField') { // 打印查询到的甲醇合约信息 Log(f.Value) } }) }); }pythondef main(): Sleep(6000) r = exchange.IO("api", "ReqQryProduct", {"ProductID": "MA"}) if not r: return for r_index in range(len(r)): for f_index in range(len(r[r_index])): if r[r_index][f_index]["Name"] == 'CThostFtdcProductField': Log(r[r_index][f_index]["Value"])rustfn main() { // CTP 协议建立连接需要一定时间 Sleep(6000); // 第三个参数只需填充所需的字段(JSON 文本形式);若字段类型为 char,传入长度为 1 的字符串即可 let r = exchange.IO(("api", "ReqQryProduct", r#"{"ProductID": "MA"}"#)).unwrap_or_default(); // CTP 未登录时调用会失败 let r = match JSONParse(&r) { Some(v) => v, None => return, }; // IO 请求可能返回多个数据包,因此以数组形式返回。遍历数据包中的所有数据类型;一个数据包可能包含多条具体数据,具体数据类型的名称请参阅 CTP 官方文档 http://www.sfit.com.cn/5_2_DocumentDown.htm if let Some(packets) = r.as_array() { for item in packets { if let Some(fields) = item.as_array() { for f in fields { // 取出所需的数据,Name 为该数据的类型,Value 为该数据的值 if f["Name"].as_str() == Some("CThostFtdcProductField") { // 打印查询到的甲醇合约信息 Log!(f["Value"]); } } } } } }c++void main() { Sleep(6000); auto r = exchange.IO("api", "ReqQryProduct", R"({"ProductID": "MA"})"_json); if(r == false) { return; } for(auto& ele1 : r.items()) { for(auto& ele2 : ele1.value().items()) { if(ele2.value()["Name"] == "CThostFtdcProductField") { Log(ele2.value()["Value"]); } } } } -
复杂的示例:
javascriptfunction main() { while (!exchange.IO("status")) { LogStatus("正在等待与交易服务器建立连接, " + new Date()) } // 也可不指定日期 var r = exchange.IO("api", "ReqQrySettlementInfo", {TradingDay: "20190506"}) var s = '' _.each(r, function(item) { _.each(item, function(f) { if (f.Name == 'CThostFtdcSettlementInfoField') { s += f.Value.Content } }) }) Log(s) }pythondef main(): while not exchange.IO("status"): LogStatus("正在等待与交易服务器建立连接, " + _D()) r = exchange.IO("api", "ReqQrySettlementInfo", {"TradingDay": "20190506"}) s = '' for i in range(len(r)): for ii in range(len(r[i])): if r[i][ii]["Name"] == "CThostFtdcSettlementInfoField": s += r[i][ii]["Value"]["Content"] Log(s)rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { LogStatus!("正在等待与交易服务器建立连接,", _D(None)); } // 也可不指定日期 let r = exchange.IO(("api", "ReqQrySettlementInfo", r#"{"TradingDay": "20190506"}"#)).unwrap_or_default(); let parsed = JSONParse(&r).unwrap_or_default(); let mut s = String::new(); if let Some(packets) = parsed.as_array() { for item in packets { if let Some(fields) = item.as_array() { for f in fields { if f["Name"].as_str() == Some("CThostFtdcSettlementInfoField") { s += f["Value"]["Content"].as_str().unwrap_or(""); } } } } } Log!(s); }c++void main() { while(exchange.IO("status") == 0) { LogStatus("正在等待与交易服务器建立连接, " + _D()); } auto r = exchange.IO("api", "ReqQrySettlementInfo", R"({"TradingDay": "20200311"})"_json); string s = ""; for(auto& ele1 : r.items()) { for(auto& ele2 : ele1.value().items()) { if(ele2.value()["Name"] == "CThostFtdcSettlementInfoField") { s += std::string(ele2.value()["Value"]["Content"]); } } } Log(s); } -
限制 GetTicker 每秒最多调用 3 次,超出限制时报错并返回空值:
javascriptfunction main() { // 等待与交易服务器建立连接 while (!exchange.IO("status")) { LogStatus("正在等待与交易服务器建立连接, " + new Date()) Sleep(1000) } // 场景1:限制 GetTicker 每秒最多调用 3 次,超出限制时返回 null exchange.IO("rate", "GetTicker", 3, "1s") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Log("Exchange not ready, waiting...", "#FF0000") Sleep(5000) continue } var ticker = exchange.GetTicker("rb888") // 螺纹钢主力合约 if (ticker) { Log("Call", i+1, "Success, Price:", ticker.Last) } else { Log("Call", i+1, "Failed: Rate limit exceeded", "#FF0000") } Sleep(100) } }pythondef main(): # 等待与交易服务器建立连接 while not exchange.IO("status"): LogStatus("正在等待与交易服务器建立连接, " + _D()) Sleep(1000) # 场景1:限制 GetTicker 每秒最多调用 3 次,超出限制时返回 null exchange.IO("rate", "GetTicker", 3, "1s") for i in range(10): if not exchange.IO("status"): Log("Exchange not ready, waiting...", "#FF0000") Sleep(5000) continue ticker = exchange.GetTicker("rb888") # 螺纹钢主力合约 if ticker: Log("Call", i+1, "Success, Price:", ticker["Last"]) else: Log("Call", i+1, "Failed: Rate limit exceeded", "#FF0000") Sleep(100)rustfn main() { // 等待与交易服务器建立连接 while exchange.IO("status").unwrap_or_default() != "true" { LogStatus!("正在等待与交易服务器建立连接,", _D(None)); Sleep(1000); } // 场景1:限制 GetTicker 每秒最多调用 3 次,超出限制时返回错误 let _ = exchange.IO(("rate", "GetTicker", 3, "1s")); for i in 0..10 { if exchange.IO("status").unwrap_or_default() != "true" { Log!("Exchange not ready, waiting...", "#FF0000"); Sleep(5000); continue; } // 螺纹钢主力合约 match exchange.GetTicker("rb888") { Ok(ticker) => Log!("Call", i + 1, "Success, Price:", ticker.Last), Err(_) => Log!("Call", i + 1, "Failed: Rate limit exceeded", "#FF0000"), } Sleep(100); } }c++void main() { // 等待与交易服务器建立连接 while (exchange.IO("status") == 0) { LogStatus("正在等待与交易服务器建立连接, " + _D()); Sleep(1000); } // 场景1:限制 GetTicker 每秒最多调用 3 次,超出限制时返回无效数据 exchange.IO("rate", "GetTicker", 3, "1s"); for (int i = 0; i < 10; i++) { if (exchange.IO("status") == 0) { Log("Exchange not ready, waiting...", "#FF0000"); Sleep(5000); continue; } auto ticker = exchange.GetTicker("rb888"); // 螺纹钢主力合约 if (ticker.Valid) { Log("Call", i + 1, "Success, Price:", ticker.Last); } else { Log("Call", i + 1, "Failed: Rate limit exceeded", "#FF0000"); } Sleep(100); } } -
限制 GetTicker 每秒最多调用 3 次,超出频率限制时自动等待:
javascriptfunction main() { while (!exchange.IO("status")) { Sleep(1000) } // 场景 2:使用 delay 参数,超出频率限制时自动等待 exchange.IO("rate", "GetTicker", 3, "1s", "delay") Log("Start testing delay mode with m888 (soybean meal)", "#00FF00") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var startTime = new Date().getTime() var ticker = exchange.GetTicker("m888") // 豆粕主力合约 var endTime = new Date().getTime() if (ticker) { Log("Call", i+1, "Price:", ticker.Last, "Time cost:", endTime - startTime, "ms") } } }pythonimport time def main(): while not exchange.IO("status"): Sleep(1000) # 场景 2:使用 delay 参数,超出频率限制时自动等待 exchange.IO("rate", "GetTicker", 3, "1s", "delay") Log("Start testing delay mode with m888 (soybean meal)", "#00FF00") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue startTime = time.time() * 1000 ticker = exchange.GetTicker("m888") # 豆粕主力合约 endTime = time.time() * 1000 if ticker: Log("Call", i+1, "Price:", ticker["Last"], "Time cost:", endTime - startTime, "ms")rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 场景 2:使用 delay 参数,超出频率限制时自动等待 let _ = exchange.IO(("rate", "GetTicker", 3, "1s", "delay")); Log!("Start testing delay mode with m888 (soybean meal)", "#00FF00"); for i in 0..10 { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(5000); continue; } let startTime = UnixNano() / 1000000; // 豆粕主力合约 let ticker = exchange.GetTicker("m888"); let endTime = UnixNano() / 1000000; if let Ok(ticker) = ticker { Log!("Call", i + 1, "Price:", ticker.Last, "Time cost:", endTime - startTime, "ms"); } } }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } // 场景 2:使用 delay 参数,超出频率限制时自动等待 exchange.IO("rate", "GetTicker", 3, "1s", "delay"); Log("Start testing delay mode with m888 (soybean meal)", "#00FF00"); for (int i = 0; i < 10; i++) { if (exchange.IO("status") == 0) { Sleep(5000); continue; } auto startTime = UnixNano() / 1000000; auto ticker = exchange.GetTicker("m888"); // 豆粕主力合约 auto endTime = UnixNano() / 1000000; if (ticker.Valid) { Log("Call", i + 1, "Price:", ticker.Last, "Time cost:", endTime - startTime, "ms"); } } } -
限制多个函数的联合调用频率:
javascriptfunction main() { while (!exchange.IO("status")) { Sleep(1000) } // 场景3: GetTicker 与 GetDepth 共享调用频率限制,合计每秒最多 5 次 exchange.IO("mode", 0) // 切换为接口立即返回模式 exchange.IO("rate", "GetTicker,GetDepth", 5, "1s") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } if (i % 2 == 0) { var ticker = exchange.GetTicker("i888") // 铁矿石主力合约 Log("Call", i+1, "GetTicker:", ticker ? "Success" : "Failed") } else { var depth = exchange.GetDepth("i888") Log("Call", i+1, "GetDepth:", depth ? "Success" : "Failed") } Sleep(100) } }pythondef main(): while not exchange.IO("status"): Sleep(1000) # 场景3: GetTicker 与 GetDepth 共享调用频率限制,合计每秒最多 5 次 exchange.IO("mode", 0) # 切换为接口立即返回模式 exchange.IO("rate", "GetTicker,GetDepth", 5, "1s") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue if i % 2 == 0: ticker = exchange.GetTicker("i888") # 铁矿石主力合约 Log("Call", i+1, "GetTicker:", "Success" if ticker else "Failed") else: depth = exchange.GetDepth("i888") Log("Call", i+1, "GetDepth:", "Success" if depth else "Failed") Sleep(100)rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 场景3: GetTicker 与 GetDepth 共享调用频率限制,合计每秒最多 5 次 let _ = exchange.IO(("mode", 0)); // 切换为接口立即返回模式 let _ = exchange.IO(("rate", "GetTicker,GetDepth", 5, "1s")); for i in 0..10 { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(5000); continue; } if i % 2 == 0 { // 铁矿石主力合约 let ticker = exchange.GetTicker("i888"); Log!("Call", i + 1, "GetTicker:", if ticker.is_ok() { "Success" } else { "Failed" }); } else { let depth = exchange.GetDepth("i888"); Log!("Call", i + 1, "GetDepth:", if depth.is_ok() { "Success" } else { "Failed" }); } Sleep(100); } }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } // 场景3: GetTicker 与 GetDepth 共享调用频率限制,合计每秒最多 5 次 exchange.IO("mode", 0); // 切换为接口立即返回模式 exchange.IO("rate", "GetTicker,GetDepth", 5, "1s"); for (int i = 0; i < 10; i++) { if (exchange.IO("status") == 0) { Sleep(5000); continue; } if (i % 2 == 0) { auto ticker = exchange.GetTicker("i888"); // 铁矿石主力合约 Log("Call", i + 1, "GetTicker:", ticker.Valid ? "Success" : "Failed"); } else { auto depth = exchange.GetDepth("i888"); Log("Call", i + 1, "GetDepth:", depth.Valid ? "Success" : "Failed"); } Sleep(100); } } -
使用通配符限制所有 API 调用的频率:
javascriptfunction main() { while (!exchange.IO("status")) { Sleep(1000) } // 场景 4:将所有 API 调用限制为每秒最多 5 次 exchange.IO("mode", 0) // 设置为立即返回模式 exchange.IO("rate", "*", 5, "1s") var symbols = ["rb888", "m888", "i888"] // 螺纹钢、豆粕、铁矿石 for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var symbol = symbols[i % symbols.length] var ticker = exchange.GetTicker(symbol) var depth = exchange.GetDepth(symbol) var account = exchange.GetAccount() Log("Round", i+1, symbol, "Ticker:", ticker ? "✓" : "✗", "Depth:", depth ? "✓" : "✗", "Account:", account ? "✓" : "✗") Sleep(100) } }pythondef main(): while not exchange.IO("status"): Sleep(1000) # 场景 4:将所有 API 调用限制为每秒最多 5 次 exchange.IO("mode", 0) # 设置为立即返回模式 exchange.IO("rate", "*", 5, "1s") symbols = ["rb888", "m888", "i888"] # 螺纹钢、豆粕、铁矿石 for i in range(10): if not exchange.IO("status"): Sleep(5000) continue symbol = symbols[i % len(symbols)] ticker = exchange.GetTicker(symbol) depth = exchange.GetDepth(symbol) account = exchange.GetAccount() Log("Round", i+1, symbol, "Ticker:", "✓" if ticker else "✗", "Depth:", "✓" if depth else "✗", "Account:", "✓" if account else "✗") Sleep(100)rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 场景 4:将所有 API 调用限制为每秒最多 5 次 let _ = exchange.IO(("mode", 0)); // 设置为立即返回模式 let _ = exchange.IO(("rate", "*", 5, "1s")); let symbols = ["rb888", "m888", "i888"]; // 螺纹钢、豆粕、铁矿石 for i in 0..10 { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(5000); continue; } let symbol = symbols[i % symbols.len()]; let ticker = exchange.GetTicker(symbol); let depth = exchange.GetDepth(symbol); let account = exchange.GetAccount(); Log!("Round", i + 1, symbol, "Ticker:", if ticker.is_ok() { "✓" } else { "✗" }, "Depth:", if depth.is_ok() { "✓" } else { "✗" }, "Account:", if account.is_ok() { "✓" } else { "✗" }); Sleep(100); } }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } // 场景 4:将所有 API 调用限制为每秒最多 5 次 exchange.IO("mode", 0); // 设置为立即返回模式 exchange.IO("rate", "*", 5, "1s"); std::vector<string> symbols = {"rb888", "m888", "i888"}; // 螺纹钢、豆粕、铁矿石 for (int i = 0; i < 10; i++) { if (exchange.IO("status") == 0) { Sleep(5000); continue; } auto symbol = symbols[i % symbols.size()]; auto ticker = exchange.GetTicker(symbol); auto depth = exchange.GetDepth(symbol); auto account = exchange.GetAccount(); Log("Round", i + 1, symbol, "Ticker:", ticker.Valid ? "✓" : "✗", "Depth:", depth.Valid ? "✓" : "✗", "Account:", account.Valid ? "✓" : "✗"); Sleep(100); } } -
使用 quota 模式实现严格的时间窗口对齐限流:
javascriptfunction main() { while (!exchange.IO("status")) { Sleep(1000) } // 场景5:quota 模式,严格的时间窗口对齐 exchange.IO("mode", 0) // 切换到立即返回模式 exchange.IO("quota", "GetTicker", 3, "1s") Log("Testing quota mode with c888 (corn)", "#00FF00") for (var i = 0; i < 8; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("c888") // 玉米主力合约 Log(_D(), "Call", i+1, ticker ? "Success" : "Quota exceeded") Sleep(150) // 每 150ms 调用一次,每秒约 6-7 次 } }pythondef main(): while not exchange.IO("status"): Sleep(1000) # 场景5:quota 模式,严格的时间窗口对齐 exchange.IO("mode", 0) # 切换到立即返回模式 exchange.IO("quota", "GetTicker", 3, "1s") Log("Testing quota mode with c888 (corn)", "#00FF00") for i in range(8): if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("c888") # 玉米主力合约 Log(_D(), "Call", i+1, "Success" if ticker else "Quota exceeded") Sleep(150) # 每 150ms 调用一次,每秒约 6-7 次rustfn main() { while exchange.IO("status").unwrap_or_default() != "true" { Sleep(1000); } // 场景5:quota 模式,严格的时间窗口对齐 let _ = exchange.IO(("mode", 0)); // 切换到立即返回模式 let _ = exchange.IO(("quota", "GetTicker", 3, "1s")); Log!("Testing quota mode with c888 (corn)", "#00FF00"); for i in 0..8 { if exchange.IO("status").unwrap_or_default() != "true" { Sleep(5000); continue; } // 玉米主力合约 let ticker = exchange.GetTicker("c888"); Log!(_D(None), "Call", i + 1, if ticker.is_ok() { "Success" } else { "Quota exceeded" }); Sleep(150); // 每 150ms 调用一次,每秒约 6-7 次 } }c++void main() { while (exchange.IO("status") == 0) { Sleep(1000); } // 场景5:quota 模式,严格的时间窗口对齐 exchange.IO("mode", 0); // 切换到立即返回模式 exchange.IO("quota", "GetTicker", 3, "1s"); Log("Testing quota mode with c888 (corn)", "#00FF00"); for (int i = 0; i < 8; i++) { if (exchange.IO("status") == 0) { Sleep(5000); continue; } auto ticker = exchange.GetTicker("c888"); // 玉米主力合约 Log(_D(), "Call", i + 1, ticker.Valid ? "Success" : "Quota exceeded"); Sleep(150); // 每 150ms 调用一次,每秒约 6-7 次 } }
返回值
| 类型 | 描述 |
string / number / bool / object / array / any (系统支持的所有类型) |
|
参数
| 名称 | 类型 | 必填 | 描述 |
k | string | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 是 | 扩展参数,根据具体的调用场景传入, |
参考
备注
使用mode参数切换行情模式:
-
exchange.IO("mode", 0)
立即返回模式。如果当前尚未接收到交易所最新的行情数据推送,则立即返回旧的行情数据;如果已有新数据,则返回新数据。
商品期货中的应用可参考:exchange.IO 函数 wait 参数的使用示例。 -
exchange.IO("mode", 1)
缓存模式(默认模式)。如果当前尚未收到交易所最新的行情数据(与上一次接口获取的数据相比),则等待接收后再返回;如果在调用该函数之前已收到最新的行情数据,则立即返回最新数据。 -
exchange.IO("mode", 2)
强制更新模式,进入等待状态,直到接收到交易所下一次最新推送的数据后返回。
API限流控制功能:
优宽量化平台支持对交易所 API 调用进行频率限制,以避免触发交易所自身的频率限制。平台支持两种限流模式:
-
rate模式(平滑限流):不严格对齐时间窗口,适用于一般的限流需求。
-
quota模式(额度限流):严格对齐时间窗口,例如 1m 对齐到整分钟,1s 对齐到整秒。
函数签名:
javascript
exchange.IO("rate", functionNames, maxCalls, period, [behavior])
exchange.IO("quota", functionNames, maxCalls, period, [behavior])
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| mode | string | 限流模式:"rate"(平滑限流)或 "quota"(额度限流) |
| functionNames | string | 需要限流的函数名,支持单个函数、多个函数(以逗号分隔)或通配符(* 表示所有函数) |
| maxCalls | number | 时间周期内允许的最大调用次数 |
| period | string | 时间周期或重置时间点。支持的时间单位:ns, us, µs, ms, s, m, h, d(例如:"1s", "1m", "1h");支持的重置时间点格式:@HHMM 或 @HHMMSS(例如:"@0815" 表示每天 08:15 重置) |
| behavior | string | 可选参数,用于设置超限行为。默认为空(超限时返回 null 并报错);设置为 "delay" 时,超限会等待 |
支持的函数列表:
交易类:CreateOrder, CancelOrder
账户类:GetAccount, GetPositions
订单类:GetOrder, GetOrders, GetHistoryOrders
行情类:GetTicker, GetDepth, GetRecords
其它:IO/api
注意事项:
-
优宽量化支持的市场:商品期货(如螺纹钢 rb888、豆粕 m888 等)
-
使用 API 限流功能前,必须先通过
exchange.IO("status")进行检查,确保与交易服务器的连接正常 -
建议配合
exchange.IO("mode", 0)立即返回模式使用,以避免不必要的等待 -
IO/api的限流仅对exchange.IO("api", ...)调用生效 -
quota模式严格对齐时间窗口,例如设置
"1s"时,时间窗口按整秒对齐 -
使用
"delay"参数时,调用时间与日志记录时间之间可能存在差异,这属于正常现象
exchange.Log
exchange.Log()函数用于在日志栏区域输出下单、撤单日志。该函数被调用时不会实际下单,仅用于输出和记录交易日志。
exchange.Log(orderType, price, amount)
exchange.Log(orderType, price, amount, ...args)示例
使用exchange.Log(orderType, price, amount)可以进行实盘跟单测试和模拟下单,也可以辅助记录下单信息。
javascript
var id = 123
function main() {
// 下单类型买入,价格999,数量 0.1
exchange.Log(LOG_TYPE_BUY, 999, 0.1)
// 取消订单
exchange.Log(LOG_TYPE_CANCEL, id)
}
python
id = 123
def main():
exchange.Log(LOG_TYPE_BUY, 999, 0.1)
exchange.Log(LOG_TYPE_CANCEL, id)
rust
fn main() {
let id = 123;
// 下单类型买入,价格999,数量 0.1
exchange.Log(LOG_TYPE_BUY, 999, 0.1);
// 取消订单,orderType为LOG_TYPE_CANCEL时price参数为撤单的订单Id(Rust中amount参数必传,可传0)
exchange.Log(LOG_TYPE_CANCEL, id, 0);
}
c++
void main() {
auto id = 123;
exchange.Log(LOG_TYPE_BUY, 999, 0.1);
exchange.Log(LOG_TYPE_CANCEL, id);
}参数
| 名称 | 类型 | 必填 | 描述 |
orderType | number | 是 |
|
price | number | 是 |
|
amount | number | 是 |
|
arg | string / number / bool / object / array / any (系统支持的所有类型) | 否 | 扩展参数,用于向该条日志输出附带信息, |
参考
备注
当orderType参数为LOG_TYPE_CANCEL时,price参数表示撤单的订单Id,用于在直接调用exchange.IO()函数撤单时打印撤单日志。exchange.Log()函数是exchange交易所对象的成员函数,需与全局函数Log区分。
Account
exchange.GetAccount
exchange.GetAccount()函数用于获取交易所账户信息。GetAccount()函数是交易所对象exchange的成员函数,exchange对象的成员函数(方法)的用途仅与exchange相关,后续文档不再赘述。
exchange.GetAccount()示例
获取当前账户信息。
javascript
function main(){
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while (!exchange.IO("status")) {
Sleep(1000)
}
// 获取账户资产信息,可以不用设置合约
var account = exchange.GetAccount()
Log("账户信息,Balance:", account.Balance, "FrozenBalance:", account.FrozenBalance, "Equity:", account.Equity, "UPnL:", account.UPnL)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
account = exchange.GetAccount()
Log("账户信息,Balance", account["Balance"], "FrozenBalance:", account["FrozenBalance"], "Equity:", account["Equity"], "UPnL:", account["UPnL"])
rust
fn main() {
// 鉴于测试代码,不使用商品期货策略一般架构,这里仅仅判断exchange.IO("status")函数,判断连接期货公司前置机成功后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
// 获取账户资产信息,可以不用设置合约
let account = exchange.GetAccount().unwrap();
Log!("账户信息,Balance:", account.Balance, "FrozenBalance:", account.FrozenBalance, "Equity:", account.Equity, "UPnL:", account.UPnL);
}
c++
void main() {
while (exchange.IO("status") == 0) {
Sleep(1000);
}
auto account = exchange.GetAccount();
Log("账户信息,Balance", account.Balance, "FrozenBalance:", account.FrozenBalance, "Equity:", account.Equity, "UPnL:", account.UPnL);
}返回值
| 类型 | 描述 |
| 用于查询账户资产信息,查询成功时返回 |
参考
exchange.GetName
exchange.GetName()函数用于获取当前交易所对象所绑定的交易所名称。
exchange.GetName()示例
javascript
function main() {
Log("判断交易所对象exchange为商品期货-CTP协议,判断结果为:", exchange.GetName() == "Futures_CTP")
}
python
def main():
Log("判断交易所对象exchange为商品期货-CTP协议,判断结果为:", exchange.GetName() == "Futures_CTP")
rust
fn main() {
Log!("判断交易所对象exchange为商品期货-CTP协议,判断结果为:", exchange.GetName() == "Futures_CTP");
}
c++
void main() {
Log("判断交易所对象exchange为商品期货-CTP协议,判断结果为:", exchange.GetName() == "Futures_CTP");
}返回值
| 类型 | 描述 |
string |
|
参考
备注
exchange.GetName()函数通常用于识别策略代码中的exchange、exchanges[1]、exchanges[2]等交易所对象。
-
股票证券
实盘:对于富途证券交易所对象,exchange.GetName()函数返回Futures_Futu;对于中泰XTP交易所对象,exchange.GetName()函数返回Futures_XTP。
回测系统:由于回测系统不区分协议,因此exchange.GetName()函数返回Futures_XTP。 -
商品期货
实盘:对于CTP协议的交易所对象,exchange.GetName()函数返回Futures_CTP;对于易盛协议的交易所对象,exchange.GetName()函数返回Futures_Esunny。
回测系统:由于回测系统不区分协议,因此exchange.GetName()函数返回Futures_CTP。
exchange.GetLabel
exchange.GetLabel()函数用于获取配置交易所对象时设置的自定义标签。
exchange.GetLabel()示例
javascript
function main() {
Log("exchange label:", exchange.GetLabel())
}
python
def main():
Log("exchange label:", exchange.GetLabel())
rust
fn main() {
Log!("exchange label:", exchange.GetLabel());
}
c++
void main() {
Log("exchange label:", exchange.GetLabel());
}返回值
| 类型 | 描述 |
string |
|
参考
备注
可通过设置的标签来识别策略代码中的exchange或exchanges[1]、exchanges[2]等交易所对象。
exchange.GetCurrency
exchange.GetCurrency()函数用于获取当前已设置的交易对。
exchange.GetCurrency()示例
javascript
function main() {
Log("exchange 当前交易对为:", exchange.GetCurrency())
}
python
def main():
Log("exchange 当前交易对为:", exchange.GetCurrency())
rust
fn main() {
Log!("exchange 当前交易对为:", exchange.GetCurrency());
}
c++
void main() {
Log("exchange 当前交易对为:", exchange.GetCurrency());
}返回值
| 类型 | 描述 |
string |
|
参考
备注
对于商品期货、股票证券等品种,该函数返回固定的字符串:
-
股票证券
实盘:当交易所对象为富途证券时,exchange.GetCurrency()函数返回STOCK。
回测系统:exchange.GetCurrency()函数返回STOCK_CNY。 -
商品期货
实盘:exchange.GetCurrency()函数返回FUTURES。
回测系统:exchange.GetCurrency()函数返回FUTURES_CNY。
Futures
exchange.GetPositions
exchange.GetPositions()函数用于获取所有合约的当前持仓信息。GetPositions()函数是交易所对象exchange的成员函数。
GetPositions()函数获取交易所对象exchange所绑定的交易所账户的持仓信息。exchange对象的成员函数(方法)的用途仅与exchange相关,文档之后不再赘述。
exchange.GetPositions()
exchange.GetPositions(symbol)示例
javascript
/*
注意:GetPositions 函数获取的是所有持仓品种的持仓信息,如果没有持仓则返回空数组,因此在使用该接口返回的数据前,需先判断返回的数据是否为空数组
*/
function main(){
// 由于是测试代码,不使用商品期货策略的一般架构,这里仅判断 exchange.IO("status") 函数,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
var info = exchange.SetContractType("rb888")
var ticker = exchange.GetTicker()
exchange.SetDirection("buy")
exchange.Buy(ticker.Last + info.PriceTick * 20, 2)
var position = exchange.GetPositions()
if(position.length>0){
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,
"ContractType:", position[0].ContractType, "Symbol:", position[0].Symbol)
}
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
info = exchange.SetContractType("rb888")
ticker = exchange.GetTicker()
exchange.SetDirection("buy")
exchange.Buy(ticker["Last"] + info["PriceTick"] * 20, 2)
position = exchange.GetPositions()
if len(position) > 0:
Log("Amount:", position[0]["Amount"], "FrozenAmount:", position[0]["FrozenAmount"], "Price:",
position[0]["Price"], "Profit:", position[0]["Profit"], "Type:", position[0]["Type"],
"ContractType:", position[0]["ContractType"], "Symbol:", position[0]["Symbol"])
rust
fn main() {
// 由于是测试代码,不使用商品期货策略的一般架构,这里仅判断 exchange.IO("status") 函数,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用 exchange.IO("status") 判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
let info = JSONParse(&exchange.SetContractType("rb888").unwrap()).unwrap();
let ticker = exchange.GetTicker(None).unwrap();
// 注意:Rust 中不推荐使用 SetDirection,优先使用 CreateOrder 直接指定方向
exchange.SetDirection("buy").unwrap();
exchange.Buy(ticker.Last + info["PriceTick"].as_f64().unwrap_or(0.0) * 20.0, 2).unwrap();
let position = exchange.GetPositions(None).unwrap();
if position.len() > 0 {
Log!("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,
"ContractType:", position[0].ContractType, "Symbol:", position[0].Symbol);
}
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
auto info = exchange.SetContractType("rb888");
auto ticker = exchange.GetTicker();
exchange.SetDirection("buy");
exchange.Buy(ticker.Last + info["PriceTick"].get<double>() * 20, 2);
auto position = exchange.GetPositions();
if(position.size() > 0) {
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,
"ContractType:", position[0].ContractType, "Symbol:", position[0].Symbol);
}
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 否 | 参数 |
参考
备注
商品期货的持仓需要注意以下几点:
- 回测系统
回测系统不区分今仓、昨仓。GetPositions函数返回的持仓数据Position结构数组中,Position结构的Type属性仅为PD_LONG或者PD_SHORT。 - 实盘
有些交易所区分今仓、昨仓,例如上期所。
有些交易所虽然也区分,但是不能指定平今仓还是平昨仓,存在今仓时优先平今仓。例如IF等一些品种只能先平今仓,因此今仓、昨仓的仓位信息合并为一个并且不予区分。
兼容exchange.GetPosition()调用。
exchange.GetPositions()函数不依赖于当前设置的合约代码。不传symbol参数时获取所有合约的当前持仓信息;传入symbol参数时获取指定合约的持仓信息。
exchange.SetMarginLevel
exchange.SetMarginLevel()函数用于设置exchange交易所对象当前交易对或合约的杠杆倍数。商品期货和股票证券不支持此功能。
exchange.SetMarginLevel(marginLevel)参数
| 名称 | 类型 | 必填 | 描述 |
marginLevel | number | 是 |
|
参考
exchange.SetDirection
exchange.SetDirection()函数用于设置exchange.Buy函数、exchange.Sell函数在进行期货合约下单时的订单方向。
exchange.SetDirection(direction)
exchange.SetDirection(direction, type)示例
javascript
function main(){
// 鉴于此为测试代码,未采用商品期货策略的一般架构,这里仅通过exchange.IO("status")函数判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
// 举例设置为螺纹钢主力合约
exchange.SetContractType("rb888")
// 设置下单类型为做多
exchange.SetDirection("buy")
// 以10000的价格,合约数量为2张下单。注意,这里的下单价格仅为举例,具体测试时可自行设置、改动
exchange.Buy(10000, 2)
// 设置下单类型为平多
exchange.SetDirection("closebuy")
exchange.Sell(1000, 2)
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
exchange.SetContractType("rb888")
exchange.SetDirection("buy")
exchange.Buy(10000, 2)
exchange.SetDirection("closebuy")
exchange.Sell(1000, 2)
rust
fn main() {
// 鉴于此为测试代码,未采用商品期货策略的一般架构,这里仅通过exchange.IO("status")函数判断,在成功连接期货公司前置机后立即执行测试代码。股票证券无需使用exchange.IO("status")判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
// 举例设置为螺纹钢主力合约
exchange.SetContractType("rb888").unwrap();
// 设置下单类型为做多。注意:Rust 中 SetDirection 不推荐使用,优先使用 CreateOrder 直接指定 side("buy"/"sell"/"closebuy"/"closesell"),无需先 SetDirection
exchange.SetDirection("buy").unwrap();
// 以10000的价格,合约数量为2张下单。注意,这里的下单价格仅为举例,具体测试时可自行设置、改动
exchange.Buy(10000, 2).unwrap();
// 设置下单类型为平多
exchange.SetDirection("closebuy").unwrap();
exchange.Sell(1000, 2).unwrap();
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
exchange.SetContractType("rb888");
exchange.SetDirection("buy");
exchange.Buy(10000, 2);
exchange.SetDirection("closebuy");
exchange.Sell(1000, 2);
}参数
| 名称 | 类型 | 必填 | 描述 |
direction | string | 是 |
|
type | string | 否 | 对于采用CTP协议的传统期货,可将第二个参数 |
参考
备注
exchange.SetDirection()函数设置了期货合约交易方向与下单函数之间的对应关系:
| 下单函数 | SetDirection函数的参数设置的方向 | 备注 |
|---|---|---|
| exchange.Buy | "buy" | 买入开多仓 |
| exchange.Buy | "closesell" | 买入平空仓 |
| exchange.Buy | "closesell_today" | 买入平空仓(今仓) |
| exchange.Sell | "sell" | 卖出开空仓 |
| exchange.Sell | "closebuy" | 卖出平多仓 |
| exchange.Sell | "closebuy_today" | 卖出平多仓(今仓) |
exchange.SetContractType
exchange.SetContractType()函数用于设置exchange交易所对象当前的合约代码。
期货支持传统商品期货的CTP协议与易盛协议。在进行任何操作之前,需要先使用exchange.SetContractType()函数设置合约代码。
exchange.SetContractType(symbol)示例
-
使用
exchange.SetContractType()函数设置(订阅)合约。javascriptfunction main(){ while(true) { if (exchange.IO("status")) { var ret = exchange.SetContractType("MA888") Log("订阅合约的详细信息:", ret) break } else { LogStatus(_D(), "未连接") } } }pythondef main(): while True: if exchange.IO("status"): ret = exchange.SetContractType("MA888") Log("订阅合约的详细信息:", ret) break else: LogStatus(_D(), "未连接")rustfn main() { loop { if exchange.IO("status").unwrap_or_default() == "true" { let ret = exchange.SetContractType("MA888"); Log!("订阅合约的详细信息:", ret); break; } else { LogStatus!(_D(None), "未连接"); } } }c++void main() { while(true) { if(exchange.IO("status") == 1) { auto ret = exchange.SetContractType("MA888"); Log("订阅合约的详细信息:", ret); break; } else { LogStatus(_D(), "未连接"); } } } -
商品期货仅在回测中支持虚拟合约交易;在实盘交易中,虚拟合约只能用于获取行情数据。实盘时,我们可以使用虚拟合约所映射的真实合约进行下单,示例代码如下:
javascriptfunction main(){ var n = 0 while(true){ // 需要在判断exchange.IO("status")函数返回true,即为真值时才可调用行情、交易等函数 if(exchange.IO("status")){ // 设置合约为虚拟合约,MA888,即甲醇主力合约 var ret = _C(exchange.SetContractType, "MA888") var ticker = exchange.GetTicker() // 当到达交易条件时 if(n == 100) { exchange.SetContractType(ret.InstrumentID) Log("设置映射的实际合约:", ret.InstrumentID) exchange.SetDirection("buy") var id = exchange.Buy(ticker.Buy - 10, 1) Log("id:", id) Sleep(1000) Log(exchange.GetOrder(id)) Sleep(1000) Log(exchange.GetPositions()) Sleep(1000) exchange.CancelOrder(id) Sleep(1000) Log(exchange.GetOrders()) } n++ LogStatus(_D(), "已经连接CTP !") } else { LogStatus(_D(), "未连接CTP !") } } }pythondef main(): n = 0 while True: if exchange.IO("status"): ret = _C(exchange.SetContractType, "MA888") ticker = exchange.GetTicker() if n == 100: exchange.SetContractType(ret["InstrumentID"]) Log("设置映射的实际合约:", ret["InstrumentID"]) exchange.SetDirection("buy") id = exchange.Buy(ticker["Buy"] - 10, 1) Log("id:", id) Sleep(1000) Log(exchange.GetOrder(id)) Sleep(1000) Log(exchange.GetPositions()) Sleep(1000) exchange.CancelOrder(id) Sleep(1000) Log(exchange.GetOrders()) n += 1 LogStatus(_D(), "已经连接CTP !") else: LogStatus(_D(), "未连接CTP !")rustfn main() { let mut n = 0; loop { // 需要在判断exchange.IO("status")函数返回true,即为真值时才可调用行情、交易等函数 if exchange.IO("status").unwrap_or_default() == "true" { // 设置合约为虚拟合约,MA888,即甲醇主力合约 let ret = JSONParse(&_C!(exchange.SetContractType("MA888"))).unwrap(); let ticker = exchange.GetTicker(None).unwrap(); // 当到达交易条件时 if n == 100 { let instrument_id = ret["InstrumentID"].as_str().unwrap_or(""); exchange.SetContractType(instrument_id).unwrap(); Log!("设置映射的实际合约:", instrument_id); // 注意:Rust 中 SetDirection 不推荐使用,优先使用 CreateOrder 直接指定方向 exchange.SetDirection("buy").unwrap(); let id = exchange.Buy(ticker.Buy - 10.0, 1).unwrap(); Log!("id:", id); Sleep(1000); Log!(exchange.GetOrder(&id)); Sleep(1000); Log!(exchange.GetPositions(None)); Sleep(1000); exchange.CancelOrder(&id).unwrap(); Sleep(1000); Log!(exchange.GetOrders(None)); } n += 1; LogStatus!(_D(None), "已经连接CTP !"); } else { LogStatus!(_D(None), "未连接CTP !"); } } }c++void main() { int n = 0; while(true) { if(exchange.IO("status") == 1) { auto ret = exchange.SetContractType("MA888"); auto ticker = exchange.GetTicker(); if(n == 100) { exchange.SetContractType(ret["InstrumentID"]); Log("设置映射的实际合约:", ret["InstrumentID"]); exchange.SetDirection("buy"); auto id = exchange.Buy(ticker.Buy - 10, 1); Log("id:", id); Sleep(1000); Log(exchange.GetOrder(id)); Sleep(1000); Log(exchange.GetPositions()); Sleep(1000); exchange.CancelOrder(id); Sleep(1000); Log(exchange.GetOrders()); } n++; LogStatus(_D(), "已经连接CTP !"); } else { LogStatus(_D(), "未连接CTP !"); } } }
返回值
| 类型 | 描述 |
object |
打印
|
参数
| 名称 | 类型 | 必填 | 描述 |
symbol | string | 是 | 例如: 主力连续合约的代码为 |
参考
备注
- 主力连续合约(例如rb888):
由该期货品种不同时期的主力合约(价格和成交量)直接拼接而成,代码以888结尾,例如rb888。合约首次上市时,以当日收盘时同品种持仓量最大者作为下一交易日起的主力合约。若同品种其他合约在收盘后持仓量超过当前主力合约的1.1倍,则在下一交易日进行主力合约切换。 - 次主力连续合约(例如rb889):
由该期货品种不同时期的次主力合约直接拼接而成,代码以889结尾,例如rb889。次主力合约为同品种中持仓量排名第二的合约。 - 指数合约(例如rb000):
由该期货品种所有正在交易的合约,按持仓量加权平均计算。
在商品期货策略中调用exchange.SetContractType(ContractType)函数时,无论是实盘还是simnow模拟盘,都可能出现订阅失败的情况,例如连接期货公司前置机失败,或设置了不存在的合约代码。虚拟合约订阅成功后,返回字段中的InstrumentID即为主力合约(会在订阅的同时获取),便于策略在实盘下单交易时进行合约映射。
对于不熟悉商品期货合约代码的用户,可以使用如下JavaScript语言的代码进行查询:
javascript
function main(){
while(true){
if(exchange.IO("status")){
var products_CZCE_Tbl = {
"type" : "table",
"title" : "郑商所 CZCE",
"cols" : ["商品名称(ProductName)", "合约代码短名(ProductID)" , "一跳价格(PriceTick)", "一手合约乘数(VolumeMultiple)", "交易所代码(ExchangeID)"],
"rows" : []
}
var products_DCE_Tbl = {
"type" : "table",
"title" : "大商所 DCE",
"cols" : ["商品名称(ProductName)", "合约代码短名(ProductID)" , "一跳价格(PriceTick)", "一手合约乘数(VolumeMultiple)", "交易所代码(ExchangeID)"],
"rows" : []
}
var products_SHFE_Tbl = {
"type" : "table",
"title" : "上期所 SHFE",
"cols" : ["商品名称(ProductName)", "合约代码短名(ProductID)" , "一跳价格(PriceTick)", "一手合约乘数(VolumeMultiple)", "交易所代码(ExchangeID)"],
"rows" : []
}
var products_other_Tbl = {
"type" : "table",
"title" : "其它",
"cols" : ["商品名称(ProductName)", "合约代码短名(ProductID)" , "一跳价格(PriceTick)", "一手合约乘数(VolumeMultiple)", "交易所代码(ExchangeID)"],
"rows" : []
}
exchange.IO("products").forEach(function(product) {
if (product.ExchangeID == "CZCE") {
products_CZCE_Tbl.rows.push([product.ProductName, product.ProductID, product.PriceTick, product.VolumeMultiple, product.ExchangeID])
} else if (product.ExchangeID == "DCE") {
products_DCE_Tbl.rows.push([product.ProductName, product.ProductID, product.PriceTick, product.VolumeMultiple, product.ExchangeID])
} else if (product.ExchangeID == "SHFE") {
products_SHFE_Tbl.rows.push([product.ProductName, product.ProductID, product.PriceTick, product.VolumeMultiple, product.ExchangeID])
} else {
products_other_Tbl.rows.push([product.ProductName, product.ProductID, product.PriceTick, product.VolumeMultiple, product.ExchangeID])
}
})
LogStatus(_D(), "已经连接CTP", "\n`" + JSON.stringify([products_CZCE_Tbl, products_DCE_Tbl, products_SHFE_Tbl, products_other_Tbl]) + "`")
Sleep(1000 * 60 * 5)
} else {
LogStatus(_D(), "未连接CTP !")
}
Sleep(1000)
}
}
查询结果将显示各个交易所的合约信息。
商品期货合约的命名规则如下:
前面的字母代表品种名称(合约代码短名),后面的数字代表合约到期日。
| 交易所 | 合约命名规则 |
|---|---|
| 上期 / 能源所: | 小写 + 4个数字 |
| 大商所: | 小写 + 4个数字 |
| 中金所: | 大写 + 4个数字 |
| 郑商所: | 大写 + 3个数字 |
exchange.GetContractType
exchange.GetContractType()函数用于获取exchange交易所对象当前设置的合约代码。
exchange.GetContractType()示例
javascript
function main () {
// 鉴于此为测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断,在确认成功连接期货公司前置机后立即执行测试代码。股票证券交易无需使用 exchange.IO("status") 判断连接状态
while(!exchange.IO("status")) {
Sleep(1000)
}
Log(exchange.SetContractType("rb888"))
Log(exchange.GetContractType())
}
python
def main():
while not exchange.IO("status"):
Sleep(1000)
Log(exchange.SetContractType("rb888"))
Log(exchange.GetContractType())
rust
fn main() {
// 鉴于此为测试代码,未采用商品期货策略的通用架构,这里仅通过 exchange.IO("status") 函数判断,在确认成功连接期货公司前置机后立即执行测试代码。股票证券交易无需使用 exchange.IO("status") 判断连接状态
while exchange.IO("status").unwrap_or_default() != "true" {
Sleep(1000);
}
Log!(exchange.SetContractType("rb888"));
Log!(exchange.GetContractType());
}
c++
void main() {
while(exchange.IO("status") == 0) {
Sleep(1000);
}
Log(exchange.SetContractType("rb888"));
Log(exchange.GetContractType());
}返回值
| 类型 | 描述 |
string |
|
参考
Threads
优宽量化交易平台从系统底层真正支持JavaScript语言策略的多线程功能,实现了以下对象:
| 对象 | 说明 | 备注 |
|---|---|---|
| threading | 多线程全局对象 | 成员函数:Thread、getThread、mainThread等。 |
| Thread | 线程对象 | 成员函数:peekMessage、postMessage、join等。 |
| ThreadLock | 线程锁对象 | 成员函数:acquire、release。可作为线程执行函数的参数传入线程环境。 |
| ThreadEvent | 事件对象 | 成员函数:set、clear、wait、isSet。可作为线程执行函数的参数传入线程环境。 |
| ThreadCondition | 条件对象 | 成员函数:notify、notifyAll、wait、acquire、release。可作为线程执行函数的参数传入线程环境。 |
| ThreadDict | 字典对象 | 成员函数:get、set。可作为线程执行函数的参数传入线程环境。 |
threading
threading对象作为全局多线程管理工具,提供了创建并发线程、线程锁、条件对象等功能。本章节介绍threading对象的成员函数。仅JavaScript语言策略支持该对象。
Thread
Thread()函数用于创建并发线程。
Thread(func, ...args)
Thread(...items)示例
-
同时创建一个自定义函数和一个匿名函数的并发线程。
javascriptfunction test1(a, b, c) { Log("test1:", a, b, c) } function main() { var t1 = threading.Thread(test1, 1, 2, 3) var t2 = threading.Thread(function (msg) { Log("msg:", msg) }, "Hello thread2") t1.join() t2.join() } -
使用
Thread(...items)形式创建并发线程,按顺序执行多个函数。javascriptfunction test1(msg) { Log("msg:", msg) test2("Hello test2") } function main() { var t1 = threading.Thread( [function(a, b, c) {Log(a, b, c)}, 1, 2, 3], [test1, "Hello test1"], [`function test2(msg) {Log("msg:", msg)}`]) t1.join() } -
支持向并发执行函数的参数中传入函数。
javascriptfunction testFunc1(p) { Log("testFunc1 p:", p) } function main() { threading.Thread(function(pfn) { var threadName = threading.currentThread().name() var threadId = threading.currentThread().id() pfn(`in thread threadName: ${threadName}, threadId: ${threadId}`) }, testFunc1).join() } -
支持传入函数字符串,可动态导入外部库进行并发计算。
javascriptfunction ml(input) { const net = new brain.NeuralNetwork() net.train([ { input: [0, 0], output: [0] }, { input: [0, 1], output: [1] }, { input: [1, 0], output: [1] }, { input: [1, 1], output: [0] }, ]) return net.run(input) } function main() { var ret = threading.Thread([ml, [1, 0]], [HttpQuery("https://unpkg.com/brain.js")]).join() // ret: {"id":1,"terminated":false,"elapsed":337636000,"ret":{"0":0.9339330196380615}} Log(ret) }
返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
func | function | 是 | 参数 |
arg | string / number / bool / object / array / function / any (系统支持的所有类型) | 否 | 参数 |
item | array | 是 | 参数 |
参考
备注
传入Thread()函数用于并发执行的线程函数func运行在隔离环境中,因此无法直接引用线程外部的变量,引用时会导致编译失败。同时,线程内不支持引用其他闭包函数。线程内部可以调用平台提供的所有API,但不能调用用户自定义的其他函数。
当线程执行完毕且没有被持续引用时,系统底层会自动回收线程相关的资源,无需显式调用join()函数来释放资源。如果存在持续引用导致无法释放资源,当并发数量超过2000个时会报错:InternalError: too many routine wait, max is 2000。
支持回测系统、实盘环境。所有并发线程相关的函数在回测系统中仅作为代码兼容性支持,实际不会真正执行并发线程,本章不再赘述。
getThread
getThread()函数用于根据指定的线程ID获取线程对象。
getThread(threadId)示例
通过threadId获取指定的线程对象。
javascript
function main() {
var t1 = threading.Thread(function () {
// Thread 对象有方法:id(),用于获取线程的Id,可以查看文档对应Thread对象的章节
var id = threading.currentThread().id()
var thread1 = threading.getThread(id)
Log("id:", id, ", thread1.id():", thread1.id())
Log(`id == thread1.id():`, id == thread1.id())
})
t1.join()
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
threadId | number | 是 | 参数 |
参考
备注
支持回测系统、实盘环境。
如果目标线程已经执行完毕并被释放,则无法通过threading.getThread(threadId)获取该线程的线程对象。
mainThread
mainThread()函数用于获取主线程的线程对象,即策略中main()函数所在的线程。
mainThread()示例
-
获取主线程的
Thread对象,输出主线程的threadId。javascriptfunction main() { Log("主线程的threadId:", threading.mainThread().id()) } -
在并发线程中获取主线程的线程对象。
javascriptfunction test() { Log("test函数中输出主线程Id:", threading.mainThread().id()) } function main() { var t1 = threading.Thread(test) t1.join() }
返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
currentThread
currentThread()函数用于获取当前线程的线程对象。
currentThread()示例
获取当前线程的Thread对象,输出当前线程的threadId。
javascript
function test() {
Log("当前线程的Id:", threading.currentThread().id())
}
function main() {
var t1 = threading.Thread(test)
t1.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Lock
Lock()函数用于创建线程锁对象。
Lock()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, lock) {
for (var i = 0; i < productionQuantity; i++) {
lock.acquire()
var count = dict.get("count")
Log("consumer:", count)
Sleep(1000)
lock.release()
}
}
function producer(productionQuantity, dict, lock) {
for (var i = 0; i < productionQuantity; i++) {
lock.acquire()
dict.set("count", i)
Log("producer:", i)
Sleep(1000)
lock.release()
}
}
function main() {
var dict = threading.Dict()
dict.set("count", -1)
var lock = threading.Lock()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, lock)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, lock)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Condition
Condition()函数用于创建条件变量对象,该对象在多线程并发环境中实现线程间的同步与通信。通过Condition(),线程可以在特定条件未满足时进入等待状态,直到其他线程发出条件满足的通知。
Condition()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, condition) {
for (var i = 0; i < productionQuantity; i++) {
condition.acquire()
while (dict.get("array").length == 0) {
condition.wait()
}
var arr = dict.get("array")
var count = arr.shift()
dict.set("array", arr)
Log("consumer:", count, ", array:", arr)
condition.release()
Sleep(1000)
}
}
function producer(productionQuantity, dict, condition) {
for (var i = 0; i < productionQuantity; i++) {
condition.acquire()
var arr = dict.get("array")
arr.push(i)
dict.set("array", arr)
Log("producer:", i, ", array:", arr)
condition.notify()
condition.release()
Sleep(1000)
}
}
function main() {
var dict = threading.Dict()
dict.set("array", [])
var condition = threading.Condition()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, condition)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, condition)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
回测系统暂不支持此功能,仅提供接口定义。
Event
Event()函数用于创建一个线程事件对象,该对象用于线程间的同步,允许一个线程等待另一个线程的通知或信号。
Event()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, pEvent, cEvent) {
for (var i = 0; i < productionQuantity; i++) {
while (dict.get("array").length == 0) {
pEvent.wait()
}
if (pEvent.isSet()) {
pEvent.clear()
}
var arr = dict.get("array")
var count = arr.shift()
dict.set("array", arr)
Log("consumer:", count, ", array:", arr)
cEvent.set()
Sleep(1000)
}
}
function producer(productionQuantity, dict, pEvent, cEvent) {
for (var i = 0; i < productionQuantity; i++) {
while (dict.get("array").length != 0) {
cEvent.wait()
}
if (cEvent.isSet()) {
cEvent.clear()
}
var arr = dict.get("array")
arr.push(i)
dict.set("array", arr)
Log("producer:", i, ", array:", arr)
pEvent.set()
Sleep(1000)
}
}
function main() {
var dict = threading.Dict()
dict.set("array", [])
var pEvent = threading.Event()
var cEvent = threading.Event()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, pEvent, cEvent)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, pEvent, cEvent)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Dict
Dict()函数用于创建一个字典对象,用于在并发线程间传递数据。
Dict()示例
-
向并发线程执行函数传入普通对象,测试修改对象键值后是否会影响其他线程中的对象键值。
javascriptfunction threadFun1(obj) { obj["age"] = 100 while (true) { Log("threadFun1 obj:", obj) Sleep(5000) } } function threadFun2(obj) { while (true) { Log("threadFun2 obj:", obj) Sleep(5000) } } function main() { var obj = {"age": 10} var t1 = threading.Thread(threadFun1, obj) var t2 = threading.Thread(threadFun2, obj) t1.join() t2.join() } -
向并发线程执行函数传入
Dict()函数创建的ThreadDict对象,测试修改对象键值后是否会影响其他线程中的对象键值。javascriptfunction threadFun1(threadDict) { threadDict.set("age", 100) while (true) { Log(`threadFun1 threadDict.get("age"):`, threadDict.get("age")) Sleep(5000) } } function threadFun2(threadDict) { while (true) { Log(`threadFun2 threadDict.get("age"):`, threadDict.get("age")) Sleep(5000) } } function main() { var threadDict = threading.Dict() threadDict.set("age", 10) var t1 = threading.Thread(threadFun1, threadDict) var t2 = threading.Thread(threadFun2, threadDict) t1.join() t2.join() }
返回值
| 类型 | 描述 |
|
|
参考
备注
向并发线程函数传入普通对象时采用深拷贝方式传递,在并发线程中修改键值不会影响其他线程中的字典。
支持回测系统、实盘环境。
pending
pending函数用于获取当前策略程序中正在运行的并发线程数量。
pending()示例
创建两个并发运行的线程,并在不同时间点调用pending()函数。
javascript
function threadFun1() {
Log("threadFun1")
Sleep(3000)
}
function threadFun2() {
for (var i = 0; i < 3; i++) {
LogStatus(_D(), "print from threadFun2")
Sleep(3000)
}
}
function main() {
Log(`begin -- threading.pending():`, threading.pending())
var t1 = threading.Thread(threadFun1)
var t2 = threading.Thread(threadFun2)
Log(`after threading.Thread -- threading.pending():`, threading.pending())
t1.join()
t2.join()
Log(`after thread.join -- threading.pending():`, threading.pending())
}返回值
| 类型 | 描述 |
number |
|
参考
备注
当策略main()函数开始运行时直接调用pending()函数将返回1,这是因为策略main()函数所在的主线程本身也被计入正在运行的线程中。
支持回测系统和实盘环境。
Thread
Thread对象可以通过threading.Thread()、threading.getThread()、threading.mainThread()、threading.currentThread()创建或返回。
peekMessage
peekMessage()函数用于从线程接收消息。
peekMessage()
peekMessage(timeout)示例
并发线程向主线程发送消息。
javascript
function main() {
var t1 = threading.Thread(function() {
for (var i = 0; i < 10; i++) {
Log("thread1 postMessage():", i)
threading.mainThread().postMessage(i)
Sleep(500)
}
})
while (true) {
var msg = threading.currentThread().peekMessage()
Log("main peekMessage():", msg)
if (msg == 9) {
break
}
Sleep(1000)
}
t1.join()
}返回值
| 类型 | 描述 |
string / number / bool / object / array / any (系统支持的所有类型) |
|
参数
| 名称 | 类型 | 必填 | 描述 |
timeout | number | 否 | 参数 |
参考
备注
编写程序时需注意避免线程死锁问题。
postMessage
postMessage()函数用于向线程发送消息。
postMessage(msg)示例
-
在并发线程中发送消息,使用
eventLoop()接收消息通知。javascriptfunction main() { var t1 = threading.Thread(function() { for (var i = 0; i < 10; i++) { Log("thread1 postMessage():", i) threading.mainThread().postMessage(i) Sleep(500) } }) for (var i = 0; i < 10; i++) { var event = threading.mainThread().eventLoop() Log("main event:", event) Sleep(500) } t1.join() } -
支持发送函数。
javascriptfunction main() { threading.mainThread().postMessage(function(msg) { Log("func from mainThread, msg:", msg) }) threading.Thread(function() { var func = threading.mainThread().peekMessage() func("in " + threading.currentThread().name()) }).join() }
参数
| 名称 | 类型 | 必填 | 描述 |
msg | string / number / bool / object / array / function / any (系统支持的所有类型) | 是 | 参数 |
参考
备注
当线程的执行函数中调用postMessage()函数发送信号或数据时,会产生消息事件。可以使用eventLoop()函数接收消息通知。
join
join()函数用于等待线程退出并回收系统资源。
join()
join(timeout)示例
测试join()函数超时并输出返回值。
javascript
function main() {
var t1 = threading.Thread(function() {
Log("Hello thread1")
Sleep(5000)
})
var ret = t1.join(1000)
Log("ret:", ret) // ret: undefined
ret = t1.join()
Log("ret:", ret) // ret: {"id":1,"terminated":false,"elapsed":5003252000}
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
timeout | number | 否 |
|
参考
备注
join()函数超时时返回undefined。
terminate
terminate()函数用于强制终止线程,释放该线程占用的硬件资源。
terminate()示例
强制终止一个线程的执行。线程被强制终止后,日志中将不再输出该线程的内容。
javascript
function main() {
var t1 = threading.Thread(function() {
for (var i = 0; i < 10; i++) {
Log("thread1 i:", i)
Sleep(1000)
}
})
Sleep(3000)
t1.terminate()
Log("after t1.terminate()")
while (true) {
LogStatus(_D())
Sleep(1000)
}
}参考
备注
对于使用terminate()函数强制终止的线程,无法再使用join()函数等待其结束。
getData
getData()函数用于访问线程环境中记录的变量。数据在线程未执行join()函数(等待退出成功)且未执行terminate()函数(强制终止线程)的情况下有效。
getData()
getData(key)示例
在并发线程的环境中记录键名为count的值,然后在主线程中读取count的键值。
javascript
function main() {
var t1 = threading.Thread(function() {
for (var i = 0; i < 5; i++) {
threading.currentThread().setData("count", i)
Log(`setData("count"):`, i)
Sleep(1000)
}
})
for (var i = 0; i < 5; i++) {
var count = threading.getThread(t1.id()).getData("count")
Log(`getData("count"):`, count)
Sleep(1000)
}
t1.join()
}返回值
| 类型 | 描述 |
string / number / bool / object / array / any (系统支持的所有类型) |
|
参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 |
|
参考
setData
setData()函数用于在线程环境中存储变量。
setData(key, value)示例
-
在并发线程中设置键值对,在主线程中读取该键值对。
javascriptfunction main() { var t1 = threading.Thread(function() { threading.currentThread().setData("data", 100) }) Sleep(1000) Log(`t1.getData("data"):`, t1.getData("data")) t1.join() } -
支持将函数作为键值传入。
javascriptfunction main() { threading.mainThread().setData("func2", function(p) { Log("func2 p:", p) }) var t1 = threading.Thread(function() { threading.currentThread().setData("func1", function(p) { Log("func1 p:", p) }) var func2 = threading.mainThread().getData("func2") func2("test2") }) Sleep(1000) var func1 = t1.getData("func1") func1("test1") t1.join() }
参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 |
|
value | string / number / bool / object / array / function / any (系统支持的所有类型) | 是 |
|
参考
备注
数据在线程未执行join()函数(等待退出成功)且未执行terminate()函数(强制终止线程)的情况下有效。参数value的值必须是可序列化的变量。
id
id()函数用于返回当前多线程对象实例的threadId。
id()示例
创建一个并发线程,在主线程中输出该并发线程的threadId。
javascript
function main() {
var t1 = threading.Thread(function() {
threading.currentThread().setData("data", 100)
})
Log(`t1.id():`, t1.id())
t1.join()
}返回值
| 类型 | 描述 |
number |
|
参考
name
name()函数用于返回当前多线程对象实例的名称。
name()示例
创建一个并发运行的线程,在主线程中输出该并发线程的名称。
javascript
function main() {
var t1 = threading.Thread(function() {
threading.currentThread().setData("data", 100)
})
Log(`t1.name():`, t1.name()) // t1.name(): Thread-1
t1.join()
}返回值
| 类型 | 描述 |
string |
|
参考
eventLoop
eventLoop()函数用于监听线程接收到的事件。
eventLoop()
eventLoop(timeout)示例
并发执行3个线程,输出接收到的事件信息。超时或立即返回时输出空值。
javascript
function main() {
var t1 = threading.Thread(function() {
while (true) {
var eventMsg = threading.currentThread().eventLoop() // 阻塞等待
// 2024-11-14 10:14:18 thread1 eventMsg: {"Seq":1,"Event":"thread","ThreadId":0,"Index":1,"Queue":0,"Nano":1731550458699947000}
Log(_D(), "thread1 eventMsg:", eventMsg)
}
})
var t2 = threading.Thread(function() {
while (true) {
var eventMsg = threading.currentThread().eventLoop(-1) // 立即返回
Log(_D(), "thread2 eventMsg:", eventMsg)
Sleep(5000)
}
})
var t3 = threading.Thread(function() {
while (true) {
var eventMsg = threading.currentThread().eventLoop(3000) // 设置3秒超时
Log(_D(), "thread3 eventMsg:", eventMsg)
}
})
t1.postMessage("Hello ", t1.name())
t2.postMessage("Hello ", t2.name())
t3.postMessage("Hello ", t3.name())
t1.join()
t2.join()
t3.join()
}返回值
| 类型 | 描述 |
object / 空值 |
|
参数
| 名称 | 类型 | 必填 | 描述 |
timeout | number | 否 | 参数 |
参考
备注
eventLoop()函数的处理机制与全局函数EventLoop()一致。
ThreadLock
线程锁对象,用于多线程同步处理。
acquire
acquire()函数用于请求线程锁(加锁)。
acquire()示例
示例请参考threading.Lock()章节的内容。
参考
备注
acquire()函数用于请求线程锁。当线程调用某个线程锁对象的acquire()函数时,它会尝试获取该锁。如果锁当前未被其他线程占用,调用线程将成功获得锁并继续执行。如果锁已被其他线程持有,调用acquire()的线程将被阻塞,直到锁被释放。
release
release()函数用于释放线程锁(解锁)。
release()示例
测试死锁场景
javascript
function consumer(productionQuantity, dict, pLock, cLock) {
for (var i = 0; i < productionQuantity; i++) {
pLock.acquire()
cLock.acquire()
var arr = dict.get("array")
var count = arr.shift()
dict.set("array", arr)
Log("consumer:", count, ", array:", arr)
cLock.release()
Sleep(1000)
pLock.release()
}
}
function producer(productionQuantity, dict, pLock, cLock) {
for (var i = 0; i < productionQuantity; i++) {
cLock.acquire() // cLock.acquire() 放在 pLock.acquire() 后不会产生死锁
pLock.acquire()
var arr = dict.get("array")
arr.push(i)
dict.set("array", arr)
Log("producer:", i, ", array:", arr)
pLock.release()
Sleep(1000)
cLock.release()
}
}
function main() {
var dict = threading.Dict()
dict.set("array", [])
var pLock = threading.Lock()
var cLock = threading.Lock()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, pLock, cLock)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, pLock, cLock)
consumerThread.join()
producerThread.join()
}参考
备注
需要注意,线程锁使用不当可能导致死锁。
ThreadEvent
事件对象,用于多线程间的事件通知和信号传递。
set
set()函数用于触发事件(设置信号)。
set()示例
请参考threading.Event()章节中的示例。
参考
备注
如果信号已经通过set()设置,则不能重复设置,需要先清除信号后才能重新设置。
wait
wait()函数用于设置事件(信号)等待,在事件(信号)被设置之前会阻塞;支持设置超时参数。
wait()
wait(timeout)示例
测试wait()函数的返回值。
javascript
function main() {
var event = threading.Event()
var t1 = threading.Thread(function(event) {
var ret = event.wait(100)
Log(`event.wait(100):`, ret)
ret = event.wait()
Log(`event.wait():`, ret)
}, event)
Sleep(1000)
event.set()
t1.join()
}返回值
| 类型 | 描述 |
bool |
|
参数
| 名称 | 类型 | 必填 | 描述 |
timeout | number | 否 | 参数 |
参考
ThreadCondition
条件变量对象,用于实现多线程间的同步与通信。
notify
notify()函数用于唤醒一个正在等待的线程(如果存在)。只有调用了wait()方法的线程才能被唤醒。
notify()示例
使用notify()函数唤醒等待中的线程。
javascript
function consumer(dict, condition) {
while (true) {
condition.acquire()
while (dict.get("array").length == 0) {
Log(threading.currentThread().name(), "wait()...", ", array:", dict.get("array"))
condition.wait()
}
var arr = dict.get("array")
var num = arr.shift()
Log(threading.currentThread().name(), ", num:", num, ", array:", arr, "#FF0000")
dict.set("array", arr)
Sleep(1000)
condition.release()
}
}
function main() {
var condition = threading.Condition()
var dict = threading.Dict()
dict.set("array", [])
var t1 = threading.Thread(consumer, dict, condition)
var t2 = threading.Thread(consumer, dict, condition)
var t3 = threading.Thread(consumer, dict, condition)
Sleep(1000)
var i = 0
while (true) {
condition.acquire()
var msg = ""
var arr = dict.get("array")
var randomNum = Math.floor(Math.random() * 5) + 1
if (arr.length >= 3) {
condition.notifyAll()
msg = "notifyAll"
} else {
arr.push(i)
dict.set("array", arr)
if (randomNum > 3 && arr.length > 0) {
condition.notify()
msg = "notify"
} else {
msg = "pass"
}
i++
}
Log(_D(), "randomNum:", randomNum, ", array:", arr, ", msg:", msg)
condition.release()
Sleep(1000)
}
}参考
备注
notify()函数会唤醒等待队列中的一个线程。
notify()函数唤醒线程时,该线程会重新获取线程锁。
notifyAll
notifyAll()函数用于唤醒所有正在等待的线程。
notifyAll()示例
示例请参考ThreadCondition.notify()章节的内容。
参考
备注
notifyAll()函数会逐个唤醒所有处于等待状态的线程,被唤醒的线程将重新尝试获取线程锁。
wait
wait()函数用于在特定条件下使线程进入等待状态。
wait()示例
示例请参考ThreadCondition.notify()章节的内容。
参考
备注
wait()函数会释放线程锁,当线程被唤醒时会重新获取线程锁。
ThreadDict
线程安全的字典对象,用于在多线程环境中进行数据共享。
get
get()函数用于获取字典对象中记录的键值。
get(key)示例
使用事件对象通知线程读取和修改数据。
javascript
function main() {
var event = threading.Event()
var dict = threading.Dict()
dict.set("data", 100)
var t1 = threading.Thread(function(dict, event) {
Log(`thread1, dict.get("data"):`, dict.get("data"))
event.set()
event.clear()
event.wait()
Log(`after main change data, thread1 dict.get("data"):`, dict.get("data"))
dict.set("data", 0)
}, dict, event)
event.wait()
dict.set("data", 99)
event.set()
event.clear()
t1.join()
Log(`main thread, dict.get("data"):`, dict.get("data"))
}返回值
| 类型 | 描述 |
string / number / bool / object / array / any (系统支持的所有类型) |
|
参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 | 参数 |
参考
set
set()函数用于设置键值对。
set(key, value)示例
支持将函数作为键值传入。
javascript
function main() {
var dict1 = threading.Dict()
dict1.set("func1", function(p) {
Log("func1 p:", p)
})
threading.Thread(function(dict1) {
var func1 = dict1.get("func1")
func1("test")
}, dict1).join()
}参数
| 名称 | 类型 | 必填 | 描述 |
key | string | 是 | 参数 |
value | string / number / bool / object / array / function / any (系统支持的所有类型) | 是 | 参数 |
参考
TA
TA.MACD
TA.MACD()函数用于计算指数平滑异同移动平均线(MACD)指标。
TA.MACD(inReal)
TA.MACD(inReal, optInFastPeriod, optInSlowPeriod, optInSignalPeriod)示例
测试TA.MACD()函数:
javascript
function main(){
// 可以填入不同k线周期,比如PERIOD_M1,PERIOD_M30,PERIOD_H1......
var records = exchange.GetRecords(PERIOD_M15)
var macd = TA.MACD(records, 12, 26, 9)
// 观看日志可得知返回三个数组,分别对应DIF,DEA,MACD
Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
}
python
def main():
r = exchange.GetRecords(PERIOD_M15)
macd = TA.MACD(r, 12, 26, 9)
Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
rust
fn main() {
// 可以填入不同k线周期,比如PERIOD_M1,PERIOD_M30,PERIOD_H1......
let records = exchange.GetRecords(None, PERIOD_M15, None).unwrap();
let macd = TA.MACD(&records, 12, 26, 9);
// 观看日志可得知返回三个数组,分别对应DIF,DEA,MACD
Log!("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2]);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M15);
auto macd = TA.MACD(r, 12, 26, 9);
Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2]);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInSlowPeriod | number | 否 |
|
optInSignalPeriod | number | 否 |
|
参考
备注
优宽量化的TA指标库对常用指标算法进行了优化,支持JavaScript、Python、C++语言策略调用,详见开源TA库代码。
TA.MACD()函数的optInFastPeriod、optInSlowPeriod、optInSignalPeriod参数默认值分别为12、26、9。
TA.KDJ
TA.KDJ()函数用于计算随机指标(KDJ)。
TA.KDJ(inReal)
TA.KDJ(inReal, period, kPeriod, dPeriod)示例
测试TA.KDJ()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M15)
var kdj = TA.KDJ(records, 9, 3, 3)
Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
}
python
def main():
r = exchange.GetRecords(PERIOD_M15)
kdj = TA.KDJ(r, 9, 3, 3)
Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M15, None).unwrap();
let kdj = TA.KDJ(&records, 9, 3, 3);
Log!("k:", kdj[0], "d:", kdj[1], "j:", kdj[2]);
}
c++
void main() {
auto r = exchange.GetRecords();
auto kdj = TA.KDJ(r, 9, 3, 3);
Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2]);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
period | number | 否 |
|
kPeriod | number | 否 |
|
dPeriod | number | 否 |
|
参考
备注
TA.KDJ()函数的period、kPeriod、dPeriod参数的默认值分别为:9、3、3。
TA.RSI
TA.RSI()函数用于计算相对强弱指标。
TA.RSI(inReal)
TA.RSI(inReal, optInTimePeriod)示例
测试TA.RSI()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M30)
var rsi = TA.RSI(records, 14)
Log(rsi)
}
python
def main():
r = exchange.GetRecords(PERIOD_M30)
rsi = TA.RSI(r, 14)
Log(rsi)
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M30, None).unwrap();
let rsi = TA.RSI(&records, 14);
Log!(rsi);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M30);
auto rsi = TA.RSI(r, 14);
Log(rsi);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
参考
备注
TA.RSI()函数中optInTimePeriod参数的默认值为14。
TA.ATR
TA.ATR()函数用于计算平均真实波幅指标。
TA.ATR(inPriceHLC)
TA.ATR(inPriceHLC, optInTimePeriod)示例
测试TA.ATR()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M30)
var atr = TA.ATR(records, 14)
Log(atr)
}
python
def main():
r = exchange.GetRecords(PERIOD_M30)
atr = TA.ATR(r, 14)
Log(atr)
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M30, None).unwrap();
let atr = TA.ATR(&records, 14);
Log!(atr);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M30);
auto atr = TA.ATR(r, 14);
Log(atr);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
参考
备注
TA.ATR()函数的optInTimePeriod参数默认值为14。
TA.OBV
TA.OBV()函数用于计算能量潮指标(OBV)。
TA.OBV(inReal)
TA.OBV(inReal, inPriceV)示例
测试TA.OBV()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M30)
var obv = TA.OBV(records)
Log(obv)
}
python
def main():
r = exchange.GetRecords(PERIOD_M30)
obv = TA.OBV(r)
Log(obv)
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M30, None).unwrap();
let obv = TA.OBV(&records);
Log!(obv);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M30);
auto obv = TA.OBV(r);
Log(obv);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
inPriceV |
| 否 |
|
参考
TA.MA
TA.MA()函数用于计算移动平均线(MA)指标。
TA.MA(inReal)
TA.MA(inReal, optInTimePeriod)示例
测试TA.MA()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M30)
var ma = TA.MA(records, 14)
Log(ma)
}
python
def main():
r = exchange.GetRecords(PERIOD_M30)
ma = TA.MA(r, 14)
Log(ma)
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M30, None).unwrap();
let ma = TA.MA(&records, 14);
Log!(ma);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M30);
auto ma = TA.MA(r, 14);
Log(ma);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
参考
备注
TA.MA()函数中optInTimePeriod参数的默认值为9。
TA.EMA
TA.EMA()函数用于计算指数移动平均线指标(EMA)。
TA.EMA(inReal)
TA.EMA(inReal, optInTimePeriod)示例
测试TA.EMA()函数:
javascript
function main(){
var records = exchange.GetRecords()
// 判断K线Bar数量是否满足指标计算周期
if (records && records.length > 9) {
var ema = TA.EMA(records, 9)
Log(ema)
}
}
python
def main():
r = exchange.GetRecords()
if r and len(r) > 9:
ema = TA.EMA(r, 9)
Log(ema)
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
// 判断K线Bar数量是否满足指标计算周期
if records.len() > 9 {
let ema = TA.EMA(&records, 9);
Log!(ema);
}
}
c++
void main() {
auto r = exchange.GetRecords();
if(r.Valid && r.size() > 9) {
auto ema = TA.EMA(r, 9);
Log(ema);
}
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
参考
备注
TA.EMA()函数的optInTimePeriod参数默认值为:9。
TA.BOLL
TA.BOLL()函数用于计算布林带指标(Bollinger Bands)。
TA.BOLL(inReal)
TA.BOLL(inReal, period, multiplier)示例
测试TA.BOLL()函数:
javascript
function main() {
var records = exchange.GetRecords()
if(records && records.length > 20) {
var boll = TA.BOLL(records, 20, 2)
var upLine = boll[0]
var midLine = boll[1]
var downLine = boll[2]
Log(upLine)
Log(midLine)
Log(downLine)
}
}
python
def main():
r = exchange.GetRecords()
if r and len(r) > 20:
boll = TA.BOLL(r, 20, 2)
upLine = boll[0]
midLine = boll[1]
downLine = boll[2]
Log(upLine)
Log(midLine)
Log(downLine)
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
if records.len() > 20 {
let [upLine, midLine, downLine] = TA.BOLL(&records, 20, 2.0);
Log!(upLine);
Log!(midLine);
Log!(downLine);
}
}
c++
void main() {
auto r = exchange.GetRecords();
if(r.Valid && r.size() > 20) {
auto boll = TA.BOLL(r, 20, 2);
auto upLine = boll[0];
auto midLine = boll[1];
auto downLine = boll[2];
Log(upLine);
Log(midLine);
Log(downLine);
}
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
period | number | 否 |
|
multiplier | number | 否 |
|
参考
备注
TA.BOLL()函数的period、multiplier参数的默认值分别为:20、2。
TA.Alligator
TA.Alligator()函数用于计算鳄鱼线指标。
TA.Alligator(inReal)
TA.Alligator(inReal, jawLength, teethLength, lipsLength)示例
测试TA.Alligator()函数:
javascript
function main(){
var records = exchange.GetRecords()
var alligator = TA.Alligator(records)
Log("jawLine:", alligator[0])
Log("teethLine:", alligator[1])
Log("lipsLine:", alligator[2])
}
python
def main():
records = exchange.GetRecords()
alligator = TA.Alligator(records)
Log("jawLine:", alligator[0])
Log("teethLine:", alligator[1])
Log("lipsLine:", alligator[2])
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
let alligator = TA.Alligator(&records, None, None, None);
Log!("jawLine:", alligator[0]);
Log!("teethLine:", alligator[1]);
Log!("lipsLine:", alligator[2]);
}
c++
void main() {
auto records = exchange.GetRecords();
auto alligator = TA.Alligator(records);
Log("jawLine:", alligator[0]);
Log("teethLine:", alligator[1]);
Log("lipsLine:", alligator[2]);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
jawLength | number | 否 |
|
teethLength | number | 否 |
|
lipsLength | number | 否 |
|
参考
备注
TA.Alligator()函数的jawLength、teethLength、lipsLength参数的默认值分别为:13、8、5。
TA.CMF
TA.CMF()函数用于计算蔡金资金流量指标(Chaikin Money Flow)。
TA.CMF(inReal)
TA.CMF(inReal, inPriceV)示例
测试TA.CMF()函数:
javascript
function main() {
var records = exchange.GetRecords()
var cmf = TA.CMF(records)
Log(cmf)
}
python
def main():
records = exchange.GetRecords()
cmf = TA.CMF(records)
Log(cmf)
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
let cmf = TA.CMF(&records, None);
Log!(cmf);
}
c++
void main() {
auto records = exchange.GetRecords();
auto cmf = TA.CMF(records);
Log(cmf);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
inPriceV |
| 否 |
|
参考
TA.Highest
TA.Highest()函数用于计算周期最高价。
TA.Highest(inReal)
TA.Highest(inReal, period, attr)示例
测试TA.Highest()函数:
javascript
function main() {
var records = exchange.GetRecords()
var highestForOpen = TA.Highest(records, 10, "Open")
Log(highestForOpen)
}
python
def main():
records = exchange.GetRecords()
highestForOpen = TA.Highest(records, 10, "Open")
Log(highestForOpen)
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
// 传入开盘价数值序列,计算最近10个周期的最高开盘价(不包含当前Bar)
let opens: Vec<f64> = records.iter().map(|r| r.Open).collect();
let highestForOpen = TA.Highest(&opens, 10);
Log!(highestForOpen);
}
c++
void main() {
auto records = exchange.GetRecords();
auto highestForOpen = TA.Highest(records.Open(), 10);
Log(highestForOpen);
}返回值
| 类型 | 描述 |
number |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
period | number | 否 |
|
attr | string | 否 |
|
参考
备注
例如调用TA.Highest(records, 30, "High")函数。如果周期参数period设置为0,则计算inReal参数传入的K线数据的所有Bar;如果不指定属性参数attr,则将inReal参数传入的K线数据视为普通数组。
TA.Lowest
TA.Lowest()函数用于计算周期最低价。
TA.Lowest(inReal)
TA.Lowest(inReal, period, attr)示例
测试TA.Lowest()函数:
javascript
function main() {
var records = exchange.GetRecords()
var lowestForOpen = TA.Lowest(records, 10, "Open")
Log(lowestForOpen)
}
python
def main():
records = exchange.GetRecords()
lowestForOpen = TA.Lowest(records, 10, "Open")
Log(lowestForOpen)
rust
fn main() {
let records = exchange.GetRecords(None, None, None).unwrap();
// 传入开盘价数值序列,计算最近10个周期的最低开盘价(不包含当前Bar)
let opens: Vec<f64> = records.iter().map(|r| r.Open).collect();
let lowestForOpen = TA.Lowest(&opens, 10);
Log!(lowestForOpen);
}
c++
void main() {
auto records = exchange.GetRecords();
auto lowestForOpen = TA.Lowest(records.Open(), 10);
Log(lowestForOpen);
}返回值
| 类型 | 描述 |
number |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
period | number | 否 |
|
attr | string | 否 |
|
参考
备注
例如调用TA.Lowest(records, 30, "Low")函数时,如果周期参数period设置为0,则表示对inReal参数传入的K线数据的所有Bar进行计算;如果未指定属性参数attr,则将inReal参数传入的K线数据视为普通数组。
在C++策略中使用TA.Highest()、TA.Lowest()函数时需要注意,Highest()、Lowest()函数各自仅有2个参数,且第一个参数传入的并非auto r = exchange.GetRecords()函数调用所获取的K线数据r,而是需要调用r的相关方法以传入具体的属性数据。例如,传入r.Close()即表示传入收盘价数据。Close、High、Low、Open、Volume的调用方式与r.Close()相同。
C++语言策略的测试范例:
c++
void main() {
Records r;
r.Valid = true;
for (auto i = 0; i < 10; i++) {
Record ele;
ele.Time = i * 100000;
ele.High = i * 10000;
ele.Low = i * 1000;
ele.Close = i * 100;
ele.Open = i * 10;
ele.Volume = i * 1;
r.push_back(ele);
}
for(int j = 0; j < r.size(); j++){
Log(r[j]);
}
// 注意:第一个参数传入的不是r,需要调用r.Close()
auto highest = TA.Highest(r.Close(), 8);
Log(highest);
}
TA.SMA
TA.SMA()函数用于计算简单移动平均指标(SMA)。
TA.SMA(inReal)
TA.SMA(inReal, optInTimePeriod)示例
测试TA.SMA()函数:
javascript
function main(){
var records = exchange.GetRecords(PERIOD_M30)
var sma = TA.SMA(records, 14)
Log(sma)
}
python
def main():
r = exchange.GetRecords(PERIOD_M30)
sma = TA.SMA(r, 14)
Log(sma)
rust
fn main() {
let records = exchange.GetRecords(None, PERIOD_M30, None).unwrap();
let sma = TA.SMA(&records, 14);
Log!(sma);
}
c++
void main() {
auto r = exchange.GetRecords(PERIOD_M30);
auto sma = TA.SMA(r, 14);
Log(sma);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
参考
备注
TA.SMA()函数的optInTimePeriod参数默认值为:9。
Talib
talib.CDL2CROWS
talib.CDL2CROWS()函数用于计算Two Crows(K线图:两只乌鸦形态)。
talib.CDL2CROWS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL2CROWS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL2CROWS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL2CROWS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL2CROWS()函数在talib库文档中的描述为:CDL2CROWS(Records[Open,High,Low,Close]) = Array(outInteger)
对于Python语言的调用,传参方式有所不同,需要根据上述描述中的Records[Open,High,Low,Close]进行传参。
例如,将变量records(即参数inPriceOHLC,类型为Record结构数组)拆分为:
Open列表:在Python中写作records.Open。
High列表:在Python中写作records.High。
Low列表:在Python中写作records.Low。
Close列表:在Python中写作records.Close。
Python策略代码中的调用方式:
talib.CDL2CROWS(records.Open, records.High, records.Low, records.Close)
其他talib指标的调用方式与此类似,不再赘述。
talib.CDL3BLACKCROWS
talib.CDL3BLACKCROWS()函数用于计算三只黑乌鸦形态(K线图形态识别)。
talib.CDL3BLACKCROWS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3BLACKCROWS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3BLACKCROWS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3BLACKCROWS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3BLACKCROWS()函数在talib库文档中的描述为:CDL3BLACKCROWS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDL3INSIDE
talib.CDL3INSIDE()函数用于计算Three Inside Up/Down(三内部上涨/下跌形态)。
talib.CDL3INSIDE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3INSIDE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3INSIDE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3INSIDE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3INSIDE()函数在talib库文档中的描述为:CDL3INSIDE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDL3LINESTRIKE
talib.CDL3LINESTRIKE()函数用于计算三线打击形态(Three-Line Strike)。
talib.CDL3LINESTRIKE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3LINESTRIKE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3LINESTRIKE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3LINESTRIKE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3LINESTRIKE()函数在talib库文档中的描述为:CDL3LINESTRIKE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDL3OUTSIDE
talib.CDL3OUTSIDE()函数用于计算Three Outside Up/Down(三外部上涨/下跌形态)。
talib.CDL3OUTSIDE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3OUTSIDE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3OUTSIDE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3OUTSIDE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3OUTSIDE()函数在talib库文档中的描述为:CDL3OUTSIDE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDL3STARSINSOUTH
talib.CDL3STARSINSOUTH()函数用于计算南方三星形态(Three Stars In The South)。
talib.CDL3STARSINSOUTH(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3STARSINSOUTH(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3STARSINSOUTH(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3STARSINSOUTH(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3STARSINSOUTH()函数在talib库文档中的描述为:CDL3STARSINSOUTH(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDL3WHITESOLDIERS
talib.CDL3WHITESOLDIERS()函数用于计算三白兵形态(Three Advancing White Soldiers)。
talib.CDL3WHITESOLDIERS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDL3WHITESOLDIERS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDL3WHITESOLDIERS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDL3WHITESOLDIERS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDL3WHITESOLDIERS()函数在talib库文档中的描述为:CDL3WHITESOLDIERS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLABANDONEDBABY
talib.CDLABANDONEDBABY()函数用于计算弃婴形态(K线图:Abandoned Baby)。
talib.CDLABANDONEDBABY(inPriceOHLC)
talib.CDLABANDONEDBABY(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLABANDONEDBABY(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLABANDONEDBABY(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLABANDONEDBABY(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLABANDONEDBABY()函数在talib库文档中的描述为:CDLABANDONEDBABY(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)
talib.CDLADVANCEBLOCK
talib.CDLADVANCEBLOCK()函数用于计算Advance Block(K线形态:推进块)。
talib.CDLADVANCEBLOCK(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLADVANCEBLOCK(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLADVANCEBLOCK(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLADVANCEBLOCK(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLADVANCEBLOCK()函数在talib库文档中的描述为:CDLADVANCEBLOCK(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLBELTHOLD
talib.CDLBELTHOLD()函数用于计算Belt-hold(捉腰带线)。
talib.CDLBELTHOLD(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLBELTHOLD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLBELTHOLD(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLBELTHOLD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLBELTHOLD()函数在talib库文档中的描述为:CDLBELTHOLD(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLBREAKAWAY
talib.CDLBREAKAWAY()函数用于计算Breakaway(K线图:突破形态)。
talib.CDLBREAKAWAY(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLBREAKAWAY(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLBREAKAWAY(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLBREAKAWAY(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLBREAKAWAY()函数在talib库文档中的描述为:CDLBREAKAWAY(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLCLOSINGMARUBOZU
talib.CDLCLOSINGMARUBOZU()函数用于计算收盘光头光脚形态(Closing Marubozu)。
talib.CDLCLOSINGMARUBOZU(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLCLOSINGMARUBOZU(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLCLOSINGMARUBOZU(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLCLOSINGMARUBOZU(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLCLOSINGMARUBOZU()函数在talib库文档中的描述为:CDLCLOSINGMARUBOZU(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLCONCEALBABYSWALL
talib.CDLCONCEALBABYSWALL()函数用于计算Concealing Baby Swallow(隐藏婴儿吞没形态)。
talib.CDLCONCEALBABYSWALL(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLCONCEALBABYSWALL(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLCONCEALBABYSWALL(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLCONCEALBABYSWALL(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLCONCEALBABYSWALL()函数在talib库文档中的描述为:CDLCONCEALBABYSWALL(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLCOUNTERATTACK
talib.CDLCOUNTERATTACK()函数用于计算反击形态(Counterattack)。
talib.CDLCOUNTERATTACK(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLCOUNTERATTACK(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLCOUNTERATTACK(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLCOUNTERATTACK(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLCOUNTERATTACK()函数在talib库文档中的描述为:CDLCOUNTERATTACK(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLDARKCLOUDCOVER
talib.CDLDARKCLOUDCOVER()函数用于计算乌云盖顶形态(Dark Cloud Cover)。
talib.CDLDARKCLOUDCOVER(inPriceOHLC)
talib.CDLDARKCLOUDCOVER(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLDARKCLOUDCOVER(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLDARKCLOUDCOVER(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLDARKCLOUDCOVER(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLDARKCLOUDCOVER()函数在talib库文档中的描述为:CDLDARKCLOUDCOVER(Records[Open,High,Low,Close],Penetration = 0.5) = Array(outInteger)
talib.CDLDOJI
talib.CDLDOJI()函数用于计算Doji(K线图:十字星)。
talib.CDLDOJI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLDOJI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLDOJI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLDOJI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLDOJI()函数在talib库文档中的描述为:CDLDOJI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLDOJISTAR
talib.CDLDOJISTAR()函数用于计算十字星形态(K线图:Doji Star)。
talib.CDLDOJISTAR(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLDOJISTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLDOJISTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLDOJISTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLDOJISTAR()函数在talib库文档中的描述为:CDLDOJISTAR(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLDRAGONFLYDOJI
talib.CDLDRAGONFLYDOJI()函数用于计算蜻蜓十字星(Dragonfly Doji)K线形态。
talib.CDLDRAGONFLYDOJI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLDRAGONFLYDOJI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLDRAGONFLYDOJI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLDRAGONFLYDOJI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLDRAGONFLYDOJI()函数在talib库文档中的描述为:CDLDRAGONFLYDOJI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLENGULFING
talib.CDLENGULFING()函数用于计算吞没形态(Engulfing Pattern)。
talib.CDLENGULFING(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLENGULFING(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLENGULFING(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLENGULFING(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLENGULFING()函数在talib库文档中的描述为:CDLENGULFING(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLEVENINGDOJISTAR
talib.CDLEVENINGDOJISTAR()函数用于计算Evening Doji Star(K线图:黄昏十字星)。
talib.CDLEVENINGDOJISTAR(inPriceOHLC)
talib.CDLEVENINGDOJISTAR(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLEVENINGDOJISTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLEVENINGDOJISTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLEVENINGDOJISTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLEVENINGDOJISTAR()函数在talib库文档中的描述为:CDLEVENINGDOJISTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)
talib.CDLEVENINGSTAR
talib.CDLEVENINGSTAR()函数用于计算Evening Star(K线图:黄昏之星)。
talib.CDLEVENINGSTAR(inPriceOHLC)
talib.CDLEVENINGSTAR(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLEVENINGSTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLEVENINGSTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLEVENINGSTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLEVENINGSTAR()函数在talib库文档中的描述为:CDLEVENINGSTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)
talib.CDLGAPSIDESIDEWHITE
talib.CDLGAPSIDESIDEWHITE()函数用于计算向上/向下跳空并列白色K线形态(K线图:上升/下降跳空并列阳线)。
talib.CDLGAPSIDESIDEWHITE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLGAPSIDESIDEWHITE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLGAPSIDESIDEWHITE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLGAPSIDESIDEWHITE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLGAPSIDESIDEWHITE()函数在talib库文档中的描述为:CDLGAPSIDESIDEWHITE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLGRAVESTONEDOJI
talib.CDLGRAVESTONEDOJI()函数用于计算**墓碑十字线(Gravestone Doji)**K线形态。
talib.CDLGRAVESTONEDOJI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLGRAVESTONEDOJI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLGRAVESTONEDOJI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLGRAVESTONEDOJI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLGRAVESTONEDOJI()函数在talib库文档中的描述为:CDLGRAVESTONEDOJI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHAMMER
talib.CDLHAMMER()函数用于计算锤子线(K线形态:锤子)。
talib.CDLHAMMER(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHAMMER(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHAMMER(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHAMMER(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHAMMER()函数在talib库文档中的描述为:CDLHAMMER(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHANGINGMAN
talib.CDLHANGINGMAN()函数用于计算上吊线形态(K线图:上吊线)。
talib.CDLHANGINGMAN(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHANGINGMAN(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHANGINGMAN(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHANGINGMAN(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHANGINGMAN()函数在talib库文档中的描述为:CDLHANGINGMAN(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHARAMI
talib.CDLHARAMI()函数用于计算Harami形态(十字孕线形态)。
talib.CDLHARAMI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHARAMI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHARAMI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHARAMI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHARAMI()函数在talib库文档中的描述为:CDLHARAMI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHARAMICROSS
talib.CDLHARAMICROSS()函数用于计算十字孕线形态(Harami Cross Pattern)。
talib.CDLHARAMICROSS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHARAMICROSS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHARAMICROSS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHARAMICROSS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHARAMICROSS()函数在talib库文档中的描述为:CDLHARAMICROSS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHIGHWAVE
talib.CDLHIGHWAVE()函数用于计算高浪线形态(High-Wave Candle)。
talib.CDLHIGHWAVE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHIGHWAVE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHIGHWAVE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHIGHWAVE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHIGHWAVE()函数在talib库文档中的描述为:CDLHIGHWAVE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHIKKAKE
talib.CDLHIKKAKE()函数用于计算Hikkake Pattern (陷阱形态)。
talib.CDLHIKKAKE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHIKKAKE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHIKKAKE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHIKKAKE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHIKKAKE()函数在talib库文档中的描述为:CDLHIKKAKE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHIKKAKEMOD
talib.CDLHIKKAKEMOD()函数用于计算改良陷阱形态(Modified Hikkake Pattern)。
talib.CDLHIKKAKEMOD(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHIKKAKEMOD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHIKKAKEMOD(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHIKKAKEMOD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHIKKAKEMOD()函数在talib库文档中的描述为:CDLHIKKAKEMOD(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLHOMINGPIGEON
talib.CDLHOMINGPIGEON()函数用于计算信鸽形态(K线图:信鸽)。
talib.CDLHOMINGPIGEON(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLHOMINGPIGEON(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLHOMINGPIGEON(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLHOMINGPIGEON(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLHOMINGPIGEON()函数在talib库文档中的描述为:CDLHOMINGPIGEON(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLIDENTICAL3CROWS
talib.CDLIDENTICAL3CROWS()函数用于计算Identical Three Crows(K线形态:三只相同乌鸦)。
talib.CDLIDENTICAL3CROWS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLIDENTICAL3CROWS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLIDENTICAL3CROWS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLIDENTICAL3CROWS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLIDENTICAL3CROWS()函数在talib库文档中的描述为:CDLIDENTICAL3CROWS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLINNECK
talib.CDLINNECK()函数用于计算颈内线形态(In-Neck Pattern)。
talib.CDLINNECK(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLINNECK(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLINNECK(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLINNECK(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLINNECK()函数在talib库文档中的描述为:CDLINNECK(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLINVERTEDHAMMER
talib.CDLINVERTEDHAMMER()函数用于计算倒锤子线(K线形态:倒锤子)。
talib.CDLINVERTEDHAMMER(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLINVERTEDHAMMER(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLINVERTEDHAMMER(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLINVERTEDHAMMER(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLINVERTEDHAMMER()函数在talib库文档中的描述为:CDLINVERTEDHAMMER(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLKICKING
talib.CDLKICKING()函数用于计算Kicking(反冲形态)。
talib.CDLKICKING(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLKICKING(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLKICKING(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLKICKING(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLKICKING()函数在talib库文档中的描述为:CDLKICKING(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLKICKINGBYLENGTH
talib.CDLKICKINGBYLENGTH()函数用于计算Kicking - bull/bear determined by the longer marubozu (K线图:由较长光头光脚阳线/阴线决定的踢腿形态)。
talib.CDLKICKINGBYLENGTH(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLKICKINGBYLENGTH(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLKICKINGBYLENGTH(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLKICKINGBYLENGTH(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLKICKINGBYLENGTH()函数在talib库文档中的描述为:CDLKICKINGBYLENGTH(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLLADDERBOTTOM
talib.CDLLADDERBOTTOM()函数用于计算梯底形态(Ladder Bottom)。
talib.CDLLADDERBOTTOM(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLLADDERBOTTOM(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLLADDERBOTTOM(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLLADDERBOTTOM(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLLADDERBOTTOM()函数在talib库文档中的描述为:CDLLADDERBOTTOM(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLLONGLEGGEDDOJI
talib.CDLLONGLEGGEDDOJI()函数用于计算长腿十字线(K线形态)。
talib.CDLLONGLEGGEDDOJI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLLONGLEGGEDDOJI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLLONGLEGGEDDOJI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLLONGLEGGEDDOJI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLLONGLEGGEDDOJI()函数在talib库文档中的描述为:CDLLONGLEGGEDDOJI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLLONGLINE
talib.CDLLONGLINE()函数用于计算长线蜡烛形态(Long Line Candle)。
talib.CDLLONGLINE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLLONGLINE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLLONGLINE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLLONGLINE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLLONGLINE()函数在talib库文档中的描述为:CDLLONGLINE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLMARUBOZU
talib.CDLMARUBOZU()函数用于计算Marubozu (K线图:光头光脚)。
talib.CDLMARUBOZU(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLMARUBOZU(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLMARUBOZU(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLMARUBOZU(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLMARUBOZU()函数在talib库文档中的描述为:CDLMARUBOZU(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLMATCHINGLOW
talib.CDLMATCHINGLOW()函数用于计算Matching Low(K线形态:匹配低点)。
talib.CDLMATCHINGLOW(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLMATCHINGLOW(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLMATCHINGLOW(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLMATCHINGLOW(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLMATCHINGLOW()函数在talib库文档中的描述为:CDLMATCHINGLOW(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLMATHOLD
talib.CDLMATHOLD()函数用于计算Mat Hold(垫住形态)。
talib.CDLMATHOLD(inPriceOHLC)
talib.CDLMATHOLD(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLMATHOLD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLMATHOLD(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLMATHOLD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLMATHOLD()函数在talib库文档中的描述为:CDLMATHOLD(Records[Open,High,Low,Close],Penetration = 0.5) = Array(outInteger)
talib.CDLMORNINGDOJISTAR
talib.CDLMORNINGDOJISTAR()函数用于计算Morning Doji Star(K线形态:早晨十字星)。
talib.CDLMORNINGDOJISTAR(inPriceOHLC)
talib.CDLMORNINGDOJISTAR(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLMORNINGDOJISTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLMORNINGDOJISTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLMORNINGDOJISTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLMORNINGDOJISTAR()函数在talib库文档中的描述为:CDLMORNINGDOJISTAR(Records[Open,High,Low,Close],Penetration = 0.3) = Array(outInteger)
talib.CDLMORNINGSTAR
talib.CDLMORNINGSTAR()函数用于计算晨星形态(Morning Star)。
talib.CDLMORNINGSTAR(inPriceOHLC)
talib.CDLMORNINGSTAR(inPriceOHLC, optInPenetration)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLMORNINGSTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLMORNINGSTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLMORNINGSTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
optInPenetration | number | 否 |
|
备注
CDLMORNINGSTAR()函数在talib库文档中的描述为:CDLMORNINGSTAR(Records[Open,High,Low,Close],Penetration=0.3) = Array(outInteger)
talib.CDLONNECK
talib.CDLONNECK()函数用于计算颈上线形态(On-Neck Pattern)。
talib.CDLONNECK(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLONNECK(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLONNECK(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLONNECK(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLONNECK()函数在talib库文档中的描述为:CDLONNECK(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLPIERCING
talib.CDLPIERCING()函数用于计算Piercing Pattern (K线图:刺透形态)。
talib.CDLPIERCING(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLPIERCING(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLPIERCING(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLPIERCING(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLPIERCING()函数在talib库文档中的描述为:CDLPIERCING(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLRICKSHAWMAN
talib.CDLRICKSHAWMAN()函数用于计算人力车夫形态(K线图:人力车夫)。
talib.CDLRICKSHAWMAN(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLRICKSHAWMAN(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLRICKSHAWMAN(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLRICKSHAWMAN(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLRICKSHAWMAN()函数在talib库文档中的描述为:CDLRICKSHAWMAN(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLRISEFALL3METHODS
talib.CDLRISEFALL3METHODS()函数用于计算上升/下降三法形态(Rising/Falling Three Methods)。
talib.CDLRISEFALL3METHODS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLRISEFALL3METHODS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLRISEFALL3METHODS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLRISEFALL3METHODS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLRISEFALL3METHODS()函数在talib库文档中的描述为:CDLRISEFALL3METHODS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSEPARATINGLINES
talib.CDLSEPARATINGLINES()函数用于计算分离线形态(Separating Lines)。
talib.CDLSEPARATINGLINES(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSEPARATINGLINES(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSEPARATINGLINES(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSEPARATINGLINES(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSEPARATINGLINES()函数在talib库文档中的描述为:CDLSEPARATINGLINES(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSHOOTINGSTAR
talib.CDLSHOOTINGSTAR()函数用于计算流星线形态(Shooting Star)。
talib.CDLSHOOTINGSTAR(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSHOOTINGSTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSHOOTINGSTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSHOOTINGSTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSHOOTINGSTAR()函数在talib库文档中的描述为:CDLSHOOTINGSTAR(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSHORTLINE
talib.CDLSHORTLINE()函数用于计算短线型K线形态(Short Line Candle)。
talib.CDLSHORTLINE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSHORTLINE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSHORTLINE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSHORTLINE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSHORTLINE()函数在talib库文档中的描述为:CDLSHORTLINE(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSPINNINGTOP
talib.CDLSPINNINGTOP()函数用于计算纺锤线形态(K线图:陀螺)。
talib.CDLSPINNINGTOP(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSPINNINGTOP(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSPINNINGTOP(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSPINNINGTOP(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSPINNINGTOP()函数在talib库文档中的描述为:CDLSPINNINGTOP(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSTALLEDPATTERN
talib.CDLSTALLEDPATTERN()函数用于计算停滞形态(Stalled Pattern)。
talib.CDLSTALLEDPATTERN(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSTALLEDPATTERN(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSTALLEDPATTERN(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSTALLEDPATTERN(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSTALLEDPATTERN()函数在talib库文档中的描述为:CDLSTALLEDPATTERN(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLSTICKSANDWICH
talib.CDLSTICKSANDWICH()函数用于计算Stick Sandwich(K线形态:夹心三明治)。
talib.CDLSTICKSANDWICH(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLSTICKSANDWICH(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLSTICKSANDWICH(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLSTICKSANDWICH(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLSTICKSANDWICH()函数在talib库文档中的描述为:CDLSTICKSANDWICH(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLTAKURI
talib.CDLTAKURI()函数用于计算Takuri (Dragonfly Doji with very long lower shadow) (K线形态:探底十字线)。
talib.CDLTAKURI(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLTAKURI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLTAKURI(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLTAKURI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLTAKURI()函数在talib库文档中的描述为:CDLTAKURI(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLTASUKIGAP
talib.CDLTASUKIGAP()函数用于计算Tasuki Gap(任务缺口形态)。
talib.CDLTASUKIGAP(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLTASUKIGAP(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLTASUKIGAP(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLTASUKIGAP(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLTASUKIGAP()函数在talib库文档中的描述为:CDLTASUKIGAP(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLTHRUSTING
talib.CDLTHRUSTING()函数用于计算Thrusting Pattern(K线图:刺透形态)。
talib.CDLTHRUSTING(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLTHRUSTING(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLTHRUSTING(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLTHRUSTING(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLTHRUSTING()函数在talib库文档中的描述为:CDLTHRUSTING(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLTRISTAR
talib.CDLTRISTAR()函数用于计算三星形态(Tristar Pattern)。
talib.CDLTRISTAR(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLTRISTAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLTRISTAR(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLTRISTAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLTRISTAR()函数在talib库文档中的描述为:CDLTRISTAR(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLUNIQUE3RIVER
talib.CDLUNIQUE3RIVER()函数用于计算Unique 3 River(K线形态:独特三河形态)。
talib.CDLUNIQUE3RIVER(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLUNIQUE3RIVER(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLUNIQUE3RIVER(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLUNIQUE3RIVER(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLUNIQUE3RIVER()函数在talib库文档中的描述为:CDLUNIQUE3RIVER(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLUPSIDEGAP2CROWS
talib.CDLUPSIDEGAP2CROWS()函数用于计算**Upside Gap Two Crows(向上跳空两只乌鸦)**K线形态。
talib.CDLUPSIDEGAP2CROWS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLUPSIDEGAP2CROWS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLUPSIDEGAP2CROWS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLUPSIDEGAP2CROWS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLUPSIDEGAP2CROWS()函数在talib库文档中的描述为:CDLUPSIDEGAP2CROWS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.CDLXSIDEGAP3METHODS
talib.CDLXSIDEGAP3METHODS()函数用于计算向上/向下跳空三法形态(K线图:向上/向下跳空三法)。
talib.CDLXSIDEGAP3METHODS(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CDLXSIDEGAP3METHODS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CDLXSIDEGAP3METHODS(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CDLXSIDEGAP3METHODS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
CDLXSIDEGAP3METHODS()函数在talib库文档中的描述为:CDLXSIDEGAP3METHODS(Records[Open,High,Low,Close]) = Array(outInteger)
talib.AD
talib.AD()函数用于计算Chaikin A/D Line(累积/派发线)。
talib.AD(inPriceHLCV)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.AD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.AD(records.High, records.Low, records.Close, records.Volume)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.AD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLCV |
| 是 |
|
备注
AD()函数在talib库文档中的描述为:AD(Records[High,Low,Close,Volume]) = Array(outReal)
talib.ADOSC
talib.ADOSC()函数用于计算Chaikin A/D Oscillator(佳庆指标)。
talib.ADOSC(inPriceHLCV)
talib.ADOSC(inPriceHLCV, optInFastPeriod, optInSlowPeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ADOSC(records, 3, 10)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ADOSC(records.High, records.Low, records.Close, records.Volume, 3, 10)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ADOSC(records, 3, 10);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLCV |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInSlowPeriod | number | 否 |
|
备注
ADOSC()函数在talib库文档中的描述为:ADOSC(Records[High,Low,Close,Volume],Fast Period = 3,Slow Period = 10) = Array(outReal)
talib.OBV
talib.OBV()函数用于计算On Balance Volume(能量潮指标)。
talib.OBV(inReal)
talib.OBV(inReal, inPriceV)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.OBV(records, records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.OBV(records.Close, records.Volume)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.OBV(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
inPriceV |
| 否 |
|
备注
OBV()函数在talib库文档中的描述为:OBV(Records[Close],Records[Volume]) = Array(outReal)
talib.ACOS
talib.ACOS()函数用于计算向量三角函数反余弦(Vector Trigonometric ACos)。
talib.ACOS(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.ACOS(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.ACOS(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.ACOS(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
ACOS()函数在talib库文档中的描述为:ACOS(Records[Close]) = Array(outReal)
talib.ASIN
talib.ASIN()函数用于计算向量三角函数反正弦(Vector Trigonometric ASin)。
talib.ASIN(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.ASIN(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.ASIN(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.ASIN(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
ASIN()函数在talib库文档中的描述为:ASIN(Records[Close]) = Array(outReal)
talib.ATAN
talib.ATAN()函数用于计算向量三角函数反正切(Vector Trigonometric ATan)。
talib.ATAN(inReal)示例
javascript
function main() {
var data = [-3.14/2, 0, 3.14/2]
var ret = talib.ATAN(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-3.14/2, 0, 3.14/2]
ret = talib.ATAN(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-3.14/2, 0, 3.14/2};
auto ret = talib.ATAN(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
ATAN()函数在talib库文档中的描述为:ATAN(Records[Close]) = Array(outReal)
talib.CEIL
talib.CEIL()函数用于计算向上取整函数(Vector Ceil)。
talib.CEIL(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CEIL(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CEIL(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CEIL(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
CEIL()函数在talib库文档中的描述为:CEIL(Records[Close]) = Array(outReal)
talib.COS
talib.COS()函数用于计算向量三角余弦函数(Vector Trigonometric Cosine)。
talib.COS(inReal)示例
javascript
function main() {
var data = [-3.14, 0, 3.14]
var ret = talib.COS(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-3.14, 0, 3.14]
ret = talib.COS(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-3.14, 0, 3.14};
auto ret = talib.COS(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
COS()函数在talib库文档中的描述为:COS(Records[Close]) = Array(outReal)
talib.COSH
talib.COSH()函数用于计算向量三角函数双曲余弦值(Vector Trigonometric Cosh)。
talib.COSH(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.COSH(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.COSH(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.COSH(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
COSH()函数在talib库文档中的描述为:COSH(Records[Close]) = Array(outReal)
talib.EXP
talib.EXP()函数用于计算向量算术指数函数(Vector Arithmetic Exp)。
talib.EXP(inReal)示例
javascript
function main() {
var data = [0, 1, 2]
var ret = talib.EXP(data) // e^0, e^1, e^2
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [0, 1.0, 2.0]
ret = talib.EXP(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {0, 1.0, 2.0};
auto ret = talib.EXP(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
EXP()函数在talib库文档中的描述为:EXP(Records[Close]) = Array(outReal)
talib.FLOOR
talib.FLOOR()函数用于计算向量向下取整(Vector Floor)。
talib.FLOOR(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.FLOOR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.FLOOR(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.FLOOR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
FLOOR()函数在talib库文档中的描述为:FLOOR(Records[Close]) = Array(outReal)
talib.LN
talib.LN()函数用于计算向量自然对数(Vector Log Natural)。
talib.LN(inReal)示例
javascript
function main() {
var data = [1, 2, 3]
var ret = talib.LN(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [1.0, 2.0, 3.0]
ret = talib.LN(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {1, 2, 3};
auto ret = talib.LN(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
LN()函数在talib库文档中的描述为:LN(Records[Close]) = Array(outReal)
talib.LOG10
talib.LOG10()函数用于计算向量以10为底的对数(Vector Log10)。
talib.LOG10(inReal)示例
javascript
function main() {
var data = [10, 100, 1000]
var ret = talib.LOG10(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [10.0, 100.0, 1000.0]
ret = talib.LOG10(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {10, 100, 1000};
auto ret = talib.LOG10(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
LOG10()函数在talib库文档中的描述为:LOG10(Records[Close]) = Array(outReal)
talib.SIN
talib.SIN()函数用于计算向量三角正弦值(Vector Trigonometric Sin)。
talib.SIN(inReal)示例
javascript
function main() {
var data = [-3.14/2, 0, 3.14/2]
var ret = talib.SIN(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-3.14/2, 0, 3.14/2]
ret = talib.SIN(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-3.14/2, 0, 3.14/2};
auto ret = talib.SIN(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
SIN()函数在talib库文档中的描述为:SIN(Records[Close]) = Array(outReal)
talib.SINH
talib.SINH()函数用于计算向量三角函数双曲正弦(Vector Trigonometric Sinh)。
talib.SINH(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.SINH(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.SINH(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.SINH(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
SINH()函数在talib库文档中的描述为:SINH(Records[Close]) = Array(outReal)
talib.SQRT
talib.SQRT()函数用于计算向量平方根(Vector Square Root)。
talib.SQRT(inReal)示例
javascript
function main() {
var data = [4, 64, 100]
var ret = talib.SQRT(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [4.0, 64.0, 100.0]
ret = talib.SQRT(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {4, 64, 100};
auto ret = talib.SQRT(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
SQRT()函数在talib库文档中的描述为:SQRT(Records[Close]) = Array(outReal)
talib.TAN
talib.TAN()函数用于计算向量三角正切函数(Vector Trigonometric Tan)。
talib.TAN(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.TAN(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.TAN(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.TAN(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
TAN()函数在talib库文档中的描述为:TAN(Records[Close]) = Array(outReal)
talib.TANH
talib.TANH()函数用于计算向量三角函数双曲正切(Vector Trigonometric Tanh)。
talib.TANH(inReal)示例
javascript
function main() {
var data = [-1, 0, 1]
var ret = talib.TANH(data)
Log(ret)
}
python
import talib
import numpy as np
def main():
data = [-1.0, 0, 1.0]
ret = talib.TANH(np.array(data))
Log(ret)
c++
void main() {
std::vector<double> data = {-1, 0, 1};
auto ret = talib.TANH(data);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
TANH()函数在talib库文档中的描述为:TANH(Records[Close]) = Array(outReal)
talib.MAX
talib.MAX()函数用于计算指定周期内的最高值(Highest value over a specified period)。
talib.MAX(inReal)
talib.MAX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MAX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MAX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MAX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MAX()函数在talib库文档中的描述为:MAX(Records[Close],Time Period = 30) = Array(outReal)
talib.MAXINDEX
talib.MAXINDEX()函数用于计算指定周期内最高值的索引(Index of highest value over a specified period)。
talib.MAXINDEX(inReal)
talib.MAXINDEX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MAXINDEX(records, 5)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MAXINDEX(records.Close, 5)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MAXINDEX(records, 5);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MAXINDEX()函数在talib库文档中的描述为:MAXINDEX(Records[Close],Time Period = 30) = Array(outInteger)
talib.MIN
talib.MIN()函数用于计算指定周期内的最低值(Lowest value over a specified period)。
talib.MIN(inReal)
talib.MIN(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MIN(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MIN(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MIN(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MIN()函数在talib库文档中的描述为:MIN(Records[Close],Time Period = 30) = Array(outReal)
talib.MININDEX
talib.MININDEX()函数用于计算指定周期内最小值的索引位置(Index of lowest value over a specified period)。
talib.MININDEX(inReal)
talib.MININDEX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MININDEX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MININDEX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MININDEX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MININDEX()函数在talib库文档中的描述为:MININDEX(Records[Close],Time Period = 30) = Array(outInteger)
talib.MINMAX
talib.MINMAX()函数用于计算Lowest and highest values over a specified period (指定周期内的最小值和最大值)。
talib.MINMAX(inReal)
talib.MINMAX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MINMAX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MINMAX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MINMAX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MINMAX()函数在talib库文档中的描述为:MINMAX(Records[Close],Time Period = 30) = [Array(outMin),Array(outMax)]
talib.MINMAXINDEX
talib.MINMAXINDEX()函数用于计算指定周期内最低值和最高值的索引(Indexes of lowest and highest values over a specified period)。
talib.MINMAXINDEX(inReal)
talib.MINMAXINDEX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MINMAXINDEX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MINMAXINDEX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MINMAXINDEX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MINMAXINDEX()函数在talib库文档中的描述为:MINMAXINDEX(Records[Close],Time Period = 30) = [Array(outMinIdx),Array(outMaxIdx)]
talib.SUM
talib.SUM()函数用于计算求和(Summation)。
talib.SUM(inReal)
talib.SUM(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.SUM(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.SUM(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.SUM(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
SUM()函数在talib库文档中的描述为:SUM(Records[Close],Time Period = 30) = Array(outReal)
talib.HT_DCPERIOD
talib.HT_DCPERIOD()函数用于计算希尔伯特变换 - 主导周期(Hilbert Transform - Dominant Cycle Period)。
talib.HT_DCPERIOD(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_DCPERIOD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_DCPERIOD(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_DCPERIOD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_DCPERIOD()函数在talib库文档中的描述为:HT_DCPERIOD(Records[Close]) = Array(outReal)
talib.HT_DCPHASE
talib.HT_DCPHASE()函数用于计算希尔伯特变换 - 主导周期相位(Hilbert Transform - Dominant Cycle Phase)。
talib.HT_DCPHASE(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_DCPHASE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_DCPHASE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_DCPHASE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_DCPHASE()函数在talib库文档中的描述为:HT_DCPHASE(Records[Close]) = Array(outReal)
talib.HT_PHASOR
talib.HT_PHASOR()函数用于计算希尔伯特变换 - 相位分量(Hilbert Transform - Phasor Components)。
talib.HT_PHASOR(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_PHASOR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_PHASOR(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_PHASOR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_PHASOR()函数在talib库文档中的描述为:HT_PHASOR(Records[Close]) = [Array(outInPhase),Array(outQuadrature)]
talib.HT_SINE
talib.HT_SINE()函数用于计算希尔伯特变换 - 正弦波(Hilbert Transform - SineWave)。
talib.HT_SINE(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_SINE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_SINE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_SINE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_SINE()函数在talib库文档中的描述为:HT_SINE(Records[Close]) = [Array(outSine),Array(outLeadSine)]
talib.HT_TRENDMODE
talib.HT_TRENDMODE()函数用于计算希尔伯特变换 - 趋势与周期模式(Hilbert Transform - Trend vs Cycle Mode)。
talib.HT_TRENDMODE(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_TRENDMODE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_TRENDMODE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_TRENDMODE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_TRENDMODE()函数在talib库文档中的描述为:HT_TRENDMODE(Records[Close]) = Array(outInteger)
talib.ATR
talib.ATR()函数用于计算平均真实波幅(Average True Range)。
talib.ATR(inPriceHLC)
talib.ATR(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ATR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ATR(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ATR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ATR()函数在talib库文档中的描述为:ATR(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.NATR
talib.NATR()函数用于计算归一化平均真实波幅(Normalized Average True Range)。
talib.NATR(inPriceHLC)
talib.NATR(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.NATR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.NATR(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.NATR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
NATR()函数在talib库文档中的描述为:NATR(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.TRANGE
talib.TRANGE()函数用于计算真实波动幅度(True Range)。
talib.TRANGE(inPriceHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TRANGE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TRANGE(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TRANGE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
备注
TRANGE()函数在talib库文档中的描述为:TRANGE(Records[High,Low,Close]) = Array(outReal)
talib.BBANDS
talib.BBANDS()函数用于计算布林带(Bollinger Bands)。
talib.BBANDS(inReal)
talib.BBANDS(inReal, optInTimePeriod)
talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp)
talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp, optInNbDevDn)
talib.BBANDS(inReal, optInTimePeriod, optInNbDevUp, optInNbDevDn, optInMAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.BBANDS(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.BBANDS(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.BBANDS(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInNbDevUp | number | 否 |
|
optInNbDevDn | number | 否 |
|
optInMAType | number | 否 |
|
备注
BBANDS()函数在talib库文档中的描述为:BBANDS(Records[Close],Time Period = 5,Deviations up = 2,Deviations down = 2,MA Type = 0) = [Array(outRealUpperBand),Array(outRealMiddleBand),Array(outRealLowerBand)]
talib.DEMA
talib.DEMA()函数用于计算双指数移动平均线(Double Exponential Moving Average)。
talib.DEMA(inReal)
talib.DEMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.DEMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.DEMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.DEMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
DEMA()函数在talib库文档中的描述为:DEMA(Records[Close],Time Period = 30) = Array(outReal)
talib.EMA
talib.EMA()函数用于计算指数移动平均线(Exponential Moving Average)。
talib.EMA(inReal)
talib.EMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.EMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.EMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.EMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
EMA()函数在talib库文档中的描述为:EMA(Records[Close],Time Period = 30) = Array(outReal)
talib.HT_TRENDLINE
talib.HT_TRENDLINE()函数用于计算希尔伯特变换 - 瞬时趋势线(Hilbert Transform - Instantaneous Trendline)。
talib.HT_TRENDLINE(inReal)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.HT_TRENDLINE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.HT_TRENDLINE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.HT_TRENDLINE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
备注
HT_TRENDLINE()函数在talib库文档中的描述为:HT_TRENDLINE(Records[Close]) = Array(outReal)
talib.KAMA
talib.KAMA()函数用于计算Kaufman Adaptive Moving Average(考夫曼自适应移动平均线)。
talib.KAMA(inReal)
talib.KAMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.KAMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.KAMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.KAMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
KAMA()函数在talib库文档中的描述为:KAMA(Records[Close],Time Period = 30) = Array(outReal)
talib.MA
talib.MA()函数用于计算移动平均线(Moving Average)。
talib.MA(inReal)
talib.MA(inReal, optInTimePeriod)
talib.MA(inReal, optInTimePeriod, optInMAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInMAType | number | 否 |
|
备注
MA()函数在talib库文档中的描述为:MA(Records[Close],Time Period = 30,MA Type = 0) = Array(outReal)
talib.MAMA
talib.MAMA()函数用于计算MESA自适应移动平均线(MESA Adaptive Moving Average)。
talib.MAMA(inReal)
talib.MAMA(inReal, optInFastLimit)
talib.MAMA(inReal, optInFastLimit, optInSlowLimit)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MAMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MAMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MAMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastLimit | number | 否 |
|
optInSlowLimit | number | 否 |
|
备注
MAMA()函数在talib库文档中的描述为:MAMA(Records[Close],Fast Limit = 0.5,Slow Limit = 0.05) = [Array(outMAMA),Array(outFAMA)]
talib.MIDPOINT
talib.MIDPOINT()函数用于计算指定周期内的中点值(MidPoint over period)。
talib.MIDPOINT(inReal)
talib.MIDPOINT(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MIDPOINT(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MIDPOINT(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MIDPOINT(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MIDPOINT()函数在talib库文档中的描述为:MIDPOINT(Records[Close],Time Period = 14) = Array(outReal)
talib.MIDPRICE
talib.MIDPRICE()函数用于计算Midpoint Price over period (周期内中点价格)。
talib.MIDPRICE(inPriceHL)
talib.MIDPRICE(inPriceHL, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MIDPRICE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MIDPRICE(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MIDPRICE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MIDPRICE()函数在talib库文档中的描述为:MIDPRICE(Records[High,Low],Time Period = 14) = Array(outReal)
talib.SAR
talib.SAR()函数用于计算抛物线转向指标(Parabolic SAR)。
talib.SAR(inPriceHL)
talib.SAR(inPriceHL, optInAcceleration)
talib.SAR(inPriceHL, optInAcceleration, optInMaximum)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.SAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.SAR(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.SAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInAcceleration | number | 否 |
|
optInMaximum | number | 否 |
|
备注
SAR()函数在talib库文档中的描述为:SAR(Records[High,Low],Acceleration Factor = 0.02,AF Maximum = 0.2) = Array(outReal)
talib.SAREXT
talib.SAREXT()函数用于计算Parabolic SAR - Extended (增强型抛物线转向指标)。
talib.SAREXT(inPriceHL)
talib.SAREXT(inPriceHL, optInStartValue)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort, optInAccelerationShort)
talib.SAREXT(inPriceHL, optInStartValue, optInOffsetOnReverse, optInAccelerationInitLong, optInAccelerationLong, optInAccelerationMaxLong, optInAccelerationInitShort, optInAccelerationShort, optInAccelerationMaxShort)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.SAREXT(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.SAREXT(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.SAREXT(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInStartValue | number | 否 |
|
optInOffsetOnReverse | number | 否 |
|
optInAccelerationInitLong | number | 否 |
|
optInAccelerationLong | number | 否 |
|
optInAccelerationMaxLong | number | 否 |
|
optInAccelerationInitShort | number | 否 |
|
optInAccelerationShort | number | 否 |
|
optInAccelerationMaxShort | number | 否 |
|
备注
SAREXT()函数在talib库文档中的描述为:SAREXT(Records[High,Low],Start Value = 0,Offset on Reverse = 0,AF Init Long = 0.02,AF Long = 0.02,AF Max Long = 0.2,AF Init Short = 0.02,AF Short = 0.02,AF Max Short = 0.2) = Array(outReal)
talib.SMA
talib.SMA()函数用于计算简单移动平均线(Simple Moving Average)。
talib.SMA(inReal)
talib.SMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.SMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.SMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.SMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
SMA()函数在talib库文档中的描述为:SMA(Records[Close],Time Period = 30) = Array(outReal)
talib.T3
talib.T3()函数用于计算三重指数移动平均线 (Triple Exponential Moving Average, T3)。
talib.T3(inReal)
talib.T3(inReal, optInTimePeriod)
talib.T3(inReal, optInTimePeriod, optInVFactor)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.T3(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.T3(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.T3(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInVFactor | number | 否 |
|
备注
T3()函数在talib库文档中的描述为:T3(Records[Close],Time Period = 5,Volume Factor = 0.7) = Array(outReal)
talib.TEMA
talib.TEMA()函数用于计算三重指数移动平均线(Triple Exponential Moving Average)。
talib.TEMA(inReal)
talib.TEMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TEMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TEMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TEMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
TEMA()函数在talib库文档中的描述为:TEMA(Records[Close],Time Period = 30) = Array(outReal)
talib.TRIMA
talib.TRIMA()函数用于计算三角移动平均线(Triangular Moving Average)。
talib.TRIMA(inReal)
talib.TRIMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TRIMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TRIMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TRIMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
TRIMA()函数在talib库文档中的描述为:TRIMA(Records[Close],Time Period = 30) = Array(outReal)
talib.WMA
talib.WMA()函数用于计算加权移动平均线(Weighted Moving Average)。
talib.WMA(inReal)
talib.WMA(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.WMA(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.WMA(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.WMA(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
WMA()函数在talib库文档中的描述为:WMA(Records[Close],Time Period = 30) = Array(outReal)
talib.LINEARREG
talib.LINEARREG()函数用于计算Linear Regression (线性回归)。
talib.LINEARREG(inReal)
talib.LINEARREG(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.LINEARREG(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.LINEARREG(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.LINEARREG(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
LINEARREG()函数在talib库文档中的描述为:LINEARREG(Records[Close],Time Period = 14) = Array(outReal)
talib.LINEARREG_ANGLE
talib.LINEARREG_ANGLE()函数用于计算线性回归角度(Linear Regression Angle)。
talib.LINEARREG_ANGLE(inReal)
talib.LINEARREG_ANGLE(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.LINEARREG_ANGLE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.LINEARREG_ANGLE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.LINEARREG_ANGLE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
LINEARREG_ANGLE()函数在talib库文档中的描述为:LINEARREG_ANGLE(Records[Close],Time Period = 14) = Array(outReal)
talib.LINEARREG_INTERCEPT
talib.LINEARREG_INTERCEPT()函数用于计算线性回归截距(Linear Regression Intercept)。
talib.LINEARREG_INTERCEPT(inReal)
talib.LINEARREG_INTERCEPT(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.LINEARREG_INTERCEPT(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.LINEARREG_INTERCEPT(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.LINEARREG_INTERCEPT(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
LINEARREG_INTERCEPT()函数在talib库文档中的描述为:LINEARREG_INTERCEPT(Records[Close],Time Period = 14) = Array(outReal)
talib.LINEARREG_SLOPE
talib.LINEARREG_SLOPE()函数用于计算线性回归斜率(Linear Regression Slope)。
talib.LINEARREG_SLOPE(inReal)
talib.LINEARREG_SLOPE(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.LINEARREG_SLOPE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.LINEARREG_SLOPE(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.LINEARREG_SLOPE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
LINEARREG_SLOPE()函数在talib库文档中的描述为:LINEARREG_SLOPE(Records[Close],Time Period = 14) = Array(outReal)
talib.STDDEV
talib.STDDEV()函数用于计算标准偏差(Standard Deviation)。
talib.STDDEV(inReal)
talib.STDDEV(inReal, optInTimePeriod)
talib.STDDEV(inReal, optInTimePeriod, optInNbDev)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.STDDEV(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.STDDEV(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.STDDEV(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInNbDev | number | 否 |
|
备注
STDDEV()函数在talib库文档中的描述为:STDDEV(Records[Close],Time Period = 5,Deviations = 1) = Array(outReal)
talib.TSF
talib.TSF()函数用于计算时间序列预测(Time Series Forecast)。
talib.TSF(inReal)
talib.TSF(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TSF(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TSF(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TSF(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
TSF()函数在talib库文档中的描述为:TSF(Records[Close],Time Period = 14) = Array(outReal)
talib.VAR
talib.VAR()函数用于计算方差(Variance)。
talib.VAR(inReal)
talib.VAR(inReal, optInTimePeriod)
talib.VAR(inReal, optInTimePeriod, optInNbDev)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.VAR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.VAR(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.VAR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInNbDev | number | 否 |
|
备注
VAR()函数在talib库文档中的描述为:VAR(Records[Close],Time Period = 5,Deviations = 1) = Array(outReal)
talib.ADX
talib.ADX()函数用于计算平均趋向指数(Average Directional Movement Index)。
talib.ADX(inPriceHLC)
talib.ADX(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ADX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ADX(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ADX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ADX()函数在talib库文档中的描述为:ADX(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.ADXR
talib.ADXR()函数用于计算平均趋向指数评级(Average Directional Movement Index Rating)。
talib.ADXR(inPriceHLC)
talib.ADXR(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ADXR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ADXR(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ADXR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ADXR()函数在talib库文档中的描述为:ADXR(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.APO
talib.APO()函数用于计算绝对价格振荡指标(Absolute Price Oscillator)。
talib.APO(inReal)
talib.APO(inReal, optInFastPeriod)
talib.APO(inReal, optInFastPeriod, optInSlowPeriod)
talib.APO(inReal, optInFastPeriod, optInSlowPeriod, optInMAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.APO(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.APO(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.APO(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInSlowPeriod | number | 否 |
|
optInMAType | number | 否 |
|
备注
APO()函数在talib库文档中的描述为:APO(Records[Close],Fast Period = 12,Slow Period = 26,MA Type = 0) = Array(outReal)
talib.AROON
talib.AROON()函数用于计算Aroon(阿隆指标)。
talib.AROON(inPriceHL)
talib.AROON(inPriceHL, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.AROON(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.AROON(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.AROON(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
AROON()函数在talib库文档中的描述为:AROON(Records[High,Low],Time Period = 14) = [Array(outAroonDown),Array(outAroonUp)]
talib.AROONOSC
talib.AROONOSC()函数用于计算Aroon Oscillator(阿隆震荡指标)。
talib.AROONOSC(inPriceHL)
talib.AROONOSC(inPriceHL, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.AROONOSC(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.AROONOSC(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.AROONOSC(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
AROONOSC()函数在talib库文档中的描述为:AROONOSC(Records[High,Low],Time Period = 14) = Array(outReal)
talib.BOP
talib.BOP()函数用于计算Balance Of Power (均势指标)。
talib.BOP(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.BOP(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.BOP(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.BOP(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
BOP()函数在talib库文档中的描述为:BOP(Records[Open,High,Low,Close]) = Array(outReal)
talib.CCI
talib.CCI()函数用于计算商品通道指数(Commodity Channel Index)。
talib.CCI(inPriceHLC)
talib.CCI(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CCI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CCI(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CCI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
CCI()函数在talib库文档中的描述为:CCI(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.CMO
talib.CMO()函数用于计算钱德动量摆动指标(Chande Momentum Oscillator)。
talib.CMO(inReal)
talib.CMO(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.CMO(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.CMO(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.CMO(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
CMO()函数在talib库文档中的描述为:CMO(Records[Close],Time Period = 14) = Array(outReal)
talib.DX
talib.DX()函数用于计算方向性运动指数(Directional Movement Index)。
talib.DX(inPriceHLC)
talib.DX(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.DX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.DX(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.DX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
DX()函数在talib库文档中的描述为:DX(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.MACD
talib.MACD()函数用于计算MACD(移动平均收敛/发散指标)。
talib.MACD(inReal)
talib.MACD(inReal, optInFastPeriod)
talib.MACD(inReal, optInFastPeriod, optInSlowPeriod)
talib.MACD(inReal, optInFastPeriod, optInSlowPeriod, optInSignalPeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MACD(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MACD(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MACD(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInSlowPeriod | number | 否 |
|
optInSignalPeriod | number | 否 |
|
备注
MACD()函数在talib库文档中的描述为:MACD(Records[Close],Fast Period = 12,Slow Period = 26,Signal Period = 9) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]
talib.MACDEXT
talib.MACDEXT()函数用于计算可控移动平均类型的MACD指标(MACD with controllable MA type)。
talib.MACDEXT(inReal)
talib.MACDEXT(inReal, optInFastPeriod)
talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType)
talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod)
talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType)
talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType, optInSignalPeriod)
talib.MACDEXT(inReal, optInFastPeriod, optInFastMAType, optInSlowPeriod, optInSlowMAType, optInSignalPeriod, optInSignalMAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MACDEXT(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MACDEXT(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MACDEXT(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInFastMAType | number | 否 |
|
optInSlowPeriod | number | 否 |
|
optInSlowMAType | number | 否 |
|
optInSignalPeriod | number | 否 |
|
optInSignalMAType | number | 否 |
|
备注
MACDEXT()函数在talib库文档中的描述为:MACDEXT(Records[Close],Fast Period = 12,Fast MA = 0,Slow Period = 26,Slow MA = 0,Signal Period = 9,Signal MA = 0) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]
talib.MACDFIX
talib.MACDFIX()函数用于计算移动平均收敛/发散固定周期指标 (Moving Average Convergence/Divergence Fix 12/26)。
talib.MACDFIX(inReal)
talib.MACDFIX(inReal, optInSignalPeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MACDFIX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MACDFIX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MACDFIX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInSignalPeriod | number | 否 |
|
备注
MACDFIX()函数在talib库文档中的描述为:MACDFIX(Records[Close],Signal Period = 9) = [Array(outMACD),Array(outMACDSignal),Array(outMACDHist)]
talib.MFI
talib.MFI()函数用于计算资金流量指数(Money Flow Index)。
talib.MFI(inPriceHLCV)
talib.MFI(inPriceHLCV, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MFI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MFI(records.High, records.Low, records.Close, records.Volume)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MFI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLCV |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MFI()函数在talib库文档中的描述为:MFI(Records[High,Low,Close,Volume],Time Period = 14) = Array(outReal)
talib.MINUS_DI
talib.MINUS_DI()函数用于计算负向指标(Minus Directional Indicator)。
talib.MINUS_DI(inPriceHLC)
talib.MINUS_DI(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MINUS_DI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MINUS_DI(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MINUS_DI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MINUS_DI()函数在talib库文档中的描述为:MINUS_DI(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.MINUS_DM
talib.MINUS_DM()函数用于计算负向动向指标(Minus Directional Movement)。
talib.MINUS_DM(inPriceHL)
talib.MINUS_DM(inPriceHL, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MINUS_DM(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MINUS_DM(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MINUS_DM(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MINUS_DM()函数在talib库文档中的描述为:MINUS_DM(Records[High,Low],Time Period = 14) = Array(outReal)
talib.MOM
talib.MOM()函数用于计算动量指标(Momentum)。
talib.MOM(inReal)
talib.MOM(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MOM(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MOM(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MOM(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
MOM()函数在talib库文档中的描述为:MOM(Records[Close],Time Period = 10) = Array(outReal)
talib.PLUS_DI
talib.PLUS_DI()函数用于计算Plus Directional Indicator(正向动向指标)。
talib.PLUS_DI(inPriceHLC)
talib.PLUS_DI(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.PLUS_DI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.PLUS_DI(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.PLUS_DI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
PLUS_DI()函数在talib库文档中的描述为:PLUS_DI(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.PLUS_DM
talib.PLUS_DM()函数用于计算正向动向指标(Plus Directional Movement)。
talib.PLUS_DM(inPriceHL)
talib.PLUS_DM(inPriceHL, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.PLUS_DM(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.PLUS_DM(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.PLUS_DM(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
PLUS_DM()函数在talib库文档中的描述为:PLUS_DM(Records[High,Low],Time Period = 14) = Array(outReal)
talib.PPO
talib.PPO()函数用于计算百分比价格振荡器(Percentage Price Oscillator)。
talib.PPO(inReal)
talib.PPO(inReal, optInFastPeriod)
talib.PPO(inReal, optInFastPeriod, optInSlowPeriod)
talib.PPO(inReal, optInFastPeriod, optInSlowPeriod, optInMAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.PPO(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.PPO(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.PPO(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInFastPeriod | number | 否 |
|
optInSlowPeriod | number | 否 |
|
optInMAType | number | 否 |
|
备注
PPO()函数在talib库文档中的描述为:PPO(Records[Close],Fast Period = 12,Slow Period = 26,MA Type = 0) = Array(outReal)
talib.ROC
talib.ROC()函数用于计算变动率指标(Rate of change: ((price/prevPrice)-1)*100)。
talib.ROC(inReal)
talib.ROC(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ROC(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ROC(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ROC(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ROC()函数在talib库文档中的描述为:ROC(Records[Close],Time Period = 10) = Array(outReal)
talib.ROCP
talib.ROCP()函数用于计算价格变化率百分比:(price-prevPrice)/prevPrice (Rate of change Percentage)。
talib.ROCP(inReal)
talib.ROCP(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ROCP(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ROCP(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ROCP(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ROCP()函数在talib库文档中的描述为:ROCP(Records[Close],Time Period = 10) = Array(outReal)
talib.ROCR
talib.ROCR()函数用于计算价格变化率比值(Rate of change ratio: price/prevPrice)。
talib.ROCR(inReal)
talib.ROCR(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ROCR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ROCR(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ROCR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ROCR()函数在talib库文档中的描述为:ROCR(Records[Close],Time Period = 10) = Array(outReal)
talib.ROCR100
talib.ROCR100()函数用于计算*价格变化率(100倍比例):(price/prevPrice)100。
talib.ROCR100(inReal)
talib.ROCR100(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ROCR100(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ROCR100(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ROCR100(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
ROCR100()函数在talib库文档中的描述为:ROCR100(Records[Close],Time Period = 10) = Array(outReal)
talib.RSI
talib.RSI()函数用于计算相对强弱指标(Relative Strength Index)。
talib.RSI(inReal)
talib.RSI(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.RSI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.RSI(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.RSI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
RSI()函数在talib库文档中的描述为:RSI(Records[Close],Time Period = 14) = Array(outReal)
talib.STOCH
talib.STOCH()函数用于计算随机指标(STOCH指标)。
talib.STOCH(inPriceHLC)
talib.STOCH(inPriceHLC, optInFastK_Period)
talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period)
talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType)
talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType, optInSlowD_Period)
talib.STOCH(inPriceHLC, optInFastK_Period, optInSlowK_Period, optInSlowK_MAType, optInSlowD_Period, optInSlowD_MAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.STOCH(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.STOCH(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.STOCH(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInFastK_Period | number | 否 |
|
optInSlowK_Period | number | 否 |
|
optInSlowK_MAType | number | 否 |
|
optInSlowD_Period | number | 否 |
|
optInSlowD_MAType | number | 否 |
|
备注
STOCH()函数在talib库文档中的描述为:STOCH(Records[High,Low,Close],Fast-K Period = 5,Slow-K Period = 3,Slow-K MA = 0,Slow-D Period = 3,Slow-D MA = 0) = [Array(outSlowK),Array(outSlowD)]
talib.STOCHF
talib.STOCHF()函数用于计算快速随机指标(Stochastic Fast)。
talib.STOCHF(inPriceHLC)
talib.STOCHF(inPriceHLC, optInFastK_Period)
talib.STOCHF(inPriceHLC, optInFastK_Period, optInFastD_Period)
talib.STOCHF(inPriceHLC, optInFastK_Period, optInFastD_Period, optInFastD_MAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.STOCHF(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.STOCHF(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.STOCHF(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInFastK_Period | number | 否 |
|
optInFastD_Period | number | 否 |
|
optInFastD_MAType | number | 否 |
|
备注
STOCHF()函数在talib库文档中的描述为:STOCHF(Records[High,Low,Close],Fast-K Period = 5,Fast-D Period = 3,Fast-D MA = 0) = [Array(outFastK),Array(outFastD)]
talib.STOCHRSI
talib.STOCHRSI()函数用于计算Stochastic Relative Strength Index(随机相对强弱指数)。
talib.STOCHRSI(inReal)
talib.STOCHRSI(inReal, optInTimePeriod)
talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period)
talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period, optInFastD_Period)
talib.STOCHRSI(inReal, optInTimePeriod, optInFastK_Period, optInFastD_Period, optInFastD_MAType)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.STOCHRSI(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.STOCHRSI(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.STOCHRSI(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
optInFastK_Period | number | 否 |
|
optInFastD_Period | number | 否 |
|
optInFastD_MAType | number | 否 |
|
备注
STOCHRSI()函数在talib库文档中的描述为:STOCHRSI(Records[Close],Time Period = 14,Fast-K Period = 5,Fast-D Period = 3,Fast-D MA = 0) = [Array(outFastK),Array(outFastD)]
talib.TRIX
talib.TRIX()函数用于计算三重指数平滑移动平均线的1日变化率(1-day Rate-Of-Change of a Triple Smooth EMA)。
talib.TRIX(inReal)
talib.TRIX(inReal, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TRIX(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TRIX(records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TRIX(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inReal |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
TRIX()函数在talib库文档中的描述为:TRIX(Records[Close],Time Period = 30) = Array(outReal)
talib.ULTOSC
talib.ULTOSC()函数用于计算Ultimate Oscillator(终极振荡指标)。
talib.ULTOSC(inPriceHLC)
talib.ULTOSC(inPriceHLC, optInTimePeriod1)
talib.ULTOSC(inPriceHLC, optInTimePeriod1, optInTimePeriod2)
talib.ULTOSC(inPriceHLC, optInTimePeriod1, optInTimePeriod2, optInTimePeriod3)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.ULTOSC(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.ULTOSC(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.ULTOSC(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod1 | number | 否 |
|
optInTimePeriod2 | number | 否 |
|
optInTimePeriod3 | number | 否 |
|
备注
ULTOSC()函数在talib库文档中的描述为:ULTOSC(Records[High,Low,Close],First Period = 7,Second Period = 14,Third Period = 28) = Array(outReal)
talib.WILLR
talib.WILLR()函数用于计算Williams' %R(威廉指标)。
talib.WILLR(inPriceHLC)
talib.WILLR(inPriceHLC, optInTimePeriod)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.WILLR(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.WILLR(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.WILLR(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
optInTimePeriod | number | 否 |
|
备注
WILLR()函数在talib库文档中的描述为:WILLR(Records[High,Low,Close],Time Period = 14) = Array(outReal)
talib.AVGPRICE
talib.AVGPRICE()函数用于计算平均价格(Average Price)。
talib.AVGPRICE(inPriceOHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.AVGPRICE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.AVGPRICE(records.Open, records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.AVGPRICE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceOHLC |
| 是 |
|
备注
AVGPRICE()函数在talib库文档中的描述为:AVGPRICE(Records[Open,High,Low,Close]) = Array(outReal)
talib.MEDPRICE
talib.MEDPRICE()函数用于计算Median Price (中位数价格)。
talib.MEDPRICE(inPriceHL)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.MEDPRICE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.MEDPRICE(records.High, records.Low)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.MEDPRICE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHL |
| 是 |
|
备注
MEDPRICE()函数在talib库文档中的描述为:MEDPRICE(Records[High,Low]) = Array(outReal)
talib.TYPPRICE
talib.TYPPRICE()函数用于计算典型价格(Typical Price)。
talib.TYPPRICE(inPriceHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.TYPPRICE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.TYPPRICE(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.TYPPRICE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
备注
TYPPRICE()函数在talib库文档中的描述为:TYPPRICE(Records[High,Low,Close]) = Array(outReal)
talib.WCLPRICE
talib.WCLPRICE()函数用于计算加权收盘价(Weighted Close Price)。
talib.WCLPRICE(inPriceHLC)示例
javascript
function main() {
var records = exchange.GetRecords()
var ret = talib.WCLPRICE(records)
Log(ret)
}
python
import talib
def main():
records = exchange.GetRecords()
ret = talib.WCLPRICE(records.High, records.Low, records.Close)
Log(ret)
c++
void main() {
auto records = exchange.GetRecords();
auto ret = talib.WCLPRICE(records);
Log(ret);
}返回值
| 类型 | 描述 |
array |
|
参数
| 名称 | 类型 | 必填 | 描述 |
inPriceHLC |
| 是 |
|
备注
WCLPRICE()函数在talib库文档中的描述为:WCLPRICE(Records[High,Low,Close]) = Array(outReal)
OS
优宽量化交易平台支持文件读写操作,os库提供了完整的文件系统操作接口,帮助用户在策略开发中进行数据持久化、配置管理和日志记录等操作。
需要注意的是,该功能仅支持JavaScript语言策略。
os库支持:文件对象、文件列表对象、文件信息对象。
| 对象 | 说明 | 备注 |
|---|---|---|
| 文件对象:File | 提供文件读写、定位等操作。 | 通过os.open()获取,使用完毕需调用close()释放资源。 |
| 文件列表对象:ListFilesResult | 用于记录目录列表信息。 | 支持通配符匹配模式,由os.listFiles()函数返回。 |
| 文件信息对象:FileStat | 文件统计信息。 | 由os.stat()函数返回。 |
支持实盘、回测系统。
- 实盘环境:
实盘默认目录为托管者目录下实盘数据库文件同级目录的files文件夹中,即:/logs/storage/xxx/files,其中xxx为实盘Id,托管者程序(robot)与logs在同一级目录。 - 回测系统环境:
回测系统是一个沙盒环境,系统模拟一个文件目录,默认目录为:/logs/storage/1/files。
当回测结束时,创建的文件内容将被清除。
os
os库为优宽量化交易平台提供完整的文件系统操作接口。
open
以指定模式打开文件。
open(filename)
open(filename, mode)示例
创建文件,写入数据后再读取。
javascript
function main() {
let fileHandle = os.open("output.txt", "w+")
if (!fileHandle) {
Log("Failed to open file")
return
}
let bytesWritten = fileHandle.write("Hello YouQuant!")
Log("Bytes written:", bytesWritten) // Bytes written: 15
fileHandle.seek(0, 0)
let fileContent = fileHandle.read()
Log("File content read:", fileContent) // File content read: Hello YouQuant!
fileHandle.close()
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件名称。参数 |
mode | string | 否 | 指定文件的打开模式。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
文件打开模式:
-
r: read(只读,文件必须存在) -
w: write(只写,文件不存在则创建,存在则清空内容) -
a: append(追加写入,文件不存在则创建,存在则写入到末尾) -
+: 在 r/w/a 后加 + 表示既可以读也可以写(例如 "r+", "w+", "a+") -
b: binary(二进制模式,常用于 Windows 区分文本/二进制文件,例如 "rb", "wb")
文件的打开/创建位于实盘数据库文件目录(xxx.db3,其中xxx为实盘Id)下的files文件夹中。
fgets
一次性读取整个文件的内容。
fgets(filename)示例
读取配置文件的内容。
javascript
function main() {
// 先创建、写入文件
// let fileHandle = os.open("config.json", "w+")
// if (!fileHandle) {
// Log("Failed to open file")
// return
// }
// let objJson = {"name": "tom", "age": 18}
// fileHandle.write(JSON.stringify(objJson))
// fileHandle.close()
let content = os.fgets("config.json")
Log("Config content:", content) // Config content: {"name":"tom","age":18}
}返回值
| 类型 | 描述 |
string | 返回文件的完整内容。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径,包含要读取的文件名。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
适用于小文件的快速读取,将整个文件内容一次性加载到内存中。
如果文件不存在,fgets()函数会抛出错误:InternalError: failed to open file: openat config.json: no such file or directory at main。
fputs
向文件写入内容。
fputs(filename, content)
fputs(filename, content, append)示例
保存策略配置到文件。
javascript
function main() {
let config = '{"strategy": "MA", "period": 20}'
let bytesWritten = os.fputs("strategy_config.json", config)
Log("Bytes written:", bytesWritten) // Bytes written: 32
Log(`os.fgets("strategy_config.json"):`, os.fgets("strategy_config.json")) // os.fgets("strategy_config.json"): {"strategy": "MA", "period": 20}
// 追加日志信息
let logInfo = "\n[" + new Date().toISOString() + "] Config saved"
os.fputs("strategy_config.json", logInfo, true)
Log(`os.fgets("strategy_config.json"):`, os.fgets("strategy_config.json")) // os.fgets("strategy_config.json"): {"strategy": "MA", "period": 20} [2025-09-08T07:20:30.563Z] Config saved
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
content | string | 是 | 要写入的内容。 |
append | bool | 否 | 是否以追加模式写入,默认为 false(覆盖模式)。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
便捷的文件写入方法,默认覆盖文件内容。设置 append 为 true 可追加到文件末尾。
mmap
内存映射文件,返回文件的二进制数据。
mmap(filename)示例
映射文件的二进制数据。
javascript
function ab2str(buf) {
let arr = new Uint8Array(buf)
return String.fromCharCode.apply(null, arr)
}
function main() {
let buffer = os.mmap("strategyConfig/testData.txt")
Log("File size in bytes:", buffer.byteLength)
let arr = Array.from(new Uint8Array(buffer))
Log("arr:", arr)
Log("ab2str(buffer):", ab2str(buffer)) // ab2str(buffer): Hello YouQuant!
}返回值
| 类型 | 描述 |
ArrayBuffer | 返回文件内容的二进制数据。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
适用于大文件的高效读取和处理,将文件映射到内存中并以ArrayBuffer形式返回。
getRootDir
获取文件操作的根目录路径。
getRootDir()示例
获取并显示根目录路径。
javascript
function main() {
let rootDir = os.getRootDir()
Log("Root directory:", rootDir)
}返回值
| 类型 | 描述 |
string | 返回根目录的路径。 |
参考
listFiles
列出指定目录中的文件和子目录。
listFiles()
listFiles(pattern)示例
列出匹配的文件和目录。
javascript
function main() {
// 列出所有json文件
let result = os.listFiles("*.json")
Log("result:", result)
// 列出所有内容
let allFiles = os.listFiles()
Log("allFiles:", allFiles)
}返回值
| 类型 | 描述 |
ListFilesResult 对象 | 返回包含 - files:匹配到的文件名数组。 - dirs:当前目录下的子目录名数组。 |
参数
| 名称 | 类型 | 必填 | 描述 |
pattern | string | 否 | 可选的匹配模式,支持通配符(如 .txt、data_.json),可以指定目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
不指定 pattern 参数时,列出当前目录(../files)下的所有文件和子目录。
exists
检查文件或目录是否存在。
exists(filename)示例
检查文件或路径是否存在。
javascript
function main() {
Log(`os.exists("./strategyConfig"):`, os.exists("./strategyConfig")) // os.exists("./strategyConfig"): true
Log(`os.exists("./strategyConfig/testData.txt"):`, os.exists("./strategyConfig/testData.txt")) // os.exists("./strategyConfig/testData.txt"): true
// Log(`os.exists("/strategyConfig"):`, os.exists("/strategyConfig")) // InternalError: invalid filename: path traversal or absolute path not allowed at main
Log(`os.exists("test_1.txt"):`, os.exists("test_1.txt")) // os.exists("test_1.txt"): true
Log(`os.exists("test_2.txt"):`, os.exists("test_2.txt")) // os.exists("test_2.txt"): false
}返回值
| 类型 | 描述 |
bool | 如果存在则返回true,否则返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件或目录的路径。 |
参考
remove
删除指定文件。
remove(filename)示例
删除文件示例。
javascript
function main() {
let tempFile = "test_1.txt"
if (os.exists(tempFile)) {
let success = os.remove(tempFile)
Log("Temp file deleted:", success)
}
}返回值
| 类型 | 描述 |
bool | 删除成功返回true,失败返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 要删除的文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此函数仅支持删除文件,不支持删除目录。如需删除目录,请使用rmdir()函数。
mkdir
创建目录。
mkdir(dirname)示例
创建数据存储目录,创建文件并写入数据。
javascript
function main() {
let success = os.mkdir("data/backtest/results")
Log("Directory created:", success)
if (success) {
os.fputs("data/backtest/results/summary.txt", "Backtest completed")
}
}返回值
| 类型 | 描述 |
bool | 创建成功返回true,失败返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
dirname | string | 是 | 要创建的目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
支持递归创建多级目录。如果父目录不存在,会自动创建。
rmdir
删除指定目录及其包含的所有内容。
rmdir(dirname)示例
删除指定目录及其所有内容。
javascript
function main() {
let tempDir = "data"
if (os.exists(tempDir)) {
let success = os.rmdir(tempDir)
Log("directory removed:", success)
}
}返回值
| 类型 | 描述 |
bool | 删除成功返回 true,失败返回 false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
dirname | string | 是 | 需要删除的目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此操作将永久删除目录及其所有内容,请谨慎使用。
rename
重命名文件或将文件移动到新位置。
rename(oldName, newName)示例
重命名文件并将其移动到其他目录。
javascript
function main() {
let oldFileName = "output.txt"
let newFileName = "outputFiles/" + new Date().getTime() + "output.txt"
// let retRename = os.rename(oldFileName, newFileName)
// Log("retRename:", retRename) // InternalError: failed to rename file: renameat output.txt outputFiles/1757322073139output.txt: no such file or directory at main
os.mkdir("outputFiles")
retRename = os.rename(oldFileName, newFileName)
Log("retRename:", retRename) // retRename: true
}返回值
| 类型 | 描述 |
bool | 操作成功时返回 true,失败时返回 false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
oldName | string | 是 | 原始文件名或文件路径。 |
newName | string | 是 | 目标文件名或文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此函数可用于重命名文件或将文件移动到不同的目录。如果目标路径中的目录不存在,操作将失败。
stat
获取文件的详细统计信息。
stat(filename)示例
获取文件信息并检查文件大小。
javascript
function main() {
if (os.exists("strategyConfig/testData.txt")) {
let stat = os.stat("strategyConfig/testData.txt") // stat: {"size":10,"mode":420,"mtime":1757312981796,"atime":1757312981796,"ctime":1757312981796}
Log("stat:", stat)
}
}返回值
| 类型 | 描述 |
FileStat 对象 | 返回包含文件统计信息的对象。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
返回的FileStat对象包含以下字段:
-
size: 文件大小(字节)。
-
mode: 文件权限模式。
-
mtime: 最后修改时间(时间戳)。
-
atime: 最后访问时间(时间戳)。
-
ctime: 创建时间(时间戳)。
exit
退出程序。
exit()
exit(status)示例
检查条件后退出程序。
javascript
function main() {
if (!os.exists("required_config.json")) {
Log("Required configuration file not found!")
os.exit(1) // 异常退出
}
Log("Configuration found, continuing...")
// 正常的策略逻辑...
}返回值
| 类型 | 描述 |
never | 此函数不会返回值,程序将直接终止执行。 |
参数
| 名称 | 类型 | 必填 | 描述 |
status | number | 否 | 可选的退出状态码,默认值为0。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
立即终止程序执行。状态码0表示正常退出,非零值表示异常退出(实盘中将显示为错误)。
File
文件对象,提供文件读写、定位等操作。
close
关闭文件并释放相关资源。
close()示例
标准的文件操作流程示例。
javascript
function main() {
let file = os.open("data.txt", "w")
file.write("Hello YouQuant!")
file.close() // 必须关闭文件
}参考
备注
使用完文件对象后必须调用此方法以释放系统资源。
puts
向文件写入一个或多个字符串。
puts(data1, data2, ...dataN)示例
向文件写入多个字符串。
javascript
function main() {
let file = os.open("output.txt", "w+")
let bytes = file.puts("Hello", " ", "World", "!")
Log("Bytes written:", bytes) // Bytes written: 12
file.seek(0, 0)
let data = file.read()
Log("data:", data) // If using os.open("output.txt", "w") may result in data being undefined
// data: Hello World!
// file.puts() // error: puts requires at least 1 argument at main
file.puts(", Hello YouQuant!")
file.seek(0, 0)
data = file.read()
Log("data:", data) // data: Hello World!, Hello YouQuant!
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | string | 是 | 要写入的字符串数据,可传入多个参数。 |
参考
备注
可一次写入多个字符串参数,将按顺序连接后写入。
printf
格式化写入数据到文件。
printf(format)
printf(format, arg1, arg2, ...argN)示例
格式化写入交易数据。
javascript
function main() {
let file = os.open("trade_log.txt", "w+")
let price = 100.25
let volume = 1000
let bytes = file.printf("Price: %.2f, Volume: %d\n", price, volume)
Log("Formatted bytes written:", bytes)
file.seek(0, 0)
let data = file.read()
Log("data:", data) // data: Price: 100.25, Volume: 1000
// file.printf("| Price: %.2f, Volume: %d\n") // "| Price: %!f(MISSING), Volume: %!d(MISSING)"
// file.seek(0, 0)
// data = file.read()
// Log("data:", data)
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
format | string | 是 | 格式化字符串。 |
args | any (平台支持的任意类型) | 否 | 格式化参数。 |
参考
flush
刷新文件缓冲区,确保数据立即写入磁盘。
flush()示例
实时写入关键日志数据。
javascript
function main() {
let logFile = os.open("critical.log", "a")
logFile.printf("[%s] Critical event occurred\n", new Date().toISOString()) // [2025-09-09T03:15:43.895Z] Critical event occurred
logFile.flush() // 立即刷新缓冲区并写入磁盘
// 继续其他操作...
logFile.close()
}参考
tell
获取文件指针的当前位置。
tell()示例
记录文件操作过程中的位置。
javascript
function main() {
let file = os.open("data.txt", "r+")
Log("Initial position:", file.tell()) // Initial position: 0
file.write("Hello")
Log("After write position:", file.tell()) // After write position: 5
file.close()
}返回值
| 类型 | 描述 |
number | 返回文件指针的当前位置(以字节为单位的偏移量)。 |
参考
备注
返回文件指针相对于文件起始位置的字节偏移量。
seek
将文件指针移动到指定位置。
seek(offset, whence)示例
倒序读取字符。
javascript
function main() {
let str = "Hello YouQuant!"
let file = os.open("data.txt", "w+")
file.write(str)
// If i > str.length: will throw InternalError: seek .../xxx/data.txt: invalid argument at main
for (let i = 1; i <= str.length; i++) {
file.seek(-i, 2)
let data = file.read(1)
Log("i:", i, ", data:", data)
}
file.close()
}返回值
| 类型 | 描述 |
number | 返回文件指针的新位置。 |
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 是 | 偏移量(以字节为单位)。 |
whence | number | 是 | 基准位置:0=文件开头,1=当前位置,2=文件末尾。 |
参考
备注
用于定位文件指针,offset参数可以为负数(表示向前移动)。
eof
检查文件指针是否已到达文件末尾。
eof()示例
逐行读取文件直至结束。
javascript
function main() {
let file = os.open("data.txt", "r")
let lineCount = 0
while (!file.eof()) {
let line = file.getline()
if (line) {
lineCount++
Log("Line", lineCount + ":", line)
}
}
Log("Total lines:", lineCount)
file.close()
}返回值
| 类型 | 描述 |
bool | 如果已到达文件末尾返回true,否则返回false。 |
参考
备注
用于在读取文件时判断是否已读取完所有内容。
read
从文件中读取数据。
read()
read(size)示例
分块读取文件内容。
javascript
function main() {
let file = os.open("data.txt", "r")
// data.txt
// This is a test line: Line 1.
// This is a test line: Line 2.
// ...
let chunkSize = 29
let totalBytes = 0
while (!file.eof()) {
let chunk = file.read(chunkSize)
if (chunk) {
totalBytes += chunk.length || chunk.byteLength
Log("Read chunk, total bytes so far:", totalBytes, ", chunk:", chunk)
}
}
file.close()
}返回值
| 类型 | 描述 |
string / ArrayBuffer / undefined | 返回读取的内容。当到达文件末尾时返回 |
参数
| 名称 | 类型 | 必填 | 描述 |
size | number | 否 | 要读取的字节数。如果不指定,则读取文件中剩余的所有内容。 |
参考
备注
可以读取指定字节数的内容或文件中剩余的全部内容。返回类型可能是字符串或ArrayBuffer。
write
向文件写入字符串数据。
write(data)示例
写入交易记录
javascript
function main() {
let file = os.open("trades.log", "a")
let timestamp = new Date().toISOString()
let tradeInfo = `${timestamp},BUY,50000,1\n`
let bytes = file.write(tradeInfo)
Log("Trade record written, bytes:", bytes)
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | string | 是 | 要写入的字符串数据。 |
参考
备注
将字符串数据写入文件的当前位置。
getline
从文件中读取下一行内容。
getline()示例
逐行读取文件直至结束。
javascript
function main() {
let file = os.open("data.txt", "r")
let lineCount = 0
while (!file.eof()) {
let line = file.getline()
if (line) {
lineCount++
Log("Line", lineCount + ":", line)
}
}
Log("Total lines:", lineCount)
file.close()
}返回值
| 类型 | 描述 |
string / undefined | 返回下一行内容,到达文件末尾时返回 |
参考
备注
按行顺序读取文件内容。
ListFilesResult
文件列表对象,用于记录目录列表信息。该对象包含两个数组属性:files(文件列表)和dirs(目录列表)。
参考
备注
ListFilesResult对象结构:
javascript
{
files: string[], // 搜索到的文件名数组
dirs: string[] // 当前目录下的子目录名数组
}
此对象由os.listFiles()函数返回。