POTE/docs/PR4_PLAN.md
ilia 02c10c85d6 Add data update tools and Phase 2 plan
- scripts/add_custom_trades.py: Manual trade entry
- scripts/scrape_alternative_sources.py: CSV import
- scripts/daily_update.sh: Automated daily updates
- docs/09_data_updates.md: Complete update guide
- docs/PR4_PLAN.md: Phase 2 analytics plan

Enables users to add representatives and set up auto-updates
2025-12-15 10:39:18 -05:00

246 lines
6.4 KiB
Markdown

# PR4: Phase 2 - Analytics Foundation
## Goal
Calculate abnormal returns and performance metrics for congressional trades.
## What We'll Build
### 1. Return Calculator (`src/pote/analytics/returns.py`)
```python
class ReturnCalculator:
"""Calculate returns for trades over various windows."""
def calculate_trade_return(
self,
trade: Trade,
window_days: int = 90
) -> dict:
"""
Calculate return for a single trade.
Returns:
{
'ticker': 'NVDA',
'transaction_date': '2024-01-15',
'window_days': 90,
'entry_price': 495.00,
'exit_price': 650.00,
'return_pct': 31.3,
'return_abs': 155.00
}
"""
pass
def calculate_benchmark_return(
self,
start_date: date,
end_date: date,
benchmark: str = "SPY" # S&P 500
) -> float:
"""Calculate benchmark return over period."""
pass
def calculate_abnormal_return(
self,
trade_return: float,
benchmark_return: float
) -> float:
"""Return - Benchmark = Abnormal Return (alpha)."""
return trade_return - benchmark_return
```
### 2. Performance Metrics (`src/pote/analytics/metrics.py`)
```python
class PerformanceMetrics:
"""Aggregate performance metrics by official, sector, etc."""
def official_performance(
self,
official_id: int,
window_days: int = 90
) -> dict:
"""
Aggregate stats for an official.
Returns:
{
'name': 'Nancy Pelosi',
'total_trades': 50,
'buy_trades': 35,
'sell_trades': 15,
'avg_return': 12.5,
'avg_abnormal_return': 5.2,
'win_rate': 0.68,
'total_value': 2500000,
'best_trade': {'ticker': 'NVDA', 'return': 85.3},
'worst_trade': {'ticker': 'META', 'return': -15.2}
}
"""
pass
def sector_analysis(self, window_days: int = 90) -> list:
"""Performance by sector (Tech, Healthcare, etc.)."""
pass
def timing_analysis(self) -> dict:
"""Analyze disclosure lag vs performance."""
pass
```
### 3. Benchmark Comparisons (`src/pote/analytics/benchmarks.py`)
```python
class BenchmarkComparison:
"""Compare official performance vs market indices."""
BENCHMARKS = {
'SPY': 'S&P 500',
'QQQ': 'NASDAQ-100',
'DIA': 'Dow Jones',
'IWM': 'Russell 2000'
}
def compare_to_market(
self,
official_id: int,
benchmark: str = 'SPY',
period_start: date = None
) -> dict:
"""
Compare official's returns to market.
Returns:
{
'official_return': 15.2,
'benchmark_return': 8.5,
'alpha': 6.7,
'sharpe_ratio': 1.35,
'win_rate_vs_market': 0.72
}
"""
pass
```
### 4. Database Schema Updates
Add `metrics_performance` table:
```sql
CREATE TABLE metrics_performance (
id SERIAL PRIMARY KEY,
official_id INTEGER REFERENCES officials(id),
security_id INTEGER REFERENCES securities(id),
trade_id INTEGER REFERENCES trades(id),
-- Return metrics
window_days INTEGER NOT NULL,
entry_price DECIMAL(15, 2),
exit_price DECIMAL(15, 2),
return_pct DECIMAL(10, 4),
return_abs DECIMAL(15, 2),
-- Benchmark comparison
benchmark_ticker VARCHAR(10),
benchmark_return_pct DECIMAL(10, 4),
abnormal_return_pct DECIMAL(10, 4), -- alpha
-- Calculated at
calculated_at TIMESTAMP,
INDEX(official_id, window_days),
INDEX(security_id, window_days),
INDEX(trade_id)
);
```
## Implementation Steps
1. **Create analytics module structure**
```
src/pote/analytics/
├── __init__.py
├── returns.py # Return calculations
├── metrics.py # Aggregate metrics
├── benchmarks.py # Benchmark comparisons
└── utils.py # Helper functions
```
2. **Add database migration**
```bash
alembic revision -m "add_performance_metrics_table"
```
3. **Implement return calculator**
- Fetch prices from database
- Calculate returns for various windows (30, 60, 90, 180 days)
- Handle edge cases (IPOs, delisting, missing data)
4. **Implement benchmark comparisons**
- Fetch benchmark data (SPY, QQQ, etc.)
- Calculate abnormal returns
- Statistical significance tests
5. **Create calculation scripts**
```bash
scripts/calculate_returns.py # Calculate all returns
scripts/update_metrics.py # Update performance table
scripts/analyze_official.py # Analyze specific official
```
6. **Add tests**
- Unit tests for calculators
- Integration tests with sample data
- Edge case handling
## Example Usage
```python
# Calculate returns for all trades
from pote.analytics.returns import ReturnCalculator
from pote.db import get_session
calculator = ReturnCalculator()
with next(get_session()) as session:
trades = session.query(Trade).all()
for trade in trades:
for window in [30, 60, 90]:
result = calculator.calculate_trade_return(trade, window)
print(f"{trade.official.name} {trade.security.ticker}: "
f"{result['return_pct']:.1f}% ({window}d)")
```
```python
# Get official performance summary
from pote.analytics.metrics import PerformanceMetrics
metrics = PerformanceMetrics()
pelosi_stats = metrics.official_performance(official_id=1, window_days=90)
print(f"Average Return: {pelosi_stats['avg_return']:.1f}%")
print(f"Alpha: {pelosi_stats['avg_abnormal_return']:.1f}%")
print(f"Win Rate: {pelosi_stats['win_rate']:.1%}")
```
## Success Criteria
- ✅ Can calculate returns for any trade + window
- ✅ Can compare to S&P 500 benchmark
- ✅ Can generate official performance summaries
- ✅ All calculations tested and accurate
- ✅ Performance data stored efficiently
- ✅ Documentation complete
## Timeline
- Implementation: 2-3 hours
- Testing: 1 hour
- Documentation: 30 minutes
- **Total: ~4 hours**
## Next Steps After PR4
**PR5**: Clustering & Behavioral Analysis
**PR6**: Research Signals (follow_research, avoid_risk, watch)
**PR7**: API & Dashboard