【问题标题】:Calculate cumulatve growth/drawdown from local min/max从局部最小值/最大值计算累积增长/下降
【发布时间】:2013-01-22 04:08:13
【问题描述】:

我正在学习 R(及其通过 quantmod lib 在交易任务中的应用),并定期浏览社区以从这里获得很多新知识和技巧。我对 R 的总体印象,尤其是对 quantmod lib 的印象——它很棒。

此时我需要经验丰富的 R 用户的帮助。我正在使用通过 getSymbols 下载的时间序列,我需要分别从局部最小值/最大值计算累积增长/下降。

我可以使用 FOR 循环来解决我的任务,也可以在 MS Excel 中进行必要的建模,但我想找出更简单的解决方案,不需要 FOR 循环并且在 R 中更“原生”。

示例。 输入数据:

20121121    79810
20121122    79100
20121123    80045
20121126    81020
20121127    80200
20121128    81350
20121129    81010
20121130    80550
20121203    80780
20121204    81700
20121205    83705
20121206    83350
20121207    83800
20121210    85385

结果:

            CLOSE   Cumulative gr/dd
20121121    79810   N/A
20121122    79100   0.58%
20121123    80045   1.55%
20121126    81020   2.37%
20121127    80200   -0.10%
20121128    81350   0.06%
20121129    81010   -0.76%
20121130    80550   -0.82%
20121203    80780   0.73%
20121204    81700   3.78%
20121205    83705   5.19%
20121206    83350   -1.50%
20121207    83800   1.67%
20121210    85385   2.22%

【问题讨论】:

  • 您假设这里的人熟悉计算累积增长/回撤的概念。您能详细说明一下您是如何获得“累积 gr/dd”的吗?
  • .. 进一步说明@agstudy 的观点:也许可以减少数据集的行数,并准确突出显示计算 0.58% 1.55% 所采取的步骤,以此类推,使用for 循环......然后也许我们可以帮助您改进它:)
  • 是的,你们两个都是对的。我应该提供更多细节和示例代码(使用 FOR)来阐明任务。一旦我使用 R 进入我的家用 PC,我就会这样做。简单地说 - 在资产增长的同时,我们计算累积 ROC。当资产开始下降时 - 我们从局部最大值(资产完成增长并开始下降的点)开始计算累积 ROC。当资产停止下跌并再次开始增长时 - 我们开始从局部最小值(即资产停止下跌并开始新一轮增长的点)计算累积 ROC。
  • 经过一些谷歌搜索和反复试验后,我已经解决了我的任务,并用我的结果更新了初始帖子,以供参考。
  • @UncleKo,而不是在您的问题标题中添加“已解决”,您应该发布您的解决方案作为答案并接受它。

标签: r time-series xts quantmod


【解决方案1】:

计算已经在tseries 包中作为函数maxdrawdown。这是其示例的开头:

mxdrwdR> # Toy example
mxdrwdR> x <- c(1:10, 9:7, 8:14, 13:8, 9:20)

mxdrwdR> mdd <- maxdrawdown(x)

mxdrwdR> mdd
$maxdrawdown
[1] 6

$from
[1] 20

$to
[1] 26

将其转换为百分比非常简单——查看函数本身的(短)代码。

【讨论】:

  • 谢谢,这不是我想要的,但帮助我继续进行谷歌搜索并最终解决了任务。我已经更新了帖子并提供了我的代码。再次感谢!
【解决方案2】:

为了补充 Dirk 的回答,PerformanceAnalytics package 有各种回撤选项。这是我的一些代码的摘录,它还显示了增长计算(以及锐化比率,作为奖励):

#x is an xts object containing OHLC data
profit=ROC(x$Close)
growth=sum(na.omit(profit)),
equity=exp(sum(na.omit(profit))),
sharpe=as.vector(SharpeRatio.annualized(profit)),
maxDrawdown=maxDrawdown(profit)

【讨论】:

  • 谢谢,这不是我想要的,但帮助我继续进行谷歌搜索并最终解决了任务。我已经更新了帖子并提供了我的代码。再次感谢!
【解决方案3】:

最后,我设法解决了它。 Dirk 和 Darren,非常感谢您的 cmets——PerformanceAnalytics 包中的“maxdrawdown”功能并不是我所需要的,但这让我开始关注 PerformanceAnalytics,并通过该站点和 Internet 进行了一些搜索。 findDrawdowns 函数来自与我的需求接近的同一包,但无论如何并不是我想要的(它需要更新最后一个高点才能开始计算新的回撤,而我什至需要取局部最大值和最小值考虑)。通过进一步的反复试验,我编写了自己的代码,无需 FOR 循环即可解决我的任务。 :) 这是代码。作为奖励 - 它返回带有资产不断增长/下降的条数的向量。如果有人可以建议如何改进它,我会很高兴。

library(rusquant)
library(quantmod)
library(tseries)

na.zero <- function(x) {
  tmp <- x
  tmp[is.na(tmp)] <- 0

  return(tmp)
}

my.cumulative.grdd <- function(asset) {
  # creating list for temporary data
  tmp <- list()
  # 
  #   tmp$asset.lag <- na.locf(lag(asset), fromLast=TRUE)

  # calculating ROC for the asset + getting ROC shifted by 1 element to the left and to the right
  # to compare ROC[i] and ROC[i+1] and ROC[i-1]
  tmp$asset.roc <- na.zero(ROC(asset))
  tmp$asset.roc.lag <- na.zero(lag(tmp$asset.roc))
  tmp$asset.roc.lag1 <- na.locf(lag(tmp$asset.roc, k=-1))

  # calculating indices of consequent growth/drawdown waves start and end
  tmp$indexfrom <- sapply(index(tmp$asset.roc[sign(tmp$asset.roc) * sign(tmp$asset.roc.lag) <= 0]), function(i) which(index(tmp$asset.roc) == i), simplify=TRUE)
  tmp$indexto <- c(sapply(index(tmp$asset.roc[sign(tmp$asset.roc) * sign(tmp$asset.roc.lag1) <= 0]), function(i) which(index(tmp$asset.roc.lag1) == i), simplify=TRUE), length(index(tmp$asset.roc)))

  # this is necessary to work around ROC[1] = 1
  tmp$indexfrom <- tmp$indexfrom[-2]
  tmp$indexto <- tmp$indexto[-1]

  # calculating dates of waves start/end based on indices
  tmp$datesfrom <- (sapply(tmp$indexfrom, FUN=function(x) format(index(asset)[x])))
  tmp$datesto <- (sapply(tmp$indexto, FUN=function(x) format(index(asset)[x])))
  tmp$dates <- apply(cbind(tmp$indexfrom, tmp$indexto), 2, FUN=function(x) format(index(asset)[x]))

  # merging dates for selection (i.e. "2012-01-02::2012-01-05") and calculation of cumulative product
  tmp$txtdates <- paste(tmp$datesfrom, tmp$datesto, sep="::")
  # extracting consequent growth/drawdowns
  tmp$drawdowns.sequences <- lapply(tmp$txtdates, function(i) tmp$asset.roc[i])
  # calculating cumulative products for extracted sub-series
  tmp$drawdowns.sequences.cumprods <- lapply(tmp$drawdowns.sequences, function(x) cumprod(1+x)-1)

  # generating final result
  result <- list()
  result$len <- tmp$indexto - tmp$indexfrom + 1
  result$cumgrdd <- xts(unlist(tmp$drawdowns.sequences.cumprods), index(tmp$asset.roc))

  return(result)
}

# let's test
getSymbols("SPY", from="2012-01-01")
spy.cl <- Cl(SPY)
spy.grdd <- my.cumulative.grdd(spy.cl)
spy.grdd

【讨论】:

  • 我想我有一个更快的使用 for 循环的解决方案。你确定这是一个有效的解决方案吗?
【解决方案4】:

您可以使用 zig zag 点找到峰值和谷值,然后计算百分比减少/增加。例如

    s <- get(getSymbols('goog'))["2012::"]
    z <- ZigZag(s[,2:3],10,percent=TRUE)
    # 10 in this example is the sensitivity to changes. 
    # if you want to use closing prices use s instad of s[,2:3]

    # extract the extreme points
    z <- rbind(z[findPeaks(z)-1],z[findValleys(z)-1])
    # calculate the difference
    names(z) <- c("zig")
    z$PercentChange <- ((z - Lag(z)) / z) * 100 

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2022-12-31
    • 1970-01-01
    • 2016-08-20
    • 2019-06-06
    相关资源
    最近更新 更多