讀取輸出
執行 K 線後,你可以通過 instance.chart() 檢查視覺輸出,通過 instance.script_info() 檢查腳本元資料。
有關完整的圖表資料模型(所有欄位、列舉和渲染演算法),請參閱圖表渲染。
存取圖形
圖表包含序列圖(逐 K 線資料)和圖形(時間點繪圖物件):
rust
let chart = instance.chart();
// 序列圖:每根 K 線一個值
for (id, graph) in chart.series_graphs() {
match graph {
SeriesGraph::Plot(plot) => { /* 線條、面積、柱狀圖等 */ }
SeriesGraph::PlotCandle(candle) => { /* OHLC K 線疊加 */ }
SeriesGraph::PlotShape(shape) => { /* 形狀標記 */ }
SeriesGraph::PlotArrow(arrow) => { /* 箭頭標記 */ }
SeriesGraph::PlotBar(bar) => { /* OHLC 條形圖 */ }
SeriesGraph::PlotChar(ch) => { /* 字元標記 */ }
SeriesGraph::BackgroundColors(bg) => { /* 背景顏色 */ }
SeriesGraph::Fill(fill) => { /* 繪圖之間的填充 */ }
}
}
// 時間點圖形
for (id, graph) in chart.graphs() {
match graph {
Graph::Label(label) => { /* 文字標註 */ }
Graph::Line(line) => { /* 線段 */ }
Graph::Box(bx) => { /* 矩形 */ }
Graph::Table(table) => { /* 儲存格網格 */ }
Graph::Hline(hline) => { /* 水平線 */ }
Graph::LineFill(fill) => { /* 兩條線之間的填充 */ }
Graph::Polyline(poly) => { /* 多點線 */ }
}
}你也可以通過 ID 查找單個圖形:
rust
if let Some(sg) = chart.series_graph(id) {
// ...
}
if let Some(g) = chart.graph(id) {
// ...
}腳本資訊
檢查已編譯腳本的元資料:
rust
let info = instance.script_info();
match &info.script_type {
ScriptType::Indicator(ind) => {
println!("Indicator: {}", ind.title);
println!("Overlay: {}", ind.overlay);
}
ScriptType::Strategy(strat) => {
println!("Strategy: {}", strat.title);
println!("Initial capital: {}", strat.initial_capital);
}
ScriptType::Library(lib) => {
println!("Library: {}", lib.title);
}
}
// 列出所有輸入
for input in &info.inputs {
// 每個輸入變體有:id、title、tooltip、default_value 等
}
// 警報條件
for alert in &info.alert_conditions {
// 警報條件定義
}事件
事件在執行期間產生,透過 instance.run() 回傳的事件流逐個取得。事件類型包括:
| 事件 | 說明 |
|---|---|
BarStart(BarStartEvent) | K 線執行開始。包含 bar_index、timestamp、bar_state。 |
BarEnd | K 線執行結束。 |
HistoryEnd | 歷史與即時 K 線的分界標記。 |
Log(LogEvent) | 日誌訊息,含級別(Info、Warning、Error)和內容。 |
Alert(AlertEvent) | 警報,含可選 id 和訊息。 |
Draw(DrawEvent) | 繪圖指令(僅 OutputMode::Stream 模式)。 |
rust
use std::pin::pin;
use futures_util::StreamExt;
use openpine_vm::{Event, LogLevel};
let mut stream = pin!(instance.run(symbol, tf));
while let Some(result) = stream.next().await {
match result? {
Event::Log(log) => {
match log.level {
LogLevel::Info => println!("INFO: {}", log.message),
LogLevel::Warning => println!("WARN: {}", log.message),
LogLevel::Error => println!("ERROR: {}", log.message),
}
}
Event::Alert(alert) => {
println!("ALERT [id={:?}]: {}", alert.id, alert.message);
}
_ => {}
}
}如不需要逐個處理事件,使用 run_to_end():
rust
instance.run_to_end(symbol, tf).await?;
// 事件被丟棄;透過 instance.chart() 等讀取結果完整範例
rust
use std::pin::pin;
use futures_util::StreamExt;
use openpine_vm::{Candlestick, Event, Instance, TimeFrame};
async fn run(candles: Vec<Candlestick>) -> Result<(), openpine_vm::Error> {
let source = r#"
//@version=6
indicator("RSI Monitor")
rsi = ta.rsi(close, 14)
plot(rsi, "RSI")
hline(70, "Overbought")
hline(30, "Oversold")
alertcondition(ta.crossover(rsi, 70), "RSI Overbought")
"#;
let tf = TimeFrame::days(1);
let symbol = "NASDAQ:AAPL";
let mut instance = Instance::builder(candles, source, tf, symbol)
.build().await?;
// 消費事件流
let mut stream = pin!(instance.run(symbol, tf));
while let Some(result) = stream.next().await {
if let Event::Alert(alert) = result? {
println!("Alert: {}", alert.message);
}
}
drop(stream);
// 列印最終 RSI 值
for (_id, graph) in instance.chart().series_graphs() {
if let Some(plot) = graph.as_plot() {
if plot.title.as_deref() == Some("RSI") {
if let Some(last) = plot.series.last() {
println!("Final RSI: {:?}", last);
}
}
}
}
Ok(())
}