Skip to main content

pine_core/
lib.rs

1mod bar;
2mod library;
3mod output;
4mod series_buffer;
5mod syminfo;
6mod timeframe;
7mod version;
8
9pub use bar::{Bar, Data, Ohlcv};
10pub use library::{DirLoader, FileResolver, LibraryLoader};
11pub use output::{
12    AlertCondition, AlertConditionOutput, BoxOutput, Color, DefaultPineOutput, DrawingOutput,
13    FillObject, FillOutput, Frequency, GlobalContext, GlobalOutput, Indicator, Input, InputOutput,
14    InputValue, Label, LabelOutput, Library, LineObject, LineOutput, LinefillObject, LogEntry,
15    LogLevel, LogOutput, MetadataOutput, PineBox, PineOutput, Plot, PlotOutput, Plotarrow, Plotbar,
16    Plotcandle, Plotchar, Plotshape, PolylineObject, Table, TableCell, TableOutput,
17};
18pub use series_buffer::{SeriesBuffer, MAX_LOOKBACK};
19pub use syminfo::SymInfo;
20pub use timeframe::{Timeframe, TimeframeError, TimeframeUnit};
21pub use version::{PineVersion, VersionError};
22
23/// The error a [`DataProvider`] fails with.
24pub type ProviderError = Box<dyn std::error::Error + Send + Sync>;
25
26/// A source of market data: given a symbol and a Pine timeframe, produce its
27/// bars.
28/// One price row of a volume footprint: the price range it spans and the volume
29/// traded into the bid (`sell`) and ask (`buy`) at that level.
30#[derive(Debug, Clone)]
31pub struct FootprintRow {
32    pub down_price: f64,
33    pub up_price: f64,
34    pub buy_volume: f64,
35    pub sell_volume: f64,
36}
37
38pub trait DataProvider {
39    fn request(&self, symbol: &str, timeframe: Timeframe) -> Result<Data, ProviderError>;
40
41    /// The volume footprint rows for the current bar (`request.footprint`),
42    /// lowest price first. `None` — the default — means the host has no order-flow
43    /// feed, so the script reads `na`.
44    fn footprint(
45        &self,
46        _ticks_per_row: f64,
47        _va_percent: f64,
48        _imbalance_percent: f64,
49    ) -> Option<Vec<FootprintRow>> {
50        None
51    }
52
53    /// A fundamental financial metric (`request.financial`), e.g. `id =
54    /// "TOTAL_REVENUE"`, `period = "FY"`/`"FQ"`. `None` — the default — means the
55    /// host has no such feed, so the script reads `na`.
56    fn financial(&self, _symbol: &str, _id: &str, _period: &str) -> Option<f64> {
57        None
58    }
59    /// A dividend field (`request.dividends`), e.g. `"gross"`/`"net"`.
60    fn dividends(&self, _ticker: &str, _field: &str) -> Option<f64> {
61        None
62    }
63    /// An earnings field (`request.earnings`), e.g. `"actual"`/`"estimate"`.
64    fn earnings(&self, _ticker: &str, _field: &str) -> Option<f64> {
65        None
66    }
67    /// A splits field (`request.splits`), e.g. `"numerator"`/`"denominator"`.
68    fn splits(&self, _ticker: &str, _field: &str) -> Option<f64> {
69        None
70    }
71    /// An economic series (`request.economic`), e.g. `country = "US"`, `field =
72    /// "GDP"`.
73    fn economic(&self, _country: &str, _field: &str) -> Option<f64> {
74        None
75    }
76    /// The exchange rate `from`→`to` (`request.currency_rate`). Same-currency
77    /// pairs are answered as `1.0` by the builtin without consulting the feed.
78    fn currency_rate(&self, _from: &str, _to: &str) -> Option<f64> {
79        None
80    }
81}