Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

standalone model configuration file with model, approximation, solution, and simulation parameters #1463

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Release Date: TBD
- Changes the behavior of make_lognormal_RiskyDstn so that the standard deviation represents the standard deviation of log(returns)
- Adds detailed parameter and latex documentation to most models.
- Add PermGroFac constructor that explicitly combines idiosyncratic and aggregate sources of growth. [1489](https://github.com/econ-ark/HARK/pull/1489)
- Adds an example, ModelConfiguration, which demonstrates how a consumption saving "true" model, approximations, solution paramaters, and simulation parameters can be defined in one YAML file. [1463](https://github.com/econ-ark/HARK/pull/1463)

### 0.15.1

Expand Down
8 changes: 2 additions & 6 deletions HARK/models/fisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@

from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
CRRA = (2.0,)

calibration = {
"DiscFac": 0.96,
"CRRA": CRRA,
"CRRA": (2.0,),
"Rfree": 1.03,
"y": [1.0, 1.0],
"BoroCnstArt": None,
Expand All @@ -25,6 +21,6 @@
"c": Control(["m"]),
"a": lambda m, c: m - c,
},
"reward": {"u": lambda c: c ** (1 - CRRA) / (1 - CRRA)},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
}
)
9 changes: 2 additions & 7 deletions HARK/models/perfect_foresight.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
from HARK.distribution import Bernoulli
from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
LivPrb = 0.98

calibration = {
"DiscFac": 0.96,
"CRRA": 2.0,
"Rfree": 1.03,
"LivPrb": LivPrb,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
}
Expand All @@ -19,7 +14,7 @@
**{
"name": "consumption",
"shocks": {
"live": Bernoulli(p=LivPrb),
"live": Bernoulli(p=calibration["LivPrb"]),
},
"dynamics": {
"y": lambda p: p,
Expand Down
14 changes: 4 additions & 10 deletions HARK/models/perfect_foresight_normalized.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
from HARK.distribution import Bernoulli
from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
CRRA = (2.0,)
LivPrb = 0.98

calibration = {
"DiscFac": 0.96,
"CRRA": CRRA,
"CRRA": (2.0,),
"Rfree": 1.03,
"LivPrb": LivPrb,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
}

block = DBlock(
**{
"shocks": {
"live": Bernoulli(p=LivPrb),
"live": Bernoulli(p=calibration["LivPrb"]),
},
"dynamics": {
"p": lambda PermGroFac, p: PermGroFac * p,
Expand All @@ -29,6 +23,6 @@
"c_nrm": Control(["m_nrm"]),
"a_nrm": lambda m_nrm, c_nrm: m_nrm - c_nrm,
},
"reward": {"u": lambda c: c ** (1 - CRRA) / (1 - CRRA)},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
}
)
84 changes: 84 additions & 0 deletions examples/ModelConfiguration/consumer_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from HARK.distribution import Bernoulli, Lognormal, MeanOneLogNormal
from HARK.model import Control

"""
This is an example of what a full configuration looks like for:

(a) a true model

(b) approximations made to it to enable efficient computation

(c) additional parameters needed to solve and simulate the model.

This file shows the model configuraiton in Python.

Another file will show a model configuration in YAML, which gets parsed into
a data structure much like this one.
"""

model_config = {
"agents": {"consumer": {"count": 10}},
"calibration": {
"DiscFac": 0.96,
"CRRA": 2.0,
"R": 1.03, # note: this can be overriden by the portfolio dynamics
"Rfree": 1.03,
"EqP": 0.02,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
"TranShkStd": 0.1,
},
"blocks": [
{
"name": "consumption normalized",
"shocks": {
"live": [Bernoulli, {"p": "LivPrb"}],
"theta": [MeanOneLogNormal, {"sigma": "TranShkStd"}],
},
"dynamics": {
"b": lambda k, R, PermGroFac: k * R / PermGroFac,
"m": lambda b, theta: b + theta,
"c": Control(["m"]),
"a": lambda m, c: m - c,
},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
},
{
"name": "portfolio",
"shocks": {
"risky_return": [
Lognormal.from_mean_std,
{"mean": "Rfree + EqP", "std": 0.1},
]
},
"dynamics": {
"stigma": Control(["a"]),
"R": lambda stigma, Rfree, risky_return: Rfree
+ (risky_return - Rfree) * stigma,
},
},
{
"name": "tick",
"dynamics": {
"k": lambda a: a,
},
},
],
"approximation": {
"theta": {"N": 5},
"risky_return": {"N": 5},
},
# "workflows": [
# {"action": "solve", "algorithm": "vbi"},
# {
# "action": "simulate",
# "initialization": { # initial values # type: ignore
# "k": Lognormal(-6, 0),
# "R": 1.03,
# },
# "population": 10, # ten agents
# "T": 20, # total number of simulated periods
# },
# ],
}
90 changes: 90 additions & 0 deletions examples/ModelConfiguration/consumer_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
model: &consumer_portfolio
agents:
consumer:
count: 100 # a model with 100 consumers

calibration:
# - DiscFac: 0.96 put this in the solution section
- CRRA: 2.0
- R: 1.03 # note: this can be overriden by the portfolio dynamics
- Rfree: 1.03
- EqP: 0.02
- PermGroFac: 1.01
- TranShkStd: 0.1

blocks:
- &cons # block definition begins with name of the block. Alias
name: consumption_normalized
agent: consumer
shocks:
theta: !MeanOneLogNormal
sigma: TranShkStd

dynamics:
b: k * R / PermGroFac
m: b + theta,
c: !Control
inset: m
constraints:
- c < m
a: m - c
reward:
u: c ** (1 - CRRA) / (1 - CRRA)}

- &port
name: portfolio
agent: consumer
shocks:
risky_return: !Lognormal
mean: Rfree + EqP
std: 0.1

dynamics:
stigma: Control(["a"]),
R: Rfree + (risky_return - Rfree) * stigma

structure: # the sequence of blocks
- *cons
- *port
- twist: # shorthand fo renaming a variable
m: k
- tick # pass discrete time step
# defaults to infinite horizion problem

approximation: &approx # right syntax?
theta: # to discretize a continuous probability distribution
N : 5
method: equiprobable
risky_return:
N: 5
method: gauss-hermite
m: !Linspace # grid over continuous state space
start: 0
stop: 10
num: 25


strategy: # these configure constructors/solvers of decision rules
# for model control variables
- &test_policy_profile
model: *consumer_portfolio
method: hard_rule
rules:
- c : m / 2
- stigma : a / (5 + a)

- &approx_best_policy_profile
model: *consumer_portfolio
method: policy_iteration
approximation: *approx
discount: 0.98 # A discount factor applied at each tick

simulation: !MonteCarlo
initialization:
k: !Lognormal
mean: 1
sigma: 0
R: 1.03
approximation: *approx # use the same shock discretization
policy_profile: *approx_best_policy_profile
periods: 100