Beispiel #1
0
 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)
Beispiel #2
0
 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
Beispiel #6
0
 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
Beispiel #7
0
 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