#[cfg(feature = "api-client")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use ib_flex::api::FlexApiClient;
use std::time::Duration;
println!("=== FLEX Web Service API Example ===\n");
let token = std::env::var("IB_FLEX_TOKEN").map_err(|_| {
"IB_FLEX_TOKEN environment variable not set.\n\
Get your token from: IB Account Management → Reports → Settings → FlexWeb Service"
})?;
let query_id = std::env::var("IB_FLEX_QUERY_ID").map_err(|_| {
"IB_FLEX_QUERY_ID environment variable not set.\n\
Create a FLEX query in: IB Account Management → Reports → Flex Queries"
})?;
println!("Token: {}...", &token[..token.len().min(10)]);
println!("Query ID: {}\n", query_id);
let client = FlexApiClient::new(token);
println!("Step 1: Sending FLEX query request...");
let reference_code = client.send_request(&query_id).await?;
println!("✓ Reference code received: {}\n", reference_code);
println!("Step 2: Retrieving statement (will retry if not ready)...");
let xml = client
.get_statement_with_retry(&reference_code, 10, Duration::from_secs(2))
.await?;
println!("✓ Statement received ({} bytes)\n", xml.len());
println!("Step 3: Parsing statement...");
let statement = ib_flex::parse_activity_flex(&xml)?;
println!("✓ Statement parsed successfully\n");
println!("=== Statement Summary ===\n");
println!("Account ID: {}", statement.account_id);
println!("Period: {} to {}", statement.from_date, statement.to_date);
println!();
println!("Content:");
println!(" Trades: {}", statement.trades.items.len());
println!(" Positions: {}", statement.positions.items.len());
println!(
" Cash Transactions: {}",
statement.cash_transactions.items.len()
);
println!(
" Corporate Actions: {}",
statement.corporate_actions.items.len()
);
println!(
" Securities Info: {}",
statement.securities_info.items.len()
);
println!(
" Conversion Rates: {}",
statement.conversion_rates.items.len()
);
println!();
if !statement.trades.items.is_empty() {
println!("\n=== Recent Trades (up to 5) ===\n");
for (i, trade) in statement.trades.items.iter().take(5).enumerate() {
println!("Trade {}:", i + 1);
println!(" Symbol: {}", trade.symbol);
println!(" Date: {}", trade.trade_date);
if let Some(ref buy_sell) = trade.buy_sell {
println!(" Side: {:?}", buy_sell);
}
if let Some(quantity) = trade.quantity {
println!(" Quantity: {}", quantity);
}
if let Some(price) = trade.price {
println!(" Price: {}", price);
}
println!(" Commission: {}", trade.commission);
println!();
}
}
let total_realized_pnl: rust_decimal::Decimal = statement
.trades
.items
.iter()
.filter_map(|t| t.fifo_pnl_realized)
.sum();
if total_realized_pnl != rust_decimal::Decimal::ZERO {
println!("=== P&L Summary ===\n");
println!("Total Realized P&L: ${}", total_realized_pnl);
}
println!("\n✓ Done!");
Ok(())
}
#[cfg(not(feature = "api-client"))]
fn main() {
eprintln!("This example requires the 'api-client' feature.");
eprintln!("Run with: cargo run --example fetch_flex_statement --features api-client");
std::process::exit(1);
}