Fix projection plot bugs.
This commit is contained in:
@@ -646,14 +646,20 @@ def create_plots(df, start=None, end=None, project_days=365):
|
||||
# Set up the style
|
||||
plt.style.use("seaborn-v0_8")
|
||||
|
||||
# Create figure with adjusted size for additional subplot
|
||||
_ = plt.figure(figsize=(15, 15)) # Increased height to accommodate new subplot
|
||||
# Create figure with adjusted size and spacing
|
||||
fig = plt.figure(figsize=(15, 15))
|
||||
|
||||
# Use GridSpec for better control over subplot spacing
|
||||
gs = plt.GridSpec(5, 1, height_ratios=[3, 1.5, 1.5, 1.5, 2], hspace=0.4)
|
||||
|
||||
# Date range for titles
|
||||
hist_date_range = f" ({plot_df['Date'].min().strftime('%Y-%m-%d')} to {plot_df['Date'].max().strftime('%Y-%m-%d')})"
|
||||
|
||||
# Calculate full date range including projections
|
||||
full_date_range = pd.date_range(plot_df["Date"].min(), projections.index.max())
|
||||
|
||||
# 1. Price history and projections (log scale)
|
||||
ax1 = plt.subplot(4, 1, 1)
|
||||
ax1 = fig.add_subplot(gs[0])
|
||||
|
||||
# Plot historical prices
|
||||
ax1.semilogy(plot_df["Date"], plot_df["Close"], "b-", label="Historical Price")
|
||||
@@ -703,22 +709,43 @@ def create_plots(df, start=None, end=None, project_days=365):
|
||||
ax1.set_title("Bitcoin Price History and Projections (Log Scale)" + hist_date_range)
|
||||
ax1.legend(fontsize=8)
|
||||
|
||||
# Set x-axis limits to full range
|
||||
ax1.set_xlim(full_date_range[0], full_date_range[-1])
|
||||
ax1.tick_params(axis="x", rotation=45)
|
||||
|
||||
# 3. Rolling volatility
|
||||
ax3 = plt.subplot(5, 1, 2)
|
||||
ax3 = fig.add_subplot(gs[1])
|
||||
ax3.plot(
|
||||
plot_df["Date"],
|
||||
plot_df["Rolling_Volatility_30d"],
|
||||
"r-",
|
||||
label="30-Day Rolling Volatility",
|
||||
)
|
||||
|
||||
# Add empty space to match price plot x-axis
|
||||
ax3.set_xlim(full_date_range[0], full_date_range[-1])
|
||||
|
||||
# Add vertical line to mark start of projections
|
||||
ax3.axvline(plot_df["Date"].max(), color="gray", linestyle="--", alpha=0.5)
|
||||
ax3.text(
|
||||
plot_df["Date"].max(),
|
||||
ax3.get_ylim()[1],
|
||||
"Projection Start",
|
||||
rotation=90,
|
||||
va="top",
|
||||
ha="right",
|
||||
alpha=0.7,
|
||||
)
|
||||
|
||||
ax3.set_title("30-Day Rolling Volatility (Annualized)" + hist_date_range)
|
||||
ax3.set_ylabel("Volatility")
|
||||
ax3.grid(True)
|
||||
ax3.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: "{:.0%}".format(y)))
|
||||
ax3.legend()
|
||||
ax3.tick_params(axis="x", rotation=45)
|
||||
|
||||
# 4. Returns distribution
|
||||
ax4 = plt.subplot(5, 1, 3)
|
||||
ax4 = fig.add_subplot(gs[2])
|
||||
returns_mean = plot_df["Daily_Return"].mean()
|
||||
returns_std = plot_df["Daily_Return"].std()
|
||||
filtered_returns = plot_df["Daily_Return"][
|
||||
@@ -746,7 +773,7 @@ def create_plots(df, start=None, end=None, project_days=365):
|
||||
)
|
||||
|
||||
# 5. Projection ranges
|
||||
ax5 = plt.subplot(5, 1, 4)
|
||||
ax5 = fig.add_subplot(gs[3:]) # Use last two grid spaces for larger plot
|
||||
timepoints = np.array(range(30, project_days, 30))
|
||||
timepoints = timepoints[timepoints <= project_days]
|
||||
|
||||
@@ -786,13 +813,13 @@ def create_plots(df, start=None, end=None, project_days=365):
|
||||
ax5.grid(True, alpha=0.3)
|
||||
ax5.set_xticks(timepoints)
|
||||
|
||||
# Adjust layout
|
||||
plt.tight_layout(h_pad=1.0) # Increased spacing between subplots
|
||||
|
||||
# Save the plot
|
||||
start_str = start if start else plot_df["Date"].min().strftime("%Y-%m-%d")
|
||||
end_str = end if end else plot_df["Date"].max().strftime("%Y-%m-%d")
|
||||
filename = f"bitcoin_analysis_{start_str}_to_{end_str}_with_projections.png"
|
||||
|
||||
# Use tight_layout with adjusted parameters
|
||||
plt.tight_layout(pad=2.0)
|
||||
plt.savefig(filename, dpi=300, bbox_inches="tight")
|
||||
plt.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user