R语言如何循环执行代码直到returns列无超出阈值的异常值
R语言循环修正异常收益率实现方法
要实现修正价格后重算收益率、直到不存在收益率超出[-0.33, 0.5]区间记录的逻辑,直接用while循环做终止判断即可,同时先修正原代码里的语法问题。
步骤1:封装单次处理逻辑
先把单轮数据清洗的逻辑封装成可重复调用的函数,注意原代码两处ungroup未加括号,会导致分组残留影响计算结果,已在封装代码中修正:
process_mkt_data <- function(raw_df) { # 基础去重+收益率初计算 df <- raw_df %>% group_by(investor, asset, datetime) %>% slice(1) %>% # 去除同一投资者、同一资产、同一日期的重复记录 group_by(investor, asset) %>% arrange(datetime) %>% mutate(returns = (fixprice - lag(fixprice))/lag(fixprice)) %>% mutate(returns = ifelse(is.na(returns), 0, returns)) %>% # 首行收益率空值替换为0 arrange(asset, datetime) %>% ungroup() # 标记异常收益率、计算调整系数 df <- df %>% mutate(ab_check = returns > 0.5 | returns < -0.33, ab_check = ifelse(is.na(ab_check), FALSE, ab_check)) %>% group_by(asset) %>% mutate(adjustm = ifelse(ab_check, fixprice/lag(fixprice), 1)) %>% ungroup() # 向下传递调整系数、修正价格和持仓量 df <- df %>% arrange(asset, datetime) %>% group_by(asset) %>% mutate(rows_to_mod = if_else(lag(ab_check) == TRUE, 1, NA_real_), new_adj = if_else(lag(ab_check) == TRUE, lag(adjustm), NA_real_)) %>% fill(rows_to_mod, new_adj) %>% replace_na(list(new_adj = 1)) %>% mutate(fixprice = fixprice / new_adj, fixquant = operation * new_adj) %>% ungroup() # 修正异常点本身的价格和持仓量 df <- df %>% group_by(asset) %>% mutate(fixprice = ifelse(ab_check, fixprice/adjustm, fixprice), fixquant = ifelse(ab_check, operation*adjustm, operation)) %>% ungroup() # 持仓量取整 df$fixquant <- round(df$fixquant) return(df) }
步骤2:编写循环终止逻辑
通过while循环反复调用处理函数,每次处理完成后统计剩余异常记录数,异常数为0时自动退出循环。建议增加最大循环轮次限制,避免特殊数据导致死循环:
# 配置参数 max_iter <- 20 # 最多处理20轮,可根据数据情况调整 current_iter <- 0 # 开始循环处理 while (current_iter < max_iter) { current_iter <- current_iter + 1 # 执行单轮处理 mktprice <- process_mkt_data(mktprice) # 统计剩余异常记录 abnormal_count <- sum(mktprice$returns > 0.5 | mktprice$returns < -0.33, na.rm = TRUE) # 打印运行进度 cat(paste0("第", current_iter, "轮处理完成,剩余异常收益率记录数:", abnormal_count, "\n")) # 无异常记录则提前终止循环 if (abnormal_count == 0) { cat("所有异常记录已修正完成\n") break } } # 循环跑完仍有异常的话给出提示 if (current_iter == max_iter & abnormal_count > 0) { warning(paste0("达到最大迭代轮次,仍剩余", abnormal_count, "条异常记录,请检查数据是否存在逻辑问题")) }
注意事项
- 原代码中
ungroup后未加括号,属于常见语法错误,实际不会执行取消分组操作,会导致后续所有计算带着残留分组,结果不符合预期,封装代码已修复该问题 - 原代码中
rows_to_mod = max(ab_check)这一步无实际作用,后续会被if_else的计算结果覆盖,已在封装代码中删除,不影响处理结果 - 250万行的数据量单轮处理速度不会太慢,如果轮次过多跑时长,可以按
asset分组拆分数据并行处理,进一步提升速度
内容的提问来源于stack exchange,提问作者Lorenzo Mazzucchelli
相关产品推荐
相关产品推荐

