411 REFERENCE · Wikibooks
Scientific Calculations with Julia/Portfolio Optimization in Finance
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Scientific Calculations with Julia Portfolio Optimization in Finance Maximizing Returns in Finance Basic Model of Sports Betting
In finance, when you want to optimize a portfolio according to Harry Markowitz, consisting, for example, of n stocks, you solve the problem by minimizing the following objective function:
subject to:
where is the variance of the portfolio you want to minimize with expected return ≥ target.
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 portfolio's variance, which must be minimized by ensuring that the expected return is greater than or equal to the target, while volatility is the square root of the variance.
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 Amazon (AMZN). 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", "AMZN"]
data = get_prices.(tickers, range="5y", interval="1d")
data = data |> DataFrame
I create a dictionary and then a DataFrame with the closing prices of the stocks and their respective dates:
prices = Dict()
for t in tickers
prices[t] = data[data.ticker.==t,"adjclose"] # adjusted price column
end
# Convert to a single DataFrame
df = DataFrame(Date = data[data.ticker.=="AMZN","timestamp"])
for t in tickers
df[!, t] = prices[t]
end
df
The average returns of the 3 stocks are calculated and we note that Apple makes more:
AAPL = reduce(vcat, df.AAPL)
MSFT = reduce(vcat, df.MSFT)
AMZN = reduce(vcat, df.AMZN)
# Calculate daily returns
rets = dropmissing(DataFrame(
AAPL = diff(log.(AAPL)),
MSFT = diff(log.(MSFT)),
AMZN = diff(log.(AMZN))
))
μ = mean(Matrix(rets), dims=1)'
println("Average returns:")
println(μ)
Average returns:
[0.0006538039701943343; 0.0005005829765010237; 0.00029305866759470864;;]
I calculate the covariance matrix:
Σ = cov(Matrix(rets))
3×3 Matrix{Float64}:
0.000299483 0.000171464 0.000210499
0.000171464 0.000272221 0.000233099
0.000210499 0.000233099 0.000493231
Finally, I calculate the minimum variance of the portfolio and its weights:
#Target return daily:
r_target = 0.0004
#Decision variables:
n = length(μ)
w = Variable(n)
#Optimization issue:
# constraints
constraints = [
sum(w) == 1,
μ' * w >= r_target,
w >= 0
]
# objective function:
objective = quadform(w, Σ)
# construction of the problem
problem = minimize(objective, constraints)
solve!(problem, SCS.Optimizer)
weights = evaluate(w)
println("Optimal weights = ", weights)
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: 12
cones: z: primal zero / dual free vars: 1
l: linear vars: 4
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): 22, nnz(P): 0
------------------------------------------------------------------
iter | pri res | dua res | gap | obj | scale | time (s)
------------------------------------------------------------------
0| 1.45e+01 1.00e+00 2.01e+01 -9.96e+00 1.00e-01 4.88e-04
75| 1.77e-04 7.28e-05 2.82e-05 2.60e-04 1.00e-01 6.02e-04
------------------------------------------------------------------
status: solved
timings: total: 6.04e-04s = setup: 2.04e-04s + solve: 4.00e-04s
lin-sys: 3.97e-05s, cones: 2.52e-05s, accel: 7.34e-06s
------------------------------------------------------------------
objective = 0.000260
------------------------------------------------------------------
Optimal weights = [0.35076741527347427, 0.37629612818017755, 0.27293645299415875]
Minimum variance = 0.00024558676226717267
# Daily return
portfolio_return_daily = dot(μ, weights)
# Daily volatility
portfolio_vol_daily = sqrt(weights' * Σ * weights)
# Monthly return (%): A stock market month has approximately 21 days.
portfolio_return_month = portfolio_return_daily * 21 * 100
# Annual return (%): A stock market year has approximately 252 days.
portfolio_return_year = portfolio_return_daily * 252 * 100
# Monthly volatility (%)
portfolio_vol_month = portfolio_vol_daily * sqrt(21) * 100
# Annual volatility (%)
portfolio_vol_year = portfolio_vol_daily * sqrt(252) * 100
println("Monthly return (%) = ", portfolio_return_month )
println("Annual return (%) = ", portfolio_return_year )
println("Monthly volatility (%) = ", portfolio_vol_month )
println("Annual volatility (%) = ", portfolio_vol_year )
Monthly return (%) = 0.9913696368340023
Annual return (%) = 11.896435642008028
Monthly volatility (%) = 7.163080305760683
Annual volatility (%) = 24.813638056547024
Conclusion:
A minimum variance of 0.00026 is obtained with 35.07% Apple, 37.63% Microsoft, and 27.29% Amazon in the portfolio with an expected return greater than 0.0004. 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.