yield_curve_gsw.md (6429B)
1 # Import Yield Curve Data 2 3 Some utilities for working with Gürkaynak-Sack-Wright (GSW) yield curve data from the New York Fed and Nelson-Siegel-Svensson model calculations. 4 Note that some of the code was first written by hand and then reimplemented using AI; while I have tested some functions, you may want to do your own sanity checks. 5 6 ## Overview 7 8 This package provides tools to: 9 - Import daily GSW yield curve parameters from the Federal Reserve 10 - Calculate yields, prices, and returns using Nelson-Siegel-Svensson models 11 - Handle both 3-factor (Nelson-Siegel) and 4-factor (Svensson) model periods 12 - Work with time series of bond returns and risk premiums 13 14 15 ## Installation 16 17 ```julia 18 using FinanceRoutines; 19 ``` 20 21 ## Quick Start 22 23 ```julia 24 # Import GSW parameters from the Fed 25 df = import_gsw_parameters(date_range=(Date("1960-01-01"), Dates.today()) ) 26 27 # Add yield calculations for multiple maturities 28 FinanceRoutines.add_yields!(df, [1, 2, 5, 10, 30]) 29 30 # Add bond prices 31 FinanceRoutines.add_prices!(df, [1, 5, 10]) 32 33 # Calculate daily returns for 10-year bonds 34 FinanceRoutines.add_returns!(df, 10.0, frequency=:daily, return_type=:log) 35 # Calculate excess returns over 3-month rate 36 FinanceRoutines.add_excess_returns!(df, 10.0, risk_free_maturity=0.25) 37 ``` 38 39 40 ## Core Types 41 42 ### GSWParameters 43 44 Structure to hold Nelson-Siegel-Svensson model parameters: 45 46 ```julia 47 # 4-factor Svensson model 48 params = GSWParameters(5.0, -2.0, 1.5, 0.8, 2.5, 0.5) 49 50 # 3-factor Nelson-Siegel model (missing β₃, τ₂) 51 params_3f = GSWParameters(5.0, -2.0, 1.5, missing, 2.5, missing) 52 53 # From DataFrame row 54 params = GSWParameters(df[1, :]) 55 ``` 56 57 ## Core Functions 58 59 ### Data Import 60 61 ```julia 62 # Import all available data 63 df = import_gsw_parameters() 64 65 # Import specific date range 66 df = import_gsw_parameters(date_range=(Date("2010-01-01"), Date("2020-12-31"))) 67 ``` 68 69 ### Yield Calculations 70 71 ```julia 72 # Single yield calculation 73 yield = gsw_yield(10.0, params) # 10-year yield 74 yield = gsw_yield(10.0, 5.0, -2.0, 1.5, 0.8, 2.5, 0.5) # Using individual parameters 75 76 # Yield curve 77 maturities = [0.25, 0.5, 1, 2, 5, 10, 30] 78 yields = gsw_yield_curve(maturities, params) 79 ``` 80 81 ### Price Calculations 82 83 ```julia 84 # Zero-coupon bond prices 85 price = gsw_price(10.0, params) # 10-year zero price 86 price = gsw_price(10.0, params, face_value=100.0) # Custom face value 87 88 # Price curve 89 prices = gsw_price_curve(maturities, params) 90 ``` 91 92 ### Return Calculations 93 94 ```julia 95 # Bond returns between two periods 96 params_today = GSWParameters(5.0, -2.0, 1.5, 0.8, 2.5, 0.5) 97 params_yesterday = GSWParameters(4.9, -1.9, 1.4, 0.9, 2.4, 0.6) 98 99 # Daily log return 100 ret = gsw_return(10.0, params_today, params_yesterday) 101 102 # Monthly arithmetic return 103 ret = gsw_return(10.0, params_today, params_yesterday, 104 frequency=:monthly, return_type=:arithmetic) 105 106 # Excess return over risk-free rate 107 excess_ret = gsw_excess_return(10.0, params_today, params_yesterday) 108 ``` 109 110 ### Forward Rates 111 112 ```julia 113 # 1-year forward rate starting in 2 years 114 fwd_rate = gsw_forward_rate(2.0, 3.0, params) 115 ``` 116 117 ## DataFrame Operations 118 119 ### Adding Calculations to DataFrames 120 121 ```julia 122 # Add yields for multiple maturities 123 FinanceRoutines.add_yields!(df, [1, 2, 5, 10, 30]) 124 125 # Add prices with custom face value 126 FinanceRoutines.add_prices!(df, [1, 5, 10], face_value=100.0) 127 128 # Add daily log returns 129 FinanceRoutines.add_returns!(df, 10.0, frequency=:daily, return_type=:log) 130 131 # Add monthly arithmetic returns 132 FinanceRoutines.add_returns!(df, 5.0, frequency=:monthly, return_type=:arithmetic) 133 134 # Add excess returns 135 FinanceRoutines.add_excess_returns!(df, 10.0, risk_free_maturity=0.25) 136 ``` 137 138 ### Column Names 139 140 The package creates standardized column names: 141 - Yields: `yield_1y`, `yield_10y`, `yield_0.5y` 142 - Prices: `price_1y`, `price_10y`, `price_0.5y` 143 - Returns: `ret_10y_daily`, `ret_5y_monthly` 144 - Excess returns: `excess_ret_10y_daily` 145 146 ## Convenience Functions 147 148 ### Yield Curve Snapshots 149 150 ```julia 151 # Create yield curve for a single date 152 curve = FinanceRoutines.gsw_curve_snapshot(params) 153 curve = FinanceRoutines.gsw_curve_snapshot(5.0, -2.0, 1.5, 0.8, 2.5, 0.5) 154 155 # Custom maturities 156 curve = FinanceRoutines.gsw_curve_snapshot(params, maturities=[1, 3, 5, 7, 10, 20, 30]) 157 ``` 158 159 ## Model Specifications 160 161 The package automatically handles two model types: 162 163 ### 4-Factor Svensson Model 164 - Uses all 6 parameters: β₀, β₁, β₂, β₃, τ₁, τ₂ 165 - More flexible yield curve shapes 166 - Used in recent periods 167 168 ### 3-Factor Nelson-Siegel Model 169 - Uses 4 parameters: β₀, β₁, β₂, τ₁ (β₃=0, τ₂=τ₁) 170 - Simpler model specification 171 - Used in earlier periods or when data is missing 172 173 The package automatically detects which model to use based on available parameters. 174 175 ## Missing Data Handling 176 177 - Automatically converts common flag values to `missing`: `-999.99`, `-999`, `-9999`, `-99.99` 178 - Gracefully handles periods with missing τ₂/β₃ parameters 179 - Propagates missing values through calculations appropriately 180 181 ## Example Analysis 182 183 ```julia 184 using DataFrames, Statistics 185 186 # Import data for 1970s and 1980s 187 df = import_gsw_parameters(date_range=(Date("1970-01-01"), Date("1989-12-31"))) 188 189 # Add calculations 190 FinanceRoutines.add_yields!(df, 1) # 1-year yields 191 FinanceRoutines.add_prices!(df, 1) # 1-year prices 192 FinanceRoutines.add_returns!(df, 2, frequency=:daily, return_type=:log) # 2-year daily returns 193 194 # Analyze by decade 195 transform!(df, :date => (x -> year.(x) .÷ 10 * 10) => :decade) 196 197 # Summary statistics 198 stats = combine( 199 groupby(df, :decade), 200 :yield_1y => (x -> mean(skipmissing(x))) => :mean_yield, 201 :yield_1y => (x -> std(skipmissing(x))) => :vol_yield, 202 :ret_2y_daily => (x -> mean(skipmissing(x))) => :mean_return, 203 :ret_2y_daily => (x -> std(skipmissing(x))) => :vol_return 204 ) 205 ``` 206 207 208 ## Data Source 209 210 GSW yield curve parameters are downloaded from the Federal Reserve Economic Data (FRED): 211 - URL: https://www.federalreserve.gov/data/yield-curve-tables/feds200628.csv 212 - Updated daily 213 - Historical data available from 1961 214 215 ## References 216 217 - Gürkaynak, R. S., B. Sack, and J. H. Wright (2007). "The U.S. Treasury yield curve: 1961 to the present." Journal of Monetary Economics 54(8), 2291-2304. 218 - Nelson, C. R. and A. F. Siegel (1987). "Parsimonious modeling of yield curves." Journal of Business 60(4), 473-489. 219 - Svensson, L. E. (1994). "Estimating and interpreting forward interest rates: Sweden 1992-1994." NBER Working Paper No. 4871. 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234