Skip to main content

ib_flex/
lib.rs

1//! # ib-flex
2//!
3//! Pure Rust parser for Interactive Brokers FLEX XML statements.
4//!
5//! ## Features
6//!
7//! - 🚀 **Zero-copy parsing** with quick-xml and serde
8//! - 💰 **Financial precision** with rust_decimal for all monetary values
9//! - 📅 **Correct datetime handling** with chrono
10//! - ✅ **Type-safe** enums for asset categories, order types, etc.
11//! - 🔧 **No external dependencies** beyond XML/serde
12//! - 📦 **Supports both Activity and Trade Confirmation FLEX**
13//!
14//! ## Quick Start
15//!
16//! ```rust,no_run
17//! use ib_flex::parse_activity_flex;
18//!
19//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
20//! let xml = std::fs::read_to_string("flex_statement.xml")?;
21//! let statement = parse_activity_flex(&xml)?;
22//!
23//! println!("Account: {}", statement.account_id);
24//! println!("Total trades: {}", statement.trades.items.len());
25//!
26//! // Calculate total commissions
27//! let total_commission: rust_decimal::Decimal =
28//!     statement.trades.items.iter().filter_map(|t| t.commission).sum();
29//! println!("Total commissions: ${}", total_commission);
30//! # Ok(())
31//! # }
32//! ```
33//!
34//! ## Supported FLEX Sections
35//!
36//! ### Activity FLEX
37//! - ✅ Trades
38//! - ✅ Open Positions
39//! - ✅ Cash Transactions
40//! - ✅ Corporate Actions
41//! - ✅ Securities Info
42//! - ✅ FX Conversion Rates
43//!
44//! ### Trade Confirmation FLEX
45//! - ✅ Trade executions with all details
46//! - ✅ Commission breakdown
47//!
48//! ## Known Limitations
49//!
50//! 1. **Date formats**: Only ISO-8601 (yyyy-MM-dd) and yyyyMMdd supported
51//! 2. **Schema versions**: Tested with FLEX schema version 3
52
53#![warn(missing_docs)]
54#![warn(clippy::all)]
55
56pub mod error;
57pub mod parsers;
58pub mod types;
59pub mod version;
60
61#[cfg(feature = "api-client")]
62pub mod api;
63
64// Re-export commonly used types
65pub use error::{ParseError, Result};
66pub use types::{
67    ActivityFlexStatement, AssetCategory, BuySell, CashTransaction, CorporateAction, OpenClose,
68    OrderType, Position, PutCall, Trade, TradeConfirmationStatement,
69};
70pub use version::FlexSchemaVersion;
71
72/// Parse an Activity FLEX XML statement
73///
74/// Parses Interactive Brokers Activity FLEX XML into a structured
75/// Rust type with all trades, positions, cash flows, and other data.
76///
77/// # Arguments
78///
79/// * `xml` - XML string from IB FLEX query (Activity type)
80///
81/// # Returns
82///
83/// * `Ok(ActivityFlexStatement)` - Successfully parsed statement
84/// * `Err(ParseError)` - Parse error with detailed context
85///
86/// # Errors
87///
88/// Returns `ParseError` if:
89/// - XML is malformed or invalid
90/// - Required fields are missing
91/// - Date/decimal formats are invalid
92/// - FLEX schema version is unsupported
93///
94/// # Example
95///
96/// ```rust,no_run
97/// use ib_flex::parse_activity_flex;
98///
99/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
100/// let xml = std::fs::read_to_string("statement.xml")?;
101/// let statement = parse_activity_flex(&xml)?;
102///
103/// println!("Trades: {}", statement.trades.items.len());
104/// # Ok(())
105/// # }
106/// ```
107pub fn parse_activity_flex(xml: &str) -> Result<ActivityFlexStatement> {
108    parsers::parse_activity_flex(xml)
109}
110
111/// Parse all Activity FLEX statements from XML
112///
113/// FLEX queries can contain multiple statements (e.g., for different days
114/// in a date range backfill). This function returns all of them.
115///
116/// # Arguments
117///
118/// * `xml` - XML string from IB Activity FLEX query
119///
120/// # Returns
121///
122/// * `Ok(Vec<ActivityFlexStatement>)` - All parsed statements
123/// * `Err(ParseError)` - Parse error with context
124pub fn parse_activity_flex_all(xml: &str) -> Result<Vec<ActivityFlexStatement>> {
125    parsers::parse_activity_flex_all(xml)
126}
127
128/// Parse a Trade Confirmation FLEX XML statement
129///
130/// Parses Interactive Brokers Trade Confirmation FLEX XML into a structured
131/// Rust type with real-time trade execution data.
132///
133/// # Arguments
134///
135/// * `xml` - XML string from IB FLEX query (Trade Confirmation type)
136///
137/// # Returns
138///
139/// * `Ok(TradeConfirmationStatement)` - Successfully parsed statement
140/// * `Err(ParseError)` - Parse error with detailed context
141///
142/// # Errors
143///
144/// Returns `ParseError` if:
145/// - XML is malformed or invalid
146/// - Required fields are missing
147/// - Date/decimal formats are invalid
148///
149/// # Example
150///
151/// ```rust,no_run
152/// use ib_flex::parse_trade_confirmation;
153///
154/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
155/// let xml = std::fs::read_to_string("trade_conf.xml")?;
156/// let statement = parse_trade_confirmation(&xml)?;
157///
158/// println!("Trade executions: {}", statement.trades.items.len());
159/// # Ok(())
160/// # }
161/// ```
162pub fn parse_trade_confirmation(xml: &str) -> Result<TradeConfirmationStatement> {
163    parsers::parse_trade_confirmation(xml)
164}
165
166/// Detect FLEX statement type from XML
167///
168/// Examines the XML structure to determine whether it's an Activity FLEX
169/// or Trade Confirmation FLEX statement.
170///
171/// # Arguments
172///
173/// * `xml` - XML string from IB FLEX query
174///
175/// # Returns
176///
177/// * `Ok(StatementType)` - Detected statement type
178/// * `Err(ParseError)` - If type cannot be determined
179///
180/// # Example
181///
182/// ```rust,no_run
183/// use ib_flex::{detect_statement_type, StatementType};
184///
185/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
186/// let xml = std::fs::read_to_string("statement.xml")?;
187///
188/// match detect_statement_type(&xml)? {
189///     StatementType::Activity => println!("Activity FLEX"),
190///     StatementType::TradeConfirmation => println!("Trade Confirmation"),
191/// }
192/// # Ok(())
193/// # }
194/// ```
195pub fn detect_statement_type(xml: &str) -> Result<StatementType> {
196    version::detect_statement_type(xml)
197}
198
199/// FLEX statement type
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub enum StatementType {
202    /// Activity FLEX statement (daily EOD)
203    Activity,
204    /// Trade Confirmation FLEX statement (real-time)
205    TradeConfirmation,
206}