public static string eqMathBiLinearInterpolation( [ExcelArgument(Description = "interpolation obj id")] string objId, [ExcelArgument(Description = "row variable x ")] double[] x, [ExcelArgument(Description = "col variable y ")] double[] y, [ExcelArgument(Description = "variable z ")] double[,] z) { if (ExcelUtil.CallFromWizard()) { return(""); } string callerAddress = ""; callerAddress = ExcelUtil.getActiveCellAddress(); try { if ((x.Length != z.GetLength(0)) || (y.Length != z.GetLength(1))) { return("size mismatch"); } QlArray xa = new QlArray((uint)x.Length); QlArray ya = new QlArray((uint)y.Length); for (uint i = 0; i < x.Length; i++) { xa.set(i, x[i]); ya.set(i, y[i]); } Matrix ma = new Matrix((uint)x.Length, (uint)y.Length); for (uint i = 0; i < x.Length; i++) { for (uint j = 0; j < y.Length; j++) { ma.set(i, j, z[i, j]); } } BilinearInterpolation interp = new BilinearInterpolation(xa, ya, ma); // Store the futures and return its id string id = "Int@" + objId; OHRepository.Instance.storeObject(id, interp, callerAddress); id += "#" + (String)DateTime.Now.ToString(@"HH:mm:ss"); return(id); } catch (Exception e) { ExcelUtil.logError(callerAddress, System.Reflection.MethodInfo.GetCurrentMethod().Name.ToString(), e.Message); return(e.Message); } }
public static string eqModelSVI( [ExcelArgument(Description = "id of option to be constructed ")] string ObjectId, [ExcelArgument(Description = "ATM forward ")] double forward, [ExcelArgument(Description = "expiry (years of fraction ")] double tenor, [ExcelArgument(Description = "Strikes ")] double[] strikes, [ExcelArgument(Description = "implied vols ")] double[] volatilities, [ExcelArgument(Description = "initial parameters ")] double[] initials, [ExcelArgument(Description = "trigger ")] object trigger) { if (ExcelUtil.CallFromWizard()) { return(""); } string callerAddress = ""; callerAddress = ExcelUtil.getActiveCellAddress(); try { if (strikes.Length != volatilities.Length) { throw new Exception("SABR input lengths don't match."); } if (initials.Length != 5) { throw new Exception("SVI has five parameters."); } int[] idx = volatilities.Select((v, Index) => new { V = v, idx = Index }) .Where(x => x.V == 0) .Select(x => x.idx) .ToArray(); QlArray xx = new QlArray((uint)strikes.Length - (uint)idx.Length); QlArray yy = new QlArray((uint)volatilities.Length - (uint)idx.Length); for (uint i = 0, j = 0; i < strikes.Length; i++) { if (volatilities[i] == 0) // empty { continue; } xx.set(j, strikes[i]); yy.set(j, volatilities[i]); j++; } EndCriteria endcriteria = new EndCriteria(100000, 100, 1e-8, 1e-8, 1e-8); OptimizationMethod opmodel = new Simplex(0.01); // alpha: ATM Vol, beta: CEV param, rho: underlying/vol correlation, nu: vol of vol SVIInterpolation svi = new SVIInterpolation(xx, yy, tenor, forward, initials[0], initials[1], initials[2], initials[3], initials[4], endcriteria, opmodel, true); double err = 0; err = svi.update(); // Store the option and return its id string id = "MODEL@" + ObjectId; OHRepository.Instance.storeObject(id, svi, callerAddress); id += "#" + (String)DateTime.Now.ToString(@"HH:mm:ss"); return(id); } catch (Exception e) { ExcelUtil.logError(callerAddress, System.Reflection.MethodInfo.GetCurrentMethod().Name.ToString(), e.Message); return(e.Message); } }
static void Main(string[] args) { const int xSteps = 100; const int tSteps = 25; const int dampingSteps = 0; Date today = new Date(15, Month.January, 2020); Settings.instance().setEvaluationDate(today); DayCounter dc = new Actual365Fixed(); YieldTermStructureHandle rTS = new YieldTermStructureHandle( new FlatForward(today, 0.06, dc)); YieldTermStructureHandle qTS = new YieldTermStructureHandle( new FlatForward(today, 0.02, dc)); const double strike = 110.0; StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Put, strike); Date maturityDate = today.Add(new Period(1, TimeUnit.Years)); double maturity = dc.yearFraction(today, maturityDate); Exercise exercise = new AmericanExercise(today, maturityDate); Instrument vanillaOption = new VanillaOption(payoff, exercise); QuoteHandle spot = new QuoteHandle(new SimpleQuote(100.0)); BlackVolTermStructureHandle volatility = new BlackVolTermStructureHandle( new BlackConstantVol(today, new TARGET(), 0.20, dc)); BlackScholesMertonProcess process = new BlackScholesMertonProcess(spot, qTS, rTS, volatility); vanillaOption.setPricingEngine(new FdBlackScholesVanillaEngine( process, tSteps, xSteps, dampingSteps)); double expected = vanillaOption.NPV(); // build an PDE engine from scratch Fdm1dMesher equityMesher = new FdmBlackScholesMesher( xSteps, process, maturity, strike, nullDouble(), nullDouble(), 0.0001, 1.5, new DoublePair(strike, 0.1)); FdmMesherComposite mesher = new FdmMesherComposite(equityMesher); FdmLinearOpComposite op = new FdmBlackScholesOp(mesher, process, strike); FdmInnerValueCalculator calc = new FdmLogInnerValue(payoff, mesher, 0); QlArray x = new QlArray(equityMesher.size()); QlArray rhs = new QlArray(equityMesher.size()); FdmLinearOpIterator iter = mesher.layout().begin(); for (uint i = 0; i < rhs.size(); ++i, iter.increment()) { x.set(i, mesher.location(iter, 0)); rhs.set(i, calc.avgInnerValue(iter, maturity)); } FdmBoundaryConditionSet bcSet = new FdmBoundaryConditionSet(); FdmStepConditionComposite stepCondition = FdmStepConditionComposite.vanillaComposite( new DividendSchedule(), exercise, mesher, calc, today, dc); FdmLinearOpComposite proxyOp = new FdmLinearOpCompositeProxy( new FdmBSDelegate(op)); FdmBackwardSolver solver = new FdmBackwardSolver( proxyOp, bcSet, stepCondition, FdmSchemeDesc.Douglas()); solver.rollback(rhs, maturity, 0.0, tSteps, dampingSteps); double logS = Math.Log(spot.value()); double calculated = new CubicNaturalSpline(x, rhs).call(logS); Console.WriteLine("Homebrew PDE engine : {0:0.0000}", calculated); Console.WriteLine("FdBlackScholesVanillaEngine: {0:0.0000}", expected); }