axis=1) C = self.X.ix[c.index[c >= self.rho] + 1] if C.shape[0] == 0: b = np.ones(m) / float(m) else: b = self.optimal_weights(C) return b def optimal_weights(self, X): X = np.mat(X) n, m = X.shape P = 2 * matrix(X.T * X) q = -3 * matrix(np.ones((1, n)) * X).T G = matrix(-np.eye(m)) h = matrix(np.zeros(m)) A = matrix(np.ones(m)).T b = matrix(1.) sol = solvers.qp(P, q, G, h, A, b) return np.squeeze(sol['x']) # use case if __name__ == '__main__': tools.quickrun(CORN())
# -*- coding: utf-8 -*- from universal.algo import Algo from universal.algos import CRP import universal.tools as tools import numpy as np class BCRP(CRP): """ Best Constant Rebalanced Portfolio = Constant Rebalanced Portfolio constructed with hindsight. It is often used as benchmark. Reference: T. Cover. Universal Portfolios, 1991. http://www-isl.stanford.edu/~cover/papers/paper93.pdf """ def weights(self, X): """ Find weights which maximize return on X in hindsight! """ self.b = tools.bcrp_weights(X) return super(BCRP, self).weights(X) if __name__ == '__main__': tools.quickrun(BCRP())
forever. """ PRICE_TYPE = 'raw' def __init__(self, b=None): """ :params b: Portfolio weights at start. Default are uniform. """ super(BAH, self).__init__() self.b = b def weights(self, S): """ Weights function optimized for performance. """ b = np.ones(S.shape[1]) / S.shape[1] if self.b is None else self.b # weights are proportional to price times initial weights w = S * b # normalize w = w.div(w.sum(axis=1), axis=0) # shift w = w.shift(1) w.ix[0] = 1. / S.shape[1] return w if __name__ == '__main__': tools.quickrun(BAH())
leverage = max(self.leverage, 1. / m) stretch = (leverage - 1. / m) / (1. - 1. / m) self.W = (self.W - 1. / m) * stretch + 1. / m def step(self, x, last_b): # calculate new wealth of all CRPs self.S = np.multiply(self.S, self.W * np.matrix(x).T) b = self.W.T * self.S return b / sum(b) def plot_leverage(self, S, leverage=np.linspace(1, 10, 10), **kwargs): """ Plot graph with leverages on x-axis and total wealth on y-axis. :param S: Stock prices. :param leverage: List of parameters for leverage. """ wealths = [] for lev in leverage: self.leverage = lev wealths.append(self.run(S).total_wealth) ax = pd.Series(wealths, index=leverage, **kwargs).plot(**kwargs) ax.set_xlabel('Leverage') ax.set_ylabel('Total Wealth') return ax if __name__ == '__main__': data = tools.dataset('sp500') tools.quickrun(UP(), data)
def step(self, x, last_b, history): # calculate return prediction x_pred = self.predict(x, history.iloc[-self.window:]) b = self.update(last_b, x_pred, self.eps) return b def predict(self, x, history): """ Predict returns on next day. """ return (history / x).mean() def update(self, b, x, eps): """ Update portfolio weights to satisfy constraint b * x >= eps and minimize distance to previous weights. """ x_mean = np.mean(x) lam = max(0., (eps - np.dot(b, x)) / np.linalg.norm(x - x_mean)**2) # limit lambda to avoid numerical problems lam = min(100000, lam) # update portfolio b = b + lam * (x - x_mean) # project it onto simplex return tools.simplex_proj(b) if __name__ == '__main__': tools.quickrun(OLMAR())
# lambda from equation 7 foo = (V - x_upper * x.T * np.sum(sigma, axis=1)) / M**2 a = 2 * theta * V * foo b = foo + 2 * theta * V * (eps - log(M)) c = eps - log(M) - theta * V a,b,c = a[0,0], b[0,0], c[0,0] lam = max(0, (-b + sqrt(b**2 - 4 * a * c)) / (2. * a), (-b - sqrt(b**2 - 4 * a * c)) / (2. * a)) # bound it due to numerical problems lam = min(lam, 1E+7) # update mu and sigma mu = mu - lam * sigma * (x - x_upper) / M sigma = inv(inv(sigma) + 2 * lam * theta * diag(x)**2) """ tmp_sigma = inv(inv(sigma) + theta*lam/U_sqroot*diag(xt)^2); % Don't update sigma if results are badly scaled. if all(~isnan(tmp_sigma(:)) & ~isinf(tmp_sigma(:))) sigma = tmp_sigma; end """ return mu, sigma # use case if __name__ == '__main__': tools.quickrun(CWMR())
PRICE_TYPE = 'raw' REPLACE_MISSING = True def __init__(self, window=5, eps=10., tau=0.001): """ :param window: Lookback window. :param eps: Constraint on return for new weights on last price (average of prices). x * w >= eps for new weights w. :param tau: Precision for finding median. Recommended value is around 0.001. Strongly affects algo speed. """ super(RMR, self).__init__(window, eps) self.tau = tau def predict(self, x, history): """ find L1 median to historical prices """ y = history.mean() y_last = None while y_last is None or norm(y - y_last) / norm(y_last) > self.tau: y_last = y d = norm(history - y) y = history.div(d, axis=0).sum() / (1. / d).sum() return y / x if __name__ == '__main__': tools.quickrun(RMR())
def update(self, b, x, eps, C): """ Update portfolio weights to satisfy constraint b * x <= eps and minimize distance to previous weights. """ x_mean = np.mean(x) le = max(0., np.dot(b, x) - eps) if self.variant == 0: lam = le / np.linalg.norm(x - x_mean)**2 elif self.variant == 1: lam = min(C, le / np.linalg.norm(x - x_mean)**2) elif self.variant == 2: lam = le / (np.linalg.norm(x - x_mean)**2 + 0.5 / C) # limit lambda to avoid numerical problems lam = min(100000, lam) # update portfolio b = b - lam * (x - x_mean) # project it onto simplex return tools.simplex_proj(b) if __name__ == '__main__': tools.quickrun(PAMR())
def step(self, x, last_b, history): # find indices of nearest neighbors throughout history ixs = self.find_nn(history, self.k, self.l) # get returns from the days following NNs J = history.iloc[[history.index.get_loc(i) + 1 for i in ixs]] # get best weights return tools.bcrp_weights(J) def find_nn(self, H, k, l): """ Note that nearest neighbors are calculated in a different (more efficient) way than shown in the article. param H: history """ # calculate distance from current sequence to every other point D = H * 0 for i in range(1, k+1): D += (H.shift(i-1) - H.iloc[-i])**2 D = D.sum(1).iloc[:-1] # sort and find nearest neighbors D.sort() return D.index[:l] if __name__ == '__main__': tools.quickrun(BNN())
Reference: Li Gao, Weiguo Zhang Weighted Moving Averag Passive Aggressive Algorithm for Online Portfolio Selection, 2013. http://ieeexplore.ieee.org/xpl/login.jsp?tp=&arnumber=6643896 """ PRICE_TYPE = 'ratio' def __init__(self, window=5, **kwargs): """ :param w: Windows length for moving average. :param kwargs: Additional arguments for PAMR. """ super(WMAMR, self).__init__(**kwargs) if window < 1: raise ValueError('window parameter must be >=1') self.window = window def step(self, x, last_b, history): xx = history[-self.window:].mean() # calculate return prediction b = self.update(last_b, xx, self.eps, self.C) return b # use case if __name__ == '__main__': tools.quickrun(WMAMR())
for (i=0; i<Nc[1]; i++) { float total_claim=0.; for (j=0; j<Nc[1]; j++) { total_claim += claim[i][j]; } if(total_claim != 0){ for (j=0; j<Nc[1]; j++) { transfer[i][j] = W2(t,i) * claim[i][j] / total_claim; } } } for (i=0; i<Nc[1]; i++) { W2(t+1,i) = W2(t,i); for (j=0; j<Nc[1]; j++) { W2(t+1,i) += transfer[j][i] - transfer[i][j]; } } } """ return weave.inline(code, ['c', 'mu', 'w']) get_weights_c(CORR, EX, weights) return weights if __name__ == '__main__': tools.quickrun(Anticor())
PRICE_TYPE = 'raw' def __init__(self, b=None): """ :params b: Portfolio weights at start. Default are uniform. """ super(BAH, self).__init__() self.b = b def weights(self, S): """ Weights function optimized for performance. """ b = np.ones(S.shape[1]) / S.shape[1] if self.b is None else self.b # weights are proportional to price times initial weights w = S * b # normalize w = w.div(w.sum(axis=1), axis=0) # shift w = w.shift(1) w.ix[0] = 1./S.shape[1] return w if __name__ == '__main__': tools.quickrun(BAH())
C = self.X.ix[c.index[c >= self.rho] + 1] if C.shape[0] == 0: b = np.ones(m) / float(m) else: b = self.optimal_weights(C) return b def optimal_weights(self, X): X = np.mat(X) n,m = X.shape P = 2 * matrix(X.T * X) q = -3 * matrix(np.ones((1,n)) * X).T G = matrix(-np.eye(m)) h = matrix(np.zeros(m)) A = matrix(np.ones(m)).T b = matrix(1.) sol = solvers.qp(P, q, G, h, A, b) return np.squeeze(sol['x']) # use case if __name__ == '__main__': tools.quickrun(CORN())
else: data.plot(logy=False) if show_3d: assert dim == 3, '3D plot works for exactly 3 assets.' plt.figure() fun = lambda b: CRP(b).run(data).total_wealth ternary.plot_heatmap(fun, steps=20, boundary=True) elif dim == 2: x, y = _crp(data) s = pd.Series(y, index=x) s.plot(ax=axes[1], logy=True) plt.title('CRP performance') plt.xlabel('weight of {}'.format(data.columns[0])) elif dim > 2: fig, axes = plt.subplots(ncols=dim - 1, nrows=dim - 1) for i in range(dim - 1): for j in range(i + 1, dim): x, y = _crp(data[[i, j]]) ax = axes[i][j - 1] ax.plot(x, y) ax.set_title('{} & {}'.format(data.columns[i], data.columns[j])) ax.set_xlabel('weights of {}'.format(data.columns[i])) if __name__ == '__main__': result = tools.quickrun(CRP()) print(result.information)
class EG(Algo): """ Exponentiated Gradient (EG) algorithm by Helmbold et al. Reference: Helmbold, David P., et al. "OnāLine Portfolio Selection Using Multiplicative Updates." Mathematical Finance 8.4 (1998): 325-347. """ def __init__(self, eta=0.05): """ :params eta: Learning rate. Controls volatility of weights. """ super(EG, self).__init__() self.eta = eta def init_weights(self, m): return np.ones(m) / m def step(self, x, last_b): b = last_b * np.exp(self.eta * x / sum(x * last_b)) return b / sum(b) if __name__ == '__main__': data = tools.dataset('nyse_o') tools.quickrun(EG(eta=0.5), data)
data.plot(ax=axes[0], logy=True) else: data.plot(logy=False) if show_3d: assert dim == 3, '3D plot works for exactly 3 assets.' plt.figure() fun = lambda b: CRP(b).run(data).total_wealth ternary.plot_heatmap(fun, steps=20, boundary=True) elif dim == 2: x,y = _crp(data) s = pd.Series(y, index=x) s.plot(ax=axes[1], logy=True) plt.title('CRP performance') plt.xlabel('weight of {}'.format(data.columns[0])) elif dim > 2: fig, axes = plt.subplots(ncols=dim-1, nrows=dim-1) for i in range(dim-1): for j in range(i + 1, dim): x,y = _crp(data[[i,j]]) ax = axes[i][j-1] ax.plot(x,y) ax.set_title('{} & {}'.format(data.columns[i], data.columns[j])) ax.set_xlabel('weights of {}'.format(data.columns[i])) if __name__ == '__main__': result = tools.quickrun(CRP()) print(result.information)
P = matrix((sigma - r*mu*mu.T + (n*r)**2) / (1+r)) q = matrix(-mu) G = matrix(-np.eye(n)) h = matrix(np.zeros(n)) sol = solvers.qp(P, q, G, h) return np.squeeze(sol['x']) def plot_fraction(self, S, fractions=np.linspace(0.,2.,10), **kwargs): """ Plot graph with Kelly fraction on x-axis and total wealth on y-axis. :param S: Stock prices. :param fractions: List (ndarray) of fractions used. """ wealths = [] for fraction in fractions: self.fraction = fraction wealths.append(self.run(S).total_wealth) ax = pd.Series(wealths, index=fractions, **kwargs).plot(**kwargs) ax.set_xlabel('Kelly Fraction') ax.set_ylabel('Total Wealth') return ax # use case if __name__ == '__main__': tools.quickrun(Kelly())
return np.ones(m) / m def step(self, x, last_b, history): # calculate return prediction x_pred = self.predict(x, history.iloc[-self.window:]) b = self.update(last_b, x_pred, self.eps) return b def predict(self, x, history): """ Predict returns on next day. """ return (history / x).mean() def update(self, b, x, eps): """ Update portfolio weights to satisfy constraint b * x >= eps and minimize distance to previous weights. """ x_mean = np.mean(x) lam = max(0., (eps - np.dot(b, x)) / np.linalg.norm(x - x_mean)**2) # limit lambda to avoid numerical problems lam = min(100000, lam) # update portfolio b = b + lam * (x - x_mean) # project it onto simplex return tools.simplex_proj(b) if __name__ == '__main__': tools.quickrun(OLMAR())
def step(self, r, p): # calculate gradient grad = np.mat(r / np.dot(p, r)).T # update A self.A += grad * grad.T # update b self.b += (1 + 1. / self.beta) * grad # projection of p induced by norm A pp = self.projection_in_norm(self.delta * self.A.I * self.b, self.A) return pp * (1 - self.eta) + np.ones(len(r)) / float(len(r)) * self.eta def projection_in_norm(self, x, M): """ Projection of x to simplex indiced by matrix M. Uses quadratic programming. """ m = M.shape[0] P = matrix(2 * M) q = matrix(-2 * M * x) G = matrix(-np.eye(m)) h = matrix(np.zeros((m, 1))) A = matrix(np.ones((1, m))) b = matrix(1.) sol = solvers.qp(P, q, G, h, A, b) return np.squeeze(sol['x']) if __name__ == '__main__': tools.quickrun(ONS())
def step(self, r, p): # calculate gradient grad = np.mat(r / np.dot(p, r)).T # update A self.A += grad * grad.T # update b self.b += (1 + 1./self.beta) * grad # projection of p induced by norm A pp = self.projection_in_norm(self.delta * self.A.I * self.b, self.A) return pp * (1 - self.eta) + np.ones(len(r)) / float(len(r)) * self.eta def projection_in_norm(self, x, M): """ Projection of x to simplex indiced by matrix M. Uses quadratic programming. """ m = M.shape[0] P = matrix(2*M) q = matrix(-2 * M * x) G = matrix(-np.eye(m)) h = matrix(np.zeros((m,1))) A = matrix(np.ones((1,m))) b = matrix(1.) sol = solvers.qp(P, q, G, h, A, b) return np.squeeze(sol['x']) if __name__ == '__main__': tools.quickrun(ONS())
def step(self, x, last_b): # calculate return prediction b = self.update(last_b, x, self.eps, self.C) return b def update(self, b, x, eps, C): """ Update portfolio weights to satisfy constraint b * x <= eps and minimize distance to previous weights. """ x_mean = np.mean(x) le = max(0., np.dot(b, x) - eps) if self.variant == 0: lam = le / np.linalg.norm(x - x_mean)**2 elif self.variant == 1: lam = min(C, le / np.linalg.norm(x - x_mean)**2) elif self.variant == 2: lam = le / (np.linalg.norm(x - x_mean)**2 + 0.5 / C) # limit lambda to avoid numerical problems lam = min(100000, lam) # update portfolio b = b - lam * (x - x_mean) # project it onto simplex return tools.simplex_proj(b) if __name__ == '__main__': tools.quickrun(PAMR())