def init_portfolio_uniform(self): """ This function initializes the allocations by naively investing equal amounts of money into each stock. """ day_1_op = self.data.get_op(relative=False)[0, :] # raw opening prices on 1st day return get_uniform_allocation(self.num_stocks, day_1_op)
def get_new_allocation(self, cur_day): if cur_day == 0: cur_day_op = self.data.get_op( relative=False)[cur_day, :] # opening prices on |cur_day| return get_uniform_allocation(self.num_stocks, cur_day_op) else: return self.b
def get_new_allocation(self, cur_day): """ :param cur_day: :return: A (1 x num_stocks) array of fractions. Each fraction represents the amount of the money should be invested in that stock at the end of the day. If we haven't reached the start date (the day when we have confidence in our mean/covariance info), return a uniform portfolio. Otherwise, perform nonparametric markowitz. """ if cur_day == 0: cur_day_op = self.data.get_op(relative=False)[cur_day, :] # opening prices on |cur_day| return util.get_uniform_allocation(self.num_stocks, cur_day_op) elif(cur_day < self.start_date): available = util.get_avail_stocks(self.data.get_op()[cur_day,:]) num_available = np.sum(available) new_allocation = 1.0/num_available * np.asarray(available) else: k = self.k available = util.get_avail_stocks(self.data.get_op()[cur_day-self.window_len+1,:]) available_inds = util.get_available_inds(available) history = self.get_market_window(self.window_len, cur_day) num_available = history.shape[0] neighbors = np.zeros((num_available, k)) history_norms = np.diag(np.dot(history, history.T)) # Compute k nearest neighbors for each stock for i in range(num_available): stock = history[i,:] neighbors[i,:] = util.k_nearest_neighbors(stock, history, k, history_norms) # Solve optimization problem l = self.risk_aversion neighbors = neighbors.astype(int) b = Variable(num_available) c = Variable(num_available) d = 0 e = 0 for i in range(num_available): inds = available_inds[neighbors[i,:]] m_i = self.mu[inds] #self.mu[inds] S_i = self.sigma[inds,:] S_i = S_i[:,inds] d += (b[i]*m_i).T*np.ones(k) e += quad_form(b[i]*np.ones(k), S_i) constraints = [c>= b, c >= -b, sum_entries(c)==1] #, b <= self.cap, b >= -self.cap] #[b >= 0, np.ones(num_available).T*b == 1] objective = Maximize(d-l*e) prob = Problem(objective, constraints) prob.solve() new_allocation = np.zeros(len(available)) new_allocation[available_inds] = b.value return new_allocation
def get_new_allocation(self, day, init=False): """ Determine the new desired allocation for the end of |day| using the OLMAR algorithm. :param day: :param init: If True, this portfolio is being initialized today. :return: """ "" if init and self.data_train is None: # Use uniform allocation cur_day_op = self.data.get_op(relative=False)[day, :] # opening prices on |cur_day| return util.get_uniform_allocation(self.num_stocks, cur_day_op) predicted_price_rel = self.predict_price_relatives(day) # Compute mean price relative of available stocks (x bar at t+1) today_op = self.data.get_op(relative=False)[day, :] avail_stocks = util.get_avail_stocks(today_op) avail_idxs = util.get_available_inds(avail_stocks) ppr_avail = predicted_price_rel[avail_idxs] # predicted price relatives of available stocks mean_price_rel = np.mean(ppr_avail) lam = self.compute_lambda(ppr_avail, mean_price_rel, avail_idxs) # lambda at t+1 # limit lambda to avoid numerical problems from acting too aggressively. # (referenced from marigold's implementation: https://github.com/Marigold/universal-portfolios) lam = min(100000, lam) # Note: we don't perform simplex project b/c negative values (shorting) is allowed. new_b = np.zeros(self.num_stocks) for i, _ in enumerate(new_b): ppr = predicted_price_rel[i] if ppr > 0: new_b[i] = self.b[i] + lam * (ppr - mean_price_rel) # Normalize b so that it sums to 1 sum_b = np.linalg.norm(new_b, ord=1) return (1.0 / sum_b) * new_b
def get_new_allocation(self, cur_day): """ :param cur_day: :return: A (1 x num_stocks) array of fractions. Each fraction represents the amount of the money should be invested in that stock at the end of the day. If we haven't reached the start date (the day when we have confidence in our mean/covariance info), return a uniform portfolio. Otherwise, perform nonparametric markowitz. """ if cur_day == 0: cur_day_op = self.data.get_op( relative=False)[cur_day, :] # opening prices on |cur_day| return util.get_uniform_allocation(self.num_stocks, cur_day_op) elif (cur_day < self.start_date): available = util.get_avail_stocks(self.data.get_op()[cur_day, :]) num_available = np.sum(available) new_allocation = 1.0 / num_available * np.asarray(available) else: k = self.k available = util.get_avail_stocks( self.data.get_op()[cur_day - self.window_len + 1, :]) available_inds = util.get_available_inds(available) history = self.get_market_window(self.window_len, cur_day) num_available = history.shape[0] neighbors = np.zeros((num_available, k)) history_norms = np.diag(np.dot(history, history.T)) # Compute k nearest neighbors for each stock for i in range(num_available): stock = history[i, :] neighbors[i, :] = util.k_nearest_neighbors( stock, history, k, history_norms) # Solve optimization problem l = self.risk_aversion neighbors = neighbors.astype(int) b = Variable(num_available) c = Variable(num_available) d = 0 e = 0 for i in range(num_available): inds = available_inds[neighbors[i, :]] m_i = self.mu[inds] #self.mu[inds] S_i = self.sigma[inds, :] S_i = S_i[:, inds] d += (b[i] * m_i).T * np.ones(k) e += quad_form(b[i] * np.ones(k), S_i) constraints = [ c >= b, c >= -b, sum_entries(c) == 1 ] #, b <= self.cap, b >= -self.cap] #[b >= 0, np.ones(num_available).T*b == 1] objective = Maximize(d - l * e) prob = Problem(objective, constraints) prob.solve() new_allocation = np.zeros(len(available)) new_allocation[available_inds] = b.value return new_allocation
def get_new_allocation(self, cur_day, init=False): cur_day_op = self.data.get_op(relative=False)[cur_day, :] # opening prices on |cur_day| new_b = util.get_uniform_allocation(self.num_stocks, cur_day_op) return new_b
def get_new_allocation(self, cur_day): if cur_day == 0: cur_day_op = self.data.get_op(relative=False)[cur_day, :] # opening prices on |cur_day| return get_uniform_allocation(self.num_stocks, cur_day_op) else: return self.b