Ejemplo n.º 1
0
def table_1(n_states=3, quadratic=False):
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states)
    g = log_Rw  # Set g to be log return on wealth

    result_min = solve(f,
                       g,
                       z0,
                       z1,
                       ξ=100.,
                       quadratic=quadratic,
                       tol=1e-9,
                       max_iter=1000)

    # Table 1: transition matrix and stationary probability
    print('Table 1: Empirical and distorted transition probabilities')
    print('-------------------------------------------------------')
    print('               empirical             min divergence')
    print('-------------------------------------------------------')
    print('Transition Matrix:')
    for state in np.arange(1, n_states + 1):
        print(
            f"           {np.round(result_min['P'][state-1],2)}         {np.round(result_min['P_tilde'][state-1],2)}"
        )
    print('')
    print('Stationary Probability:')
    print(
        f"           {np.round(result_min['π'],2)}         {np.round(result_min['π_tilde'],2)}"
    )
    print('-------------------------------------------------------')
Ejemplo n.º 2
0
def figure_2():
    # Figure 2: bounds on risk premia
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states=3)
    g1 = Rm
    g2 = Rf
    solver_args = (f, z0, z1, False, 1e-9, 1000)
    risk_premia_min, risk_premia_cond_min, risk_premia_empirical, risk_premia_cond_empirical\
        = bound_ratio(find_ξ_args=(solver_args, 0., None, None, None, None),
                         g1=g1, g2=g2, ζ=1.)
    result_risk_min = {
        'moment_empirical': risk_premia_empirical,
        'moment_empirical_cond': risk_premia_cond_empirical,
        'moment_bound': risk_premia_min,
        'moment_bound_cond': risk_premia_cond_min
    }

    # Below we load presolved ζs but users can plot the objective function over ζ to find the optimal ζs.
    # ζs that correspond to 0%-30% higher min RE (risk premia), step size=5%
    ζs_lower = [1., 1.007, 1.006, 1.006, 1.006, 1.006, 1.008]
    ζs_upper = [1., 1.007, 1.007, 1.008, 1.007, 1.008, 1.006]
    result_risk_lower_list = []
    result_risk_upper_list = []
    for i in range(0, 7):
        # lower bound
        risk_premia_lower, risk_premia_cond_lower, _ ,_\
            = bound_ratio(find_ξ_args=(solver_args, i*0.05, 1., (0., 100.), 1e-5, 100),
                             g1=g1, g2=g2, ζ=ζs_lower[i], lower=True)
        result_risk_lower = {
            'moment_bound': risk_premia_lower,
            'moment_bound_cond': risk_premia_cond_lower
        }
        result_risk_lower_list.append(result_risk_lower)
        # upper bound
        risk_premia_upper, risk_premia_cond_upper, _ ,_\
            = bound_ratio(find_ξ_args=(solver_args, i*0.05, 1., (0., 100.), 1e-5, 100),
                             g1=g1, g2=g2, ζ=ζs_upper[i], lower=False)
        result_risk_upper = {
            'moment_bound': -risk_premia_upper,
            'moment_bound_cond': -risk_premia_cond_upper
        }
        result_risk_upper_list.append(result_risk_upper)

    def f2(percent):
        box_chart(result_risk_min, result_risk_lower_list[int(percent / 5)],
                  result_risk_upper_list[int(percent / 5)])

    res = interact(f2,
                   percent=widgets.IntSlider(min=0, max=30, step=5, value=20))

    return res
Ejemplo n.º 3
0
def objective_vs_ξ(n_states):
    """
    An illustration of how the optimized μ and ϵ change with ξ.

    """
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states)
    ξ_grid = np.arange(.01, 1.01, .005)
    results_lower = [None] * len(ξ_grid)

    for i in range(len(ξ_grid)):
        ξ = ξ_grid[i]
        temp = solve(f=f,
                     g=log_Rw,
                     z0=z0,
                     z1=z1,
                     ξ=ξ,
                     quadratic=False,
                     tol=1e-9,
                     max_iter=1000)
        results_lower[i] = temp

    μs_lower = np.array([result['μ'] for result in results_lower])
    ϵs_lower = np.array([result['ϵ'] for result in results_lower])

    fig = make_subplots(rows=1, cols=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=μs_lower,
                             name='μ',
                             line=dict(color='blue')),
                  row=1,
                  col=1)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=ϵs_lower,
                             name='ϵ',
                             line=dict(color='green')),
                  row=1,
                  col=2)
    fig.update_layout(height=400,
                      width=1000,
                      title_text="Minimized μ (left) and ϵ (right)",
                      showlegend=False)
    fig.update_xaxes(rangemode="tozero", title_text='ξ')
    fig.update_yaxes(rangemode="tozero")

    fig['layout']['xaxis' + str(int(1))].update(range=(0., 1.))
    fig['layout']['xaxis' + str(int(2))].update(range=(0., 1.))

    fig.show()
Ejemplo n.º 4
0
def figure_1():
    # Figure 1: bounds on expected log market return
    # Below we load presolved ξs but users can use find_ξ to resolve them.
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states=3)
    g = log_Rw

    result_min = solve(f,
                       g,
                       z0,
                       z1,
                       ξ=10.,
                       quadratic=False,
                       tol=1e-9,
                       max_iter=1000)

    ξs_lower = [100, 0.29255, 0.20511, 0.16625, 0.14302, 0.12713, 0.11539]
    ξs_upper = [100, 0.29898, 0.21142, 0.17248, 0.14918, 0.13323, 0.12141]
    result_lower_list = []
    result_upper_list = []

    for i in range(0, 7):
        temp = solve(f,
                     g,
                     z0,
                     z1,
                     ξ=ξs_lower[i],
                     quadratic=False,
                     tol=1e-9,
                     max_iter=1000)
        result_lower_list.append(temp)
        temp = solve(f,
                     -g,
                     z0,
                     z1,
                     ξ=ξs_upper[i],
                     quadratic=False,
                     tol=1e-9,
                     max_iter=1000)
        result_upper_list.append(temp)

    def f1(percent):
        box_chart(result_min, result_lower_list[int(percent / 5)],
                  result_upper_list[int(percent / 5)])

    res = interact(f1,
                   percent=widgets.IntSlider(min=0, max=30, step=5, value=20))
    return res
Ejemplo n.º 5
0
def table_5(n_states=3):
    # Table 5: Comparison of transition matrices
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states)
    g = log_Rw  # Set g to be log return on wealth

    result_re = solve(f,
                      g,
                      z0,
                      z1,
                      ξ=10.,
                      quadratic=False,
                      tol=1e-9,
                      max_iter=1000)
    result_qd = solve(f,
                      g,
                      z0,
                      z1,
                      ξ=10.,
                      quadratic=True,
                      tol=1e-9,
                      max_iter=1000)

    print('Table 5: Transition probabilities and stationary probabilities')
    print('-------------------------------------------------------')
    print('          relative entropy        quadratic divergence')
    print('-------------------------------------------------------')
    print('Transition Matrix:')
    for state in np.arange(1, n_states + 1):
        print(
            f"           {np.round(result_re['P'][state-1],2)}         {np.round(result_qd['P_tilde'][state-1],2)}"
        )
    print('')
    print('Stationary Probability:')
    print(
        f"           {np.round(result_re['π'],2)}         {np.round(result_qd['π_tilde'],2)}"
    )
    print('-------------------------------------------------------')
Ejemplo n.º 6
0
def entropy_moment_bounds(n_states):
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states)
    ξ_grid = np.arange(.01, 1.01, .01)
    results_lower = [None] * len(ξ_grid)
    results_upper = [None] * len(ξ_grid)

    for i in range(len(ξ_grid)):
        ξ = ξ_grid[i]
        temp = solve(f=f,
                     g=log_Rw,
                     z0=z0,
                     z1=z1,
                     ξ=ξ,
                     quadratic=False,
                     tol=1e-9,
                     max_iter=1000)
        results_lower[i] = temp
        temp = solve(f=f,
                     g=-log_Rw,
                     z0=z0,
                     z1=z1,
                     ξ=ξ,
                     quadratic=False,
                     tol=1e-9,
                     max_iter=1000)
        results_upper[i] = temp

    REs_lower = np.array([result['RE'] for result in results_lower])
    moment_bounds_cond_lower = np.array(
        [result['moment_bound_cond'] for result in results_lower])
    moment_bounds_cond_upper = np.array(
        [-result['moment_bound_cond'] for result in results_upper])
    moment_bounds_lower = np.array(
        [result['moment_bound'] for result in results_lower])
    moment_bounds_upper = np.array(
        [-result['moment_bound'] for result in results_upper])
    moment_cond = np.array(
        [result['moment_empirical_cond'] for result in results_lower])
    moment = np.array([result['moment_empirical'] for result in results_lower])

    # Plots for RE and E[Mg(X)]
    fig = make_subplots(rows=1, cols=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=np.ones_like(ξ_grid) * REs_lower[-1] * 1.2,
                             name='1.2x min RE',
                             line=dict(color='black', dash='dash')),
                  row=1,
                  col=1)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=REs_lower,
                             name='lower bound',
                             line=dict(color='blue')),
                  row=1,
                  col=1)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_lower,
                             name='lower bound',
                             line=dict(color='green')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_upper,
                             name='upper bound',
                             line=dict(color='red')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment,
                             name='E[g(X)]',
                             line=dict(dash='dash', color='orange')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_lower[:, 0],
                             name='lower bound',
                             visible=False,
                             line=dict(color='green')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_upper[:, 0],
                             name='upper bound',
                             visible=False,
                             line=dict(color='red')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_cond[:, 0],
                             name='E[g(X)|1]',
                             visible=False,
                             line=dict(dash='dash', color='orange')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_lower[:, 1],
                             name='lower bound',
                             visible=False,
                             line=dict(color='green')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_upper[:, 1],
                             name='upper bound',
                             visible=False,
                             line=dict(color='red')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_cond[:, 1],
                             name='E[g(X)|2]',
                             visible=False,
                             line=dict(dash='dash', color='orange')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_lower[:, 2],
                             name='lower bound',
                             visible=False,
                             line=dict(color='green')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_bounds_cond_upper[:, 2],
                             name='upper bound',
                             visible=False,
                             line=dict(color='red')),
                  row=1,
                  col=2)
    fig.add_trace(go.Scatter(x=ξ_grid,
                             y=moment_cond[:, 2],
                             name='E[g(X)|3]',
                             visible=False,
                             line=dict(dash='dash', color='orange')),
                  row=1,
                  col=2)
    fig.update_layout(
        height=400,
        width=1000,
        title_text="Relative entropy (left) and moment bounds (right)",
        showlegend=False)
    fig.update_xaxes(rangemode="tozero", title_text='ξ')
    fig.update_yaxes(rangemode="tozero")

    fig['layout']['xaxis' + str(int(1))].update(range=(0., 1.))
    fig['layout']['yaxis' + str(int(1))].update(range=(0., 0.06))
    fig['layout']['xaxis' + str(int(2))].update(range=(0., 1.))
    fig['layout']['yaxis' + str(int(2))].update(range=(-0.01, 0.04))

    # Add button
    fig.update_layout(updatemenus=[
        dict(
            type="buttons",
            direction="up",
            active=0,
            x=1.2,
            y=0.9,
            buttons=list([
                dict(label="Unconditional",
                     method="update",
                     args=[{
                         "visible": [True] * 5 + [False] * 15
                     }]),
                dict(label="State 1",
                     method="update",
                     args=[{
                         "visible": [True] * 2 + [False] * 3 + [True] * 3 +
                         [False] * 6
                     }]),
                dict(label="State 2",
                     method="update",
                     args=[{
                         "visible": [True] * 2 + [False] * 6 + [True] * 3 +
                         [False] * 3
                     }]),
                dict(label="State 3",
                     method="update",
                     args=[{
                         "visible": [True] * 2 + [False] * 9 + [True] * 3
                     }]),
            ]),
        )
    ])

    fig.show()
Ejemplo n.º 7
0
def table_4():
    # Table 4: Proportional risk compensations
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states=3)

    # 1) Calculate bounds on risk premia of market return
    # Below we load presolved ζs but users can plot the objective function over ζ to find the optimal ζs.
    g1 = Rm
    g2 = Rf
    solver_args = (f, z0, z1, False, 1e-9, 1000)
    risk_Rm_min, risk_Rm_cond_min, risk_Rm_empirical, risk_Rm_cond_empirical\
        = bound_ratio(find_ξ_args=(solver_args, 0., None, None, None, None),
                      g1=g1, g2=g2, ζ=1., lower=True)
    risk_Rm_lower, risk_Rm_cond_lower, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.006, lower=True)
    risk_Rm_upper, risk_Rm_cond_upper, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.007, lower=False)

    # 2) Calculate bounds on risk premia of SMB return
    # Below we load presolved ζs but users can plot the objective function over ζ to find the optimal ζs.
    g1 = SMB
    g2 = Rf
    solver_args = (f, z0, z1, False, 1e-9, 1000)
    risk_SMB_min, risk_SMB_cond_min, risk_SMB_empirical, risk_SMB_cond_empirical\
        = bound_ratio(find_ξ_args=(solver_args, 0., None, None, None, None),
                      g1=g1, g2=g2, ζ=1., lower=True)
    risk_SMB_lower, risk_SMB_cond_lower, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.001, lower=True)
    risk_SMB_upper, risk_SMB_cond_upper, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.002, lower=False)

    # 3) Calculate bounds on risk premia of HML return
    # Below we load presolved ζs but users can plot the objective function over ζ to find the optimal ζs.
    g1 = HML
    g2 = Rf
    solver_args = (f, z0, z1, False, 1e-9, 1000)
    risk_HML_min, risk_HML_cond_min, risk_HML_empirical, risk_HML_cond_empirical\
        = bound_ratio(find_ξ_args=(solver_args, 0., None, None, None, None),
                      g1=g1, g2=g2, ζ=1., lower=True)
    risk_HML_lower, risk_HML_cond_lower, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=0.999, lower=True)
    risk_HML_upper, risk_HML_cond_upper, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1., lower=False)

    print('Table 4: Proportional risk compensations')
    print(
        '------------------------------------------------------------------------'
    )
    print(
        'conditioning      market return     small minus big     high minus low'
    )
    print(
        '                  (lower, upper)     (lower, upper)     (lower, upper)'
    )
    print(
        '                    empirical          empirical           empirical')
    print(
        '------------------------------------------------------------------------'
    )
    print('low D/P           (%s,%s)         (%s,%s)       (%s,%s)'  \
          % (np.round(risk_Rm_cond_lower[0]*400,2),
             np.round(risk_Rm_cond_upper[0]*400,2),
             np.round(risk_SMB_cond_lower[0]*400,2),
             np.round(risk_SMB_cond_upper[0]*400,2),
             np.round(risk_HML_cond_lower[0]*400,2),
             np.round(risk_HML_cond_upper[0]*400,2)))
    print('                      %s                %s               %s' \
          % (np.round(risk_Rm_cond_empirical[0]*400,2),
             np.round(risk_SMB_cond_empirical[0]*400,2),
             np.round(risk_HML_cond_empirical[0]*400,2)))
    print('mid D/P           (%s,%s)         (%s,%s)       (%s,%s)'  \
          % (np.round(risk_Rm_cond_lower[1]*400,2),
             np.round(risk_Rm_cond_upper[1]*400,2),
             np.round(risk_SMB_cond_lower[1]*400,2),
             np.round(risk_SMB_cond_upper[1]*400,2),
             np.round(risk_HML_cond_lower[1]*400,2),
             np.round(risk_HML_cond_upper[1]*400,2)))
    print('                      %s                %s               %s' \
          % (np.round(risk_Rm_cond_empirical[1]*400,2),
             np.round(risk_SMB_cond_empirical[1]*400,2),
             np.round(risk_HML_cond_empirical[1]*400,2)))
    print('high D/P          (%s,%s)         (%s,%s)       (%s,%s)'  \
          % (np.round(risk_Rm_cond_lower[2]*400,2),
             np.round(risk_Rm_cond_upper[2]*400,2),
             np.round(risk_SMB_cond_lower[2]*400,2),
             np.round(risk_SMB_cond_upper[2]*400,2),
             np.round(risk_HML_cond_lower[2]*400,2),
             np.round(risk_HML_cond_upper[2]*400,2)))
    print('                     %s                %s               %s' \
          % (np.round(risk_Rm_cond_empirical[2]*400,2),
             np.round(risk_SMB_cond_empirical[2]*400,2),
             np.round(risk_HML_cond_empirical[2]*400,2)))
    print('unconditional     (%s,%s)         (%s,%s)       (%s,%s)'  \
          % (np.round(risk_Rm_lower*400,2),
             np.round(risk_Rm_upper*400,2),
             np.round(risk_SMB_lower*400,2),
             np.round(risk_SMB_upper*400,2),
             np.round(risk_HML_lower*400,2),
             np.round(risk_HML_upper*400,2)))
    print('                      %s                %s               %s' \
          % (np.round(risk_Rm_empirical*400,2),
             np.round(risk_SMB_empirical*400,2),
             np.round(risk_HML_empirical*400,2)))
    print(
        '------------------------------------------------------------------------'
    )
    print(
        'Note 1: here we use n_states = 3 and a relative entropy divergence.')
    print(
        'Note 2: the numbers in the parentheses impose a divergence constraint'
    )
    print('        that is 20 percent higher than the minimum.')
Ejemplo n.º 8
0
def table_3():
    # Table 3: Expected log market return bounds
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states=3)
    g = log_Rw  # Set g to be log return on wealth

    # 1) Relative entropy specification
    result_min_RE = solve(f,
                          g,
                          z0,
                          z1,
                          ξ=100.,
                          quadratic=False,
                          tol=1e-9,
                          max_iter=1000)
    ξ_20_lower_RE = find_ξ(solver_args=(f, g, z0, z1, False, 1e-9, 1000),
                           min_div=result_min_RE['RE'],
                           pct=0.2,
                           initial_guess=1.,
                           interval=(0, 10.),
                           tol=1e-5,
                           max_iter=100)
    result_lower_RE = solve(f,
                            g,
                            z0,
                            z1,
                            ξ=ξ_20_lower_RE,
                            quadratic=False,
                            tol=1e-9,
                            max_iter=1000)
    ξ_20_upper_RE = find_ξ(solver_args=(f, -g, z0, z1, False, 1e-9, 1000),
                           min_div=result_min_RE['RE'],
                           pct=0.2,
                           initial_guess=1.,
                           interval=(0, 10.),
                           tol=1e-5,
                           max_iter=100)
    result_upper_RE = solve(f,
                            -g,
                            z0,
                            z1,
                            ξ=ξ_20_upper_RE,
                            quadratic=False,
                            tol=1e-9,
                            max_iter=1000)

    # 2) Quadratic specification
    result_min_QD = solve(f,
                          g,
                          z0,
                          z1,
                          ξ=10.,
                          quadratic=True,
                          tol=1e-9,
                          max_iter=1000)
    ξ_20_lower_QD = find_ξ(solver_args=(f, g, z0, z1, True, 1e-9, 1000),
                           min_div=result_min_QD['QD'],
                           pct=0.2,
                           initial_guess=1.,
                           interval=(0, 10.),
                           tol=1e-4,
                           max_iter=100)
    result_lower_QD = solve(f,
                            g,
                            z0,
                            z1,
                            ξ=ξ_20_lower_QD,
                            quadratic=True,
                            tol=1e-9,
                            max_iter=1000)
    ξ_20_upper_QD = find_ξ(solver_args=(f, -g, z0, z1, True, 1e-9, 1000),
                           min_div=result_min_QD['QD'],
                           pct=0.2,
                           initial_guess=1.,
                           interval=(0, 10.),
                           tol=1e-4,
                           max_iter=100)
    result_upper_QD = solve(f,
                            -g,
                            z0,
                            z1,
                            ξ=ξ_20_upper_QD,
                            quadratic=True,
                            tol=1e-9,
                            max_iter=1000)

    print('Table 3: Expected log market return bounds')
    print(
        '-----------------------------------------------------------------------'
    )
    print(
        'conditioning    empirical   relative entropy     quadratic divergence'
    )
    print('                             (lower, upper)         (lower,upper)')
    print(
        '-----------------------------------------------------------------------'
    )
    print('low D/P           %s         (%s,%s)           (%s,%s) ' \
          % (np.round(result_min_RE['moment_empirical_cond'][0]*400,2),
             np.round(result_lower_RE['moment_bound_cond'][0]*400,2),
             np.round(-result_upper_RE['moment_bound_cond'][0]*400,2),
             np.round(result_lower_QD['moment_bound_cond'][0]*400,2),
             np.round(-result_upper_QD['moment_bound_cond'][0]*400,2)))
    print('mid D/P           %s         (%s,%s)           (%s,%s)    ' \
          % (np.round(result_min_RE['moment_empirical_cond'][1]*400,2),
             np.round(result_lower_RE['moment_bound_cond'][1]*400,2),
             np.round(-result_upper_RE['moment_bound_cond'][1]*400,2),
             np.round(result_lower_QD['moment_bound_cond'][1]*400,2),
             np.round(-result_upper_QD['moment_bound_cond'][1]*400,2)))
    print('high D/P          %s        (%s,%s)           (%s,%s)  ' \
          % (np.round(result_min_RE['moment_empirical_cond'][2]*400,2),
             np.round(result_lower_RE['moment_bound_cond'][2]*400,2),
             np.round(-result_upper_RE['moment_bound_cond'][2]*400,2),
             np.round(result_lower_QD['moment_bound_cond'][2]*400,2),
             np.round(-result_upper_QD['moment_bound_cond'][2]*400,2)))
    print('unconditional     %s         (%s,%s)           (%s,%s)   ' \
          % (np.round(result_min_RE['moment_empirical']*400,2),
             np.round(result_lower_RE['moment_bound']*400,2),
             np.round(-result_upper_RE['moment_bound']*400,2),
             np.round(result_lower_QD['moment_bound']*400,2),
             np.round(-result_upper_QD['moment_bound']*400,2)))
    print(
        '-----------------------------------------------------------------------'
    )
    print('Note 1: here we use n_states = 3.')
    print(
        'Note 2: the numbers in the parentheses impose a divergence constraint'
    )
    print('        that is 20 percent higher than the minimum.')
Ejemplo n.º 9
0
def table_2():
    # Table 2: bounds on log expected return and generalized volatility
    f, log_Rw, z0, z1, Rf, Rm, SMB, HML = preprocess_data(n_states=3)

    # 1) Calculate bounds on expected return
    # Minimum divergence case
    result_min = solve(f,
                       Rm,
                       z0,
                       z1,
                       ξ=100.,
                       quadratic=False,
                       tol=1e-9,
                       max_iter=1000)

    # 20% higher divergence case, lower bound problem
    ξ_20_lower = find_ξ(solver_args=(f, Rm, z0, z1, False, 1e-9, 1000),
                        min_div=result_min['RE'],
                        pct=0.2,
                        initial_guess=1.,
                        interval=(0, 100.),
                        tol=1e-5,
                        max_iter=100)
    result_lower = solve(f=f,
                         g=Rm,
                         z0=z0,
                         z1=z1,
                         ξ=ξ_20_lower,
                         quadratic=False,
                         tol=1e-9,
                         max_iter=1000)

    # 20% higher divergence case, upper bound problem
    ξ_20_upper = find_ξ(solver_args=(f, -Rm, z0, z1, False, 1e-9, 1000),
                        min_div=result_min['RE'],
                        pct=0.2,
                        initial_guess=1.,
                        interval=(0, 100.),
                        tol=1e-5,
                        max_iter=100)
    result_upper = solve(f=f,
                         g=-Rm,
                         z0=z0,
                         z1=z1,
                         ξ=ξ_20_upper,
                         quadratic=False,
                         tol=1e-9,
                         max_iter=1000)

    # 2) Calculate bounds on generalized volatility
    # Below we load presolved ζs but users can plot the objective function over ζ to find the optimal ζs.
    g1 = Rm
    g2 = log_Rw
    solver_args = (f, z0, z1, False, 1e-9, 1000)
    vol_min, vol_cond_min, vol_empirical, vol_cond_empirical\
        = bound_ratio(find_ξ_args=(solver_args, 0., None, None, None, None),
                      g1=g1, g2=g2, ζ=1., lower=True, result_type=2)
    vol_lower, vol_cond_lower, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.008, lower=True, result_type=2)
    vol_upper, vol_cond_upper, _, _\
        = bound_ratio(find_ξ_args=(solver_args, 0.2, 1., (0., 10.), 1e-5, 100),
                         g1=g1, g2=g2, ζ=1.009, lower=False, result_type=2)

    print('Table 2: Log expected market return and generalized volatility')
    print(
        '-------------------------------------------------------------------------------'
    )
    print(
        'conditioning      logE           logE          logE - Elog     logE - Elog'
    )
    print(
        '                empirical       imputed         empirical        imputed'
    )
    print(
        '                             (lower, upper)                   (lower,upper)'
    )
    print(
        '-------------------------------------------------------------------------------'
    )
    print('low D/P           %s           %s             %s            %s' \
          % (np.round(np.log(result_min['moment_empirical_cond'][0])*400,2),
             np.round(np.log(result_min['moment_bound_cond'][0])*400,2),
             np.round(vol_cond_empirical[0]*400,2),
             np.round(vol_cond_min[0]*400,2)))
    print('                              (%s,%s)                      (%s,%s)' \
          % (np.round(np.log(result_lower['moment_bound_cond'][0])*400,2),
             np.round(np.log(-result_upper['moment_bound_cond'][0])*400,2),
             np.round(vol_cond_lower[0]*400,2),np.round(vol_cond_upper[0]*400,2)))
    print('mid D/P           %s            %s             %s            %s' \
          % (np.round(np.log(result_min['moment_empirical_cond'][1])*400,2),
             np.round(np.log(result_min['moment_bound_cond'][1])*400,2),
             np.round(vol_cond_empirical[1]*400,2),np.round(vol_cond_min[1]*400,2)))
    print('                              (%s,%s)                      (%s,%s)' \
          % (np.round(np.log(result_lower['moment_bound_cond'][1])*400,2),
             np.round(np.log(-result_upper['moment_bound_cond'][1])*400,2),
             np.round(vol_cond_lower[1]*400,2),np.round(vol_cond_upper[1]*400,2)))
    print('high D/P          %s          %s             %s            %s' \
          % (np.round(np.log(result_min['moment_empirical_cond'][2])*400,2),
             np.round(np.log(result_min['moment_bound_cond'][2])*400,2),
             np.round(vol_cond_empirical[2]*400,2),np.round(vol_cond_min[2]*400,2)))
    print('                              (%s,%s)                      (%s,%s)' \
          % (np.round(np.log(result_lower['moment_bound_cond'][2])*400,2),
             np.round(np.log(-result_upper['moment_bound_cond'][2])*400,2),
             np.round(vol_cond_lower[2]*400,2),np.round(vol_cond_upper[2]*400,2)))
    print('unconditional     %s           %s             %s            %s' \
          % (np.round(np.log(result_min['moment_empirical'])*400,2),
             np.round(np.log(result_min['moment_bound'])*400,2),
             np.round(vol_empirical*400,2),np.round(vol_min*400,2)))
    print('                              (%s,%s)                      (%s,%s)' \
          % (np.round(np.log(result_lower['moment_bound'])*400,2),
             np.round(np.log(-result_upper['moment_bound'])*400,2),
             np.round(vol_lower*400,2),np.round(vol_upper*400,2)))
    print(
        '-------------------------------------------------------------------------------'
    )
    print(
        'Note 1: here we use n_states = 3 and a relative entropy divergence.')
    print(
        'Note 2: the numbers in the parentheses impose a divergence constraint'
    )
    print('        that is 20 percent higher than the minimum.')