您需要为此类问题设置一个有限状态机,使用 VBA 或辅助列都没有关系。
所以有三种状态
(1)初始状态
(2)“已启动”状态
(3) 处于周期状态
三个过渡
(A) 从 (1) 到 (2) 发现超买股票时
(B) 从 (2) 到 (3) 找到下一个买进不足的股票时
(C) 当发现下一个超买股票时,从 (3) 回到 (1)。
所以你需要设置一个列来处理这些包含公式的状态和转换
=IF(AND(I2=1,H3>80),2,IF(AND(I2=2,H3<30),3,IF(AND(I2=3,H3>80),1,I2)))
从(比如)I3 开始(I2 设置为 1)。
那么你需要另外两个帮助列来计算句点的结束和开始
=IF(AND(I1=2,I2=3),MAX(J$1:J1)+1,"")
=IF(AND(I1=3,I2=1),MAX(K$1:K1)+1,"")
最后是一个专栏来总结差异
=IFERROR(INDEX(G$2:G$100,MATCH(ROWS(L$1:L1),J$2:J$100,0))-INDEX(G$2:G$100,MATCH(ROWS(L$1:L1),K$2:K$100,0)),"")
找到第 n 个周期的差异的 VBA 如下所示 - 您可以从(比如)I2 开始这样称呼它
=IFERROR(stock(G$2:G$100,H$2:H$100,ROWS(N$1:N1)),"")
所以当你拉下公式时,它会寻找下一个周期。
Option Explicit
Function Stock(Actual As Range, Predicted As Range, n As Integer) As Variant
Dim i, rows, LastRow, period As Long
Dim state As Integer
Dim startFound, endFound As Boolean
Dim actualValue, predictedValue, startValue, endValue As Double
state = 1
period = 0
startFound = False
endFound = False
rows = Actual.rows.Count
If rows <> Predicted.rows.Count Then
Stock = CVErr(xlErrValue)
Return
End If
For i = 1 To rows
actualValue = Actual.Cells(i, 1).Value
predictedValue = Predicted.Cells(i, 1).Value
If state = 1 And predictedValue > 80 Then
state = 2
Else
If state = 2 And predictedValue < 30 Then
state = 3
period = period + 1
If period = n Then
startValue = actualValue
startFound = True
End If
Else
If state = 3 And predictedValue > 80 Then
state = 1
If period = n Then
endValue = actualValue
endFound = True
Exit For
End If
End If
End If
End If
Next I
If startFound And endFound Then
Stock = startValue - endValue
Else
Stock = CVErr(xlErrValue)
End If
End Function