Calcoli scientifici con Julia/Minimizzazione del rischio in finanza
In finanza quando si vuole ottenere il minor rischio possibile avendo n asset che costituiscono un portafoglio, costituito per esempio da n azioni, si risolve la questione, minimizzando la seguente funzione obiettivo:
dove è la varianza o volatività del portafoglio. Se un titolo ha un rendimento atteso del 7%, ma a volte fa +20% , a volte fa –15% allora è rischioso non perché perda sempre, ma perché è imprevedibile. La misura matematica di questa imprevedibilità è la varianza o volatilità del portafoglio che deve essere minimizzata.
invece è la matrice di covarianza e w il vettore dei pesi che rappresenta la percentuale del portafoglio investita in ciascun asset, ad esempio:
- → 40% nell’asset 1
- → 35% nell’asset 2
- → 25% nell’asset 3
E valgono sempre:
e i pesi tutti positivi.
La matrice di covarianza è uno degli oggetti matematici più importanti nella finanza quantitativa.
Per un portafoglio con n asset, la matrice è:
Dove è la serie dei rendimenti dell’asset ( i ).
Sulla diagonale principale si trova la varianza dei vari asset per cui:
che misura la volatilità dell’asset (più è grande, più è rischioso)
Fuori diagonale la covarianza:
e misura se due asset si muovono insieme per cui se :
- Cov > 0 → si muovono nella stessa direzione
- Cov < 0 → si muovono in direzioni opposte
- Cov ≈ 0 → movimenti indipendenti
Se si hanno due titoli dove:
- uno sale quando l’altro scende → covarianza negativa → ottima diversificazione
- si muovono sempre insieme → covarianza positiva → poca diversificazione
- movimenti indipendenti → covarianza vicino a 0 → discreta diversificazione
Implementazione in Julia
[modifica | modifica sorgente]Innanzitutto installo le librerie di Julia che mi servono:
using Pkg
Pkg.add(["Convex", "SCS", "LinearAlgebra","YFinance", "DataFrames", "Statistics"])
Supponiamo di considerare tre titoli : Apple (AAPL), Microsoft (MSFT), Google (GOOG) . Tramite il package YFinance scarico i prezzi giornalieri degli ultimi 5 anni e trasformo i dati in un DataFrame:
using YFinance, DataFrames, Statistics
tickers = ["AAPL", "MSFT", "GOOG"]
data =get_prices.(tickers, range="5y", interval="1d")
data = data |> DataFrame
Calcolo i rendimenti logaritmici dei prezzi di chiusura delle azioni dati dalla formula :
.
Ad esempio per Google i prezzi di chiusura si ottengono da :
data[data.ticker.=="GOOG","close"]
1-element Vector{Vector{Float64}}:
[101.33550262451172, 102.45449829101562, 105.427001953125, 101.20850372314453, 102.63500213623047, 102.75150299072266, 105.7385025024414, 103.09600067138672, 103.32450103759766, 104.6259994506836 … 302.82000732421875, 303.94000244140625, 303.55999755859375, 314.8999938964844, 311.69000244140625, 310.9200134277344, 313.0299987792969, 307.1499938964844, 311.42999267578125, 306.3599853515625]
mentre i rendimenti si ottengono da:
function log_returns(prices)
p = prices[1]
return log.(p[2:end] ./ p[1:end-1])
end
# Calcolo i rendimenti per tutti i titoli
returns = DataFrame()
for t in tickers
prices = data1[data1.ticker.==t,"close"]
returns[!, t] = log_returns(prices)
end
first(returns, 5)
Calcolo la matrice di covarianza:
Σ = cov(Matrix(returns))
3×3 Matrix{Float64}:
0.000301193 0.000172574 0.000192449
0.000172574 0.000273012 0.000195294
0.000192449 0.000195294 0.000372485
Per finire calcolo la varianza minima del portafoglio ed i relativi pesi:
using Convex, SCS
# numero di asset
n = 3
# variabile dei pesi
w = Variable(n)
# vincoli
constraints = [sum(w) == 1,
w >= 0]
# funzione obiettivo: w' Σ w
objective = quadform(w, Σ)
# costruzione del problema
problem = minimize(objective, constraints)
# risoluzione
solve!(problem, SCS.Optimizer)
println("Pesi ottimali = ", evaluate(w))
println("Varianza minima = ", evaluate(objective))
------------------------------------------------------------------
SCS v3.2.11 - Splitting Conic Solver
(c) Brendan O'Donoghue, Stanford University, 2012
------------------------------------------------------------------
problem: variables n: 5, constraints m: 11
cones: z: primal zero / dual free vars: 1
l: linear vars: 3
q: soc vars: 7, qsize: 2
settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
max_iters: 100000, normalize: 1, rho_x: 1.00e-06
acceleration_lookback: 10, acceleration_interval: 10
compiled with openmp parallelization enabled
lin-sys: sparse-direct-amd-qdldl
nnz(A): 19, nnz(P): 0
------------------------------------------------------------------
iter | pri res | dua res | gap | obj | scale | time (s)
------------------------------------------------------------------
0| 1.45e+01 1.00e+00 2.01e+01 -9.97e+00 1.00e-01 4.76e-03
100| 5.78e-05 3.38e-05 3.09e-06 2.28e-04 1.00e-01 2.16e-02
------------------------------------------------------------------
status: solved
timings: total: 2.16e-02s = setup: 1.08e-04s + solve: 2.15e-02s
lin-sys: 5.90e-05s, cones: 4.12e-05s, accel: 1.45e-05s
------------------------------------------------------------------
objective = 0.000228
------------------------------------------------------------------
[ Info: [Convex.jl] Compilation finished: 0.01 seconds, 199.312 KiB of memory allocated
Pesi ottimali = [0.3484971984347163, 0.36753960780239314, 0.2839631923712822]
Varianza minima = 0.000226558562734014
Conclusione:
Si ottiene una varianza minima di 0.000227 col 34,84% di Apple, il 36,75% di Microsoft e il 28,39% di Google nel portafoglio, ma dalla matrice di covarianza si vede che le covarianze sono tutte positive quindi c'è poca diversificazione, nel senso che se sale un titolo sale anche l'altro e viceversa, il che è normale perché tutti appartengono al settore tech USA.