Aprendizado de máquina no trading: teoria, prática, negociação e não só - página 213

Você está perdendo oportunidades de negociação:
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Registro
Login
Você concorda com a política do site e com os termos de uso
Se você não tem uma conta, por favor registre-se
Outro exemplo para uma simulação.
Construímos 20.000 modelos lineares (1.000 observações em toda parte, número de preditores de 1 a 20 (1.000 modelos para cada número), mais uma variável independente). Dados i.i.d., N(0,1).
O objetivo da simulação é garantir que a estatística F não exceda o valor crítico quando a regressão do MNA é construída sobre dados independentes (não contendo dependências), satisfazendo os requisitos do modelo lin.lin. Portanto, pode ser usado como um indicador do treinamento modelo.
############### simulate lm f-stats with random vars
rm(list=ls());gc()
library(data.table)
library(ggplot2)
start <- Sys.time()
set.seed(1)
x <- as.data.table(matrix(rnorm(21000000, 0, 1), ncol = 21))
x[, sampling:= sample(1000, nrow(x), replace = T)]
lm_models <- x[,
{
lapply(c(1:20), function(x) summary(lm(data = .SD[, c(1:x, 21), with = F], formula = V21 ~ . -1))$'fstatistic'[[1]])
}
, by = sampling
]
lm_models_melted <- melt(lm_models, measure.vars = paste0('V', c(1:20)))
crtitical_f_stats <- qf(p = 0.99, df1 = c(1:20), df2 = 1000, lower.tail = TRUE, log.p = FALSE)
boxplot(data = lm_models_melted, value ~ variable); lines(crtitical_f_stats, type = 's', col = 'red')
Sys.time() - start
gc()
Tempo de funcionamento do código: 1,35 minutos.
Código útil. Visualiza sequências de transacções em três hipóstases.
##########################
rm(list=ls());gc()
library(data.table)
library(ggplot2)
library(gridExtra)
library(tseries)
start <- Sys.time()
set.seed(1)
x <- as.data.table(matrix(rnorm(1000000, 0.1, 1), ncol = 1)) #random normal value with positive expectation
x[, variable:= rep(1:1000, times = 1000)]
x[, trade:= 1:.N, by = variable]
x.cast = dcast.data.table(x, variable ~ trade, value.var = 'V1', fun.aggregate = sum)
x_cum <- x.cast[, as.list(cumsum(unlist(.SD))), by = variable]
monte_trades <- melt(x_cum, measure.vars = names(x_cum)[-1], variable.name = "trade", value.name = 'V1')
setorder(monte_trades, variable, trade)
monte_trades_last <- as.data.table(monte_trades[trade == '1000', V1])
quantile_trade <- monte_trades[, quantile(V1, probs = 0.05), by = trade]
RF_last <- monte_trades[, V1[.N] / maxdrawdown(V1)[[1]], by = variable]
p1 <- ggplot(data = monte_trades, aes(x = trade, y = V1, group = variable)) +
geom_line(size = 2, color = 'blue', alpha = 0.01) +
geom_line(data = quantile_trade, aes(x = trade, y = V1, group = 1), size = 2, alpha = 0.5, colour = 'blue') +
ggtitle('Simulated Trade Sequences of Length 1000')
p2 <- ggplot(data = monte_trades_last, aes(V1)) +
geom_density(alpha = 0.1, size = 1, color = 'blue', fill = 'blue') +
scale_x_continuous(limits = c(min(monte_trades$V1), max(monte_trades$V1))) +
coord_flip() +
ggtitle('Cumulative Profit Density')
p3 <- ggplot(data = RF_last, aes(V1)) +
geom_density(alpha = 0.1, size = 1, color = 'blue', fill = 'blue') +
geom_vline(xintercept = mean(RF_last$V1), colour = "blue", linetype = 2, size = 1) +
geom_vline(xintercept = median(RF_last$V1), colour = "red", linetype = 2, size = 1) +
ggtitle('Recovery Factor Density + Mean (blue) and Median (red)')
grid.arrange(p1, p2, p3, ncol = 3)
Sys.time() - start
gc()
Funciona durante cerca de 45 segundos. Arrasta durante cerca de 1,5 minutos.
O objetivo da simulação é assegurar que a estatística F não exceda um valor crítico quando a regressão do MNA é construída sobre dados independentes (não contendo dependências), satisfazendo os requisitos de um modelo linear. Portanto, pode ser usado como um indicador do treinamento modelo.
Como interpretar corretamente o resultado desse exemplo?
Eu entendo que o primeiro preditor pode ser considerado mais qualitativo do que o primeiro + segundo. E 1+2 é melhor do que 1+2+3. Ai sim? É razoável selecionar por genética o conjunto de preditores que dará a maior fstatistic?
Eu não entendi completamente sobre a fstatistic. Os dados aqui são aleatórios, mas o modelo aprendeu alguma coisa, então você pode concluir que o modelo é adequado e super-treinado. O que significa que a avaliação do modelo deve ser má. Ou seja, eu estava esperando uma fstatis negativa, ou alguma outra indicação de que as coisas estão ruins no gráfico.
Como interpretar corretamente o resultado desse exemplo?
Eu entendo que o primeiro preditor pode ser considerado mais qualitativo do que o primeiro + segundo. E 1+2 é melhor do que 1+2+3. Ai sim? É razoável selecionar por genética o conjunto de preditores que dará a maior fstatistic?
Olha para a tabela de distribuição F.http://www.socr.ucla.edu/applets.dir/f_table.html
A estatística F é um valor que depende dos graus de liberdade. É sempre positivo, porque temos uma distribuição unilateral.
Mas o modelo não aprende nada, porque um modelo treinado deve ter uma estatística F alta (maior ou igual à crítica em um determinado alfa - como soa quando se testa a hipótese nula).
Em todos os casos, não excedendo o valor crítico em alfa = 0,01, mas você poderia defini-lo como 0,0001, por exemplo.
Dito isto, eu queria ter certeza (não estudei isto na universidade) que adicionando variáveis de ruído o modelo linear não mostraria um aumento na aprendizagem. Como podem ver...
Código útil. Visualiza sequências de transacções em três hipóstases.
Em relação ao código acima. Por favor, escreva pelo menos breves comentários no código. Especialmente quando você usa expressões complexas. Nem todos conhecem e usam o pacote "data.table", não é supérfluo explicar o que o dcast.data.table faz, derreter o que é .N, .SD. Não se afixa o código para mostrar o quanto se sabe sobre isso. Na minha opinião, o código publicado deve ajudar outros usuários (mesmo com nível elementar de treinamento) a entender o script.
É ótimo que R permite que você programe a ação de várias maneiras, mas é desejável que você não perca a legibilidade do código.
Algumas sugestões sobre o código:
- As variáveis intermediárias x, x.cast, x.cum não são necessárias nos cálculos e só ocupam memória. Todos os cálculos que não exijam resultados intermédios de poupança devem ser efectuados preferencialmente através de tubos.
Por exemplo
rm(list=ls());gc()
library(data.table)
library(ggplot2)
library(gridExtra)
library(tseries)
#----
require(magrittr)
require(dplyr)
start <- Sys.time()
monte_trades <- as.data.table(matrix(rnorm(1000000, 0.1, 1), ncol = 1)) %>%
.[, variable := rep(1:1000, times = 1000)]%>%
.[, trade := 1:.N, by = variable] %>%
dcast.data.table(., variable ~ trade, value.var = 'V1', fun.aggregate = sum)%>%
.[, as.list(cumsum(unlist(.SD))), by = variable]%>%
melt(., measure.vars = names(.)[-1], variable.name = "trade", value.name = 'V1')%>%
setorder(., variable, trade)
monte_trades_last <- as.data.table(monte_trades[trade == '1000', V1])
quantile_trade <- monte_trades[, quantile(V1, probs = 0.05), by = trade]
RF_last <- monte_trades[, V1[.N] / maxdrawdown(V1)[[1]], by = variable]
Sys.time() - start
#Time difference of 2.247022 secs
Claro, demora muito tempo a construir gráficos.
Não é uma crítica.
Boa sorte.
Eu não entendi completamente sobre a fstatistic. Os dados aqui são aleatórios, mas o modelo aprendeu alguma coisa, então você pode concluir que o modelo é adequado e super-treinado. O que significa que a avaliação do modelo deve ser má. Ou seja, eu estava esperando uma fstatis negativa, ou alguma outra indicação de que as coisas estão ruins no gráfico.
Como interpretar corretamente o resultado desse exemplo?
Eu entendo que o primeiro preditor pode ser considerado mais qualitativo do que o primeiro + segundo. E 1+2 é melhor do que 1+2+3. Ai sim? É razoável selecionar por genética o conjunto de preditores que dará a maior fstatistic?
E aqui está um exemplo onde assumimos que o modelo totalmente treinado incluirá 20 variáveis, com peso crescente (1 variável - peso 1, a 20 variável - peso 20). E vejamos como a distribuição das estatísticas F irá mudar após a adição sucessiva de preditores ao modelo:
############### simulate lm f-stats with non-random vars
rm(list=ls());gc()
library(data.table)
library(ggplot2)
start <- Sys.time()
set.seed(1)
x <- as.data.table(matrix(rnorm(20000000, 0, 1), ncol = 20))
x[, (paste0('coef', c(1:20))):= lapply(1:20, function(x) rnorm(.N, x, 1))]
x[, output:= Reduce(`+`, Map(function(x, y) (x * y), .SD[, (1:20), with = FALSE], .SD[, (21:40), with = FALSE])), .SDcols = c(1:40)]
x[, sampling:= sample(1000, nrow(x), replace = T)]
lm_models <- x[,
{
lapply(c(1:20), function(x) summary(lm(data = .SD[, c(1:x, 41), with = F], formula = output ~ . -1))$'fstatistic'[[1]])
}
, by = sampling
]
lm_models_melted <- melt(lm_models, measure.vars = paste0('V', c(1:20)))
crtitical_f_stats <- qf(p = 0.99, df1 = c(1:20), df2 = 1000, lower.tail = TRUE, log.p = FALSE)
boxplot(data = lm_models_melted, value ~ variable, log = 'y'); lines(crtitical_f_stats, type = 's', col = 'red')
summary(lm(data = x[sample(1000000, 1000, replace = T), c(1:20, 41), with = F], formula = output ~ . -1))
Sys.time() - start
gc()
Gráfico com eixo y logarítmico:
Aparentemente, sim...
> summary(lm(data = x[sample(1000000, 1000, replace = T), c(1:20, 41), with = F], formula = output ~ . -1))
Call:
lm(formula = output ~ . - 1, data = x[sample(1e+06, 1000, replace = T),
c(1:20, 41), with = F])
Residuals:
Min 1Q Median 3Q Max
-19.6146 -2.8252 0.0192 3.0659 15.8853
Coefficients:
Estimate Std. Error t value Pr(>|t|)
V1 0.9528 0.1427 6.676 4.1e-11 ***
V2 1.7771 0.1382 12.859 < 2e-16 ***
V3 2.7344 0.1442 18.968 < 2e-16 ***
V4 4.0195 0.1419 28.325 < 2e-16 ***
V5 5.2817 0.1479 35.718 < 2e-16 ***
V6 6.2776 0.1509 41.594 < 2e-16 ***
V7 6.9771 0.1446 48.242 < 2e-16 ***
V8 7.9722 0.1469 54.260 < 2e-16 ***
V9 9.0349 0.1462 61.806 < 2e-16 ***
V10 10.1372 0.1496 67.766 < 2e-16 ***
V11 10.8783 0.1487 73.134 < 2e-16 ***
V12 11.9129 0.1446 82.386 < 2e-16 ***
V13 12.8079 0.1462 87.588 < 2e-16 ***
V14 14.2017 0.1487 95.490 < 2e-16 ***
V15 14.9080 0.1458 102.252 < 2e-16 ***
V16 15.9893 0.1428 111.958 < 2e-16 ***
V17 17.4997 0.1403 124.716 < 2e-16 ***
V18 17.8798 0.1448 123.470 < 2e-16 ***
V19 18.9317 0.1470 128.823 < 2e-16 ***
V20 20.1143 0.1466 137.191 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4.581 on 980 degrees of freedom
Multiple R-squared: 0.9932, Adjusted R-squared: 0.993
F-statistic: 7123 on 20 and 980 DF, p-value: < 2.2e-16
Obrigado! Eu ainda não sabia como fazer isso. Mas na verdade, você deve manter os cálculos em mente o máximo possível. Vai ser mais rápido. Bom kung fu...
Com os teus afinações:
#---variant-------------
rm(list=ls());gc()
library(data.table)
library(ggplot2)
library(gridExtra)
library(tseries)
#----
require(magrittr)
require(dplyr)
start <- Sys.time()
monte_trades <- as.data.table(matrix(rnorm(1000000, 0.1, 1), ncol = 1)) %>%
.[, variable := rep(1:1000, times = 1000)]%>%
.[, trade := 1:.N, by = variable] %>%
dcast.data.table(., variable ~ trade, value.var = 'V1', fun.aggregate = sum)%>%
.[, as.list(cumsum(unlist(.SD))), by = variable]%>%
melt(., measure.vars = names(.)[-1], variable.name = "trade", value.name = 'V1')%>%
setorder(., variable, trade)
monte_trades_last <- as.data.table(monte_trades[trade == '1000', V1])
quantile_trade <- monte_trades[, quantile(V1, probs = 0.05), by = trade]
RF_last <- monte_trades[, V1[.N] / maxdrawdown(V1)[[1]], by = variable]
p1 <- ggplot(data = monte_trades, aes(x = trade, y = V1, group = variable)) +
geom_line(size = 2, color = 'blue', alpha = 0.01) +
geom_line(data = quantile_trade, aes(x = trade, y = V1, group = 1), size = 2, alpha = 0.5, colour = 'blue') +
ggtitle('Simulated Trade Sequences of Length 1000')
p2 <- ggplot(data = monte_trades_last, aes(V1)) +
geom_density(alpha = 0.1, size = 1, color = 'blue', fill = 'blue') +
scale_x_continuous(limits = c(min(monte_trades$V1), max(monte_trades$V1))) +
coord_flip() +
ggtitle('Cumulative Profit Density')
p3 <- ggplot(data = RF_last, aes(V1)) +
geom_density(alpha = 0.1, size = 1, color = 'blue', fill = 'blue') +
geom_vline(xintercept = mean(RF_last$V1), colour = "blue", linetype = 2, size = 1) +
geom_vline(xintercept = median(RF_last$V1), colour = "red", linetype = 2, size = 1) +
ggtitle('Recovery Factor Density + Mean (blue) and Median (red)')
grid.arrange(p1, p2, p3, ncol = 3)
Sys.time() - start
O tempo de execução é de 47 segundos. Então o código é mais bonito e compacto, mas não há diferença na velocidade... A desenhar, sim, muito tempo. 1000 linhas com transparência - por causa delas...
Obrigado! Eu ainda não sabia como fazer isso. Mas na verdade, você deve manter os cálculos em mente o máximo possível. Vai ser mais rápido. Bom kung fu...
Tempo de execução: 47 segundos. Quero dizer, o código é mais bonito e compacto, mas não há diferença na velocidade... O desenho, sim, é muito longo. 1000 linhas com transparência - por causa delas...
O meu cálculo leva
# tempo de execução em segundos
# min lq média mediana uq max neval
# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100
Mas não é assim tão importante. Era sobre a legibilidade do código.
Boa sorte.
PS. E fazer o cálculo lm() em paralelo. Este é exatamente o caso quando você precisa
Eu tenho um cálculo que leva
#tempo de execução em segundos
# min lq média mediana uq max neval
# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100
Mas não é assim tão importante. Era sobre a legibilidade do código.
Boa sorte.
PS. E fazer o cálculo lm() em paralelo. Este é exactamente o caso quando é necessário.
Não. Você está dando tempo para parte do código antes dos gráficos. Eu já o indiquei, juntamente com os gráficos.
Eu tenho 1,5 segundos antes dos gráficos. O seu método é 1,15 segundos.
rm(list=ls());gc()
library(data.table)
library(ggplot2)
library(gridExtra)
library(tseries)
start <- Sys.time()
set.seed(1)
x <- as.data.table(matrix(rnorm(1000000, 0.1, 1), ncol = 1)) #random normal value with positive expectation
x[, variable:= rep(1:1000, times = 1000)]
x[, trade:= 1:.N, by = variable]
x.cast = dcast.data.table(x, variable ~ trade, value.var = 'V1', fun.aggregate = sum)
x_cum <- x.cast[, as.list(cumsum(unlist(.SD))), by = variable]
monte_trades <- melt(x_cum, measure.vars = names(x_cum)[-1], variable.name = "trade", value.name = 'V1')
setorder(monte_trades, variable, trade)
monte_trades_last <- as.data.table(monte_trades[trade == '1000', V1])
quantile_trade <- monte_trades[, quantile(V1, probs = 0.05), by = trade]
RF_last <- monte_trades[, V1[.N] / maxdrawdown(V1)[[1]], by = variable]
Sys.time() - start
rm(list=ls());gc()
library(data.table)
library(ggplot2)
library(gridExtra)
library(tseries)
#----
require(magrittr)
require(dplyr)
start <- Sys.time()
monte_trades <- as.data.table(matrix(rnorm(1000000, 0.1, 1), ncol = 1)) %>%
.[, variable := rep(1:1000, times = 1000)]%>%
.[, trade := 1:.N, by = variable] %>%
dcast.data.table(., variable ~ trade, value.var = 'V1', fun.aggregate = sum)%>%
.[, as.list(cumsum(unlist(.SD))), by = variable]%>%
melt(., measure.vars = names(.)[-1], variable.name = "trade", value.name = 'V1')%>%
setorder(., variable, trade)
monte_trades_last <- as.data.table(monte_trades[trade == '1000', V1])
quantile_trade <- monte_trades[, quantile(V1, probs = 0.05), by = trade]
RF_last <- monte_trades[, V1[.N] / maxdrawdown(V1)[[1]], by = variable]
Sys.time() - start
Acontece que o seu método é mais rápido...