111111** Restriction 2** (Positivity):
112112
113113$$
114- m > 0.
114+ m \geq 0.
115115$$
116116
117117Restriction 1 must hold in any model consistent with consumer optimality.
118118
119- Restriction 2 rules out arbitrage opportunities: {doc}` hansen_richard_1987 ` show that no-arbitrage implies $m > 0$ with probability one.
119+ Restriction 2 rules out arbitrage opportunities: {doc}` hansen_richard_1987 ` show that no-arbitrage implies $m > 0$ with probability one, so in particular $m \geq 0$ .
120120
121121Together, they imply that
122122$[ E(m), \sigma(m)] $ must lie in a certain admissible region in the
@@ -131,10 +131,10 @@ If the period utility function is $U(c) = c^{1+\gamma}/(1+\gamma)$ for
131131$\gamma < 0$, then
132132
133133$$
134- m = \delta \left(\frac{c_{t+1}}{c_t}\right)^{\gamma},
134+ m = \beta \left(\frac{c_{t+1}}{c_t}\right)^{\gamma},
135135$$
136136
137- where $\delta $ is a subjective discount factor and $-\gamma > 0$ is the
137+ where $\beta $ is a subjective discount factor and $-\gamma > 0$ is the
138138coefficient of relative risk aversion.
139139
140140Later we evaluate this model by computing $[ E(m), \sigma(m)] $ from consumption
@@ -480,7 +480,7 @@ def mean_variance_frontier(μ_x, Σ, n_points=300):
480480 c_min = B / C
481481 c_grid = np.linspace(c_min - 0.10, c_min + 0.15, n_points)
482482
483- var_c = (A * c_grid**2 - 2 * B * c_grid + C ) / D
483+ var_c = (C * c_grid**2 - 2 * B * c_grid + A ) / D
484484 std_c = np.sqrt(np.maximum(var_c, 0))
485485 return c_grid, std_c
486486
@@ -624,27 +624,27 @@ def load_quarterly_bill():
624624quarterly_bill_data = load_quarterly_bill().to_numpy()
625625μ_bill = quarterly_bill_data.mean(axis=0)
626626Σ_bill = np.cov(quarterly_bill_data.T, bias=True)
627- Σ_inv_bill = np.linalg.inv (Σ_bill)
627+ Σ_inv_bill = np.linalg.pinv (Σ_bill)
628628ones_bill = np.ones(len(μ_bill))
629629
630630A_bill = μ_bill @ Σ_inv_bill @ μ_bill
631631B_bill = μ_bill @ Σ_inv_bill @ ones_bill
632632C_bill = ones_bill @ Σ_inv_bill @ ones_bill
633633D_bill = A_bill * C_bill - B_bill**2
634634
635- # Frontier: σ^2 = (A *μ^2 - 2B*μ + C ) / D => μ = (B +/- sqrt(D*(A *σ^2 - 1))) / A
636- σ_min_bill = 1.0 / np.sqrt(A_bill )
635+ # Frontier: σ^2 = (C *μ^2 - 2B*μ + A ) / D => μ = (B +/- sqrt(D*(C *σ^2 - 1))) / C
636+ σ_min_bill = 1.0 / np.sqrt(C_bill )
637637σ_grid_bill = np.linspace(σ_min_bill * 1.001, 1.3, 1000)
638- disc_bill = D_bill * (A_bill * σ_grid_bill**2 - 1)
638+ disc_bill = D_bill * (C_bill * σ_grid_bill**2 - 1)
639639disc_bill = np.maximum(disc_bill, 0)
640- μ_upper_bill = (B_bill + np.sqrt(disc_bill)) / A_bill
641- μ_lower_bill = (B_bill - np.sqrt(disc_bill)) / A_bill
640+ μ_upper_bill = (B_bill + np.sqrt(disc_bill)) / C_bill
641+ μ_lower_bill = (B_bill - np.sqrt(disc_bill)) / C_bill
642642
643643# Minimum second-moment payoff r*
644- μ_star_bill = B_bill / (A_bill + D_bill)
644+ μ_star_bill = B_bill / (C_bill + D_bill)
645645σ_star_bill = np.sqrt(
646646 max(
647- (A_bill * μ_star_bill**2 - 2 * B_bill * μ_star_bill + C_bill ) / D_bill, 0)
647+ (C_bill * μ_star_bill**2 - 2 * B_bill * μ_star_bill + A_bill ) / D_bill, 0)
648648)
649649r_star_norm = np.sqrt(σ_star_bill**2 + μ_star_bill**2)
650650```
@@ -697,10 +697,10 @@ mystnb:
697697 name: fig-frontiers-r-rv
698698---
699699σ_zoom = np.linspace(σ_min_bill * 1.001, 0.04, 500)
700- disc_zoom = D_bill * (A_bill * σ_zoom**2 - 1)
700+ disc_zoom = D_bill * (C_bill * σ_zoom**2 - 1)
701701disc_zoom = np.maximum(disc_zoom, 0)
702- μ_up_zoom = (B_bill + np.sqrt(disc_zoom)) / A_bill
703- μ_lo_zoom = (B_bill - np.sqrt(disc_zoom)) / A_bill
702+ μ_up_zoom = (B_bill + np.sqrt(disc_zoom)) / C_bill
703+ μ_lo_zoom = (B_bill - np.sqrt(disc_zoom)) / C_bill
704704
705705σ_comb_zoom = np.concatenate([σ_zoom[::-1], σ_zoom])
706706μ_comb_zoom = np.concatenate([μ_lo_zoom[::-1], μ_up_zoom])
@@ -742,14 +742,16 @@ Hansen and Jagannathan show that the minimum variance **nonnegative** $m$
742742satisfying Restriction 1 is of the form
743743
744744$$
745- \tilde{m}^v = \left(x_a^\top \alpha^v\right)^+ = \max\!\left\{x_a^\top \alpha^v,\ 0\right\},
745+ \tilde{m}^v = \left(x_a^\top \tilde{\ alpha} ^v\right)^+ = \max\!\left\{x_a^\top \tilde{\ alpha} ^v,\ 0\right\},
746746$$
747747
748748which is the payoff on a ** European call (or put) option** on a portfolio of
749749the assets.
750750
751- The option truncates the negative part of $m^v$, reducing its variance while
752- preserving the pricing restrictions.
751+ Note that $\tilde{\alpha}^v$ is * not* the same coefficient vector as
752+ $\alpha^v$ from the unconstrained problem: the positivity constraint changes
753+ the optimal portfolio weights, and the positive part is then applied to the
754+ result.
753755
754756The positive bound $\sigma(\tilde{m}^v)$ satisfies:
755757
@@ -758,7 +760,7 @@ The positive bound $\sigma(\tilde{m}^v)$ satisfies:
758760- $S^+$ is ** convex** .
759761
760762Computing $\sigma(\tilde{m}^v)$ requires knowing the distribution of
761- $x_a^\top \alpha^v$, not just its first two moments.
763+ $x_a^\top \tilde{\ alpha} ^v$, not just its first two moments.
762764
763765For the figures below, we use the exact sample analogue of the truncation
764766problem and solve it numerically over a grid of candidate means.
@@ -909,17 +911,17 @@ The HJ bound provides a nonparametric restatement of the equity premium puzzle.
909911For the bound to be met, the IMRS of the representative agent must be far more
910912volatile than consumption growth alone can generate under standard preferences.
911913
912- For a CRRA consumer with risk aversion $\gamma$ ,
914+ For a CRRA consumer with risk aversion $- \gamma$ (recall $\gamma < 0$) ,
913915
914916$$
915- m = \delta \left(\frac{c_{t+1}}{c_t}\right)^{\gamma}.
917+ m = \beta \left(\frac{c_{t+1}}{c_t}\right)^{\gamma}.
916918$$
917919
918920If consumption growth is lognormal with mean $\mu_c$ and standard deviation
919921$\sigma_c$, then
920922
921923$$
922- E(m) = \delta \exp\!\left(\gamma \mu_c + \tfrac{1}{2} \gamma^2 \sigma_c^2\right),
924+ E(m) = \beta \exp\!\left(\gamma \mu_c + \tfrac{1}{2} \gamma^2 \sigma_c^2\right),
923925\quad
924926\frac{\sigma(m)}{E(m)} = \sqrt{\exp\!\left(\gamma^2 \sigma_c^2\right) - 1}
925927\approx |\gamma| \sigma_c.
@@ -942,9 +944,15 @@ The table below reports $E(m)$ and $\sigma(m)$ for selected values of $\gamma$
942944and indicates whether the implied IMRS lies inside the admissible region.
943945
944946``` {code-cell} ipython3
947+ # Use the positivity-restricted frontier for the bound
948+ valid_pos = np.isfinite(annual_pos_std)
949+ pos_order = np.argsort(annual_pos_mean[valid_pos])
950+ pos_mean_sorted = annual_pos_mean[valid_pos][pos_order]
951+ pos_std_sorted = annual_pos_std[valid_pos][pos_order]
952+
945953rows = []
946954for g, E_m, s_m in zip(annual_γ_grid, annual_crra_mean, annual_crra_std):
947- bound_val = float(np.interp(E_m, v_annual, σ_annual ))
955+ bound_val = float(np.interp(E_m, pos_mean_sorted, pos_std_sorted ))
948956 if g in {0, -1, -2, -5, -10, -15, -20, -25, -30}:
949957 rows.append({'γ': g, 'E(m)': round(E_m, 4),
950958 'σ(m)': round(s_m, 4),
@@ -972,8 +980,8 @@ The IMRS becomes more complex because it depends on current and future
972980marginal utilities:
973981
974982$$
975- m = \delta \frac{(s_{t+1})^\gamma + \theta \delta E[(s_{t+2})^\gamma \mid I_{t+1}]}
976- {(s_t)^\gamma + \theta \delta E[(s_{t+1})^\gamma \mid I_t]}.
983+ m = \beta \frac{(s_{t+1})^\gamma + \theta \beta E[(s_{t+2})^\gamma \mid I_{t+1}]}
984+ {(s_t)^\gamma + \theta \beta E[(s_{t+1})^\gamma \mid I_t]}.
977985$$
978986
979987The paper shows (Figure 5) that habit persistence ($\theta < 0$) dramatically
@@ -984,8 +992,7 @@ Local durability ($\theta > 0$) barely reduces it.
984992The paper's Figure 5 uses a consumption process estimated by Gallant and
985993Tauchen, which is not bundled with this lecture.
986994
987- Instead, we use monthly U.S. stock and bill returns as payoffs, augmented by
988- lagged instruments to tighten the bound.
995+ Instead, we use monthly U.S. stock and bill returns as the two base payoffs.
989996
990997We then simulate the nonseparable IMRS for three values of $\theta$ (0, 0.5,
991998$-0.5$) across a range of $\gamma < 0$ values, and plot the resulting
0 commit comments