Post
Topic
Board Italiano (Italian)
Merits 10 from 1 user
Re: Un modello logistico del prezzo di Bitcoin
by
arulbero
on 18/04/2025, 16:19:30 UTC
⭐ Merited by fillippone (10)
se volete farvi delle implementazioni/esperimenti/farvi venire un po' di mal di testa,  vi posto un po' di codice



Possiamo fare una rappresentazione grafica simile anche di BTC/XAU.



Il pattern adesso cresce in modo molto meno che proporzionale e, dalla analisi grafica, sembra che il trend dei valori minimi (linea rossa) stia performando meglio di quello dei valori massimi (linea blu), il che mi torna perchè testimonia da un lato la maggiore stabilità e maturazione di bitcoin, dall'altro la difficoltà recente a sovraperformare in modo rilevante il sasso giallo.

La conseguenza è che la banda di oscillazione tra massimi e minimi si sta riducendo e che bitcoin sembra tendere asintoticamente ad un massimo assoluto tra le 100 e le 140 once dopo il quale ci sarà solo una crescita lentissima al crescere del tempo (secondo il classico andamento di una funzione logaritmica)

Ho provato a scaricare i dati settimanali di bitcoin vs dollaro e dollaro vs oro  da qui https://it.investing.com/crypto/bitcoin/historical-data
partono da luglio 2010

ho chiesto quindi al nuovo modello gpt04 di trovare i 3 parametri della nostra curva logistica che meglio approssimano i dati (L_L = 0, L_U =140, ho preso come target il target asintotico della curva logaritmica proposta da Plutosky))

Code:
Il grafico qui sopra mostra in arancione i 770 valori reali (Bitcoin in once d’oro) e in linea continua il modello logistico asimmetrico
ricostruito con i parametri ottimizzati; si osserva che il fit cattura il trend di crescita di lungo periodo, pur non riuscendo a seguire
le oscillazioni più brusche e i picchi (fenomeni tipici delle criptovalute).

Interpretazione rapida

I_x ≈ 770 indica che, con questi limiti superiori scelti, il punto d’inflessione si colloca proprio all’estremo della serie disponibile:
il modello “spinge” l’inflessione verso il futuro per accomodare l’accelerazione del rapporto BTC/Oro degli ultimi anni.

S ≈ 0.25 riflette una pendenza relativamente morbida nel punto di inflessione (circa +25 % del range limite per settimana,
una crescita comunque molto rapida).

c ≈ −5 rende la curva fortemente asimmetrica: l’inflessione si trova molto più vicina al limite superiore, con una lunga “coda” iniziale
quasi piatta e poi un’accelerazione finale.

Questi valori sono il compromesso migliore, in senso RMS, dato che la volatilità e i picchi del dato reale non sono descrivibili
da una singola curva sigmoide.






Se vi interessa il codice per fare il plot delle 2 curve:

Code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# --- Load data and parameters -------------------------------------------------
data_path = "/mnt/data/bitcoin_in_gold_weekly.xlsx"
df = pd.read_excel(data_path).sort_values("Week").reset_index(drop=True)

x_data = np.arange(1, len(df) + 1)          # 1 .. 770
y_data = df["BTC_in_gold"].values

# Parameters found in previous fit (LL=0, LU=140)
LL, LU = 0.0, 140.0
I_x, S, c = 770.0, 0.2522498, -5.0          # rounded popt values

# --- Asymmetric logistic model function --------------------------------------
def asymmetric_logistic(x_vals, I_x, S, c):
    s0 = np.exp(c) + 1.0
    s1 = np.exp(-c)
    s2 = s0 ** (s0 * s1)
    s3 = S / (LU - LL)
    y_part = (np.exp(s2 * (s3 * (I_x - x_vals) + c / s2)) + 1.0) ** (-s1)
    return LL + (LU - LL) * y_part

# --- Generate prediction up to week 2000 -------------------------------------
x_pred = np.arange(1, 2001)                 # 1 .. 2000
y_pred = asymmetric_logistic(x_pred, I_x, S, c)

# --- Plot ---------------------------------------------------------------------
plt.figure(figsize=(9,4))
plt.scatter(x_data, y_data, s=10, label="Dati reali (BTC/Oro)")
plt.plot(x_pred, y_pred, linewidth=2, label="Modello logistico (proiezione)")
plt.xlim(0, 2000)
plt.xlabel("Numero della settimana")
plt.ylabel("BTC in once d'oro")
plt.title("Proiezione della curva logistica asimmetrica fino alla settimana 2000\n(LL=0, LU=140)")
plt.legend()
plt.tight_layout()
plt.show()

Il codice per trovare i parametri (io non l'ho testato direttamente, mi limito a riportarvelo):

Code:
import pandas as pd
import numpy as np
from math import exp
import matplotlib.pyplot as plt

# Load the weekly BTC-in-gold data we previously produced
data_path = "/mnt/data/bitcoin_in_gold_weekly.xlsx"
df = pd.read_excel(data_path)

# Ensure chronological order and reset index
df = df.sort_values("Week").reset_index(drop=True)
x = np.arange(1, len(df) + 1)        # week number (1 .. 770)
y = df["BTC_in_gold"].values         # target variable

# Fixed logistic parameters
LL = 0.0          # lower asymptote
LU = 140.0        # upper asymptote

# --- Asymmetric 5‑parameter logistic model (re‑parameterised) -----------------
def asymmetric_logistic(x_vals, I_x, S, c):
    """
    5‑param asymmetric logistic with LL, LU fixed.
   
    Parameters
    ----------
    x_vals : ndarray
        Independent variable (week number)
    I_x : float
        x‑coordinate of inflection point
    S : float
        Slope at inflection point
    c : float
        Symmetry parameter (0 = symmetric)
       
    Returns
    -------
    ndarray
        Model values at x_vals
    """
    # common sub‑expressions (cfr. Osthege & Helleckes 2021)
    s0 = np.exp(c) + 1.0
    s1 = np.exp(-c)
    s2 = s0 ** (s0 * s1)
    s3 = S / (LU - LL)
   
    y_part = (np.exp(s2 * (s3 * (I_x - x_vals) + c / s2)) + 1.0) ** (-s1)
    return LL + (LU - LL) * y_part

# ------------------------------------------------------------------------------

# Use SciPy's curve_fit if available; otherwise fall back to nelder‑mead
try:
    from scipy.optimize import curve_fit
    popt, pcov = curve_fit(
        asymmetric_logistic,
        x,
        y,
        # initial guesses: Ix halfway, slope small, symmetry neutral
        p0=[x.mean(), 0.5, 0.0],
        bounds=([0.0, -np.inf, -5.0], [x[-1], np.inf, 5.0]),
        maxfev=20000
    )
except Exception as e:
    # SciPy not present: very light Nelder‑Mead with numpy
    print("SciPy unavailable – using fallback optimisation.")
    from functools import partial
    def mse(params):
        Ix, S, c = params
        y_hat = asymmetric_logistic(x, Ix, S, c)
        return np.mean((y - y_hat) ** 2)
   
    # simple random restart Nelder‑Mead
    best = None
    best_val = np.inf
    for guess in [
        (x.mean(), 0.5, 0.0),
        (x.mean()*0.8, 1.0, 0.2),
        (x.mean()*1.2, 0.1, -0.2)
    ]:
        res = scipy.optimize.minimize(mse, guess, method="Nelder-Mead")
        if res.fun < best_val:
            best_val, best = res.fun, res.x
    popt = best
    pcov = np.full((3,3), np.nan)

I_x, S, c = popt

# Print fitted parameters
print(f"Fitted parameters (least‑squares):\n  I_x = {I_x:.3f}\n  S   = {S:.6f}\n  c   = {c:.6f}")

# Plot data vs model
plt.figure(figsize=(8,4))
plt.scatter(x, y, s=10, label="Data (BTC in gold)")
plt.plot(x, asymmetric_logistic(x, *popt), linewidth=2, label="Fitted logistic")
plt.xlabel("Settimana (index)")
plt.ylabel("BTC / Oncia d'oro")
plt.title("Adattamento funzione logistica asimmetrica (LL=0, LU=140)")
plt.legend()
plt.tight_layout()
plt.show()