public override void calculate(IPricingEngineResults r) { OneAssetOption.Results results = r as OneAssetOption.Results; setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); initializeStepCondition(); // typedef StandardSystemFiniteDifferenceModel model_type; List <IOperator> operatorSet = new List <IOperator>(); List <Vector> arraySet = new List <Vector>(); BoundaryConditionSet bcSet = new BoundaryConditionSet(); StepConditionSet <Vector> conditionSet = new StepConditionSet <Vector>(); prices_ = (SampledCurve)intrinsicValues_.Clone(); controlPrices_ = (SampledCurve)intrinsicValues_.Clone(); controlOperator_ = (TridiagonalOperator)finiteDifferenceOperator_.Clone(); controlBCs_[0] = BCs_[0]; controlBCs_[1] = BCs_[1]; operatorSet.Add(finiteDifferenceOperator_); operatorSet.Add(controlOperator_); arraySet.Add(prices_.values()); arraySet.Add(controlPrices_.values()); bcSet.Add(BCs_); bcSet.Add(controlBCs_); conditionSet.Add(stepCondition_); conditionSet.Add(new NullCondition <Vector>()); var model = new FiniteDifferenceModel <ParallelEvolver <CrankNicolson <TridiagonalOperator> > >(operatorSet, bcSet); object temp = arraySet; model.rollback(ref temp, getResidualTime(), 0.0, timeSteps_, conditionSet); arraySet = (List <Vector>)temp; prices_.setValues(arraySet[0]); controlPrices_.setValues(arraySet[1]); StrikedTypePayoff striked_payoff = payoff_ as StrikedTypePayoff; if (striked_payoff == null) { throw new ApplicationException("non-striked payoff given"); } double variance = process_.blackVolatility().link.blackVariance(exerciseDate_, striked_payoff.strike()); double dividendDiscount = process_.dividendYield().link.discount(exerciseDate_); double riskFreeDiscount = process_.riskFreeRate().link.discount(exerciseDate_); double spot = process_.stateVariable().link.value(); double forwardPrice = spot * dividendDiscount / riskFreeDiscount; BlackCalculator black = new BlackCalculator(striked_payoff, forwardPrice, Math.Sqrt(variance), riskFreeDiscount); results.value = prices_.valueAtCenter() - controlPrices_.valueAtCenter() + black.value(); results.delta = prices_.firstDerivativeAtCenter() - controlPrices_.firstDerivativeAtCenter() + black.delta(spot); results.gamma = prices_.secondDerivativeAtCenter() - controlPrices_.secondDerivativeAtCenter() + black.gamma(spot); results.additionalResults.Add("priceCurve", prices_); }
public void rollback(ref object a, double from, double to, int steps, int dampingSteps) { double deltaT = from - to; int allSteps = steps + dampingSteps; double dampingTo = from - (deltaT * dampingSteps) / allSteps; if (dampingSteps > 0 && schemeDesc_.type != FdmSchemeDesc.FdmSchemeType.ImplicitEulerType) { ImplicitEulerScheme implicitEvolver = new ImplicitEulerScheme(map_, bcSet_); FiniteDifferenceModel <ImplicitEulerScheme> dampingModel = new FiniteDifferenceModel <ImplicitEulerScheme>(implicitEvolver, condition_.stoppingTimes()); dampingModel.rollback(ref a, from, dampingTo, dampingSteps, condition_); } switch (schemeDesc_.type) { case FdmSchemeDesc.FdmSchemeType.HundsdorferType: { HundsdorferScheme hsEvolver = new HundsdorferScheme(schemeDesc_.theta, schemeDesc_.mu, map_, bcSet_); FiniteDifferenceModel <HundsdorferScheme> hsModel = new FiniteDifferenceModel <HundsdorferScheme>(hsEvolver, condition_.stoppingTimes()); hsModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.DouglasType: { DouglasScheme dsEvolver = new DouglasScheme(schemeDesc_.theta, map_, bcSet_); FiniteDifferenceModel <DouglasScheme> dsModel = new FiniteDifferenceModel <DouglasScheme>(dsEvolver, condition_.stoppingTimes()); dsModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.CrankNicolsonType: { CrankNicolsonScheme cnEvolver = new CrankNicolsonScheme(schemeDesc_.theta, map_, bcSet_); FiniteDifferenceModel <CrankNicolsonScheme> cnModel = new FiniteDifferenceModel <CrankNicolsonScheme>(cnEvolver, condition_.stoppingTimes()); cnModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.CraigSneydType: { CraigSneydScheme csEvolver = new CraigSneydScheme(schemeDesc_.theta, schemeDesc_.mu, map_, bcSet_); FiniteDifferenceModel <CraigSneydScheme> csModel = new FiniteDifferenceModel <CraigSneydScheme>(csEvolver, condition_.stoppingTimes()); csModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.ModifiedCraigSneydType: { ModifiedCraigSneydScheme csEvolver = new ModifiedCraigSneydScheme(schemeDesc_.theta, schemeDesc_.mu, map_, bcSet_); FiniteDifferenceModel <ModifiedCraigSneydScheme> mcsModel = new FiniteDifferenceModel <ModifiedCraigSneydScheme>(csEvolver, condition_.stoppingTimes()); mcsModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.ImplicitEulerType: { ImplicitEulerScheme implicitEvolver = new ImplicitEulerScheme(map_, bcSet_); FiniteDifferenceModel <ImplicitEulerScheme> implicitModel = new FiniteDifferenceModel <ImplicitEulerScheme>(implicitEvolver, condition_.stoppingTimes()); implicitModel.rollback(ref a, from, to, allSteps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.ExplicitEulerType: { ExplicitEulerScheme explicitEvolver = new ExplicitEulerScheme(map_, bcSet_); FiniteDifferenceModel <ExplicitEulerScheme> explicitModel = new FiniteDifferenceModel <ExplicitEulerScheme>(explicitEvolver, condition_.stoppingTimes()); explicitModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.MethodOfLinesType: { MethodOfLinesScheme methodOfLines = new MethodOfLinesScheme(schemeDesc_.theta, schemeDesc_.mu, map_, bcSet_); FiniteDifferenceModel <MethodOfLinesScheme> molModel = new FiniteDifferenceModel <MethodOfLinesScheme>(methodOfLines, condition_.stoppingTimes()); molModel.rollback(ref a, dampingTo, to, steps, condition_); } break; case FdmSchemeDesc.FdmSchemeType.TrBDF2Type: { FdmSchemeDesc trDesc = new FdmSchemeDesc().CraigSneyd(); CraigSneydScheme hsEvolver = new CraigSneydScheme(trDesc.theta, trDesc.mu, map_, bcSet_); TrBDF2Scheme <CraigSneydScheme> trBDF2 = new TrBDF2Scheme <CraigSneydScheme>( schemeDesc_.theta, map_, hsEvolver, bcSet_, schemeDesc_.mu); FiniteDifferenceModel <TrBDF2Scheme <CraigSneydScheme> > trBDF2Model = new FiniteDifferenceModel <TrBDF2Scheme <CraigSneydScheme> >(trBDF2, condition_.stoppingTimes()); trBDF2Model.rollback(ref a, dampingTo, to, steps, condition_); } break; default: Utils.QL_FAIL("Unknown scheme type"); break; } }
public override void calculate(IPricingEngineResults r) { OneAssetOption.Results results = r as OneAssetOption.Results; if (results == null) { throw new ApplicationException("incorrect results type"); } double beginDate, endDate; int dateNumber = stoppingTimes_.Count; bool lastDateIsResTime = false; int firstIndex = -1; int lastIndex = dateNumber - 1; bool firstDateIsZero = false; double firstNonZeroDate = getResidualTime(); double dateTolerance = 1e-6; int j; if (dateNumber > 0) { if (!(getDividendTime(0) >= 0)) { throw new ApplicationException("first date (" + getDividendTime(0) + ") cannot be negative"); } if (getDividendTime(0) < getResidualTime() * dateTolerance) { firstDateIsZero = true; firstIndex = 0; if (dateNumber >= 2) { firstNonZeroDate = getDividendTime(1); } } if (Math.Abs(getDividendTime(lastIndex) - getResidualTime()) < dateTolerance) { lastDateIsResTime = true; lastIndex = dateNumber - 2; } if (!firstDateIsZero) { firstNonZeroDate = getDividendTime(0); } if (dateNumber >= 2) { for (j = 1; j < dateNumber; j++) { if (!(getDividendTime(j - 1) < getDividendTime(j))) { throw new ApplicationException("dates must be in increasing order: " + getDividendTime(j - 1) + " is not strictly smaller than " + getDividendTime(j)); } } } } double dt = getResidualTime() / (timeStepPerPeriod_ * (dateNumber + 1)); // Ensure that dt is always smaller than the first non-zero date if (firstNonZeroDate <= dt) { dt = firstNonZeroDate / 2.0; } setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); initializeModel(); initializeStepCondition(); prices_ = (SampledCurve)intrinsicValues_.Clone(); if (lastDateIsResTime) { executeIntermediateStep(dateNumber - 1); } j = lastIndex; object temp; do { if (j == dateNumber - 1) { beginDate = getResidualTime(); } else { beginDate = getDividendTime(j + 1); } if (j >= 0) { endDate = getDividendTime(j); } else { endDate = dt; } temp = prices_.values(); model_.rollback(ref temp, beginDate, endDate, timeStepPerPeriod_, stepCondition_); prices_.setValues((Vector)temp); if (j >= 0) { executeIntermediateStep(j); } } while (--j >= firstIndex); temp = prices_.values(); model_.rollback(ref temp, dt, 0, 1, stepCondition_); prices_.setValues((Vector)temp); if (firstDateIsZero) { executeIntermediateStep(0); } results.value = prices_.valueAtCenter(); results.delta = prices_.firstDerivativeAtCenter(); results.gamma = prices_.secondDerivativeAtCenter(); results.additionalResults["priceCurve"] = prices_; }