411 REFERENCE · Wikibooks
Scientific Calculations with Julia/Risk Minimization in Finance
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Scientific Calculations with Julia Risk Minimization in Finance Pension Simulator Maximizing Returns in Finance
In finance, when you want to minimize risk by having n assets that make up a portfolio, for example, consisting of n stocks, you solve the problem by minimizing the following objective function:
where is the variance or volatility of the portfolio.
If a stock has an expected return of 7%, but sometimes returns +20%, sometimes returns -15%, then it is risky not because it always loses, but because it is unpredictable. The mathematical measure of this unpredictability is the variance or volatility of the portfolio, which must be minimized.
is the covariance matrix, and w is the weight vector , which represents the percentage of the portfolio invested in each asset. For example:
→ 40% in asset 1
→ 35% in asset 2
→ 25% in asset 3
And the following always hold:
and the weights are all positive.
The covariance matrix is one of the most important mathematical objects in quantitative finance.
For a portfolio with n assets, the matrix is:
Where is the return series for asset ( i ).
On the main diagonal is the variance of the various assets, so:
which measures the volatility of the asset (the greater it is, the riskier it is)
Off the diagonal is the covariance:
and measures whether two assets move together, so if:
Cov > 0 → they move in the same direction
Cov < 0 → they move in opposite directions
Cov ≈ 0 → independent movements
If you have two stocks where:
one rises when the other falls → negative covariance → excellent diversification
they always move together → positive covariance → little diversification
independent movements → Covariance near 0 → discrete diversification
Implementation in Julia
First, I install the Julia libraries I need:
using Pkg
Pkg.add(["Convex", "SCS", "LinearAlgebra","YFinance", "DataFrames", "Statistics"])
Suppose we consider three stocks: Apple (AAPL), Microsoft (MSFT), and Google (GOOG). Using the YFinance package, I download daily prices for the last 5 years and transform the data into a DataFrame:
using YFinance, DataFrames, Statistics
tickers = ["AAPL", "MSFT", "GOOG"]
data = get_prices.(tickers, range="5y", interval="1d")
data = data |> DataFrame
I calculate the logarithmic returns of the closing prices of the given stocks using the formula:
.
For example, for Google, closing prices are obtained from:
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]
while the returns are obtained from:
function log_returns(prices)
p = prices[1]
return log.(p[2:end] ./ p[1:end-1])
end
# Calculate returns for all stocks
returns = DataFrame()
for t in tickers
prices = data1[data1.ticker.==t,"close"]
returns[!, t] = log_returns(prices)
end
first(returns, 5)
I calculate the covariance matrix:
Σ = 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
Finally, I calculate the minimum variance of the portfolio and its weights:
using Convex, SCS
# number of assets
n = 3
# weight variable
w = Variable(n)
# constraints
constraints = [sum(w) == 1,
w >= 0]
# objective function: w' Σ w
objective = quadform(w, Σ)
# problem construction
problem = minimize(objective, constraints)
# resolution
solve!(problem, SCS.Optimizer)
println("Optimal weights = ", evaluate(w))
println("Minimum variance = ", 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
Optimal weights = [0.3484971984347163, 0.36753960780239314, 0.2839631923712822]
Minimum variance = 0.000226558562734014
Conclusion:
We obtain a minimum variance of 0.000227 with 34.84% Apple, 36.75% Microsoft, and 28.39% Google in the portfolio. However, from the covariance matrix, we see that the covariances are all positive, so there is little diversification, meaning that if one stock rises, the other also rises, and vice versa, which is normal because they all belong to the US tech sector.