Пример #1
0
    def mom_symbol(self, moments):
        """ Symbolic solver for ordinary method of moments
        find k-point representative distribution

        Args:
        moments: a sequence of estimated moments, starting from degree 1
            only use first 2k-1 moments
        num_comps: number of atoms in the output RV

        Returns:
        U(finiteRV): estimated RV, whose first 2k-1 moments equal m

        """

        num = 2 * self.k - 1
        assert len(moments) >= num

        p_var = sympy.symbols('p0:%d' % (self.k), nonnegative=True, real=True)
        x_var = sympy.symbols('x0:%d' % (self.k), real=True)

        eqn = -1
        for i in range(self.k):
            eqn = eqn + p_var[i]
        equations = [eqn]

        for i in range(num):
            eqn = -moments[i]
            ########### truncate a real number to rational
            # eq = -nsimplify(m[i], tolerance=0.1)
            # eq = float('%.2g' % -m[i])
            for j in range(self.k):
                eqn = eqn + p_var[j] * (x_var[j]**(i + 1))
            equations.append(eqn)

        var = [x for xs in zip(p_var, x_var)
               for x in xs]  # format: [p1,x1,p2,x2,...]
        s_var = sympy.solve(equations, var)
        # s = solveset(equations,list(p)+list(x))
        # s = nonlinsolve(equations,list(p)+list(x))

        ########## some other tools in SymPy
        # print(equations)
        # s = solve_poly_system(equations,list(p)+list(x))
        # s = solve_triangulated(equations,list(p)+list(x))
        # s = solve_triangulated(equations,p[0],p[1],x[0],x[1])

        ########## test over simple rational coefficients
        # testEq = [x[0]*p[0] - 2*p[0], 2*p[0]**2 - x[0]**2]
        # s = solve_triangulated(testEq, x[0], p[0])

        if len(s_var) == 0:
            return DiscreteRV(w=[], x=[])
        else:
            return DiscreteRV(w=s_var[0][0::2], x=s_var[0][1::2])
Пример #2
0
    def mom_numeric(self, moments, start):
        """ numerical solver for ordinary method of moments
        find k-point representative distribution

        Args:
        moments: a sequence of estimated moments, starting from degree 1
            only use first 2k-1 moments
        start: initial guess. k = the number of components in start.

        Returns:
        U(finiteRV): estimated RV

        """
        k = len(start.p)
        assert k == self.k

        num = 2 * k - 1
        assert len(moments) >= num
        moments = moments[0:num]

        def equation(x_var):
            """
            local moments condition equation
            """
            model = DiscreteRV(x=x_var[0:k],
                               w=np.append(x_var[k:], 1 - np.sum(x_var[k:])))
            return model.moment(num) - moments

        x0_var = np.concatenate((start.x, start.p[0:-1]))
        x_var = scipy.optimize.fsolve(equation, x0_var)
        # x = scipy.optimize.broyden2(equation, x0)

        return DiscreteRV(x=x_var[0:k],
                          w=np.append(x_var[k:], 1 - np.sum(x_var[k:])))
Пример #3
0
 def equation(x_var):
     """
     local moments condition equation
     """
     model = DiscreteRV(x=x_var[0:k],
                        w=np.append(x_var[k:], 1 - np.sum(x_var[k:])))
     return model.moment(num) - moments
Пример #4
0
def mc_sample_path(P, init=0, sample_size=1000):
    # === set up array to store output === #
    X = np.empty(sample_size, dtype=int)
    if isinstance(init, int):
        X[0] = init
    else:
        X[0] = DiscreteRV(init).draw()

    # === turn each row into a distribution === #
    # In particular, let P_dist[i] be the distribution corresponding to the
    # i-th row P[i,:]
    n = len(P)
    P_dist = [DiscreteRV(P[i, :]) for i in range(n)]

    # === generate the sample path === #
    for t in range(sample_size - 1):
        X[t+1] = P_dist[X[t]].draw()

    return X
Пример #5
0
def quadmom(moments, dettol=0, inf=1e10):
    """ compute quadrature from moments
    ref: Gene Golub, John Welsch, Calculation of Gaussian Quadrature Rules

    Args:
    m: moments sequence
    dettol: tolerant of singularity of moments sequence (quantified by determinant of moment matrix)
    INF: infinity

    Returns:
    U: quadrature
    """

    moments = np.asarray(moments)
    # INF = float('inf')
    inf = 1e10

    if len(moments) % 2 == 1:
        moments = np.append(moments, inf)
    num = int(len(moments) / 2)
    moments = np.insert(moments, 0, 1)

    h_mat = hankel(moments[:num + 1:], moments[num::])  # Hankel matrix
    for i in range(len(h_mat)):
        # check positive definite and decide to use how many moments
        if np.linalg.det(
                h_mat[0:i + 1, 0:i +
                      1]) <= dettol:  # alternative: less than some threshold
            h_mat = h_mat[0:i + 1, 0:i + 1]
            h_mat[i, i] = inf
            num = i
            break
    r_mat = np.transpose(
        np.linalg.cholesky(h_mat))  # upper triangular Cholesky factor

    # Compute alpha and beta from r, using Golub and Welsch's formula.
    alpha = np.zeros(num)
    alpha[0] = r_mat[0][1] / r_mat[0][0]
    for i in range(1, num):
        alpha[i] = r_mat[i][i + 1] / r_mat[i][i] - r_mat[i - 1][i] / r_mat[
            i - 1][i - 1]

    beta = np.zeros(num - 1)
    for i in range(num - 1):
        beta[i] = r_mat[i + 1][i + 1] / r_mat[i][i]

    jacobi = np.diag(alpha, 0) + np.diag(beta, 1) + np.diag(beta, -1)

    eigval, eigvec = np.linalg.eig(jacobi)

    atoms = eigval
    weights = moments[0] * np.power(eigvec[0], 2)

    return DiscreteRV(w=weights, x=atoms)
Пример #6
0
def mc_sample_path(P, init=0, sample_size=1000): 
    """
    Generates one sample path from a finite Markov chain with (n x n) Markov
    matrix P on state space S = {0,...,n-1}. 

    Parameters 
    ==========
        P : A nonnegative 2D NumPy array with rows that sum to 1

        init : Either an integer in S or a nonnegative array of length n
                with elements that sum to 1

        sample_size : int

    If init is an integer, the integer is treated as the determinstic initial
    condition.  If init is a distribution on S, then X_0 is drawn from this
    distribution.

    Returns
    ========
        A NumPy array containing the sample path

    """
    # === set up array to store output === #
    X = np.empty(sample_size, dtype=int)
    if isinstance(init, int):
        X[0] = init
    else:
        X[0] = DiscreteRV(init).draw()

    # === turn each row into a distribution === #
    # In particular, let P_dist[i] be the distribution corresponding to the
    # i-th row P[i,:]
    n = len(P)
    P_dist = [DiscreteRV(P[i,:]) for i in range(n)]

    # === generate the sample path === #
    for t in range(sample_size - 1):
        X[t+1] = P_dist[X[t]].draw()
    return X
Пример #7
0
 def std_rv(self):
     """
     discrete rv for the sigmas
     """
     return DiscreteRV(self.weights, self.sigma)
Пример #8
0
 def mean_rv(self):
     """
     discrete rv for the means
     """
     return DiscreteRV(self.weights, self.centers)
    def __init__(self,
                 agents,
                 D,
                 D_probs,
                 aggregate_asset_endowment=1.0,
                 seed=None,
                 lucas_tree=False):
        '''
        Market simply consists of collection of agents.

        lucas_tree: True means agents get same allocation of xi0 every morning
        '''

        self.seed = seed
        self.RNG = np.random.RandomState(self.seed)
        self.lucas_tree = lucas_tree
        self.agents = agents
        self.price_history = []
        self.volume_history = []
        self.payoff_history = []

        self.bilateral_price_history = []
        self.bilateral_volume_history = []
        self.bilateral_trade_partner_history = []

        self.total_agent_cash_wealth_history = []
        self.total_agent_initial_asset_endowment = []
        #self.total_agent_asset_volume = []

        self.aggregate_asset_endowment = aggregate_asset_endowment

        # Set up storage for agent values:
        self.agents_history = []  # Store agent variables here.
        for i in range(len(self.agents)):
            temp_storage = {'y': [], 'c': [], 'xi': []}
            self.agents_history.append(temp_storage)

        # To find reasonable "first guess" price, find the risk-neutral asset
        # asset price for first-agent's preferences:
        agent0 = self.agents[0]
        self.p0_guess = agent0.beta * np.dot(agent0.D, agent0.D_probs)
        if self.p0_guess <= 0.0:
            self.p0_guess = 1e-5
        self.p_tm1 = self.p0_guess

        # Set up the dividend process:
        # Ensure that dividend payoffs are sorted from smallest to largest:
        self.D = np.array(D)
        self.D_probs = np.array(D_probs)
        ii = np.argsort(self.D)
        self.D = self.D[ii]
        self.D_probs = self.D_probs[ii]

        # Quick check:
        assert np.isclose(
            np.sum(D_probs), 1.0
        ), "Problem: p_dividend does not sum to 1.0: np.sum(D_probs) = " + str(
            np.sum(D_probs))

        D_seed = self.RNG.randint(low=0, high=(2**31) - 1)
        self.D_process = DiscreteRV(self.D_probs, self.D, seed=D_seed)