164 lines
8.0 KiB
Markdown
164 lines
8.0 KiB
Markdown
# Architecture Patterns
|
|
|
|
**Domain:** Options trading analysis module for multi-agent AI trading system
|
|
**Researched:** 2026-03-29
|
|
|
|
## Recommended Architecture
|
|
|
|
The options module plugs into the existing TradingAgents architecture as a **parallel agent team** alongside the stock analysis team. It follows the same patterns: agent factory closures, LangGraph StateGraph, vendor-routed data layer.
|
|
|
|
### Component Boundaries
|
|
|
|
| Component | Responsibility | Communicates With |
|
|
|-----------|---------------|-------------------|
|
|
| `tradingagents/dataflows/tradier.py` | Options chain retrieval, expirations, strikes via Tradier REST API | Agent tools, config |
|
|
| `tradingagents/dataflows/tastytrade.py` | Real-time Greeks streaming via DXLink WebSocket (optional) | Agent tools, config |
|
|
| `tradingagents/options/greeks.py` | 2nd/3rd order Greeks calculation (Charm, Vanna, Volga) from 1st-order + spot | Greeks analysis agent |
|
|
| `tradingagents/options/volatility.py` | IV Rank, IV Percentile, SVI surface fitting, vol skew metrics | Volatility analysis agent |
|
|
| `tradingagents/options/gex.py` | GEX computation, Call/Put Walls, gamma flip zone, Vanna/Charm exposure | GEX analysis agent |
|
|
| `tradingagents/options/flow.py` | Volume/OI analysis, unusual activity detection heuristics | Flow analysis agent |
|
|
| `tradingagents/options/strategies.py` | Multi-leg strategy construction, P/L profiles, PoP estimation | Strategy selection agent |
|
|
| `tradingagents/options/scoring.py` | MenthorQ-style composite Options Score (0-5) | Options portfolio manager |
|
|
| `tradingagents/agents/options/` | Agent factory functions for each options analyst role | LangGraph StateGraph |
|
|
| `tradingagents/graph/options_team.py` | LangGraph StateGraph for the options analysis pipeline | Main graph (parallel branch) |
|
|
|
|
### Data Flow
|
|
|
|
```
|
|
User input (ticker, date range)
|
|
|
|
|
v
|
|
[Tradier API] --> options chain DataFrame (strikes, bids, asks, Greeks, IV, OI)
|
|
|
|
|
+---> [Volatility Agent] --> IV Rank, IV Percentile, vol skew, SVI surface
|
|
|
|
|
+---> [Greeks Agent] --> 2nd-order Greeks (Charm, Vanna, Volga) per strike
|
|
|
|
|
+---> [GEX Agent] --> Net GEX, Call/Put Walls, gamma flip zone, regime
|
|
|
|
|
+---> [Flow Agent] --> Unusual activity signals, volume/OI anomalies
|
|
|
|
|
v
|
|
[Strategy Selection Agent] <-- all analysis outputs
|
|
|
|
|
v
|
|
[Options Debate] (bull vs bear on options thesis, configurable rounds)
|
|
|
|
|
v
|
|
[Options Portfolio Manager] --> final recommendation
|
|
|
|
|
v
|
|
Output: specific contracts + alternative ranges + reasoning chain
|
|
```
|
|
|
|
## Patterns to Follow
|
|
|
|
### Pattern 1: Agent Factory Closures (existing pattern)
|
|
|
|
**What:** Each agent is created via a `create_*()` closure that captures LLM client and tools.
|
|
**When:** Always -- this is the established pattern in the codebase.
|
|
**Example:**
|
|
```python
|
|
def create_volatility_analyst(llm_client, tools):
|
|
"""Create volatility analysis agent with options-specific tools."""
|
|
system_prompt = VOLATILITY_ANALYST_PROMPT
|
|
|
|
def volatility_analyst(state):
|
|
chain_data = state["options_chain"]
|
|
# Compute IV metrics using tools
|
|
iv_rank = tools["compute_iv_rank"](chain_data, state["ticker"])
|
|
# LLM interprets the metrics
|
|
response = llm_client.invoke([
|
|
SystemMessage(content=system_prompt),
|
|
HumanMessage(content=format_iv_analysis(iv_rank, chain_data))
|
|
])
|
|
return {"volatility_analysis": response.content}
|
|
|
|
return volatility_analyst
|
|
```
|
|
|
|
### Pattern 2: Vendor-Routed Data Layer (existing pattern)
|
|
|
|
**What:** Data retrieval goes through a routing layer that selects the vendor based on config.
|
|
**When:** For all options data retrieval -- Tradier is primary, tastytrade is fallback/supplement.
|
|
**Example:**
|
|
```python
|
|
# In tradingagents/dataflows/config.py (extend existing)
|
|
# Add "tradier" to data_vendors options
|
|
|
|
def get_options_chain(ticker, expiration, config):
|
|
vendor = config.get("options_vendor", "tradier")
|
|
if vendor == "tradier":
|
|
return tradier.get_chain(ticker, expiration)
|
|
elif vendor == "tastytrade":
|
|
return tastytrade.get_chain(ticker, expiration)
|
|
```
|
|
|
|
### Pattern 3: Computation Modules as Pure Functions
|
|
|
|
**What:** GEX, Greeks, vol surface calculations are stateless pure functions that take DataFrames and return DataFrames.
|
|
**When:** All options math modules.
|
|
**Why:** Testable without LLM calls, cacheable, composable.
|
|
```python
|
|
# tradingagents/options/gex.py
|
|
def compute_gex(chain_df: pd.DataFrame, spot: float) -> pd.DataFrame:
|
|
"""Pure function: chain DataFrame in, GEX DataFrame out."""
|
|
chain_df["call_gex"] = chain_df["gamma"] * chain_df["open_interest"] * 100 * spot**2 * 0.01
|
|
chain_df["put_gex"] = -chain_df["gamma"] * chain_df["open_interest"] * 100 * spot**2 * 0.01
|
|
# ... aggregate, find walls, flip zone
|
|
return gex_df
|
|
```
|
|
|
|
### Pattern 4: 5-Tier Rating Scale (existing pattern)
|
|
|
|
**What:** All analysis outputs use BUY/OVERWEIGHT/HOLD/UNDERWEIGHT/SELL scale.
|
|
**When:** Options agents should output ratings consistent with existing stock analysts.
|
|
**Adaptation:** Options-specific interpretation:
|
|
- BUY = strong bullish options position recommended (long calls, bull spreads)
|
|
- OVERWEIGHT = moderately bullish (covered calls, bull put spreads)
|
|
- HOLD = neutral strategies (iron condors, straddles if high IV)
|
|
- UNDERWEIGHT = moderately bearish (bear call spreads, protective puts)
|
|
- SELL = strong bearish (long puts, bear spreads)
|
|
|
|
## Anti-Patterns to Avoid
|
|
|
|
### Anti-Pattern 1: Monolithic Options Agent
|
|
|
|
**What:** Single agent that does all options analysis (Greeks + GEX + flow + strategy).
|
|
**Why bad:** Unmanageable prompts, impossible to debug, cannot run analyses in parallel.
|
|
**Instead:** Separate specialized agents with focused prompts, composed via LangGraph.
|
|
|
|
### Anti-Pattern 2: LLM Doing Math
|
|
|
|
**What:** Asking the LLM to calculate Greeks, GEX, or IV metrics.
|
|
**Why bad:** LLMs are unreliable at arithmetic. A single wrong calculation cascades into bad recommendations.
|
|
**Instead:** All math in Python (blackscholes, numpy, scipy). LLM only interprets pre-computed results.
|
|
|
|
### Anti-Pattern 3: Hardcoded Strike Selection
|
|
|
|
**What:** Agent tools that select specific strikes based on rigid rules (e.g., "always pick ATM +/- 2 strikes").
|
|
**Why bad:** Different strategies need different strike selection logic. Iron condor wings vs vertical spread width depend on IV, premium targets, and risk tolerance.
|
|
**Instead:** Provide the LLM agent with a range of strikes and their computed metrics; let it reason about selection within the strategy context.
|
|
|
|
### Anti-Pattern 4: Synchronous Tastytrade Streaming in Batch Flow
|
|
|
|
**What:** Starting a DXLink WebSocket connection for every `propagate()` call.
|
|
**Why bad:** WebSocket setup overhead (auth, handshake, subscription) for a single snapshot is wasteful. Adds 2-5 seconds per call.
|
|
**Instead:** Use Tradier REST for batch flow. Only use tastytrade streaming if building a persistent session or needing sub-minute freshness.
|
|
|
|
## Scalability Considerations
|
|
|
|
| Concern | Current (single ticker) | Multi-ticker (10 tickers) | High volume (50+ tickers) |
|
|
|---------|------------------------|--------------------------|---------------------------|
|
|
| API rate limits | Tradier: ~2 req/ticker (chain + expirations), well within 120 req/min | 20 requests, still fine | 100+ requests, need queuing/throttling |
|
|
| Chain data size | ~200 strikes per expiry, 5-8 expiries = 1000-1600 rows | 10x = 10-16K rows, fine in memory | 50x = manageable but cache aggressively |
|
|
| GEX computation | Sub-second numpy vectorization | Still sub-second | Still sub-second; numpy handles millions of rows |
|
|
| LLM calls per analysis | ~6 agents x 1 call each = 6 LLM calls | 60 LLM calls, significant latency | Need batching or parallel execution |
|
|
| Tastytrade WebSocket | Single subscription, minimal overhead | 10 subscriptions, fine | May hit subscription limits |
|
|
|
|
## Sources
|
|
|
|
- Existing codebase patterns in `tradingagents/agents/`, `tradingagents/graph/`, `tradingagents/dataflows/`
|
|
- [LangGraph StateGraph documentation](https://langchain-ai.github.io/langgraph/)
|
|
- [Tradier API rate limits](https://docs.tradier.com/)
|