Skip to main content

DataProvider

Trait DataProvider 

Source
pub trait DataProvider {
    type Error: Display + Debug + 'static;

    // Required methods
    fn symbol_info<'life0, 'async_trait>(
        &'life0 self,
        symbol: String,
        fields: SyminfoFields,
    ) -> Pin<Box<dyn Future<Output = Result<PartialSymbolInfo, DataProviderError<Self::Error>>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn candlesticks(
        &self,
        symbol: String,
        timeframe: TimeFrame,
        from_time: i64,
        count: Option<usize>,
    ) -> Result<impl Stream<Item = Result<CandlestickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>;

    // Provided methods
    fn ticks(
        &self,
        _symbol: String,
        _from_time: i64,
        _count: Option<usize>,
    ) -> Result<impl Stream<Item = Result<TickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn currency_rate(
        &self,
        _from: Currency,
        _to: Currency,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn financial(
        &self,
        _symbol: String,
        _financial_id: String,
        _period: String,
        _currency: Option<Currency>,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn earnings(
        &self,
        _symbol: String,
        _field: EarningsField,
        _currency: Option<Currency>,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn dividends(
        &self,
        _symbol: String,
        _field: DividendsField,
        _currency: Option<Currency>,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn economic(
        &self,
        _country_code: String,
        _field: String,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn splits(
        &self,
        _symbol: String,
        _field: SplitsField,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
    fn data(
        &self,
        _function: String,
        _args: DataArgs,
        _from_time: i64,
    ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>> { ... }
}
Expand description

Supplies candlestick data and symbol metadata to the VM.

Implement this trait and pass it as the first argument to Instance::builder. It serves two purposes: main chart K-lines consumed by Instance::run and MTF/cross-symbol data for request.security() calls.

For simple single-symbol use cases, pass a Vec<Candlestick> directly — it implements DataProvider and wraps bars as CandlestickItem::Bar.

§Contract

  • candlesticks must return bars in strict ascending time order.
  • The stream should start at or before from_time so that MTF bar state is initialised even before the first chart bar.
  • Returning Err(DataProviderError::InvalidSymbol(_)) causes request.security() to return na when ignore_invalid_symbol = true, or a runtime error otherwise.

Required Associated Types§

Source

type Error: Display + Debug + 'static

The error payload type for DataProviderError::Other.

Required Methods§

Source

fn symbol_info<'life0, 'async_trait>( &'life0 self, symbol: String, fields: SyminfoFields, ) -> Pin<Box<dyn Future<Output = Result<PartialSymbolInfo, DataProviderError<Self::Error>>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Returns partial symbol metadata for the given symbol string.

fields is the set of syminfo property fields that the compiled script actually accesses. Implementations may use this to fetch only the required data, but are free to always return all fields.

Any None field falls back to a default derived from the symbol’s exchange prefix. Return PartialSymbolInfo::default() if you only want the defaults.

Source

fn candlesticks( &self, symbol: String, timeframe: TimeFrame, from_time: i64, count: Option<usize>, ) -> Result<impl Stream<Item = Result<CandlestickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of candlestick items for the given symbol and timeframe.

  • symbol — e.g. "BINANCE:BTCUSDT", "NASDAQ:AAPL"
  • timeframe — the requested timeframe
  • from_time — epoch-millisecond timestamp of the first chart bar; start at or before this time
  • count — optional cap for how many recent historical bars to load for a shared request stream; None means no provider-side cap

Items must be yielded in strict ascending time order.

Returns Err(DataProviderError::InvalidSymbol(_)) at creation time when the symbol is not recognised. This is checked before any stream items are yielded.

§Finite vs. infinite streams

The stream may be finite (all items are yielded and the stream ends) or infinite (the stream never terminates and keeps producing Realtime items as new ticks arrive).

  • Finite — typical for historical backtests. The stream yields Confirmed bars, then HistoryEnd, then terminates. If a Realtime bar is still open when the stream ends, the VM confirms it automatically. Instance::run returns when the stream is exhausted.
  • Infinite — typical for live trading / real-time monitoring. The stream yields historical bars followed by HistoryEnd, then keeps producing Realtime items indefinitely as new market ticks arrive. Instance::run runs until the stream is dropped or the caller stops polling.
§Stream protocol

The expected sequence is:

Bar(t0)  Bar(t1)  …  Bar(tN-1)  Bar(tN)   <- bars sent before HistoryEnd
HistoryEnd                                  <- boundary marker (once)
Bar(tN)                         <- realtime update for the forming bar
                                   (tN may equal the last historical ts)
Bar(tA)  (tA > tN)              <- new period: VM confirms tN, opens tA
Bar(tA)                         <- in-place update for tA
…                               <- finite: stream ends
                                   infinite: keeps producing

Key rules:

  • Bar — the role depends on position relative to HistoryEnd. Before HistoryEnd, bars t0 through tN-1 are fully closed historical bars. The last bar tN (the one immediately before HistoryEnd) may be a currently forming bar — the VM executes it in realtime mode for this reason. After HistoryEnd, Bar items represent the currently forming bar. Multiple consecutive Bar items with the same timestamp are treated as in-place updates. A Bar with a later timestamp implicitly confirms the previous bar and starts a new one.
  • HistoryEnd — emitted once, signals that the server has sent all currently available bars. It does not mean the last bar is a closed period — if the current period is still forming, the last bar before HistoryEnd will be that forming bar, and realtime updates for it will follow with the same timestamp. If the stream ends after HistoryEnd with an open realtime bar, the VM confirms it automatically.

Provided Methods§

Source

fn ticks( &self, _symbol: String, _from_time: i64, _count: Option<usize>, ) -> Result<impl Stream<Item = Result<TickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of tick events for the given symbol.

  • symbol — e.g. "BINANCE:BTCUSDT", "NASDAQ:AAPL"
  • from_time — epoch-millisecond timestamp of the first chart bar; start at or before this time
  • count — optional cap for how many recent historical ticks to load; None means no provider-side cap

The stream protocol is identical to candlesticks: historical TickItem::Tick events are followed by exactly one TickItem::HistoryEnd marker, then optional realtime ticks.

This method is only called by the VM when a tick-based timeframe (T suffix) is requested. The default implementation returns an empty stream (no tick data available).

Source

fn currency_rate( &self, _from: Currency, _to: Currency, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of historical exchange rate data points for converting from from currency to to currency.

Default: empty stream (no data available).

Source

fn financial( &self, _symbol: String, _financial_id: String, _period: String, _currency: Option<Currency>, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of financial report data points (e.g. quarterly revenue, EPS) for the given symbol and financial identifier.

Default: empty stream (no data available).

Source

fn earnings( &self, _symbol: String, _field: EarningsField, _currency: Option<Currency>, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of earnings data points for the given symbol.

Default: empty stream (no data available).

Source

fn dividends( &self, _symbol: String, _field: DividendsField, _currency: Option<Currency>, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of dividend data points for the given symbol.

Default: empty stream (no data available).

Source

fn economic( &self, _country_code: String, _field: String, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of macroeconomic data points for the given country and field.

Default: empty stream (no data available).

Source

fn splits( &self, _symbol: String, _field: SplitsField, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a stream of stock split data points for the given symbol.

Default: empty stream (no data available).

Source

fn data( &self, _function: String, _args: DataArgs, _from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Returns a custom data stream identified by function and args.

Called by request.data(function, args) in Navi. Implement this method to expose arbitrary time-series data to scripts.

  • function — the function name from the request.data call site.
  • args — typed key/value parameters from the map<string, any> argument. Use [DataArgs::deserialize] to convert them into a typed struct.
  • from_time — epoch-millisecond timestamp of the first chart bar.

Default: empty stream (no data available).

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl DataProvider for Vec<CandlestickItem>

Vec<CandlestickItem> implements DataProvider by yielding the items as-is on every candlesticks() call, regardless of symbol/timeframe.

Use this when you need to mix CandlestickItem::Bar and CandlestickItem::HistoryEnd in a single stream. For plain historical bars, prefer Vec<Candlestick>.

Source§

type Error = Infallible

Source§

fn symbol_info<'life0, 'async_trait>( &'life0 self, _symbol: String, _fields: SyminfoFields, ) -> Pin<Box<dyn Future<Output = Result<PartialSymbolInfo, DataProviderError<Self::Error>>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn candlesticks( &self, _symbol: String, _timeframe: TimeFrame, _from_time: i64, count: Option<usize>, ) -> Result<impl Stream<Item = Result<CandlestickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

impl DataProvider for Vec<Candlestick>

Vec<Candlestick> implements DataProvider for the simple case of running a script against a fixed set of historical bars.

All candlesticks() requests (regardless of symbol/timeframe) receive the same bars wrapped as CandlestickItem::Bar, followed by a CandlestickItem::HistoryEnd marker.

For script_info() queries that need no data, pass vec![].

Source§

type Error = Infallible

Source§

fn symbol_info<'life0, 'async_trait>( &'life0 self, _symbol: String, _fields: SyminfoFields, ) -> Pin<Box<dyn Future<Output = Result<PartialSymbolInfo, DataProviderError<Self::Error>>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn candlesticks( &self, _symbol: String, _timeframe: TimeFrame, _from_time: i64, count: Option<usize>, ) -> Result<impl Stream<Item = Result<CandlestickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

impl<P> DataProvider for Rc<P>
where P: DataProvider + 'static,

Rc<P> implements DataProvider by delegating to the inner P.

Allows sharing a single provider instance between multiple Instance builders or background tasks without cloning the provider value itself.

Source§

type Error = <P as DataProvider>::Error

Source§

fn symbol_info<'life0, 'async_trait>( &'life0 self, symbol: String, fields: SyminfoFields, ) -> Pin<Box<dyn Future<Output = Result<PartialSymbolInfo, DataProviderError<Self::Error>>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn candlesticks( &self, symbol: String, timeframe: TimeFrame, from_time: i64, count: Option<usize>, ) -> Result<impl Stream<Item = Result<CandlestickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn ticks( &self, symbol: String, from_time: i64, count: Option<usize>, ) -> Result<impl Stream<Item = Result<TickItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn currency_rate( &self, from: Currency, to: Currency, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn financial( &self, symbol: String, financial_id: String, period: String, currency: Option<Currency>, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn earnings( &self, symbol: String, field: EarningsField, currency: Option<Currency>, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn dividends( &self, symbol: String, field: DividendsField, currency: Option<Currency>, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn economic( &self, country_code: String, field: String, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Source§

fn splits( &self, symbol: String, field: SplitsField, from_time: i64, ) -> Result<impl Stream<Item = Result<AuxDataItem, DataProviderError<Self::Error>>> + 'static, DataProviderError<Self::Error>>

Implementors§