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

# Data provided
open_prices = np.array([83840.59, 84088.79, 84223.38, 86845.93, 82715.03, 84010.02, 82574.52])
close_prices = np.array([86082.50, 83840.59, 84088.79, 84223.39, 86845.94, 82715.03, 84010.03])

# Create dates (March 17-23, 2024)
end_date = datetime(2024, 3, 23)
start_date = end_date - timedelta(days=6)
date_range = [start_date + timedelta(days=i) for i in range(7)]
date_labels = [date.strftime('%m-%d') for date in date_range]

# Calculate additional metrics
daily_change = close_prices - open_prices
daily_change_pct = (daily_change / open_prices) * 100
high_prices = np.maximum(open_prices, close_prices)
low_prices = np.minimum(open_prices, close_prices)
price_range = high_prices - low_prices

# Create DataFrame for easier analysis
df = pd.DataFrame({
    'Date': date_range,
    'Open': open_prices,
    'Close': close_prices,
    'High': high_prices,
    'Low': low_prices,
    'Change': daily_change,
    'Change%': daily_change_pct,
    'Range': price_range
})

# Determine if each day is up or down
is_up_day = close_prices > open_prices
colors = ['green' if up else 'red' for up in is_up_day]
edge_colors = ['darkgreen' if up else 'darkred' for up in is_up_day]

# Create figure and primary axis
plt.figure(figsize=(14, 10))

# Style configuration
plt.style.use('seaborn-v0_8-darkgrid')
bg_color = '#f6f6f6'
text_color = '#333333'
title_color = '#000000'

# Set the background color
plt.gcf().patch.set_facecolor(bg_color)

# Main price subplot (top)
ax1 = plt.subplot2grid((3, 1), (0, 0), rowspan=2)

# Plot candlestick-like representation
for i in range(len(date_range)):
    # Plot the price range line (High to Low)
    ax1.plot([i, i], [low_prices[i], high_prices[i]], color=edge_colors[i], linewidth=2)
    
    # Plot the open-close body
    body_height = abs(close_prices[i] - open_prices[i])
    body_bottom = min(open_prices[i], close_prices[i])
    ax1.bar(i, body_height, bottom=body_bottom, color=colors[i], 
            width=0.6, edgecolor=edge_colors[i], linewidth=1.5, alpha=0.8)

# Plot the actual lines for open and close prices
ax1.plot(open_prices, 'o-', color='blue', alpha=0.7, linewidth=1.5, label='Open Price')
ax1.plot(close_prices, 'o-', color='purple', alpha=0.7, linewidth=1.5, label='Close Price')

# Add moving average line
ma5 = np.convolve(close_prices, np.ones(5)/5, mode='valid')
if len(ma5) > 0:
    ax1.plot(range(4, 7), ma5, 'o--', color='orange', linewidth=2.5, label='5-Day MA')

# Annotate key points
max_idx = np.argmax(high_prices)
min_idx = np.argmin(low_prices)
ax1.annotate(f'High: ${high_prices[max_idx]:.2f}', 
            xy=(max_idx, high_prices[max_idx]), 
            xytext=(max_idx+0.3, high_prices[max_idx]+500),
            arrowprops=dict(facecolor='black', shrink=0.05, width=1.5, headwidth=8), 
            fontsize=10)
ax1.annotate(f'Low: ${low_prices[min_idx]:.2f}', 
            xy=(min_idx, low_prices[min_idx]), 
            xytext=(min_idx+0.3, low_prices[min_idx]-500),
            arrowprops=dict(facecolor='black', shrink=0.05, width=1.5, headwidth=8), 
            fontsize=10)

# Configure the main price chart
ax1.set_xticks(range(len(date_labels)))
ax1.set_xticklabels([])  # Hide x-labels on the first plot
ax1.set_title('Bitcoin Price Analysis (March 17-23, 2024)', fontsize=16, fontweight='bold', color=title_color, pad=15)
ax1.set_ylabel('Price (USD)', fontsize=12, fontweight='bold', color=text_color)
ax1.grid(True, alpha=0.3)
ax1.legend(loc='upper left')

# Format y-axis to show dollar amounts
ax1.yaxis.set_major_formatter('${x:,.2f}')

# Add price statistics as text box
stats_text = (
    f"Average Close: ${np.mean(close_prices):.2f}\n"
    f"Price Range: ${np.max(high_prices) - np.min(low_prices):.2f}\n"
    f"Volatility: {np.std(close_prices):.2f}"
)
props = dict(boxstyle='round', facecolor='wheat', alpha=0.4)
ax1.text(0.02, 0.05, stats_text, transform=ax1.transAxes, fontsize=10,
        verticalalignment='bottom', bbox=props)

# Daily change subplot (bottom)
ax2 = plt.subplot2grid((3, 1), (2, 0), rowspan=1, sharex=ax1)
ax2.bar(range(len(daily_change)), daily_change, color=colors, alpha=0.7, width=0.6, edgecolor=edge_colors)

# Add percentage change annotations
for i, (change, pct) in enumerate(zip(daily_change, daily_change_pct)):
    ax2.annotate(f"{pct:.1f}%", 
                xy=(i, change), 
                xytext=(0, 5 if change >= 0 else -15),
                textcoords="offset points",
                ha='center', 
                fontsize=9, 
                fontweight='bold',
                color='darkgreen' if change >= 0 else 'darkred')

# Configure the daily change chart
ax2.axhline(y=0, color='black', linestyle='-', alpha=0.3)
ax2.set_xticks(range(len(date_labels)))
ax2.set_xticklabels(date_labels, rotation=45)
ax2.set_ylabel('Daily Change (USD)', fontsize=12, fontweight='bold', color=text_color)
ax2.grid(True, alpha=0.3)

# Add a legend for up/down days
legend_elements = [
    Patch(facecolor='green', edgecolor='darkgreen', label='Up Day'),
    Patch(facecolor='red', edgecolor='darkred', label='Down Day')
]
ax2.legend(handles=legend_elements, loc='upper right')

# Calculate and display summary statistics
total_change = close_prices[-1] - open_prices[0]
total_change_pct = (total_change / open_prices[0]) * 100
up_days = sum(is_up_day)
down_days = len(is_up_day) - up_days

summary_text = (
    f"Period Change: ${total_change:.2f} ({total_change_pct:.1f}%)\n"
    f"Up Days: {up_days}   Down Days: {down_days}"
)
props = dict(boxstyle='round', facecolor='lightblue', alpha=0.4)
ax2.text(0.02, 0.05, summary_text, transform=ax2.transAxes, fontsize=10,
        verticalalignment='bottom', bbox=props)

# Adjust layout
plt.tight_layout()
plt.subplots_adjust(hspace=0.1)

# Add a watermark
plt.figtext(0.5, 0.01, "Bitcoin Price Analysis - Created on 2025-03-30", 
           ha="center", fontsize=8, color="gray")

plt.show()