При торговле опционами весьма неплохо знать и понимать теорию Блэка и Шоулса. Можно, конечно, смотреть профили позиций и прочее на многочисленных специальных сервисах типа
www.option.ru, но, как известно, хочешь сделать хорошо--сделай все сам. В применении к опционам это вполне правильная вещь--не стоит доверять сторонним сервисам. Не потому, что они плохи (они обычно вполне корректно все рассчитывают), а потому, что опционы надо чувствовать.
Краткая и лаконичная суть теории Блэка и Шоулса изложена здесь:
http://anatoly-utkin.livejournal.com/2835.html . Ничего сложного в ней нет, это просто теория эффективного рынка в применении к опционам, не более. В настоящей заметке я хотел бы привести некоторые быстрые расчетные методы для работы с формулой Блэка-Шоулса, позволяющие быстро находить цены опционов и IV.
Итак, формула Блэка-Шоулса имеет вид: C=KN(d1)-SN(d2) (
Wikipedia ). Первое, что тут есть из нетривиального--это функция N(x)--функция нормального распределения. В трейдерской тусовке модно аппроксимировать N(x) полиномом, однако мне это режет глаз, поскольку при этом не выполнено экспоненциальное стремление N(x) к единице на плюс бесконечности и к нулю на минус бесконечности. Поэтому такая метода мне абсолютно не нравится.
Вообще, N(x)--это интеграл от простой и имеющейся во всех приличных языках программирования экспоненциальной функции exp(-x^2). Однако, влобовую брать интегралы через интегральные суммы--дело накладное в плане вычислительных мощностей. Для нормального распределения существует множество асимптотических формул. Одну из них--так называемый T алгоритм--я и использую. Математическое описание T алгоритма:
http://algolist.manual.ru/maths/matstat/NormalDF/NormalDF1.php
Код VBA:
Function FERT(x As Single) As Single
Dim i%, n%
Dim S!, T!, s1!, x2!, epsilon!
epsilon = 0.00001
s1 = 0
T = Abs(x)
s1 = T
x2 = x ^ 2
n = 3
For i = 0 To 100
T = x ^ 2 * T / n
S = s1
s1 = S + T
n = n + 2
If Abs(S — s1) < epsilon Then GoTo 10
Next i
10 If x >= 0 Then FERT = 0.5 + s1 * NORM(x)
If x < 0 Then FERT = 0.5 — s1 * NORM(x)
'FERT = FERT — 0.5
If x < -10 Then FERT = 0
If x > 10 Then FERT = 1
End Function
Здесь NORM(x)=1/sqrt(2pi)*exp(-x^2/2)--плотность единичного нормального распределения, ее код:
Function NORM(x As Single) As Single
NORM = Exp(-x ^ 2 / 2) / (2 * 3.1415926) ^ (0.5)
End Function
Вторая нетривиальная и часто нужная вещь в формуле БШ--это как найти волатильность при известной цене опциона. Иными словами, нужно обратить формулу Блэка-Шоулса и найти в ней величину z=sigma*sqrt(T) по известным C, K, S. Для этого я использую метод Ньютона (
Wikipedia ). Введем вспомогательную функцию g(z)=KN(d1)-SN(d2)-C. Тогда искомая величина z будет решением уравнения g(z)=0. g(z)--это хорошая, аналитическая, достаточно плавная функция своего аргумента. Поэтому метод Ньютона для нее будет работать хорошо. Суть метода Ньютона неплохо поясняет картинка ниже:
а его итерационная формула имеет простой вид: z_next=z-f(z)/(df/dz(z)).Особую прелесть именно методу Ньютона в применении к формуле Блэка-Шоулса придает тот факт, что производная от C по волатильности (так называемая вега) имеет простой вид S*NORM(d1)*sqrt(T). Код VBA:
Function IV_C(S As Single, K As Single, C As Single) As Single
Dim x!, x_next!, f!, df!, epsilon!
Dim i%, i_max%
epsilon = 0.00001
x = 0.5
i_max = 15
For i = 1 To i_max
f = C — S * FERT((Log(S / K) + x ^ 2 / 2) / x) + K * FERT((Log(S / K) — x ^ 2 / 2) / x)
df = -S * NORM((Log(S / K) + x ^ 2 / 2) / x)
x_next = x — f / df
If (Abs(x — x_next)) < epsilon Then GoTo 20
x = x_next
Next i
20 IV_C = x
End Function
Ну и напоследок общий финальный код VBA, объединяющий все эти вещи и позволяющий вертеть формулу Блэка-Шоулса во все стороны:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function NORM(x As Single) As Single
NORM = Exp(-x ^ 2 / 2) / (2 * 3.1415926) ^ (0.5)
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function FERT(x As Single) As Single
Dim i%, n%
Dim S!, T!, s1!, x2!, epsilon!
epsilon = 0.00001
s1 = 0
T = Abs(x)
s1 = T
x2 = x ^ 2
n = 3
For i = 0 To 100
T = x ^ 2 * T / n
S = s1
s1 = S + T
n = n + 2
If Abs(S — s1) < epsilon Then GoTo 10
Next i
10 If x >= 0 Then FERT = 0.5 + s1 * NORM(x)
If x < 0 Then FERT = 0.5 — s1 * NORM(x)
'FERT = FERT — 0.5
If x < -10 Then FERT = 0
If x > 10 Then FERT = 1
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function BS_C(K As Single, S As Single, T As Single, V As Single) As Single
Dim x!
x = V * (T / 365) ^ (0.5)
BS_C = S * FERT((Log(S / K) + (x ^ 2) / 2) / x) — K * FERT((Log(S / K) — (x ^ 2) / 2) / x)
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IV_C(S As Single, K As Single, C As Single) As Single
Dim x!, x_next!, f!, df!, epsilon!
Dim i%, i_max%
epsilon = 0.00001
x = 0.5
i_max = 10
For i = 1 To i_max
f = C — S * FERT((Log(S / K) + x ^ 2 / 2) / x) + K * FERT((Log(S / K) — x ^ 2 / 2) / x)
df = -S * NORM((Log(S / K) + x ^ 2 / 2) / x)
x_next = x — f / df
If (Abs(x — x_next)) < epsilon Then GoTo 20
x = x_next
Next i
20 IV_C = x
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub ggg()
MsgBox (BS_C(120000, 110000, 10, 0.76))
MsgBox (IV_C(110000, 120000, 2091.91) / (10 / 365) ^ (0.5))
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Функция BS_C рассчитывает цену опциона по известным страйку K, ЦБА S, волатильности V и времени до экспирации T, волатильность измерена в 1/корень из года, время до экспирации в днях.
Функция IV_C рассчитывает величину «волатильность*корень из времени до экспирации» по известным страйку K, ЦБА S и цене опциона C.
Все это написано для коллов, для путов обобщение тривиально.
Код на экране усиливает ощущение заумности и значимости написанного :)
давно хотел запрограммить свой опц.калькулятор в Экселе, но руки не доходили… может с твоей помощью и осилю…
кстати, где-то читал, что более близкие результаты к реальности дает не нормальное а лог-нормальное распределение.
а) Предпочитаю сам все сделать--оно как-то душевней. Понимание появляется.
б) Какая встроенная в эксель функция обращает формулу Блэка-Шоулса?
понимание то может и появляется — только
1. вместо 1 строки у Вас десятки
2. у вас приближенные вычисления
3. да и производительность у вас будет ниже
-и что касается обращения, вместо быстрого точного! определения волатильности подбором, вы пользуетесь весьма приближенным методом Ньютона, который оказался лучше (исправлен комментарий после тестирования)
1. Десятки строк кода--это само по себе не является проблемой. Тем более, что коды и алгоритмы простые.
2. Численные расчеты всегда приближенные, не только у меня.
3. «быстрого точного! определения волатильности подбором». Метод Ньютона, как и любой численный метод решения уравнений, основан на подборе. Все дело в том, как перебирать значения. Метод Ньютона автоматизировано находит решение подобных задач за три-пять итераций с точностью знака 4.
Скопируйте общий финальный код в VBA редактор и запускайте макрос ggg. Возможно, при копировании минусы в формулах заменятся на тире--это надо подправить.
Собссна этим и привлекателен Эксель — там потом все допиливается с помощью VBA
www.ivolatility.com/calc/
и нефиг силу проверять
1) Что вы понимаете под фразой «Блек-шоулз не работает»? В рамках этой модели нельзя заработать денег, или что?
2) Что же тогда работает?
1. Под этим я понимаю что в рамках этой модели нельзя получить представительные данные о риске
2. Работает объективная оценка.
1) Если речь про тяжелые хвосты, то согласен.
2) Какая оценка является объективной?
Думаю, erf использует похожие вещи--ибо ничего принципиально более быстрого просто нет. Поэтому наиболее вероятный ответ на ваш вопрос таков: стандартный erf наверняка чуть-чуть быстрее, может, в разы--ибо создатели наверняка там использовали похожие асимптотические разложения, но наверняка все вылизали, в отличие от меня :)
Про затабулированность не могу знать. Не имею нужного уровня владения материалом :) Мне кажется, особого смысла в этом нет--ибо неизвестно еще, что быстрее--три итерации провернуть или по таблице искать. А спросить про это у кого-нибудь из создателей этих функций нельзя?
Резюме:
1. У вас некорректно выполняется если X>10 или -10, переполнение вызывается раньше, чем условие выполнится. Но это не важно.
2. По точности, хорошо, разница лишь в 7 знаке.
3. По скорости так себе, в абсолютных величинах конечно мелочь: 0.03 секунды на 10 000 итераций, но в процентном на 30-35% хуже.
Итого, как я и декларировал имеем: худшую производительность, некорректную обработку некоторых значения и нерациональный рост кода в ущерб пониманию.
По методу Ньютона (попозже проверю) отпишусь.
1. Согласен, может, так и есть. Кому надо--вылижут этот момент, я и так много сказал и показал.
2. Гут
3. Этот код еще есть куда вылизать. Там немало написано неоптимально. Я подробно описал, как я делал этот код, в комментарии к вопросу Никиты Масюкова.
Еще одно. Поиграйтесь с epsilon. Она регулирует точность расчета и влияет на скорость. Думаю, точность в 0.00001 не нужна.
По поводу общей философии. Нравится вам erf или normdist--да ради бога. Мне не нравится и я привел алтернативный, более гибкий и гораздо менее «черноящечный» метод.
влияет только на точность, скорость не увеличивается, те же 0.03 секунды в среднем
Подставьте epsilon=0.01. В этом случае точность будет до 3го знака. Интересно, что будет со временем расчета.
Во-первых точность у Вас сопоставимая, максимальное отклонение 0.1% в волатильностях, что вполне приемлимо. Я думал все будет гораздо хуже.
А вот со скоростью, вроде у Вас даже побыстрее, на некоторых 18 комбинаций скорость одинаковая — 0.003906 но это видимо мин. измеряемый квант времени, а если зациклить на 1000 и добавить случайное отклонение по фьючерсу, то у Вас даже побыстрее вроде, но у меня несопоставимые листы и может где-то я ошибаюсь, но перепроверять уже не буду.
Вердикт: метод Ньютона видимо быстрее подбора при сопоставимой точности, так что забираю свои слова назад про этот метод.
А вообще, общефилософски, я советую поменьше использовать встроенные функции, особенно в эксель, а побольше писать все самому. Вначале это долго, но зато потом будете писать любые вещи быстро и правильно, не тратя время на разборки в хитросплетениях мозга разработчиков.
В любом случае, ваша критика качается лишь normdist. А для поиска, например, IV никаких встроенных в эксель функций в природе нет. Мне такую функцию написать пять минут, также, как и многие другие--normdist, Блэк-Шоулс, греки всякие, да вообще что угодно. При этом я буду понимать и смогу менять их точность, их границы применения, итд. Но, повторюсь, это мой выбор, я его не навязываю, эта статья--это бесплатный опцион. Можно использовать, можно не использовать.
>>опционы надо чувствовать.
Для меня весь смысл уместился в этой фразе))))
quantlib.org/index.shtml