I mercati finanziari

Un mercato finanziario è un luogo (fisico o virtuale) dove compratori e venditori si incontrano per scambiare prodotti finanziari. Il prezzo si forma dall'incontro tra domanda e offerta.

I principali mercati sono:

MercatoCosa si negoziaOrari (UTC+1)Volatilità tipica
Azionario (equities)Azioni di società quotate (AAPL, MSFT, ENI)NYSE: 15:30–22:00Media
ForexCoppie di valute (EUR/USD, GBP/JPY)24h/5gg — picchi Londra/NYBassa
FuturesContratti su indici, materie prime, tassiQuasi 24hMedia-alta
CryptoBitcoin, Ethereum, altcoin24h/7ggAlta
OpzioniDiritti di acquisto/vendita su sottostanteCome azionarioMolto alta
Nota

Per iniziare con Python, ci concentreremo sulle azioni USA (NYSE/NASDAQ) grazie alla disponibilità di dati storici gratuiti tramite yfinance. I principi si applicano poi a qualsiasi mercato.

Principali strumenti finanziari

📄Azione (Stock)

Quota di proprietà di una società. Il detentore partecipa agli utili tramite dividendi e all'apprezzamento del capitale. Esempio: acquistare 10 azioni AAPL significa possedere una piccola parte di Apple Inc.

📦ETF (Exchange-Traded Fund)

Fondo che replica un indice (es. S&P 500) o un settore. Negoziato come un'azione. Offre diversificazione immediata con un singolo strumento. Ideale per strategie passive.

⏱️Futures

Contratto per comprare/vendere un asset a un prezzo fisso in una data futura. Usato sia per speculazione che per hedging. Richiede margine e ha date di scadenza.

🎰Opzioni

Diritto (non obbligo) di comprare (call) o vendere (put) un asset a un prezzo prefissato (strike). Strumento complesso, utile per strategie di protezione del portafoglio.

Come si forma il prezzo

Il prezzo di un'azione in ogni istante è semplicemente l'ultimo prezzo al quale è avvenuta una transazione. Il mercato è un continuo book of orders: ordini di acquisto (bid) e ordini di vendita (ask) si incontrano.

Il bid-ask spread è la differenza tra il miglior prezzo di acquisto e il miglior prezzo di vendita. Nei mercati liquidi (AAPL, SPY) è minimo (pochi centesimi); nei mercati illiquidi può essere ampio e aumenta i costi di transazione.

Dati OHLCV — la struttura base del trading algoritmico

Quasi tutta l'analisi tecnica si basa su candele OHLCV: ogni riga rappresenta un periodo di tempo (1 minuto, 1 ora, 1 giorno) e contiene cinque valori:

CampoSignificatoUso principale
OpenPrezzo di apertura del periodoGap analysis, strategie di apertura
HighMassimo raggiunto nel periodoResistenze, ATR, Bollinger
LowMinimo raggiunto nel periodoSupporti, ATR, Bollinger
ClosePrezzo di chiusura del periodoQuasi tutti gli indicatori
VolumeNumero di azioni/contratti scambiatiConferma segnali, OBV, VWAP
In:
import yfinance as yf # Scarica dati giornalieri degli ultimi 3 mesi ticker = yf.Ticker("AAPL") df = ticker.history(period="3mo") # Mostra le ultime 3 righe print(df[["Open", "High", "Low", "Close", "Volume"]].tail(3)) # Range giornaliero medio (utile per il position sizing) df["range"] = df["High"] - df["Low"] print(f"\nRange medio: ${df['range'].mean():.2f}")
Out:
Open High Low Close \ Date 2026-03-12 00:00:00-04:00 258.660004 258.950012 254.179993 255.759995 2026-03-13 00:00:00-04:00 255.479996 256.329987 249.520004 250.119995 2026-03-16 00:00:00-04:00 252.104996 253.884995 249.880005 252.820007 Volume Date 2026-03-12 00:00:00-04:00 40794000 2026-03-13 00:00:00-04:00 36930000 2026-03-16 00:00:00-04:00 30091880 Range medio: $5.42
Consiglio pratico

La colonna Close adjusted (Adj Close) corregge per dividendi - quando un’azienda paga un dividendo, il prezzo scende automaticamente - e split azionari - uno stock split cambia il numero di azioni e il prezzo unitario, ma non il valore totale dell'investimento-. Per l'analisi tecnica è sempre preferibile usare i prezzi aggiustati per avere una serie storica coerente.

In:
import pandas as pd def compute_adj_close(df): """ df deve avere colonne: - 'Close' - 'Divid' (0 se nessuno) - 'Splits' (es. 2 per split 2:1, 0 o 1 se nessuno) """ df = df.copy() # Normalizza split: 0 -> 1 (nessuno split) df['Splits'] = df['Splits'].replace(0, 1) # Fattore giornaliero adj_factor = [] for i in range(len(df)): if i == len(df) - 1: adj_factor.append(1.0) else: today = df.iloc[i] tomorrow = df.iloc[i + 1] split = tomorrow['Splits'] dividend = tomorrow['Divid'] price = today['Close'] # fattore combinato factor = (1 / split) * (1 - dividend / price) adj_factor.append(factor) df['Daily Factor'] = adj_factor # Fattore cumulativo (all’indietro) df['Cum Factor'] = df['Daily Factor'][::-1].cumprod()[::-1] # Adj Close df['Adj Close'] = df['Close'] * df['Cum Factor'] return df df = pd.DataFrame({ 'Close': [100, 102, 98, 50, 52], 'Dividends': [0, 0, 5, 0, 0], 'Stock Splits': [0, 0, 0, 2, 0] # split 2:1 tra giorno 3→4 }) compute_adj_close(df)
Out:
Close Divid Splits Daily Factor Cum Factor Adj Close 0 100 0 1 1.00000 0.47549 47.54902 1 102 0 1 0.95098 0.47549 48.50000 2 98 5 1 0.50000 0.50000 49.00000 3 50 0 2 1.00000 1.00000 50.00000 4 52 0 1 1.00000 1.00000 52.00000

Tipi di ordine

Capire i tipi di ordine è fondamentale: nel backtesting simulerai come gli ordini vengono eseguiti, e nel live trading sceglierai quale tipo usare in base alla strategia.

TipoDescrizioneEsecuzione garantitaPrezzo garantito
Market order Esecuzione immediata al miglior prezzo disponibile No
Limit order Esecuzione solo se il prezzo raggiunge il livello specificato No
Stop order Diventa market order quando il prezzo tocca lo stop Condizionale No
Stop-limit Diventa limit order quando il prezzo tocca lo stop No
Trailing stop Stop che si muove con il prezzo a una distanza fissa Condizionale No
In:
# Simulazioni di alcuni tipi di ordine (nel modulo 6 con l'API reale di Alpaca) # --- Market Order --- Compra subito a qualsiasi prezzo. Rischio: slippage def market_buy(qty): return {"type": "MARKET", "qty": qty, "price": prezzo_mercato} # --- Limit Order --- Compra solo se il prezzo scende a 148.00 def limit_buy(qty, limit): if prezzo_mercato <= limit: return {"type": "LIMIT", "qty": qty, "price": limit} return {"status": "pending", "limit": limit} # --- Stop Loss --- Vendi se il prezzo scende sotto 145.00 (protezione) def stop_loss(qty, stop): if prezzo_mercato <= stop: return {"type": "STOP_SELL", "qty": qty, "trigger": stop} return {"status": "watching", "stop": stop} prezzo_mercato = 150.0 print(market_buy(10)) print(limit_buy(10, 148.0)) print(stop_loss(10, 145.0))
Out:
{'type': 'MARKET', 'qty': 10, 'price': 150.0} {'status': 'pending', 'limit': 148.0} {'status': 'watching', 'stop': 145.0}

Gestione del rischio

Questa è la sezione più importante del modulo. Un trader sistematico può avere una strategia con tasso di vincita del 40% e guadagnare comunque — purché gestisca bene il rapporto rischio/rendimento.

Regola fondamentale

Non rischiare mai più del 1–2% del capitale totale su una singola operazione. Con questa regola, anche 10 perdite consecutive non ti distruggono (perdita massima ~18%).

Position sizing — quante azioni comprare

Il position sizing risponde alla domanda: "quante azioni/contratti devo acquistare per rispettare il mio limite di rischio?". La formula è semplice:

Formula — Position Size Quantità = (Capitale × %Rischio) / (Prezzo_entrata Stop_loss)
In:
def calcola_quantita(capitale, rischio_pct, prezzo_entrata, stop_loss): if prezzo_entrata <= stop_loss: raise ValueError("Stop loss deve essere sotto il prezzo di entrata") return int(capitale * rischio_pct / prezzo_entrata - stop_loss) # Esempio capitale = 10_000 # 10.000 € disponibili rischio_pct = 0.01 # rischio max 1% = 100 € prezzo_entrata = 150.0 # compriamo a 150 $ stop_loss = 145.0 # stop a 145 $ → rischio 5 $ per azione qty = calcola_quantita(capitale, rischio_pct, prezzo_entrata, stop_loss) print(f"Quantità da acquistare: {qty} azioni") print(f"Capitale impiegato: ${qty * prezzo_entrata:.0f}") print(f"Rischio massimo: ${qty * (prezzo_entrata - stop_loss):.0f}")
Out:
Quantità da acquistare: 20 azioni Capitale impiegato: $3000 Rischio massimo: $100

Il rapporto Risk/Reward (R:R)

Il rapporto risk/reward confronta il guadagno atteso con la perdita massima accettata. Un R:R di 1:2 significa che per ogni euro rischiato si punta a guadagnare due.

Formula — Risk/Reward Ratio R:R = (Target Entrata) / (Entrata StopLoss)
In:
def risk_reward(entrata, stop, target): return (target - entrata) / (entrata - stop) def breakeven_winrate(rr): """Tasso di vincita minimo per essere profittevoli.""" return 1 / (1 + rr) # Trade su AAPL entrata = 150.0 stop = 145.0 # -5 $ di rischio target = 165.0 # +15 $ di guadagno atteso rr = risk_reward(entrata, stop, target) print(f"R:R ratio: 1:{rr:.1f}") print(f"Win rate minimo: {breakeven_winrate(rr)*100:.1f}%")
Out:
R:R ratio: 1:3.0 Win rate minimo: 25.0%

Setup dell'ambiente Python

Prima di partire con il modulo 2, assicurati di avere l'ambiente correttamente configurato. Usiamo un virtual environment per isolare le dipendenze del progetto.

In:
terminal (bash) SHELL # 1. Crea il virtual environment python -m venv pytrading-env # 2. Attivalo (macOS/Linux) source pytrading-env/bin/activate # 2b. Su Windows: # pytrading-env\Scripts\activate # 3. Installa le librerie del corso pip install yfinance pandas numpy matplotlib plotly pip install pandas-ta backtrader scikit-learn keras pip install alpaca-py jupyter
In:
# Esegui questo script per verificare che tutto sia installato import importlib, sys librerie = [ "yfinance", "pandas", "numpy", "matplotlib", "plotly", "pandas_ta" ] for lib in librerie: try: m = importlib.import_module(lib) versione = getattr(m, "__version__", "n/d") print(f" ✓ {lib:<14} {versione}") except ImportError: print(f" ✗ {lib:<14} NON TROVATA — esegui pip install {lib}") print(f"\nPython: {sys.version.split()[0]}")
Out:
✓ yfinance 0.2.66 ✓ pandas 2.2.2 ✓ numpy 2.0.2 ✓ matplotlib 3.10.0 ✓ plotly 5.24.1 ✗ pandas_ta NON TROVATA — esegui pip install pandas_ta Python: 3.12.12
Alternativa — Google Colab

Se non vuoi installare nulla in locale, puoi usare Google Colab gratuitamente. Crea un nuovo notebook e installa le librerie con !pip install yfinance pandas-ta. Tutti gli script del corso funzionano su Colab.

Verifica la comprensione
Hai un capitale di €5.000 e vuoi rischiare l'1%. Entri su un'azione a €100 con stop loss a €95. Quante azioni acquisti?
A 5 azioni (€500 investiti)
B 10 azioni (€1.000 investiti)
C 50 azioni (€5.000 investiti)
D 1 azione (€100 investiti)
ESERCIZIO Calcola il position size per 3 trade diversi

Usando la funzione calcola_quantita() vista in questa pagina, completa l'analisi per i seguenti tre trade ipotetici. Capitale iniziale: €20.000, rischio massimo: 1,5% per trade.

  • Trade A — TSLA: entrata €220, stop loss €210, target €250
  • Trade B — SPY: entrata €520, stop loss €515, target €535
  • Trade C — BTC: entrata €65.000, stop loss €62.000, target €72.000

Per ciascuno calcola: quantità, capitale impiegato, R:R ratio, win rate minimo di breakeven.