yieldcurveml.utils
105def get_swap_rates(dataset: Literal["ap10", "and07", "ab13e6m", "ab13ois", "negativerates"]) -> SwapRatesData: 106 """ 107 Get example swap rates datasets. 108 109 Args: 110 dataset: String specifying the dataset to use, 111 one of "ap10", "and07", "ab13e6m", "ab13ois", "negativerates" 112 113 Returns: 114 SwapRatesData containing maturity and rate vectors 115 116 Examples: 117 >>> print(get_swap_rates("ap10")) 118 SwapRatesData(maturity=array([ 1, 2, 3, 5, 7, 10, 12, 15, 20, 25]), 119 rate=array([0.042, 0.043, 0.047, 0.054, 0.057, 0.06 , 0.061, 0.059, 0.056, 0.0555])) 120 """ 121 # Define all datasets 122 swap_rates: Dict[str, SwapRatesData] = { 123 "ap10": SwapRatesData( 124 maturity=np.array([1, 2, 3, 5, 7, 10, 12, 15, 20, 25]), 125 rate=np.array([4.2, 4.3, 4.7, 5.4, 5.7, 6, 6.1, 5.9, 5.6, 5.55]) / 100 126 ), 127 128 "and07": SwapRatesData( 129 maturity=np.array([0.5, 1, 1.5, 2, 2.5, 3, 4, 5, 7, 10, 12, 15, 20, 30]), 130 rate=np.array([2.75, 3.10, 3.30, 3.43, 3.53, 3.30, 3.78, 3.95, 131 4.25, 4.50, 4.65, 4.78, 4.88, 4.85]) / 100 132 ), 133 134 "ab13e6m": SwapRatesData( 135 maturity=np.array(list(range(1, 31)) + [35, 40, 50, 60]), 136 rate=np.array([ 137 0.286, 0.324, 0.424, 0.576, 0.762, 0.954, 1.135, 1.303, 1.452, 1.584, 138 1.703, 1.809, 1.901, 1.976, 2.037, 2.086, 2.123, 2.150, 2.171, 2.187, 139 2.200, 2.211, 2.220, 2.228, 2.234, 2.239, 2.243, 2.247, 2.251, 2.256, 140 2.295, 2.348, 2.421, 2.463 141 ]) / 100 142 ), 143 144 "ab13ois": SwapRatesData( 145 maturity=np.array(list(range(1, 13)) + [15, 20, 25, 30]), 146 rate=np.array([ 147 0.000, 0.036, 0.127, 0.274, 0.456, 0.647, 0.827, 0.996, 1.147, 1.280, 148 1.404, 1.516, 1.764, 1.939, 2.003, 2.038 149 ]) / 100 150 ), 151 152 "negativerates": SwapRatesData( 153 maturity=np.array([0.5, 1, 2, 3, 5]), 154 rate=np.array([-0.00337, -0.003610, -0.003647, -0.003413, -0.003047]) 155 ) 156 } 157 158 if dataset not in swap_rates: 159 raise ValueError( 160 f"Dataset {dataset} not found. Available datasets: {', '.join(swap_rates.keys())}" 161 ) 162 163 return swap_rates[dataset]
Get example swap rates datasets.
Args: dataset: String specifying the dataset to use, one of "ap10", "and07", "ab13e6m", "ab13ois", "negativerates"
Returns: SwapRatesData containing maturity and rate vectors
Examples:
print(get_swap_rates("ap10")) SwapRatesData(maturity=array([ 1, 2, 3, 5, 7, 10, 12, 15, 20, 25]), rate=array([0.042, 0.043, 0.047, 0.054, 0.057, 0.06 , 0.061, 0.059, 0.056, 0.0555]))
SwapRatesData(maturity, rate)
21def swap_cashflows_matrix( 22 swap_rates: Union[List[float], np.ndarray], 23 maturities: Union[List[float], np.ndarray], 24 tenor_swaps: Literal["1m", "3m", "6m", "1y"] = "6m" 25) -> SwapCashflows: 26 """ 27 Creates a matrix of swap cashflows. 28 29 Args: 30 swap_rates: Vector of swap rates 31 maturities: Vector of maturities (in years) 32 tenor_swaps: Tenor for the swaps, one of "1m", "3m", "6m", "1y" 33 34 Returns: 35 SwapCashflows object containing: 36 - nb_swaps: number of swaps 37 - swaps_maturities: original maturities 38 - nb_swap_dates: number of cashflow dates per swap 39 - swap_rates: original swap rates 40 - cashflow_dates: matrix of cashflow dates 41 - cashflow_matrix: matrix of cashflows 42 43 Example: 44 >>> rates = [0.02, 0.025, 0.03] 45 >>> maturities = [1, 2, 3] 46 >>> result = swap_cashflows_matrix(rates, maturities, "6m") 47 """ 48 # Convert inputs to numpy arrays if they aren't already 49 swap_rates = np.array(swap_rates) 50 maturities = np.array(maturities) 51 52 nb_swaps = len(swap_rates) 53 if nb_swaps != len(maturities): 54 raise ValueError("There must be as many swap rates as maturities") 55 56 # Define frequency mapping 57 freq_map = { 58 "1m": 1/12, 59 "3m": 1/4, 60 "6m": 1/2, 61 "1y": 1 62 } 63 64 if tenor_swaps not in freq_map: 65 raise ValueError("tenor_swaps must be one of: '1m', '3m', '6m', '1y'") 66 67 freq = freq_map[tenor_swaps] 68 69 # Create cashflow dates 70 cashflow_dates = np.arange(freq, max(maturities) + freq, freq) 71 nb_cashflow_dates = len(cashflow_dates) 72 nb_cashflow_dates_swaps = (1 / freq) * maturities 73 74 # Initialize matrices 75 swap_cashflows_matrix = np.zeros((nb_swaps, nb_cashflow_dates)) 76 cashflow_dates_matrix = np.zeros((nb_swaps, nb_cashflow_dates)) 77 nb_swap_dates = np.zeros(nb_swaps) 78 79 # Fill matrices 80 for i in range(nb_swaps): 81 nb_cashflow_dates_swaps_i = int(nb_cashflow_dates_swaps[i]) 82 swap_rate_i_times_freq = swap_rates[i] * freq 83 84 # Set regular cashflows 85 swap_cashflows_matrix[i, :nb_cashflow_dates_swaps_i] = swap_rate_i_times_freq 86 # Add principal repayment at maturity 87 swap_cashflows_matrix[i, nb_cashflow_dates_swaps_i - 1] += 1 88 89 nb_swap_dates[i] = np.sum(swap_cashflows_matrix[i, :] > 0) 90 cashflow_dates_matrix[i, :nb_cashflow_dates_swaps_i] = cashflow_dates[:nb_cashflow_dates_swaps_i] 91 92 # Add row and column names 93 swap_names = [f"swap{i+1}" for i in range(nb_swaps)] 94 date_names = [f"{d}y" for d in cashflow_dates] 95 96 return SwapCashflows( 97 nb_swaps=nb_swaps, 98 swaps_maturities=maturities, 99 nb_swap_dates=nb_swap_dates, 100 swap_rates=swap_rates, 101 cashflow_dates=cashflow_dates_matrix, 102 cashflow_matrix=swap_cashflows_matrix 103 )
Creates a matrix of swap cashflows.
Args: swap_rates: Vector of swap rates maturities: Vector of maturities (in years) tenor_swaps: Tenor for the swaps, one of "1m", "3m", "6m", "1y"
Returns: SwapCashflows object containing: - nb_swaps: number of swaps - swaps_maturities: original maturities - nb_swap_dates: number of cashflow dates per swap - swap_rates: original swap rates - cashflow_dates: matrix of cashflow dates - cashflow_matrix: matrix of cashflows
Example:
rates = [0.02, 0.025, 0.03] maturities = [1, 2, 3] result = swap_cashflows_matrix(rates, maturities, "6m")
165def regression_report( 166 model: 'CurveStripper', 167 name: str = "Model" 168) -> str: 169 """Create a formatted report of regression diagnostics for a fitted CurveStripper model. 170 171 Parameters 172 ---------- 173 model : CurveStripper 174 Fitted CurveStripper model 175 name : str, default="Model" 176 Name to use for the model in the report 177 178 Returns 179 ------- 180 str 181 Formatted report string 182 183 Examples 184 -------- 185 >>> from yieldcurveml.stripcurve import CurveStripper 186 >>> from sklearn.ensemble import RandomForestRegressor 187 >>> model = CurveStripper(RandomForestRegressor()) 188 >>> model.fit(X, y) 189 >>> print(regression_report(model, "RandomForest")) 190 """ 191 if not hasattr(model, 'curve_rates_'): 192 raise ValueError("Model must be fitted before generating report") 193 194 diagnostics = model.get_diagnostics() 195 196 metrics_data = { 197 'Metric': ['Samples', 'R²', 'RMSE', 'MAE', 'Min Error', 'Max Error'], 198 name: [ 199 diagnostics.n_samples, 200 f"{diagnostics.r2_score:.4f}", 201 f"{diagnostics.rmse:.4f}", 202 f"{diagnostics.mae:.4f}", 203 f"{diagnostics.min_error:.4f}", 204 f"{diagnostics.max_error:.4f}" 205 ] 206 } 207 208 summary_data = { 209 'Statistic': ['Mean', 'Std Dev', 'Median', 'MAD', 'Skewness', 'Kurtosis'], 210 name: [ 211 f"{diagnostics.residuals_summary['mean']:.4f}", 212 f"{diagnostics.residuals_summary['std']:.4f}", 213 f"{diagnostics.residuals_summary['median']:.4f}", 214 f"{diagnostics.residuals_summary['mad']:.4f}", 215 f"{diagnostics.residuals_summary['skewness']:.4f}", 216 f"{diagnostics.residuals_summary['kurtosis']:.4f}" 217 ] 218 } 219 220 percentiles_data = { 221 'Percentile': ['1%', '5%', '25%', '75%', '95%', '99%'], 222 name: [ 223 f"{diagnostics.residuals_summary['percentiles']['1%']:.4f}", 224 f"{diagnostics.residuals_summary['percentiles']['5%']:.4f}", 225 f"{diagnostics.residuals_summary['percentiles']['25%']:.4f}", 226 f"{diagnostics.residuals_summary['percentiles']['75%']:.4f}", 227 f"{diagnostics.residuals_summary['percentiles']['95%']:.4f}", 228 f"{diagnostics.residuals_summary['percentiles']['99%']:.4f}" 229 ] 230 } 231 232 metrics_df = pd.DataFrame(metrics_data) 233 summary_df = pd.DataFrame(summary_data) 234 percentiles_df = pd.DataFrame(percentiles_data) 235 236 report = ( 237 f"\nModel Performance Metrics:\n" 238 f"{tabulate(metrics_df, headers='keys', tablefmt='pipe', showindex=False)}\n\n" 239 f"Residuals Summary Statistics:\n" 240 f"{tabulate(summary_df, headers='keys', tablefmt='pipe', showindex=False)}\n\n" 241 f"Residuals Percentiles:\n" 242 f"{tabulate(percentiles_df, headers='keys', tablefmt='pipe', showindex=False)}" 243 ) 244 245 return report
Create a formatted report of regression diagnostics for a fitted CurveStripper model.
Parameters
model : CurveStripper Fitted CurveStripper model name : str, default="Model" Name to use for the model in the report
Returns
str Formatted report string
Examples
>>> from yieldcurveml.stripcurve import CurveStripper
>>> from sklearn.ensemble import RandomForestRegressor
>>> model = CurveStripper(RandomForestRegressor())
>>> model.fit(X, y)
>>> print(regression_report(model, "RandomForest"))