-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathportfolio_allocation.py
More file actions
141 lines (106 loc) · 2.85 KB
/
Copy pathportfolio_allocation.py
File metadata and controls
141 lines (106 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import numpy as np
import scipy
import pandas as pd
def get_reduced_correlation_weights(R):
"""
Implementation of minimum correlation algorithm.
ref: http://cssanalytics.com/doc/MCA%20Paper.pdf
parameters
----------
R : pandas.DataFrame
Timeseries of asset returns
returns
-------
pandas.Series
portfolio weights that minimize the correlation
in the portfolio.
"""
correlations = R.corr()
adj_correlations = get_adjusted_cor_matrix(correlations)
initial_weights = adj_correlations.T.mean()
ranks = initial_weights.rank()
ranks /= ranks.sum()
weights = adj_correlations.dot(ranks)
weights /= weights.sum()
return weights
def get_adjusted_cor_matrix(cor):
"""
Helper function for get_reduced_correlation_weights
parameters
----------
cor : pandas.DataFrame
Asset returns correlation matrix
returns
-------
pandas.DataFrame
adjusted correlation matrix
"""
values = cor.values.flatten()
mu = np.mean(values)
sigma = np.std(values)
distribution = scipy.stats.norm(mu, sigma)
return 1 - cor.apply(lambda x: distribution.cdf(x))
def minimum_var(R):
"""
Minimum Variance Portfolio weights.
parameters
----------
R : pandas.DataFrame
Dataframe of asset returns
returns
-------
pandas.Series
minimum variance weights
"""
cov_inv = np.linalg.inv(R.cov())
ones = np.ones(len(cov_inv))
v = cov_inv.dot(ones)
w = v / ones.T.dot(v)
return pd.Series(w, index=R.columns)
def efficient_frontier(R, target_return):
"""
Efficient Frontier Portfolio weights.
An EF portfolio can be thought of as the
portfolio with the minimum risk for a given target return.
parameters
----------
R : pandas.DataFrame
asset returns
target_return : float
the target return for the portfolio
returns
-------
pandas.Series
efficient frontier portfolio weights
"""
c_inv = np.linalg.inv(R.cov())
ones = np.ones(len(c_inv))
mu_t = np.array([target_return, 1.0])
M = np.array([R.mean(), ones]).T
B = np.dot(M.T, c_inv.dot(M))
B_inv = np.linalg.inv(B)
v = np.dot(c_inv, M)
u = np.dot(B_inv, mu_t)
w = np.dot(v, u)
return pd.Series(w, index=R.columns)
def tangent_portfolio(R, rfr=0.0):
"""
Modern portfolio theory tangency portfolio
given a risk free rate
parameters
----------
R : pandas.DataFrame
asset returns
rfr : float
the risk free rate
returns
-------
pandas.Series
tangent portfolio weights
"""
c_inv = np.linalg.inv(R.cov())
mu = R.mean()
ones = np.ones(len(mu), dtype=float)
rf = rfr * ones
t = c_inv.dot(mu - rf) / ones.T.dot(c_inv.dot(mu - rf))
return pd.Series(t, index=R.columns)