트레이딩의 머신러닝: 이론, 모델, 실전 및 알고리즘 트레이딩 - 페이지 213

 

또 다른 시뮬레이션 예.

20,000개의 선형 모델이 구축됩니다(어디서나 1000개의 관측값, 예측 변수의 수는 1에서 20까지입니다(각 숫자에 대해 1000개 모델) 및 하나의 독립 변수). 데이터 ID, N(0,1).

시뮬레이션의 목적은 선형 모델의 요구 사항을 충족하는 독립 데이터(종속성 없음)에 대한 LSM 회귀를 구축할 때 F-통계량이 임계값을 초과하지 않도록 하는 것입니다. 이는 모델 학습의 지표로 사용할 수 있음을 의미합니다.

############### 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()

코드 실행 시간: 1.35분.

 

유용한 코드. 트랜잭션 시퀀스는 세 가지 형태로 시각화됩니다.

##########################


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()

약 45초 동안 작동합니다. 약 1.5분 렌더링합니다.

 
알렉세이 버나코프 :


아름다운 감사합니다.
 
알렉세이 버나코프 :

시뮬레이션의 목적은 선형 모델의 요구 사항을 충족하는 독립 데이터(종속성 없음)에 대한 LSM 회귀를 구축할 때 F-통계량이 임계값을 초과하지 않도록 하는 것입니다. 이는 모델 학습의 지표로 사용할 수 있음을 의미합니다.

나는 fstatistic에 대해 완전히 이해하지 못했습니다. 여기에 있는 데이터는 무작위이지만 모델이 무언가를 학습했으므로 모델이 적합 및 과적합되었다는 결론을 내릴 수 있습니다. 이는 모델에 대한 평가가 나빠야 함을 의미합니다. 저것들. 나는 부정적인 fstatistiс 또는 차트에서 모든 것이 나쁘다는 다른 표시를 기대했습니다.
해당 예제의 결과를 올바르게 해석하는 방법은 무엇입니까?
첫 번째 예측 변수가 첫 번째 + 두 번째보다 더 나은 것으로 간주될 수 있음을 이해합니다. 그리고 1+2는 1+2+3보다 낫습니다. 이 같은? 가장 높은 fstatistic을 제공할 예측 변수 집합을 선택하기 위해 유전학을 사용하는 것이 합리적입니까?
 
트레이더 박사 :
나는 fstatistic에 대해 완전히 이해하지 못했습니다. 여기에 있는 데이터는 무작위이지만 모델이 무언가를 학습했으므로 모델이 적합 및 과적합되었다는 결론을 내릴 수 있습니다. 이는 모델에 대한 평가가 나빠야 함을 의미합니다. 저것들. 나는 부정적인 fstatistiс 또는 차트에서 모든 것이 나쁘다는 다른 표시를 기대했습니다.
해당 예제의 결과를 올바르게 해석하는 방법은 무엇입니까?
첫 번째 예측 변수가 첫 번째 + 두 번째보다 더 나은 것으로 간주될 수 있음을 이해합니다. 그리고 1+2는 1+2+3보다 낫습니다. 이 같은? 가장 높은 fstatistic을 제공할 예측 변수 집합을 선택하기 위해 유전학을 사용하는 것이 합리적입니까?

표 F 분포를 참조하십시오. http://www.socr.ucla.edu/applets.dir/f_table.html

F-통계량은 자유도에 따라 달라지는 양입니다. 단측 분포가 있으므로 항상 양수입니다.

그러나 훈련된 모델은 높은 F-통계량(주어진 알파에 대해 임계값보다 크거나 같음 - 귀무 가설을 테스트할 때 들리는 것처럼 들림)을 가져야 하기 때문에 모델은 아무 것도 학습하지 않습니다.

모든 경우에 alpha = 0.01에서 임계값을 초과하지 않았지만 예를 들어 0.0001로 설정할 수 있습니다.

동시에 나는 선형 모델에 노이즈 변수를 추가해도 학습이 증가하지 않는다는 것을 확인하고 싶었습니다(대학에서 이것을 연구하지 않았습니다). 보이는 것은...

F-Distribution Tables
  • Ivo Dinov: www.SOCR.ucla.edu
  • www.socr.ucla.edu
Statistics Online Computational Resource
 
알렉세이 버나코프 :

유용한 코드. 트랜잭션 시퀀스는 세 가지 형태로 시각화됩니다.

위의 코드에 대해. 코드에 최소한 간단한 설명을 작성하십시오. 특히 복잡한 표현을 사용할 때. 모든 사람이 "data.table" 패키지를 알고 사용하는 것은 아닙니다. dcast.data.table이 하는 일, .N, .SD가 무엇인지 설명하는 것은 불필요합니다. 주제에 대한 깊이를 보여주지 않기 위해 코드를 게시합니다. 내 생각에 게시된 코드는 다른 사용자(초기 교육 수준 포함)가 스크립트를 이해하는 데 도움이 되어야 합니다.

R을 사용하여 여러 가지 방법으로 작업을 프로그래밍할 수 있다는 것은 좋지만 코드의 가독성을 잃지 않는 것이 바람직합니다.

몇 가지 코드 제안:

- 중간 변수 x, x.cast, x.cum은 계산에 필요하지 않으며 메모리만 차지합니다. 파이프를 통해 중간 결과를 저장할 필요가 없는 모든 계산을 수행하는 것이 바람직합니다.

예를 들어

#---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]
Sys.time() - start
#Time difference of 2.247022 secs

물론 그래프를 작성하는 데는 매우 오랜 시간이 걸립니다.

비판이 아닙니다.

행운을 빕니다

 
트레이더 박사 :
나는 fstatistic에 대해 완전히 이해하지 못했습니다. 여기에 있는 데이터는 무작위이지만 모델이 무언가를 학습했으므로 모델이 적합 및 과적합되었다는 결론을 내릴 수 있습니다. 이는 모델에 대한 평가가 나빠야 함을 의미합니다. 저것들. 나는 부정적인 fstatistiс 또는 차트에서 모든 것이 나쁘다는 다른 표시를 기대했습니다.
해당 예제의 결과를 올바르게 해석하는 방법은 무엇입니까?
첫 번째 예측 변수가 첫 번째 + 두 번째보다 더 나은 것으로 간주될 수 있음을 이해합니다. 그리고 1+2는 1+2+3보다 낫습니다. 이 같은? 가장 높은 fstatistic을 제공할 예측 변수 집합을 선택하기 위해 유전학을 사용하는 것이 합리적입니까?

그리고 다음은 완전히 훈련된 모델이 20개의 변수를 포함하고 가중치가 증가한다고 가정할 때의 예입니다(변수 1개 - 가중치 1, 20번째 변수 - 가중치 20). 예측 변수를 모델에 순차적으로 추가한 후 F 통계의 분포가 어떻게 변경되는지 보겠습니다.

############### 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()

로그 y축이 있는 플롯:

분명히 예...

> 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

 
블라디미르 페레르벤코 :

고맙습니다! 나는 아직 이것을 할 수 없었다. 그러나 실제로는 가능한 한 많은 계산을 메모리에 보관해야 합니다. 더 빨라질 것입니다. 좋은 쿵푸...

수정 사항:

#---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

작동 시간 47초. 즉, 코드가 더 아름답고 간결해졌지만 속도에는 차이가 없습니다.네, 렌더링이 매우 깁니다. 투명도가 있는 1000줄 - 그것 때문에...

 
알렉세이 버나코프 :

고맙습니다! 나는 아직 이것을 할 수 없었다. 그러나 실제로는 가능한 한 많은 계산을 메모리에 보관해야 합니다. 더 빨라질 것입니다. 좋은 쿵푸...

작동 시간 47초. 즉, 코드가 더 아름답고 간결해졌지만 속도에는 차이가 없습니다.네, 렌더링이 매우 깁니다. 투명도가 있는 1000줄 - 그것 때문에...

계산이 있어요

# - 실행 시간(초)

# 최소 lq 평균 중앙값 uq 최대 neval

# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100

하지만 그렇게 중요한 것은 아닙니다. 그것은 코드 가독성 에 관한 것이었습니다.

행운을 빕니다

추신. 그리고 lm() 계산을 병렬화합니다. 이것은 당신이 필요할 때만 해당됩니다.

 
블라디미르 페레르벤코 :

계산이 있어요

# - 실행 시간(초)

# 최소 lq 평균 중앙값 uq 최대 neval

# 2.027561 2.253354 2.254134 2.275785 2.300051 2.610649 100

하지만 그렇게 중요한 것은 아닙니다. 그것은 코드 가독성 에 관한 것이었습니다.

행운을 빕니다

추신. 그리고 lm() 계산을 병렬화합니다. 이것은 당신이 필요할 때만 해당됩니다.

아니요. 그래프 전에 코드 부분의 타이밍을 맞추고 있습니다. 그래프와 함께 지적했습니다.

내가 가지고 있는 차트 전에: 1.5초. 당신의 방법은 1.15초입니다.

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

당신이 여전히 더 빠르다는 것이 밝혀졌습니다 ...

사유: