Rust Strategy Development Guide
- The difference between writing strategies in
Rustand inJavaScriptlies mainly in the different form of data returned by the platform API functions. Take theexchange.GetTicker()function as an example:
-
JavaScript
exchange.GetTicker()returns an object on a successful call; if the call fails (e.g., due to exchange server issues, network issues, etc.), it returnsnull.javascriptfunction main() { var ticker = exchange.GetTicker() // Check whether the exchange.GetTicker call failed (returns null) if (ticker) { Log(ticker) } } -
Rust
API calls that may fail uniformly return theResult<T>type, and errors can be handled in idiomatic Rust style:rustfn main() { // Approach 1: pattern matching to check whether the exchange.GetTicker call succeeded if let Ok(ticker) = exchange.GetTicker(None) { Log!(ticker); } // Approach 2: use the _C! macro to retry automatically until the call succeeds let ticker = _C!(exchange.GetTicker(None)); Log!(ticker); }Optional parameters (such as the
symbolparameter ofGetTicker) useNoneas a placeholder when not passed, and are passed directly when a value is needed, e.g.,exchange.GetTicker("BTC_USDT").
- Strategy entry point and lifecycle: The entry point of a Rust strategy is
fn main()(which shares the same name as the entry point of a standard Rust program, but is invoked by the platform and has no return value). As with JavaScript, you can optionally definefn init()(executed automatically first when the strategy starts running) andfn onexit()(executed to perform cleanup when the strategy exits), which the bootstrap layer will call automatically. In addition, you can also callOnExit()within the strategy code to register additional exit hooks:
rust
fn main() {
// Strategy logic...
}
fn init() {
Log!("Initializing");
}
fn onexit() {
Log!("Strategy exiting, performing cleanup");
}
-
Logging and global features are provided in the form of macros:
Log!(),LogStatus!(),Panic!(),_G!(),_C!(), etc. are Rust macros (note the trailing exclamation mark); whereasLogProfit(),Sleep(),_D(),_N(),HttpQuery(), etc. are regular functions. -
Strategy parameters are injected as global constants: strategy parameters configured in the UI are injected into the strategy code according to their value types (number maps to
f64, boolean tobool, string/password to&str, and dropdowns according to the value type of their options), and can be referenced directly by parameter name. If you need to use them as integers, convert them yourself, e.g.,let n = Period as usize;. The complete parameter set can be obtained as JSON text via theparams()function and parsed yourself. -
JSON data handling: The raw JSON text returned by the platform API (such as the return value of
exchange.IO()and theInfofield of various structs) can be parsed into aJsonValueusing the built-inJSONParse()function, and navigated by indexing in the form ofv["key"]andv[0], then obtaining scalar values via methods such asas_f64(),as_str(), andas_bool(). Since the SDK does not have built-in JSON serialization, you can assemble JSON text using theformat!macro, or introduce a third-party crate (such asserde_json). -
Third-party crates and TLS notes: The strategy source code is the only code file, and dependencies must be declared in a
[dependencies]frontmatter block wrapped by---at the very top of the source code (see the "Programming Languages - Rust" section for details). Since the compilation sandbox does not have system OpenSSL, for crates that require TLS please choose the pure-Rust implementationrustlsand avoid depending onnative-tls/openssl-sys; for WebSocket connections, prefer the built-inDial()function.