Maschinelles Lernen im Handel: Theorie, Modelle, Praxis und Algo-Trading - Seite 213
Sie verpassen Handelsmöglichkeiten:
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Registrierung
Einloggen
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Wenn Sie kein Benutzerkonto haben, registrieren Sie sich
Ein weiteres Beispiel für eine Simulation.
Wir erstellen 20.000 lineare Modelle (überall 1.000 Beobachtungen, Anzahl der Prädiktoren von 1 bis 20 (1.000 Modelle für jede Anzahl), plus eine unabhängige Variable). Daten i.i.d., N(0,1).
Mit der Simulation soll sichergestellt werden, dass die F-Statistik den kritischen Wert nicht überschreitet, wenn die MNA-Regression auf unabhängigen Daten (die keine Abhängigkeiten enthalten) aufgebaut ist und die Anforderungen des lin.model erfüllt. Sie kann also als Indikator für die Modellausbildung verwendet werden.
############### 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()
Laufzeit des Codes: 1,35 Minuten.
Nützlicher Code. Visualisiert Transaktionssequenzen in drei Hypostasen.
##########################
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()
Läuft etwa 45 Sekunden lang. Hat eine Laufzeit von etwa 1,5 Minuten.
Mit der Simulation soll sichergestellt werden, dass die F-Statistik einen kritischen Wert nicht überschreitet, wenn die MNA-Regression auf unabhängigen Daten (die keine Abhängigkeiten enthalten) aufgebaut ist und die Anforderungen eines linearen Modells erfüllt. Sie kann also als Indikator für die Modellausbildung verwendet werden.
Wie interpretiere ich das Ergebnis aus diesem Beispiel richtig?
Ich verstehe, dass der erste Prädiktor als qualitativer angesehen werden kann als der erste + zweite. Und 1+2 ist besser als 1+2+3. Ist das so? Ist es sinnvoll, die Prädiktoren mit Hilfe der Genetik auszuwählen, die die höchste fstatistic ergeben?
Ich habe das mit der fstatistic nicht ganz verstanden. Die Daten sind hier zufällig, aber das Modell hat etwas gelernt, so dass man daraus schließen kann, dass das Modell passt und übertrainiert ist. Das bedeutet, dass die Modellbewertung schlecht sein muss. D.h. ich habe eine negative fstatistis oder einen anderen Hinweis darauf erwartet, dass es in der Grafik schlecht aussieht.
Wie interpretiere ich das Ergebnis aus diesem Beispiel richtig?
Ich verstehe, dass der erste Prädiktor als qualitativer angesehen werden kann als der erste + zweite. Und 1+2 ist besser als 1+2+3. Ist das so? Ist es sinnvoll, die Prädiktoren mit Hilfe der Genetik auszuwählen, die die höchste fstatistic ergeben?
Sehen Sie sich die F-Verteilungstabelle an.http://www.socr.ucla.edu/applets.dir/f_table.html
Die F-Statistik ist ein Wert, der von den Freiheitsgraden abhängt. Sie ist immer positiv, weil wir eine einseitige Verteilung haben.
Aber das Modell lernt nichts, denn ein trainiertes Modell muss eine hohe F-Statistik haben (größer oder gleich kritisch bei einem gegebenen Alpha - wie es beim Testen der Nullhypothese klingt).
In allen Fällen darf der kritische Wert bei alpha = 0,01 nicht überschritten werden, aber man könnte ihn z. B. auf 0,0001 setzen.
Allerdings wollte ich mich vergewissern (ich habe das nicht an der Universität studiert), dass das lineare Modell durch das Hinzufügen von Rauschvariablen keinen Anstieg der Lernleistung zeigen würde. Wie Sie sehen können...
Nützlicher Code. Visualisiert Transaktionssequenzen in drei Hypostasen.
Bezüglich des obigen Codes. Bitte schreiben Sie zumindest kurze Kommentare in den Code. Vor allem, wenn Sie komplexe Ausdrücke verwenden. Nicht jeder kennt und benutzt das "data.table" Paket, es ist nicht überflüssig zu erklären, was dcast.data.table macht, was .N, .SD ist. Sie stellen den Code nicht ein, um zu zeigen, wie gut Sie sich damit auskennen. Meiner Meinung nach sollte der veröffentlichte Code anderen Nutzern (auch solchen mit Grundkenntnissen) helfen, das Skript zu verstehen.
Es ist großartig, dass R es Ihnen erlaubt, die Aktion auf verschiedene Arten zu programmieren, aber es ist wünschenswert, dass Sie die Lesbarkeit des Codes nicht verlieren.
Ein paar Vorschläge zum Code:
- Die Zwischenvariablen x, x.cast, x.cum werden in den Berechnungen nicht benötigt und nehmen nur Speicherplatz in Anspruch. Alle Berechnungen, die keine Speicherung von Zwischenergebnissen erfordern, sollten vorzugsweise über Rohrleitungen durchgeführt werden.
Zum Beispiel
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
Natürlich dauert es sehr lange, Diagramme zu erstellen.
Das ist keine Kritik.
Viel Glück!
Ich habe das mit der fstatistic nicht ganz verstanden. Die Daten sind hier zufällig, aber das Modell hat etwas gelernt, so dass man daraus schließen kann, dass das Modell passt und übertrainiert ist. Das bedeutet, dass die Modellbewertung schlecht sein muss. D.h. ich habe eine negative fstatistis oder einen anderen Hinweis darauf erwartet, dass es in der Grafik schlecht aussieht.
Wie interpretiere ich das Ergebnis aus diesem Beispiel richtig?
Ich verstehe, dass der erste Prädiktor als qualitativer angesehen werden kann als der erste + zweite. Und 1+2 ist besser als 1+2+3. Ist das so? Ist es sinnvoll, die Prädiktoren mit Hilfe der Genetik auszuwählen, die die höchste fstatistic ergeben?
Und hier ein Beispiel, bei dem wir davon ausgehen, dass das vollständig trainierte Modell 20 Variablen mit steigender Gewichtung enthält (1 Variable - Gewichtung 1, die 20. Variable - Gewichtung 20). Und wir wollen sehen, wie sich die Verteilung der F-Statistiken nach dem sukzessiven Hinzufügen von Prädiktoren zum Modell verändert:
############### 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()
Diagramm mit logarithmischer y-Achse:
Anscheinend ja...
> 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
Ich danke Ihnen! Ich wusste noch nicht, wie man das macht. Aber eigentlich sollten Sie die Berechnungen so weit wie möglich im Hinterkopf behalten. Es wird schneller gehen. Gutes Kung Fu...
Mit Ihren Optimierungen:
#---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
Die Laufzeit beträgt 47 Sekunden. Ich meine, der Code ist hübscher und kompakter, aber es gibt keinen Unterschied in der Geschwindigkeit... Zeichnen, ja, sehr lang. 1000 Zeilen mit Transparenz - wegen ihnen...
Ich danke Ihnen! Ich wusste noch nicht, wie man das macht. Aber eigentlich sollten Sie die Berechnungen so weit wie möglich im Hinterkopf behalten. Es wird schneller gehen. Gutes Kung Fu...
Die Laufzeit beträgt 47 Sekunden. Ich meine, der Code ist hübscher und kompakter, aber es gibt keinen Unterschied in der Geschwindigkeit... Das Zeichnen, ja, ist sehr lang. 1000 Zeilen mit Transparenz - wegen ihnen...
Meine Berechnung geht von
# Laufzeit in Sekunden
# min lq mittel median uq max neval
# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100
Aber das ist nicht so wichtig. Es ging um die Lesbarkeit des Codes.
Viel Glück!
PS. Und parallelisieren Sie die lm()-Berechnung. Dies ist genau der Fall, wenn Sie Folgendes benötigen
Ich habe eine Berechnung, bei der
#-Ausführungszeit in Sekunden
# min lq mittel median uq max neval
# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100
Aber das ist nicht so wichtig. Es ging um die Lesbarkeit des Codes.
Viel Glück!
PS. Und parallelisieren Sie die lm()-Berechnung. Das ist genau der Fall, wenn es notwendig ist.
Nö. Sie geben die Zeit für einen Teil des Codes vor den Diagrammen an. Ich habe sie zusammen mit den Diagrammen angegeben.
Ich habe 1,5 Sekunden vor den Karten. Ihre Methode beträgt 1,15 Sekunden.
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
Es stellt sich heraus, dass Ihre Methode schneller ist...