rusty_feeder/exchange/bybit/data/
subscription_converter.rs

1//! BybitSubscriptionConverter - Conversion between standardized options and Bybit-specific formats
2//!
3//! This module provides functions to convert from the standardized SubscriptionOptions
4//! structure to Bybit-specific subscription formats.
5
6use smallvec::SmallVec;
7use smartstring::alias::String;
8
9use super::subscription::SubscriptionRequest;
10use crate::provider::prelude::*;
11
12/// Convert from standardized SubscriptionOptions to Bybit subscription format
13#[inline]
14pub fn options_to_bybit_subscription(options: &SubscriptionOptions) -> SubscriptionRequest {
15    match options.subscription_type {
16        SubscriptionType::Trade => create_trade_subscription(options.symbols.clone()),
17        SubscriptionType::OrderBook => create_orderbook_subscription(
18            options.symbols.clone(),
19            options.depth.unwrap_or(50), // Default to 50 levels if not specified
20        ),
21        SubscriptionType::Ticker => create_ticker_subscription(options.symbols.clone()),
22        SubscriptionType::Kline => {
23            if let Some(interval) = &options.interval {
24                create_kline_subscription(options.symbols.clone(), interval)
25            } else {
26                // Default to 1m if no interval specified
27                create_kline_subscription(options.symbols.clone(), "1")
28            }
29        }
30        _ => {
31            // Create empty subscription for unsupported types
32            SubscriptionRequest::new(SmallVec::<[String; 4]>::new())
33        }
34    }
35}
36
37/// Create a trade subscription for Bybit WebSocket
38#[inline]
39pub fn create_trade_subscription(symbols: SmallVec<[String; 8]>) -> SubscriptionRequest {
40    let topics = symbols
41        .iter()
42        .map(|symbol| format!("publicTrade.{symbol}").into())
43        .collect();
44
45    SubscriptionRequest::new(topics)
46}
47
48/// Create an orderbook subscription for Bybit WebSocket
49#[inline]
50pub fn create_orderbook_subscription(
51    symbols: SmallVec<[String; 8]>,
52    depth: u32,
53) -> SubscriptionRequest {
54    // Map depth to Bybit's supported depths (1, 50, 200, 500)
55    let depth_level = match depth {
56        d if d <= 1 => 1,
57        d if d <= 50 => 50,
58        d if d <= 200 => 200,
59        _ => 500,
60    };
61
62    let topics = symbols
63        .iter()
64        .map(|symbol| format!("orderbook.{depth_level}.{symbol}").into())
65        .collect();
66
67    SubscriptionRequest::new(topics)
68}
69
70/// Create a ticker subscription for Bybit WebSocket
71#[inline]
72pub fn create_ticker_subscription(symbols: SmallVec<[String; 8]>) -> SubscriptionRequest {
73    let topics = symbols
74        .iter()
75        .map(|symbol| format!("tickers.{symbol}").into())
76        .collect();
77
78    SubscriptionRequest::new(topics)
79}
80
81/// Create a kline subscription for Bybit WebSocket
82#[inline]
83pub fn create_kline_subscription(
84    symbols: SmallVec<[String; 8]>,
85    interval: &str,
86) -> SubscriptionRequest {
87    // Map interval to Bybit's format
88    // Convert common interval formats to Bybit's numeric format
89    let bybit_interval = match interval {
90        "1m" => "1",
91        "3m" => "3",
92        "5m" => "5",
93        "15m" => "15",
94        "30m" => "30",
95        "1h" => "60",
96        "2h" => "120",
97        "4h" => "240",
98        "6h" => "360",
99        "12h" => "720",
100        "1d" => "D",
101        "1w" => "W",
102        "1M" => "M",
103        // If already in Bybit format, use as is
104        i => i,
105    };
106
107    let topics = symbols
108        .iter()
109        .map(|symbol| format!("kline.{bybit_interval}.{symbol}").into())
110        .collect();
111
112    SubscriptionRequest::new(topics)
113}