dxlink/lib.rs
1//! # dxlink
2//!
3//! `dxlink` is a Rust client library for the DXLink WebSocket protocol used by tastytrade
4//! for real-time market data. This library provides a clean and type-safe API for connecting
5//! to DXLink servers, subscribing to market events, and processing real-time market data.
6//!
7//! ## Features
8//!
9//! - Full implementation of the DXLink WebSocket protocol (AsyncAPI 2.4.0)
10//! - Strongly typed event definitions for Quote, Trade, Greeks, and more
11//! - Async/await based API for efficient resource usage
12//! - Automatic handling of authentication and connection maintenance
13//! - Support for multiple subscription channels
14//! - Callback and stream-based APIs for event processing
15//! - Robust error handling and reconnection logic
16//!
17//! ref: <https://raw.githubusercontent.com/dxFeed/dxLink/refs/heads/main/dxlink-specification/asyncapi.yml>
18//!
19//! ## Example
20//!
21//! Here's a basic example of using the library to connect to a DXLink server
22//! and subscribe to market data:
23//!
24//! ```rust,no_run
25//! use std::error::Error;
26//! use dxlink::{DXLinkClient, EventType, FeedSubscription, MarketEvent};
27//! use tokio::time::sleep;
28//! use std::time::Duration;
29//!
30//! #[tokio::main]
31//! async fn main() -> Result<(), Box<dyn Error>> {
32//!
33//! // Create a new DXLink client with the API token
34//! // (typically obtained from tastytrade API)
35//! use tracing::info;
36//! let token = "your_api_token_here";
37//! let url = "wss://tasty-openapi-ws.dxfeed.com/realtime";
38//! let mut client = DXLinkClient::new(url, token);
39//!
40//! // Connect to the DXLink server
41//! client.connect().await?;
42//!
43//! // Create a feed channel with AUTO contract type
44//! let channel_id = client.create_feed_channel("AUTO").await?;
45//!
46//! // Configure the channel for Quote and Trade events
47//! client.setup_feed(channel_id, &[EventType::Quote, EventType::Trade]).await?;
48//!
49//! // Register a callback for specific symbol
50//! client.on_event("SPY", |event| {
51//! info!("Event received for SPY: {:?}", event);
52//! });
53//!
54//! // Get a stream for all events
55//! let mut event_stream = client.event_stream()?;
56//!
57//! // Process events in a separate task
58//! tokio::spawn(async move {
59//! while let Some(event) = event_stream.recv().await {
60//! match &event {
61//! MarketEvent::Quote(quote) => {
62//! info!(
63//! "Quote: {} - Bid: {} x {}, Ask: {} x {}",
64//! quote.event_symbol,
65//! quote.bid_price,
66//! quote.bid_size,
67//! quote.ask_price,
68//! quote.ask_size
69//! );
70//! },
71//! MarketEvent::Trade(trade) => {
72//! info!(
73//! "Trade: {} - Price: {}, Size: {}, Volume: {}",
74//! trade.event_symbol,
75//! trade.price,
76//! trade.size,
77//! trade.day_volume
78//! );
79//! },
80//! _ => info!("Other event type: {:?}", event),
81//! }
82//! }
83//! });
84//!
85//! // Subscribe to some symbols
86//! let subscriptions = vec![
87//! FeedSubscription {
88//! event_type: "Quote".to_string(),
89//! symbol: "SPY".to_string(),
90//! from_time: None,
91//! source: None,
92//! },
93//! FeedSubscription {
94//! event_type: "Trade".to_string(),
95//! symbol: "SPY".to_string(),
96//! from_time: None,
97//! source: None,
98//! },
99//! ];
100//!
101//! client.subscribe(channel_id, subscriptions).await?;
102//!
103//! // Keep the connection active for some time
104//! sleep(Duration::from_secs(60)).await;
105//!
106//! // Cleanup
107//! client.disconnect().await?;
108//!
109//! Ok(())
110//! }
111//! ```
112//!
113//! ## Working with historical data
114//!
115//! DXLink supports subscribing to historical data through Candle events.
116//! When subscribing to candle events, you need to specify the period,
117//! type, and a timestamp from which to fetch the data:
118//!
119//! ```rust,no_run
120//! use dxlink::FeedSubscription;
121//! use std::time::{SystemTime, UNIX_EPOCH};
122//!
123//! // Get current timestamp in milliseconds
124//! let now = SystemTime::now()
125//! .duration_since(UNIX_EPOCH)
126//! .unwrap()
127//! .as_millis() as i64;
128//!
129//! // Timestamp for 24 hours ago
130//! let one_day_ago = now - (24 * 60 * 60 * 1000);
131//!
132//! // Subscribe to 5-minute candles for SPY for the last 24 hours
133//! let candle_subscription = FeedSubscription {
134//! event_type: "Candle".to_string(),
135//! symbol: "SPY{=5m}".to_string(), // 5-minute candles
136//! from_time: Some(one_day_ago),
137//! source: None,
138//! };
139//! ```
140//!
141//! ## Error Handling
142//!
143//! The library uses a custom error type `DXLinkError` that encompasses
144//! various error cases that can occur when interacting with the DXLink API:
145//!
146//! ```rust,no_run
147//! use tracing::{error, info};
148//! use dxlink::{DXLinkClient, DXLinkError};
149//!
150//! async fn example_error_handling() {
151//! let mut client = DXLinkClient::new("wss://example.com", "token");
152//! match client.connect().await {
153//! Ok(_) => info!("Connected successfully!"),
154//! Err(DXLinkError::Authentication(e)) => error!("Authentication failed: {}", e),
155//! Err(DXLinkError::Connection(e)) => error!("Connection error: {}", e),
156//! Err(e) => error!("Other error: {}", e),
157//! }
158//! }
159//! ```
160//!
161//! ## Available Event Types
162//!
163//! The library supports the following event types:
164//!
165//! - `Quote` - Current bid/ask prices and sizes
166//! - `Trade` - Last trade information
167//! - `Greeks` - Option greeks data (delta, gamma, theta, etc.)
168//! - `Summary` - Daily summary information
169//! - `Profile` - Instrument profile information
170//! - `Candle` - OHLC (Open, High, Low, Close) data for time periods
171//! - And more!
172//!
173//!
174//! ## License
175//!
176//! This project is licensed under the MIT License. See the LICENSE file for details.
177//!
178//! ## Setup Instructions
179//!
180//! 1. Clone the repository:
181//! ```shell
182//! git clone https://github.com/joaquinbejar/DXlink
183//! cd DXlink
184//! ```
185//!
186//! 2. Build the project:
187//! ```shell
188//! make build
189//! ```
190//!
191//! 3. Run tests:
192//! ```shell
193//! make test
194//! ```
195//!
196//! 4. Format the code:
197//! ```shell
198//! make fmt
199//! ```
200//!
201//! 5. Run linting:
202//! ```shell
203//! make lint
204//! ```
205//!
206//! 6. Clean the project:
207//! ```shell
208//! make clean
209//! ```
210//!
211//! 7. Run the project:
212//! ```shell
213//! make run
214//! ```
215//!
216//! 8. Fix issues:
217//! ```shell
218//! make fix
219//! ```
220//!
221//! 9. Run pre-push checks:
222//! ```shell
223//! make pre-push
224//! ```
225//!
226//! 10. Generate documentation:
227//! ```shell
228//! make doc
229//! ```
230//!
231//! 11. Publish the package:
232//! ```shell
233//! make publish
234//! ```
235//!
236//! 12. Generate coverage report:
237//! ```shell
238//! make coverage
239//! ```
240//!
241//!
242//! ## Testing
243//!
244//! To run unit tests:
245//! ```shell
246//! make test
247//! ```
248//!
249//! To run tests with coverage:
250//! ```shell
251//! make coverage
252//! ```
253//!
254//! ## Contribution and Contact
255//!
256//! We welcome contributions to this project! If you would like to contribute, please follow these steps:
257//!
258//! 1. Fork the repository.
259//! 2. Create a new branch for your feature or bug fix.
260//! 3. Make your changes and ensure that the project still builds and all tests pass.
261//! 4. Commit your changes and push your branch to your forked repository.
262//! 5. Submit a pull request to the main repository.
263//!
264//! If you have any questions, issues, or would like to provide feedback, please feel free to contact the project maintainer:
265//!
266//! **Joaquín Béjar García**
267//! - Email: jb@taunais.com
268//! - GitHub: [joaquinbejar](https://github.com/joaquinbejar)
269//!
270//! We appreciate your interest and look forward to your contributions!
271//!
272
273/// Client module for the DXLink WebSocket library.
274///
275/// This module provides the main `DXLinkClient` struct, which handles WebSocket connections,
276/// authentication, event subscriptions, and message processing for the DXLink protocol.
277///
278/// Key features include:
279/// - Establishing and managing WebSocket connections
280/// - Authenticating with the DXLink server
281/// - Creating and managing communication channels
282/// - Subscribing to market data feeds
283/// - Processing real-time market events
284/// - Handling connection lifecycle (connect, disconnect)
285pub mod client;
286
287/// WebSocket connection management module.
288///
289/// This module defines the `WebSocketConnection` struct, which provides low-level
290/// WebSocket communication capabilities. It handles:
291/// - Establishing secure WebSocket connections
292/// - Sending and receiving messages
293/// - Managing read and write streams
294/// - Implementing keep-alive mechanisms
295/// - Thread-safe connection handling
296pub mod connection;
297
298/// Error handling module for the DXLink WebSocket library.
299///
300/// Defines a comprehensive error enum `DXLinkError` that covers various potential
301/// error conditions during DXLink interactions, including:
302/// - WebSocket connection errors
303/// - Serialization/deserialization failures
304/// - Authentication issues
305/// - Connection problems
306/// - Protocol violations
307/// - Timeout scenarios
308/// - Unexpected message handling
309pub mod error;
310
311/// Event types and structures for market data.
312///
313/// This module provides:
314/// - Enum and structs representing different market event types
315/// - Support for Quote, Trade, and Greeks events
316/// - Serialization and deserialization of market events
317/// - Flexible event handling with a unified `MarketEvent` enum
318pub mod events;
319
320/// Message structures for the DXLink protocol.
321///
322/// Contains serializable structs representing various message types used in
323/// DXLink communication, including:
324/// - Authentication messages
325/// - Channel management messages
326/// - Feed subscription messages
327/// - Setup and configuration messages
328/// - Error messages
329pub mod messages;
330
331/// Utility functions for parsing and processing market data.
332///
333/// Provides helper functions for:
334/// - Parsing compact data formats
335/// - Converting raw data into structured market events
336/// - Supporting efficient event processing
337mod utils;
338
339pub use client::DXLinkClient;
340pub use error::DXLinkError;
341pub use events::{EventType, MarketEvent};
342pub use messages::FeedSubscription;
343pub use utils::parse_compact_data;