ccxt_core/symbol/
mod.rs

1//! Unified Symbol Format Module
2//!
3//! This module provides comprehensive parsing, formatting, and analysis functionality for
4//! unified trading pair symbols across different market types (Spot, Swap, Futures) and
5//! settlement currencies (Linear/Inverse).
6//!
7//! # Overview
8//!
9//! The unified symbol format follows the CCXT standard, providing a consistent way to
10//! represent trading pairs across all supported cryptocurrency exchanges. This enables
11//! seamless interoperability and simplifies cross-exchange trading operations.
12//!
13//! # Symbol Format
14//!
15//! | Market Type | Format | Example |
16//! |-------------|--------|---------|
17//! | Spot | `BASE/QUOTE` | `BTC/USDT` |
18//! | Linear Swap | `BASE/QUOTE:SETTLE` (settle = quote) | `BTC/USDT:USDT` |
19//! | Inverse Swap | `BASE/QUOTE:SETTLE` (settle = base) | `BTC/USD:BTC` |
20//! | Futures | `BASE/QUOTE:SETTLE-YYMMDD` | `BTC/USDT:USDT-241231` |
21//!
22//! # Components
23//!
24//! - [`SymbolParser`]: Parse unified symbol strings into [`ParsedSymbol`] structures
25//! - [`SymbolFormatter`]: Format [`ParsedSymbol`] back to unified symbol strings
26//! - [`SymbolError`]: Error types for symbol parsing and validation
27//! - [`ParsedSymbol`]: Structured representation of a parsed symbol
28//! - [`ExpiryDate`]: Futures contract expiry date in YYMMDD format
29//! - [`SymbolMarketType`]: Market type enum (Spot, Swap, Futures)
30//! - [`ContractType`]: Contract settlement type (Linear, Inverse)
31//!
32//! # Quick Start
33//!
34//! ## Parsing Symbols
35//!
36//! ```rust
37//! use ccxt_core::symbol::{SymbolParser, ParsedSymbol};
38//!
39//! // Parse a spot symbol
40//! let spot = SymbolParser::parse("BTC/USDT").unwrap();
41//! assert!(spot.is_spot());
42//! assert_eq!(spot.base, "BTC");
43//! assert_eq!(spot.quote, "USDT");
44//!
45//! // Parse a perpetual swap symbol
46//! let swap = SymbolParser::parse("BTC/USDT:USDT").unwrap();
47//! assert!(swap.is_swap());
48//! assert!(swap.is_linear());
49//!
50//! // Parse a futures symbol
51//! let futures = SymbolParser::parse("BTC/USDT:USDT-241231").unwrap();
52//! assert!(futures.is_futures());
53//! assert!(futures.expiry.is_some());
54//! ```
55//!
56//! ## Using FromStr Trait
57//!
58//! ```rust
59//! use ccxt_core::symbol::ParsedSymbol;
60//!
61//! // Parse using the FromStr trait
62//! let symbol: ParsedSymbol = "ETH/USDT".parse().unwrap();
63//! assert_eq!(symbol.base, "ETH");
64//! assert_eq!(symbol.quote, "USDT");
65//! ```
66//!
67//! ## Creating Symbols Programmatically
68//!
69//! ```rust
70//! use ccxt_core::symbol::{ParsedSymbol, ExpiryDate};
71//!
72//! // Create a spot symbol
73//! let spot = ParsedSymbol::spot("BTC".to_string(), "USDT".to_string());
74//! assert_eq!(spot.to_string(), "BTC/USDT");
75//!
76//! // Create a linear swap symbol
77//! let swap = ParsedSymbol::linear_swap("ETH".to_string(), "USDT".to_string());
78//! assert_eq!(swap.to_string(), "ETH/USDT:USDT");
79//!
80//! // Create an inverse swap symbol
81//! let inverse = ParsedSymbol::inverse_swap("BTC".to_string(), "USD".to_string());
82//! assert_eq!(inverse.to_string(), "BTC/USD:BTC");
83//!
84//! // Create a futures symbol
85//! let expiry = ExpiryDate::new(24, 12, 31).unwrap();
86//! let futures = ParsedSymbol::futures(
87//!     "BTC".to_string(),
88//!     "USDT".to_string(),
89//!     "USDT".to_string(),
90//!     expiry
91//! );
92//! assert_eq!(futures.to_string(), "BTC/USDT:USDT-241231");
93//! ```
94//!
95//! ## Formatting Symbols
96//!
97//! ```rust
98//! use ccxt_core::symbol::{SymbolFormatter, ParsedSymbol};
99//!
100//! let symbol = ParsedSymbol::linear_swap("BTC".to_string(), "USDT".to_string());
101//!
102//! // Using SymbolFormatter
103//! let formatted = SymbolFormatter::format(&symbol);
104//! assert_eq!(formatted, "BTC/USDT:USDT");
105//!
106//! // Using Display trait (equivalent)
107//! assert_eq!(symbol.to_string(), "BTC/USDT:USDT");
108//!
109//! // Using helper methods
110//! assert_eq!(SymbolFormatter::format_spot("BTC", "USDT"), "BTC/USDT");
111//! assert_eq!(SymbolFormatter::format_swap("BTC", "USDT", "USDT"), "BTC/USDT:USDT");
112//! ```
113//!
114//! ## Analyzing Symbols
115//!
116//! ```rust
117//! use ccxt_core::symbol::{SymbolParser, SymbolMarketType, ContractType};
118//!
119//! let symbol = SymbolParser::parse("BTC/USDT:USDT").unwrap();
120//!
121//! // Check market type
122//! assert_eq!(symbol.market_type(), SymbolMarketType::Swap);
123//! assert!(symbol.is_swap());
124//! assert!(symbol.is_derivative());
125//!
126//! // Check contract type
127//! assert_eq!(symbol.contract_type(), Some(ContractType::Linear));
128//! assert!(symbol.is_linear());
129//! ```
130//!
131//! # Error Handling
132//!
133//! ```rust
134//! use ccxt_core::symbol::{SymbolParser, SymbolError};
135//!
136//! // Invalid format
137//! let result = SymbolParser::parse("BTCUSDT");
138//! assert!(result.is_err());
139//!
140//! // Invalid date in futures symbol
141//! let result = SymbolParser::parse("BTC/USDT:USDT-241301"); // month 13
142//! assert!(result.is_err());
143//!
144//! // Validate without parsing
145//! assert!(SymbolParser::validate("BTC/USDT").is_ok());
146//! assert!(SymbolParser::validate("invalid").is_err());
147//! ```
148//!
149//! # Round-Trip Consistency
150//!
151//! The symbol module guarantees round-trip consistency: parsing a formatted symbol
152//! and formatting it again produces the same result.
153//!
154//! ```rust
155//! use ccxt_core::symbol::{SymbolParser, SymbolFormatter, ParsedSymbol};
156//!
157//! let original = "BTC/USDT:USDT-241231";
158//! let parsed = SymbolParser::parse(original).unwrap();
159//! let formatted = SymbolFormatter::format(&parsed);
160//! let reparsed = SymbolParser::parse(&formatted).unwrap();
161//!
162//! assert_eq!(parsed, reparsed);
163//! assert_eq!(formatted, original);
164//! ```
165
166pub mod error;
167pub mod formatter;
168pub mod parser;
169
170// Re-export main types for convenience
171pub use error::SymbolError;
172pub use formatter::SymbolFormatter;
173pub use parser::SymbolParser;
174
175// Re-export types from the types module for convenience
176pub use crate::types::symbol::{ContractType, ExpiryDate, ParsedSymbol, SymbolMarketType};