betas.jl (3260B)
1 @testset verbose=true "betas tests ... " begin 2 3 import Dates: Date, Month 4 import Statistics: mean 5 6 7 # -- generate a test dataframe 8 function gen_dataset(; 9 return_noise = 0.0, 10 missing_ratio = 0.0 11 ) 12 13 dates = [ 14 Date(2010,1,1):Month(1):Date(2022,12,31), 15 Date(2017,1,1):Month(1):Date(2024,12,31), 16 Date(2000,1,1):Month(1):Date(2015,12,31) 17 ] 18 n = length(dates) 19 firms = [1, 2, 3] 20 α = [0, 0.1, 0.05] 21 β = [0.8 1 1.2; 0.2 -0.3 0; -0.8 0.1 0] 22 23 # generate aggregate factors 24 date_factors = minimum(minimum.(dates)):Month(1):maximum(maximum.(dates)) 25 df_factors = DataFrame( 26 datem = date_factors, 27 mkt = accumulate((x,ϵ) -> 0.9*x + 0.1 * ϵ, randn(length(date_factors))), 28 F1 = accumulate((x,ϵ) -> 0.5*x + 0.5 * ϵ, randn(length(date_factors))), 29 F2 = accumulate((x,ϵ) -> 0.05*x + 0.9 * ϵ, randn(length(date_factors))) 30 ) 31 32 df_firms = [ 33 leftjoin( 34 DataFrame( 35 datem = dates[i], firm_id = firms[i], 36 α = α[i], βmkt = β[1, i], βF1 = β[2, i], βF2 = β[3, i]), 37 df_factors, on = :datem) 38 for i in 1:3] 39 df_firms = reduce(vcat, df_firms) 40 41 # -- estimate the return with some noise 42 # @transform!(df_firms, 43 # :ret = :α + :βmkt .* :mkt + :βF1 .* :F1 + :βF2 .* :F2 + 0.0.*randn(nrow(df_firms)) ) 44 transform!(df_firms, 45 AsTable([:α, :βmkt, :mkt, :βF1, :F1, :βF2, :F2]) => 46 (n -> n.α + n.βmkt .* n.mkt + n.βF1 .* n.F1 + n.βF2 .* n.F2 + 0.0.*randn(nrow(df_firms))) => 47 :ret) 48 allowmissing!(df_firms, :ret) 49 50 # put some random missing ... 51 df_firms[rand(1:nrow(df_factors), round(Int, missing_ratio*nrow(df_factors))), :ret] .= missing; 52 sort!(df_firms, [:firm_id, :datem]) 53 54 return df_firms 55 end 56 57 58 # -- test the function when we have fixed betas ... but we are running rolling regressions 59 df_firms = gen_dataset() 60 insertcols!(df_firms, :a => missing, :bmkt => missing, :bF1 => missing, :bF2 => missing) 61 62 for subdf in groupby(df_firms, :firm_id) 63 β = calculate_rolling_betas( 64 [ones(nrow(subdf)) subdf.mkt subdf.F1 subdf.F2], 65 subdf.ret; 66 window=60, min_data=nothing 67 ) 68 # Create and assign columns for β coefficients 69 subdf[!, [:a, :bmkt, :bF1, :bF2]] = β 70 end 71 72 df_test1 = @p df_firms |> 73 subset(__, :a => ByRow(x -> !ismissing(x))) |> 74 select(__, :datem, :firm_id, 75 [:a, :α] => ByRow((x,y) -> x - y) => :Δ_a, 76 [:bmkt, :βmkt] => ByRow((x,y) -> x - y) => :Δ_bmkt, 77 [:bF1, :βF1] => ByRow((x,y) -> x - y) => :Δ_bF1, 78 [:bF2, :βF2] => ByRow((x,y) -> x - y) => :Δ_bF2) |> 79 groupby(__, :firm_id) |> 80 combine(__, [:Δ_a, :Δ_bmkt, :Δ_bF1, :Δ_bF2] .=> mean, renamecols=false) 81 82 @test isapprox.(0.0, 83 maximum(abs.(Array(combine(df_test1, [:Δ_a, :Δ_bmkt, :Δ_bF1, :Δ_bF2] .=> mean)[1, :]))), 84 atol = 1E-10) 85 86 87 88 end 89 90 91 92 93 94 95 96 97