Гауссовский VaR стабильно ошибается в обе стороны. Нормальная модель заставляет инвесторов излишне перестраховываться вблизи середины распределения, но при этом становится абсурдно оптимистичной и совершенно слепой к реальной угрозе там, где начинается дальний хвост.
Срез истории рынка США по базе Кеннета Френча охватывает век. Архив с июля 1926 года вместил 26 317 торговых дней. Нормальная модель с аналогичной волатильностью ожидает падение глубже четырех стандартных отклонений всего 0,83 раза. Факт суровее. Рынок пробивал этот порог 105 раз.
Дальше разрыв становится астрономическим. За пределами пяти отклонений гауссовская математика допускает 0,0075 случая, тогда как реальность выдала 51 обвал. Зато около центра распределения модель пугает зря. За границей 1,645 стандартного отклонения она ждет 1315 убыточных сессий. Рыночный факт мягче. История зафиксировала 1082 таких дня.
Параметрический VaR 95% останавливается на самом пороге. Он скрывает от риск-менеджера истинную глубину просадки при внезапных катастрофах масштаба Черного понедельника, когда историческое дневное падение рынка на 17,41% обернулось аномальным движением в 16,2 стандартного отклонения. Исторически скользящий VaR 99% пробивался в 2,36% случаев вместо заложенного одного процента.

Привет, коллеги!
Хочу поделиться историей о том, как мы столкнулись с типичной проблемой в количественных финансах и что из этого вышло.
Проблема, знакомая каждому, кто строил риск-моделиПредставьте: у вас портфель из тысяч инструментов. Вы считаете Value-at-Risk (VaR), ожидаемые потери (Expected Shortfall), греки для опционов, скоринговые модели. Данные обновляются постоянно — новые цены, ставки, волатильности.
Как это обычно работает?
Либо вы пересчитываете всё с нуля каждый раз (дорого, медленно, особенно если инструментов много)
Либо вы строите сложные триггеры и кэши, которые потом отлаживаете месяцами
В обоих случаях вы либо жертвуете скоростью, либо тратите уйму времени разработчиков.
Как мы пытались решить эту проблемуМы начали с простого вопроса: «А что, если пересчитывать только то, что реально изменилось?»
Звучит очевидно, но реализация оказалась нетривиальной. Когда у вас многослойная модель (например: цены → греки по инструментам → агрегация по секторам → портфельные метрики → общебанковские лимиты), одно изменение в цене может затронуть десятки тысяч зависимых значений.
О чём это.
Все нормальные расчёты (опционы, VaR, греки) либо дёргают неуправляемый C++ код, либо жрут память и GC, либо просто медленные.
Я написал свою библиотеку — QuantCore.Net. Это in-process .NET 8 ядро для финансовых вычислений. Без REST, без Python-прослоек, без боли.
Под капотом: SIMD, ArrayPool, детерминированный RNG, батч-режимы. Всё, чтобы считать сотни тысяч инструментов за миллисекунды и не ловить StopTheWorld в 3 часа ночи.
Вы пишете своих роботов на C#.
— Хотите быстро считать справедливую цену опционов или греки в реальном времени.
— Надоело дёргать Excel или самопальные функции из интернета, которые плавают на 5%.
Вы управляете портфелем и считаете риск.
— Historical VaR / ES (CVaR) за 0.4 мс на 100 000 наблюдений.
— Ни одной аллокации памяти — GC молчит.
Вы делаете factor model PnL.
— SIMD-скалярка экспозиций и факторных доходностей.
— 100 000 позиций × 32 фактора = 2.8 мс.



# Daily, typical daily log returns StudentT(0.001, 0.015) p = 1-1/(365*10*10) # once in 10y for portfolio of 10 stocks exp( quantile(StudentT(0.001, 0.015, 3), p) - quantile(StudentT(0.001, 0.015, 3.7), p) ) # => 1.22 # Monthly, typical monthly log returns StudentT(0.01, 0.08) p = 1-1/(12*10*10) # once in 10y for portfolio of 10 stocks exp( quantile(StudentT(0.01, 0.08, 3), p) - quantile(StudentT(0.01, 0.08, 3.7), p) ) # => 1.24