Considerações sobre Random Forest em simulação relacionada às finanças

 

Análise de Modelos

Random Forest

Bibliotecas necessárias

Code
library(randomForest)
randomForest 4.7-1.2
Type rfNews() to see new features/changes/bug fixes.
Code
library(tidyr)
library(rpart)
library(glmnet)
Carregando pacotes exigidos: Matrix

Anexando pacote: 'Matrix'
Os seguintes objetos são mascarados por 'package:tidyr':

    expand, pack, unpack
Loaded glmnet 4.1-10
Code
options(scipen = 999)

Base de dados

Code
source("C:/Users/Thomas/Desktop/FGC/Códigos/Base de dados.R")

Modelando Random Forest

Ajustando Modelo

Code
rf_fit <- randomForest(
  retorno ~ .,   
  data = df_retorno,
  ntree = 500,
  mtry = floor(sqrt(ncol(df_retorno) - 1)),
  maxnodes = 50,
  importance = TRUE,
  na.action = na.omit
)

#| label: setup

library(rpart)
library(randomForest)

# split
set.seed(123)
idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))
train <- df_retorno[idx, ]
test  <- df_retorno[-idx, ]

# árvore
tree_single <- rpart(retorno ~ ., data = train)
pred_tree_test <- predict(tree_single, newdata = test)

Primeiros resultados

Resumo do modelo

Code
rf_fit

Call:
 randomForest(formula = retorno ~ ., data = df_retorno, ntree = 500,      mtry = floor(sqrt(ncol(df_retorno) - 1)), maxnodes = 50,      importance = TRUE, na.action = na.omit) 
               Type of random forest: regression
                     Number of trees: 500
No. of variables tried at each split: 5

          Mean of squared residuals: 0.001508512
                    % Var explained: 50.3

Importância das variáveis

Code
importance_mdi <- importance(rf_fit, type = 1)
importance_df <- data.frame(
  variavel = rownames(importance_mdi),
  importancia = importance_mdi[,1]
)

importance_df <- importance_df[order(-importance_df$importancia), ]

importance_df
                               variavel importancia
crescimento_lucro     crescimento_lucro  12.6348315
pe_ratio                       pe_ratio  11.6867617
retorno_12m                 retorno_12m  10.0517246
roe                                 roe   8.1181106
margem_liquida           margem_liquida   7.0453340
setor                             setor   6.8652137
margem_bruta               margem_bruta   6.2803747
alavancagem                 alavancagem   6.0778847
market_cap                   market_cap   5.4127845
tamanho                         tamanho   5.0502150
roa                                 roa   4.8228949
pb_ratio                       pb_ratio   4.5521337
retorno_6m                   retorno_6m   4.0749226
giro_ativos                 giro_ativos   3.9117809
volume_medio               volume_medio   3.8245617
setorEnergia               setorEnergia   3.8105361
setorIndustria           setorIndustria   3.7688328
liq_diaria                   liq_diaria   3.2946993
free_float                   free_float   2.6944693
price_sales                 price_sales   2.2431753
intensidade_capital intensidade_capital   1.8912538
capex_receita             capex_receita   1.8306600
setorFinanceiro         setorFinanceiro   1.7382822
setorTecnologia         setorTecnologia   1.5637343
volatilidade               volatilidade   1.1178894
retorno_1m                   retorno_1m   0.9946446
ev_ebitda                     ev_ebitda   0.9341098
cobertura_juros         cobertura_juros   0.8793166
crescimento_receita crescimento_receita   0.4668721
beta_mercado               beta_mercado   0.4192277
dividend_yield           dividend_yield   0.4008306
downside_risk             downside_risk   0.1129489
turnover                       turnover  -0.1852425
payout                           payout  -1.3098328
Code
par(cex = 0.6)

varImpPlot(
  rf_fit,
  type = 2,
  main = "Importância de Variáveis (Permutação)",
  cex = 0.5,
  cex.axis = 0.5
)

Falha ao fazer o upload do arquivo "". Invalid response: Error code = 7, Path = /_/BloggerUi/data/batchexecute, Message = There was an error during the transport or processing of this request., Unknown HTTP error in underlying XHR (HTTP Status: 0) (XHR Error Code: 6) (XHR Error Message: ' [0]')


Explicação

Regressão:

“Cada 1 ponto de ROE aumenta retorno em 0.5%”

Random Forest:

“Empresas com ROE alto têm retorno maior — mas o efeito depende do contexto”

ROE é importante NÃO diz quanto ele aumenta o retorno

Regressão mede “quanto muda” Random forest mede “o que importa”

Fazendo Previsões

Code
set.seed(123)
idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))

train <- df_retorno[idx, ]
test  <- df_retorno[-idx, ]
tree_single <- rpart(retorno ~ ., data = train)
rf_fit <- randomForest(
  retorno ~ .,
  data = train,
  ntree = 500,
  mtry = floor(sqrt(ncol(train) - 1))
)

pred_test <- predict(rf_fit, newdata = test)

rmse <- sqrt(mean((test$retorno - pred_test)^2))
r2 <- cor(test$retorno, pred_test)^2

paste("RMSE = ",rmse)
[1] "RMSE =  0.0385210612043032"
Code
paste("R² = ",r2)
[1] "R² =  0.600250808531214"
Code
plot(sqrt(rf_fit$mse), type = "l",
     xlab = "Número de árvores",
     ylab = "RMSE (OOB)",
     main = "RMSE vs Número de Árvores")



Code
plot(test$retorno, pred_test,
     xlab = "Retorno Real",
     ylab = "Retorno Previsto",
     main = "Previsto vs Real (Out-of-Sample)")
abline(0, 1, col = "red", lwd = 2)

Explicação

  • Eixo X (horizontal) → retorno real

  • Eixo Y (vertical) → retorno previsto pelo modelo

Cada ponto = uma empresa no conjunto de teste

Se o modelo fosse perfeito:

  • todos os pontos estariam exatamente sobre a linha
  • valores altos (ex: 0.20) → o modelo prevê menos que isso
  • valores baixos → o modelo prevê mais que isso

Isso significa:

o modelo está “puxando tudo para a média”. O modelo está sendo: Conservador

  • subestima retornos muito altos

  • superestima retornos muito baixos

Isso é típico de random forest. Porque o random forest faz:

média de várias árvores

E cada árvore prevê:

média dos valores dentro de uma região

Comparando com árvore individual

Estimando árvore individual

Code
tree_single <- rpart(retorno ~ ., data = train,
 control = rpart.control(maxdepth = 7))

pred_tree_single <- predict(tree_single, newdata = test)

rmse_tree_single <- sqrt(mean((test$retorno - pred_tree_test)^2))

r2_ar <- cor(test$retorno, pred_tree_single)^2
r2_ar
[1] 0.3535545

Resultado da árvore individual

Code
paste("RMSE = ", rmse_tree_single)
[1] "RMSE =  0.0531672818463887"

Comparando resultados

Code
# Comparação
cat("RMSE Árvore Individual:", rmse_tree_single, "
")
RMSE Árvore Individual: 0.05316728 
Code
cat("RMSE Random Forest: ", rmse, "
")
RMSE Random Forest:  0.03852106 
Code
cat("Redução relativa: ",
 round(100 * (rmse_tree_single - rmse) / rmse_tree_single, 2), "%
")
Redução relativa:  27.55 %

Explicação

A árvore individual, ao ser avaliada corretamente (out-of-sample), revelou sua fragilidade:

  • alta sensibilidade aos dados de treino

  • captura de ruído

O Random Forest, ao agregar múltiplas árvores:

suaviza flutuações idiossincráticas → previsões mais estáveis

Uma redução de ~28% no RMSE não é trivial.

Em muitos contextos aplicados (especialmente financeiros, como sugere sua variável retorno):

isso representa um ganho preditivo bastante relevante

Estimando a quantidade ideal de árvores

Estimando quantidade ideal

Code
ntrees <- seq(10, 300, by = 10)  # espaço de busca global
n_rep  <- 20                     # número de repetições

rmse_mat <- matrix(NA, nrow = length(ntrees), ncol = n_rep)

set.seed(123)

for (j in 1:n_rep) {
  
  idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))
  train <- df_retorno[idx, ]
  test  <- df_retorno[-idx, ]
  
  for (i in seq_along(ntrees)) {
    
    rf_temp <- randomForest(
      retorno ~ .,
      data = train,
      ntree = ntrees[i],
      mtry = floor(sqrt(ncol(train) - 1))
    )
    
    pred <- predict(rf_temp, newdata = test)
    
    rmse_mat[i, j] <- sqrt(mean((test$retorno - pred)^2))
  }
}

Resultados

Code
rmse_mean <- rowMeans(rmse_mat)
rmse_sd   <- apply(rmse_mat, 1, sd)

best_ntree_global <- ntrees[which.min(rmse_mean)]

cat("Ótimo global (esperado):", best_ntree_global, "\n")
Ótimo global (esperado): 210 
Code
cat("RMSE no ótimo global:", min(rmse_mean), "\n")
RMSE no ótimo global: 0.03900742 
Code
plot(ntrees, rmse_mean, type = "l",
     xlab = "Número de árvores",
     ylab = "RMSE médio (teste)",
     main = "RMSE esperado vs Número de Árvores")

lines(ntrees, rmse_mean + rmse_sd, lty = 2)
lines(ntrees, rmse_mean - rmse_sd, lty = 2)

abline(v = best_ntree_global, col = "red", lty = 2)
points(best_ntree_global,
       min(rmse_mean),
       col = "red", pch = 19)



Outros Resultados

Retorno esperado x var. importantes

Retorno esperado com base em variáveis selecionadas.

Code
partialPlot(rf_fit, df_retorno, "roe")



Code
partialPlot(rf_fit, df_retorno, "pe_ratio")



Code
partialPlot(rf_fit, df_retorno, "crescimento_lucro")



Code
partialPlot(rf_fit, df_retorno, "volatilidade")



Code
partialPlot(rf_fit, df_retorno, "alavancagem")



Code
partialPlot(rf_fit, df_retorno, "tamanho")



Melhores empresas

Previsão com base em random forest.

Code
pred_all <- predict(rf_fit, newdata = df_retorno)
ranking <- df_retorno[order(-pred_all), ]

head(ranking, 10)   # Top 10
    retorno   roe   roa margem_liquida margem_bruta crescimento_receita
118   0.224 0.185 0.129          0.134        0.421               0.224
31    0.222 0.179 0.112          0.124        0.447               0.202
72    0.218 0.177 0.137          0.180        0.425               0.107
34    0.212 0.163 0.107          0.198        0.399               0.054
74    0.200 0.198 0.097          0.125        0.380               0.142
51    0.204 0.167 0.092          0.127        0.498               0.197
33    0.212 0.197 0.131          0.159        0.450               0.061
100   0.193 0.217 0.177          0.181        0.535               0.113
110   0.187 0.183 0.120          0.149        0.493               0.103
24    0.176 0.213 0.097          0.118        0.365               0.206
    crescimento_lucro payout dividend_yield alavancagem cobertura_juros
118             0.231   0.42          0.045        1.58            6.84
31              0.204   0.13          0.019        1.32            6.05
72              0.151   0.08          0.025        1.15            8.34
34              0.164   0.50          0.051        1.07            8.47
74              0.185   0.25          0.020        0.87            6.06
51              0.207   0.51          0.048        1.21            6.02
33              0.204   0.52          0.052        0.99            7.71
100             0.267   0.26          0.024        0.54            8.72
110             0.160   0.61          0.058        0.97            8.36
24              0.237   0.72          0.067        1.27            4.74
    pe_ratio pb_ratio ev_ebitda price_sales tamanho  market_cap free_float
118    45.00     3.31     14.58        6.85    9.68  4778435222       0.42
31     45.00     3.80     10.70        6.90    9.56  3650203775       0.46
72     44.86     3.36      3.00        2.61    9.94  8793566444       0.23
34     45.00     2.56      6.32        0.85    9.58  3819773952       0.38
74     45.00     2.77      8.65        2.62    9.86  7231846827       0.41
51     45.00     1.99     10.98        5.76    9.80  6270866003       0.51
33     45.00     4.69      8.54        1.58    9.97  9330565767       0.42
100    45.00     5.42      4.10        3.45   10.15 14203155127       0.40
110    40.77     2.93      7.53        1.44    9.56  3666951679       0.44
24     45.00     2.94      9.84        6.88    9.07  1162869303       0.35
    liq_diaria volume_medio turnover beta_mercado volatilidade downside_risk
118    7119876      6384998    0.005         0.36        0.260         0.280
31    27032817     21021346    0.011         0.30        0.232         0.311
72    30036673     24913998    0.006         1.32        0.328         0.275
34    10410787      6367443    0.005         0.30        0.126         0.214
74    31850550     29777151    0.005         0.30        0.139         0.247
51    50778855     80996548    0.005         0.76        0.276         0.261
33    12784375     18517269    0.007         0.89        0.329         0.335
100   67495852     60500488    0.008         1.09        0.301         0.306
110   16369725     12923027    0.005         0.30        0.148         0.185
24     6298821      4963078    0.013         0.48        0.294         0.328
    retorno_1m retorno_6m retorno_12m intensidade_capital capex_receita
118      0.141      0.304       0.332                0.52         0.116
31       0.015      0.197       0.044                0.49         0.093
72       0.098      0.220       0.289                0.52         0.077
34       0.058      0.169       0.376                0.46         0.094
74       0.107      0.236       0.233                0.29         0.064
51       0.018      0.100       0.306                0.49         0.083
33       0.142      0.186       0.281                0.32         0.056
100      0.039      0.175       0.303                0.37         0.035
110      0.066      0.354       0.236                0.43         0.091
24       0.180      0.203       0.261                0.60         0.112
    giro_ativos      setor setorEnergia setorFinanceiro setorIndustria
118        1.05    Energia            1               0              0
31         1.23    Energia            1               0              0
72         1.42 Tecnologia            0               0              0
34         1.60 Financeiro            0               1              0
74         1.52    Consumo            0               0              0
51         1.28    Consumo            0               0              0
33         1.47 Financeiro            0               1              0
100        1.72 Tecnologia            0               0              0
110        1.46    Consumo            0               0              0
24         1.17    Energia            1               0              0
    setorTecnologia
118               0
31                0
72                1
34                0
74                0
51                0
33                0
100               1
110               0
24                0
Code
tail(ranking, 10)   # Bottom 10
    retorno   roe   roa margem_liquida margem_bruta crescimento_receita
64    0.041 0.109 0.068          0.087        0.368               0.058
123   0.025 0.168 0.089          0.137        0.388               0.067
76    0.049 0.039 0.016          0.038        0.177               0.016
125   0.010 0.128 0.070          0.126        0.392               0.079
35    0.040 0.090 0.057          0.049        0.317               0.104
81    0.027 0.092 0.016          0.061        0.223               0.079
79    0.029 0.080 0.037          0.113        0.270               0.119
83    0.024 0.092 0.052          0.076        0.270               0.121
36    0.007 0.036 0.054          0.085        0.261               0.041
41    0.015 0.074 0.051          0.052        0.247               0.108
    crescimento_lucro payout dividend_yield alavancagem cobertura_juros
64              0.095   0.36          0.031        1.85            5.95
123             0.107   0.48          0.056        1.47            4.98
76              0.040   0.71          0.074        2.03            4.10
125             0.109   0.55          0.041        1.63            5.55
35              0.100   0.32          0.038        1.89            7.09
81              0.099   0.59          0.063        1.65            4.96
79              0.098   0.25          0.027        1.86            4.44
83              0.097   0.37          0.035        2.19            4.65
36              0.058   0.36          0.045        1.75            4.99
41              0.038   0.35          0.051        2.00            5.04
    pe_ratio pb_ratio ev_ebitda price_sales tamanho  market_cap free_float
64     11.23     1.17      8.30        2.36    9.57  3723545599       0.50
123    23.13     3.72      4.02        2.33   10.25 17619344430       0.33
76      4.00     0.40      7.19        0.30    9.78  6057781590       0.32
125    18.02     2.52      5.16        1.69    9.10  1247425146       0.21
35      9.04     0.40      8.85        3.15   10.31 20243199524       0.54
81      8.65     1.75      4.55        1.52    9.92  8354646277       0.51
79     10.57     0.40      9.45        3.10   10.49 31094360875       0.45
83      6.04     0.51     15.30        2.35    9.84  6950550894       0.29
36      4.00     0.40      5.15        0.30    9.53  3405403137       0.26
41      4.00     0.72      8.31        3.27   10.46 28760739176       0.69
    liq_diaria volume_medio turnover beta_mercado volatilidade downside_risk
64    13002352     10265137    0.005         0.30        0.217         0.192
123   49700043     53625653    0.005         1.27        0.366         0.283
76    33149709     36368526    0.005         0.55        0.275         0.229
125    2573619      3203734    0.005         1.26        0.334         0.343
35    49034464     43855250    0.005         1.38        0.340         0.360
81    81506966     75941006    0.005         0.71        0.263         0.270
79   100995342    123089245    0.006         1.61        0.379         0.344
83    14112619     19112091    0.005         0.74        0.299         0.345
36    13281224     14280059    0.005         0.34        0.213         0.222
41    63236125     87761590    0.006         1.35        0.357         0.325
    retorno_1m retorno_6m retorno_12m intensidade_capital capex_receita
64       0.090      0.152       0.128                0.50         0.091
123      0.062      0.140       0.045                0.47         0.064
76       0.101      0.125      -0.005                0.46         0.061
125      0.063      0.129       0.104                0.59         0.070
35       0.029      0.070       0.017                0.43         0.101
81      -0.066      0.007       0.031                0.37         0.053
79       0.058      0.169       0.153                0.53         0.069
83       0.025     -0.058       0.135                0.45         0.100
36       0.083      0.007      -0.085                0.60         0.062
41       0.042     -0.001       0.186                0.40         0.066
    giro_ativos     setor setorEnergia setorFinanceiro setorIndustria
64         0.98   Consumo            0               0              0
123        1.20 Industria            0               0              1
76         0.85   Consumo            0               0              0
125        1.37 Industria            0               0              1
35         1.05   Consumo            0               0              0
81         1.06   Consumo            0               0              0
79         0.76 Industria            0               0              1
83         1.13 Industria            0               0              1
36         1.05 Industria            0               0              1
41         0.86   Consumo            0               0              0
    setorTecnologia
64                0
123               0
76                0
125               0
35                0
81                0
79                0
83                0
36                0
41                0

Regressão Linear

Estimando regressão

Code
lm_fit <- lm(retorno ~ ., data = train)

pred_lm <- predict(lm_fit, newdata = test)

rmse_lm <- sqrt(mean((test$retorno - pred_lm)^2))
r2_lm <- cor(test$retorno, pred_lm)^2

Comparando com árvores

Code
cat("RMSE Árvore:", rmse_tree_single, "\n")
RMSE Árvore: 0.05316728 
Code
cat("RMSE Random Forest:", rmse, "\n")
RMSE Random Forest: 0.03852106 
Code
cat("RMSE Regressão:", rmse_lm, "\n\n")
RMSE Regressão: 0.05054714 
Code
cat("RMSE Árvore:", r2_ar, "\n")
RMSE Árvore: 0.3535545 
Code
cat("R² Random Forest:", r2, "\n")
R² Random Forest: 0.6002508 
Code
cat("R² Regressão:", r2_lm, "\n")
R² Regressão: 0.2661825 

Coeficientes das variáveis

Code
summary(lm_fit)

Call:
lm(formula = retorno ~ ., data = train)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.088099 -0.015447 -0.002155  0.018376  0.073263 

Coefficients: (4 not defined because of singularities)
                              Estimate         Std. Error t value Pr(>|t|)  
(Intercept)         -0.055107315610454  0.308846204117828  -0.178   0.8590  
roe                  0.107249127142272  0.211087697028102   0.508   0.6134  
roa                 -0.173613633357377  0.274139852747045  -0.633   0.5292  
margem_liquida       0.103489076385502  0.233271603925358   0.444   0.6590  
margem_bruta         0.038613866260513  0.099108286986395   0.390   0.6983  
crescimento_receita -0.021198550838721  0.250990743642754  -0.084   0.9330  
crescimento_lucro   -0.066268654914055  0.170426431927382  -0.389   0.6989  
payout              -0.020013951368129  0.050589482695361  -0.396   0.6939  
dividend_yield      -0.099366117055482  0.572781097434476  -0.173   0.8629  
alavancagem         -0.043544740019271  0.021661898696970  -2.010   0.0493 *
cobertura_juros     -0.001426757455814  0.005964695627351  -0.239   0.8118  
pe_ratio             0.001580114695989  0.000808028099671   1.956   0.0556 .
pb_ratio            -0.001995816099361  0.006837659357208  -0.292   0.7715  
ev_ebitda            0.001454714153875  0.002112992543474   0.688   0.4941  
price_sales          0.000814065450844  0.005862833964212   0.139   0.8901  
tamanho              0.009860157787834  0.031985152726584   0.308   0.7590  
market_cap          -0.000000000001308  0.000000000001875  -0.697   0.4885  
free_float          -0.006903960176814  0.054989075453527  -0.126   0.9005  
liq_diaria          -0.000000000138415  0.000000000267006  -0.518   0.6063  
volume_medio        -0.000000000076537  0.000000000198777  -0.385   0.7017  
turnover            -0.141558477300292  2.090839270265971  -0.068   0.9463  
beta_mercado         0.021789511494080  0.033436775060467   0.652   0.5173  
volatilidade        -0.195824992095012  0.233506841786750  -0.839   0.4053  
downside_risk        0.197838204398160  0.155225981708926   1.275   0.2078  
retorno_1m          -0.132925864692983  0.111363593586788  -1.194   0.2377  
retorno_6m           0.053318345344792  0.073623263067820   0.724   0.4720  
retorno_12m          0.056435685308295  0.059021275803553   0.956   0.3432  
intensidade_capital  0.111674553550194  0.065954242163290   1.693   0.0961 .
capex_receita       -0.078908936124126  0.298243503119102  -0.265   0.7923  
giro_ativos          0.037816219254301  0.030024679329861   1.260   0.2132  
setorEnergia         0.021237401665962  0.019947576928591   1.065   0.2917  
setorFinanceiro      0.017845076386871  0.017430887843918   1.024   0.3104  
setorIndustria      -0.037785504435944  0.016786265330397  -2.251   0.0284 *
setorTecnologia      0.009407480671922  0.018373709487851   0.512   0.6107  
setorEnergia                        NA                 NA      NA       NA  
setorFinanceiro                     NA                 NA      NA       NA  
setorIndustria                      NA                 NA      NA       NA  
setorTecnologia                     NA                 NA      NA       NA  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.03736 on 55 degrees of freedom
Multiple R-squared:  0.7563,    Adjusted R-squared:  0.6101 
F-statistic: 5.173 on 33 and 55 DF,  p-value: 0.00000004435

Comentários

Sua regressão mostra:

  • R² = 0.756 (in-sample)

  • R² = 0.266 (out-of-sample)

👉 Isso é um diagnóstico clássico:

overfitting estrutural + instabilidade dos coeficientes

Ou seja:

  • o modelo “explica bem” dentro da amostra

  • mas falha em generalizar

  • coeficientes instáveis

  • sinais pouco confiáveis

  • p-values inflados

Lasso

Estimando o modelo

Code
x_train <- model.matrix(retorno ~ ., train)[, -1]
y_train <- train$retorno

x_test  <- model.matrix(retorno ~ ., test)[, -1]
y_test  <- test$retorno

Coeficientes das variáveis

Code
set.seed(123)

lasso_cv <- cv.glmnet(
  x_train, y_train,
  alpha = 1,        # Lasso
  nfolds = 10
)
best_lambda <- lasso_cv$lambda.min
coef(lasso_cv, s = "lambda.min")
38 x 1 sparse Matrix of class "dgCMatrix"
                               lambda.min
(Intercept)          0.082066817608004466
roe                  0.105272540995267533
roa                  .                   
margem_liquida       .                   
margem_bruta         0.001217598166731726
crescimento_receita  .                   
crescimento_lucro    .                   
payout               .                   
dividend_yield       .                   
alavancagem         -0.029630578227862095
cobertura_juros      .                   
pe_ratio             0.001472439631984189
pb_ratio             .                   
ev_ebitda            .                   
price_sales          .                   
tamanho              .                   
market_cap          -0.000000000001160637
free_float           .                   
liq_diaria          -0.000000000041696761
volume_medio        -0.000000000023433138
turnover             .                   
beta_mercado         .                   
volatilidade         .                   
downside_risk        0.018741068842953873
retorno_1m           .                   
retorno_6m           .                   
retorno_12m          0.024376771310056840
intensidade_capital  0.007434071812512003
capex_receita        .                   
giro_ativos          0.022342046171543829
setorEnergia         0.014912573979217190
setorFinanceiro      .                   
setorIndustria      -0.025073923409735306
setorTecnologia      0.004793075237009337
setorEnergia         .                   
setorFinanceiro      .                   
setorIndustria      -0.000036574332628236
setorTecnologia      0.000000022073694698

Comparações

Code
pred_lasso <- predict(lasso_cv, s = "lambda.min", newx = x_test)

rmse_lasso <- sqrt(mean((y_test - pred_lasso)^2))
r2_lasso <- cor(y_test, pred_lasso)^2

cat("RMSE Regressão:", rmse_lm, "\n")
RMSE Regressão: 0.05054714 
Code
cat("RMSE Lasso:", rmse_lasso, "\n")
RMSE Lasso: 0.03960081 
Code
cat("RMSE Random Forest:", rmse, "\n\n")
RMSE Random Forest: 0.03852106 
Code
cat("R² Regressão:", r2_lm, "\n")
R² Regressão: 0.2661825 
Code
cat("R² Lasso:", r2_lasso, "\n")
R² Lasso: 0.3333849 
Code
cat("R² Random Forest:", r2, "\n")
R² Random Forest: 0.6002508 

Ridge

Estimando modelo

Code
set.seed(123)

ridge_cv <- cv.glmnet(
  x_train, y_train,
  alpha = 0,   # Ridge
  nfolds = 10
)

best_lambda_ridge <- ridge_cv$lambda.min

Coeficientes das variáveis

Code
pred_ridge <- predict(ridge_cv, s = "lambda.min", newx = x_test)

rmse_ridge <- sqrt(mean((y_test - pred_ridge)^2))
r2_ridge <- cor(y_test, pred_ridge)^2
coef(ridge_cv, s = "lambda.min")
38 x 1 sparse Matrix of class "dgCMatrix"
                                lambda.min
(Intercept)          0.0855309193492710673
roe                  0.0834265816229555063
roa                  0.0663588595419826871
margem_liquida       0.0828179296518122554
margem_bruta         0.0371959671281663143
crescimento_receita  0.0674360469900480292
crescimento_lucro    0.0584120979283184460
payout              -0.0045743299965871204
dividend_yield      -0.1381782928759840434
alavancagem         -0.0225148173940401090
cobertura_juros      0.0013821091837038304
pe_ratio             0.0005444504545149758
pb_ratio             0.0022422180172897198
ev_ebitda            0.0002801907990725817
price_sales          0.0006802390131784736
tamanho             -0.0068781020698232345
market_cap          -0.0000000000005890674
free_float          -0.0017096803640096027
liq_diaria          -0.0000000000679181277
volume_medio        -0.0000000000587050556
turnover            -0.4547145188164948837
beta_mercado         0.0012318609192911460
volatilidade        -0.0354444294747081889
downside_risk        0.0541208593602293536
retorno_1m          -0.0522772184683747976
retorno_6m           0.0152274475605262069
retorno_12m          0.0310916944819384158
intensidade_capital  0.0330293409663580395
capex_receita        0.0786582833794073621
giro_ativos          0.0276547775250127852
setorEnergia         0.0098027330403938576
setorFinanceiro      0.0047515097892812021
setorIndustria      -0.0140302958640639019
setorTecnologia      0.0050747984689695916
setorEnergia         0.0098042689873498751
setorFinanceiro      0.0047530831043705486
setorIndustria      -0.0140331743858793778
setorTecnologia      0.0050723620024720152

Comparações

Code
cat("RMSE Regressão:", rmse_lm, "\n")
RMSE Regressão: 0.05054714 
Code
cat("RMSE Lasso:", rmse_lasso, "\n")
RMSE Lasso: 0.03960081 
Code
cat("RMSE Ridge:", rmse_ridge, "\n")
RMSE Ridge: 0.04050553 
Code
cat("RMSE Random Forest:", rmse, "\n\n")
RMSE Random Forest: 0.03852106 
Code
cat("R² Regressão:", r2_lm, "\n")
R² Regressão: 0.2661825 
Code
cat("R² Lasso:", r2_lasso, "\n")
R² Lasso: 0.3333849 
Code
cat("R² Ridge:", r2_ridge, "\n")
R² Ridge: 0.3088375 
Code
cat("R² Random Forest:", r2, "\n")
R² Random Forest: 0.6002508 

Conclusão

De início, estimou-se uma modelo de random forest genérico, embora robusto, com 500 árvores aleatórias. A finalidade do modelo, que se entende por conservador, é observar a média de resultados dessas árvores. Assim, obtém-se resultado conservador, visto que o modelo centra-se na média, o que nos leva a resultados viesados, a despeito de se reduzir a variância, potencializando retornos menores e deprimindo retornos maiores. Ainda, diz-se que o modelo é genérico porque foi a primeira tentativa relacionada a random forest, inclusive sem nenhuma comparação com outros modelos.

Em face de outros modelos, percebe-se, de imediato, que o modelo random forest carece de interpretabilidade, como uma regressão linear convecional. Podemos elencar a importância de cada variável para o modelo, não obstante, não se tem demonstração do sinal de cada uma dessas variáveis - o que nos faz considerar a necessidade de uma regressão simples com a finalidade de verificar o sinal de cada variável (e, apenas para isso, como se justificará).

Também foi perceptível que o número de 500 árvores foi supérfluo, sobretudo por ser um valor escolhido de modo discricionário. Após análise posterior, ficou mostrado que um número menor de árvores era suficiente. Parece-nos, agora, que é mais interessante verificar primeiro o número ótimo de árvores, considerando, se necessário, algum threshold grande. Ainda, tal medida favorece especialmente a simplicidade do modelo.

Comparando-se com outros modelos, a saber, com regressão linear multivariada, regressão do tipo Lasso e do tipo Ridge, percebe-se através de nossos resultados que o random forest obtém resultados superiores a todos. Inclusive, observando uma única árvore, também o random forest tem desempenho muito superior. O caso da única árvore é interessante pois tem desempenho inferior a regressão OLS.


Comentários

Postagens mais visitadas deste blog

Da filosofia de Interestelar

Cointegração entre BTC e juros de curto prazo (2014 - 2025)

A predestinação da nação em Dostoievski e ideais brasileiros