#!/usr/bin/env python3
"""
MU Overnight Edge - Complete Analysis with Charts
Generates all visualizations and sensitivity analysis
"""

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime, timedelta

# Styling
plt.style.use('dark_background')
COLORS = {
    'overnight': '#10b981',
    'intraday': '#f59e0b', 
    'buyhold': '#3b82f6',
    'drawdown': '#ef4444'
}

# Fetch data
ticker = "MU"
end_date = datetime.now()
start_date = end_date - timedelta(days=5*365)

print(f"Fetching {ticker} data...")
mu = yf.Ticker(ticker)
df = mu.history(start=start_date, end=end_date)
print(f"✓ Loaded {len(df)} trading days\n")

# Calculate returns
df['Overnight_Return'] = (df['Open'] - df['Close'].shift(1)) / df['Close'].shift(1)
df['Intraday_Return'] = (df['Close'] - df['Open']) / df['Open']
df['Daily_Return'] = df['Close'].pct_change()

# Cumulative performance
df['Overnight_Cum'] = (1 + df['Overnight_Return']).cumprod()
df['Intraday_Cum'] = (1 + df['Intraday_Return']).cumprod()
df['BuyHold_Cum'] = (1 + df['Daily_Return']).cumprod()

# Drawdowns
df['Overnight_DD'] = df['Overnight_Cum'] / df['Overnight_Cum'].cummax() - 1
df['Intraday_DD'] = df['Intraday_Cum'] / df['Intraday_Cum'].cummax() - 1
df['BuyHold_DD'] = df['BuyHold_Cum'] / df['BuyHold_Cum'].cummax() - 1

# Slippage scenarios (basis points)
slippage_scenarios = [0, 5, 10, 15, 20, 30, 50]  # bps
slippage_results = []

for slippage_bps in slippage_scenarios:
    slip = slippage_bps / 10000
    # Round-trip slippage: buy at close (slip), sell at open (slip)
    adj_return = df['Overnight_Return'] - (2 * slip)
    cum_return = (1 + adj_return).prod()
    cagr = (cum_return ** (252 / len(df))) - 1
    slippage_results.append({
        'slippage_bps': slippage_bps,
        'final_value': cum_return * 1000,
        'cagr': cagr * 100
    })

slip_df = pd.DataFrame(slippage_results)

# =============================================================================
# FIGURE 1: Cumulative Returns
# =============================================================================
fig1, ax1 = plt.subplots(figsize=(14, 7))
ax1.plot(df.index, df['Overnight_Cum'] * 1000, 
         color=COLORS['overnight'], linewidth=2.5, label='🌙 Overnight (Close→Open)')
ax1.plot(df.index, df['Intraday_Cum'] * 1000, 
         color=COLORS['intraday'], linewidth=2.5, label='☀️ Intraday (Open→Close)')
ax1.plot(df.index, df['BuyHold_Cum'] * 1000, 
         color=COLORS['buyhold'], linewidth=2.5, label='📊 Buy & Hold', linestyle='--', alpha=0.7)

ax1.axhline(1000, color='white', linestyle=':', alpha=0.3, linewidth=1)
ax1.set_ylabel('Portfolio Value ($)', fontsize=12, fontweight='bold')
ax1.set_xlabel('Date', fontsize=12, fontweight='bold')
ax1.set_title('MU: Overnight vs Intraday Returns (2021-2026)\nStarting Capital: $1,000', 
              fontsize=14, fontweight='bold', pad=20)
ax1.legend(fontsize=11, loc='upper left')
ax1.grid(alpha=0.2)
ax1.set_ylim(bottom=0)

# Add annotations
final_overnight = df['Overnight_Cum'].iloc[-1] * 1000
final_intraday = df['Intraday_Cum'].iloc[-1] * 1000
final_buyhold = df['BuyHold_Cum'].iloc[-1] * 1000

ax1.annotate(f'${final_overnight:,.0f}\n(+{(final_overnight/1000-1)*100:.0f}%)', 
             xy=(df.index[-1], final_overnight),
             xytext=(10, 0), textcoords='offset points',
             color=COLORS['overnight'], fontweight='bold', fontsize=10)

ax1.annotate(f'${final_intraday:,.0f}\n(+{(final_intraday/1000-1)*100:.0f}%)', 
             xy=(df.index[-1], final_intraday),
             xytext=(10, -20), textcoords='offset points',
             color=COLORS['intraday'], fontweight='bold', fontsize=10)

plt.tight_layout()
plt.savefig('/tmp/mu_overnight_cumulative.png', dpi=150, bbox_inches='tight', facecolor='#0d1117')
print("✓ Saved: mu_overnight_cumulative.png")
plt.close()

# =============================================================================
# FIGURE 2: Drawdown Analysis
# =============================================================================
fig2, (ax2a, ax2b) = plt.subplots(2, 1, figsize=(14, 10), sharex=True)

# Panel A: Overnight drawdown
ax2a.fill_between(df.index, df['Overnight_DD'] * 100, 0, 
                  color=COLORS['drawdown'], alpha=0.6)
ax2a.plot(df.index, df['Overnight_DD'] * 100, 
          color=COLORS['drawdown'], linewidth=2)
ax2a.set_ylabel('Drawdown (%)', fontsize=12, fontweight='bold')
ax2a.set_title('🌙 Overnight Strategy Drawdown', fontsize=12, fontweight='bold')
ax2a.grid(alpha=0.2)
ax2a.axhline(0, color='white', linestyle=':', alpha=0.5, linewidth=1)

max_dd_overnight = df['Overnight_DD'].min() * 100
ax2a.annotate(f'Max DD: {max_dd_overnight:.1f}%',
             xy=(df['Overnight_DD'].idxmin(), max_dd_overnight),
             xytext=(10, -20), textcoords='offset points',
             color='white', fontweight='bold',
             bbox=dict(boxstyle='round,pad=0.5', facecolor=COLORS['drawdown'], alpha=0.8))

# Panel B: Intraday drawdown
ax2b.fill_between(df.index, df['Intraday_DD'] * 100, 0, 
                  color=COLORS['intraday'], alpha=0.6)
ax2b.plot(df.index, df['Intraday_DD'] * 100, 
          color=COLORS['intraday'], linewidth=2)
ax2b.set_ylabel('Drawdown (%)', fontsize=12, fontweight='bold')
ax2b.set_xlabel('Date', fontsize=12, fontweight='bold')
ax2b.set_title('☀️ Intraday Strategy Drawdown', fontsize=12, fontweight='bold')
ax2b.grid(alpha=0.2)
ax2b.axhline(0, color='white', linestyle=':', alpha=0.5, linewidth=1)

max_dd_intraday = df['Intraday_DD'].min() * 100
ax2b.annotate(f'Max DD: {max_dd_intraday:.1f}%',
             xy=(df['Intraday_DD'].idxmin(), max_dd_intraday),
             xytext=(10, -20), textcoords='offset points',
             color='white', fontweight='bold',
             bbox=dict(boxstyle='round,pad=0.5', facecolor=COLORS['intraday'], alpha=0.8))

plt.tight_layout()
plt.savefig('/tmp/mu_overnight_drawdowns.png', dpi=150, bbox_inches='tight', facecolor='#0d1117')
print("✓ Saved: mu_overnight_drawdowns.png")
plt.close()

# =============================================================================
# FIGURE 3: Slippage Sensitivity Analysis
# =============================================================================
fig3, (ax3a, ax3b) = plt.subplots(1, 2, figsize=(14, 6))

# Panel A: Final value vs slippage
ax3a.plot(slip_df['slippage_bps'], slip_df['final_value'], 
          marker='o', markersize=8, linewidth=2.5, color=COLORS['overnight'])
ax3a.axhline(1000, color='white', linestyle='--', alpha=0.5, linewidth=1.5, label='Break-even')
ax3a.set_xlabel('Round-Trip Slippage (basis points)', fontsize=12, fontweight='bold')
ax3a.set_ylabel('Final Value ($1,000 start)', fontsize=12, fontweight='bold')
ax3a.set_title('Slippage Impact on Final Portfolio Value', fontsize=12, fontweight='bold')
ax3a.grid(alpha=0.2)
ax3a.legend(fontsize=10)

# Annotate break-even
breakeven_slip = slip_df[slip_df['final_value'] < 1000].iloc[0]['slippage_bps'] if len(slip_df[slip_df['final_value'] < 1000]) > 0 else None
if breakeven_slip:
    ax3a.axvline(breakeven_slip, color='red', linestyle=':', alpha=0.5, linewidth=1.5)
    ax3a.text(breakeven_slip, ax3a.get_ylim()[1] * 0.95, 
              f'Break-even:\n~{breakeven_slip:.0f} bps',
              ha='center', fontsize=9, color='red', fontweight='bold',
              bbox=dict(boxstyle='round,pad=0.5', facecolor='black', alpha=0.8))

# Panel B: CAGR vs slippage
ax3b.plot(slip_df['slippage_bps'], slip_df['cagr'], 
          marker='o', markersize=8, linewidth=2.5, color=COLORS['overnight'])
ax3b.axhline(0, color='white', linestyle='--', alpha=0.5, linewidth=1.5, label='0% CAGR')
ax3b.set_xlabel('Round-Trip Slippage (basis points)', fontsize=12, fontweight='bold')
ax3b.set_ylabel('CAGR (%)', fontsize=12, fontweight='bold')
ax3b.set_title('Slippage Impact on CAGR', fontsize=12, fontweight='bold')
ax3b.grid(alpha=0.2)
ax3b.legend(fontsize=10)

plt.tight_layout()
plt.savefig('/tmp/mu_overnight_slippage.png', dpi=150, bbox_inches='tight', facecolor='#0d1117')
print("✓ Saved: mu_overnight_slippage.png")
plt.close()

# =============================================================================
# FIGURE 4: Return Distribution
# =============================================================================
fig4, (ax4a, ax4b) = plt.subplots(1, 2, figsize=(14, 6))

# Panel A: Overnight returns histogram
ax4a.hist(df['Overnight_Return'] * 100, bins=50, color=COLORS['overnight'], alpha=0.7, edgecolor='white')
ax4a.axvline(df['Overnight_Return'].mean() * 100, color='white', linestyle='--', linewidth=2, label=f'Mean: {df["Overnight_Return"].mean()*100:.2f}%')
ax4a.set_xlabel('Overnight Return (%)', fontsize=12, fontweight='bold')
ax4a.set_ylabel('Frequency', fontsize=12, fontweight='bold')
ax4a.set_title('🌙 Overnight Return Distribution', fontsize=12, fontweight='bold')
ax4a.legend(fontsize=10)
ax4a.grid(alpha=0.2)

# Panel B: Intraday returns histogram
ax4b.hist(df['Intraday_Return'] * 100, bins=50, color=COLORS['intraday'], alpha=0.7, edgecolor='white')
ax4b.axvline(df['Intraday_Return'].mean() * 100, color='white', linestyle='--', linewidth=2, label=f'Mean: {df["Intraday_Return"].mean()*100:.2f}%')
ax4b.set_xlabel('Intraday Return (%)', fontsize=12, fontweight='bold')
ax4b.set_ylabel('Frequency', fontsize=12, fontweight='bold')
ax4b.set_title('☀️ Intraday Return Distribution', fontsize=12, fontweight='bold')
ax4b.legend(fontsize=10)
ax4b.grid(alpha=0.2)

plt.tight_layout()
plt.savefig('/tmp/mu_overnight_distribution.png', dpi=150, bbox_inches='tight', facecolor='#0d1117')
print("✓ Saved: mu_overnight_distribution.png")
plt.close()

# =============================================================================
# FIGURE 5: Rolling Sharpe Ratio
# =============================================================================
window = 60  # 60-day rolling window

df['Overnight_Rolling_Sharpe'] = (
    df['Overnight_Return'].rolling(window).mean() / 
    df['Overnight_Return'].rolling(window).std()
) * np.sqrt(252)

df['Intraday_Rolling_Sharpe'] = (
    df['Intraday_Return'].rolling(window).mean() / 
    df['Intraday_Return'].rolling(window).std()
) * np.sqrt(252)

fig5, ax5 = plt.subplots(figsize=(14, 7))
ax5.plot(df.index, df['Overnight_Rolling_Sharpe'], 
         color=COLORS['overnight'], linewidth=2, label='🌙 Overnight', alpha=0.9)
ax5.plot(df.index, df['Intraday_Rolling_Sharpe'], 
         color=COLORS['intraday'], linewidth=2, label='☀️ Intraday', alpha=0.9)
ax5.axhline(0, color='white', linestyle=':', alpha=0.3, linewidth=1)
ax5.axhline(1, color='white', linestyle='--', alpha=0.3, linewidth=1, label='Sharpe = 1')
ax5.set_ylabel('Rolling Sharpe Ratio (60-day)', fontsize=12, fontweight='bold')
ax5.set_xlabel('Date', fontsize=12, fontweight='bold')
ax5.set_title('MU: Rolling Sharpe Ratio Comparison', fontsize=14, fontweight='bold', pad=20)
ax5.legend(fontsize=11, loc='upper left')
ax5.grid(alpha=0.2)

plt.tight_layout()
plt.savefig('/tmp/mu_overnight_rolling_sharpe.png', dpi=150, bbox_inches='tight', facecolor='#0d1117')
print("✓ Saved: mu_overnight_rolling_sharpe.png")
plt.close()

# =============================================================================
# Print Summary Statistics
# =============================================================================
print("\n" + "="*70)
print("SUMMARY STATISTICS")
print("="*70)

stats_data = {
    'Metric': [
        'Final Value ($1,000)',
        'CAGR (%)',
        'Annualized Volatility (%)',
        'Sharpe Ratio',
        'Max Drawdown (%)',
        'Avg Daily Return (%)',
        'Win Rate (%)',
        'Best Day (%)',
        'Worst Day (%)',
    ],
    'Overnight': [
        f"${df['Overnight_Cum'].iloc[-1] * 1000:,.0f}",
        f"{((df['Overnight_Cum'].iloc[-1] ** (252/len(df))) - 1) * 100:.2f}",
        f"{df['Overnight_Return'].std() * np.sqrt(252) * 100:.2f}",
        f"{(df['Overnight_Return'].mean() / df['Overnight_Return'].std()) * np.sqrt(252):.2f}",
        f"{df['Overnight_DD'].min() * 100:.2f}",
        f"{df['Overnight_Return'].mean() * 100:.3f}",
        f"{(df['Overnight_Return'] > 0).sum() / len(df) * 100:.1f}",
        f"{df['Overnight_Return'].max() * 100:.2f}",
        f"{df['Overnight_Return'].min() * 100:.2f}",
    ],
    'Intraday': [
        f"${df['Intraday_Cum'].iloc[-1] * 1000:,.0f}",
        f"{((df['Intraday_Cum'].iloc[-1] ** (252/len(df))) - 1) * 100:.2f}",
        f"{df['Intraday_Return'].std() * np.sqrt(252) * 100:.2f}",
        f"{(df['Intraday_Return'].mean() / df['Intraday_Return'].std()) * np.sqrt(252):.2f}",
        f"{df['Intraday_DD'].min() * 100:.2f}",
        f"{df['Intraday_Return'].mean() * 100:.3f}",
        f"{(df['Intraday_Return'] > 0).sum() / len(df) * 100:.1f}",
        f"{df['Intraday_Return'].max() * 100:.2f}",
        f"{df['Intraday_Return'].min() * 100:.2f}",
    ]
}

stats_df = pd.DataFrame(stats_data)
print(stats_df.to_string(index=False))

print("\n" + "="*70)
print("SLIPPAGE SENSITIVITY")
print("="*70)
print(slip_df.to_string(index=False))

print("\n✓ Analysis complete. 5 charts saved to /tmp/\n")
