Skip to main content

tradingview/source/
mod.rs

1//! Data source abstraction.
2//!
3//! Sources produce normalized [`MarketEvent`](crate::events::MarketEvent) batches and feed them into the
4//! loader pipeline. The [`DataSource`](crate::source::DataSource) trait is the extension point for new
5//! data providers (REST APIs, WebSocket feeds, CSV files, etc.).
6
7use async_trait::async_trait;
8use tokio_util::sync::CancellationToken;
9
10use crate::Result;
11use crate::events::MarketEvent;
12
13/// A provider of normalized market events.
14///
15/// A data source is responsible for:
16/// 1. Connecting to the underlying data feed (WebSocket, REST, file).
17/// 2. Fetching/streaming raw data.
18/// 3. Normalizing raw data into [`MarketEvent`] variants.
19/// 4. Sending events to the supplied `sink` channel.
20///
21/// The `run` method is the main execution loop. It runs until the feed is
22/// exhausted, an unrecoverable error occurs, or the [`CancellationToken`] is
23/// triggered.
24#[async_trait]
25pub trait DataSource: Send + Sync + 'static {
26    /// Start streaming events.
27    ///
28    /// The implementation sends `Vec<MarketEvent>` batches to the provided
29    /// async channel sender. The `cancel` token should be polled periodically
30    /// to support graceful shutdown.
31    async fn run(
32        &self,
33        sink: tokio::sync::mpsc::Sender<Vec<MarketEvent>>,
34        cancel: CancellationToken,
35    ) -> Result<()>;
36
37    /// A human-readable name for logging and debugging.
38    fn name(&self) -> &str;
39}
40
41/// Configuration for a data source subscription.
42#[derive(Debug, Clone)]
43pub struct Subscription {
44    /// The instrument to subscribe to (e.g. `"BINANCE:BTCUSDT"`, `"AAPL"`).
45    pub symbol: String,
46    /// What kind of data to request.
47    pub data_kind: crate::events::DataKind,
48    /// Optional bar interval for candle subscriptions.
49    pub interval: Option<crate::models::Interval>,
50    /// Optional number of bars to fetch (historical only).
51    pub bar_count: Option<u64>,
52}
53
54impl Subscription {
55    /// Create a new candle subscription for a symbol.
56    pub fn candle(symbol: impl Into<String>, interval: crate::models::Interval) -> Self {
57        Self {
58            symbol: symbol.into(),
59            data_kind: crate::events::DataKind::Candle,
60            interval: Some(interval),
61            bar_count: None,
62        }
63    }
64
65    /// Create a new quote subscription for a symbol.
66    pub fn quote(symbol: impl Into<String>) -> Self {
67        Self {
68            symbol: symbol.into(),
69            data_kind: crate::events::DataKind::Quote,
70            interval: None,
71            bar_count: None,
72        }
73    }
74
75    /// Create a new economic data subscription.
76    pub fn economic(indicator_id: impl Into<String>) -> Self {
77        Self {
78            symbol: indicator_id.into(),
79            data_kind: crate::events::DataKind::Economic,
80            interval: None,
81            bar_count: None,
82        }
83    }
84}
85
86/// TradingView WebSocket data source adapter.
87///
88/// Wraps the existing [`WebSocketClient`](crate::websocket::WebSocketClient) and `CommandRunner` infrastructure
89/// to produce normalized [`MarketEvent`] batches.
90///
91/// Note: This is a forward-looking design. The full implementation that bridges
92/// the existing WebSocket handler to the new event pipeline requires the
93/// existing handler code to be adapted. This module provides the trait
94/// interface and a skeleton that can be completed incrementally.
95pub mod tradingview;