Guest User

Untitled

a guest
Nov 9th, 2026
134
0
5 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.26 KB | None | 0 0
  1. !pip -q install yfinance scipy matplotlib pandas numpy
  2.  
  3. import yfinance as yf
  4. import numpy as np
  5. import pandas as pd
  6. import matplotlib.pyplot as plt
  7. from scipy.optimize import minimize_scalar
  8. from datetime import datetime
  9.  
  10. GENESIS = pd.Timestamp("2009-01-03")
  11. START_DATE = "2014-09-17"
  12. END_DATE = "2032-01-01"
  13. FIT_YEARS = 5
  14.  
  15. LAMBDA_1 = 2.081
  16. LAMBDA_2 = 1.305
  17.  
  18. OMEGA_1 = 2 * np.pi / np.log(LAMBDA_1)
  19. OMEGA_2 = 2 * np.pi / np.log(LAMBDA_2)
  20.  
  21. DACOINMINSTER_COEFFICIENT = 4.42e-17
  22. DACOINMINSTER_EXPONENT = 5.6
  23.  
  24. PERRENOD_COEFFICIENT = 0.00688
  25. PERRENOD_EXPONENT = 5.848
  26.  
  27. btc = yf.download(
  28. "BTC-USD",
  29. start=START_DATE,
  30. auto_adjust=True,
  31. progress=False
  32. )
  33.  
  34. if isinstance(btc.columns, pd.MultiIndex):
  35. btc.columns = btc.columns.get_level_values(0)
  36.  
  37. btc = btc[["Close"]].dropna()
  38. btc.index = pd.to_datetime(btc.index).tz_localize(None)
  39. btc = btc.rename(columns={"Close": "BTC"})
  40.  
  41. forecast_dates = pd.date_range(
  42. start=btc.index.min(),
  43. end=END_DATE,
  44. freq="D"
  45. )
  46.  
  47. data = pd.DataFrame(index=forecast_dates)
  48. data = data.join(btc, how="left")
  49.  
  50. data["Days"] = (data.index - GENESIS).days
  51. data["Age"] = data["Days"] / 365.2425
  52.  
  53. data = data[data["Days"] > 0].copy()
  54.  
  55. data["Dacoinminster"] = (
  56. DACOINMINSTER_COEFFICIENT
  57. * data["Days"] ** DACOINMINSTER_EXPONENT
  58. )
  59.  
  60. data["Perrenod"] = (
  61. PERRENOD_COEFFICIENT
  62. * data["Age"] ** PERRENOD_EXPONENT
  63. )
  64.  
  65. fit_end = btc.index.max()
  66. fit_start = fit_end - pd.DateOffset(years=FIT_YEARS)
  67.  
  68. fit_data = data.loc[
  69. (data.index >= fit_start)
  70. & (data.index <= fit_end)
  71. ].dropna(subset=["BTC"]).copy()
  72.  
  73. t = fit_data["Age"].values
  74. actual = fit_data["BTC"].values
  75. baseline = fit_data["Perrenod"].values
  76.  
  77. y = np.log10(actual / baseline)
  78.  
  79. X = np.column_stack([
  80. np.ones(len(t)),
  81. np.cos(OMEGA_1 * np.log(t)),
  82. np.sin(OMEGA_1 * np.log(t)),
  83. np.cos(OMEGA_2 * np.log(t)),
  84. np.sin(OMEGA_2 * np.log(t))
  85. ])
  86.  
  87. coefficients, residuals, rank, singular_values = np.linalg.lstsq(
  88. X,
  89. y,
  90. rcond=None
  91. )
  92.  
  93. c0, c1, c2, c3, c4 = coefficients
  94.  
  95. age = data["Age"].values
  96. log_age = np.log(age)
  97.  
  98. oscillation_1 = (
  99. c1 * np.cos(OMEGA_1 * log_age)
  100. + c2 * np.sin(OMEGA_1 * log_age)
  101. )
  102.  
  103. oscillation_2 = (
  104. c3 * np.cos(OMEGA_2 * log_age)
  105. + c4 * np.sin(OMEGA_2 * log_age)
  106. )
  107.  
  108. data["Oscillation_1"] = (
  109. data["Perrenod"]
  110. * 10 ** (c0 + oscillation_1)
  111. )
  112.  
  113. data["Oscillation_2"] = (
  114. data["Perrenod"]
  115. * 10 ** (c0 + oscillation_2)
  116. )
  117.  
  118. data["Combined"] = (
  119. data["Perrenod"]
  120. * 10 ** (c0 + oscillation_1 + oscillation_2)
  121. )
  122.  
  123. data["Average"] = (
  124. data["Oscillation_1"]
  125. + data["Oscillation_2"]
  126. + data["Combined"]
  127. ) / 3
  128.  
  129. forecast_start = pd.Timestamp("2029-01-01")
  130. forecast_end = pd.Timestamp("2030-12-31")
  131.  
  132. forecast_window = data.loc[
  133. (data.index >= forecast_start)
  134. & (data.index <= forecast_end)
  135. ]
  136.  
  137. peak_date = forecast_window["Combined"].idxmax()
  138. peak_price = forecast_window.loc[peak_date, "Combined"]
  139.  
  140. plt.figure(figsize=(18, 10))
  141.  
  142. plt.plot(
  143. data.index,
  144. data["BTC"],
  145. color="orange",
  146. linewidth=1.5,
  147. label="Bitcoin Actual Price"
  148. )
  149.  
  150. plt.plot(
  151. data.index,
  152. data["Dacoinminster"],
  153. color="blue",
  154. linewidth=1.8,
  155. label="Dacoinminster Power Law"
  156. )
  157.  
  158. plt.plot(
  159. data.index,
  160. data["Perrenod"],
  161. color="purple",
  162. linewidth=1.8,
  163. label="Perrenod Global Power Law"
  164. )
  165.  
  166. plt.plot(
  167. data.index,
  168. data["Oscillation_1"],
  169. color="cyan",
  170. linewidth=1.5,
  171. label="Oscillation 1"
  172. )
  173.  
  174. plt.plot(
  175. data.index,
  176. data["Oscillation_2"],
  177. color="gold",
  178. linewidth=1.5,
  179. label="Oscillation 2"
  180. )
  181.  
  182. plt.plot(
  183. data.index,
  184. data["Combined"],
  185. color="limegreen",
  186. linewidth=2.5,
  187. label="Combined Model"
  188. )
  189.  
  190. plt.plot(
  191. data.index,
  192. data["Average"],
  193. color="darkgreen",
  194. linewidth=1.8,
  195. linestyle="--",
  196. label="Average of Three Models"
  197. )
  198.  
  199. plt.axvline(
  200. fit_start,
  201. color="gray",
  202. linestyle=":",
  203. linewidth=1
  204. )
  205.  
  206. plt.axvline(
  207. fit_end,
  208. color="gray",
  209. linestyle=":",
  210. linewidth=1
  211. )
  212.  
  213. plt.scatter(
  214. peak_date,
  215. peak_price,
  216. color="red",
  217. s=80,
  218. zorder=5
  219. )
  220.  
  221. plt.annotate(
  222. f"${peak_price:,.0f}\n{peak_date.strftime('%d %B %Y')}",
  223. xy=(peak_date, peak_price),
  224. xytext=(15, 15),
  225. textcoords="offset points",
  226. fontsize=11,
  227. color="red",
  228. arrowprops=dict(arrowstyle="->", color="red")
  229. )
  230.  
  231. plt.yscale("log")
  232. plt.xlim(data.index.min(), data.index.max())
  233. plt.xlabel("Date")
  234. plt.ylabel("Bitcoin Price (USD, logarithmic scale)")
  235. plt.title(
  236. "Bitcoin: Power Laws and Log-Periodic Oscillations",
  237. fontsize=17
  238. )
  239.  
  240. plt.grid(True, which="both", alpha=0.25)
  241. plt.legend(loc="upper left")
  242. plt.tight_layout()
  243. plt.show()
  244.  
  245. print("FIT PERIOD")
  246. print(f"{fit_start:%d %B %Y} to {fit_end:%d %B %Y}")
  247.  
  248. print("\nOSCILLATION PARAMETERS")
  249. print(f"Lambda 1: {LAMBDA_1}")
  250. print(f"Omega 1: {OMEGA_1:.6f}")
  251. print(f"Lambda 2: {LAMBDA_2}")
  252. print(f"Omega 2: {OMEGA_2:.6f}")
  253.  
  254. print("\nFITTED COEFFICIENTS")
  255. print(f"c0 = {c0:.6f}")
  256. print(f"c1 = {c1:.6f}")
  257. print(f"c2 = {c2:.6f}")
  258. print(f"c3 = {c3:.6f}")
  259. print(f"c4 = {c4:.6f}")
  260.  
  261. print("\nCOMBINED MODEL PEAK")
  262. print(f"Date: {peak_date:%d %B %Y}")
  263. print(f"Price: ${peak_price:,.0f}")
Advertisement
Add Comment
Please, Sign In to add comment