GaiaEx AcademyGaiaEx Academy
Analisi dei dati con Pandas, NumPy e Matplotlib
SviluppatoreProgrammazione12 min read

Analisi dei dati con Pandas, NumPy e Matplotlib

Pulisci, trasforma e visualizza dati finanziari come un quant

Condividi Post

NumPy: il motore sotto il cofano

Ogni calcolo finanziario serio in Python passa alla fine attraverso NumPy. Mentre le liste Python sono flessibili, sono lente — ogni elemento è un oggetto Python completo con overhead di controllo del tipo. Gli array NumPy memorizzano numeri grezzi in blocchi di memoria contigui, permettendo operazioni che girano 100 volte più veloci dei loop Python puri.

Ecco la differenza in pratica:

import numpy as np

# Create an array of 1 million random daily returns
returns = np.random.normal(0.0005, 0.02, 1_000_000)

# Vectorized operations — no loops needed
cumulative = np.cumprod(1 + returns)  # Growth of $1
sharpe = returns.mean() / returns.std() * np.sqrt(252)
max_drawdown = np.min(cumulative / np.maximum.accumulate(cumulative) - 1)

print(f"Sharpe Ratio: {sharpe:.3f}")
print(f"Max Drawdown: {max_drawdown:.2%}")

Concetti chiave di NumPy per la finanza:

  • Operazioni vettorizzate — applicare la matematica a interi array in una volta invece di scorrere elemento per elemento.
  • Broadcasting — allinea automaticamente array di forme diverse per l'aritmetica (per esempio, sottraendo una media scalare da ogni elemento).
  • Algebra linearenp.linalg fornisce moltiplicazione di matrici, decomposizione in autovalori, e solver usati nell'ottimizzazione di portafoglio.
  • Campionamento casuale — le simulazioni Monte Carlo, il bootstrap sampling e la modellazione stocastica si basano tutti su np.random.

Consiglio sulle performance: preferisci sempre le operazioni NumPy vettorizzate ai for-loop Python. Un'ottimizzazione di portafoglio su 500 asset che richiede 30 secondi con i loop può finire in meno di 50 millisecondi con NumPy vettorizzato — un aumento di velocità di 600x.

NumPy: contiguous memory + vectorized ops ndarray — dtype, shape, strides (C-contiguous) one loop in C/Fortran, not a million Python bytecode steps broadcasting: align shapes for element-wise math e.g. returns vector − scalar mean, or (n,) with (n, m) matrix rows linalg: cov, eig, solve — portfolio math lives here
Gli array sono il percorso rapido; il broadcasting è come mantieni il codice leggibile senza loop.

Pandas: DataFrame per dati finanziari

Se NumPy è il motore, pandas è il cruscotto. Avvolge gli array NumPy in strutture etichettate e indicizzate che rendono intuitiva ed espressiva la manipolazione dei dati finanziari.

Le due strutture fondamentali sono:

  • Series — una singola colonna di dati con un indice (pensa: una serie temporale di prezzi di chiusura).
  • DataFrame — una tabella di colonne, ognuna una Series, che condividono un indice comune (pensa: dati candlestick OHLCV).

Caricare e ispezionare i dati è semplice:

import pandas as pd

# Read from CSV
df = pd.read_csv("btc_daily.csv", parse_dates=["date"], index_col="date")

# Or from JSON (common in API responses)
df = pd.read_json("https://api.example.com/candles?symbol=ETH")

# Quick inspection
print(df.shape)          # (365, 5)
print(df.dtypes)         # Column types
print(df.describe())     # Statistical summary
print(df.tail())         # Last 5 rows

Ciò che rende pandas indispensabile per la finanza è il suo DatetimeIndex. Una volta che il tuo indice è di tipo datetime, sblocchi potenti operazioni di serie temporali:

# Slice by date range
q1_data = df["2025-01":"2025-03"]

# Resample daily data to weekly OHLC
weekly = df["close"].resample("W").ohlc()

# Forward-fill missing data (weekends, holidays)
df = df.asfreq("D").ffill()

Queste operazioni gestiscono le realtà disordinate dei dati finanziari — lacune, differenze di fuso orario, timestamp irregolari — così puoi concentrarti sull'analisi piuttosto che sull'impianto idraulico dei dati.

Calcoli rolling: medie mobili e volatilità

L'analisi finanziaria è intrinsecamente a finestra. Raramente ti interessa un singolo punto dati isolato — il contesto viene da come si relaziona alla storia recente. Il metodo .rolling() di pandas è il tuo strumento principale qui.

import pandas as pd
import numpy as np

# Assume df has a "close" column with DatetimeIndex
df["sma_20"] = df["close"].rolling(20).mean()
df["sma_50"] = df["close"].rolling(50).mean()
df["ema_12"] = df["close"].ewm(span=12).mean()

# Daily returns and rolling volatility
df["returns"] = df["close"].pct_change()
df["vol_30d"] = df["returns"].rolling(30).std() * np.sqrt(365)

# Bollinger Bands
df["bb_upper"] = df["sma_20"] + 2 * df["close"].rolling(20).std()
df["bb_lower"] = df["sma_20"] - 2 * df["close"].rolling(20).std()

# Rolling correlation between two assets
df["corr_btc_eth"] = df["btc_returns"].rolling(60).corr(df["eth_returns"])

Calcoli rolling chiave che ogni trader dovrebbe conoscere:

  • Simple Moving Average (SMA) — media pesata equamente su N periodi. In ritardo ma stabile.
  • Exponential Moving Average (EMA) — pesa più pesantemente i dati recenti tramite .ewm(). Più reattiva ai cambiamenti di prezzo.
  • Volatilità rolling — deviazione standard dei rendimenti su una finestra, annualizzata. Essenziale per il dimensionamento delle posizioni e i budget di rischio.
  • Correlazione rolling — misura come due asset si muovono insieme nel tempo. Fondamentale per la diversificazione di portafoglio.

Su piattaforme come GaiaEx, puoi estrarre dati storici di candele tramite l'API di trading, caricarli in un DataFrame pandas, e calcolare questi indicatori in secondi — tutto mentre i tuoi asset restano al sicuro nel tuo wallet MPC.

GroupBy e aggregazione per l'analisi di portafoglio

Quando gestisci più asset, .groupby() diventa essenziale. Ti permette di dividere i dati per categoria, applicare calcoli, e combinare i risultati — il pattern split-apply-combine.

# DataFrame with multiple assets
trades = pd.DataFrame({
    "symbol": ["BTC", "ETH", "BTC", "SOL", "ETH", "BTC"],
    "side": ["buy", "buy", "sell", "buy", "sell", "buy"],
    "pnl": [120.5, -45.2, 89.0, 210.3, 55.8, -30.1],
    "volume": [5000, 3200, 4800, 1500, 2900, 5100],
})

# Performance by asset
summary = trades.groupby("symbol").agg(
    total_pnl=("pnl", "sum"),
    avg_pnl=("pnl", "mean"),
    trade_count=("pnl", "count"),
    total_volume=("volume", "sum"),
    win_rate=("pnl", lambda x: (x > 0).mean()),
)

print(summary.sort_values("total_pnl", ascending=False))

Pattern di aggregazione avanzati per il lavoro di portafoglio:

  • GroupBy multi-livello — raggruppa per symbol e side per vedere la performance long vs. short per asset.
  • Funzioni di aggregazione personalizzate — calcola Sharpe ratio, Sortino ratio, o max drawdown per gruppo di asset.
  • Pivot table — riorganizza i dati per vedere i rendimenti mensili per asset in un formato adatto a una heatmap usando pd.pivot_table().
  • Resampling con groupby — combina il resampling basato sul tempo con il raggruppamento categorico per l'analisi di serie temporali multi-asset.

Matplotlib: grafici del price action e dei segnali

I dati senza visualizzazione sono solo numeri. Matplotlib trasforma la tua analisi in grafici che rivelano pattern invisibili nei dati grezzi.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, axes = plt.subplots(3, 1, figsize=(14, 10),
                         sharex=True, gridspec_kw={"height_ratios": [3, 1, 1]})

# Price + Moving Averages
axes[0].plot(df.index, df["close"], label="Close", linewidth=1.2)
axes[0].plot(df.index, df["sma_20"], label="SMA 20", linestyle="--")
axes[0].fill_between(df.index, df["bb_upper"], df["bb_lower"],
                     alpha=0.1, color="blue", label="Bollinger Bands")
axes[0].set_ylabel("Price (USD)")
axes[0].legend(loc="upper left")

# Volume bars
colors = ["green" if c > o else "red"
          for c, o in zip(df["close"], df["open"])]
axes[1].bar(df.index, df["volume"], color=colors, alpha=0.7)
axes[1].set_ylabel("Volume")

# Rolling Volatility
axes[2].plot(df.index, df["vol_30d"], color="purple")
axes[2].set_ylabel("30d Volatility")
axes[2].axhline(y=0.8, color="red", linestyle=":", alpha=0.5)

axes[2].xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.tight_layout()
plt.savefig("analysis_dashboard.png", dpi=150)
plt.show()

Questo produce una dashboard professionale a tre pannelli: il price action con le Bande di Bollinger in cima, il volume nel mezzo, e la volatilità in basso. Questo layout imita quello che vedresti su terminali di trading professionali.

Per la visualizzazione statistica, seaborn si costruisce su Matplotlib con funzioni di livello superiore:

import seaborn as sns

# Return distribution
sns.histplot(df["returns"].dropna(), bins=100, kde=True)

# Correlation heatmap across assets
corr_matrix = portfolio_returns.corr()
sns.heatmap(corr_matrix, annot=True, cmap="RdYlGn", center=0)
Pandas → analysis; Matplotlib → insight DataFrame index + columns rolling resample groupby Series metrics returns, vol, Sharpe matplotlib.pyplot — figure, axes, artists price volume indicators seaborn optional — same Artist layer, prettier defaults
Pandas prepara tabelle ordinate; Matplotlib le mappa su assi che puoi annotare e condividere.

Mettere tutto insieme: una pipeline di analisi completa

Il vero potere emerge quando incateni questi strumenti in una pipeline ripetibile. Ecco un workflow che i quant professionisti usano quotidianamente:

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

def analyze_asset(symbol: str, df: pd.DataFrame) -> dict:
    """Full analysis pipeline for a single asset."""
    df["returns"] = df["close"].pct_change()
    df["log_returns"] = np.log(df["close"] / df["close"].shift(1))

    return {
        "symbol": symbol,
        "total_return": (df["close"].iloc[-1] / df["close"].iloc[0]) - 1,
        "annual_vol": df["returns"].std() * np.sqrt(365),
        "sharpe": df["returns"].mean() / df["returns"].std() * np.sqrt(365),
        "max_drawdown": (df["close"] / df["close"].cummax() - 1).min(),
        "skewness": df["returns"].skew(),
        "kurtosis": df["returns"].kurtosis(),
    }

# Analyze multiple assets
results = [analyze_asset(sym, data) for sym, data in assets.items()]
summary = pd.DataFrame(results).set_index("symbol")
print(summary.round(4))

Questa pipeline prende dati di prezzo grezzi e produce un profilo completo di rischio-rendimento per ogni asset. Da qui, puoi alimentare queste metriche in un optimizer di portafoglio, generare raccomandazioni di allocazione, o attivare segnali di ribilanciamento.

Lo stack pandas-NumPy-Matplotlib è la fondazione su cui si costruisce tutto il resto della finanza in Python. Padroneggia queste tre librerie e avrai le competenze per analizzare qualsiasi mercato, costruire qualsiasi indicatore, e visualizzare qualsiasi strategia — che tu stia facendo trading su azioni al NYSE, crypto su GaiaEx, o derivati al CME.