Skip to content

C/C++ API

OpenPine 提供带有 C++ 包装器的 C ABI 绑定,允许你在 C 和 C++ 应用程序中嵌入 Pine Script 引擎。

要求

  • C++17 编译器
  • CMake 3.11+
  • Rust 工具链(用于构建原生库)

使用 CMake 设置

C++ API 使用 Corrosion 从 CMake 构建 Rust 库:

cmake
cmake_minimum_required(VERSION 3.11)
project(my_project)

add_subdirectory(path/to/openpine)

add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE openpine_capi)

基本用法

cpp
#include <openpine.hpp>
#include <iostream>

int main() {
    const char* script = R"(
//@version=6
indicator("SMA")
plot(ta.sma(close, 5))
)";

    // 创建实例
    openpine::CreateInstanceOptions opts(script, "1D", "NASDAQ:AAPL");

    try {
        openpine::MyProvider provider(candlesticks);
        opts.setDataProvider(&provider);
        auto instance = openpine::Instance::create(opts);

        // 异步执行,回调在执行线程上触发
        std::promise<void> done;
        instance.run("NASDAQ:AAPL", "1D", 0, [&done](const openpine::Result& r) {
            if (!r.isSuccess())
                std::cerr << "Error: " << r.errorMessage() << std::endl;
            done.set_value();
        });
        done.get_future().wait();

        // 读取图表输出
        auto chart = instance.chart();
        auto iter = chart.seriesGraphIterator(
            openpine::SeriesGraphType::Plot
        );

        while (iter.next()) {
            const auto plot = iter.seriesGraph().asPlot().value();
            std::cout << "Plot: " << plot.title() << std::endl;

            for (size_t i = 0; i < chart.seriesLength(); i++) {
                auto val = plot.value(i);
                if (val.has_value()) {
                    std::cout << "  bar " << i << ": " << val.value()
                              << std::endl;
                }
            }
        }
    } catch (const openpine::Error& e) {
        std::cerr << "Error: " << e.errorMessage() << std::endl;
        return 1;
    }

    return 0;
}

核心 C++ 类型

类型描述
CreateInstanceOptions配置:源码、时间周期、标的,可选 DataProviderOutputMode
Instance已编译的可执行脚本
DataProvider抽象基类:实现 symbolInfo + candlesticksOpen
CandlestickStreamRAII 推送流;在 candlesticksOpen 里创建,可从任意线程推数据
CandlestickItemK 线加 confirmed 标志(true = 已收盘,false = 正在形成)
Chart视觉输出集合
SeriesGraphIterator迭代序列图(可选类型过滤)
GraphIterator迭代时间点图形
SeriesGraph标记联合体(Plot、PlotCandle、PlotShape 等)
Graph标记联合体(Label、Line、Box、Table 等)
Error带错误信息和可选 span 的异常

输出模式

CreateInstanceOptions 上设置输出模式,控制 plot() 数据的产出方式:

cpp
openpine::CreateInstanceOptions opts(script, "1D", "NASDAQ:AAPL");
opts.setOutputMode(ffi::OutputMode::Stream);
模式行为
OutputMode::Chart(默认)绘图数据写入 instance.chart()
OutputMode::Stream绘图数据通过事件回调发出

事件回调

Instance::run() 传入可选的事件回调,在脚本执行时逐个接收事件:

cpp
instance.run("NASDAQ:AAPL", "1D", 0,
    // 完成回调
    [&done](const openpine::Result& r) {
        done.set_value();
    },
    // 事件回调(可选)
    [](const ffi::Event& event) {
        switch (event.kind) {
            case ffi::EventKind::BarStart:
                std::cout << "K线 " << event.bar_start.bar_index << std::endl;
                break;
            case ffi::EventKind::HistoryEnd:
                std::cout << "历史回放完成" << std::endl;
                break;
            case ffi::EventKind::DrawUpdatePlot:
                std::cout << "绘图 " << event.draw_update_plot.id
                          << " = " << event.draw_update_plot.value << std::endl;
                break;
            default:
                break;
        }
    }
);

不传事件回调(或传 nullptr)时,run() 直接执行到完成,无逐事件通知。

喂入数据

实现 DataProvider 并在 candlesticksOpen 回调里创建 CandlestickStream 推数据:

cpp
class MyProvider : public openpine::DataProvider {
 public:
  explicit MyProvider(const std::vector<openpine::Candlestick>& bars)
      : bars_(bars) {}

  openpine::PartialSymbolInfo symbolInfo(std::string_view) override {
    return {};  // 使用默认值
  }

  ffi::CandlestickStream* candlesticksOpen(
      std::string_view symbol, std::string_view timeframe,
      int64_t from_time) override {
    auto stream = std::make_unique<openpine::CandlestickStream>(
        symbol, timeframe, from_time);
    for (const auto& bar : bars_)
      stream->push(openpine::CandlestickItem{bar, true});
    stream->finish();
    return stream->release();
  }

 private:
  std::vector<openpine::Candlestick> bars_;
};

// 使用
MyProvider provider(candlesticks);
opts.setDataProvider(&provider);
auto instance = openpine::Instance::create(opts);

std::promise<void> done;
instance.run("NASDAQ:AAPL", "1D", 0, [&done](const openpine::Result& r) {
    done.set_value();
});
done.get_future().wait();

如需异步推送(实时数据),在 candlesticksOpen 里启动独立线程推数据:

cpp
ffi::CandlestickStream* candlesticksOpen(...) override {
    auto* stream = new openpine::CandlestickStream(symbol, timeframe, from_time);
    std::thread([stream, this]() {
        for (auto& bar : fetch_bars())
            stream->push(openpine::CandlestickItem{bar, true});
        stream->finish();
        delete stream;
    }).detach();
    return stream->handle();
}

访问图形

执行 K 线后,调用 instance.chart() 访问所有视觉输出。图表提供两种迭代器类型:

方法过滤器内容
chart.seriesGraphIterator(type?)SeriesGraphType逐 K 线数据:绘图、背景、填充、K 线、形状、箭头
chart.graphIterator(type?)GraphType时间点对象:标签、线条、框、表格、水平线、折线

两种迭代器都接受可选的类型过滤器。传入 std::nullopt 可迭代所有类型。

cpp
auto chart = instance.chart();
auto length = chart.seriesLength();

// 序列图:每根 K 线一个值
auto iter = chart.seriesGraphIterator(std::nullopt);
while (iter.next()) {
    auto sg = iter.seriesGraph();

    if (sg.type() == openpine::SeriesGraphType::Plot) {
        auto plot = sg.asPlot().value();
        // plot.value(i), plot.color(i), plot.title(), ...
    }
    if (sg.type() == openpine::SeriesGraphType::PlotCandle) {
        auto candle = sg.asPlotCandle().value();
        // candle.value(i) -> std::optional<Bar>
    }
    // PlotShape, PlotArrow, PlotBar, PlotChar, BackgroundColors, Fill
}

// 时间点图形
auto giter = chart.graphIterator(std::nullopt);
while (giter.next()) {
    auto g = giter.graph();

    if (g.type() == openpine::GraphType::Label) {
        auto label = g.asLabel().value();
        // label.x(), label.y(), label.text(), ...
    }
    if (g.type() == openpine::GraphType::Line) {
        auto line = g.asLine().value();
        // line.x1(), line.y1(), line.x2(), line.y2(), ...
    }
    // Box, Table, Hline, LineFill, Polyline
}

有关完整的图表数据模型(所有字段、枚举和渲染算法),请参阅图表渲染

错误处理

所有错误以 openpine::Error 异常抛出:

cpp
try {
    opts.setDataProvider(&provider);
    auto instance = openpine::Instance::create(opts);
    std::promise<void> done;
    instance.run("NASDAQ:AAPL", "1D", 0, [&](const openpine::Result& r) {
        done.set_value();
    });
    done.get_future().wait();
} catch (const openpine::Error& e) {
    std::cerr << "Error: " << e.errorMessage() << std::endl;

    // 可选:获取错误源码位置
    auto span = e.errorSpan();
    if (span.has_value()) {
        std::cerr << "  at line " << span.value().startLine << std::endl;
    }
}

下一步

基于 MIT 许可证发布。