"""Option symbol parsing utilities.""" import re from datetime import datetime from typing import Optional, NamedTuple from decimal import Decimal class OptionInfo(NamedTuple): """ Parsed option information. Attributes: underlying_symbol: Base ticker symbol (e.g., "AAPL") expiration_date: Option expiration date option_type: "CALL" or "PUT" strike_price: Strike price """ underlying_symbol: str expiration_date: datetime option_type: str strike_price: Decimal def parse_option_symbol(option_symbol: str) -> Optional[OptionInfo]: """ Parse Fidelity option symbol format into components. Fidelity format: -SYMBOL + YYMMDD + C/P + STRIKE Example: -AAPL260116C150 = AAPL Call expiring Jan 16, 2026 at $150 strike Args: option_symbol: Fidelity option symbol string Returns: OptionInfo object if parsing successful, None otherwise Examples: >>> parse_option_symbol("-AAPL260116C150") OptionInfo( underlying_symbol='AAPL', expiration_date=datetime(2026, 1, 16), option_type='CALL', strike_price=Decimal('150') ) >>> parse_option_symbol("-TSLA251219P500") OptionInfo( underlying_symbol='TSLA', expiration_date=datetime(2025, 12, 19), option_type='PUT', strike_price=Decimal('500') ) """ # Regex pattern: -SYMBOL + YYMMDD + C/P + STRIKE # Symbol: one or more uppercase letters # Date: 6 digits (YYMMDD) # Type: C (call) or P (put) # Strike: digits with optional decimal point pattern = r"^-([A-Z]+)(\d{6})([CP])(\d+\.?\d*)$" match = re.match(pattern, option_symbol) if not match: return None symbol, date_str, option_type, strike_str = match.groups() # Parse date (YYMMDD format) try: # Assume 20XX for years (works until 2100) year = 2000 + int(date_str[:2]) month = int(date_str[2:4]) day = int(date_str[4:6]) expiration_date = datetime(year, month, day) except (ValueError, IndexError): return None # Parse option type option_type_full = "CALL" if option_type == "C" else "PUT" # Parse strike price try: strike_price = Decimal(strike_str) except (ValueError, ArithmeticError): return None return OptionInfo( underlying_symbol=symbol, expiration_date=expiration_date, option_type=option_type_full, strike_price=strike_price, )