<jupyter_start><jupyter_text>True returns<jupyter_code>import statsmodels.formula.api as smf
from scipy.stats import lognorm
from scipy.stats import norm
import pandas as pd
import numpy as np

pd.options.display.float_format = '${:,.2f}'.format<jupyter_output><empty_output><jupyter_text>Solution We can solve the model by backward induction.<jupyter_code>def conditional_expectation(eval_point, s):
    """This function calculates the conditional expectation for realizations larger than the
    point of evaluation."""
    rslt = 1
    rslt *= np.exp(s ** 2 / 2)
    rslt *= norm.cdf((s ** 2 - np.log(eval_point)) / s)
    rslt /= 1 - norm.cdf(np.log(eval_point) / s)
    return rslt

# We initialize containers for our objects of interest-
Y = np.tile(np.nan, 5)
V = np.tile(np.nan, 5)
p = np.tile(np.nan, 4)

r, s = 0.1, 0.1

# We study earnings that are log linear in schooling.
Y[0] = 1
for i in range(1, 5):
    Y[i] = Y[i - 1] * (1 + r)


# This is the adjustment to the expected earnings as the expectation of the random shock is not one.
shift = np.exp(s ** 2 / 2)

# Value of choosing five years of schooling from the perspective of four years.
V[4] = Y[4] * shift

# Value of choosing four years of schooling from the perspective of three years.
eval_point = V[4]/ ((1 + r) * Y[3])
p[3] = lognorm.cdf(eval_point, s)

V[3] = 0
V[3] += (1 - p[3]) * Y[3] * conditional_expectation(eval_point, s) 
V[3] += p[3] * (V[4] / (1 + r))

# Value of choosing three years of schooling from teh perspective of two
eval_point = V[3] / ((1 + r) * Y[2]) 
p[2] = lognorm.cdf(eval_point, s)

V[2] = 0
V[2] += (1 - p[2]) * Y[2] * conditional_expectation(eval_point, s)
V[2] += p[2] * (V[3] / (1 + r))

# Value of choosing two years of schooling from the perspective of two
eval_point = V[2] / ((1 + r) * Y[1]) 
p[1] = lognorm.cdf(eval_point, s)

V[1] = 0
V[1] += (1 - p[1]) * Y[1] * conditional_expectation(eval_point, s)
V[1] += p[1] * (V[2] / (1 + r))

# Value of choosing one year of schooling from teh perspective of zero
eval_point = V[1] / ((1 + r) * Y[0]) 
p[0] = lognorm.cdf(eval_point, s)

V[0] = 0
V[0] += (1 - p[0]) * Y[0] * conditional_expectation(eval_point, s) 
V[0] += p[0] * (V[1] / (1 + r))<jupyter_output><empty_output><jupyter_text>Just to be sure, we check that we reproduce the transition probabilites from Table 6a.<jupyter_code>print('\nTransition probabilities\n')
for s in range(4):
    label = s + 2
    print('s = {}, {:,.2f}'.format(*[label, p[s]]))<jupyter_output>Transition probabilities

s = 2, 0.80
s = 3, 0.75
s = 4, 0.67
s = 5, 0.52
{'fraction_non_alphanumeric': 0.16060961313012895, 'fraction_numerical': 0.038686987104337635, 'mean_word_length': 3.7761194029850746, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '15190', 'license': 'MIT', 'n_tokens_mistral': 1062, 'n_tokens_neox': 1007, 'n_words': 315, 'path': 'lectures/02-returns-schooling/material/jnb-model-true.ipynb', 'repo_name': 'MargaritaRad/labor-economics', 'size': '2559'}