diff --git a/application/execution_service.py b/application/execution_service.py index be46b21..2257c24 100644 --- a/application/execution_service.py +++ b/application/execution_service.py @@ -471,6 +471,247 @@ def _resolve_weight_allocation(signal_metadata: dict[str, Any] | None) -> dict[s } +def _normalize_option_order_intents(signal_metadata: dict[str, Any] | None) -> tuple[dict[str, Any], ...]: + metadata = dict(signal_metadata or {}) + raw_payload = metadata.get("option_order_intents") + if isinstance(raw_payload, dict): + raw_intents = raw_payload.get("intents") + else: + raw_intents = raw_payload + intents = [] + for intent in raw_intents or (): + if isinstance(intent, dict): + intents.append(dict(intent)) + return tuple(intents) + + +def _option_intent_underliers(option_intents: tuple[dict[str, Any], ...]) -> tuple[str, ...]: + underliers = [] + for intent in option_intents: + underlier = str(intent.get("underlier") or intent.get("symbol") or "").strip().upper() + if underlier: + underliers.append(underlier) + return tuple(sorted(dict.fromkeys(underliers))) + + +def _is_executable_option_intent(intent: dict[str, Any]) -> bool: + intent_type = str(intent.get("intent_type") or "").strip() + action = str(intent.get("action") or "").strip().lower() + if ( + str(intent.get("asset_class") or "").strip().lower() == "option" + and intent_type == "single_leg_option" + and action in {"buy_to_open", "sell_to_close"} + ): + return True + return ( + str(intent.get("asset_class") or "").strip().lower() == "option" + and intent_type == "multi_leg_option" + and action == "sell_to_open_put_credit_spread" + ) + + +def _has_executable_option_plan(option_intents: tuple[dict[str, Any], ...]) -> bool: + return any(_is_executable_option_intent(intent) for intent in option_intents) + + +def _format_option_intent_symbol(intent: dict[str, Any]) -> str: + underlier = str(intent.get("underlier") or intent.get("symbol") or "").strip().upper() + if str(intent.get("intent_type") or "").strip() == "multi_leg_option": + expiration = str(intent.get("expiration") or "").strip() + return f"{underlier} {expiration} PCS".strip() + right = str(intent.get("right") or "").strip().upper() + expiration = str(intent.get("expiration") or "").strip() + strike = intent.get("strike") + if underlier and right and expiration and strike not in {None, ""}: + return f"{underlier} {expiration} {float(strike):g}{right}" + return underlier or "