You are on page 1of 9

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.

bas

Sunday, November 3, 2013 9:42 AM

Attribute VB_Name = "Algebra" '---------------------------------------------------------------'Leonid Sopotnitskiy, 2nd January 2013 'Certificate in Quantitative Finance 'Final Project: kth to default CDS pricing by Copula '---------------------------------------------------------------'Please see comments containing descriptions of numerical 'techniques implemented in the task. 'All variables are declared explicitly. Option Explicit

'-----------------------------------------------' MEAN CALCULATION CODE '-----------------------------------------------Function Mean(rng As Variant) As Variant Dim Arr As Variant 'array containing the input values Dim I As Integer, n As Integer, temp_mean As Double ' i - row index ' n - total number of rows in array ' temp_maen - dummy sum of values within the array Arr = rng I = 1 n = UBound(Arr, 1) 'I now enter a loop to sum up all the values in the array While I <= n temp_mean = temp_mean + Arr(I, 1) I = I + 1 Wend Mean = temp_mean / n 'the function returns the value of the mean End Function '-----------------------------------------------' VARIANCE CALCULATION CODE '-----------------------------------------------Function Variance(rng As Variant) As Variant Dim Arr As Variant Dim mu As Double, temp_var As Double Dim I As Integer, n As Integer Arr = rng 'array containing the input values mu = Mean(Arr) 'calculated mean n = UBound(Arr, 1) 'total number of rows in array 'this loop calculates the variance of the input values For I = 1 To n
-1-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

temp_var = temp_var + (Arr(I, 1) - mu) ^ 2 / n Next I Variance = temp_var 'the last coefficient is for scaling purposes End Function '-----------------------------------------------' COVARIANCE CALCULATION CODE ' this algorithm is required to calculate the ' elementwise covariances that will be placed off ' the diagonal in the covariance matrix '-----------------------------------------------Function Covariance(x As Variant, y As Variant) As Variant Dim ArrX As Variant, ArrY As Variant Dim muX As Double, muY As Double, temp_covar As Double Dim I As Integer, n As Integer muX = Mean(x) ' calculate the mean of array 1 muY = Mean(y) ' calculate the mean of array 2 ArrX = x ArrY = y n = UBound(ArrX, 1) ' since the arrays should be of the same size, I will use a single variable to ' store the number of values in them 'the following loop calculates the covariance of the input data For I = 1 To n temp_covar = temp_covar + ((ArrX(I, 1) - muX) * (ArrY(I, 1) - muY)) Next I Covariance = (temp_covar / n) 'the last coefficient is used for scaling factors End Function '--------------------------------------------------' COVARIANCE MATRIX CALCULATION CODE ' this function generates a covariance matrix ' and implements the Variance & Covariance functions ' coded in this module '--------------------------------------------------Function CovarianceMatrix(rng As Variant) As Variant Dim Dim I = j = ArrX As Variant, ArrY As Variant, CMtx As Variant I As Integer, j As Integer, n As Integer rng.rows.Count rng.columns.Count

ReDim CVMtx(1 To j, 1 To j) ' the output is a jxj symmetric matrix ' with variances stored on the diagonal and ' covariances placed off the diagonal. 'ArrX & ArrY store different vectors of data that is required to calculate 'covariance ReDim ArrX(1 To I, 1) ReDim ArrY(1 To I, 1)
-2-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

'the following algorithm calculates and places the variances and covariances 'of the input data For j = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrX(n, 1) = rng(n, j) Next n For I = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrY(n, 1) = rng(n, I) Next n If I = j Then CVMtx(I, j) = Variance(ArrX) 'the diagonal of the matrix contains variances Else CVMtx(I, j) = Covariance(ArrX, ArrY) 'off-diagonal values are covariances End If Next I Next j CovarianceMatrix = CVMtx 'output End Function ' The next 2 functions were done for testing purposes: ' in order to build a covariance matrix, we could also ' create a correlation matrix P and a variance matrix ' S, that would contain variances on the diagonal and ' zeros everywhere else. We could then apply the following formula: ' ' Covariance Matrix = S^0.5 * P * S^0.5 (P. Wilmott on Quantitative Finance Vol. 1, Ch. 11, p.184) ' ' or in VBA it would be: ' ' CovarianceMatrix = MtxMultiply(MtxMultiply(VarianceMatrix(rng) _ ^ 0.5, CorrelationMatrix(rng)), VarianceMatrix(rng) ^ 0.5) ' ' the result would be the same. '-----------------------------------------------' VARIANCE MATRIX CALCULATION CODE ' this function returns a variance matrix, i.e. ' it contains zeros off its diagonal. '-----------------------------------------------Function VarianceMatrix(rng As Variant) As Variant Dim matrix As Variant, VMtx As Variant Dim I As Integer, j As Integer, n As Integer I = rng.rows.Count j = rng.columns.Count ReDim VMtx(1 To j, 1 To j) 'the output will be a symmetric jxj matrix ReDim matrix(1 To I, 1) 'this matrix will store individual columns
-3-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

'The following loops build the variance matrix. For j = 1 To rng.columns.Count For I = 1 To rng.columns.Count If I = j Then For n = 1 To rng.rows.Count matrix(n, 1) = rng(n, j) 'columns are copied into separate arrays Next n VMtx(I, j) = Variance(matrix) 'the variance of values contained in the input array Else VMtx(I, j) = 0 'off-diagonal elements are 0, as we are not interested in covariance here End If Next I Next j VarianceMatrix = VMtx 'output End Function '------------------------------------------------------' A simple linear correlation function, ' calculating correlation between 2 variables / arrays '------------------------------------------------------Function Correlation(a As Variant, B As Variant) As Variant Dim ArrA As Variant, ArrB As Variant Dim I As Integer If TypeName(a) = "Range" Then I = a.rows.Count Else I = UBound(a, 1) End If ReDim ArrA(1 To I, 1) 'ArrX & ArrY store various arrays which ReDim ArrB(1 To I, 1) 'will be analyzed for correlation. ArrA = a ArrB = B Correlation = Covariance(ArrA, ArrB) / ((Variance(ArrA) * Variance(ArrB)) ^ 0.5) End Function '-----------------------------------------------' CORRELATION CALCULATION CODE ' this function produces a matrix with calculated ' correlations of vectors of the input array. '-----------------------------------------------Function CorrelationMatrix(rng As Variant) As Variant Dim ArrX As Variant, ArrY As Variant, CMtx As Variant Dim I As Integer, j As Integer, n As Integer I = rng.rows.Count j = rng.columns.Count ReDim CMtx(1 To j, 1 To j) ReDim ArrX(1 To I, 1) 'ArrX & ArrY store various arrays which ReDim ArrY(1 To I, 1) 'will be analyzed for correlation.
-4-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

' The following loop performs an element-wise calculation of correlations ' by switching vectors. For j = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrX(n, 1) = rng(n, j) Next n For I = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrY(n, 1) = rng(n, I) Next n If I = j Then CMtx(I, j) = 1 'the diagonal of the matrix should contain 1's Else ' correlation is computed in this part of the code CMtx(I, j) = Covariance(ArrX, ArrY) / ((Variance(ArrX) * Variance(ArrY)) ^ 0.5) End If Next I Next j CorrelationMatrix = CMtx 'output End Function '-----------------------------------------------' TRANSPOSE MATRIX CODE ' this function produces a transposed matrix. '-----------------------------------------------Function Transpose(a As Variant) As Variant Dim I As Integer, j As Integer, AT As Variant I = a.rows.Count j = a.columns.Count ReDim AT(1 To j, 1 To I) 'setting the dimensions for the target matrix

While I > 0 j = a.columns.Count While j > 0 AT(j, I) = a(I, j) ' remapping of matrix elements j = j - 1 Wend I = I - 1 Wend Transpose = AT 'output End Function '-----------------------------------------------' MATRIX MULTIPLICATION CODE ' this function multiplies 2 matrices '-----------------------------------------------Function MtxMultiply(a As Variant, B As Variant) As Variant
-5-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

Dim ia As Integer, ja As Integer, ib As Integer, jb As Integer Dim I As Integer, j As Integer, z As Integer Dim temp_Mtx As Variant, v1 As Variant, v2 As Variant ia ja ib jb = = = = a.rows.Count ' #rows in A a.columns.Count ' #columns in A B.rows.Count ' #rows in B B.columns.Count ' #columns in B

'creating dimensions for the output product matrix ReDim temp_Mtx(1 To ia, 1 To jb) 'the following code does element-wise multiplication of matrix A and B For I = 1 To ia For j = 1 To jb For z = 1 To ja temp_Mtx(I, j) = temp_Mtx(I, j) + a(I, z) * B(z, j) Next z Next j Next I MtxMultiply = temp_Mtx 'output End Function '-----------------------------------------------------------------------' Cholesky Decomposition coded in the following function ' Returns the lower matrix A (M = A x A_transposed) '-----------------------------------------------------------------------Function cholesky(matrix As range) Dim I As Integer, j As Integer, k As Integer, n As Integer Dim a() As Double Dim element As Double Dim L_Lower() As Double n = matrix.columns.Count ReDim a(1 To n, 1 To n) ReDim L_Lower(1 To n, 1 To n) 'copying values into array For I = 1 To n For j = 1 To n a(I, j) = matrix(I, j).Value L_Lower(I, j) = 0 Next j Next I For I = 1 To n For j = 1 To n element = a(I, j) For k = 1 To I - 1 element = element - L_Lower(I, k) * L_Lower(j, k) Next k If I = j Then L_Lower(I, I) = Sqr(element)
-6-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

ElseIf I < j Then L_Lower(j, I) = element / L_Lower(I, I) End If Next j Next I cholesky = L_Lower End Function 'Spearman's Rho ranked correlation matrix Function RhoMatrix(rng As Variant) As Variant

Dim ArrX As Variant, ArrY As Variant, CMtx As Variant Dim I As Integer, j As Integer, n As Integer I = rng.rows.Count j = rng.columns.Count ReDim CMtx(1 To j, 1 To j) ReDim ArrX(1 To I, 1) 'ArrX & ArrY store various arrays which ReDim ArrY(1 To I, 1) 'will be analyzed for correlation. ' The following loop performs an element-wise calculation of correlations ' by switching vectors. For j = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrX(n, 1) = rng(n, j) Next n For I = 1 To rng.columns.Count For n = 1 To rng.rows.Count ArrY(n, 1) = rng(n, I) Next n If I = j Then CMtx(I, j) = 1 'the diagonal of the matrix should contain 1's Else ' correlation is computed in this part of the code CMtx(I, j) = SpearmanRho(ArrX, ArrY) End If Next I Next j RhoMatrix = CMtx 'output End Function 'Spearman's Rho ranked correlation Function SpearmanRho(x As Variant, y As Variant) As Variant SpearmanRho = Correlation(RankIndex(x), RankIndex(y)) End Function 'Determination of ranks of data Function RankIndex(x As Variant) As Variant Dim I As Integer, j As Integer, n As Integer Dim test As Variant Dim Rank As Variant If TypeName(x) = "Range" Then n = x.rows.Count
-7-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

Else n = UBound(x, 1) End If ReDim Rank(1 To n, 1 To 1) 'The algorithm that I use is the following: 'each row in the output matrix is assigned a single value - the number of input rows 'and then each element goes through a pair-wise comparison and each time there is an element 'which is larger, the rank assigned to this element is being reduced by 1. For I = 1 To n Rank(I, 1) = n test = x(I, 1) For j = 1 To n If test < x(j, 1) Then Rank(I, 1) = Rank(I, 1) - 1 End If Next j Next I RankIndex = Rank End Function 'KENDALL's TAU function Public Function KendallTau(xRange As range, yRange As range) As Double Dim n As Long Dim xRange_Array() As Double Dim yRange_Array() As Double n = xRange.rows.Count ReDim xRange_Array(1 To n) ReDim yRange_Array(1 To n) Dim I As Long, j As Long, acc As Double acc = 0 For I = 1 To n For j = I To n If I = 1 Then xRange_Array(j) = xRange.Cells(j) yRange_Array(j) = yRange.Cells(j) End If acc = acc + Sgn((xRange_Array(I) - xRange_Array(j)) * (yRange_Array(I) yRange_Array(j))) Next j Next I KendallTau = acc * 2 / n / (n - 1) End Function 'returns the maximum of 2 values Function MAXIMUM(a As Variant, B As Variant) As Variant If a > B Then MAXIMUM = a Else
-8-

C:\Users\chanmu\Desktop\vba\kbasket\Algebra.bas

Sunday, November 3, 2013 9:42 AM

MAXIMUM = B End If End Function 'linear interpolation which will be used to interpolate the discount factors 'when calculating the CDO leg premiums. Function interpolateDF(y As Variant, x As Variant) As Variant Dim I As Integer Dim B As Integer Dim n As Integer If x = 0 Then interpolateDF = 0 Exit Function End If If TypeName(y) = "Range" Then n = y.rows.Count Else n = UBound(y, 1) End If

For I = 1 To n If x < I And x > 0 Then If I = 1 Then interpolateDF = 1 Exit Function ElseIf I > 1 Then interpolateDF = y(I - 1) + (y(I) - y(I - 1)) * (CDbl(x) - (I - 1)) Exit Function End If End If Next I End Function

-9-