Seznamuje posluchače se základními statistickými pojmy, s analýzou a prezentací statistických dat. Pozornost je zaměřena zejména na nejpoužívanější statistické postupy a metody.
Statistika pro finance aplikuje statistické a ekonometrické metody na finanční data. Zahrnuje teorii portfolia, CAPM, analýzu časových řad, regresi pro finanční data a měření rizika (VaR). Praktická část v R a Pythonu.
Jednoduchý (diskrétní) výnos: Rₜ = (Pₜ - Pₜ₋₁) / Pₜ₋₁ = Pₜ/Pₜ₋₁ - 1
Logaritmický (spojitý) výnos: rₜ = ln(Pₜ/Pₜ₋₁) = ln(Pₜ) - ln(Pₜ₋₁)
Výhody log výnosů: Aditivita (r₁+r₂+...+rₙ = celkový log výnos), lepší normalitní vlastnosti, analyticky pohodlnější.
Aritmetický průměr: R̄ = (1/T) · Σₜ Rₜ
Geometrický průměr: R_geo = (∏ (1+Rₜ))^(1/T) - 1
Kdy který: Geometrický pro víceleté historické výnosy, aritmetický pro budoucí očekávání.
Příklad: Výnosy: +50%, -33.33% Aritmetický: (50% - 33.33%) / 2 = 8.33% Geometrický: √(1.5 × 0.6667) - 1 = √1 - 1 = 0% (správně — vrátilo se na původní cenu)
Rozptyl a směrodatná odchylka: σ² = (1/T-1) · Σₜ (Rₜ - R̄)² σ = √σ² (jako % výnosu)
Kovariance: Cov(Rᵢ, Rⱼ) = σᵢⱼ = (1/T-1) · Σₜ (Rᵢₜ - R̄ᵢ)(Rⱼₜ - R̄ⱼ)
Korelační koeficient: ρᵢⱼ = σᵢⱼ / (σᵢ · σⱼ) ∈ [-1, +1]
Annualizace: σ_roční = σ_denní · √252 (252 obchodních dní) σ_roční = σ_měsíční · √12
import numpy as np
import pandas as pd
# Načtení dat (z Yahoo Finance nebo jiného zdroje)
returns = prices.pct_change().dropna()
# Základní statistiky
mean_ret = returns.mean() * 252 # annualizovaný výnos
std_ret = returns.std() * np.sqrt(252) # annualizovaná volatilita
sharpe = mean_ret / std_ret # Sharpe ratio (Rf=0)
# Kovarianční matice
cov_matrix = returns.cov() * 252
corr_matrix = returns.corr()
print(f"Průměrný výnos: {mean_ret:.2%}")
print(f"Volatilita: {std_ret:.2%}")
print(f"Sharpe Ratio: {sharpe:.2f}")
Výnos portfolia: E(Rₚ) = Σᵢ wᵢ · E(Rᵢ)
kde wᵢ = váha aktiva i (Σwᵢ = 1)
Rozptyl portfolia (2 aktiva): σ²ₚ = w₁²σ₁² + w₂²σ₂² + 2w₁w₂σ₁₂
Rozptyl portfolia (n aktiv — maticový zápis): σ²ₚ = wᵀ · Σ · w
kde Σ = kovarianční matice, w = vektor vah
Diverzifikace: Pokud ρ < 1, σₚ < Σwᵢσᵢ (portfoliové riziko < váženého průměru individuálních rizik).
Množina portfolií s:
import scipy.optimize as sco
def portfolio_performance(weights, mean_returns, cov_matrix):
ret = np.dot(weights, mean_returns)
vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
return ret, vol
def min_variance_portfolio(mean_returns, cov_matrix):
n = len(mean_returns)
constraints = [{"type": "eq", "fun": lambda x: np.sum(x) - 1}]
bounds = tuple((0, 1) for _ in range(n))
result = sco.minimize(
lambda w: portfolio_performance(w, mean_returns, cov_matrix)[1],
n * [1./n],
method="SLSQP",
bounds=bounds,
constraints=constraints
)
return result
def max_sharpe_portfolio(mean_returns, cov_matrix, rf=0.03):
n = len(mean_returns)
def neg_sharpe(w):
ret, vol = portfolio_performance(w, mean_returns, cov_matrix)
return -(ret - rf) / vol
constraints = [{"type": "eq", "fun": lambda x: np.sum(x) - 1}]
bounds = tuple((0, 1) for _ in range(n))
result = sco.minimize(neg_sharpe, n*[1./n], method="SLSQP",
bounds=bounds, constraints=constraints)
return result
CML (Capital Market Line): E(Rₚ) = Rf + [(E(Rm) - Rf) / σm] · σₚ
Platí jen pro efektivní portfolia (kombinace Rf a tržního portfolia M).
SML (Security Market Line — CAPM): E(Rᵢ) = Rf + βᵢ · [E(Rm) - Rf]
Platí pro jakékoliv aktivum nebo portfolio.
Rozdíl CML vs. SML:
αᵢ > 0 → aktivum je pod SML (podhodnoceno, koupit) αᵢ < 0 → aktivum je nad SML (nadhodnoceno, prodat)
βᵢ = Cov(Rᵢ, Rm) / Var(Rm) = ρᵢm · σᵢ / σm
Interpretace:
import statsmodels.api as sm
# Excess returns
excess_asset = asset_returns - rf_rate
excess_market = market_returns - rf_rate
# Regrese
X = sm.add_constant(excess_market)
model = sm.OLS(excess_asset, X).fit()
print(f"Alpha: {model.params[0]:.4f}")
print(f"Beta: {model.params[1]:.4f}")
print(f"R²: {model.rsquared:.4f}")
print(model.summary())
Celkové riziko = Systematické + Nesystematické: σ²ᵢ = β²ᵢ · σ²m + σ²εᵢ
Slabá stacionarita (covariance stationarity):
from statsmodels.tsa.stattools import adfuller, kpss
adf_result = adfuller(returns)
print(f"ADF statistika: {adf_result[0]:.4f}")
print(f"p-hodnota: {adf_result[1]:.4f}")
# p < 0.05 → zamítáme H₀ (nestacionarita) → stacionární
Cenové řady: Obvykle nestacionární (random walk), ale výnos (první diference ln cen) = stacionární.
AR(p) — autoregresní model: Xₜ = φ₁Xₜ₋₁ + ... + φₚXₜ₋ₚ + εₜ
MA(q) — model klouzavých průměrů: Xₜ = εₜ + θ₁εₜ₋₁ + ... + θqεₜ₋q
ARMA(p,q): Kombinace AR a MA. ARIMA(p,d,q): Pro nestacionární řady — d = počet diferencování.
Identifikace řádu modelu:
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# ARMA(1,1) model
model = ARIMA(returns, order=(1, 0, 1))
results = model.fit()
print(results.summary())
# Forecastování
forecast = results.forecast(steps=10)
Volatility clustering: Velké výkyvy tend. następuj po velkých, malé po malých.
GARCH(1,1):
Interpretace parametrů:
from arch import arch_model
# GARCH(1,1) model
garch = arch_model(returns * 100, vol='Garch', p=1, q=1, dist='Normal')
garch_result = garch.fit(disp='off')
print(garch_result.summary())
# Podmíněná volatilita
cond_vol = garch_result.conditional_volatility / 100
Detekce:
HC3 v statsmodels# OLS s robustními SE (White)
model = sm.OLS(y, X).fit(cov_type='HC3')
print(model.summary())
Durbin-Watson statistika: DW = Σ(eₜ - eₜ₋₁)² / Σeₜ² ∈ [0, 4]
# Newey-West HAC SE
model_hac = sm.OLS(y, X).fit(cov_type='HAC', cov_kwds={'maxlags': 4})
Definice: VaR(α) = maximální ztráta, která nebude překročena s pravděpodobností α (typicky 95% nebo 99%) za dané časové období.
"S 99% pravděpodobností ztráta nepřekročí VaR(99%) za jeden den."
1. Historická simulace: Výnosová distribuce z historických dat.
def historical_var(returns, confidence=0.95):
var = np.percentile(returns, (1 - confidence) * 100)
return abs(var)
var_95 = historical_var(returns, 0.95)
print(f"VaR (95%, 1-denní): {var_95:.2%}")
2. Parametrický VaR (normální distribuce): VaR(α) = μ - zα · σ
kde zα = kvantil normálního rozdělení (z₀.₉₅ = 1.645, z₀.₉₉ = 2.326)
from scipy import stats
def parametric_var(returns, confidence=0.95):
mu = returns.mean()
sigma = returns.std()
z = stats.norm.ppf(1 - confidence)
return abs(mu + z * sigma)
3. Monte Carlo simulace:
def monte_carlo_var(mu, sigma, n_simulations=10000, confidence=0.95):
simulated_returns = np.random.normal(mu, sigma, n_simulations)
var = np.percentile(simulated_returns, (1 - confidence) * 100)
return abs(var)
CVaR = průměrná ztráta za podmínky, že ztráta přesáhne VaR.
CVaR(α) = -E[R | R < -VaR(α)]
CVaR je koherentní míra rizika (VaR není — porušuje subadditivitu).
Backtesting VaR: Počítáme exceedances (dny, kdy ztráta překročila VaR). Kupiecův LR test.
H₀: μ = μ₀ (výnos = 0 nebo CAPM hodnota) t = (R̄ - μ₀) / (s/√n) ~ t(n-1)
H₀: β₁ = β₂ = ... = βₖ = 0 (model nemá vysvětlovací sílu) F = (R² / k) / ((1-R²) / (n-k-1)) ~ F(k, n-k-1)
H₀: parametry regrese jsou stabilní v čase. Aplikace: Testování, zda se vztah změnil po krizi/události.
# Testování normality výnosů
from scipy.stats import jarque_bera, shapiro
jb_stat, jb_p = jarque_bera(returns)
print(f"Jarque-Bera: stat={jb_stat:.4f}, p={jb_p:.4f}")
# p < 0.05 → zamítáme normalitu (typické pro finanční data — fat tails!)
Stylizovaná fakta o finančních výnosech:
| rₜ |
|---|
quantmod, PerformanceAnalytics, rugarch, forecastarch, statsmodels, scipy.stats, yfinance# R příklady pro VaR a GARCH
library(quantmod)
library(PerformanceAnalytics)
library(rugarch)
# Stažení dat
getSymbols("^GSPC", from="2020-01-01")
returns <- dailyReturn(GSPC)
# VaR a CVaR
VaR(returns, p=0.95, method="historical")
CVaR(returns, p=0.95, method="historical")
# GARCH(1,1)
spec <- ugarchspec(variance.model=list(garchOrder=c(1,1)),
mean.model=list(armaOrder=c(0,0)))
fit <- ugarchfit(spec, returns)
show(fit)
Používej Markdown: ## Nadpis, **tučně**, `kód`, - odrážky, > citace