public Tuple <Date, OptionType, double>[] GetExerciseInfo(IMarketCondition market) { return(EmbededOptions.SelectMany((x, i) => x.ExerciseDates.Select(date => Tuple.Create(date, x.OptionType, x.Strike + (StrikePriceType[i] == PriceQuoteType.Dirty ? 0.0 : GetAccruedInterest(date, market))) )).ToArray()); }
public static double ConvertCcy(this IMarketCondition market, Date date, double amount, CurrencyCode fromCcy, CurrencyCode toCcy) { if (fromCcy == toCcy) { return(amount); } return(amount * market.GetFxRate(date, fromCcy, toCcy)); }
protected override double CalcPv(IOption option, IMarketCondition market, double timeIncrement = 0.0) { //if (!(option is BarrierOption)) //{ // throw new PricingLibraryException("Must be dko option in McDkoBbEngine!"); //} //return markets.Select(m => CalcSinglePv(option as BarrierOption, m)).ToArray(); return(CalcSinglePv(option as BarrierOption, market)); }
public double ModelValue(IMarketCondition market, MktInstrumentCalibMethod calibMethod = MktInstrumentCalibMethod.Default) { var discountCurve = market.DiscountCurve.Value; var dividendCurve = market.DividendCurves.Value.Values.First(); return(market.SpotPrices.Value.Values.First() * dividendCurve.GetDf(market.ValuationDate, UnderlyingMaturityDate) / discountCurve.GetDf(market.ValuationDate, UnderlyingMaturityDate)); }
private BarrierOptionCalculator configureCalculator(IOption option, IMarketCondition market, double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0) { var trade = (BarrierOption)option; var exerciseDate = trade.ExerciseDates.Last(); var maturityDate = trade.UnderlyingMaturityDate; var spot = market.SpotPrices.Value.Values.First(); double exerciseInYears; if (!double.IsNaN(expiryDayRemainingLife)) { exerciseInYears = expiryDayRemainingLife; } else { exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement; } //barrier adjust var dt = trade.DayCount.CalcDayCountFraction(trade.ObservationDates.First(), trade.ObservationDates.Last()) / trade.ObservationDates.Length; var riskFreeRate = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate); var riskfreeRateAtMaturity = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate); var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate); var dividendInput = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate, option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount); var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate); var vol = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(), exerciseDate: exerciseDate, option: option, spot: spot); var barrierCalculator = new BarrierOptionCalculator( trade.OptionType, trade.BarrierType, trade.Rebate, trade.IsDiscreteMonitored ? DiscreteAdjustedBarrier(trade.BarrierType, trade.Position, trade.Barrier, vol, dt, trade.BarrierShift) : trade.Barrier, trade.IsDiscreteMonitored ? DiscreteAdjustedBarrier(trade.BarrierType, trade.Position, trade.UpperBarrier, vol, dt, trade.BarrierShift) : trade.UpperBarrier, option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike, spot, exerciseInYears, vol, riskFreeRate, dividendRate, valuationDate: market.ValuationDate, exerciseDate: exerciseDate, underlyingMaturityDate: trade.UnderlyingMaturityDate, dayCount: trade.DayCount, underlyingInstrumentType: trade.UnderlyingProductType, notional: trade.Notional ); this._calculator = barrierCalculator; return(barrierCalculator); }
private AsianOptionCalculator ConfigureCalculator(IOption option, IMarketCondition market, double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0) { var trade = (AsianOption)option; var exerciseDate = trade.ExerciseDates.Last(); var remainingObsDates = trade.ObservationDates.Where(x => x >= market.ValuationDate).ToArray(); var numOfObsDates = trade.ObservationDates.Count(); var numOfObservedDates = numOfObsDates - remainingObsDates.Count(); var observedAverage = trade.Fixings.Any() ? trade.Fixings.Average(x => x.Value) : market.SpotPrices.Value.Values.First(); //if (trade.Fixings.Count != numOfObservedDates) //{ // throw new PricingLibraryException("AsianOption: number of fixings does not match!"); //} var spot = market.SpotPrices.Value.Values.First(); double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(), exerciseDate: exerciseDate, option: option, spot: spot); double t; if (!double.IsNaN(expiryDayRemainingLife)) { t = expiryDayRemainingLife; } else { t = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement; } var t2 = AnalyticalOptionPricerUtil.timeToMaturityFraction(trade.ObservationDates[0], remainingObsDates.Last(), trade); var t1 = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, remainingObsDates[0], trade) + timeIncrement; var riskFreeRate = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate); var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate); var dividendInput = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate, option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount); var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate); var calculator = new AsianOptionCalculator(trade.OptionType, trade.AsianType, trade.UnderlyingProductType, trade.StrikeStyle, strike: option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike, spotPrice: spot, realizedAveragePrice: observedAverage, exerciseInYears: t, originalAveragePeriod: t2, timetoNextAveragePoint: t1, sigma: sigma, riskFreeRate: riskFreeRate, dividendRate: dividendRate, notional: trade.Notional, numOfObsDates: numOfObsDates, numOfObservedDates: numOfObservedDates); this._calculator = calculator; return(calculator); }
public Cashflow[] GetCashflows(IMarketCondition market, bool netted = true) { //TODO return(new[] { new Cashflow(StartDate, UnderlyingMaturityDate, UnderlyingMaturityDate, -NotionalInFgnCcy * NearStrikeFxRate, DomCcy, CashflowType.Gross, true, market.GetDf(UnderlyingMaturityDate), null), new Cashflow(StartDate, UnderlyingMaturityDate, UnderlyingMaturityDate, NotionalInFgnCcy, FgnCcy, CashflowType.Gross, true, market.GetDf(UnderlyingMaturityDate), null), }); }
public override IPricingResult Calculate(FxOption fxOption, IMarketCondition market, PricingRequest request) { var newMarket = market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DividendCurves, market.FgnDiscountCurve.Value), new UpdateMktConditionPack <double>(x => x.SpotPrices.Value.Values.First(), market.GetFxRate(GetSpotDate(market.ValuationDate, fxOption), fxOption.DomCcy, fxOption.FgnCcy)) ); return(new AnalyticalVanillaEuropeanOptionEngine().Calculate(fxOption, newMarket, request)); }
protected override double CalcPv(IOption option, IMarketCondition market, double timeIncrement = 0.0) { var trade = (BarrierOption)option; var exerciseDate = trade.ExerciseDates.Last(); var maturityDate = trade.UnderlyingMaturityDate; var unitPv = DoCalcPv(option, market, timeIncrement: timeIncrement); return(unitPv * trade.ParticipationRate); //+ trade.Notional * trade.Coupon * market.DiscountCurve.Value.GetDf(exerciseDate, maturityDate); }
public override IPricingResult Calculate(DynamicLeveragedNote dln, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); double finalLeverage; result.Pv = CalcPv(dln, market, out finalLeverage); result.Delta = finalLeverage * result.Pv; return(result); }
public int GetAccruedInterestDays(Date calcDate, IMarketCondition market, bool isEod = false) { if (calcDate < StartDate || calcDate >= UnderlyingMaturityDate) { return(0); } var cashflows = GetAiCashflows(market, false); return(AiCalculation.GetAccruedInterestDays(calcDate, cashflows, isEod)); }
protected override double CalcIntrinsicValue(IOption option, IMarketCondition market) { var barrier = option as BarrierOption; double S = market.SpotPrices.Value.Values.First(); double _H = barrier.Barrier; double _X = barrier.Strike; double _rebate = barrier.Rebate; //price here if (barrier.BarrierType.Equals(BarrierType.DownAndIn)) { if (S <= _H) { return(base.CalcIntrinsicValue(option, market)); } else { return(_rebate * barrier.Notional); } } else if (barrier.BarrierType.Equals(BarrierType.UpAndIn)) { if (S >= _H) { return(base.CalcIntrinsicValue(option, market)); } else { return(_rebate * barrier.Notional); } } else if (barrier.BarrierType.Equals(BarrierType.DownAndOut)) { if (S <= _H) { return(_rebate * barrier.Notional); // already knocked out } else { return(base.CalcIntrinsicValue(option, market)); } } else //if (barrier.BarrierType.Equals(BarrierType.UpAndOut) ) { if (S >= _H) { return(_rebate * barrier.Notional); // already knocked out } else { return(base.CalcIntrinsicValue(option, market)); } } }
protected override double CalcPv(IOption option, IMarketCondition market, double timeIncrement = 0.0) { if (!(option is VanillaOption)) { throw new PricingBaseException(""); } var trade = (VanillaOption)option; var BSCalculator = ConfigureCalculator(option, market, timeIncrement: timeIncrement); return(BSCalculator.Pv); }
public override IPricingResult Calculate(CallableBond callableBond, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); if (result.IsRequested(PricingRequest.Pv)) { result.Pv = CalcPv(callableBond, market); } return(result); }
//Todo:Payoff protected override double CalcIntrinsicValue(IOption option, IMarketCondition market) { if (option.OptionType == OptionType.Call) { return((market.SpotPrices.Value.Values.First() - option.Strike) * option.Notional); } else { return((option.Strike - market.SpotPrices.Value.Values.First()) * option.Notional); } }
public Cashflow[] GetCashflows(IMarketCondition market, bool netted = true) { return(DomCcyLeg.GetCashflows(market, netted) .Union(FgnCcyLeg.GetCashflows( market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.FgnDiscountCurve.Value), new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FgnFixingCurve.Value) ), netted) ).ToArray()); }
public static double GetDf(this IMarketCondition market, Date date) { if (market.DiscountCurve.HasValue && market.DiscountCurve.Value != null) { return(market.DiscountCurve.Value.GetDf(date)); } else { return(1.0); } }
/// <summary> /// 计算Pv /// </summary> /// <param name="trade">交易</param> /// <param name="market">市场数据对象</param> /// <returns>计算结果</returns> public virtual double CalcPv(TTrade trade, IMarketCondition market) { if (market.ValuationDate >= trade.UnderlyingMaturityDate) { return(0.0); } var cfs = trade.GetCashflows(market, true); return(cfs.Where(cf => cf.PaymentDate > market.ValuationDate) .Sum(cf => cf.PaymentAmount * market.DiscountCurve.Value.GetDf(market.ValuationDate, cf.PaymentDate))); }
private double DoCalcExpiryDelta(IOption option, IMarketCondition market, double T) { var markets = new[] { market, market.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, double> >(x => x.SpotPrices, new Dictionary <string, double> { { "", market.SpotPrices.Value.Values.First() + SpotPriceBump } })), }; return(CalcExpiryDelta(option, markets, T)); }
private ISpread GetUnderlyingBondZeroSpread(Bond bond, IMarketCondition market) { if (market.CreditSpread.HasValue) { return(market.CreditSpread.Value); } else { var bMarket = market.UpdateCondition(new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.UnderlyingDiscountCurve.Value)); return(new ZeroSpread(BondPricingFunctions.ZeroSpread(bond, bMarket))); } }
public virtual double CalcPv(Forward <TUnderlying> trade, IMarketCondition market) { if (market.ValuationDate >= trade.UnderlyingMaturityDate) { return(0.0); } var cfs = trade.GetReplicatingCashflows(market); return(cfs[0].PaymentAmount * (market.DividendCurves.HasValue ? market.DividendCurves.Value.Values.First().GetDf(market.ValuationDate, trade.UnderlyingMaturityDate) : 1.0) + cfs.Last().PaymentAmount *market.DiscountCurve.Value.GetDf(market.ValuationDate, trade.UnderlyingMaturityDate) + cfs.Where((x, i) => !(i == 0 || i == cfs.Length - 1)).Sum(x => x.PaymentAmount * market.UnderlyingDiscountCurve.Value.GetDf(market.ValuationDate, x.PaymentDate))); }
public override IPricingResult Calculate(Loan trade, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); if (result.IsRequested(PricingRequest.Cashflow)) { result.Cashflows = trade.GetCashflows(market); result.CashflowDict = result.Cashflows.ToDictionary(x => x.ToCfKey(), x => x.PaymentAmount); } return(result); }
public Cashflow[] GetCashflows(IMarketCondition market, bool netted = true) { var accDates = Accruals.ToArray(); var cashflowType = (Coupon is FixedCoupon) ? CashflowType.FixedLegInterest : CashflowType.FloatingLegInterest; var cashflows = new List <Cashflow>(); for (var i = 0; i < accDates.Length - 1; ++i) { CfCalculationDetail[] temp; var paymentRate = Coupon.GetCoupon(accDates[i], accDates[i + 1], market.FixingCurve.Value, market.HistoricalIndexRates, out temp) * DayCount.CalcDayCountFraction(accDates[i], accDates[i + 1]); cashflows.Add( new Cashflow( accDates[i], accDates[i + 1], accDates[i + 1], Notional * paymentRate, Currency, cashflowType, temp.Aggregate(true, (current, x) => current && x.IsFixed), market.DiscountCurve.Value.GetDf(accDates[i + 1]), temp ) ); } if (NotionalExchange) { if (cashflows.Count >= 1) { var last = cashflows[cashflows.Count - 1]; if (netted) { cashflows[cashflows.Count - 1] = new Cashflow(last.AccrualStartDate, last.AccrualEndDate, last.PaymentDate, last.PaymentAmount + Notional, Currency, CashflowType.Principal, last.IsFixed, market.DiscountCurve.Value.GetDf(last.PaymentDate), last.CalculationDetails); } else { cashflows.Add(new Cashflow(last.AccrualStartDate, last.AccrualEndDate, last.PaymentDate, Notional, Currency, CashflowType.Principal, true, market.DiscountCurve.Value.GetDf(last.PaymentDate), null)); } } } if (TerminationDate != null && !double.IsNaN(TerminationAmount)) { return(cashflows.Where(x => x.PaymentDate < TerminationDate).ToArray() .Union(new[] { new Cashflow(TerminationDate, TerminationDate, TerminationDate, TerminationAmount, Currency, CashflowType.TerminationFee, true, market.DiscountCurve.Value.GetDf(TerminationDate), null) }) .ToArray()); } else { return(cashflows.ToArray()); } }
private BinomialTree BuildTree(IMarketCondition market, double tEnd, double strike, double spotPrice, int steps, double vol, double r) { //most suitable arrangement to deal with both strike vol and moneyness vol var process = new BlackScholesProcess( r: r, q: 0.0, sigma: vol ); return(_binomialTreeType == BinomialTreeType.CoxRossRubinstein ? (BinomialTree) new CoxRossRubinsteinBinomialTree(process, spotPrice, tEnd, steps) : new LeisenReimerBinomialTree(process, spotPrice, strike, tEnd, steps)); }
public double ParSpread(CreditDefaultSwap creditDefaultSwap, IMarketCondition market) { if (market.ValuationDate >= creditDefaultSwap.UnderlyingMaturityDate) { throw new PricingBaseException("Instrument has matured!"); } var coupon = ((FixedCoupon)creditDefaultSwap.PremiumLeg.Coupon).FixedRate; var rpv01 = _premiumLegEngine.Calculate(creditDefaultSwap.PremiumLeg, market, PricingRequest.Pv).Pv / coupon; var protectionLegPv = _protectionLegEngine.Calculate(creditDefaultSwap.ProtectionLeg, market, PricingRequest.Pv).Pv; return(Math.Abs(protectionLegPv / rpv01)); }
protected virtual double CalcIntrinsicValue(IOption option, IMarketCondition market) { double strike = option.IsMoneynessOption ? option.Strike * option.InitialSpotPrice : option.Strike; if (option.OptionType == OptionType.Call) { return(Math.Round(Math.Max(market.SpotPrices.Value.Values.First() - strike, 0), PayoffPreciseToDecimalPlace) * option.Notional); } else { return(Math.Round(Math.Max(strike - market.SpotPrices.Value.Values.First(), 0), PayoffPreciseToDecimalPlace) * option.Notional); } }
/// <summary> /// 计算Delta /// </summary> /// <param name="option">期权</param> /// <param name="market">市场</param> /// <returns>计算结果</returns> public virtual double CalcDelta(IOption option, IMarketCondition market) { var markets = new[] { market, market.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, double> >(x => x.SpotPrices, new Dictionary <string, double> { { "", market.SpotPrices.Value.Values.First() + SpotPriceBump } })), }; var pvs = CalcPvs(option, markets); return((pvs[1] - pvs[0]) / SpotPriceBump); }
private void GetExercisePrices(ConvertibleBond convertibleBond, IMarketCondition market, IDayCount dayCount, Date valueDate, double dt, VanillaOption[] options, PriceQuoteType[] optionStrikeType, out double[] callExercisePrices, out double[] putExercisePrices ) { var infinity = 1.0e20; callExercisePrices = Enumerable.Range(0, _steps + 1).Select(x => infinity).ToArray(); putExercisePrices = Enumerable.Range(0, _steps + 1).Select(x => - infinity).ToArray(); if (options == null) { return; } for (var i = 0; i < options.Length; ++i) { var option = options[i]; var start = option.ExerciseDates.First(); var end = option.ExerciseDates.Last(); var startInd = start <= valueDate ? 0 : (int)Math.Round(dayCount.CalcDayCountFraction(valueDate, start) / dt); var endInd = start >= convertibleBond.UnderlyingMaturityDate ? _steps : (int)Math.Round(dayCount.CalcDayCountFraction(valueDate, end) / dt); for (var j = startInd; j <= endInd; ++j) { if (option.OptionType == OptionType.Call) { callExercisePrices[j] = option.Strike; if (optionStrikeType[i] == PriceQuoteType.Clean) { var date = new Term(j * dt, Period.Year).Next(valueDate); callExercisePrices[j] += convertibleBond.GetAccruedInterest(date, market); } } else { putExercisePrices[j] = option.Strike; if (optionStrikeType[i] == PriceQuoteType.Clean) { var date = new Term(j * dt, Period.Year).Next(valueDate); putExercisePrices[j] += convertibleBond.GetAccruedInterest(date, market); } } } } }
public override IPricingResult Calculate(ConstantLeveragedNote cln, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); double finalNoteValue; result.Pv = CalcPv(cln, market, out finalNoteValue); var startFxRate = cln.FxRates[cln.StartDate]; var endFxRate = cln.FxRates[market.ValuationDate]; result.Delta = finalNoteValue * cln.TargetLeverage * endFxRate / startFxRate; return(result); }
private BinomialTree BuildTree(ConvertibleBond convertibleBond, IMarketCondition market) { var endDate = convertibleBond.UnderlyingMaturityDate; //assuming we use a strike vol var process = new BlackScholesProcess( market.DiscountCurve.Value.ZeroRate(market.ValuationDate, endDate), market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, endDate), market.VolSurfaces.Value.Values.First().GetValue(endDate, market.SpotPrices.Value.Values.First()) ); var dayCount = market.DiscountCurve.Value.DayCount; var tEnd = dayCount.CalcDayCountFraction(market.ValuationDate, convertibleBond.UnderlyingMaturityDate); return(new CoxRossRubinsteinBinomialTree(process, market.SpotPrices.Value.Values.First(), tEnd, _steps)); }