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
相关产品推荐
相关产品推荐

