Skip to main content

TrackingErrorAnalysis

Struct TrackingErrorAnalysis 

Source
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: f64

Tracking error (standard deviation of the residuals)

§tracking_error_annualized_daily: f64

Tracking error annualized (daily)

§tracking_error_annualized_monthly: f64

Tracking error annualized (monthly)

§information_ratio: f64

Information ratio (alpha / tracking error)

§alpha: f64

Alpha of the model

§r_squared: f64

R² of the model

§correlation: f64

Correlação between returns obbevados and prevthiss

§rmse: f64

RMSE (Root Mean Squared Error)

§mae: f64

MAE (Mean Absolute Error)

§periods_above_1pct: f64

Proporção of periods with tracking error > 1%

§periods_above_2pct: f64

Proporção of periods with tracking error > 2%

§rolling_te: Option<Array1<f64>>

Rolling tracking error (window of 12 periods)

§n_obs: usize

Number of observations

§residuals: Array1<f64>

Residuals

Implementations§

Source§

impl TrackingErrorAnalysis

Source

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 obbevados
  • fitted_values - Returns prevthiss pelthe model
  • alpha - Alpha of the model
  • r_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}
Source

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}
Source

pub fn ir_classification(&self) -> &str

Classifies the information ratio

Trait Implementations§

Source§

impl Clone for TrackingErrorAnalysis

Source§

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)

Performs copy-assignment from source. Read more
Source§

impl Debug for TrackingErrorAnalysis

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for TrackingErrorAnalysis

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

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

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> ToStringFallible for T
where T: Display,

Source§

fn try_to_string(&self) -> Result<String, TryReserveError>

ToString::to_string, but without panic on OOM.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more