/// <summary> /// Расчет будущей цены стредла с учетом заданной волатильности /// </summary> /// <param name="basePrice">Цена базового актива</param> /// <param name="strike">Цена страйк</param> /// <param name="expTime">Время до экспирации в долях года (с учетом рабочих дней биржи)</param> /// <param name="sigma">Волатильность (всегда положительное число; без перевода в проценты)</param> /// <param name="pctRate">Процентная ставка без риска (В ПРОЦЕНТАХ)</param> /// <returns>Цена стредла</returns> public static double GetStradlePrice(double basePrice, double strike, double expTime, double sigma, double pctRate) { if ((basePrice <= 0) || (strike <= 0) || (expTime <= 0) || (sigma <= 0)) { return(0); } double rate = pctRate / 100.0; double sst = sigma * sigma * expTime; double sqst = Math.Sqrt(sst); double lnP = Math.Log(basePrice / strike); double putPx, callPx; { double d1 = (lnP + 0.5 * sst) / sqst; double d2 = (lnP - 0.5 * sst) / sqst; double normDistD1; try { normDistD1 = StatMath.NormalDistribution(d1); } catch (ArithmeticException arex) { ArgumentException argEx = new ArgumentException( String.Format("d1:{0}; lnP:{1}; basePrice:{2}; strike:{3}; sigma:{4}; sst:{5}; sqst:{6}", d1, lnP, basePrice, strike, sigma, sst, sqst), "d1", arex); throw argEx; } double normDistD2; try { normDistD2 = StatMath.NormalDistribution(d2); } catch (ArithmeticException arex) { ArgumentException argEx = new ArgumentException( String.Format("d2:{0}; lnP:{1}; basePrice:{2}; strike:{3}; sigma:{4}; sst:{5}; sqst:{6}", d2, lnP, basePrice, strike, sigma, sst, sqst), "d2", arex); throw argEx; } callPx = Math.Exp(-rate * expTime) * (basePrice * normDistD1 - strike * normDistD2); putPx = Math.Exp(-rate * expTime) * (basePrice * (normDistD1 - 1) - strike * (normDistD2 - 1)); } double res = putPx + callPx; return(res); }
/// <summary> /// Теоретическая дельта опциона согласно модели Блека-Шолза /// </summary> /// <param name="basePrice">Цена базового актива</param> /// <param name="strike">Цена страйк</param> /// <param name="expTime">Время до экспирации в долях года (с учетом рабочих дней биржи)</param> /// <param name="sigma">Волатильность (всегда положительное число; без перевода в проценты)</param> /// <param name="pctRate">Процентная ставка без риска (В ПРОЦЕНТАХ)</param> /// <param name="isCall">Тип опциона, True = CALL</param> /// <returns>Дельта опциона</returns> public static double GetOptionDelta(double basePrice, double strike, double expTime, double sigma, double pctRate, bool isCall = true) { double rate = pctRate / 100.0; if (isCall) { if (expTime < Double.Epsilon) { if (basePrice <= strike) { return(0); } else { return(1); } } var variation = sigma * Math.Sqrt(expTime); var d1 = Math.Log(basePrice / strike) + rate * expTime + 0.5 * variation * variation; d1 /= variation; var nd1 = StatMath.NormalDistribution(d1); return(nd1); } else { if (expTime < Double.Epsilon) { if (basePrice >= strike) { return(0); } else { return(-1); } } var variation = sigma * Math.Sqrt(expTime); var d1 = Math.Log(basePrice / strike) + rate * expTime + 0.5 * variation * variation; d1 /= variation; var nd1 = StatMath.NormalDistribution(d1); return(nd1 - 1.0); } }
/// <summary> /// Теоретическая тета опциона согласно модели Блека-Шолза /// </summary> /// <param name="basePrice">Цена базового актива</param> /// <param name="strike">Цена страйк</param> /// <param name="expTime">Время до экспирации в долях года (с учетом рабочих дней биржи)</param> /// <param name="sigma">Волатильность (всегда положительное число; без перевода в проценты)</param> /// <param name="pctRate">Процентная ставка без риска (В ПРОЦЕНТАХ)</param> /// <param name="isCall">Тип опциона, True = CALL</param> /// <returns>Тета опциона</returns> public static double GetOptionTheta(double basePrice, double strike, double expTime, double sigma, double pctRate, bool isCall = true) { double rate = pctRate / 100.0; if (isCall) { if (expTime < Double.Epsilon) { return(0); } var variation = sigma * Math.Sqrt(expTime); var d1 = Math.Log(basePrice / strike) + rate * expTime + 0.5 * variation * variation; d1 /= variation; var d2 = d1 - variation; var dnd1 = Math.Exp(-d1 * d1 / 2.0) / Math.Sqrt(2.0 * Math.PI); var nd2 = StatMath.NormalDistribution(d2); var result = -basePrice * dnd1 * sigma / 2.0 / Math.Sqrt(expTime) - rate * strike * nd2 * Math.Exp(-rate * expTime); // know-how: тета нормируется на число дней в году return(result / TSLab.Script.Handlers.Options.OptionUtils.DaysInYear); } else { if (expTime < Double.Epsilon) { return(0); } var variation = sigma * Math.Sqrt(expTime); var d1 = Math.Log(basePrice / strike) + rate * expTime + 0.5 * variation * variation; d1 /= variation; var d2 = d1 - variation; var dnd1 = Math.Exp(-d1 * d1 / 2.0) / Math.Sqrt(2.0 * Math.PI); var nd2 = StatMath.NormalDistribution(-d2); var result = -basePrice * dnd1 * sigma / 2.0 / Math.Sqrt(expTime) + rate * strike * nd2 * Math.Exp(-rate * expTime); // know-how: тета нормируется на число дней в году return(result / TSLab.Script.Handlers.Options.OptionUtils.DaysInYear); } }
/// <summary> /// Расчет будущей цены опциона с учетом заданной волатильности /// </summary> /// <param name="basePrice">Цена базового актива</param> /// <param name="strike">Цена страйк</param> /// <param name="expTime">Время до экспирации в долях года (с учетом рабочих дней биржи)</param> /// <param name="sigma">Волатильность (всегда положительное число; без перевода в проценты)</param> /// <param name="pctRate">Процентная ставка без риска (В ПРОЦЕНТАХ)</param> /// <param name="isCall">Тип опциона, True = CALL</param> /// <returns>Цена опциона</returns> public static double GetOptionPrice(double basePrice, double strike, double expTime, double sigma, double pctRate, bool isCall = true) { if ((basePrice <= 0) || (strike <= 0) || (expTime <= 0) || (sigma <= 0)) { return(0); } double sst = sigma * sigma * expTime; double sqst = Math.Sqrt(sst); double lnP = Math.Log(basePrice / strike); // [2015-12-09] Википедия даёт другую формулу ПРИ УЧЕТЕ ПРОЦЕНТНОЙ СТАВКИ // https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model double rate = pctRate / 100.0; //double d1 = (lnP + 0.5 * sst) / sqst; //double d2 = (lnP - 0.5 * sst) / sqst; double d1 = (lnP + 0.5 * sst + rate * expTime) / sqst; double d2 = (lnP - 0.5 * sst + rate * expTime) / sqst; double normDistD1; try { normDistD1 = StatMath.NormalDistribution(d1); } catch (ArithmeticException arex) { ArgumentException argEx = new ArgumentException( String.Format("d1:{0}; lnP:{1}; basePrice:{2}; strike:{3}; sigma:{4}; sst:{5}; sqst:{6}", d1, lnP, basePrice, strike, sigma, sst, sqst), "d1", arex); throw argEx; } double normDistD2; try { normDistD2 = StatMath.NormalDistribution(d2); } catch (ArithmeticException arex) { ArgumentException argEx = new ArgumentException( String.Format("d2:{0}; lnP:{1}; basePrice:{2}; strike:{3}; sigma:{4}; sst:{5}; sqst:{6}", d2, lnP, basePrice, strike, sigma, sst, sqst), "d2", arex); throw argEx; } double expRt = Math.Exp(-rate * expTime); double callPx = basePrice * normDistD1 - expRt * strike * normDistD2; if (isCall) { //return Math.Exp(-rate * expTime) * (basePrice * normDistD1 - strike * normDistD2); return(callPx); } else { //return Math.Exp(-rate * expTime) * (basePrice * (normDistD1 - 1) - strike * (normDistD2 - 1)); // Цена ПУТ вычисляется через паритет: double putPx = callPx + expRt * strike - basePrice; return(putPx); } }