Vai al contenuto

Calcoli scientifici con Julia/Massimizzazione del rendimento in finanza

Wikibooks, manuali e libri di testo liberi.
Indice del libro

In finanza quando si vuole massimizzare il rendimento atteso di un portafoglio avendo n asset che lo costituiscono , formato per esempio da n azioni, si risolve la questione, minimizzando la seguente funzione obiettivo che è tipicamente un problema di programmazione lineare:

dove sono i pesi del portafoglio il vettore dei rendimenti attesi

Implementazione in Julia

[modifica | modifica sorgente]

Innanzitutto installo le librerie di Julia che mi servono:

using Pkg
Pkg.add(["JuMP", "HiGHS"])

Supponiamo di considerare tre titoli : Apple (AAPL), Microsoft (MSFT), Amazon ("AMZN") . 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", "AMZN"]

data =get_prices.(tickers, range="5y", interval="1d")
data = data |> DataFrame

Creo un dizionario e poi un DataFrame con i prezzi di chiusura delle azioni e la rispettiva data:

prices = Dict()

for t in tickers
    prices[t] = data[data.ticker.==t,"close"]   # colonna dei prezzi aggiustati
end


# Converti in DataFrame unico
df = DataFrame(Date = data[data.ticker.=="AMZN","timestamp"])


for t in tickers
    df[!, t] = prices[t]
end

df

Si calcolano i rendimenti attesi annui delle 3 azioni e si nota che Apple rende di più col 15,82%:

Date = reduce(vcat, df.Date)
AAPL = reduce(vcat, df.AAPL)
MSFT = reduce(vcat, df.MSFT)
AMZN = reduce(vcat, df.AMZN)

# Calcola rendimenti giornalieri
rets = dropmissing(DataFrame(
    Date = Date[2:end],
    AAPL = diff(log.(AAPL)),
    MSFT = diff(log.(MSFT)),
    AMZN = diff(log.(AMZN)),
))

# Media giornaliera → annualizzata (252 giorni)
μ = Dict(
    "AAPL" => mean(rets.AAPL) * 252,
    "MSFT" => mean(rets.MSFT) * 252,
    "AMZN" => mean(rets.AMZN) * 252,
)

println("Rendimenti attesi annualizzati:")
println(μ)
Rendimenti attesi annualizzati:
Dict("MSFT" => 0.11644058687702825, "AMZN" => 0.07435392903921334, "AAPL" => 0.1582824969436331)

Tramite il modello di programmazione lineare HiGHS si scelgono i pesi ottimali e si nota che tutto il capitale va su Apple perché ha il rendimento atteso più alto, ma bisogna tenere conto della minimizzazione del rischio o della varianza - volatilità del portafoglio:

using JuMP, HiGHS, LinearAlgebra

mu_vec = [μ["AAPL"], μ["MSFT"], μ["AMZN"]]
n = length(mu_vec)

model = Model(HiGHS.Optimizer)

@variable(model, w[1:n] >= 0)
@constraint(model, sum(w) == 1)
@objective(model, Max, dot(mu_vec, w))

optimize!(model)

println("----------------------------------------------------------------------")
println("Pesi ottimali: ", value.(w))
println("Rendimento atteso: ", objective_value(model))
Running HiGHS 1.13.1 (git hash: 1d267d97c): Copyright (c) 2026 under Apache 2.0 license terms
Using BLAS: blastrampoline
LP has 1 row; 3 cols; 3 nonzeros
Coefficient ranges:
  Matrix  [1e+00, 1e+00]
  Cost    [7e-02, 2e-01]
  Bound   [0e+00, 0e+00]
  RHS     [1e+00, 1e+00]
Presolving model
1 rows, 1 cols, 1 nonzeros  0s
0 rows, 0 cols, 0 nonzeros  0s
Presolve reductions: rows 0(-1); columns 0(-3); nonzeros 0(-3) - Reduced to empty
Performed postsolve
Solving the original LP from the solution after postsolve
Model status        : Optimal
Objective value     :  1.5828249694e-01
P-D objective error :  0.0000000000e+00
HiGHS run time      :          0.00
----------------------------------------------------------------------
Pesi ottimali: [1.0, 0.0, 0.0]
Rendimento atteso: 0.1582824969436331