pub struct TrackingErrorAnalysis {Show 14 fields
pub tracking_error: f64,
pub tracking_error_annualized_daily: f64,
pub tracking_error_annualized_monthly: f64,
pub information_ratio: f64,
pub alpha: f64,
pub r_squared: f64,
pub correlation: f64,
pub rmse: f64,
pub mae: f64,
pub periods_above_1pct: f64,
pub periods_above_2pct: f64,
pub rolling_te: Option<Array1<f64>>,
pub n_obs: usize,
pub residuals: Array1<f64>,
}Expand description
Analysis of Tracking Error
Tracking error measures how much the return of um portfólio desvia of the return of um benchmark ou model.
Fields§
§tracking_error: f64Tracking error (standard deviation of the residuals)
tracking_error_annualized_daily: f64Tracking error annualized (daily)
tracking_error_annualized_monthly: f64Tracking error annualized (monthly)
information_ratio: f64Information ratio (alpha / tracking error)
alpha: f64Alpha of the model
r_squared: f64R² of the model
correlation: f64Correlação between returns obbevados and prevthiss
rmse: f64RMSE (Root Mean Squared Error)
mae: f64MAE (Mean Absolute Error)
periods_above_1pct: f64Proporção of periods with tracking error > 1%
periods_above_2pct: f64Proporção of periods with tracking error > 2%
rolling_te: Option<Array1<f64>>Rolling tracking error (window of 12 periods)
n_obs: usizeNumber of observations
residuals: Array1<f64>Residuals
Implementations§
Source§impl TrackingErrorAnalysis
impl TrackingErrorAnalysis
Sourcepub fn new(
actual_returns: &Array1<f64>,
fitted_values: &Array1<f64>,
alpha: f64,
r_squared: f64,
) -> Result<Self, GreenersError>
pub fn new( actual_returns: &Array1<f64>, fitted_values: &Array1<f64>, alpha: f64, r_squared: f64, ) -> Result<Self, GreenersError>
Creates analysis of tracking error
§Arguments
actual_returns- Returns obbevadosfitted_values- Returns prevthiss pelthe modelalpha- Alpha of the modelr_squared- R² of the model
§Example
use frenchrs::{CAPM, TrackingErrorAnalysis};
use greeners::CovarianceType;
use ndarray::array;
let asset = array![0.01, 0.02, -0.01, 0.03, 0.015, -0.005];
let market = array![0.008, 0.015, -0.005, 0.025, 0.012, -0.003];
let capm = CAPM::fit(&asset, &market, 0.0001, CovarianceType::HC3).unwrap();
let te = TrackingErrorAnalysis::new(
&asset,
&capm.fitted_values,
capm.alpha,
capm.r_squared
).unwrap();
assert!(te.tracking_error > 0.0);Examples found in repository?
examples/risk_analysis.rs (line 122)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("\n{}", "=".repeat(80));
9 println!("ANALYSIS OF RISCO: IVOL & TRACKING ERROR");
10 println!("{}", "=".repeat(80));
11
12 // ========================================================================
13 // DADOS SIMULADOS
14 // ========================================================================
15 let fund = array![
16 0.058, 0.042, -0.018, 0.082, 0.045, -0.032, 0.068, 0.052, -0.015, 0.062, 0.041, 0.075
17 ];
18 let market = array![
19 0.042, 0.030, -0.015, 0.060, 0.033, -0.025, 0.050, 0.038, -0.012, 0.045, 0.032, 0.055
20 ];
21 let smb = array![
22 0.008, -0.003, 0.012, 0.005, -0.007, 0.015, 0.002, -0.005, 0.010, 0.003, -0.004, 0.006
23 ];
24 let hml = array![
25 0.005, 0.008, -0.010, 0.012, 0.003, -0.006, 0.009, 0.004, -0.008, 0.011, 0.002, 0.007
26 ];
27 let mom = array![
28 0.012, 0.008, -0.015, 0.018, 0.010, -0.012, 0.015, 0.009, -0.010, 0.013, 0.007, 0.014
29 ];
30 let rmw = array![
31 0.006, 0.004, -0.005, 0.008, 0.003, -0.004, 0.007, 0.005, -0.003, 0.006, 0.004, 0.007
32 ];
33 let cma = array![
34 0.003, -0.002, 0.005, 0.002, -0.003, 0.004, 0.003, -0.002, 0.004, 0.003, -0.001, 0.003
35 ];
36
37 let rf = 0.03 / 12.0;
38
39 // ========================================================================
40 // ESTIMAÇÃO DOS MODELOS
41 // ========================================================================
42 println!("\nEstimatesndthe models...\n");
43
44 let capm = CAPM::fit(&fund, &market, rf, CovarianceType::HC3)?;
45 let ff3 = FamaFrench3Factor::fit(&fund, &market, &smb, &hml, rf, CovarianceType::HC3)?;
46 let carhart = Carhart4Factor::fit(&fund, &market, &smb, &hml, &mom, rf, CovarianceType::HC3)?;
47 let ff5 = FamaFrench5Factor::fit(
48 &fund,
49 &market,
50 &smb,
51 &hml,
52 &rmw,
53 &cma,
54 rf,
55 CovarianceType::HC3,
56 )?;
57
58 // ========================================================================
59 // ANALYSIS OF IVOL
60 // ========================================================================
61 println!("{}", "=".repeat(80));
62 println!("COMPARAÇÃO DE IVOL (IDIOSYNCRATIC VOLATILITY)");
63 println!("{}", "=".repeat(80));
64
65 let ivol_capm = IVOLAnalysis::from_residuals(&capm.residuals)?;
66 let ivol_ff3 = IVOLAnalysis::from_residuals(&ff3.residuals)?;
67 let ivol_carhart = IVOLAnalysis::from_residuals(&carhart.residuals)?;
68 let ivol_ff5 = IVOLAnalysis::from_residuals(&ff5.residuals)?;
69
70 println!(
71 "\n{:<20} {:>15} {:>20} {:>20}",
72 "Model", "IVOL", "IVOL Anual (Monthly)", "Classification"
73 );
74 println!("{}", "-".repeat(80));
75
76 println!(
77 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
78 "CAPM",
79 ivol_capm.ivol * 100.0,
80 ivol_capm.ivol_annualized_monthly * 100.0,
81 ivol_capm.ivol_classification()
82 );
83
84 println!(
85 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
86 "FF3",
87 ivol_ff3.ivol * 100.0,
88 ivol_ff3.ivol_annualized_monthly * 100.0,
89 ivol_ff3.ivol_classification()
90 );
91
92 println!(
93 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
94 "Carhart",
95 ivol_carhart.ivol * 100.0,
96 ivol_carhart.ivol_annualized_monthly * 100.0,
97 ivol_carhart.ivol_classification()
98 );
99
100 println!(
101 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
102 "FF5",
103 ivol_ff5.ivol * 100.0,
104 ivol_ff5.ivol_annualized_monthly * 100.0,
105 ivol_ff5.ivol_classification()
106 );
107
108 println!("\n{}", "-".repeat(80));
109 println!("INTERPRETATION:");
110 println!("• IVOL diminui à medida que adicionamos factors to the model");
111 println!("• Menor IVOL indica que the model explica better the returns");
112 println!("• IVOL representa the risk diversificável/específico of the asset");
113
114 // ========================================================================
115 // ANALYSIS OF TRACKING ERROR
116 // ========================================================================
117 println!("\n{}", "=".repeat(80));
118 println!("COMPARAÇÃO DE TRACKING ERROR");
119 println!("{}", "=".repeat(80));
120
121 let te_capm =
122 TrackingErrorAnalysis::new(&fund, &capm.fitted_values, capm.alpha, capm.r_squared)?;
123 let te_ff3 = TrackingErrorAnalysis::new(&fund, &ff3.fitted_values, ff3.alpha, ff3.r_squared)?;
124 let te_carhart = TrackingErrorAnalysis::new(
125 &fund,
126 &carhart.fitted_values,
127 carhart.alpha,
128 carhart.r_squared,
129 )?;
130 let te_ff5 = TrackingErrorAnalysis::new(&fund, &ff5.fitted_values, ff5.alpha, ff5.r_squared)?;
131
132 println!(
133 "\n{:<20} {:>12} {:>18} {:>18} {:>15}",
134 "Model", "TE", "TE Anual (Monthly)", "Info Ratio", "Classification"
135 );
136 println!("{}", "-".repeat(80));
137
138 println!(
139 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
140 "CAPM",
141 te_capm.tracking_error * 100.0,
142 te_capm.tracking_error_annualized_monthly * 100.0,
143 te_capm.information_ratio,
144 te_capm.te_classification()
145 );
146
147 println!(
148 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
149 "FF3",
150 te_ff3.tracking_error * 100.0,
151 te_ff3.tracking_error_annualized_monthly * 100.0,
152 te_ff3.information_ratio,
153 te_ff3.te_classification()
154 );
155
156 println!(
157 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
158 "Carhart",
159 te_carhart.tracking_error * 100.0,
160 te_carhart.tracking_error_annualized_monthly * 100.0,
161 te_carhart.information_ratio,
162 te_carhart.te_classification()
163 );
164
165 println!(
166 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
167 "FF5",
168 te_ff5.tracking_error * 100.0,
169 te_ff5.tracking_error_annualized_monthly * 100.0,
170 te_ff5.information_ratio,
171 te_ff5.te_classification()
172 );
173
174 println!("\n{}", "-".repeat(80));
175 println!("INTERPRETATION:");
176 println!("• Tracking Error measures o how much o fundo desvia of the model");
177 println!("• Information Ratio = Alpha / Tracking Error");
178 println!("• IR > 0.5 é considerado bom, > 1.0 é excelente");
179
180 // ========================================================================
181 // ANALYSIS OFTALHADA: CAPM
182 // ========================================================================
183 println!("\n{}", "=".repeat(80));
184 println!("ANALYSIS OFTALHADA: CAPM");
185 println!("{}", "=".repeat(80));
186
187 println!("{}", ivol_capm);
188 println!("{}", te_capm);
189
190 // ========================================================================
191 // ANALYSIS OFTALHADA: FAMA-FRENCH 5 FACTOR
192 // ========================================================================
193 println!("\n{}", "=".repeat(80));
194 println!("ANALYSIS OFTALHADA: FAMA-FRENCH 5 FACTOR");
195 println!("{}", "=".repeat(80));
196
197 println!("{}", ivol_ff5);
198 println!("{}", te_ff5);
199
200 // ========================================================================
201 // STATISTICS COMPARATIVAS Dthe residuals
202 // ========================================================================
203 println!("\n{}", "=".repeat(80));
204 println!("RESIDUAL STATISTICS");
205 println!("{}", "=".repeat(80));
206
207 println!(
208 "\n{:<20} {:>12} {:>12} {:>12} {:>12}",
209 "Model", "Mean", "Skewness", "Kurtosis", "Normal?"
210 );
211 println!("{}", "-".repeat(80));
212
213 println!(
214 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
215 "CAPM",
216 ivol_capm.residual_mean,
217 ivol_capm.residual_skewness,
218 ivol_capm.residual_kurtosis,
219 if ivol_capm.is_residuals_normal(0.05) {
220 "SIM"
221 } else {
222 "NÃO"
223 }
224 );
225
226 println!(
227 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
228 "FF3",
229 ivol_ff3.residual_mean,
230 ivol_ff3.residual_skewness,
231 ivol_ff3.residual_kurtosis,
232 if ivol_ff3.is_residuals_normal(0.05) {
233 "SIM"
234 } else {
235 "NÃO"
236 }
237 );
238
239 println!(
240 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
241 "Carhart",
242 ivol_carhart.residual_mean,
243 ivol_carhart.residual_skewness,
244 ivol_carhart.residual_kurtosis,
245 if ivol_carhart.is_residuals_normal(0.05) {
246 "SIM"
247 } else {
248 "NÃO"
249 }
250 );
251
252 println!(
253 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
254 "FF5",
255 ivol_ff5.residual_mean,
256 ivol_ff5.residual_skewness,
257 ivol_ff5.residual_kurtosis,
258 if ivol_ff5.is_residuals_normal(0.05) {
259 "SIM"
260 } else {
261 "NÃO"
262 }
263 );
264
265 println!("\n{}", "-".repeat(80));
266 println!("INTERPRETATION:");
267 println!("• Mean of the residuals should be próxima of zero");
268 println!("• Skewness measures assimetria (0 = simétrico)");
269 println!("• Kurtosis measures caudas pesadas (0 = normal)");
270 println!("• Test of normalidade: Jarque-Bera a 5%");
271
272 // ========================================================================
273 // METRICS DE FIT QUALITY
274 // ========================================================================
275 println!("\n{}", "=".repeat(80));
276 println!("FIT QUALITY");
277 println!("{}", "=".repeat(80));
278
279 println!(
280 "\n{:<20} {:>12} {:>12} {:>12} {:>12}",
281 "Model", "R²", "Correlação", "RMSE", "MAE"
282 );
283 println!("{}", "-".repeat(80));
284
285 println!(
286 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
287 "CAPM", te_capm.r_squared, te_capm.correlation, te_capm.rmse, te_capm.mae
288 );
289
290 println!(
291 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
292 "FF3", te_ff3.r_squared, te_ff3.correlation, te_ff3.rmse, te_ff3.mae
293 );
294
295 println!(
296 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
297 "Carhart", te_carhart.r_squared, te_carhart.correlation, te_carhart.rmse, te_carhart.mae
298 );
299
300 println!(
301 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
302 "FF5", te_ff5.r_squared, te_ff5.correlation, te_ff5.rmse, te_ff5.mae
303 );
304
305 println!("\n{}", "-".repeat(80));
306 println!("INTERPRETATION:");
307 println!("• R² = proportion of the variesnce explieach");
308 println!("• Correlação = relação linear between obbevado e prevthis");
309 println!("• RMSE = erro quadrático médio");
310 println!("• MAE = erro absoluto médio");
311
312 // ========================================================================
313 // CONCLUSÕES
314 // ========================================================================
315 println!("\n{}", "=".repeat(80));
316 println!("CONCLUSÕES");
317 println!("{}", "=".repeat(80));
318
319 println!("\n1. EVOLUÇÃO DO IVOL:");
320 println!(
321 " • CAPM: {:.2}% (annualized)",
322 ivol_capm.ivol_annualized_monthly * 100.0
323 );
324 println!(
325 " • FF5: {:.2}% (annualized)",
326 ivol_ff5.ivol_annualized_monthly * 100.0
327 );
328 println!(
329 " • Redução: {:.2} pontos percentuais",
330 (ivol_capm.ivol_annualized_monthly - ivol_ff5.ivol_annualized_monthly) * 100.0
331 );
332
333 println!("\n2. INFORMATION RATIO:");
334 println!(" • CAPM: {:.4}", te_capm.information_ratio);
335 println!(" • FF5: {:.4}", te_ff5.information_ratio);
336 println!(
337 " • Melhor model por IR: {}",
338 if te_ff5.information_ratio.abs() > te_capm.information_ratio.abs() {
339 "FF5"
340 } else {
341 "CAPM"
342 }
343 );
344
345 println!("\n3. DISTRIBUIÇÃO Dthe residuals:");
346 println!(
347 " • Models with residuals normore: {}",
348 [
349 ("CAPM", ivol_capm.is_residuals_normal(0.05)),
350 ("FF3", ivol_ff3.is_residuals_normal(0.05)),
351 ("Carhart", ivol_carhart.is_residuals_normal(0.05)),
352 ("FF5", ivol_ff5.is_residuals_normal(0.05))
353 ]
354 .iter()
355 .filter(|(_, is_normal)| *is_normal)
356 .map(|(name, _)| *name)
357 .collect::<Vec<&str>>()
358 .join(", ")
359 );
360
361 println!("\n4. RECOMENDAÇÃO:");
362 if ivol_ff5.ivol < ivol_capm.ivol * 0.8 {
363 println!(" • FF5 reduz significantly o IVOL (>20%)");
364 println!(" • Recomenda-if usar FF5 for better explicação of the returns");
365 } else {
366 println!(" • Ganho marginal with models multi-fatoriais");
367 println!(" • CAPM can be suficiente for this asset");
368 }
369
370 println!("\n{}", "=".repeat(80));
371
372 Ok(())
373}Sourcepub fn te_classification(&self) -> &str
pub fn te_classification(&self) -> &str
Classifies the level of tracking error
Examples found in repository?
examples/risk_analysis.rs (line 144)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("\n{}", "=".repeat(80));
9 println!("ANALYSIS OF RISCO: IVOL & TRACKING ERROR");
10 println!("{}", "=".repeat(80));
11
12 // ========================================================================
13 // DADOS SIMULADOS
14 // ========================================================================
15 let fund = array![
16 0.058, 0.042, -0.018, 0.082, 0.045, -0.032, 0.068, 0.052, -0.015, 0.062, 0.041, 0.075
17 ];
18 let market = array![
19 0.042, 0.030, -0.015, 0.060, 0.033, -0.025, 0.050, 0.038, -0.012, 0.045, 0.032, 0.055
20 ];
21 let smb = array![
22 0.008, -0.003, 0.012, 0.005, -0.007, 0.015, 0.002, -0.005, 0.010, 0.003, -0.004, 0.006
23 ];
24 let hml = array![
25 0.005, 0.008, -0.010, 0.012, 0.003, -0.006, 0.009, 0.004, -0.008, 0.011, 0.002, 0.007
26 ];
27 let mom = array![
28 0.012, 0.008, -0.015, 0.018, 0.010, -0.012, 0.015, 0.009, -0.010, 0.013, 0.007, 0.014
29 ];
30 let rmw = array![
31 0.006, 0.004, -0.005, 0.008, 0.003, -0.004, 0.007, 0.005, -0.003, 0.006, 0.004, 0.007
32 ];
33 let cma = array![
34 0.003, -0.002, 0.005, 0.002, -0.003, 0.004, 0.003, -0.002, 0.004, 0.003, -0.001, 0.003
35 ];
36
37 let rf = 0.03 / 12.0;
38
39 // ========================================================================
40 // ESTIMAÇÃO DOS MODELOS
41 // ========================================================================
42 println!("\nEstimatesndthe models...\n");
43
44 let capm = CAPM::fit(&fund, &market, rf, CovarianceType::HC3)?;
45 let ff3 = FamaFrench3Factor::fit(&fund, &market, &smb, &hml, rf, CovarianceType::HC3)?;
46 let carhart = Carhart4Factor::fit(&fund, &market, &smb, &hml, &mom, rf, CovarianceType::HC3)?;
47 let ff5 = FamaFrench5Factor::fit(
48 &fund,
49 &market,
50 &smb,
51 &hml,
52 &rmw,
53 &cma,
54 rf,
55 CovarianceType::HC3,
56 )?;
57
58 // ========================================================================
59 // ANALYSIS OF IVOL
60 // ========================================================================
61 println!("{}", "=".repeat(80));
62 println!("COMPARAÇÃO DE IVOL (IDIOSYNCRATIC VOLATILITY)");
63 println!("{}", "=".repeat(80));
64
65 let ivol_capm = IVOLAnalysis::from_residuals(&capm.residuals)?;
66 let ivol_ff3 = IVOLAnalysis::from_residuals(&ff3.residuals)?;
67 let ivol_carhart = IVOLAnalysis::from_residuals(&carhart.residuals)?;
68 let ivol_ff5 = IVOLAnalysis::from_residuals(&ff5.residuals)?;
69
70 println!(
71 "\n{:<20} {:>15} {:>20} {:>20}",
72 "Model", "IVOL", "IVOL Anual (Monthly)", "Classification"
73 );
74 println!("{}", "-".repeat(80));
75
76 println!(
77 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
78 "CAPM",
79 ivol_capm.ivol * 100.0,
80 ivol_capm.ivol_annualized_monthly * 100.0,
81 ivol_capm.ivol_classification()
82 );
83
84 println!(
85 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
86 "FF3",
87 ivol_ff3.ivol * 100.0,
88 ivol_ff3.ivol_annualized_monthly * 100.0,
89 ivol_ff3.ivol_classification()
90 );
91
92 println!(
93 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
94 "Carhart",
95 ivol_carhart.ivol * 100.0,
96 ivol_carhart.ivol_annualized_monthly * 100.0,
97 ivol_carhart.ivol_classification()
98 );
99
100 println!(
101 "{:<20} {:>14.4}% {:>19.2}% {:>20}",
102 "FF5",
103 ivol_ff5.ivol * 100.0,
104 ivol_ff5.ivol_annualized_monthly * 100.0,
105 ivol_ff5.ivol_classification()
106 );
107
108 println!("\n{}", "-".repeat(80));
109 println!("INTERPRETATION:");
110 println!("• IVOL diminui à medida que adicionamos factors to the model");
111 println!("• Menor IVOL indica que the model explica better the returns");
112 println!("• IVOL representa the risk diversificável/específico of the asset");
113
114 // ========================================================================
115 // ANALYSIS OF TRACKING ERROR
116 // ========================================================================
117 println!("\n{}", "=".repeat(80));
118 println!("COMPARAÇÃO DE TRACKING ERROR");
119 println!("{}", "=".repeat(80));
120
121 let te_capm =
122 TrackingErrorAnalysis::new(&fund, &capm.fitted_values, capm.alpha, capm.r_squared)?;
123 let te_ff3 = TrackingErrorAnalysis::new(&fund, &ff3.fitted_values, ff3.alpha, ff3.r_squared)?;
124 let te_carhart = TrackingErrorAnalysis::new(
125 &fund,
126 &carhart.fitted_values,
127 carhart.alpha,
128 carhart.r_squared,
129 )?;
130 let te_ff5 = TrackingErrorAnalysis::new(&fund, &ff5.fitted_values, ff5.alpha, ff5.r_squared)?;
131
132 println!(
133 "\n{:<20} {:>12} {:>18} {:>18} {:>15}",
134 "Model", "TE", "TE Anual (Monthly)", "Info Ratio", "Classification"
135 );
136 println!("{}", "-".repeat(80));
137
138 println!(
139 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
140 "CAPM",
141 te_capm.tracking_error * 100.0,
142 te_capm.tracking_error_annualized_monthly * 100.0,
143 te_capm.information_ratio,
144 te_capm.te_classification()
145 );
146
147 println!(
148 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
149 "FF3",
150 te_ff3.tracking_error * 100.0,
151 te_ff3.tracking_error_annualized_monthly * 100.0,
152 te_ff3.information_ratio,
153 te_ff3.te_classification()
154 );
155
156 println!(
157 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
158 "Carhart",
159 te_carhart.tracking_error * 100.0,
160 te_carhart.tracking_error_annualized_monthly * 100.0,
161 te_carhart.information_ratio,
162 te_carhart.te_classification()
163 );
164
165 println!(
166 "{:<20} {:>11.4}% {:>17.2}% {:>18.4} {:>15}",
167 "FF5",
168 te_ff5.tracking_error * 100.0,
169 te_ff5.tracking_error_annualized_monthly * 100.0,
170 te_ff5.information_ratio,
171 te_ff5.te_classification()
172 );
173
174 println!("\n{}", "-".repeat(80));
175 println!("INTERPRETATION:");
176 println!("• Tracking Error measures o how much o fundo desvia of the model");
177 println!("• Information Ratio = Alpha / Tracking Error");
178 println!("• IR > 0.5 é considerado bom, > 1.0 é excelente");
179
180 // ========================================================================
181 // ANALYSIS OFTALHADA: CAPM
182 // ========================================================================
183 println!("\n{}", "=".repeat(80));
184 println!("ANALYSIS OFTALHADA: CAPM");
185 println!("{}", "=".repeat(80));
186
187 println!("{}", ivol_capm);
188 println!("{}", te_capm);
189
190 // ========================================================================
191 // ANALYSIS OFTALHADA: FAMA-FRENCH 5 FACTOR
192 // ========================================================================
193 println!("\n{}", "=".repeat(80));
194 println!("ANALYSIS OFTALHADA: FAMA-FRENCH 5 FACTOR");
195 println!("{}", "=".repeat(80));
196
197 println!("{}", ivol_ff5);
198 println!("{}", te_ff5);
199
200 // ========================================================================
201 // STATISTICS COMPARATIVAS Dthe residuals
202 // ========================================================================
203 println!("\n{}", "=".repeat(80));
204 println!("RESIDUAL STATISTICS");
205 println!("{}", "=".repeat(80));
206
207 println!(
208 "\n{:<20} {:>12} {:>12} {:>12} {:>12}",
209 "Model", "Mean", "Skewness", "Kurtosis", "Normal?"
210 );
211 println!("{}", "-".repeat(80));
212
213 println!(
214 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
215 "CAPM",
216 ivol_capm.residual_mean,
217 ivol_capm.residual_skewness,
218 ivol_capm.residual_kurtosis,
219 if ivol_capm.is_residuals_normal(0.05) {
220 "SIM"
221 } else {
222 "NÃO"
223 }
224 );
225
226 println!(
227 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
228 "FF3",
229 ivol_ff3.residual_mean,
230 ivol_ff3.residual_skewness,
231 ivol_ff3.residual_kurtosis,
232 if ivol_ff3.is_residuals_normal(0.05) {
233 "SIM"
234 } else {
235 "NÃO"
236 }
237 );
238
239 println!(
240 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
241 "Carhart",
242 ivol_carhart.residual_mean,
243 ivol_carhart.residual_skewness,
244 ivol_carhart.residual_kurtosis,
245 if ivol_carhart.is_residuals_normal(0.05) {
246 "SIM"
247 } else {
248 "NÃO"
249 }
250 );
251
252 println!(
253 "{:<20} {:>12.6} {:>12.4} {:>12.4} {:>12}",
254 "FF5",
255 ivol_ff5.residual_mean,
256 ivol_ff5.residual_skewness,
257 ivol_ff5.residual_kurtosis,
258 if ivol_ff5.is_residuals_normal(0.05) {
259 "SIM"
260 } else {
261 "NÃO"
262 }
263 );
264
265 println!("\n{}", "-".repeat(80));
266 println!("INTERPRETATION:");
267 println!("• Mean of the residuals should be próxima of zero");
268 println!("• Skewness measures assimetria (0 = simétrico)");
269 println!("• Kurtosis measures caudas pesadas (0 = normal)");
270 println!("• Test of normalidade: Jarque-Bera a 5%");
271
272 // ========================================================================
273 // METRICS DE FIT QUALITY
274 // ========================================================================
275 println!("\n{}", "=".repeat(80));
276 println!("FIT QUALITY");
277 println!("{}", "=".repeat(80));
278
279 println!(
280 "\n{:<20} {:>12} {:>12} {:>12} {:>12}",
281 "Model", "R²", "Correlação", "RMSE", "MAE"
282 );
283 println!("{}", "-".repeat(80));
284
285 println!(
286 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
287 "CAPM", te_capm.r_squared, te_capm.correlation, te_capm.rmse, te_capm.mae
288 );
289
290 println!(
291 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
292 "FF3", te_ff3.r_squared, te_ff3.correlation, te_ff3.rmse, te_ff3.mae
293 );
294
295 println!(
296 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
297 "Carhart", te_carhart.r_squared, te_carhart.correlation, te_carhart.rmse, te_carhart.mae
298 );
299
300 println!(
301 "{:<20} {:>12.4} {:>12.4} {:>12.6} {:>12.6}",
302 "FF5", te_ff5.r_squared, te_ff5.correlation, te_ff5.rmse, te_ff5.mae
303 );
304
305 println!("\n{}", "-".repeat(80));
306 println!("INTERPRETATION:");
307 println!("• R² = proportion of the variesnce explieach");
308 println!("• Correlação = relação linear between obbevado e prevthis");
309 println!("• RMSE = erro quadrático médio");
310 println!("• MAE = erro absoluto médio");
311
312 // ========================================================================
313 // CONCLUSÕES
314 // ========================================================================
315 println!("\n{}", "=".repeat(80));
316 println!("CONCLUSÕES");
317 println!("{}", "=".repeat(80));
318
319 println!("\n1. EVOLUÇÃO DO IVOL:");
320 println!(
321 " • CAPM: {:.2}% (annualized)",
322 ivol_capm.ivol_annualized_monthly * 100.0
323 );
324 println!(
325 " • FF5: {:.2}% (annualized)",
326 ivol_ff5.ivol_annualized_monthly * 100.0
327 );
328 println!(
329 " • Redução: {:.2} pontos percentuais",
330 (ivol_capm.ivol_annualized_monthly - ivol_ff5.ivol_annualized_monthly) * 100.0
331 );
332
333 println!("\n2. INFORMATION RATIO:");
334 println!(" • CAPM: {:.4}", te_capm.information_ratio);
335 println!(" • FF5: {:.4}", te_ff5.information_ratio);
336 println!(
337 " • Melhor model por IR: {}",
338 if te_ff5.information_ratio.abs() > te_capm.information_ratio.abs() {
339 "FF5"
340 } else {
341 "CAPM"
342 }
343 );
344
345 println!("\n3. DISTRIBUIÇÃO Dthe residuals:");
346 println!(
347 " • Models with residuals normore: {}",
348 [
349 ("CAPM", ivol_capm.is_residuals_normal(0.05)),
350 ("FF3", ivol_ff3.is_residuals_normal(0.05)),
351 ("Carhart", ivol_carhart.is_residuals_normal(0.05)),
352 ("FF5", ivol_ff5.is_residuals_normal(0.05))
353 ]
354 .iter()
355 .filter(|(_, is_normal)| *is_normal)
356 .map(|(name, _)| *name)
357 .collect::<Vec<&str>>()
358 .join(", ")
359 );
360
361 println!("\n4. RECOMENDAÇÃO:");
362 if ivol_ff5.ivol < ivol_capm.ivol * 0.8 {
363 println!(" • FF5 reduz significantly o IVOL (>20%)");
364 println!(" • Recomenda-if usar FF5 for better explicação of the returns");
365 } else {
366 println!(" • Ganho marginal with models multi-fatoriais");
367 println!(" • CAPM can be suficiente for this asset");
368 }
369
370 println!("\n{}", "=".repeat(80));
371
372 Ok(())
373}Sourcepub fn ir_classification(&self) -> &str
pub fn ir_classification(&self) -> &str
Classifies the information ratio
Trait Implementations§
Source§impl Clone for TrackingErrorAnalysis
impl Clone for TrackingErrorAnalysis
Source§fn clone(&self) -> TrackingErrorAnalysis
fn clone(&self) -> TrackingErrorAnalysis
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for TrackingErrorAnalysis
impl Debug for TrackingErrorAnalysis
Auto Trait Implementations§
impl Freeze for TrackingErrorAnalysis
impl RefUnwindSafe for TrackingErrorAnalysis
impl Send for TrackingErrorAnalysis
impl Sync for TrackingErrorAnalysis
impl Unpin for TrackingErrorAnalysis
impl UnsafeUnpin for TrackingErrorAnalysis
impl UnwindSafe for TrackingErrorAnalysis
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.