Maxime Mohnen
Maxime Mohnen

Reputation: 1

VBA: Using defined Arrays/Ranges within Loop

I am pretty new to VBA hence my current struggle and clumsy code. Within my code I am trying identify uncorrelated stocks for a study project. The idea is that my macro generates a correlation matrix, bounded the Stock Names and then loops through line by line to return the most "uncorrelated" stock for the underlying sample. However, I do not currently know whether there is just a referencing issue in my code or whether there is any fundamental issue. Any help would be much appreciated

Find below the relevant part of the script:

Sub Test()

Dim Names As Variant

Dim Ref As Variant

Set Names = Worksheets("Correlation Matrix").Range(Cells(1, 3), Cells(1, Stocks))

For i = 1 To Stocks

    Worksheets("Correlation Matrix").Activate

        Ref = Worksheets("Correlation Matrix").Range(Cells(i + 1, 3), Cells(i + 1, Stocks)).Value

    Worksheets("Main").Activate

        Worksheets("Main").Cells("O" & i + 4).FormulaArray = "=Index(" & Names.Address & ",MATCH(MIN(ABS(" & Ref.Address & " - 0),ABS(" & Names.Address & "- 0),0))"

Next i

End Sub

The "Correlation Matrix" worksheet looks like this:

           Disney        Microsoft     Apple         sp500 
Disney     1             0.764790855   0.737566223   0.832602399 
Microsoft  0.764790855   1             0.754724823   0.827980429
Apple      0.737566223   0.754724823   1             0.90982066
sp500      0.832602399   0.827980429   0.90982066    1

Upvotes: 0

Views: 75

Answers (2)

Tomalak
Tomalak

Reputation: 338406

Consider this approach:

In the correlation matrix, we only need to look at the numbers either "above" or "below" the diagonal line of "1"s. All other values are just a mirror image, looking at them would be a waste of time.

So we try to look at a triangle of coordinates:

        
   A (1)      B (2)         C (3)         D (4)         E (5)
1             Disney        Microsoft     Apple         sp500 
2  Disney     1             0.764790855   0.737566223   0.832602399 
3  Microsoft  0.764790855   1             0.754724823   0.827980429
4  Apple      0.737566223   0.754724823   1             0.90982066
5  sp500      0.832602399   0.827980429   0.90982066    1

Excel also counts columns from 1, that's what the numbers in the parenthesis are. The row-column coordinates we want to inspect could be the "lower" half, like this (the "x" marks the diagonal cells with value 1):

        
  A (1)      B (2)         C (3)         D (4)         E (5)
1
2            x
3            (3,2)         x
4            (4,2)         (4,3)         x
5            (5,2)         (5,3)         (5,4)         x

A nested loop can create those coordinate pairs. The loop runs for rows 3..5 and columns 2..4, respectively, but it excludes any columns outside of the "triangle":

Sub LeastCorrelated(NumStocks As Integer)
  Dim corrMatrix As Worksheet
  Dim minimumCell As Range, cell As Range
  Dim r As Integer, c As Integer
  Dim stock1 As String, stock2 As String

  Set corrMatrix = Worksheets("Correlation Matrix")
  Set minimumCell = corrMatrix.Cells(2, 2) ' the top-left cell containing "1"

  For r = 3 To NumStocks + 1
    For c = 2 To r - 1
      Set cell = corrMatrix.Cells(r, c)
      If cell.Value < minimumCell.Value Then Set minimumCell = cell
    Next
  Next

  minimumCell.Select
  stock1 = corrMatrix.Cells(1, minimumCell.Column).Value
  stock2 = corrMatrix.Cells(minimumCell.Row, 1).Value

  Debug.Print stock1 & " / " & stock2
End Sub

When called as

LeastCorrelated 4

this prints

Disney / Apple

and selects cell A4.

Upvotes: 1

Scott Holtzman
Scott Holtzman

Reputation: 27269

Dimension the variables as Range objects. Variant is a catch all data type and does not have a .Name property.

See below. I also changed Names variable since .Names refers to named ranges.

Sub Test()

Dim theNames As Range
Dim Ref As Range

Set theNames = Worksheets("Correlation Matrix").Range(Cells(1, 3), Cells(1, Stocks))

For i = 1 To Stocks

    'Worksheets("Correlation Matrix").Activate - no need to activate sheet

    Set Ref = Worksheets("Correlation Matrix").Range(Cells(i + 1, 3), Cells(i + 1, Stocks)).Value

    'Worksheets("Main").Activate - no need to activate sheet

    Worksheets("Main").Cells("O" & i + 4).FormulaArray = "=Index(" & theNames.Address & ",MATCH(MIN(ABS(" & Ref.Address & " - 0),ABS(" & theNames.Address & "- 0),0))"

Next i

End Sub

Upvotes: 0

Related Questions