我建立的蒙特卡罗模拟有一个奇怪的问题。它是一个嵌套循环来计算投资的预期价值(实际上是扑克锦标赛)。为了演示,假设我们正在谈论单挑扑克锦标赛,这相当于硬币翻转。假设每个硬币翻转的投资回报率为25%,买入费为1,因此100(500,1000)次硬币翻转后的EV为25(125,250)个单位。然而,模拟分别返回24,6,123,6和246。 代码中的关键行在这里:
Randomize
randomnumber = Rnd()
If randomnumber > adjustedITM Then
MC_array(m, n) = -tournamentvariables(k, 6)
Else:
Randomize
MC_array(m, n) = CDec(tournamentstructures(Int(Rnd() * (tournamentvariables(k, 7)) + 1), k) * tournamentvariables(k, 6) * (1 - tournamentvariables(k, 5)) * tournamentvariables(k, 2) - tournamentvariables(k, 6))
End If
第二个MC_array(m,n)是关键的代码行。如果玩家获胜,它会给出净利润。在硬币翻转的情况下,这是一个单元。如果我将第二行更改为
Randomize
If Rnd() > adjustedITM Then
MC_array(m, n) = -tournamentvariables(k, 6)
Else:
Randomize
MC_array(m, n) = 1
End If
结果是正确的。第二次MCarray简化为硬币翻转后的代码:
CDec(tournamentstructures(Int(Rnd() * (tournamentvariables(k, 7)) + 1), k) * tournamentvariables(k, 6) * (1 - tournamentvariables(k, 5)) * tournamentvariables(k, 2) - tournamentvariables(k, 6))
=
CDec(tournamentstructures(1,1) * 1 * (1 - 0%) * 2 - 1)
所以它与一个完全相同。数组tournamentstructures()的大小为(1,1),所以它无法读取任何内容。我确认所有结果都是整数(对于硬币翻转你只能赢或输一个单位),我强烈怀疑随机数发生器有点偏颇。
我声明代码中的所有内容都是变体,并排除第二个Randomize而不改变偏差。那么伙计们,这是怎么回事?
答案 0 :(得分:1)
看起来你反复打电话给Randomize
,可能是紧张循环的一部分。每次调用它时,它都会从系统时钟重新生成随机数生成器。每次通过循环都这样做会引入自相关(虽然确切地说并不是很清楚)。
考虑以下实验:
Sub Test()
Dim i As Long, A As Variant
Dim count1 As Long, count2 As Long
ReDim A(1 To 10000)
For i = 1 To 10000
Randomize
A(i) = IIf(Rnd() < 0.5, 0, 1)
Next i
'count how often A(i) = A(i+1)
For i = 1 To 9999
If A(i) = A(i + 1) Then count1 = count1 + 1
Next i
For i = 1 To 10000
A(i) = IIf(Rnd() < 0.5, 0, 1)
Next i
'count how often A(i) = A(i+1)
For i = 1 To 9999
If A(i) = A(i + 1) Then count2 = count2 + 1
Next i
Debug.Print "First Loop: " & count1
Debug.Print "Second Loop: " & count2 & vbCrLf
End Sub
典型输出:
First Loop: 5452
Second Loop: 4996
我已经跑了好几次了。第一个循环几乎总是产生一个与5000相差很大的数字,而第二个循环几乎总是产生一个相当接近5000的数字(如果对Rnd
的连续调用对应于独立的随机变量,则预期值为4999.5 - - 因此在重复播种时明显缺乏独立性。)
故事的道德:在模拟中调用Randomize
只需一次,比如作为主要子的第一行。或者,使用Application.WorksheetFunction.RandBetween(0,1)
并让Excel担心播种。
如果此自相关无法解释错误,则问题在于您尚未显示的代码,因此您需要包含该代码。