RiskPremium

Measuring the market risk premium
Log | Files | Refs

test_cay.jl (3750B)


      1 # test/test_cay.jl  — Validate CAY module against Lettau & Ludvigson's published data
      2 #
      3 # Run:  julia --project=. test/test_cay.jl
      4 
      5 using Test, CSV, DataFrames, Dates, Statistics
      6 
      7 # ---------- Load the CAY module ------------------------------------------
      8 include(joinpath(@__DIR__, "..", "src", "CAY.jl"))
      9 using .CAY
     10 
     11 # ---------- Load Lettau's published data ---------------------------------
     12 lettau = CSV.read(
     13     joinpath(@__DIR__, "..", "input", "cay_current.csv"),
     14     DataFrame;
     15     header = 1,
     16     normalizenames = true,
     17 )
     18 
     19 # Rename columns to standard names
     20 rename!(lettau, names(lettau) .=> ["date", "c", "w", "y", "cay"])
     21 
     22 # Parse dates
     23 lettau.date = Date.(lettau.date)
     24 
     25 # ---------- Download & process our data ----------------------------------
     26 println("Downloading FRED series and computing CAY...")
     27 # Estimate DOLS on Lettau's sample period (1951Q4-2019Q3) for replication
     28 result = CAY.compute_cay(estimation_start=Date(1951,10,1), estimation_end=Date(2019,9,30))
     29 cay_df = result.data
     30 
     31 # ---------- Align to Lettau's date range ---------------------------------
     32 # Our result uses end-of-quarter dates; Lettau's also uses end-of-quarter.
     33 # Merge on date
     34 merged = innerjoin(
     35     select(cay_df, :date, :c => :c_ours, :a => :a_ours, :y => :y_ours, :cay => :cay_ours),
     36     select(lettau, :date, :c => :c_lettau, :w => :w_lettau, :y => :y_lettau, :cay => :cay_lettau),
     37     on = :date,
     38 )
     39 
     40 println("Merged $(nrow(merged)) quarters (Lettau has $(nrow(lettau)) quarters)")
     41 
     42 @testset "CAY Validation" begin
     43 
     44     # ---- 1) Correlation of log-levels > 0.999 ----------------------------
     45     @testset "Level correlations" begin
     46         corr_c = cor(merged.c_ours, merged.c_lettau)
     47         corr_a = cor(merged.a_ours, merged.w_lettau)
     48         corr_y = cor(merged.y_ours, merged.y_lettau)
     49         println("  cor(c): $corr_c")
     50         println("  cor(a): $corr_a")
     51         println("  cor(y): $corr_y")
     52         @test corr_c > 0.999
     53         @test corr_a > 0.999
     54         @test corr_y > 0.999
     55     end
     56 
     57     # ---- 2) First-difference max errors ----------------------------------
     58     @testset "First-difference accuracy" begin
     59         dc_ours   = diff(merged.c_ours)
     60         dc_lettau = diff(merged.c_lettau)
     61         da_ours   = diff(merged.a_ours)
     62         da_lettau = diff(merged.w_lettau)
     63         dy_ours   = diff(merged.y_ours)
     64         dy_lettau = diff(merged.y_lettau)
     65 
     66         max_dc = maximum(abs.(dc_ours .- dc_lettau))
     67         max_da = maximum(abs.(da_ours .- da_lettau))
     68         max_dy = maximum(abs.(dy_ours .- dy_lettau))
     69         println("  max |Δc - Δc_L|: $max_dc")
     70         println("  max |Δa - Δa_L|: $max_da")
     71         println("  max |Δy - Δy_L|: $max_dy")
     72         @test max_dc < 0.01
     73         @test max_da < 0.01
     74         @test max_dy < 0.01
     75     end
     76 
     77     # ---- 3) DOLS coefficients -------------------------------------------
     78     @testset "DOLS coefficients" begin
     79         beta_a = result.beta_a
     80         beta_y = result.beta_y
     81         println("  β_a = $beta_a  (Lettau: ≈0.218)")
     82         println("  β_y = $beta_y  (Lettau: ≈0.801)")
     83         @test abs(beta_a - 0.218) < 0.05
     84         @test abs(beta_y - 0.801) < 0.10
     85     end
     86 
     87     # ---- 4) CAY correlation > 0.99 --------------------------------------
     88     @testset "CAY correlation" begin
     89         # Demean both series
     90         cay_ours   = merged.cay_ours .- mean(merged.cay_ours)
     91         cay_lettau = merged.cay_lettau .- mean(merged.cay_lettau)
     92         corr_cay = cor(cay_ours, cay_lettau)
     93         println("  cor(cay_demeaned): $corr_cay")
     94         # Threshold 0.98: cross-vintage replication with 2023 NIPA comprehensive revision
     95         # shifts deflator ~6% and modifies component series definitions
     96         @test corr_cay > 0.98
     97     end
     98 end
     99 
    100 println("\nAll CAY tests passed!")