Skip to content

Commit

Permalink
Merge pull request econ-ark#891 from sbenthall/i637
Browse files Browse the repository at this point in the history
adds constructor for LogNormal distribution using mean and std
  • Loading branch information
sbenthall authored Dec 22, 2020
2 parents 498e6af + 587be28 commit 435937c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 13 deletions.
3 changes: 3 additions & 0 deletions Documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ Release Data: TBD

#### Major Changes

* Adds a constructor for LogNormal distributions from mean and standard deviation (#891)[https://github.com/econ-ark/HARK/pull/891/]
* Uses new LogNormal constructor in ConsPortfolioModel (#891)[https://github.com/econ-ark/HARK/pull/891/]
* calcExpectations method for taking the expectation of a distribution over a function (#884)[https://github.com/econ-ark/HARK/pull/884/]


#### Minor Changes

* Remove uses of deprecated time.clock [#887](https://github.com/econ-ark/HARK/pull/887)
Expand Down
23 changes: 11 additions & 12 deletions HARK/ConsumptionSaving/ConsPortfolioModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,24 +241,23 @@ def updateRiskyDstn(self):
# Generate a discrete approximation to the risky return distribution if the
# agent has age-varying beliefs about the risky asset
if "RiskyAvg" in self.time_vary:
RiskyDstn = []
self.RiskyDstn = []
for t in range(self.T_cycle):
RiskyAvgSqrd = self.RiskyAvg[t] ** 2
RiskyVar = self.RiskyStd[t] ** 2
mu = np.log(self.RiskyAvg[t] / (np.sqrt(1.0 + RiskyVar / RiskyAvgSqrd)))
sigma = np.sqrt(np.log(1.0 + RiskyVar / RiskyAvgSqrd))
RiskyDstn.append(Lognormal(mu=mu, sigma=sigma).approx(self.RiskyCount))
self.RiskyDstn = RiskyDstn
self.RiskyDstn.append(
Lognormal.from_mean_std(
self.RiskyAvg[t],
self.RiskyStd[t]
).approx(self.RiskyCount)
)
self.addToTimeVary("RiskyDstn")

# Generate a discrete approximation to the risky return distribution if the
# agent does *not* have age-varying beliefs about the risky asset (base case)
else:
RiskyAvgSqrd = self.RiskyAvg ** 2
RiskyVar = self.RiskyStd ** 2
mu = np.log(self.RiskyAvg / (np.sqrt(1.0 + RiskyVar / RiskyAvgSqrd)))
sigma = np.sqrt(np.log(1.0 + RiskyVar / RiskyAvgSqrd))
self.RiskyDstn = Lognormal(mu=mu, sigma=sigma).approx(self.RiskyCount)
self.RiskyDstn = Lognormal.from_mean_std(
self.RiskyAvg,
self.RiskyStd,
).approx(self.RiskyCount)
self.addToTimeInv("RiskyDstn")

def updateShockDstn(self):
Expand Down
34 changes: 33 additions & 1 deletion HARK/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,39 @@ def approx(self, N, tail_N=0, tail_bound=None, tail_order=np.e):
pmf, X, seed=self.RNG.randint(0, 2 ** 31 - 1, dtype="int32")
)

@classmethod
def from_mean_std(cls, mean, std, seed = 0):
"""
Construct a LogNormal distribution from its
mean and standard deviation.
This is unlike the normal constructor for the distribution,
which takes the mu and sigma for the normal distribution
that is the logarithm of the Log Normal distribution.
Parameters
----------
mean : float or [float]
One or more means. Number of elements T in mu determines number
of rows of output.
std : float or [float]
One or more standard deviations. Number of elements T in sigma
determines number of rows of output.
seed : int
Seed for random number generator.
Returns
---------
LogNormal
"""
mean_squared = mean ** 2
variance = std ** 2
mu = np.log(mean / (np.sqrt(1.0 + variance / mean_squared)))
sigma = np.sqrt(np.log(1.0 + variance / mean_squared))

return cls(mu = mu, sigma = sigma, seed = seed)


class MeanOneLogNormal(Lognormal):
def __init__(self, sigma=1.0, seed=0):
Expand Down Expand Up @@ -440,7 +473,6 @@ def approx(self, N):
pmf, X, seed=self.RNG.randint(0, 2 ** 31 - 1, dtype="int32")
)


### DISCRETE DISTRIBUTIONS


Expand Down

0 comments on commit 435937c

Please sign in to comment.