Skip to content

读取输出

执行 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_indextimestampbar_state
BarEndK 线执行结束。
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(())
}

下一步

基于 MIT 许可证发布。