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!")