quant-econ Solutions: Search with Unknown Offer Distribution

Solutions for http://quant-econ.net/jl/odu.html


In [2]:
using QuantEcon, QuantEcon.Models
using PyPlot
using Grid
using StatsBase

Exercise 1

This code solves the "Offer Distribution Unknown" model by iterating on a guess of the reservation wage function. You should find that the run time is much shorter than that of the value function approach in examples/odu_vfi_plots.jl


In [3]:
sp = SearchProblem(pi_grid_size=50)

phi_init = ones(sp.n_pi) 
f(x) = res_wage_operator(sp, x)
w_bar = compute_fixed_point(f, phi_init)

fig, ax = subplots(figsize=(9, 7))
ax[:plot](sp.pi_grid, w_bar, linewidth=2, color="black")
ax[:set_ylim](0, 2)
ax[:grid](axis="x", linewidth=0.25, linestyle="--", color="0.25")
ax[:grid](axis="y", linewidth=0.25, linestyle="--", color="0.25")
ax[:fill_between](sp.pi_grid, 0, w_bar, color="blue", alpha=0.15)
ax[:fill_between](sp.pi_grid, w_bar, 2, color="green", alpha=0.15)
ax[:text](0.42, 1.2, "reject")
ax[:text](0.7, 1.8, "accept")
plt.show()


Compute iterate 10 with error 0.007194437603255777
Converged in 18 steps

The next piece of code is not one of the exercises from quant-econ, it's just a fun simulation to see what the effect of a change in the underlying distribution on the unemployment rate is.

At a point in the simulation, the distribution becomes significantly worse. It takes a while for agents to learn this, and in the meantime they are too optimistic, and turn down too many jobs. As a result, the unemployment rate spikes.

The code takes a few minutes to run.


In [4]:
# Set up model and compute the function w_bar
sp = SearchProblem(pi_grid_size=50, F_a=1, F_b=1)
phi_init = ones(sp.n_pi) 
g(x) = res_wage_operator(sp, x)
w_bar_vals = compute_fixed_point(g, phi_init)
w_bar = CoordInterpGrid(sp.pi_grid, w_bar_vals, BCnearest, InterpLinear)

# Holds the employment state and beliefs of an individual agent.
type Agent  
    _pi
    employed
end

Agent(_pi=1e-3) = Agent(_pi, 1)

function update!(ag::Agent, H)
    if ag.employed == 0
        w = rand(H) * 2  # account for scale in python
        if w >= w_bar[ag._pi]
            ag.employed = 1
        else
            ag._pi = 1.0 ./ (1 .+ ((1 - ag._pi) .* sp.g(w)) ./ (ag._pi * sp.f(w)))
        end
    end
    nothing
end

num_agents = 5000
separation_rate = 0.025  # Fraction of jobs that end in each period
separation_num = int(num_agents * separation_rate)
agent_indices = [1:num_agents]
agents = [Agent() for i=1:num_agents]
sim_length = 600
H = sp.G  # Start with distribution G
change_date = 200  # Change to F after this many periods
unempl_rate = Array(Float64, sim_length)

for i=1:sim_length
    if i % 20 == 0
        println("date = $i")
    end
    
    if i == change_date
        H = sp.F
    end
    
    # Randomly select separation_num agents and set employment status to 0
    shuffle!(agent_indices)
    separation_list = agent_indices[1:separation_num]
    
    for agent in agents[separation_list]
        agent.employed = 0
    end
    
    # update agents
    for agent in agents
        update!(agent, H)
    end
    employed = Int[agent.employed for agent in agents]
    unempl_rate[i] = 1.0 - mean(employed)
end

plt.close("all")
fig, ax = subplots(figsize=(9, 7))
ax[:plot](unempl_rate, lw=2, alpha=0.8, label="unemployment rate")
ax[:axvline](change_date, color="red")
ax[:legend]()
show()


Compute iterate 10 with error 0.007194437603255777
Converged in 18 steps
date = 20
date = 40
date = 60
date = 80
date = 100
date = 120
date = 140
date = 160
date = 180
date = 200
date = 220
date = 240
date = 260
date = 280
date = 300
date = 320
date = 340
date = 360
date = 380
date = 400
date = 420
date = 440
date = 460
date = 480
date = 500
date = 520
date = 540
date = 560
date = 580
date = 600