/// <summary> /// 计算期权持仓的delta值 /// </summary> /// <param name="positionLast">最后持仓状态</param> /// <param name="holdingStatus">记录的跨式期权情况</param> /// <param name="today">今日日期</param> /// <param name="dataToday">今日数据</param> /// <param name="index">交易时间对应的下标</param> /// <returns></returns> private double computeOptionDelta(Dictionary <string, PositionsWithDetail> positionLast, StraddlePair holdingStatus, DateTime today, Dictionary <string, List <KLine> > dataToday, int index) { double delta = 0; foreach (var item in positionLast) { if (item.Key == holdingStatus.callCodeFront) { var callDelta = ImpliedVolatilityUtilities.ComputeOptionDelta(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDate) / 252.0, 0.04, 0, "认购", ImpliedVolatilityUtilities.ComputeImpliedVolatility(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDate) / 252.0, 0.04, 0, "认购", dataToday[item.Key][index].close, dataToday["510050.SH"][index].close), dataToday["510050.SH"][index].close); delta += holdingStatus.callPositionFront * callDelta; } if (item.Key == holdingStatus.putCodeFront) { var putDelta = ImpliedVolatilityUtilities.ComputeOptionDelta(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDate) / 252.0, 0.04, 0, "认沽", ImpliedVolatilityUtilities.ComputeImpliedVolatility(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDate) / 252.0, 0.04, 0, "认沽", dataToday[item.Key][index].close, dataToday["510050.SH"][index].close), dataToday["510050.SH"][index].close); delta += holdingStatus.putPositionFront * putDelta; } if (item.Key == holdingStatus.callCodeNext) { var callDelta = ImpliedVolatilityUtilities.ComputeOptionDelta(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDateNext) / 252.0, 0.04, 0, "认购", ImpliedVolatilityUtilities.ComputeImpliedVolatility(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDateNext) / 252.0, 0.04, 0, "认购", dataToday[item.Key][index].close, dataToday["510050.SH"][index].close), dataToday["510050.SH"][index].close); delta += holdingStatus.callPositionNext * callDelta; } if (item.Key == holdingStatus.putCodeNext) { var putDelta = ImpliedVolatilityUtilities.ComputeOptionDelta(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDateNext) / 252.0, 0.04, 0, "认沽", ImpliedVolatilityUtilities.ComputeImpliedVolatility(holdingStatus.strike, DateUtils.GetSpanOfTradeDays(today, holdingStatus.endDateNext) / 252.0, 0.04, 0, "认沽", dataToday[item.Key][index].close, dataToday["510050.SH"][index].close), dataToday["510050.SH"][index].close); delta += holdingStatus.putPositionNext * putDelta; } } return(delta); }
/// <summary> /// 估算未来的期权价格 /// </summary> /// <param name="days"></param> /// <param name="code"></param> /// <param name="etfPrice"></param> /// <returns></returns> private double computeFuturePrice(int days, string code, double etfPrice) { double price = 0; var option = OptionUtilities.getOptionByCode(optionList, code); int x = Convert.ToInt32(optionPrice[code].duration - days); int y = Convert.ToInt32(Math.Round(1000 * Math.Log(option.strike / etfPrice), 0) + 500); double vol = volSurface[x, y]; price = ImpliedVolatilityUtilities.ComputeOptionPrice(option.strike, (optionPrice[code].duration - days) / 252.0, riskFreeRate, 0, option.optionType, vol, etfPrice); return(price); }
public void computeVol() { var etfPrice = dataList[ETF].last; Console.Clear(); foreach (var code in dataListKey) { var option = dataList[code]; var optionCode = code; if (optionCode != ETF && etfPrice != 0) { var info = optionInfo[optionCode]; var ask = option.ask1; var bid = option.bid1; var mid = (ask + bid) / 2; var strike = info.strike; var type = info.optionType; var vol = ImpliedVolatilityUtilities.ComputeImpliedVolatility(strike: strike, duration: duartion / 252.0, riskFreeRate: rate, StockRate: 0, optionType: type, optionPrice: mid, underlyingPrice: etfPrice); Console.WriteLine("本地时间:{2},数据时间:{3},期权:{0},波动率:{1}", info.optionName, Math.Round(vol, 3), DateTime.Now.TimeOfDay.ToString("hhmmss"), option.time.ToString("hhmmss")); } } }
private void computeImpv() { optionVol = new double[etfDailyData.Count()]; for (int i = startIndex; i < etfDailyData.Count(); i++) { DateTime today = etfDailyData[i].time; double etfPrice = etfDailyData[i].close; double volThisMonth; double volNextMonth; double duration; //获取当日期限结构,选取当月合约 List <double> dateStructure = OptionUtilities.getDurationStructure(optionInfoList, today); double duration0 = dateStructure[0] == 0 ? dateStructure[1] : dateStructure[0]; duration = duration0; var call = OptionUtilities.getOptionListByOptionType(OptionUtilities.getOptionListByDuration(optionInfoList, today, duration), "认购").OrderBy(x => Math.Abs(x.strike - etfPrice)).Where(x => x.startDate <= today).ToList(); var callATM = call[0]; var callPrice = Platforms.container.Resolve <OptionDailyRepository>().fetchFromLocalCsvOrWindAndSave(callATM.optionCode, today, today); double callImpv = ImpliedVolatilityUtilities.ComputeImpliedVolatility(callATM.strike, duration / 252.0, 0.04, 0, callATM.optionType, callPrice[0].close, etfPrice); var put = OptionUtilities.getOptionListByOptionType(OptionUtilities.getOptionListByDuration(optionInfoList, today, duration), "认沽").OrderBy(x => Math.Abs(x.strike - callATM.strike)).ToList(); var putATM = put[0]; var putPrice = Platforms.container.Resolve <OptionDailyRepository>().fetchFromLocalCsvOrWindAndSave(putATM.optionCode, today, today); double putImpv = ImpliedVolatilityUtilities.ComputeImpliedVolatility(putATM.strike, duration / 252.0, 0.04, 0, putATM.optionType, putPrice[0].close, etfPrice); if (callImpv * putImpv == 0) { volThisMonth = callImpv + putImpv; } else { volThisMonth = (callImpv + putImpv) / 2; } //获取当日期限结构,选取下月合约,若下月合约不存在,就获取季月合约 double duration1 = dateStructure[0] == 0 ? dateStructure[2] : dateStructure[1]; duration = duration1; call = OptionUtilities.getOptionListByOptionType(OptionUtilities.getOptionListByDuration(optionInfoList, today, duration), "认购").OrderBy(x => Math.Abs(x.strike - etfPrice)).Where(x => x.startDate <= today).ToList(); callATM = call[0]; callPrice = Platforms.container.Resolve <OptionDailyRepository>().fetchFromLocalCsvOrWindAndSave(callATM.optionCode, today, today); callImpv = ImpliedVolatilityUtilities.ComputeImpliedVolatility(callATM.strike, duration / 252.0, 0.04, 0, callATM.optionType, callPrice[0].close, etfPrice); put = OptionUtilities.getOptionListByOptionType(OptionUtilities.getOptionListByDuration(optionInfoList, today, duration), "认沽").OrderBy(x => Math.Abs(x.strike - callATM.strike)).ToList(); putATM = put[0]; putPrice = Platforms.container.Resolve <OptionDailyRepository>().fetchFromLocalCsvOrWindAndSave(putATM.optionCode, today, today); putImpv = ImpliedVolatilityUtilities.ComputeImpliedVolatility(putATM.strike, duration / 252.0, 0.04, 0, putATM.optionType, putPrice[0].close, etfPrice); if (callImpv * putImpv == 0) { volNextMonth = callImpv + putImpv; } else { volNextMonth = (callImpv + putImpv) / 2; } if (duration0 >= step) { optionVol[i] = Math.Sqrt(step / duration0) * volThisMonth; } else if ((duration0 < step && duration1 > step)) { optionVol[i] = Math.Sqrt((duration1 - step) / (duration1 - duration0)) * volThisMonth + Math.Sqrt((step - duration0) / (duration1 - duration0)) * volNextMonth; } else if (duration1 <= step) { optionVol[i] = volNextMonth; } } }