You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言新旧代码调用quantmod计算收益及标准差结果不一致求助

问题修复指南

核心问题拆解

你的新代码和旧代码的核心差异是没有按ID分组处理,这直接导致了行偏移、跨ID计算错误,以及双周指标不符。另外未复刻旧代码的NA过滤、数据量判断逻辑,也是结果差异的关键原因。


1. 修复日收益率行偏移 + 跨ID计算错误

旧代码是循环每个ID单独处理,先过滤NA价格再计算指标,新代码直接全局计算完全忽略了分组逻辑,这是最致命的错误。用dplyr分组复刻旧逻辑,代码如下:

library(quantmod)
library(dplyr)

# 第一步:预处理数据,和旧代码逻辑对齐
AllPrices_clean <- AllPrices %>%
  # 过滤价格为空的行,对应旧代码的is.na(Prices$fg.price) == FALSE
  filter(!is.na(P_PRICE.0..400.D.)) %>%
  # 按ID+日期升序排序,确保Delt按时间顺序计算收益
  arrange(requestId, as.Date(date))

# 第二步:按ID分组计算所有指标
Prices <- AllPrices_clean %>%
  group_by(requestId) %>%
  mutate(
    # 日收益率:保留你需要的取反逻辑,和旧代码结果对齐
    DailyRet = Delt(P_PRICE.0..400.D., k=1) * -1,
    # 仅当组内价格数量>252时计算标准差,否则留NA(复刻旧代码的if判断)
    DailySD = if(n() > 252) {
      rollapply(DailyRet, width=252, FUN=sd, fill=NA, align="right") * sqrt(252)
    } else NA,
    # 双周收益率:按组内时间序列计算k=10的收益
    BiWeeklyRet = Delt(P_PRICE.0..400.D., k=10),
    BiWeeklySD = if(n() > 252) {
      rollapply(BiWeeklyRet, width=252, FUN=sd, fill=NA, align="right") * sqrt(25.2)
    } else NA
  ) %>%
  ungroup() %>%
  # 重命名列,匹配你需要的格式
  rename(
    ID = requestId,
    Date = date,
    Price = P_PRICE.0..400.D.
  ) %>%
  select(ID, Date, Price, DailyRet, DailySD, BiWeeklyRet, BiWeeklySD)

# 第三步:复刻旧代码的写入逻辑(按ID追加,仅写入数据量>252的ID)
MPTempFN <- "Prices.csv"
file.create(MPTempFN) # 先创建/清空目标文件
for(id in unique(Prices$ID)){
  subset_data <- Prices[Prices$ID == id, ]
  if(nrow(subset_data) > 252){
    write.table(subset_data, file=MPTempFN, append=TRUE, sep=",", col.names=FALSE, row.names=TRUE, qmethod="double")
  }
}

2. 解决双周收益/标准差不符的问题

按上述分组逻辑处理后,双周指标应该和旧代码对齐。如果仍有差异,检查两个关键点:

  • 日期连续性:旧代码的价格数据是否为连续交易日?如果新数据存在日期缺口,Delt(k=10)会取第10行而非间隔10天的价格。可以用xts格式处理时间序列,确保按日期对齐:
    # 拿单个ID测试验证
    test_id <- "你的测试ID"
    test_data <- AllPrices_clean %>% filter(requestId == test_id)
    test_xts <- xts(test_data$P_PRICE.0..400.D., order.by=as.Date(test_data$date))
    # 计算按交易日间隔的双周收益
    BiWeeklyRet_xts <- Delt(test_xts, k=10)
    # 和旧代码的BiWeeklyRet结果对比
    
  • Delt计算方向:确认新旧数据的日期排序是否一致,如果新数据是日期降序,Delt(k=10)的结果会和旧代码相反,此时需要给BiWeeklyRet也添加取反逻辑。

3. 日收益率需取反的问题

这说明新数据和旧数据的时间排序方向相反(比如旧代码是日期从旧到新,新代码是从新到旧)。建议先把日期序列改成升序,这样可以不用取反,避免后续逻辑混乱:

# 调整日期为升序(如果当前是降序,把desc改成asc即可)
AllPrices_clean <- AllPrices_clean %>% arrange(requestId, desc(as.Date(date)))
# 重新计算DailyRet,去掉*-1,验证是否和旧代码一致

内容的提问来源于stack exchange,提问作者DiegoM90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:35:38