option-pdf-vis / src /ai /prompts.py
Arjit
Production-ready Option-Implied PDF Visualizer
8e1643b
"""
Prompt templates for AI interpretation of option-implied PDFs.
"""
from typing import Dict, List, Optional
from datetime import datetime
PDF_ANALYSIS_PROMPT = """You are a derivatives analyst interpreting option-implied probability densities for institutional clients.
Current Market Context:
- Ticker: {ticker}
- Spot Price: ${spot:.2f}
- Analysis Date: {date}
- Days to Expiration: {days_to_expiry}
PDF Statistics:
- Expected Price (Mean): ${mean:.2f} ({drift:+.2f}% from spot)
- Standard Deviation: ${std:.2f}
- Implied Move: ±{implied_move:.2f}%
- Implied Volatility: {implied_vol:.2f}%
Distribution Shape:
- Skewness: {skew:.3f} (negative = left tail heavy, positive = right tail heavy)
- Excess Kurtosis: {kurtosis:.3f} (positive = fat tails, negative = thin tails)
Tail Risk Analysis:
- P(Down >5%): {prob_down_5:.2f}%
- P(Up >5%): {prob_up_5:.2f}%
- P(Down >10%): {prob_down_10:.2f}%
- P(Up >10%): {prob_up_10:.2f}%
Confidence Intervals:
- 68% CI: ${ci_68_lower:.2f} - ${ci_68_upper:.2f}
- 95% CI: ${ci_95_lower:.2f} - ${ci_95_upper:.2f}
{historical_context}
Provide a comprehensive analysis covering:
1. Market Sentiment (2-3 sentences)
- What does the PDF shape reveal about current market positioning?
- Is there directional bias or are markets balanced?
2. Tail Risk Assessment (2-3 sentences)
- Compare tail probabilities to a normal distribution
- Are extreme moves priced in or underpriced?
- What does the skewness/kurtosis tell us?
3. Trading Implications (2-3 sentences)
- What strategies are favored by this probability distribution?
- Where are the areas of mispricing or opportunity?
{historical_comparison}
4. Key Takeaway (1 sentence)
- Single most important insight for traders
Be specific and quantitative. Reference the actual statistics provided. No generic fluff.
"""
HISTORICAL_COMPARISON_PROMPT = """
Historical Pattern Match:
The current PDF shape is {similarity:.1f}% similar to {match_date}, when:
- Market conditions: {match_description}
- Subsequent move: {actual_move}
- Prediction accuracy: {accuracy}
Consider this historical precedent in your analysis.
"""
MULTI_EXPIRATION_PROMPT = """You are analyzing the term structure of option-implied probabilities across multiple expirations.
Market: {ticker} @ ${spot:.2f}
Analysis Date: {date}
Expiration Structure:
{expiration_data}
Term Structure Observations:
- Volatility term structure: {vol_term_structure}
- Skew evolution: {skew_evolution}
- Tail risk progression: {tail_evolution}
Analyze:
1. Term Structure Pattern (2-3 sentences)
- How does implied volatility change across time?
- What does this reveal about market expectations?
2. Risk Evolution (2-3 sentences)
- How do tail risks evolve with time?
- Are near-term or longer-term expirations pricing more risk?
3. Structural Insights (2-3 sentences)
- Any anomalies or dislocations in the term structure?
- What trading opportunities does this create?
4. Summary (1 sentence)
- Key insight from the term structure analysis
Be concise and quantitative.
"""
PREDICTION_TRACKING_PROMPT = """You are evaluating the accuracy of a past probability forecast.
Original Forecast ({forecast_date}):
- Predicted probability: {predicted_prob:.2f}%
- Condition: {condition}
- Target level: ${target_level:.2f}
- Expiration: {expiration_date}
Actual Outcome ({evaluation_date}):
- Final price: ${final_price:.2f}
- Condition met: {outcome}
- Prediction accuracy: {accuracy}
Provide a brief assessment (3-4 sentences):
1. Was the forecast directionally correct?
2. What factors may have contributed to accuracy/inaccuracy?
3. What can we learn for future forecasts?
Be honest and analytical.
"""
def format_pdf_analysis_prompt(
ticker: str,
spot: float,
stats: Dict[str, float],
days_to_expiry: int,
historical_matches: Optional[List[Dict]] = None
) -> str:
"""
Format the main PDF analysis prompt.
Args:
ticker: Ticker symbol
spot: Current spot price
stats: PDF statistics dictionary
days_to_expiry: Days to expiration
historical_matches: Optional list of historical pattern matches
Returns:
Formatted prompt string
"""
# Format historical context
historical_context = ""
if historical_matches and len(historical_matches) > 0:
historical_context = "Historical Pattern Matches:\n"
for i, match in enumerate(historical_matches[:3], 1):
historical_context += f"{i}. {match['date']}: {match['similarity']:.0f}% similar - {match['description']}\n"
else:
historical_context = "No significant historical pattern matches found."
# Format historical comparison
historical_comparison = ""
if historical_matches and len(historical_matches) > 0:
best_match = historical_matches[0]
historical_comparison = HISTORICAL_COMPARISON_PROMPT.format(
similarity=best_match['similarity'] * 100,
match_date=best_match['date'],
match_description=best_match.get('description', 'N/A'),
actual_move=best_match.get('actual_move', 'N/A'),
accuracy=best_match.get('accuracy', 'N/A')
)
# Format main prompt
return PDF_ANALYSIS_PROMPT.format(
ticker=ticker,
spot=spot,
date=datetime.now().strftime('%Y-%m-%d'),
days_to_expiry=days_to_expiry,
mean=stats['mean'],
drift=stats.get('risk_neutral_drift_pct', 0),
std=stats['std'],
implied_move=stats['implied_move_pct'],
implied_vol=stats['implied_volatility'] * 100,
skew=stats['skewness'],
kurtosis=stats['excess_kurtosis'],
prob_down_5=stats['prob_down_5pct'] * 100,
prob_up_5=stats['prob_up_5pct'] * 100,
prob_down_10=stats['prob_down_10pct'] * 100,
prob_up_10=stats['prob_up_10pct'] * 100,
ci_68_lower=stats['ci_68_lower'],
ci_68_upper=stats['ci_68_upper'],
ci_95_lower=stats['ci_95_lower'],
ci_95_upper=stats['ci_95_upper'],
historical_context=historical_context,
historical_comparison=historical_comparison
)
def format_multi_expiration_prompt(
ticker: str,
spot: float,
expiration_data: List[Dict[str, any]]
) -> str:
"""
Format multi-expiration analysis prompt.
Args:
ticker: Ticker symbol
spot: Current spot price
expiration_data: List of dicts with stats for each expiration
Returns:
Formatted prompt string
"""
# Format expiration data table
exp_table = ""
vols = []
skews = []
for exp in expiration_data:
days = exp['days_to_expiry']
stats = exp['stats']
exp_table += f" {days}D: IV={stats['implied_volatility']*100:.1f}%, "
exp_table += f"Skew={stats['skewness']:.2f}, "
exp_table += f"Move=±{stats['implied_move_pct']:.1f}%\n"
vols.append(stats['implied_volatility'] * 100)
skews.append(stats['skewness'])
# Analyze term structure patterns
if len(vols) >= 2:
vol_trend = "upward" if vols[-1] > vols[0] else "downward" if vols[-1] < vols[0] else "flat"
vol_term_structure = f"{vol_trend} ({vols[0]:.1f}% → {vols[-1]:.1f}%)"
else:
vol_term_structure = "insufficient data"
if len(skews) >= 2:
skew_trend = "increasing" if skews[-1] > skews[0] else "decreasing"
skew_evolution = f"{skew_trend} ({skews[0]:.2f}{skews[-1]:.2f})"
else:
skew_evolution = "insufficient data"
# Tail risk evolution
near_term_down = expiration_data[0]['stats']['prob_down_5pct'] * 100
far_term_down = expiration_data[-1]['stats']['prob_down_5pct'] * 100
tail_evolution = f"5% down risk: {near_term_down:.1f}% (near) → {far_term_down:.1f}% (far)"
return MULTI_EXPIRATION_PROMPT.format(
ticker=ticker,
spot=spot,
date=datetime.now().strftime('%Y-%m-%d'),
expiration_data=exp_table,
vol_term_structure=vol_term_structure,
skew_evolution=skew_evolution,
tail_evolution=tail_evolution
)
def format_prediction_tracking_prompt(
forecast_date: str,
predicted_prob: float,
condition: str,
target_level: float,
expiration_date: str,
evaluation_date: str,
final_price: float,
outcome: bool
) -> str:
"""
Format prediction tracking evaluation prompt.
Args:
forecast_date: Date when forecast was made
predicted_prob: Predicted probability (0-1)
condition: Condition type ('above' or 'below')
target_level: Target price level
expiration_date: Original expiration date
evaluation_date: Date of evaluation
final_price: Actual final price
outcome: Whether condition was met
Returns:
Formatted prompt string
"""
accuracy = "Correct" if (
(condition == 'above' and final_price > target_level and predicted_prob > 0.5) or
(condition == 'below' and final_price < target_level and predicted_prob > 0.5) or
(condition == 'above' and final_price <= target_level and predicted_prob <= 0.5) or
(condition == 'below' and final_price >= target_level and predicted_prob <= 0.5)
) else "Incorrect"
return PREDICTION_TRACKING_PROMPT.format(
forecast_date=forecast_date,
predicted_prob=predicted_prob * 100,
condition=f"Price {condition} ${target_level:.2f}",
target_level=target_level,
expiration_date=expiration_date,
evaluation_date=evaluation_date,
final_price=final_price,
outcome="Yes" if outcome else "No",
accuracy=accuracy
)
# System prompts for different analysis modes
SYSTEM_PROMPTS = {
'standard': "You are an expert derivatives analyst specializing in option-implied probability analysis. Provide clear, quantitative insights.",
'conservative': "You are a risk-focused derivatives analyst. Emphasize downside protection and tail risk management.",
'aggressive': "You are a returns-focused derivatives analyst. Identify asymmetric opportunities and mispriced volatility.",
'educational': "You are a derivatives educator. Explain concepts clearly while maintaining analytical rigor."
}
if __name__ == "__main__":
# Test prompt formatting
print("Testing prompt templates...\n")
# Sample statistics
stats = {
'mean': 451.5,
'std': 15.2,
'implied_move_pct': 3.38,
'implied_volatility': 0.20,
'skewness': -0.15,
'excess_kurtosis': 0.5,
'prob_down_5pct': 0.18,
'prob_up_5pct': 0.22,
'prob_down_10pct': 0.08,
'prob_up_10pct': 0.10,
'ci_68_lower': 436.3,
'ci_68_upper': 466.7,
'ci_95_lower': 421.1,
'ci_95_upper': 481.9,
'risk_neutral_drift_pct': 0.3
}
# Test main analysis prompt
prompt = format_pdf_analysis_prompt(
ticker="SPY",
spot=450.0,
stats=stats,
days_to_expiry=30,
historical_matches=[{
'date': '2023-10-15',
'similarity': 0.85,
'description': 'Pre-earnings uncertainty',
'actual_move': '-2.5%',
'accuracy': 'High'
}]
)
print("=== PDF Analysis Prompt ===")
print(prompt[:500] + "...\n")
# Test multi-expiration prompt
exp_data = [
{'days_to_expiry': 15, 'stats': stats},
{'days_to_expiry': 30, 'stats': stats},
{'days_to_expiry': 60, 'stats': stats}
]
prompt2 = format_multi_expiration_prompt("SPY", 450.0, exp_data)
print("=== Multi-Expiration Prompt ===")
print(prompt2[:300] + "...\n")
print("✅ Prompt template test passed!")