-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathoptimum port - quantopian.py
58 lines (48 loc) · 2.4 KB
/
optimum port - quantopian.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
import pandas as pd
import numpy as np
import numpy.linalg as la
import math
def initialize(context):
#parameters
context.nobs = 252
context.recalibrate = 126 #re-estimate every so often (in days)
context.leverage= 1
#setup the identifiers and data storage
context.tickers = ['xlf', 'xle', 'xlu', 'xlk', 'xlb', 'xlp', 'xly','xli', 'xlv']
context.sids = [ sid(19656), sid(19655),
sid(19660), sid(19658),
sid(19654), sid(19659),
sid(19662), sid(19657),
sid(19661) ]
context.data = pd.DataFrame({ k : pd.Series() for k in context.tickers } )
context.mvp = np.array([0]*len(context.tickers))
context.temp = False
context.daysToRecalibration = 0
context.onevec = np.asmatrix(np.ones((len(context.tickers), 1)))
def handle_data(context, data):
if len(context.data.index) < context.nobs:
#still recording data
newRow = pd.DataFrame({k:float(data[e].returns()) for k,e in zip(context.tickers, context.sids) },index=[0])
context.data = context.data.append(newRow, ignore_index = True)
else:
newRow = pd.DataFrame({k:float(data[e].returns()) for k,e in zip(context.tickers, context.sids) },index=[0])
context.data = context.data.append(newRow, ignore_index = True)
context.data = context.data[1:len(context.data.index)]
if context.daysToRecalibration == 0:
context.daysToRecalibration = context.recalibrate
#recalibrate
log.info('recalibrating...')
#calculate the minimum variance portfolio weights;
precision = np.asmatrix(la.inv(context.data.cov()))
pimv = precision*context.onevec / (context.onevec.T*precision*context.onevec)
pimv = { e:pimv[i,0] for i,e in enumerate(context.tickers) }
#print pimv
#open all positions:
startingCash = context.portfolio.starting_cash*context.leverage
for i, e in enumerate(context.sids):
currentPosition = context.portfolio.positions[e].amount
newPosition = math.floor(startingCash*pimv[context.tickers[i]]/data[e].price)
order(e, newPosition - currentPosition)
else:
context.daysToRecalibration -= 1
record(c = context.portfolio.positions_value)