基于阈值穿越的多头持仓策略向量获取及收益索引合理性问询
解决滚动均值穿越信号的持仓时间与收益计算问题
一、生成持仓时间向量的简洁方案
你需要先识别真正的穿越信号(而非所有正收益的日子):向上穿越(从负/零转正,触发做多)和向下穿越(从正转负/零,触发平仓),再基于这两类信号生成持仓区间。
用Base R就能通过核心代码快速实现,逻辑如下:
- 精准识别向上/向下穿越的信号点
- 配对入场与平仓信号(处理边界情况)
- 生成完整的持仓天数集合
# 1. 定义严谨的穿越信号(处理NA和零值) goLong <- (Returns > 0) & c(FALSE, Returns[-length(Returns)] <= 0) # 向上穿越:当日>0,前一日<=0 goShort <- (Returns <= 0) & c(FALSE, Returns[-length(Returns)] > 0) # 向下穿越:当日<=0,前一日>0 # 2. 提取信号位置并配对(处理最后无平仓信号的情况) initiate <- which(goLong) terminate <- which(goShort) if (length(initiate) > length(terminate)) terminate <- c(terminate, length(Returns)) # 3. 生成所有持仓天数 hold_days <- unlist(mapply(function(s, e) (s+1):e, initiate, terminate))
用你给出的例子测试:Returns>0的位置是3,4,5,9,10,11,...,这段代码会生成4:6,10:12,...,完全匹配你需要的持仓时间向量。
二、你的代码逻辑验证:是否存在未来数据问题?
你的代码逻辑完全正确,没有未来数据偏差,理由如下:
- 你在第
Initiate_Long_Position[i]日观察到做多信号后,从i+1日开始持仓并获取当日收益,这是典型的「滞后执行」策略——用已发生的信号决定下一期操作,完全没有用到未发生的未来数据。 - 平仓时在
Terminate_Long_Position[i]日获取当日收益再平仓,符合「实时执行」逻辑,也没有提前使用后续数据。
小优化建议
- 信号生成部分:直接用
(Returns > 0) & c(FALSE, Returns[-length(Returns)] <=0)的写法,比ifelse(goLong == TRUE,1,0) ==1更简洁高效。 - 信号配对逻辑:如果
goShort是严格的向下穿越信号,一般不会出现length(Terminate) > length(Initiate)的情况,除非策略启动前就有平仓信号——你现在的处理(去掉第一个平仓信号)是合理的,但可以从信号生成源头优化(比如默认第一天的goShort为FALSE)。
内容的提问来源于stack exchange,提问作者user3612816
相关产品推荐
相关产品推荐

