navi-vm 概述
navi-vm 是編譯和執行 Navi 程式的 Rust crate。它提供了以 Instance 類型為中心的高階 API。
添加依賴
toml
[dependencies]
navi-vm = { git = "https://github.com/longbridge/navi.git" }核心概念
執行模型
Navi 使用逐 K 線執行模型。VM 主動從 DataProvider 拉取 K 線資料,並為每根 K 線執行整個指令碼。
DataProvider::candlesticks()
→ Candlestick 1 → Execute → Outputs updated
→ Candlestick 2 → Execute → Outputs updated
→ Candlestick 3 → Execute → Outputs updated
→ ...核心類型
| 類型 | 描述 |
|---|---|
Instance | 已編譯的可執行腳本實例 |
InstanceBuilder | 用於設定和編譯腳本的建構器 |
Candlestick | 由 DataProvider 提供、VM 消費的 OHLCV K 線資料 |
TimeFrame | 圖表時間週期(1D、5m、1W 等) |
SymbolInfo | 交易標的元資料——由 DataProvider 自動提供,無需手動構造 |
DataProvider | 非同步 trait,為 request.security() 提供 K 線資料和標的資訊 |
CandlestickItem | 由 DataProvider::candlesticks yield 的列舉:Confirmed(candle)、Realtime(candle) 或 HistoryEnd |
Chart | 視覺輸出集合(繪圖、標籤、線條等) |
Event | 執行期間發出的日誌和警報事件 |
ScriptInfo | 已編譯腳本的元資料(類型、輸入、警報、宣告的序列輸出、可選的 bar_color 宣告) |
Error | 編譯或執行時錯誤 |
最小範例
rust
use navi_vm::{Instance, TimeFrame};
#[tokio::main]
async fn main() -> Result<(), navi_vm::Error> {
// 1. 定義 Navi 腳本
let source = r#"
indicator("SMA Crossover")
fast = ta.sma(close, 5)
slow = ta.sma(close, 20)
plot(fast, "Fast SMA", color.BLUE)
plot(slow, "Slow SMA", color.RED)
plot_shape(ta.crossover(fast, slow), style=Shape.TriangleUp)
"#;
// 2. 建構實例,直接傳入 K 線資料
let timeframe = TimeFrame::days(1);
let symbol = "NASDAQ:AAPL";
let bars = load_candles(); // 你的資料來源——Vec<Candlestick>
let instance = Instance::builder(bars, source, timeframe, symbol)
.build().await?;
// 3. 檢查編譯警告
let warnings = instance.warnings();
if !warnings.is_empty() {
eprintln!("{}", warnings.display());
}
// 4. 執行腳本——從 provider 讀取所有 K 線
let instance = instance.run_to_end(symbol, timeframe).await?;
// 5. 讀取輸出
for (_id, graph) in instance.chart().series_graphs() {
if let Some(plot) = graph.as_plot() {
let title = plot.title.as_deref().unwrap_or("unnamed");
println!("Plot '{}': {} bars", title, plot.series.len());
}
}
Ok(())
}執行模型
Instance::run() 消費 DataProvider 的 K 線流,驅動整個執行迴圈:
DataProvider::candlesticks() 流
Confirmed(_) -> 已收盤的 K 線(bar_index 遞增,barstate.is_confirmed = true)
Realtime(_) -> 正在形成的 K 線(可回滾;rollover 或流結束時自動確認)
HistoryEnd -> 標記歷史資料已全部推送完畢instance.run() 回傳 RunHandle,透過 handle.next_event().await 逐個取得事件。執行期間 handle 會持有 Instance,若後續還要繼續使用實例,需要在結束後呼叫 handle.into_instance() 取回。使用 run_to_end() 可以在內部消費所有事件後直接拿回完成執行的實例;也可以直接使用 run() 進行逐 K 線事件處理(handle 同時透過 DerefMut 暴露 save_state() 等實例方法)。