输入/搜索内容
入门
欢迎使用发明者量化交易平台
快速开始
密钥安全性
平台基础
账号与计费
实盘计费与充值
子账号
交易所
通用协议
本地凭据文件
交易所特殊说明
证券与期货
加密货币
托管者
策略库
实盘
编写策略
开发工具
回测系统
进阶专题
数据与研究
对外接口

平台支持用Rust编写策略。Rust 策略先编译再运行:回测时由平台服务器编译,在浏览器端的回测系统中运行;实盘时编译通过后在托管者上运行。策略编辑器为 Rust 集成了rust-analyzer,提供代码补全与实时诊断。

策略结构

策略代码只需要一个fn main()。平台 API(exchange、exchanges、TA、Log!、_C!等)已经自动导入,不需要写use或mod声明。

可选的fn init()、fn onexit()由托管者自动调用,定义即可,不需要注册:init()在main()之前执行;onexit()在main()正常返回、实盘被停止、策略panic时都会执行。Rust 不支持onerror()。详见 策略结构。

rust
fn init() { Log!("初始化"); } fn main() { // 可能失败的 API 返回 Result<T>,_C! 宏在失败时重试,直到调用成功 let ticker = _C!(exchange.GetTicker(None)); Log!("Last:", ticker.Last); } fn onexit() { Log!("策略退出,执行扫尾处理"); }

日志等部分功能以宏的形式提供(注意感叹号):Log!()、LogStatus!()、Panic!()、_G!()、_C!();LogProfit()、Sleep()、_D()、_N()、HttpQuery()等是普通函数。

参数类型

界面参数以同名的全局常量注入策略,只能读取,不能在代码中修改(需要变化的值请复制到局部变量)。类型由参数种类决定:

参数种类Rust 类型
数字型f64
布尔型bool
字符串&str
下拉框(单选)f64(选项索引);选项绑定了字符串数据时为&str
下拉框(多选)&[i64]、&[f64]或&[&str];选项值类型混杂时为 JSON 文本&str
加密串&str或Decrypted(可解引用为str)
  • 整数用途需要自行转换,例如let n = Period as usize;。
  • 选填参数没有填写时为该类型的零值:0.0、""、false,多选下拉框为空。
  • 加密串参数在服务端不能预先解密时(例如私有托管者),注入为static的Decrypted类型,第一次使用时才解密。它实现了Display,可以直接用于format!;传给Log!或其它需要&str的地方写&*参数名(对&str类型的参数同样适用):
rust
fn main() { let key: &str = &*ApiKey; // ApiKey 为加密串参数 Log!("key length:", key.len()); }
  • 参数名与代码中的其它名字冲突时,可以用args::参数名引用参数。

错误与返回值

可能失败的 API 调用返回Result<T>,用 Rust 惯用的方式处理(JavaScript 中失败返回null):

rust
fn main() { // 方式一:模式匹配 if let Ok(ticker) = exchange.GetTicker(None) { Log!(ticker); } // 方式二:_C! 宏在失败时重试,直到调用成功 let ticker = _C!(exchange.GetTicker(None)); Log!(ticker); }

可选参数(例如GetTicker的symbol参数)不传时用None占位,传值时直接传入,例如exchange.GetTicker("BTC_USDT")。

JSON

平台 API 返回的原始 JSON 文本(例如exchange.IO()的返回值、各结构体的Info字段)用内置的JSONParse()解析,得到Option<JsonValue>;用v["key"]、v[0]取子节点,用as_f64()、as_str()、as_bool()等方法取值。JsonValue实现了Display,v.to_string()或format!("{}", v)得到紧凑的 JSON 文本。SDK 没有提供构造 JSON 的便捷接口,生成 JSON 文本可以用format!拼接,或者引入serde_json。

第三方 crate

策略源码是唯一的代码文件(没有单独的Cargo.toml)。在源码最顶部用---包裹的 frontmatter 声明依赖,构建时合并进Cargo.toml:

rust
--- [dependencies] serde_json = "1" --- /*backtest start: 2024-01-01 00:00:00 end: 2024-02-01 00:00:00 period: 1h */ fn main() { let v: serde_json::Value = serde_json::from_str(r#"{"a": 1}"#).unwrap(); Log!("a:", v["a"].to_string()); }
  • frontmatter 必须在源码开头,前面只能有空行;/*backtest ... */回测配置块要放在 frontmatter 结束的---之后。策略中还没有回测配置块时,「保存回测设置」会把配置块插入到源码最前面,这时需要把它移到 frontmatter 之后(之后再保存会在原位置更新)。
  • 策略和它引用的模板类库中,依赖块只能写在其中一处,两处都写会编译失败。
  • 编译环境中没有系统 OpenSSL,需要 TLS 的 crate(HTTP/WebSocket 客户端等)请选用纯 Rust 实现的rustls(例如tokio-tungstenite开启rustls-tls-webpki-roots特性),避免依赖native-tls/openssl-sys;WebSocket 连接优先使用内置的 Dial 函数,不需要第三方 crate。

内置库

Rust 策略可以使用TA指标库,不支持talib,见 内置库。