Расчет теоретической цены опциона по методике Московской Биржи

Страницы: 1
RSS
Расчет теоретической цены опциона по методике Московской Биржи
 
Функция стандартного нормального распределения - как это написать в коде Lua?
 
Код
--- Функция распределения стандартного нормального закона.
-- @param x аргумент
-- @return значение
function n(x)
    if x > 10 then
        return 1.0
    end
    if x < -10 then
        return 0.0
    end
    local ax = math.abs(x)
    local t = 1.0 / (1.0 + 0.2316419 * ax)
    local d = 1.0 / math.sqrt(2 * math.pi) * math.exp(-x * x / 2)
    local p = d * t * ((((1.330274429 * t - 1.821255978) * t + 1.781477937) * t - 0.356563782) * t + 0.31938153)
    if x > 0 then
        return 1.0 - p
    else
        return p
    end
end

--- Плотность нормального распределения.
-- @param x аргумент
-- @return значение
function phi(x)
    return 1.0 / math.sqrt(2.0 * math.pi) * math.exp(-x * x / 2.0)
end
 
Код
-- F: Текущая цена фьючерса
-- S: Страйк
-- V: Волатильность
-- T: Время в долях года до окончания срока действия опциона (30 / 365)
function Black_Scholes(F, S, V, T)
   d1 = (math.log(F / S) + V * V * (T / 366) / 2) / (V * math.sqrt(T / 366))
   d2 = d1 - V * math.sqrt(T / 366)
   
   Call = F * N(d1) - S * N(d2)
   Put = Call + S - F
   return Call
end

function N(x) -- Функция стандартного нормального распределения
   if x > 10 then return 1 end
   if x < -10 then return 0 end
   local ax = math.abs(x)
   local t = 1 / (1 + 0.2316419 * ax)
   local d = 1 / math.sqrt(2 * math.pi) * math.exp(-x * x / 2)
   local p = d * t * ((((1.330274429 * t - 1.821255978) * t + 1.781477937) * t - 0.356563782) * t + 0.31938153)
   if x > 0 then return 1 - p else return p end
end


Функция стандартного нормального распределения - взял Вашу,  Black_Scholes - по методике МБ, но все равно не получается получить теор. цену
 
Проверьте следующие пункты:
1) Время в долях года надо подставлять. Для RIH6 в данный момент (2016-03-09) это что-то типа 0.017.
2) Волатильность должна быть в долях, а не процентах. Для RIH6 на страйке 80 000 это что-то типа 0.385 сейчас.
Код
/**
 * Цена опциона колл.
 *
 * @param underlying значение базового актива
 * @param strike     страйк
 * @param t          время до экспирации
 * @param sigma      волатильность
 * @return цена опциона колл
 */
public static double callPrice(final double underlying, final double strike, final double t, final double sigma) {
    if (t <= 0) {
        return Math.max(underlying - strike, 0);
    } else {
        final double d0 = Math.log(underlying / strike);
        final double a = sigma * sigma * t / 2;
        final double b = sigma * Math.sqrt(t);
        final double d1 = (d0 + a) / b;
        final double d2 = (d0 - a) / b;
        return underlying * n(d1) - strike * n(d2);
    }
}
 
Спасибо разобрался. Волатильность была в процентах  
 
Добрый день. Прошу помощи у опытных опционщиков, помогите понять, как идет расчет теоретической цены опциона. Если использовать приведенный в теме код, то он совпадает с расчетами опционного калькулятора с сайта option.ru.
Однако в таблице опционов Quik цифра совсем иная, практически всегда бОльшая, хотя бывает, что и расчет кодом выдает значение большее, чем теоретическая цена в момент обновления на доске опционов в Quik.

Подскажите, где узнать, по какому принципу идет расчет на бирже? Используется ли для расчета крайнее или все же предыдущее значение волатильности?
Или все же можно просто смотреть расчет по коду и не переживать?
 
Цитата
Подскажите, где узнать, по какому принципу идет расчет на бирже?  Используется ли для расчета крайнее или все же предыдущее значение  волатильности?

Биржа рассчитывает волатильность и теоретическую цену не реал-тайм, а с некоторой периодичностью. Методика расчёта тут: http://fs.moex.com/files/4720

Для простых вариантов можно брать волатильность опциона из QUIK и оценивать теоретическую цену по формуле Б.-Ш. с использованием текущей цены. Для более сложных вариантов придётся самому брать биды/офера по страйкам и вычислять свою улыбку волатильности.
 
Цитата
_sk_ написал:
Биржа рассчитывает волатильность и теоретическую цену не реал-тайм, а с некоторой периодичностью. Методика расчёта тут: http://fs.moex.com/files/4720
Спасибо, я этот документ и читал, просто подумал, что не актуальный, т.к. идет разница.
Цитата
_sk_ написал:
Для простых вариантов можно брать волатильность опциона из QUIK и оценивать теоретическую цену по формуле Б.-Ш. с использованием текущей цены.
Я так и делаю. Вывел себе все данные для формулы для наглядности в момент изменения теоретической цены на доске опционов, и вот именно в момент обновления по формуле Б.-Ш. расчет совпадает с сайтом option.ru, а теоретическая цена на доске другая. Вот и возник вопрос: кто считает верно?
 
И еще такой момент, значение волатильности тоже "запаздывает"? Его тоже необходимо рассчитывать самому и использовать в формуле Б.-Ш.? Или на доске актуальное значение?
 
Цитата
Женя написал:
И еще такой момент, значение волатильности тоже "запаздывает"? Его тоже необходимо рассчитывать самому и использовать в формуле Б.-Ш.? Или на доске актуальное значение?
Значение волатильности тоже запаздывает. Правда, вред от его запаздывания сильно меньше, чем вред от резкого изменения цена базового актива. Волатильность потому и придумывали/используют, что она меняется заметно медленнее, чем цены опционов и базового актива.
 
Скопировал функции Black_Scholes из этой темы, но где-то делаю ошибку, так как функция выдаёт 0.
Помогите, пожалуйста, найти ошибку в коде:
Код
-- F: Текущая цена фьючерса
-- S: Страйк
-- V: Волатильность
-- T: Время в долях года до окончания срока действия опциона (30 / 365)
function Black_Scholes(F, S, V, T)
    d1 = (math.log(F / S) + V * V * (T / 366) / 2) / (V * math.sqrt(T / 366))
    d2 = d1 - V * math.sqrt(T / 366)

    Call = F * N(d1) - S * N(d2)
    Put = Call + S - F
    return Call
end

function N(x) -- Функция стандартного нормального распределения
    if x > 10 then return 1 end
    if x < -10 then return 0 end
    ax = math.abs(x)
    t = 1 / (1 + 0.2316419 * ax)
    d = 1 / math.sqrt(2 * math.pi) * math.exp(-x * x / 2)
    p = d * t * ((((1.330274429 * t - 1.821255978) * t + 1.781477937) * t - 0.356563782) * t + 0.31938153)
    if x > 0 then return 1 - p else return p end
end

function GetOptionTheorprices()
    ClassCode = "SPBOPT";
    SecCode = "RI120000BH4";
    BaseClassCode = "SPBFUT";
    --заказ данных
    ParamRequest(ClassCode, SecCode, "volatility");
    ParamRequest(ClassCode, SecCode, "theorprice");
    ParamRequest(ClassCode, SecCode, "DAYS_TO_MAT_DATE");
    ParamRequest(ClassCode, SecCode, "strike");
    ParamRequest(ClassCode, SecCode, "optiontype");
    ParamRequest(ClassCode, SecCode, "optionbase");
    Optionbase = getParamEx(ClassCode, SecCode, "optionbase").param_image;
    ParamRequest(BaseClassCode, Optionbase, "settleprice");
    Optiontype = getParamEx(ClassCode, SecCode, "optiontype").param_image;
    DAYS_TO_MAT_DATE = getParamEx(ClassCode, SecCode, "DAYS_TO_MAT_DATE").param_value + 0;
    option_base_settleprice = getParamEx("SPBFUT", Optionbase, "settleprice").param_value + 0;
    strike = getParamEx(ClassCode, SecCode, "strike").param_value + 0;
    volatility = getParamEx(ClassCode, SecCode, "volatility").param_value + 0;
    theorprice = getParamEx(ClassCode, SecCode, "theorprice").param_value + 0;
    Black_Scholes_Price = Black_Scholes(option_base_settleprice, strike, volatility / 100.0, DAYS_TO_MAT_DATE / 365.0);
    message(
        "QLua: _____________________________________" ..
        "\n" .. YYYYMMDD() ..
        "\nClassCode=" .. tostring(ClassCode) ..
        "\nSecCode=" .. tostring(SecCode) ..
        "\nOption Base ClassCode=" .. tostring(BaseClassCode) ..
        "\nOptionbase=" .. tostring(Optionbase) ..
        "\nOptiontype=" .. tostring(Optiontype) ..
        "\nDAYS_TO_MAT_DATE=" .. tostring(DAYS_TO_MAT_DATE) ..
        "\nOption Base settleprice=" .. tostring(option_base_settleprice) ..
        "\nstrike=" .. tostring(strike) ..
        "\nvolatility=" .. tostring(volatility) ..
        "\ntheorprice=" .. tostring(theorprice) ..
        "\nBlack_Scholes_Price=" .. tostring(Black_Scholes_Price) ..
        "\nQLua: _____________________________________",
        1);
    --[[
        Результат:
        QLua: _____________________________________
        2024.06.29
        ClassCode=SPBOPT
        SecCode=RI120000BH4
        Option Base ClassCode=SPBFUT
        Optionbase=RIU4
        Optiontype=Call
        DAYS_TO_MAT_DATE=48.0
        Option Base settleprice=115200.0
        strike=120000.0
        volatility=18.318
        theorprice=1280.0
        Black_Scholes_Price=0.0
        QLua: _____________________________________
    ]]
end

function main()
    do_it = true;
    while (do_it) do
        GetOptionTheorprices();
        for _ = 1, 20 do
            sleep(500);
            if not do_it then
                return;
            end
        end
    end
end

function OnStop()
    do_it = false;
end

function YYYYMMDD(datetime)
    if not datetime then
        datetime = os.date("*t");
    end
    local DD = datetime.day
    if DD < 10 then DD = "0" .. DD end

    local MM = datetime.month
    if MM < 10 then MM = "0" .. MM end

    local YYYY = datetime.year
    return table.concat({ YYYY, MM, DD }, ".");
end

Страницы: 1
Читают тему
Наверх