From 525d3ba634bd3db658ce3ea911c519a4eb965851 Mon Sep 17 00:00:00 2001 From: Sam Fredrickson Date: Tue, 26 Nov 2024 00:49:54 -0800 Subject: [PATCH] Add CDPR plot. --- model.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/model.py b/model.py index bee0242..f2c714d 100644 --- a/model.py +++ b/model.py @@ -688,10 +688,79 @@ def analyze_bitcoin_prices(csv_path): # Main plotting functions +def add_cdpr_plot(df, output: Output): + """ + Add a plot showing the Compounding Daily Periodic Rate (CDPR) over different time periods. + """ + plt.style.use("seaborn-v0_8") + fig, ax = plt.subplots(figsize=(15, 6)) + + # Calculate CDPR for different time periods + periods = [180, 360, 720] + cdpr = {} + + # Find the longest CDPR series length + max_period = max(periods) + + for period in periods: + daily_returns = df["Close"].pct_change().fillna(0) + cdpr[f"{period}d CDPR"] = ( + daily_returns.rolling(period).apply( + lambda x: (1 + x).prod() ** (1 / period) - 1, raw=True + ) + ) * 100 + + # Clip all CDPR series to the length of the longest one + cdpr[f"{period}d CDPR"] = cdpr[f"{period}d CDPR"][max_period:] + + # Find the non-NaN min and max CDPR values + cdpr_values = [values for values in cdpr.values()] + min_cdpr = np.nanmin([np.nanmin(values) for values in cdpr_values]) + max_cdpr = np.nanmax([np.nanmax(values) for values in cdpr_values]) + + # Ensure x-axis (dates) and y-axis (CDPR) have the same length + start_date = df["Date"].iloc[max_period:].min() + end_date = df["Date"].max() + plot_dates = pd.date_range(start=start_date, end=end_date, freq="D") + + # Plot CDPR lines + for label, values in cdpr.items(): + ax.plot(plot_dates, values, label=label) + + # Customize the plot + ax.set_title("Compounding Daily Periodic Rate (CDPR)") + ax.set_xlabel("Date") + ax.set_ylabel("CDPR (%)") + ax.grid(True, alpha=0.3) + + # Adjust y-axis tick marks and add shaded lines between ticks + yticks = list(np.arange(int(min_cdpr), int(max_cdpr) + 1, 0.5)) + ax.set_yticks(yticks) + ax.tick_params(axis="y", which="major", labelsize=8) + ax.set_yticklabels(["{:.1f}%".format(y) for y in yticks]) + + # Add shaded lines between tick marks + for i in range(1, len(yticks)): + ax.axhline( + y=yticks[i], color="lightgray", linestyle="--", linewidth=1, alpha=0.5 + ) + + ax.legend() + + # Save the plot + filename = output.named("bitcoin_cdpr_plot.png") + plt.tight_layout() + plt.savefig(filename, dpi=300, bbox_inches="tight") + plt.close() + + def create_plots(df, output: Output, start=None, end=None, project_days=365): """ Create enhanced plots including market maturity visualization. """ + # Add the new CDPR plot + add_cdpr_plot(df, output) + # Filter data based on date range mask = pd.Series(True, index=df.index) if start: