I have been trying to use VBA for a couple of months now, but I'm not sure I code very efficiently when it comes to speed.
The below code is a calculation of zscores used in a ranking model for stocks. The calculation is quite simple, just a calculation of zscore=zscore1*weight1+zscore2*weight2....zscoreN*zscoreN
, where the zscores
are in different sheets and the weights are contained in an array. The code works, but with 500 stocks and 103 periods it takes about 30 seconds to complete. I was looking for advice to speed my code up / make it more "correct" as in terms of good programming practices.
I know my code is a bít messy, but since it works I just hoped I could get some general advice on my way to use loops, if-sentenses and arrays.
Public factor() As Single
Sub zscores()
Dim StartTime As Double, EndTime As Double
Dim sheetNames() As String
Dim r As Integer, i As Integer
Dim antalAktier As Integer, perioder As Integer
Dim zscore As Single
StartTime = Timer
Worksheets("ZScores").Range("B2:AAA1000").ClearContents
'perioder and antalAktier is just variables to determine number of stocks and periods
perioder = Application.WorksheetFunction.CountA(Worksheets("returns").Range("A2:A1500"))
antalAktier = Application.WorksheetFunction.CountA(Worksheets("returns").Range("B1:AAA1"))
'Makes an array of sheetnames
r = 1
i = 0
ReDim sheetNames(0)
Do Until Worksheets("BloomdataFLDS").Cells(r, 1).Value = ""
sheetNames(i) = Worksheets("BloomdataFLDS").Cells(r, 1).Value
i = i + 1
ReDim Preserve sheetNames(i)
r = r + 1
Loop
'factor() is an array of values from textboxes in a userform
'Code uses the sheetnames array to jump between sheets and making a weighted average of the cell values and factor array values
k = 2
For k = 2 To antalAktier + 1
r = 2
For r = 2 To perioder + 1
zscore = 0
For i = 0 To (UBound(factor) - 18)
zscore = zscore + (factor(i) * Worksheets(sheetNames(i)).Cells(r, k).Value)
Next i
'truncates the value to be max/min +/- 3
If Worksheets("binær").Cells(k, r).Value = 1 And Worksheets("returns").Cells(r, k).Value <> "#N/A N/A" Then
If zscore < 3 And zscore > -3 Then
Worksheets("ZScores").Cells(r, k).Value = zscore
ElseIf zscore < -3 Then
Worksheets("ZScores").Cells(r, k).Value = -3
ElseIf zscore > 3 Then
Worksheets("ZScores").Cells(r, k).Value = 3
End If
Else:
Worksheets("ZScores").Cells(r, k).Value = ""
End If
Next r
Next k
EndTime = Timer
MsgBox "Execution time in seconds: " + Format$(EndTime - StartTime)
End Sub