private double getOptionDelta(double strike, double duration, double r, double dividend, double vol, double stockPrice) { double delta = 0; delta = ImpliedVolatilityExtension.ComputeOptionDelta(strike, duration, r, dividend, "认购", vol, stockPrice); return(delta); }
private double getOptionDelta(DateTime date, string BondCode, string stockCode) { double delta = 0.5; var bondInfo = getBondDailyInfo(date, BondCode); int days = DateTimeExtension.DateUtils.GetSpanOfTradeDays(date, bondInfo.conversionEndDate); double duration = (double)days / 252.0; var stockList = getPreviousStockCloseList(date, stockCode, days); var stockLastClose = stockList[stockList.Count() - 1]; double volatility = HistoricalVolatilityExtension.getHistoricalVolatilityByClosePrice(stockList); double strike = bondInfo.conversionPrice; delta = ImpliedVolatilityExtension.ComputeOptionDelta(strike, duration, 0.04, 0, "认购", volatility, stockLastClose); return(delta); }
//计算从开始日期到结束日期的对冲成本 private double deltaHedgePerDate(DateTime startDate, DateTime endDate, Dictionary <DateTime, double> vol) { double option = 0; var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); int deltaIndex = 220; //计算历史波动率参数 string hedgeCode = ""; double deltaNow = 0; double pnl = 0; double cash = 0; //按第一天的开盘价确定期初价格和行权价 var stock = stockDailyRepo.GetStockTransactionWithRedis(indexCode, startDate, endDate); double startPrice = stock[0].Open; double strike = startPrice; foreach (var date in tradedays) { //获取当日期货合约代码 var list = getSpecialFutureList(date); //获取当日收盘前标的价格 // var index = stockMinutelyRepo.GetStockTransactionWithRedis(indexCode, date, date); var index = allData[date][indexCode]; var indexPrice = index[deltaIndex].Close; double duration = (DateUtils.GetSpanOfTradeDays(date, endDate) + 1 / 12) / 252.0; //按标的计算收盘前delta值 double deltaTarget = ImpliedVolatilityExtension.ComputeOptionDelta(strike, duration, 0.04, 0, "认沽", vol[date], indexPrice); //对冲未开仓进行开仓 if (hedgeCode == "") { hedgeCode = list.Last().Value.code; double futurePrice = allData[date][hedgeCode][deltaIndex + 1].Close; cash += -futurePrice * deltaTarget; deltaNow = deltaTarget; } //如果对冲的合约快到期时,进行移仓操作,移仓到季月合约 if (list.ContainsKey(hedgeCode) && list[hedgeCode].expireDate.Date.AddDays(-7) <= date.Date) { double futurePriceFront = allData[date][hedgeCode][deltaIndex + 1].Close; hedgeCode = list.Last().Value.code; double futurePriceNext = allData[date][hedgeCode][deltaIndex + 1].Close; cash += futurePriceFront * deltaNow - futurePriceNext * deltaTarget; deltaNow = deltaTarget; } else if (list.ContainsKey(hedgeCode)) //对冲的合约未到期,继续对冲 { double futurePrice = allData[date][hedgeCode][deltaIndex + 1].Close; cash += -futurePrice * (deltaTarget - deltaNow); deltaNow = deltaTarget; } //错误情况 if (list.ContainsKey(hedgeCode) == false && hedgeCode != "") { throw new ArgumentOutOfRangeException("对冲选取错误!!"); } } //计算最后一天的PNL=cash+期货值的钱+付出去的期权收益 var lastDate = tradedays.Last(); double futureLastPrice = allData[lastDate][hedgeCode][239].Close; double indexLastPrice = stock.Last().Close; pnl = -(cash + deltaNow * futureLastPrice - Math.Max(startPrice - indexLastPrice, 0)); option = pnl / startPrice; return(option); }
private Dictionary <string, optionGreeks> getGreekInformation(DateTime date, StockTransaction underlyingData, Dictionary <string, StockOptionInformationWithModified> optionList, List <StockOptionTransaction> optionData) { double oneYearDays = 280; double underlyingClose = Math.Round(underlyingData.Close, 3); Dictionary <string, optionGreeks> greeks = new Dictionary <string, optionGreeks>(); Dictionary <DateTime, double> durationDic = new Dictionary <DateTime, double>(); Dictionary <DateTime, List <double> > strikeDic = new Dictionary <DateTime, List <double> >(); Dictionary <DateTime, double> basisList = new Dictionary <DateTime, double>(); //希腊值的处理 //预处理到期日和行权价 foreach (var option in optionData) { var info = optionList[option.Code]; var expiredate = info.expireDate; double strike = info.strike; double unit = info.unit; if (info.existsModified == true && date < info.dividendDate) { strike = info.strike; unit = info.unitBeforeModifed; } if (durationDic.ContainsKey(expiredate) == false) { double modifiedDays = getModifiedDuration(date, expiredate, durationModifiedCoff); oneYearDays = getModifiedDuration(expiredate.AddYears(-1), expiredate, durationModifiedCoff); double duration = modifiedDays / oneYearDays; durationDic.Add(expiredate, duration); } if (strikeDic.ContainsKey(expiredate) == false) { List <double> strikeList = new List <double>(); strikeList.Add(strike); strikeDic.Add(expiredate, strikeList); } else { if (strikeDic[expiredate].Contains(strike) == false) { strikeDic[expiredate].Add(strike); } } } //逐月逐行权价,计算基差,同时计算基本信息 foreach (var list in strikeDic) { DateTime expireDate = list.Key; double avgBasis = 0; Dictionary <double, double> basisByStrike = new Dictionary <double, double>(); foreach (var item in list.Value) { double strike = item; double callPrice = 0; double putPrice = 0; foreach (var option in optionData) { var info = optionList[option.Code]; //找出认购期权 if (info.type == "认购" && info.expireDate == expireDate) { if (info.existsModified == true && date < info.dividendDate) { if (info.strikeBeforeModified == strike) { callPrice = option.Close; } } if (info.existsModified == false && info.strike == strike) { callPrice = option.Close; } } //找出认沽期权 if (info.type == "认沽" && info.expireDate == expireDate) { if (info.existsModified == true && date < info.dividendDate) { if (info.strikeBeforeModified == strike) { putPrice = option.Close; } } if (info.existsModified == false && info.strike == strike) { putPrice = option.Close; } } } double durationOfInterest = getInterestDuartion(date, expireDate); double basis = callPrice - putPrice + strike * Math.Exp(-rate * durationOfInterest) - underlyingClose; basisByStrike.Add(strike, basis); } List <double> strikeOrdered = list.Value.OrderBy(x => Math.Abs(x - underlyingClose)).ToList(); for (int i = 0; i < 3; i++) { avgBasis += basisByStrike[strikeOrdered[i]]; } avgBasis = avgBasis / 3; basisList.Add(expireDate, avgBasis); } //逐合约计算波动率及希腊值 foreach (var option in optionData) { optionGreeks greek = new optionGreeks(); var info = optionList[option.Code]; double strike = info.strike; double optionPrice = option.Close; int unit = info.unit; if (info.existsModified == true && date < info.dividendDate) { strike = info.strike; unit = info.unitBeforeModifed; } greek.strike = strike; greek.name = info.name; greek.underlying = info.underlying; greek.underlyPrice = underlyingClose; greek.unit = unit; greek.today = date; greek.code = info.code; greek.expireDate = info.expireDate; greek.duration = getInterestDuartion(date, info.expireDate); greek.modifiedDuration = getModifiedDuration(date, info.expireDate, durationModifiedCoff) / getModifiedDuration(info.expireDate.AddYears(-1), info.expireDate, durationModifiedCoff); greek.Basis = basisList[info.expireDate]; greek.optionPrice = optionPrice; greek.type = info.type; double optionPriceWithBasis = greek.underlyPrice + greek.Basis; //计算波动率 greek.impliedVol = ImpliedVolatilityExtension.ComputeImpliedVolatility(greek.strike, greek.modifiedDuration, rate, 0, greek.type, greek.optionPrice, optionPriceWithBasis); greek.delta = ImpliedVolatilityExtension.ComputeOptionDelta(greek.strike, greek.modifiedDuration, rate, 0, greek.type, greek.impliedVol, optionPriceWithBasis); greek.cashDelta = greek.delta * greek.unit * greek.underlyPrice * 0.01; greek.vega = ImpliedVolatilityExtension.ComputeOptionVega(greek.strike, greek.modifiedDuration, rate, 0, greek.impliedVol, optionPriceWithBasis); greek.cashVega = greek.vega * greek.unit; greek.cashGamma = 0.5 * greek.gamma * Math.Pow((greek.unit * greek.underlyPrice * 0.01), 2); greek.cashBasis = greek.Basis * greek.delta * greek.unit; //讲信息写入希腊值列表 greeks.Add(info.code, greek); } return(greeks); }