class PortfolioConsumerFrameType(FrameAgentType, PortfolioConsumerType):
    """
    A consumer type with a portfolio choice, using Frame architecture.

    A subclass of PortfolioConsumerType for now.
    This is mainly to keep the _solver_ logic intact.
    """
    def __init__(self, **kwds):
        params = init_portfolio.copy()
        params.update(kwds)
        kwds = params

        # Initialize a basic consumer type
        PortfolioConsumerType.__init__(self, **kwds)
        # Initialize a basic consumer type
        FrameAgentType.__init__(self, self.model, **kwds)

        self.shocks = {}
        self.controls = {}
        self.state_now = {}

    def solve(self):
        # Some contortions are needed here to make decision rule shaped objects
        # out of the HARK solution objects

        super().solve(self)

        ## TODO: make this a property of FrameAgentTypes or FrameModels?
        self.decision_rules = {}

        def decision_rule_Share_from_solution(solution_t):
            def decision_rule_Share(Adjust, mNrm, Share):
                Share = np.zeros(len(Adjust)) + np.nan

                Share[Adjust] = solution_t.ShareFuncAdj(mNrm[Adjust])

                Share[~Adjust] = solution_t.ShareFuncFxd(
                    mNrm[~Adjust], Share[~Adjust])

                return Share

            return decision_rule_Share

        def decision_rule_cNrm_from_solution(solution_t):
            def decision_rule_cNrm(Adjust, mNrm, Share):
                cNrm = np.zeros(len(Adjust)) + np.nan

                cNrm[Adjust] = solution_t.cFuncAdj(mNrm[Adjust])

                cNrm[~Adjust] = solution_t.cFuncFxd(mNrm[~Adjust],
                                                    Share[~Adjust])

                return cNrm

            return decision_rule_cNrm

        self.decision_rules[('Share', )] = [
            decision_rule_Share_from_solution(sol) for sol in self.solution
        ]
        self.decision_rules[('cNrm', )] = [
            decision_rule_cNrm_from_solution(sol) for sol in self.solution
        ]

    # TODO: streamline this so it can draw the parameters from context
    def birth_aNrmNow(self, N):
        """
        Birth value for aNrmNow
        """
        return Lognormal(
            mu=self.aNrmInitMean,
            sigma=self.aNrmInitStd,
            seed=self.RNG.randint(0, 2**31 - 1),
        ).draw(N)

    # TODO: streamline this so it can draw the parameters from context
    def birth_pLvlNow(self, N):
        """
        Birth value for pLvlNow
        """
        pLvlInitMeanNow = self.pLvlInitMean + np.log(
            self.state_now["PlvlAgg"]
        )  # Account for newer cohorts having higher permanent income

        return Lognormal(pLvlInitMeanNow,
                         self.pLvlInitStd,
                         seed=self.RNG.randint(0, 2**31 - 1)).draw(N)

    # maybe replace reference to init_portfolio to self.parameters?
    model = FrameModel(
        [
            # todo : make an aggegrate value
            Frame(('PermShkAgg', ), ('PermGroFacAgg', ),
                  transition=lambda PermGroFacAgg: (PermGroFacAgg, ),
                  aggregate=True),
            Frame(
                ('PermShk'),
                None,
                default={
                    'PermShk': 1.0
                },  # maybe this is unnecessary because the shock gets sampled at t = 0
                # this is discretized before it's sampled
                transition=IndexDistribution(
                    Lognormal.from_mean_std, {
                        'mean': init_portfolio['PermGroFac'],
                        'std': init_portfolio['PermShkStd']
                    }).approx(init_portfolio['PermShkCount'], tail_N=0),
            ),
            Frame(
                ('TranShk'),
                None,
                default={
                    'TranShk': 1.0
                },  # maybe this is unnecessary because the shock gets sampled at t = 0
                transition=add_discrete_outcome_constant_mean(
                    IndexDistribution(MeanOneLogNormal, {
                        'sigma': init_portfolio['TranShkStd']
                    }).approx(init_portfolio['TranShkCount'], tail_N=0),
                    p=init_portfolio['UnempPrb'],
                    x=init_portfolio['IncUnemp'])),
            Frame(  ## TODO: Handle Risky as an Aggregate value
                ('Risky'),
                None,
                transition=IndexDistribution(
                    Lognormal.from_mean_std, {
                        'mean': init_portfolio['RiskyAvg'],
                        'std': init_portfolio['RiskyStd']
                    }
                    # seed=self.RNG.randint(0, 2 ** 31 - 1) : TODO: Seed logic
                ).approx(init_portfolio['RiskyCount']),
                aggregate=True),
            Frame(
                ('Adjust'),
                None,
                default={'Adjust': False},
                transition=IndexDistribution(
                    Bernoulli,
                    {'p': init_portfolio['AdjustPrb']},
                    # seed=self.RNG.randint(0, 2 ** 31 - 1) : TODO: Seed logic
                )  # self.t_cycle input implied
            ),
            Frame(('Rport'), ('Share', 'Risky', 'Rfree'),
                  transition=lambda Share, Risky, Rfree:
                  (Share * Risky + (1.0 - Share) * Rfree, )),
            Frame(('PlvlAgg'), ('PlvlAgg', 'PermShkAgg'),
                  default={'PlvlAgg': 1.0},
                  transition=lambda PlvlAgg, PermShkAgg: PlvlAgg * PermShkAgg,
                  aggregate=True),
            Frame(('pLvl', ), ('pLvl', 'PermShk'),
                  default={'pLvl': birth_pLvlNow},
                  transition=lambda pLvl, PermShk: (pLvl * PermShk, )),
            Frame(('bNrm', ), ('aNrm', 'Rport', 'PermShk'),
                  transition=lambda aNrm, Rport, PermShk:
                  (Rport / PermShk) * aNrm),
            Frame(('mNrm', ), ('bNrm', 'TranShk'),
                  transition=lambda bNrm, TranShk: (bNrm + TranShk, )),
            Frame(('Share'), ('Adjust', 'mNrm', 'Share'),
                  default={'Share': 0},
                  control=True),
            Frame(('cNrm'), ('Adjust', 'mNrm', 'Share'), control=True),
            Frame(
                ('U'),
                ('cNrm',
                 'CRRA'),  ## Note CRRA here is a parameter not a state var
                transition=lambda cNrm, CRRA: (CRRAutility(cNrm, CRRA), ),
                reward=True),
            Frame(('aNrm'), ('mNrm', 'cNrm'),
                  default={'aNrm': birth_aNrmNow},
                  transition=lambda mNrm, cNrm: (mNrm - cNrm, )),
            Frame(('aLvl'), ('aNrm', 'pLvl'),
                  transition=lambda aNrm, pLvl: (aNrm * pLvl, ))
        ],
        init_portfolio)
Esempio n. 2
0
aGrid = np.linspace(0,8,400) # Savings grid for EGM.

# Model parameters

# Parameters that need to be fixed
# Relative risk aversion. This is fixed at 2 in order to mantain
# the analytical solution that we use, from Carroll (2000)
CRRA   = 2 

# Parameters that can be changed.
w          = 1    # Deterministic wage per period.
willCstFac = 0.35 # Fraction of resources charged by lawyer for writing a will.
DiscFac    = 0.98 # Time-discount factor.

# Define utility (and related) functions
u     = lambda x: CRRAutility(x,CRRA)
uP    = lambda x: CRRAutilityP(x, CRRA)
uPinv = lambda x: CRRAutilityP_inv(x, CRRA)

# Create a grid for market resources
mGrid       = (aGrid-aGrid[0])*1.5
mGridPlots  = np.linspace(w,10*w,100)
mGridPlotsC = np.insert(mGridPlots,0,0)

# Transformations for value funtion interpolation
vTransf   = lambda x: np.exp(x)
vUntransf = lambda x: np.log(x)

# %% [markdown]
# # The third (last) period of life
#
Esempio n. 3
0
init_parameters['PermShkCount'] = 5
init_parameters['TranShkStd'] = 3.0
init_parameters['TranShkCount'] = 5
init_parameters['RiskyAvg'] = 1.05
init_parameters['RiskyStd'] = 1.5
init_parameters['RiskyCount'] = 5
init_parameters['Rfree'] = 1.03

frames_A = [
    Frame(('bNrm', ), ('aNrm', ), transition=lambda Rfree, aNrm: Rfree * aNrm),
    Frame(('mNrm', ), ('bNrm', 'TranShk'), transition=lambda bNrm: mNrm),
    Frame(('cNrm'), ('mNrm', ), control=True),
    Frame(
        ('U'),
        ('cNrm', 'CRRA'),  ## Note CRRA here is a parameter not a state var
        transition=lambda cNrm, CRRA: (CRRAutility(cNrm, CRRA), ),
        reward=True,
        context={'CRRA': 2.0}),
    Frame(('aNrm'), ('mNrm', 'cNrm'),
          transition=lambda mNrm, cNrm: (mNrm - cNrm, )),
]


class test_FrameModel(unittest.TestCase):
    def setUp(self):
        self.model = FrameModel(frames_A, init_parameters)

    def test_init(self):

        self.model.frames.var('aNrm')