0

该代码(采用随机生成的二维数组(R,C))并将结果分解为每个月(21 天)的 2 个数组(1 个表示平均值,1 个表示曝光)

 Public R As Double
 Public C As Integer
 Public Strike,Spot,Ton  As Double
 Public Ton As Double
 Public AVG(), EXP(), w() As Variant
 ''''''''''''''
 Sub Start()
 sss = SetParmeters()
 MonteCarlo (Copy2Array())
 i = calcW()
 cpSheet (True)
 End Sub 
 '''''''''''''''
  Function SetParmeters() As Boolean
 Dim w As Worksheet
 Set w = Worksheets("Copper daily moves")
R = w.Range("cc")
C = w.Range("row")
Strike = w.Range("strike")
Spot = w.Range("spot")
Ton = w.Range("ton")
End Function                       
'''''''''''''''''''
Function Copy2Array() As Variant
  Dim w As Worksheet
  Set w = Worksheets("Copper daily moves")
  Copy2Array = w.Range("price")
 End Function
''''''''''''''''''''
 Function MonteCarlo(p As Variant)
 ReDim w(R, C)
 For i = 0 To R
 s = Spot
 For j = 0 To C
 w(i, j) = s * (1 + p(Application.WorksheetFunction.RandBetween(1, 1275), 1))
 s = w(i, j)
 Next j
 Next i
 End Function
''''''''''''''''
 Function calcW() As Boolean
 ReDim AVG(R, (C / 21) - 1)
 ReDim EXP(R, (C / 21) - 1)
 Count21 = 0
 countW = 0
 For i = 0 To R
 Sum = 0
 countW = 0
 Count21 = 21
 For j = 0 To C
 Sum = Sum + w(i, j)
 If Count21 = j Then
 AVG(i, countW) = Sum / 21
 If Strike > AVG(i, countW) Then
 EXP(i, countW) = (Strike - AVG(i, countW)) * ((C / 21) - countW) * Ton
 Else
 EXP(i, countW) = 0
 End If
 countW = countW + 1
 Count21 = Count21 + 21
 Sum = 0
 End If
 Next j
 Next i
 End Function
''''''''''''''
Sub cpSheet(flag)
Addr = "$A$1"
Addr = Addr & ":" & Range(Addr).Cells(UBound(AVG), _
UBound(AVG, 2) + 1).Address
Worksheets("AVG").Range(Addr).Value = AVG
Worksheets("EXP").Range(Addr).Value = EXP
End Sub

主要问题是处理数据需要很长时间(尤其是在进行 100k 模拟(行)及以上时),因此使用 excel 表格而不是 VBA 可能会更快!

我用 (R=100k ,c=252) 对其进行了测试,大约需要 8 分钟,有没有办法优化代码以使其运行得更快?

4

1 回答 1

1

尽量不要使用 Variant 类型,并使用

Application.ScreenUpdating = False

在代码的早期和

Application.ScreenUpdating = True

...在代码的末尾。

另一个技巧是将“/”除法(返回单个值)替换为“\”除法(返回整数值)。这,特别是在一个循环内,可以提高一点他的表现。

于 2015-09-07T10:36:12.123 回答