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 許可證發佈。