### download() example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/client.md Example demonstrating how to use the client.download() function to get raw XML and then parse it using the parser module. ```python from ibflex import client, parser token = "YOUR_FLEXWEB_TOKEN" query_id = "123456" try: # Download raw XML xml_bytes = client.download(token, query_id) # Parse into Python objects response = parser.parse(xml_bytes) stmt = response.FlexStatements[0] print(f"Downloaded statement for {stmt.accountId}") print(f"Period: {stmt.fromDate} to {stmt.toDate}") except client.ResponseCodeError as e: print(f"IB Error {e.code}: {e.msg}") except client.StatementGenerationTimeout: print("Statement generation timed out; try again later") ``` -------------------------------- ### Top-level Imports Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Example of how to import from the ibflex package. ```python from ibflex import parse, BuySell, AssetClass # Top-level imports ``` -------------------------------- ### Installation Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Install the ibflex library. Use `ibflex[web]` to include the client for downloading capabilities. ```bash # Core library (parsing only) pip install ibflex # With client (download capability) pip install ibflex[web] ``` -------------------------------- ### CLI interface example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/client.md Example of using the flexget CLI script to download a statement. ```bash flexget -t -q > statement.xml ``` -------------------------------- ### Install Client Dependencies Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Install the `ibflex` library with web support using pip. ```bash pip install ibflex[web] ``` -------------------------------- ### Installation Source: https://github.com/csingley/ibflex/blob/master/README.rst Install the ibflex library using pip. ```bash pip install ibflex ``` -------------------------------- ### CLI interface example with specific values Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/client.md Example of using the flexget CLI script with specific token and query ID values. ```bash flexget -t 111111111111111111111111 -q 123456 > 2024_jan.xml ``` -------------------------------- ### ResponseCodeError example usage Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/client.md Example of how to catch and handle ResponseCodeError exceptions. ```python try: response = client.download(token, query_id) except client.ResponseCodeError as e: if e.code == "1012": print("Your FlexWeb token has expired. Generate a new one.") elif e.code == "1015": print("Invalid token. Check your credentials.") else: print(f"IB Error {e.code}: {e.msg}") ``` -------------------------------- ### Flex Client Example Source: https://github.com/csingley/ibflex/blob/master/README.rst Example of using the ibflex.client to download statements using a token and query ID. ```python from ibflex import client In [2]: token = '111111111111111111111111' In [3]: query_id = '111111' In [4]: response = client.download(token, query_id) In [5]: response[:215] Out[5]: b' ' ``` -------------------------------- ### parse() Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/parser.md Examples demonstrating how to parse Flex XML data from a file path or bytes, and how to access the parsed statements. ```python from ibflex import parser # Parse from file path response = parser.parse("2024_jan_statements.xml") # Parse from bytes (e.g., from client.download()) xml_bytes = b'...' response = parser.parse(xml_bytes) # Access statements for stmt in response.FlexStatements: print(f"Account: {stmt.accountId}, Period: {stmt.fromDate} to {stmt.toDate}") print(f"Trades: {len(stmt.Trades)}, Positions: {len(stmt.OpenPositions)}") ``` -------------------------------- ### Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of parsing a statement and calculating total fees. ```python from ibflex import parser from ibflex.enums import CashAction response = parser.parse("statement.xml") stmt = response.FlexStatements[0] total_fees = 0 for txn in stmt.CashTransactions: if txn.cashAction == CashAction.FEES: total_fees += float(txn.amount or 0) print(f"{txn.dateTime.date()} {txn.description}: {txn.amount}") print(f"\nTotal fees: {total_fees:+.2f}") ``` -------------------------------- ### Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of finding security info for a trade. ```python from ibflex import parser response = parser.parse("statement.xml") stmt = response.FlexStatements[0] # Find security info for a trade trade = stmt.Trades[0] sec = next(s for s in stmt.SecuritiesInfo if s.conid == trade.conid) print(f"{sec.symbol}: {sec.description}") print(f"ISIN: {sec.isin}, CUSIP: {sec.cusip}") ``` -------------------------------- ### Common Enums Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Examples of common enum values for BuySell and LongShort. ```python # Direction BuySell.BUY # "BUY" BuySell.SELL # "SELL" LongShort.LONG # "Long" LongShort.SHORT # "Short" ``` -------------------------------- ### Filter Trades by Asset Class Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Example of filtering trades to get only stocks or options using the AssetClass enum. ```python from ibflex import AssetClass stocks = [t for t in stmt.Trades if t.assetCategory == AssetClass.STOCK] options = [t for t in stmt.Trades if t.assetCategory == AssetClass.OPTION] ``` -------------------------------- ### Using Enums Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Demonstrates how to compare enum members, get their names and values, create enums from values, and iterate through all members. ```python # Compare if trade.buySell == BuySell.BUY: print("Buy") # Get name print(trade.buySell.name) # "BUY" # Get value print(trade.buySell.value) # "BUY" # Create from value action = BuySell("BUY") # → BuySell.BUY # List all members for member in BuySell: print(member.name, member.value) ``` -------------------------------- ### Complete Error Handling Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md A comprehensive example showing how to handle various IBFlex and network errors with retries and specific logic for different error codes. ```python from ibflex import client, parser import requests import time def download_and_parse(token, query_id, max_retries=3): """Download and parse a Flex statement with comprehensive error handling.""" for attempt in range(1, max_retries + 1): try: print(f"Download attempt {attempt}...") xml = client.download(token, query_id) print(f"Parse attempt {attempt}...") response = parser.parse(xml) return response except client.ResponseCodeError as e: # IB-specific errors if e.code == "1012": raise ValueError("Token expired. Generate new token in Account Management.") elif e.code == "1013": raise ValueError("IP not whitelisted in Account Management.") elif e.code in ("1009", "1019", "1004", "1005"): # Transient errors, but client.download() should have already retried if attempt < max_retries: wait = 30 * attempt # 30s, 60s, 90s print(f"Transient error. Waiting {wait}s before retry...") time.sleep(wait) continue raise else: raise except client.StatementGenerationTimeout: if attempt < max_retries: print(f"Generation timeout. Waiting 60s before retry...") time.sleep(60) continue raise except (client.BadResponseError, requests.exceptions.Timeout): if attempt < max_retries: print(f"Network error. Waiting 10s before retry...") time.sleep(10) continue raise except parser.FlexParserError as e: # Parse errors are not transient raise ValueError(f"Cannot parse statement: {e}") raise RuntimeError("Download failed after maximum retries") # Usage try: response = download_and_parse(token, query_id) stmt = response.FlexStatements[0] print(f"Successfully loaded statement for {stmt.accountId}") except (ValueError, RuntimeError) as e: print(f"Failed: {e}") except Exception as e: print(f"Unexpected error: {e}") ``` -------------------------------- ### OpenPosition Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of how to iterate through open positions and print details. ```python from ibflex import parser from ibflex.enums import LongShort response = parser.parse("statement.xml") stmt = response.FlexStatements[0] for pos in stmt.OpenPositions: side = "Long" if pos.side == LongShort.LONG else "Short" print(f"{side:5} {pos.position:>8} {pos.symbol:>8} " f"@ {pos.markPrice:>10} = {pos.positionValue:>15}") if pos.fifoPnlUnrealized: unrealized = float(pos.fifoPnlUnrealized) print(f" Unrealized P&L: {unrealized:+.2f}") ``` -------------------------------- ### FlexParserError Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/parser.md An example demonstrating how to catch and handle FlexParserError when parsing fails. ```python from ibflex import parser try: response = parser.parse("malformed.xml") except parser.FlexParserError as e: print(f"Parse failed: {e}") ``` -------------------------------- ### CLI Interface Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/parser.md Command-line interface usage for validating XML files. ```bash python -m ibflex.parser file1.xml file2.xml ... ``` -------------------------------- ### Example Usage of FlexStatement Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of how to access core and container attributes of a FlexStatement. ```python from ibflex import parser response = parser.parse("statement.xml") stmt = response.FlexStatements[0] print(f"Account: {stmt.accountId}") print(f"Period: {stmt.fromDate} to {stmt.toDate}") print(f"Generated: {stmt.whenGenerated}") print(f"Trades: {len(stmt.Trades)}") print(f"Open positions: {len(stmt.OpenPositions)}") print(f"Cash report: {len(stmt.CashReport)} currencies") # Iterate over trades for trade in stmt.Trades: if trade.buySell.name == 'BUY': print(f"BUY {trade.quantity} {trade.symbol} @ {trade.tradePrice}") ``` -------------------------------- ### Example Usage of FlexQueryResponse Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of how to parse a Flex statement and access basic information. ```python from ibflex import parser response = parser.parse("statement.xml") print(f"Query: {response.queryName}") print(f"Statements: {len(response.FlexStatements)}") for stmt in response.FlexStatements: print(f" Account {stmt.accountId}: {stmt.fromDate} to {stmt.toDate}") ``` -------------------------------- ### Handling IbflexClientError Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example of how to catch and handle IbflexClientError during client operations like downloading. ```python from ibflex import client try: xml = client.download(token, query_id) except client.IbflexClientError as e: print(f"Download failed: {e}") ``` -------------------------------- ### Trade Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of how to iterate through trades and print details. ```python from ibflex import parser from ibflex.enums import BuySell response = parser.parse("statement.xml") stmt = response.FlexStatements[0] for trade in stmt.Trades: action = "BUY" if trade.buySell == BuySell.BUY else "SELL" print(f"{trade.tradeDate} {action} {abs(trade.quantity):>8} {trade.symbol:>8} " f"@ {trade.tradePrice:>10} {trade.currency}") # Calculate realized P&L if hasattr(trade, 'fifoPnlRealized'): print(f" Realized P&L: {trade.fifoPnlRealized}") ``` -------------------------------- ### Flex Parser Usage Example Source: https://github.com/csingley/ibflex/blob/master/README.rst Example demonstrating how to parse a Flex XML file and access trade data. ```python from ibflex import parser response = parser.parse("2017-01_ibkr.xml") stmt = response.FlexStatements[0] trade = stmt.Trades[-1] print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}") ``` -------------------------------- ### Example of using enums for BuySell and Code Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Shows how to use enumerated types like BuySell and Code to check trade properties. ```python from ibflex import enums trade = stmt.Trades[0] if trade.buySell == enums.BuySell.BUY: print("This is a buy") if enums.Code.PARTIAL in trade.notes: print("Partial execution") ``` -------------------------------- ### Inspect Object Fields Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Code examples for inspecting all fields of a parsed statement object using pprint and __annotations__. ```python # Print all fields import pprint pprint.pprint(vars(stmt)) # Use __annotations__ to see all fields for field, type_hint in FlexStatement.__annotations__.items(): value = getattr(stmt, field, None) print(f"{field}: {type_hint} = {value!r}") ``` -------------------------------- ### Parse Errors Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Example of how to catch and handle specific parsing errors using a try-except block. ```python try: response = parser.parse("statement.xml") except parser.FlexParserError as e: print(f"Parse failed: {e}") ``` -------------------------------- ### Example Usage of ChangeInNAV Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/types.md Example of how to parse a response and access ChangeInNAV data. ```python from ibflex import parser response = parser.parse("statement.xml") stmt = response.FlexStatements[0] if stmt.ChangeInNAV: nav = stmt.ChangeInNAV print(f"NAV Change for {nav.currency}") print(f" Starting: {nav.startingValue}") print(f" Ending: {nav.endingValue}") print(f" Realized P&L: {nav.realized}") print(f" Unrealized MTM: {nav.mtm}") print(f" Dividends: {nav.dividends}") print(f" Commissions: {nav.commissions}") ``` -------------------------------- ### Type Hints in Your Code Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Shows how to use type hints for function arguments and return values, specifically for `FlexStatement` and `Trade` types, and includes a list comprehension to filter profitable trades. ```python from ibflex.Types import FlexStatement, Trade from typing import List def process_statement(stmt: FlexStatement) -> List[Trade]: """Process trades in a statement.""" profitable_trades = [ t for t in stmt.Trades if t.fifoPnlRealized and float(t.fifoPnlRealized) > 0 ] return profitable_trades ``` -------------------------------- ### Download Flex statements from Interactive Brokers Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Example of downloading Flex statements using the client module with a token and query ID. ```python from ibflex import client xml = client.download("YOUR_TOKEN", "YOUR_QUERY_ID") ``` -------------------------------- ### Field Availability Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Provides examples on how to check for the existence of fields, handle None values for single-element containers, and handle None for individual field values. ```python # Check existence if stmt.Trades: # Non-empty tuple print(f"Has {len(stmt.Trades)} trades") # Handle None for single-element containers if stmt.ChangeInNAV is not None: print(f"NAV: {stmt.ChangeInNAV.endingValue}") # Handle None for field values if trade.fifoPnlRealized is not None: pnl = float(trade.fifoPnlRealized) ``` -------------------------------- ### Import All Enums Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Demonstrates how to import all enums from the main ibflex package or the enums module. ```python from ibflex import ( BuySell, AssetClass, Code, PutCall, # ... and all others ) # Or import the module: from ibflex import enums action = enums.BuySell.BUY ``` -------------------------------- ### Single Statement Iteration Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Example of iterating through trades within a single statement object. ```python response = parser.parse("statement.xml") stmt = response.FlexStatements[0] for trade in stmt.Trades: ... ``` -------------------------------- ### Check Parsed Data Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Examples for verifying data types and enum values of parsed statement objects. ```python # Verify data types assert isinstance(stmt.fromDate, datetime.date) assert isinstance(stmt.Trades, tuple) assert isinstance(stmt.Trades[0], Trade) # Verify enum values assert isinstance(trade.buySell, BuySell) assert trade.buySell in BuySell ``` -------------------------------- ### Optional Attributes Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Demonstrates that most attributes in data classes are Optional and can be None, with an example showing equivalent ways to declare an optional string attribute. ```python # These are equivalent symbol: str | None = None symbol: Optional[str] = None ``` -------------------------------- ### Parse Multiple Files Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Example of parsing multiple Flex XML files from a directory and aggregating all statements. ```python from ibflex import parser import glob files = glob.glob("statements/*.xml") all_statements = [] for file in files: response = parser.parse(file) all_statements.extend(response.FlexStatements) print(f"Loaded {len(all_statements)} statements") ``` -------------------------------- ### Creating Type-Safe Analysis Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Provides an example of creating a type-safe analysis function that parses an XML file, iterates through open positions, and calculates the total value of long and short positions. ```python from ibflex import parser from ibflex.Types import OpenPosition from ibflex.enums import LongShort def analyze_positions(xml_path: str) -> dict[str, float]: """Analyze positions by direction.""" response = parser.parse(xml_path) stmt = response.FlexStatements[0] analysis: dict[str, float] = {"long_value": 0.0, "short_value": 0.0} for pos in stmt.OpenPositions: value = float(pos.positionValue or 0) if pos.side == LongShort.LONG: analysis["long_value"] += value else: analysis["short_value"] -= value return analysis ``` -------------------------------- ### Filter Trades and Positions by Direction Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Examples of filtering trades by BuySell enum and positions by LongShort enum. ```python from ibflex import BuySell, LongShort # Trades buys = [t for t in stmt.Trades if t.buySell == BuySell.BUY] sells = [t for t in stmt.Trades if t.buySell == BuySell.SELL] # Positions long_pos = [p for p in stmt.OpenPositions if p.side == LongShort.LONG] short_pos = [p for p in stmt.OpenPositions if p.side == LongShort.SHORT] ``` -------------------------------- ### Immutability Strategy Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Shows how data classes are defined as frozen to ensure immutability, with an example of using `dataclasses.replace` to create a modified copy. ```python @dataclass(frozen=True) class Trade(FlexElement): ... ``` ```python from dataclasses import replace modified_trade = replace(trade, quantity=100) ``` -------------------------------- ### Flexget Console Script Source: https://github.com/csingley/ibflex/blob/master/README.rst Example of using the flexget console script to download and save Flex XML reports. ```bash $ flexget -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml ``` -------------------------------- ### Handling Network Errors (Timeout and RequestException) Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example demonstrating how to catch network-related errors like timeouts and general request exceptions from the 'requests' library. ```python from ibflex import client import requests try: xml = client.download(token, query_id) except requests.exceptions.Timeout: print("Network timeout. Check your internet connection and try again.") except requests.exceptions.RequestException as e: print(f"Network error: {e}") ``` -------------------------------- ### Error Handling: Client Errors Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Example of how to catch and handle various client-side errors during data download. ```python from ibflex import client try: xml = client.download(token, query_id) except client.ResponseCodeError as e: if e.code == "1012": print("Token expired") else: print(f"Error {e.code}: {e.msg}") except client.StatementGenerationTimeout: print("Generation took too long, retry later") except client.BadResponseError as e: print("Invalid server response") ``` -------------------------------- ### Example of using FlexStatement and Trade types Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Demonstrates accessing statement data and iterating through trades, asserting the type of trade objects. ```python from ibflex.Types import FlexStatement, Trade stmt: FlexStatement = response.FlexStatements[0] for trade in stmt.Trades: assert isinstance(trade, Trade) print(f"{trade.symbol}: {trade.quantity} @ {trade.tradePrice}") ``` -------------------------------- ### Usage Example for enums.CashAction Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Shows how to iterate through cash transactions and identify specific actions like fees or dividends. ```python for txn in stmt.CashTransactions: if txn.cashAction == enums.CashAction.FEES: print(f"Fee: {txn.amount}") elif txn.cashAction == enums.CashAction.DIVIDEND: print(f"Dividend: {txn.amount}") ``` -------------------------------- ### Filter Trades by Asset Class Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Examples of filtering trades to get only stocks or options. ```python # Get only stock trades stocks = [t for t in stmt.Trades if t.assetCategory == enums.AssetClass.STOCK] # Get only option trades options = [t for t in stmt.Trades if t.assetCategory == enums.AssetClass.OPTION] ``` -------------------------------- ### Type Checking Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Demonstrates how to use `isinstance` to check if an object is a Flex type or a specific Flex data type like `Trade`. ```python from ibflex.Types import FlexElement, Trade # Check if object is a Flex type if isinstance(obj, FlexElement): print("This is a Flex data type") # Check specific type if isinstance(obj, Trade): print("This is a trade") ``` -------------------------------- ### Entry Point: ibflex/__init__.py Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Re-exports the public API from other modules. ```python from . import Types, client, enums, parser, utils from .parser import parse # Main entry: parse() from .enums import * # All enum types from .Types import * # All data classes ``` -------------------------------- ### Download and Parse Statement using CLI Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Demonstrates downloading a statement using flexget and then parsing it with a Python one-liner. ```bash # Download statement (requires pip install ibflex[web]) flexget -t YOUR_TOKEN -q YOUR_QUERY_ID > statement.xml # Parse downloaded statement python -c " from ibflex import parser resp = parser.parse('statement.xml') print(f'Account: {resp.FlexStatements[0].accountId}') " ``` -------------------------------- ### Convenience Re-exports Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md The ibflex/__init__.py file re-exports key modules and functions for easier top-level access. ```python from . import parser, client, Types, enums, utils from .parser import parse # Direct import from .Types import * # All data classes from .enums import * # All enums ``` ```python from ibflex import parse, BuySell, Trade # Top-level usage ``` -------------------------------- ### Date/Time Handling Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Shows how to extract components from date/time objects, format them for display, compare dates, and work with datetime objects. ```python # Extract components date_obj = stmt.fromDate # datetime.date year = date_obj.year month = date_obj.month day = date_obj.day # Format for display date_str = stmt.fromDate.strftime("%Y-%m-%d") date_str = stmt.fromDate.isoformat() # "2024-01-15" # Compare dates if trade.tradeDate > stmt.fromDate: print("Trade is after statement start") # Working with datetime ts = stmt.whenGenerated # datetime.datetime ts.date() # Get date part ts.time() # Get time part ``` -------------------------------- ### Download Method Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Download Flex data using the client. Requires a token and query ID. Optionally set max_tries. The downloaded XML bytes can then be parsed. ```python # Requires requests library: pip install ibflex[web] xml_bytes = client.download( token="YOUR_TOKEN", query_id="YOUR_QUERY_ID", max_tries=5 # Optional, default is 5 ) # Then parse response = parser.parse(xml_bytes) ``` -------------------------------- ### Enable Warnings Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Shows how to enable warnings to see which unknown elements the parser skips. ```python import warnings warnings.simplefilter("always") response = parser.parse("statement.xml") # Shows all warnings ``` -------------------------------- ### Multiple Files Iteration Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Shows how to process multiple statement files by iterating through files found using `glob` and aggregating trades. ```python import glob all_trades = [] for file in glob.glob("statements/*.xml"): response = parser.parse(file) for stmt in response.FlexStatements: all_trades.extend(stmt.Trades) ``` -------------------------------- ### BuySell Usage Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Example of iterating through trades and checking the BuySell enum. ```python for trade in stmt.Trades: if trade.buySell == enums.BuySell.BUY: print(f"Bought {trade.quantity} shares") else: print(f"Sold {abs(trade.quantity)} shares") ``` -------------------------------- ### Client Module - Download Flow Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Illustrates the two-step HTTP API interaction for downloading Flex statements, including request generation and statement retrieval. ```text Step 1: Request Generation download(token, query_id) └→ request_statement() └→ submit_request(REQUEST_URL) └→ requests.get() [1st HTTP call] └→ parse_stmt_response() └→ StatementAccess Step 2: Retrieve Statement while status != True: ├→ sleep(status_delay) └→ check_statement_response() └→ submit_request(STMT_URL) └→ requests.get() [2nd+ HTTP call] └→ return True or sleep_delay └→ bytes [raw XML] ``` -------------------------------- ### Decimal Math Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Illustrates how to use Python's `Decimal` type for precise financial calculations, avoiding floating-point errors, and performing comparisons and arithmetic. ```python from decimal import Decimal # Decimals preserve precision amount = trade.tradePrice * trade.quantity # No float rounding errors # Convert to float for display print(f"${float(amount):.2f}") # String formatting print(f"{amount}") # Full precision # Comparison if amount > Decimal("1000"): print("Large trade") # Arithmetic total = sum( trade.ibCommission or Decimal(0) for trade in stmt.Trades ) ``` -------------------------------- ### PutCall Usage Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Example of determining option type using the PutCall enum. ```python for pos in stmt.OpenPositions: if pos.assetCategory == AssetClass.OPTION: option_type = "Put" if pos.putCall == enums.PutCall.PUT else "Call" print(f"{option_type} {pos.symbol} {pos.strike} {pos.expiry}") ``` -------------------------------- ### Imports Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Import necessary components from the ibflex library for parsing, client operations, data types, and enums. ```python # Parser from ibflex import parser from ibflex.parser import FlexParserError # Client from ibflex import client from ibflex.client import ResponseCodeError, StatementGenerationTimeout # Data types from ibflex.Types import FlexQueryResponse, FlexStatement, Trade, OpenPosition from ibflex import Types # Enums from ibflex import ( BuySell, AssetClass, Code, PutCall, OrderType, TradeType, OpenClose, LongShort, CashAction, Reorg, # ... and all others ) from ibflex import enums ``` -------------------------------- ### AssetClass Usage Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Example of filtering trades by asset class using the AssetClass enum. ```python from ibflex.enums import AssetClass # Filter trades by asset class for trade in stmt.Trades: if trade.assetCategory == AssetClass.OPTION: print(f"Option trade: {trade.symbol}") elif trade.assetCategory == AssetClass.STOCK: print(f"Stock trade: {trade.symbol}") ``` -------------------------------- ### File Structure Source: https://github.com/csingley/ibflex/blob/master/_autodocs/INDEX.md Overview of the project's file structure, indicating the purpose of each file. ```text output/ ├── README.md # Start here: overview & quick start ├── QUICK_REFERENCE.md # Cheat sheet & common patterns ├── ARCHITECTURE.md # System design & internals ├── INDEX.md # This file: navigation guide ├── types.md # Type system reference ├── errors.md # Error handling reference └── api-reference/ ├── parser.md # Parser module API ├── client.md # Client module API ├── types.md # Types module API └── enums.md # Enums module API ``` -------------------------------- ### Handling StatementGenerationTimeout Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example of catching StatementGenerationTimeout and retrying with increased max_tries. ```python from ibflex import client try: # Download with default 5 max tries xml = client.download(token, query_id) except client.StatementGenerationTimeout: print("Statement took too long to generate.") print("Try again later when IB servers are less busy.") # Or increase max_tries for next attempt: xml = client.download(token, query_id, max_tries=10) ``` -------------------------------- ### Handling FlexParserError Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example of how to catch and handle FlexParserError during XML parsing. ```python from ibflex import parser try: response = parser.parse("statement.xml") except parser.FlexParserError as e: print(f"Parse failed: {e}") # Inspect the problematic file # Check Flex report configuration # Verify XML is from Interactive Brokers ``` -------------------------------- ### download() function signature Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/client.md Signature for the download function, which initiates the 2-step FlexQueryReport download process. ```python def download(token: str, query_id: str, max_tries: int | None = 5) -> bytes: """2-step FlexQueryReport download process. Args: token: Current access token from Reports > Settings > FlexWeb Service. query_id: Flex Query ID from Reports > Flex Queries > Custom Flex Queries > Configure. """ ``` -------------------------------- ### Download Flow - Client to Parser Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Diagram illustrating the download process initiated by user code, involving client calls and leading to raw XML bytes. ```text User Code ↓ client.download(token, query_id) ├─ request_statement(token, query_id) │ └─ submit_request(REQUEST_URL) │ └─ GET https://...FlexWebService/SendRequest?v=3&t=TOKEN&q=QUERY_ID │ ↓ │ ABC123https://...GetStatement │ ↓ │ StatementAccess(ReferenceCode="ABC123", ...) │ └─ Loop: check_statement_response() ├─ submit_request(STMT_URL) │ └─ GET https://...FlexWebService/GetStatement?v=3&t=TOKEN&q=ABC123 │ ↓ │ status = "Success" → bytes [XML] → return True │ status = "Warn/Fail" → ResponseCodeError or retry delay │ └─ if not ready: sleep(delay) and retry ↓ bytes (raw XML) ↓ [User calls parse()] ↓ FlexQueryResponse object ``` -------------------------------- ### Optional/None Handling Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Demonstrates how attributes are defined as optional and how converters handle null indicators in the input. ```python symbol: str | None = None ``` ```python # In make_optional(): if value in ("", "-", "--", "N/A"): return None else: return func(value) ``` -------------------------------- ### Handling BadResponseError Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example of how to catch and handle BadResponseError, printing details about the unparseable response. ```python from ibflex import client try: xml = client.download(token, query_id) except client.BadResponseError as e: print("Bad response from IB server:") print(e.response.status_code) print(e.response.headers) print(e.response.text[:500]) # First 500 chars of response # Check for HTML error pages if "html" in e.response.headers.get("content-type", "").lower(): print("Server returned an HTML error page (maintenance?)") # Retry later print("Wait a few minutes and try again") ``` -------------------------------- ### Summing Values Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Calculate total commission, realized PnL, and unrealized PnL from trades and positions. ```python total_commission = sum(float(t.ibCommission or 0) for t in stmt.Trades) total_pnl_realized = sum(float(t.fifoPnlRealized or 0) for t in stmt.Trades) total_pnl_unrealized = sum(float(p.fifoPnlUnrealized or 0) for p in stmt.OpenPositions) ``` -------------------------------- ### Types Module Structure Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Hierarchy of dataclasses defined in the Types module, starting from the base class. ```text FlexElement [base class] ├─ FlexQueryResponse [root] ├─ FlexStatement [statement level] │ ├─ Trade, OpenPosition, CashTransaction [transaction/position level] │ ├─ SecurityInfo, ConversionRate [reference data] │ └─ Performance, NAV [summary data] ├─ [50+ specialized types] └─ [All frozen=True for immutability] ``` -------------------------------- ### Network Errors Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Shows how to catch network-related exceptions like timeouts and general request errors. ```python import requests try: xml = client.download(token, query_id) except requests.exceptions.Timeout: print("Network timeout") except requests.exceptions.RequestException as e: print(f"Network error: {e}") ``` -------------------------------- ### Handling ResponseCodeError by Error Code Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example of how to handle specific IB error codes when a ResponseCodeError is caught. ```python from ibflex import client, parser try: xml = client.download(token, query_id) response = parser.parse(xml) except client.ResponseCodeError as e: if e.code == "1012": print("Token expired. Generate a new one at:") print("https://www.interactivebrokers.com/Account/Settings/FlexWebService") elif e.code == "1013": print("IP not whitelisted. Check Account Settings > FlexWeb Service > IP Restrictions") elif e.code in ("1009", "1019"): print("Statement generation in progress. Retrying...") # Automatic retry happens in client.download() elif e.code == "1015": print("Invalid token. Verify you copied it correctly from Account Settings.") elif e.code == "1014": print("Query ID not found. Check Reports > Flex Queries > Custom Flex Queries") else: print(f"IB Error {e.code}: {e.msg}") ``` -------------------------------- ### Multiple Statements Iteration Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Demonstrates how to iterate through multiple statement objects within a response. ```python response = parser.parse("statement.xml") for stmt in response.FlexStatements: print(f"Account {stmt.accountId}") for trade in stmt.Trades: ... ``` -------------------------------- ### Validate XML file(s) using CLI Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Command-line usage for validating one or more XML statement files using the ibflex parser. ```bash # Validate XML file(s) python -m ibflex.parser statement.xml python -m ibflex.parser *.xml ``` -------------------------------- ### Error Handling: Parser Errors Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Example of how to catch and handle parsing errors from the ibflex parser. ```python from ibflex import parser try: response = parser.parse("statement.xml") except parser.FlexParserError as e: print(f"Parse failed: {e}") ``` -------------------------------- ### Immutability Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Illustrates that all types are frozen dataclasses (immutable) and shows how to modify an instance using `dataclasses.replace()`. ```python stmt = response.FlexStatements[0] stmt.accountId = "U999999" # TypeError: cannot assign to field 'accountId' # To modify: create a new instance using dataclasses.replace() from dataclasses import replace modified_stmt = replace(stmt, accountId="U999999") ``` -------------------------------- ### Accessing Position Data Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Iterate through open positions and access attributes like symbol, side (long/short), quantity, mark price, and unrealized PnL. ```python for pos in stmt.OpenPositions: pos.symbol # str pos.side # LongShort enum (LONG/SHORT) pos.position # Decimal (shares held) pos.markPrice # Decimal (current price) pos.positionValue # Decimal (position * price) pos.openPrice # Decimal (avg cost) pos.fifoPnlUnrealized # Decimal | None pos.assetCategory # AssetClass enum ``` -------------------------------- ### Type Introspection Example Source: https://github.com/csingley/ibflex/blob/master/_autodocs/types.md Shows how to use `__annotations__` to inspect a type's fields and check if a field is optional. ```python from ibflex.Types import Trade # Get all fields for field_name, field_type in Trade.__annotations__.items(): print(f"{field_name}: {field_type}") # Check if field is optional field_type = Trade.__annotations__['symbol'] is_optional = "None" in str(field_type) ``` -------------------------------- ### Client Outputs Bytes, Parser Accepts Bytes Source: https://github.com/csingley/ibflex/blob/master/_autodocs/ARCHITECTURE.md Illustrates the direct data flow where the client's output (raw XML bytes) is accepted by the parser. ```python # Flow: xml_bytes = client.download(token, query_id) # bytes response = parser.parse(xml_bytes) # Parse bytes directly ``` -------------------------------- ### Usage Example for enums.LongShort Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Illustrates how to check the side of an open position using the LongShort enumeration. ```python for pos in stmt.OpenPositions: if pos.side == enums.LongShort.LONG: print(f"Long: {pos.quantity} shares") else: print(f"Short: {pos.quantity} shares") ``` -------------------------------- ### Client Errors Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Illustrates handling various client-side errors, including response code errors, timeouts, and bad responses. ```python from ibflex import client try: xml = client.download(token, query_id) except client.ResponseCodeError as e: if e.code == "1012": print("Token expired") elif e.code == "1013": print("IP not whitelisted") else: print(f"Error {e.code}: {e.msg}") except client.StatementGenerationTimeout: print("Generation timed out") except client.BadResponseError: print("Invalid response") ``` -------------------------------- ### Usage Example for enums.Code Source: https://github.com/csingley/ibflex/blob/master/_autodocs/api-reference/enums.md Demonstrates how to check for specific codes within trade notes using the enums.Code enumeration. ```python for trade in stmt.Trades: if enums.Code.PARTIAL in trade.notes: print(f"Partial execution: {trade.symbol}") if enums.Code.PRICEIMPROVEMENT in trade.notes: print(f"Price improvement: {trade.symbol}") ``` -------------------------------- ### Type Checking Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Demonstrates how to check if an object is a Flex type, a specific Flex type like Trade, and how to use types in function type hints. ```python from ibflex.Types import FlexElement, Trade, OpenPosition # Check if object is a Flex type if isinstance(obj, FlexElement): print("This is a Flex type") # Check specific type if isinstance(obj, Trade): print("This is a trade") # Use in type hints def process_trades(trades: list[Trade]) -> None: for trade in trades: ... ``` -------------------------------- ### Accessing Trade Data Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Iterate through trades and access specific attributes like symbol, buy/sell direction, quantity, price, commission, and asset category. ```python for trade in stmt.Trades: trade.symbol # str trade.buySell # BuySell enum trade.quantity # Decimal trade.tradePrice # Decimal trade.tradeDate # datetime.date trade.tradeTime # datetime.time trade.ibCommission # Decimal | None trade.proceeds # Decimal trade.netCash # Decimal trade.fifoPnlRealized # Decimal | None trade.assetCategory # AssetClass enum trade.currency # str ``` -------------------------------- ### Client Download Function Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md The `download` function requires a token and query ID, with an optional `max_tries` parameter. ```python download(token, query_id, max_tries=5) # Token and query ID required ``` -------------------------------- ### Checking Statement Completeness Source: https://github.com/csingley/ibflex/blob/master/_autodocs/errors.md Example code to verify if all expected data sections (Trades, Positions, Cash, SecuritiesInfo) are present in a parsed Flex statement. ```python from ibflex import parser response = parser.parse("statement.xml") stmt = response.FlexStatements[0] # Check if all expected data is present checks = { "Trades": len(stmt.Trades) > 0, "Positions": len(stmt.OpenPositions) > 0, "Cash": len(stmt.CashReport) > 0, "SecuritiesInfo": len(stmt.SecuritiesInfo) > 0, } for name, present in checks.items(): status = "✓" if present else "✗" print(f"{status} {name}") if not all(checks.values()): print("Warning: Some expected data is missing") print("Check Flex Query configuration") ``` -------------------------------- ### Accessing Security Information Source: https://github.com/csingley/ibflex/blob/master/_autodocs/QUICK_REFERENCE.md Iterate through security information and access attributes like symbol, conid, description, asset category, CUSIP, and ISIN. ```python for sec in stmt.SecuritiesInfo: sec.symbol # str sec.conid # str sec.description # str sec.assetCategory # AssetClass enum sec.cusip # str | None sec.isin # str | None ``` -------------------------------- ### Parse Flex XML data Source: https://github.com/csingley/ibflex/blob/master/_autodocs/README.md Example of parsing Flex XML data using the parser module, showing how to access statements and trades. ```python from ibflex import parser response = parser.parse("2024_jan.xml") stmt = response.FlexStatements[0] trades = stmt.Trades ```