In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from pandas import DataFrame, Series
In [2]:
import pandas.io.data as web
names = ['AAPL', 'GOOG', 'MSFT', 'DELL', 'GS', 'MS', 'BAC', 'C']
def get_px(stock, start, end):
return web.get_data_yahoo(stock, start, end)['Adj Close']
In [3]:
px = DataFrame({n: get_px(n, '1/1/2009', '6/1/2012') for n in names})
In [4]:
px
Out[4]:
In [5]:
px = px.asfreq('B').fillna(method='pad')
In [6]:
rets = px.pct_change()
In [7]:
((1 + rets).cumprod() - 1).plot()
Out[7]:
In [78]:
def calc_mom(price, lookback, lag):
mom_ret = price.shift(lag).pct_change(lookback)
ranks = mom_ret.rank(axis=1, ascending=False)
#ranks = ranks.fillna(method='bfill')
demeaned = ranks.sub(ranks.mean(axis=1), axis='index')
return demeaned.divide(demeaned.std(axis=1), axis='index')
In [79]:
compound = lambda x: (1 + x).prod() - 1
daily_sr = lambda x: x.mean() / x.std()
def strat_sr(prices, lb, hold):
# 计算投资组合权重
freq = '%dB' % hold
port = calc_mom(prices, lb, lag=1)
daily_rets = prices.pct_change()
# 计算投资组合收益
port = port.shift(1).resample(freq, how='first')
returns = daily_rets.resample(freq, how=compound)
port_rets = (port * returns).sum(axis=1)
return daily_sr(port_rets) * np.sqrt(252 / hold)
#return port_rets
In [80]:
strat_sr(px, 70, 30)
Out[80]:
In [83]:
from collections import defaultdict
lookbacks = range(20, 90, 5)
holdings = range(20, 90, 5)
dd = defaultdict(dict)
for lb in lookbacks:
for hold in holdings:
dd[lb][hold] = strat_sr(px, lb, hold)
ddf = DataFrame(dd)
ddf.index.name = 'Holding Period'
ddf.columns.name = 'Lookback Period'
In [84]:
def heatmap(df, cmap=plt.cm.gray_r):
fig = plt.figure()
ax = fig.add_subplot(111)
axim = ax.imshow(df.values, cmap=cmap, interpolation='nearest')
ax.set_xlabel(df.columns.name)
ax.set_xticks(np.arange(len(df.columns)))
ax.set_xticklabels(list(df.columns))
ax.set_ylabel(df.index.name)
ax.set_yticks(np.arange(len(df.index)))
ax.set_yticklabels(list(df.index))
plt.colorbar(axim)
In [85]:
heatmap(ddf)
In [86]:
# 标准普尔500指数的近似价格
px = web.get_data_yahoo('SPY')['Adj Close'] * 10
px
Out[86]:
In [87]:
len(px)
Out[87]:
In [88]:
from datetime import datetime
expiry = {'ESU2': datetime(2012, 9, 21),
'ESZ2': datetime(2012, 12, 21)}
expiry = Series(expiry).order()
In [89]:
expiry
Out[89]:
In [90]:
np.random.seed(12347)
N = 200
walk = (np.random.randint(0, 200, size=N) - 100) * 0.25
perturb = (np.random.randint(0, 20, size=N) - 10) * 0.25
walk = walk.cumsum()
rng = pd.date_range(px.index[0], periods=len(px) + N, freq='B')
near = np.concatenate([px.values, px.values[-1] + walk])
far = np.concatenate([px.values, px.values[-1] + walk + perturb])
prices = DataFrame({'ESU2': near, 'ESZ2': far}, index=rng)
prices.tail()
Out[90]:
In [91]:
def get_roll_weights(start, expiry, items, roll_periods=5):
# start: 用于计算加权矩阵的第一天
# expiry: 由”合约代码 -> 到期日期“组成的序列
# items: 一组合约名称
dates = pd.date_range(start, expiry[-1], freq='B')
weights = DataFrame(np.zeros((len(dates), len(items))),
index=dates, columns=items)
prev_date = weights.index[0]
for i, (item, ex_date) in enumerate(expiry.iteritems()):
if i < len(expiry) - 1:
weights.ix[prev_date:ex_date - pd.offsets.BDay(), item] = 1
roll_rng = pd.date_range(end=ex_date - pd.offsets.BDay(),
periods=roll_periods + 1, freq='B')
decay_weights = np.linspace(0, 1, roll_periods + 1)
weights.ix[roll_rng, item] = 1 - decay_weights
weights.ix[roll_rng, expiry.index[i + 1]] = decay_weights
else:
weights.ix[prev_date:, item] = 1
prev_date = ex_date
return weights
In [92]:
weights = get_roll_weights('6/1/2012', expiry, prices.columns)
In [93]:
weights.ix['2012-09-12':'2012-09-21']
Out[93]:
In [96]:
rolled_returns = (prices['2012-06-01':'2012-12-21'].pct_change() * weights).sum(1)
rolled_returns
Out[96]:
In [98]:
aapl = web.get_data_yahoo('AAPL', '2000-01-01', '2012-07-27')['Adj Close']
msft = web.get_data_yahoo('MSFT', '2000-01-01', '2012-07-27')['Adj Close']
aapl_rets = aapl.pct_change()
msft_rets = msft.pct_change()
In [99]:
aapl_rets.rolling(250).corr(msft_rets).plot()
Out[99]:
In [100]:
model = pd.ols(y=aapl_rets, x={'MSFT': msft_rets}, window=250)
model.beta
Out[100]:
In [101]:
model.beta['MSFT'].plot()
Out[101]:
In [ ]: