-
Notifications
You must be signed in to change notification settings - Fork 997
/
Copy pathutilities_for_tests.py
139 lines (115 loc) · 4.38 KB
/
utilities_for_tests.py
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
import os
import numpy as np
import pandas as pd
from pypfopt import expected_returns, risk_models
from pypfopt.cla import CLA
from pypfopt.efficient_frontier import (
EfficientCDaR,
EfficientCVaR,
EfficientFrontier,
EfficientSemivariance,
)
def resource(name):
return os.path.join(os.path.dirname(__file__), "resources", name)
def get_data():
return pd.read_csv(resource("stock_prices.csv"), parse_dates=True, index_col="date")
def get_benchmark_data():
return pd.read_csv(resource("spy_prices.csv"), parse_dates=True, index_col="date")
def get_market_caps():
mcaps = {
"GOOG": 927e9,
"AAPL": 1.19e12,
"FB": 574e9,
"BABA": 533e9,
"AMZN": 867e9,
"GE": 96e9,
"AMD": 43e9,
"WMT": 339e9,
"BAC": 301e9,
"GM": 51e9,
"T": 61e9,
"UAA": 78e9,
"SHLD": 0,
"XOM": 295e9,
"RRC": 1e9,
"BBY": 22e9,
"MA": 288e9,
"PFE": 212e9,
"JPM": 422e9,
"SBUX": 102e9,
}
return mcaps
def get_cov_matrix():
return pd.read_csv(resource("cov_matrix.csv"), index_col=0)
def setup_efficient_frontier(data_only=False, *args, **kwargs):
df = get_data()
mean_return = expected_returns.mean_historical_return(df)
sample_cov_matrix = risk_models.sample_cov(df)
if data_only:
return mean_return, sample_cov_matrix
return EfficientFrontier(
mean_return, sample_cov_matrix, verbose=True, *args, **kwargs
)
def setup_efficient_semivariance(data_only=False, *args, **kwargs):
df = get_data().dropna(axis=0, how="any")
mean_return = expected_returns.mean_historical_return(df)
historic_returns = expected_returns.returns_from_prices(df)
if data_only:
return mean_return, historic_returns
return EfficientSemivariance(
mean_return, historic_returns, verbose=True, *args, **kwargs
)
def setup_efficient_cvar(data_only=False, *args, **kwargs):
df = get_data().dropna(axis=0, how="any")
mean_return = expected_returns.mean_historical_return(df)
historic_returns = expected_returns.returns_from_prices(df)
if data_only:
return mean_return, historic_returns
return EfficientCVaR(mean_return, historic_returns, verbose=True, *args, **kwargs)
def setup_efficient_cdar(data_only=False, *args, **kwargs):
df = get_data().dropna(axis=0, how="any")
mean_return = expected_returns.mean_historical_return(df)
historic_returns = expected_returns.returns_from_prices(df)
if data_only:
return mean_return, historic_returns
return EfficientCDaR(mean_return, historic_returns, verbose=True, *args, **kwargs)
def setup_cla(data_only=False, *args, **kwargs):
df = get_data()
mean_return = expected_returns.mean_historical_return(df)
sample_cov_matrix = risk_models.sample_cov(df)
if data_only:
return mean_return, sample_cov_matrix
return CLA(mean_return, sample_cov_matrix, *args, **kwargs)
def simple_ef_weights(expected_returns, cov_matrix, target_return, weights_sum):
"""
Calculate weights to achieve target_return on the efficient frontier.
The only constraint is the sum of the weights.
Note: This is just a simple test utility, it does not support the generalised
constraints that EfficientFrontier does and is used to check the results
of EfficientFrontier in simple cases. In particular it is not capable of
preventing negative weights (shorting).
:param expected_returns: expected returns for each asset.
:type expected_returns: np.ndarray
:param cov_matrix: covariance of returns for each asset.
:type cov_matrix: np.ndarray
:param target_return: the target return for the portfolio to achieve.
:type target_return: float
:param weights_sum: the sum of the returned weights, optimization constraint.
:type weights_sum: float
:return: weight for each asset, which sum to 1.0
:rtype: np.ndarray
"""
# Solve using Lagrangian and matrix inversion.
r = expected_returns.reshape((-1, 1))
m = np.block(
[
[cov_matrix, r, np.ones(r.shape)],
[r.transpose(), 0, 0],
[np.ones(r.shape).transpose(), 0, 0],
]
)
y = np.block([[np.zeros(r.shape)], [target_return], [weights_sum]])
x = np.linalg.inv(m) @ y
# Weights are all but the last 2 elements, which are the lambdas.
w = x.flatten()[:-2]
return w