-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPortfolioSimulation.py
107 lines (81 loc) · 2.81 KB
/
PortfolioSimulation.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
import numpy as np
import matplotlib.pyplot as plt
import cvxopt as opt
from cvxopt import blas, solvers
import pandas as pd
from zipline.utils.factory import load_bars_from_yahoo
np.random.seed(123)
# Turn off progress printing
solvers.options['show_progress'] = False
## NUMBER OF ASSETS
n_assets = 4
## NUMBER OF OBSERVATIONS
n_observations = 1000
return_vec = np.random.randn(n_assets, n_observations)
#plt.plot(return_vec.T, alpha=0.4)
#plt.xlabel('time')
#plt.ylabel('returns')
#plt.show()
def rand_weights(n):
''' Produces n random weights that sum up to 1 '''
k = np.random.rand(n)
return k / sum(k)
#print(rand_weights(n_assets))
#print(rand_weights(n_assets))
def random_portfolio(returns):
'''
Returns the mean and standard deviation of returns for a random portfolio
'''
p = np.asmatrix(np.mean(returns, axis=1))
w = np.asmatrix(rand_weights(returns.shape[0]))
C = np.asmatrix(np.cov(returns))
mu = w * p.T
sigma = np.sqrt(w * C * w.T)
# This recursion reduces outliers to keep plots pretty
if sigma > 2:
return random_portfolio(returns)
return mu, sigma
n_portfolios = 500
means, stds = np.column_stack([
random_portfolio(return_vec)
for _ in range(n_portfolios)
])
## CALCULATE THE EFFICIENT FRONTIER
def optimal_portfolio(returns):
n = len(returns)
returns = np.asmatrix(returns)
N = 100
mus = [10**(5.0 * t/N - 1.0) for t in range(N)]
# convert to cvxopt matrices
S = opt.matrix(np.cov(returns))
pbar = opt.matrix(np.mean(returns, axis=1))
# create constraint matrices
G = -opt.matrix(np.eye(n)) # negative n x n identity matrix
h = opt.matrix(0.0, (n ,1))
A = opt.matrix(1.0, (1, n))
b = opt.matrix(1.0)
# Calculate efficient frontier weights using quadratic programming
portfolios = [solvers.qp(mu*S, -pbar, G, h, A, b)['x']
for mu in mus]
## CALCULATE RISKS AND RETURNS FOR FRONTIER
returns = [blas.dot(pbar, x) for x in portfolios]
risks = [np.sqrt(blas.dot(x, S*x)) for x in portfolios]
## CALCULATE THE 2ND DEGREE POLYNOMIAL OF THE FRONTIER CURVE
m1 = np.polyfit(returns, risks, 2)
x1 = np.sqrt(m1[2] / m1[0])
## CALCULATE THE OPTIMAL PORTFOLIO
wt = solvers.qp(opt.matrix(x1 * S), -pbar, G, h, A, b)['x']
return np.asarray(wt), returns, risks
weights, returns, risks = optimal_portfolio(return_vec)
end = pd.Timestamp.utcnow()
start = end - 2500 * pd.tseries.offsets.BDay()
data = load_bars_from_yahoo(stocks=['IBM', 'GLD', 'XOM', 'AAPL', 'MSFT', 'TLT', 'SHY'], start=start, end=end)
data.loc[:, :, 'price'].plot(figsize=(8.5))
plt.ylabel('price in $')
#plt.plot(stds, means, 'o', markersize = 5)
#plt.xlabel('std')
#plt.ylabel('mean')
#plt.plot(risks, returns, 'y-o')
#plt.title('Markowitz bullet and efficient frontier')
plt.show()
print(weights)