Вопрос или проблема
‘Данный код VBA для биномальных опционов содержит отсутствующий синтаксис, предназначенный для создания матрицы цен на акции размером N на N с использованием входных данных для оценки биномальных деревьев опционов с дискретными дивидендами, сохранёнными как именованный диапазон “Dividends” в MS Excel.
Идея состоит в том, что конечная матрица акций используется для рекурсивного расчёта окончательной стоимости опциона, хотя функция Binomial возвращает #VALUE. Пожалуйста, помогите определить, какие операторы Dim и ReDim и т.д. необходимо добавить в ndivs, divsum и т.д., чтобы создать раздел Первой матрицы акций и Финальной матрицы акций для расчёта оставшихся записей для раздела Опционов на покупку и продажу. Спасибо.’
Function Binomial(Spot, K, T, r, sigma, n, PutCall As String, EuroAmer As String, Dividends)
dt = T / n: u = Exp(sigma * (dt ^ 0.5)):
d=1/u a = Exp(r * dt):
p = (a - d) / (u - d) ndivs = Application.Count(Dividends) / 3
Dim ndivs As Double
ndivs = Application.Count(Dividends) / 3
' Дерево для цены акций
Dim S() As Double
Dim Tau() As Double
Dim Div() As Double
Dim Rate() As Double
Dim divsum() As Double
'Создаёт массивы с выплатами дивидендов в массиве Div(), временем
' выплат в массиве Tau(), и процентной ставкой, применяемой к каждой выплате дивидендов в массиве
divsum = 0
For i = 1 To ndivs
Tau(i) = Dividends(i, 1)
Div(i) = Dividends(i, 2)
Rate(i) = Dividends(i, 3)
divsum = divsum + Div(i) * Exp(-Rate(i) * tau(i))
Next i
'Первая матрица акций temp (i, j) для создания начальных цен на акции
Dim Temp() As Double
ReDim Temp(n + 1, n + 1) As Double
temp(1, 1) = Spot - divsum
For i = 1 To n + 1
For j = i To n + 1
temp(i, j) = temp(1, 1) * u ^ (j - i) * d ^ (i - 1)
Next j
Next i
'Финальная матрица акций S(i, j) для добавления первой матрицы акций с
' дополнительными дисконтированными дивидендами из Div()
ReDim S(n + 1, n + 1) As Double
S(1, 1) = temp(1, 1) + divsum
For j = 2 To n + 1
For i = 1 To j
If tau(1) < (j - 1) * dt Then S(i, j) = temp(i, j)
Else S(i, j) = temp(i, j) + Div(1) * Exp(-Rate(1) * (tau(1) - (j - 1) * dt))
Next i
Next j
For z = 2 To ndivs
For j = 2 To n + 1
For i = 1 To j
If tau(z) < (j - 1) * dt Then S(i, j) = S(i, j)
Else S(i, j) = S(i, j) + Div(z)* Exp(-Rate(z) * (tau(z) - (j - 1) * dt))
Next i
Next j
Next z
End Function
'Изначально модель содержит выплаты дивидендов в массиве Div(), время выплат в
массиве Tau(), и процентную ставку, применяемую к каждой выплате дивидендов в массиве Rate().
Затем опция создаёт Первую матрицу акций temp (i, j) для создания начальных цен на акции.
Наконец, создаётся Финальная матрица акций, чтобы добавить первую матрицу акций с дополнительными дисконтированными дивидендами для дальнейшего расчёта окончательной стоимости опциона. Спасибо.'
Ответ или решение
Ошибка #VALUE в функции VBA может возникать по нескольким причинам при создании многомерного массива для хранения цен акций из именованного диапазона. Давайте рассмотрим проблемные области вашего кода и предложим соответствующие исправления.
1. Ошибки в объявлениях переменных
В вашем коде существует несколько мест, где объявление и перераспределение массивов (ReDim) могут быть неоптимальными или неправильными. Убедитесь, что все массивы имеют правильные размеры и правильно инициализируются.
2. Неверное использование индексов массива
VBA массивы по умолчанию индексируются с 0, если вы не задаете иное. Если ваши данные в Dividends
имеют одну строку на каждый элемент, то вам, возможно, потребуется скорректировать индексацию.
3. Ошибки в расчетах
Проверьте вашу логику расчетов, связанные с временными интервалами (tau
) и скидками. Убедитесь, что индексы и показаемая логика корректны.
4. Задание значений Div и других массивов
При определении и заполнении массивов, таких как Div
, Tau
, и Rate
, убедитесь, что вы корректно задаете размерность. Например, вы используете индексы 1 to ndivs
, которые не соответствуют размеру массива в VBA без явного указания начального элемента.
Исправленный код
Вот модифицированный фрагмент вашего кода, который устраняет некоторые из вышеупомянутых проблем:
Function Binomial(Spot As Double, K As Double, T As Double, r As Double, sigma As Double, n As Long, PutCall As String, EuroAmer As String, Dividends As Range)
Dim dt As Double, u As Double, d As Double, a As Double, p As Double
Dim ndivs As Long, i As Long, z As Long, j As Long
Dim divsum As Double
Dim Tau() As Double, Div() As Double, Rate() As Double
Dim Temp() As Double, S() As Double
dt = T / n
u = Exp(sigma * Sqr(dt))
d = 1 / u
a = Exp(r * dt)
p = (a - d) / (u - d)
ndivs = Application.Count(Dividends) ' Количество дивидендов
ReDim Tau(1 To ndivs) As Double
ReDim Div(1 To ndivs) As Double
ReDim Rate(1 To ndivs) As Double
divsum = 0
' Заполнение массивов дивидендов
For i = 1 To ndivs
Tau(i) = Dividends(i, 1)
Div(i) = Dividends(i, 2)
Rate(i) = Dividends(i, 3)
divsum = divsum + Div(i) * Exp(-Rate(i) * Tau(i))
Next i
' Создание матрицы цен акций
ReDim Temp(1 To n + 1, 1 To n + 1) As Double
Temp(1, 1) = Spot - divsum
For i = 1 To n + 1
For j = i To n + 1
Temp(i, j) = Temp(1, 1) * u ^ (j - i) * d ^ (i - 1)
Next j
Next i
' Создание финальной матрицы цен акций
ReDim S(1 To n + 1, 1 To n + 1) As Double
S(1, 1) = Temp(1, 1) + divsum
For j = 2 To n + 1
For i = 1 To j
If Tau(1) < (j - 1) * dt Then
S(i, j) = Temp(i, j)
Else
S(i, j) = Temp(i, j) + Div(1) * Exp(-Rate(1) * (Tau(1) - (j - 1) * dt))
End If
Next i
Next j
For z = 2 To ndivs
For j = 2 To n + 1
For i = 1 To j
If Tau(z) < (j - 1) * dt Then
S(i, j) = S(i, j)
Else
S(i, j) = S(i, j) + Div(z) * Exp(-Rate(z) * (Tau(z) - (j - 1) * dt))
End If
Next i
Next j
Next z
End Function
Заключение
Проведя изменения, вы сможете избежать ошибки #VALUE и успешно создать матрицы цен акций. Обратите внимание на корректное разделение и инициализацию массивов, а также на правильное использование индексов. Это гарантирует, что ваш код не только компилируется, но и работает правильно.