为什么模拟股票 returns 在 R 中的 pbo(回测过度拟合概率)包的“pbo”小插图中重新缩放和重新居中?
Why are simulated stock returns re-scaled and re-centered in the “pbo” vignette in the pbo (probability of backtest overfitting) package in R?
这是小插图中的相关代码,稍作修改以适合此处的页面,并使其易于复制。可视化代码省略。评论来自插图作者。
(完整插图:https://cran.r-project.org/web/packages/pbo/vignettes/pbo.html)
library(pbo)
#First, we assemble the trials into an NxT matrix where each column
#represents a trial and each trial has the same length T. This example
#is random data so the backtest should be overfit.`
set.seed(765)
n <- 100
t <- 2400
m <- data.frame(matrix(rnorm(n*t),nrow=t,ncol=n,
dimnames=list(1:t,1:n)), check.names=FALSE)
sr_base <- 0
mu_base <- sr_base/(252.0)
sigma_base <- 1.00/(252.0)**0.5
for ( i in 1:n ) {
m[,i] = m[,i] * sigma_base / sd(m[,i]) # re-scale
m[,i] = m[,i] + mu_base - mean(m[,i]) # re-center
}
#We can use any performance evaluation function that can work with the
#reassembled sub-matrices during the cross validation iterations.
#Following the original paper we can use the Sharpe ratio as
sharpe <- function(x,rf=0.03/252) {
sr <- apply(x,2,function(col) {
er = col - rf
return(mean(er)/sd(er))
})
return(sr)
}
#Now that we have the trials matrix we can pass it to the pbo function
#for analysis.
my_pbo <- pbo(m,s=8,f=sharpe,threshold=0)
summary(my_pbo)
这是我很好奇的部分:
sr_base <- 0
mu_base <- sr_base/(252.0)
sigma_base <- 1.00/(252.0)**0.5
for ( i in 1:n ) {
m[,i] = m[,i] * sigma_base / sd(m[,i]) # re-scale
m[,i] = m[,i] + mu_base - mean(m[,i]) # re-center
}
为什么数据会在for循环内进行转换,这种重新缩放和重新居中需要真正的returns吗?或者这只是作者为了让他的模拟 returns 看起来更像真实的东西而做的事情?
通过 Whosebug 进行谷歌搜索和搜索,找到了一些关于将波动率缩放到时间平方根的文章和帖子,但这看起来与我所看到的不太一样。通常它们涉及将一些短期(即每日)的波动性度量值乘以时间的根,但事实并非如此。此外,该包的文档不包括这段重新缩放和重新居中的代码。文档:https://cran.r-project.org/web/packages/pbo/pbo.pdf
所以:
为什么这个里面的数据转换了way/what是这个的结果
转型?
是只需要这个模拟数据,还是我需要
类似地转换 real returns?
我在 r-help 邮件列表上发布了这个问题并得到了以下答案:
“嗨,乔,
居中和重新缩放是为了他的示例的目的而完成的,并且
也与他对夏普函数的定义保持一致。
特别要注意的是,夏普函数具有 rf(无风险)
默认值为 .03/252 的参数,即每年 3% 的转换率
到每日费率,以十进制表示。
这意味着该函数的另一个参数 x 应该是 DAILY
returns,以十进制表示。
假设他想从 returns 的分布中创建随机数据
ANNUAL 平均值 MU_A 和 ANNUAL 标准差 SIGMA_A,均以十进制表示。
等效的 DAILY returns 意味着 MU_D = MU_A / 252 和标准
偏差 SIGMA_D = SIGMA_A/SQRT(252)。
他叫 MU_D mu_base,叫 SIGMA_D sigma_base。
他的循环现在转换矩阵中的随机数,以便每一列
均值 MU_D 和标准差 SIGMA_D。
HTH,
埃里克
我跟进了这个:
"If I'm understanding correctly, if I’m wanting to use actual returns from backtests rather than simulated returns, I would need to make sure my risk-adjusted return measure, sharpe ratio in this case, matches up in scale with my returns (i.e. daily returns with daily sharpe, monthly with monthly, etc). And I wouldn’t need to transform returns like the simulated returns are in the vignette, as the real returns are going to have whatever properties they have (meaning they will have whatever average and std dev they happen to have). Is that correct?"
有人告诉我这是正确的。
这是小插图中的相关代码,稍作修改以适合此处的页面,并使其易于复制。可视化代码省略。评论来自插图作者。
(完整插图:https://cran.r-project.org/web/packages/pbo/vignettes/pbo.html)
library(pbo)
#First, we assemble the trials into an NxT matrix where each column
#represents a trial and each trial has the same length T. This example
#is random data so the backtest should be overfit.`
set.seed(765)
n <- 100
t <- 2400
m <- data.frame(matrix(rnorm(n*t),nrow=t,ncol=n,
dimnames=list(1:t,1:n)), check.names=FALSE)
sr_base <- 0
mu_base <- sr_base/(252.0)
sigma_base <- 1.00/(252.0)**0.5
for ( i in 1:n ) {
m[,i] = m[,i] * sigma_base / sd(m[,i]) # re-scale
m[,i] = m[,i] + mu_base - mean(m[,i]) # re-center
}
#We can use any performance evaluation function that can work with the
#reassembled sub-matrices during the cross validation iterations.
#Following the original paper we can use the Sharpe ratio as
sharpe <- function(x,rf=0.03/252) {
sr <- apply(x,2,function(col) {
er = col - rf
return(mean(er)/sd(er))
})
return(sr)
}
#Now that we have the trials matrix we can pass it to the pbo function
#for analysis.
my_pbo <- pbo(m,s=8,f=sharpe,threshold=0)
summary(my_pbo)
这是我很好奇的部分:
sr_base <- 0
mu_base <- sr_base/(252.0)
sigma_base <- 1.00/(252.0)**0.5
for ( i in 1:n ) {
m[,i] = m[,i] * sigma_base / sd(m[,i]) # re-scale
m[,i] = m[,i] + mu_base - mean(m[,i]) # re-center
}
为什么数据会在for循环内进行转换,这种重新缩放和重新居中需要真正的returns吗?或者这只是作者为了让他的模拟 returns 看起来更像真实的东西而做的事情?
通过 Whosebug 进行谷歌搜索和搜索,找到了一些关于将波动率缩放到时间平方根的文章和帖子,但这看起来与我所看到的不太一样。通常它们涉及将一些短期(即每日)的波动性度量值乘以时间的根,但事实并非如此。此外,该包的文档不包括这段重新缩放和重新居中的代码。文档:https://cran.r-project.org/web/packages/pbo/pbo.pdf
所以:
为什么这个里面的数据转换了way/what是这个的结果 转型?
是只需要这个模拟数据,还是我需要
类似地转换 real returns?
我在 r-help 邮件列表上发布了这个问题并得到了以下答案:
“嗨,乔, 居中和重新缩放是为了他的示例的目的而完成的,并且 也与他对夏普函数的定义保持一致。 特别要注意的是,夏普函数具有 rf(无风险) 默认值为 .03/252 的参数,即每年 3% 的转换率 到每日费率,以十进制表示。 这意味着该函数的另一个参数 x 应该是 DAILY returns,以十进制表示。
假设他想从 returns 的分布中创建随机数据 ANNUAL 平均值 MU_A 和 ANNUAL 标准差 SIGMA_A,均以十进制表示。 等效的 DAILY returns 意味着 MU_D = MU_A / 252 和标准 偏差 SIGMA_D = SIGMA_A/SQRT(252)。
他叫 MU_D mu_base,叫 SIGMA_D sigma_base。
他的循环现在转换矩阵中的随机数,以便每一列 均值 MU_D 和标准差 SIGMA_D。
HTH, 埃里克
我跟进了这个:
"If I'm understanding correctly, if I’m wanting to use actual returns from backtests rather than simulated returns, I would need to make sure my risk-adjusted return measure, sharpe ratio in this case, matches up in scale with my returns (i.e. daily returns with daily sharpe, monthly with monthly, etc). And I wouldn’t need to transform returns like the simulated returns are in the vignette, as the real returns are going to have whatever properties they have (meaning they will have whatever average and std dev they happen to have). Is that correct?"
有人告诉我这是正确的。