packages feed

hasquant 0.5.0.2 → 0.6.0.0

raw patch · 67 files changed

+8993/−1355 lines, 67 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- QuantLib.Index.Equity: currency :: EquityIndex -> IO Currency
- QuantLib.Index.Equity: equityDividendCurve :: EquityIndex -> IO YieldTermStructure
- QuantLib.Index.Equity: equityInterestRateCurve :: EquityIndex -> IO YieldTermStructure
- QuantLib.Index.Equity: spot :: EquityIndex -> IO Quote
- QuantLib.Instrument: instance GHC.Classes.Eq QuantLib.Instrument.AdditionalResultType
- QuantLib.Instrument: instance GHC.Classes.Eq QuantLib.Instrument.AdditionalResultVal
- QuantLib.Instrument: instance GHC.Internal.Enum.Enum QuantLib.Instrument.AdditionalResultType
- QuantLib.Instrument: instance GHC.Internal.Foreign.Storable.Storable QuantLib.Instrument.RawResult
- QuantLib.Instrument: instance GHC.Internal.Show.Show QuantLib.Instrument.AdditionalResultType
- QuantLib.Instrument: instance GHC.Internal.Show.Show QuantLib.Instrument.AdditionalResultVal
- QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasFixedLeg QuantLib.Internal.Type.VanillaSwap
- QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasFloatingLeg QuantLib.Internal.Type.VanillaSwap
- QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasSpread QuantLib.Internal.Type.VanillaSwap
- QuantLib.Model: G2 :: G2 -> AffineModel
- QuantLib.Model: Gsr :: Gsr -> Gaussian1dModel
- QuantLib.Model: HullWhite :: HullWhite -> AffineModel
- QuantLib.Model: LiborForwardModel :: LiborForwardModel -> AffineModel
- QuantLib.Model: MarkovFunctional :: MarkovFunctional -> Gaussian1dModel
- QuantLib.Model: OneFactorAffineModel :: OneFactorAffineModel -> AffineModel
- QuantLib.Model: data AffineModel
- QuantLib.Model: data Gaussian1dModel
- QuantLib.Time.Calendar: instance GHC.Classes.Eq QuantLib.Time.Calendar.BusinessDayConvention
- QuantLib.Time.Calendar: instance GHC.Internal.Enum.Enum QuantLib.Time.Calendar.BusinessDayConvention
- QuantLib.Time.Calendar: instance GHC.Internal.Show.Show QuantLib.Time.Calendar.BusinessDayConvention
+ QuantLib.CashFlow: bachelierYoYInflationCouponPricer :: YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO YoYInflationCouponPricer
+ QuantLib.CashFlow: blackYoYInflationCouponPricer :: YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO YoYInflationCouponPricer
+ QuantLib.CashFlow: data YoYInflationCouponPricer
+ QuantLib.CashFlow: instance GHC.Classes.Eq QuantLib.CashFlow.LinearTsrPricerStrategyTag
+ QuantLib.CashFlow: instance GHC.Internal.Enum.Enum QuantLib.CashFlow.LinearTsrPricerStrategyTag
+ QuantLib.CashFlow: instance GHC.Internal.Show.Show QuantLib.CashFlow.LinearTsrPricerStrategyTag
+ QuantLib.CashFlow: setYoYInflationCouponPricer :: GenLeg l -> YoYInflationCouponPricer -> IO ()
+ QuantLib.CashFlow: unitDisplacedBlackYoYInflationCouponPricer :: YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO YoYInflationCouponPricer
+ QuantLib.Commodity: Energy :: UnitOfMeasureType
+ QuantLib.Commodity: Mass :: UnitOfMeasureType
+ QuantLib.Commodity: PricingDate :: PaymentTermEventType
+ QuantLib.Commodity: QuantityUnit :: UnitOfMeasureType
+ QuantLib.Commodity: TradeDate :: PaymentTermEventType
+ QuantLib.Commodity: UomDerived :: UnitOfMeasureConversionType
+ QuantLib.Commodity: UomDirect :: UnitOfMeasureConversionType
+ QuantLib.Commodity: Volume :: UnitOfMeasureType
+ QuantLib.Commodity: addUomConversion :: UnitOfMeasureConversion -> IO ()
+ QuantLib.Commodity: barrelUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: chainUnitOfMeasureConversion :: UnitOfMeasureConversion -> UnitOfMeasureConversion -> IO UnitOfMeasureConversion
+ QuantLib.Commodity: clearUomConversions :: IO ()
+ QuantLib.Commodity: closeEnoughQuantity :: Quantity -> Quantity -> Int -> IO Bool
+ QuantLib.Commodity: closeQuantity :: Quantity -> Quantity -> Int -> IO Bool
+ QuantLib.Commodity: commoditySettingsCurrency :: IO Currency
+ QuantLib.Commodity: commoditySettingsUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: commodityType :: String -> String -> IO CommodityType
+ QuantLib.Commodity: commodityTypeCode :: CommodityType -> String
+ QuantLib.Commodity: commodityTypeEmpty :: CommodityType -> Bool
+ QuantLib.Commodity: commodityTypeName :: CommodityType -> String
+ QuantLib.Commodity: convertQuantity :: UnitOfMeasureConversion -> Quantity -> IO Quantity
+ QuantLib.Commodity: data CommodityType
+ QuantLib.Commodity: data PaymentTerm
+ QuantLib.Commodity: data PaymentTermEventType
+ QuantLib.Commodity: data PricingPeriod
+ QuantLib.Commodity: data UnitOfMeasure
+ QuantLib.Commodity: data UnitOfMeasureConversion
+ QuantLib.Commodity: data UnitOfMeasureConversionType
+ QuantLib.Commodity: data UnitOfMeasureType
+ QuantLib.Commodity: gallonUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: instance GHC.Classes.Eq QuantLib.Commodity.PricingPeriod
+ QuantLib.Commodity: instance GHC.Classes.Eq QuantLib.Commodity.UnitOfMeasureConversionType
+ QuantLib.Commodity: instance GHC.Internal.Enum.Enum QuantLib.Commodity.UnitOfMeasureConversionType
+ QuantLib.Commodity: instance GHC.Internal.Show.Show QuantLib.Commodity.PricingPeriod
+ QuantLib.Commodity: instance GHC.Internal.Show.Show QuantLib.Commodity.UnitOfMeasureConversionType
+ QuantLib.Commodity: intersection :: DateInterval -> DateInterval -> Maybe DateInterval
+ QuantLib.Commodity: isDateBetween :: DateInterval -> Day -> Bool -> Bool -> Bool
+ QuantLib.Commodity: kilolitreUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: litreUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: lookupUomConversion :: CommodityType -> UnitOfMeasure -> UnitOfMeasure -> UnitOfMeasureConversionType -> IO UnitOfMeasureConversion
+ QuantLib.Commodity: lotUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: mbUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: mtUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: nullCommodityType :: IO CommodityType
+ QuantLib.Commodity: paymentTerm :: String -> PaymentTermEventType -> Int -> Calendar -> IO PaymentTerm
+ QuantLib.Commodity: paymentTermCalendar :: PaymentTerm -> IO Calendar
+ QuantLib.Commodity: paymentTermEmpty :: PaymentTerm -> Bool
+ QuantLib.Commodity: paymentTermEventType :: PaymentTerm -> PaymentTermEventType
+ QuantLib.Commodity: paymentTermGetPaymentDate :: PaymentTerm -> Day -> IO Day
+ QuantLib.Commodity: paymentTermName :: PaymentTerm -> String
+ QuantLib.Commodity: paymentTermOffsetDays :: PaymentTerm -> Int
+ QuantLib.Commodity: pricingPeriod :: Day -> Day -> Day -> Quantity -> PricingPeriod
+ QuantLib.Commodity: pricingPeriodEndDate :: PricingPeriod -> Day
+ QuantLib.Commodity: pricingPeriodPaymentDate :: PricingPeriod -> Day
+ QuantLib.Commodity: pricingPeriodQuantity :: PricingPeriod -> Quantity
+ QuantLib.Commodity: pricingPeriodStartDate :: PricingPeriod -> Day
+ QuantLib.Commodity: roundedQuantity :: Quantity -> Quantity
+ QuantLib.Commodity: setCommoditySettingsCurrency :: Currency -> IO ()
+ QuantLib.Commodity: setCommoditySettingsUnitOfMeasure :: UnitOfMeasure -> IO ()
+ QuantLib.Commodity: tokyoKilolitreUnitOfMeasure :: IO UnitOfMeasure
+ QuantLib.Commodity: type CommodityUnitCost = (Double, Currency, UnitOfMeasure)
+ QuantLib.Commodity: type DateInterval = (Day, Day)
+ QuantLib.Commodity: type PricingPeriods = [PricingPeriod]
+ QuantLib.Commodity: type Quantity = (CommodityType, UnitOfMeasure, Double)
+ QuantLib.Commodity: unitOfMeasure :: String -> String -> UnitOfMeasureType -> IO UnitOfMeasure
+ QuantLib.Commodity: unitOfMeasureCode :: UnitOfMeasure -> String
+ QuantLib.Commodity: unitOfMeasureConversion :: CommodityType -> UnitOfMeasure -> UnitOfMeasure -> Double -> IO UnitOfMeasureConversion
+ QuantLib.Commodity: unitOfMeasureConversionCode :: UnitOfMeasureConversion -> String
+ QuantLib.Commodity: unitOfMeasureConversionCommodityType :: UnitOfMeasureConversion -> IO CommodityType
+ QuantLib.Commodity: unitOfMeasureConversionFactor :: UnitOfMeasureConversion -> Double
+ QuantLib.Commodity: unitOfMeasureConversionSource :: UnitOfMeasureConversion -> IO UnitOfMeasure
+ QuantLib.Commodity: unitOfMeasureConversionTarget :: UnitOfMeasureConversion -> IO UnitOfMeasure
+ QuantLib.Commodity: unitOfMeasureConversionType :: UnitOfMeasureConversion -> UnitOfMeasureConversionType
+ QuantLib.Commodity: unitOfMeasureEmpty :: UnitOfMeasure -> Bool
+ QuantLib.Commodity: unitOfMeasureName :: UnitOfMeasure -> String
+ QuantLib.Commodity: unitOfMeasureType :: UnitOfMeasure -> UnitOfMeasureType
+ QuantLib.Index.Commodity: commodityIndex :: String -> CommodityType -> Currency -> UnitOfMeasure -> Calendar -> Double -> Maybe CommodityCurve -> IO CommodityIndex
+ QuantLib.Index.Commodity: commodityIndexEmpty :: CommodityIndex -> Bool
+ QuantLib.Index.Commodity: commodityIndexForwardPrice :: CommodityIndex -> Day -> IO Double
+ QuantLib.Index.Commodity: commodityIndexLastQuoteDate :: CommodityIndex -> IO Day
+ QuantLib.Index.Commodity: type CommodityIndex = GenIndex CCommodityIndex
+ QuantLib.Instrument: Rebated :: !Exercise -> !Double -> !Word -> !Calendar -> !BusinessDayConvention -> Exercise
+ QuantLib.Instrument.Energy: Absolute :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: DeliveryConstant :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryDaily :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryHourly :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryMonthly :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryQuarterly :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryWeekly :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryWindow :: DeliverySchedule
+ QuantLib.Instrument.Energy: DeliveryYearly :: DeliverySchedule
+ QuantLib.Instrument.Energy: EnergyDailyPosition :: Day -> Double -> Double -> Double -> Double -> Bool -> EnergyDailyPosition
+ QuantLib.Instrument.Energy: Error :: PricingErrorLevel
+ QuantLib.Instrument.Energy: Fatal :: PricingErrorLevel
+ QuantLib.Instrument.Energy: Info :: PricingErrorLevel
+ QuantLib.Instrument.Energy: PerDay :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PerHour :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PerMonth :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PerQuarter :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PerWeek :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PerYear :: QuantityPeriodicity
+ QuantLib.Instrument.Energy: PricingError :: PricingErrorLevel -> String -> String -> PricingError
+ QuantLib.Instrument.Energy: Warning :: PricingErrorLevel
+ QuantLib.Instrument.Energy: [edpDate] :: EnergyDailyPosition -> Day
+ QuantLib.Instrument.Energy: [edpPayLegPrice] :: EnergyDailyPosition -> Double
+ QuantLib.Instrument.Energy: [edpQuantityAmount] :: EnergyDailyPosition -> Double
+ QuantLib.Instrument.Energy: [edpReceiveLegPrice] :: EnergyDailyPosition -> Double
+ QuantLib.Instrument.Energy: [edpRiskDelta] :: EnergyDailyPosition -> Double
+ QuantLib.Instrument.Energy: [edpUnrealized] :: EnergyDailyPosition -> Bool
+ QuantLib.Instrument.Energy: [pricingErrorDetail] :: PricingError -> String
+ QuantLib.Instrument.Energy: [pricingErrorLevel] :: PricingError -> PricingErrorLevel
+ QuantLib.Instrument.Energy: [pricingErrorMessage] :: PricingError -> String
+ QuantLib.Instrument.Energy: addPricingError :: GenCommodity c -> PricingErrorLevel -> String -> String -> IO ()
+ QuantLib.Instrument.Energy: commodityCashFlowDate :: CommodityCashFlow -> Day
+ QuantLib.Instrument.Energy: commodityCashFlowDiscountFactor :: CommodityCashFlow -> Double
+ QuantLib.Instrument.Energy: commodityCashFlowDiscountedAmount :: CommodityCashFlow -> IO (Double, Currency)
+ QuantLib.Instrument.Energy: commodityCashFlowDiscountedPaymentAmount :: CommodityCashFlow -> IO (Double, Currency)
+ QuantLib.Instrument.Energy: commodityCashFlowFinalized :: CommodityCashFlow -> Bool
+ QuantLib.Instrument.Energy: commodityCashFlowPaymentDiscountFactor :: CommodityCashFlow -> Double
+ QuantLib.Instrument.Energy: commodityCashFlowUndiscountedAmount :: CommodityCashFlow -> IO (Double, Currency)
+ QuantLib.Instrument.Energy: commodityCashFlowUndiscountedPaymentAmount :: CommodityCashFlow -> IO (Double, Currency)
+ QuantLib.Instrument.Energy: createPricingPeriods :: Day -> Day -> Quantity -> DeliverySchedule -> QuantityPeriodicity -> PaymentTerm -> IO PricingPeriods
+ QuantLib.Instrument.Energy: dailyPositions :: GenEnergySwap s -> IO EnergyDailyPositions
+ QuantLib.Instrument.Energy: data CommodityCashFlow
+ QuantLib.Instrument.Energy: data DeliverySchedule
+ QuantLib.Instrument.Energy: data EnergyDailyPosition
+ QuantLib.Instrument.Energy: data PricingError
+ QuantLib.Instrument.Energy: data PricingErrorLevel
+ QuantLib.Instrument.Energy: data QuantityPeriodicity
+ QuantLib.Instrument.Energy: energyBasisSwap :: Calendar -> CommodityIndex -> CommodityIndex -> CommodityIndex -> Bool -> Currency -> Currency -> PricingPeriods -> CommodityUnitCost -> CommodityType -> SecondaryCosts -> GenYieldTermStructure y1 -> GenYieldTermStructure y2 -> GenYieldTermStructure y3 -> IO EnergyBasisSwap
+ QuantLib.Instrument.Energy: energyFuture :: Int -> Quantity -> CommodityUnitCost -> CommodityIndex -> CommodityType -> SecondaryCosts -> IO EnergyFuture
+ QuantLib.Instrument.Energy: energyVanillaSwap :: Bool -> Calendar -> (Double, Currency) -> UnitOfMeasure -> CommodityIndex -> Currency -> Currency -> PricingPeriods -> CommodityType -> SecondaryCosts -> GenYieldTermStructure y1 -> GenYieldTermStructure y2 -> GenYieldTermStructure y3 -> IO EnergyVanillaSwap
+ QuantLib.Instrument.Energy: instance GHC.Classes.Eq QuantLib.Instrument.Energy.EnergyDailyPosition
+ QuantLib.Instrument.Energy: instance GHC.Classes.Eq QuantLib.Instrument.Energy.PricingError
+ QuantLib.Instrument.Energy: instance GHC.Internal.Show.Show QuantLib.Instrument.Energy.EnergyDailyPosition
+ QuantLib.Instrument.Energy: instance GHC.Internal.Show.Show QuantLib.Instrument.Energy.PricingError
+ QuantLib.Instrument.Energy: paymentCashFlows :: GenEnergySwap s -> IO [CommodityCashFlow]
+ QuantLib.Instrument.Energy: pricingErrors :: GenCommodity c -> IO PricingErrors
+ QuantLib.Instrument.Energy: quantity :: GenEnergyCommodity e -> IO Quantity
+ QuantLib.Instrument.Energy: secondaryCostAmounts :: GenCommodity c -> IO SecondaryCostAmounts
+ QuantLib.Instrument.Energy: type CommodityCashFlows = [CommodityCashFlow]
+ QuantLib.Instrument.Energy: type EnergyBasisSwap = GenEnergySwap CEnergyBasisSwap
+ QuantLib.Instrument.Energy: type EnergyDailyPositions = [EnergyDailyPosition]
+ QuantLib.Instrument.Energy: type EnergyFuture = GenEnergyCommodity CEnergyFuture
+ QuantLib.Instrument.Energy: type EnergySwap = GenEnergySwap CEnergySwap
+ QuantLib.Instrument.Energy: type EnergyVanillaSwap = GenEnergySwap CEnergyVanillaSwap
+ QuantLib.Instrument.Energy: type PricingErrors = [PricingError]
+ QuantLib.Instrument.Energy: type SecondaryCostAmounts = [(String, (Double, Currency))]
+ QuantLib.Instrument.Energy: type SecondaryCosts = [(String, Either CommodityUnitCost (Double, Currency))]
+ QuantLib.Instrument.InflationCapFloor: cpiCapFloor :: OptionType -> Double -> Day -> Double -> Day -> Calendar -> BusinessDayConvention -> Calendar -> BusinessDayConvention -> Double -> ZeroInflationIndex -> (Word, TimeUnit) -> CPIInterpolationType -> IO CPICapFloor
+ QuantLib.Instrument.InflationCapFloor: type CPICapFloor = GenInstrument CCPICapFloor
+ QuantLib.Instrument.InflationCapFloor: type YoYInflationCapFloor = GenInstrument CYoYInflationCapFloor
+ QuantLib.Instrument.InflationCapFloor: yoyInflationCap :: GenLeg l -> [Double] -> IO YoYInflationCapFloor
+ QuantLib.Instrument.InflationCapFloor: yoyInflationCapFloorAtmRate :: YoYInflationCapFloor -> GenYieldTermStructure y -> IO Double
+ QuantLib.Instrument.InflationCapFloor: yoyInflationCapFloorOptionlet :: YoYInflationCapFloor -> Word -> IO YoYInflationCapFloor
+ QuantLib.Instrument.InflationCapFloor: yoyInflationCollar :: GenLeg l -> [Double] -> [Double] -> IO YoYInflationCapFloor
+ QuantLib.Instrument.InflationCapFloor: yoyInflationFloor :: GenLeg l -> [Double] -> IO YoYInflationCapFloor
+ QuantLib.Instrument.Option: Rebated :: !Exercise -> !Double -> !Word -> !Calendar -> !BusinessDayConvention -> Exercise
+ QuantLib.Instrument.Option: simpleChooserOption :: Day -> Double -> Exercise -> IO OneAssetOption
+ QuantLib.Instrument.Option: softBarrierOption :: BarrierType -> Double -> Double -> StrikedPayoff -> Exercise -> IO SoftBarrierOption
+ QuantLib.Instrument.Option: softBarrierOptionImpliedVolatility :: SoftBarrierOption -> Double -> GenGeneralizedBlackScholesProcess gbs -> Double -> Word -> Double -> Double -> IO Double
+ QuantLib.Instrument.Option: twoAssetCorrelationOption :: OptionType -> Double -> Double -> Exercise -> IO MultiAssetOption
+ QuantLib.Instrument.Option: type SoftBarrierOption = GenOneAssetOption CSoftBarrierOption
+ QuantLib.Instrument.Option: writerExtensibleOption :: PlainVanillaPayoff -> Exercise -> PlainVanillaPayoff -> Exercise -> IO OneAssetOption
+ QuantLib.Instrument.Swap: CalibrationBasketNaive :: CalibrationBasketType
+ QuantLib.Instrument.Swap: ConstNotionalCrossCurrencyBasisSwapOpts :: Int -> Int -> Bool -> Maybe Word -> Bool -> Word -> RateAveragingType -> Bool -> Maybe Word -> Bool -> Word -> RateAveragingType -> Bool -> ConstNotionalCrossCurrencyBasisSwapOpts
+ QuantLib.Instrument.Swap: FloatFloatSwapOpts :: Bool -> Bool -> Double -> Double -> Maybe Double -> Maybe Double -> Double -> Double -> Maybe Double -> Maybe Double -> Maybe BusinessDayConvention -> Maybe BusinessDayConvention -> FloatFloatSwapOpts
+ QuantLib.Instrument.Swap: FloatFloatSwapVaryingOpts :: Bool -> Bool -> [Double] -> [Double] -> [Double] -> [Double] -> [Double] -> [Double] -> [Double] -> [Double] -> Maybe BusinessDayConvention -> Maybe BusinessDayConvention -> FloatFloatSwapVaryingOpts
+ QuantLib.Instrument.Swap: MaturityStrikeByDeltaGamma :: CalibrationBasketType
+ QuantLib.Instrument.Swap: [cccbsPayAveragingMethod] :: ConstNotionalCrossCurrencyBasisSwapOpts -> RateAveragingType
+ QuantLib.Instrument.Swap: [cccbsPayCompoundSpread] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [cccbsPayLockoutDays] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Word
+ QuantLib.Instrument.Swap: [cccbsPayLookbackDays] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Maybe Word
+ QuantLib.Instrument.Swap: [cccbsPayObservationShift] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [cccbsPayPaymentLag] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Int
+ QuantLib.Instrument.Swap: [cccbsRecAveragingMethod] :: ConstNotionalCrossCurrencyBasisSwapOpts -> RateAveragingType
+ QuantLib.Instrument.Swap: [cccbsRecCompoundSpread] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [cccbsRecLockoutDays] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Word
+ QuantLib.Instrument.Swap: [cccbsRecLookbackDays] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Maybe Word
+ QuantLib.Instrument.Swap: [cccbsRecObservationShift] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [cccbsRecPaymentLag] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Int
+ QuantLib.Instrument.Swap: [cccbsTelescopicValueDates] :: ConstNotionalCrossCurrencyBasisSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [ffsCappedRate1] :: FloatFloatSwapOpts -> Maybe Double
+ QuantLib.Instrument.Swap: [ffsCappedRate2] :: FloatFloatSwapOpts -> Maybe Double
+ QuantLib.Instrument.Swap: [ffsFinalCapitalExchange] :: FloatFloatSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [ffsFlooredRate1] :: FloatFloatSwapOpts -> Maybe Double
+ QuantLib.Instrument.Swap: [ffsFlooredRate2] :: FloatFloatSwapOpts -> Maybe Double
+ QuantLib.Instrument.Swap: [ffsGearing1] :: FloatFloatSwapOpts -> Double
+ QuantLib.Instrument.Swap: [ffsGearing2] :: FloatFloatSwapOpts -> Double
+ QuantLib.Instrument.Swap: [ffsIntermediateCapitalExchange] :: FloatFloatSwapOpts -> Bool
+ QuantLib.Instrument.Swap: [ffsPaymentConvention1] :: FloatFloatSwapOpts -> Maybe BusinessDayConvention
+ QuantLib.Instrument.Swap: [ffsPaymentConvention2] :: FloatFloatSwapOpts -> Maybe BusinessDayConvention
+ QuantLib.Instrument.Swap: [ffsSpread1] :: FloatFloatSwapOpts -> Double
+ QuantLib.Instrument.Swap: [ffsSpread2] :: FloatFloatSwapOpts -> Double
+ QuantLib.Instrument.Swap: [ffsvCappedRate1] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvCappedRate2] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvFinalCapitalExchange] :: FloatFloatSwapVaryingOpts -> Bool
+ QuantLib.Instrument.Swap: [ffsvFlooredRate1] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvFlooredRate2] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvGearing1] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvGearing2] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvIntermediateCapitalExchange] :: FloatFloatSwapVaryingOpts -> Bool
+ QuantLib.Instrument.Swap: [ffsvPaymentConvention1] :: FloatFloatSwapVaryingOpts -> Maybe BusinessDayConvention
+ QuantLib.Instrument.Swap: [ffsvPaymentConvention2] :: FloatFloatSwapVaryingOpts -> Maybe BusinessDayConvention
+ QuantLib.Instrument.Swap: [ffsvSpread1] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: [ffsvSpread2] :: FloatFloatSwapVaryingOpts -> [Double]
+ QuantLib.Instrument.Swap: calibrationBasket :: NonstandardSwaption -> GenSwapIndex sidx -> GenSwaptionVolatilityStructure sv -> CalibrationBasketType -> IO [BlackCalibrationHelper]
+ QuantLib.Instrument.Swap: constNotionalCrossCurrencyBasisSwap :: Double -> Currency -> Schedule -> GenIborIndex ibor1 -> Double -> Double -> Double -> Currency -> Schedule -> GenIborIndex ibor2 -> Double -> Double -> ConstNotionalCrossCurrencyBasisSwapOpts -> IO ConstNotionalCrossCurrencyBasisSwap
+ QuantLib.Instrument.Swap: constNotionalCrossCurrencyFixedVsFloatingSwap :: SwapType -> Double -> Currency -> Schedule -> Double -> DayCounter -> BusinessDayConvention -> Word -> Calendar -> Double -> Currency -> Schedule -> GenIborIndex ibor -> Double -> BusinessDayConvention -> Word -> Calendar -> Bool -> Bool -> Maybe Word -> Bool -> Word -> RateAveragingType -> IO ConstNotionalCrossCurrencyFixedVsFloatingSwap
+ QuantLib.Instrument.Swap: constNotionalCrossCurrencySwap :: GenLeg l1 -> Currency -> GenLeg l2 -> Currency -> IO ConstNotionalCrossCurrencySwap
+ QuantLib.Instrument.Swap: constNotionalCrossCurrencySwap' :: [(Leg, Bool)] -> [Currency] -> IO ConstNotionalCrossCurrencySwap
+ QuantLib.Instrument.Swap: data CalibrationBasketType
+ QuantLib.Instrument.Swap: data ConstNotionalCrossCurrencyBasisSwapOpts
+ QuantLib.Instrument.Swap: data FloatFloatSwapOpts
+ QuantLib.Instrument.Swap: data FloatFloatSwapVaryingOpts
+ QuantLib.Instrument.Swap: defaultConstNotionalCrossCurrencyBasisSwapOpts :: ConstNotionalCrossCurrencyBasisSwapOpts
+ QuantLib.Instrument.Swap: defaultFloatFloatSwapOpts :: FloatFloatSwapOpts
+ QuantLib.Instrument.Swap: defaultFloatFloatSwapVaryingOpts :: FloatFloatSwapVaryingOpts
+ QuantLib.Instrument.Swap: fairPaySpread :: ConstNotionalCrossCurrencyBasisSwap -> IO Double
+ QuantLib.Instrument.Swap: fairRecSpread :: ConstNotionalCrossCurrencyBasisSwap -> IO Double
+ QuantLib.Instrument.Swap: fairSpread1 :: FloatFloatSwap -> IO Double
+ QuantLib.Instrument.Swap: fairSpread2 :: FloatFloatSwap -> IO Double
+ QuantLib.Instrument.Swap: floatFloatSwap :: SwapType -> Double -> Double -> Schedule -> GenInterestRateIndex ridx1 -> DayCounter -> Schedule -> GenInterestRateIndex ridx2 -> DayCounter -> FloatFloatSwapOpts -> IO FloatFloatSwap
+ QuantLib.Instrument.Swap: floatFloatSwap' :: SwapType -> [Double] -> [Double] -> Schedule -> GenInterestRateIndex ridx1 -> DayCounter -> Schedule -> GenInterestRateIndex ridx2 -> DayCounter -> FloatFloatSwapVaryingOpts -> IO FloatFloatSwap
+ QuantLib.Instrument.Swap: floatFloatSwaption :: FloatFloatSwap -> Exercise -> SettlementType -> SettlementMethod -> IO FloatFloatSwaption
+ QuantLib.Instrument.Swap: floatFloatSwaptionCalibrationBasket :: FloatFloatSwaption -> GenSwapIndex sidx -> GenSwaptionVolatilityStructure sv -> CalibrationBasketType -> IO [BlackCalibrationHelper]
+ QuantLib.Instrument.Swap: inCcyLegBPS :: GenConstNotionalCrossCurrencySwap x -> Word -> IO Double
+ QuantLib.Instrument.Swap: inCcyLegNPV :: GenConstNotionalCrossCurrencySwap x -> Word -> IO Double
+ QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasFixedLeg (QuantLib.Internal.Type.GenFixedVsFloatingSwap f)
+ QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasFloatingLeg (QuantLib.Internal.Type.GenFixedVsFloatingSwap f)
+ QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasSpread (QuantLib.Internal.Type.GenFixedVsFloatingSwap f)
+ QuantLib.Instrument.Swap: instance QuantLib.Instrument.Swap.HasSpread QuantLib.Internal.Type.ConstNotionalCrossCurrencyFixedVsFloatingSwap
+ QuantLib.Instrument.Swap: legCurrency :: GenConstNotionalCrossCurrencySwap x -> Word -> IO Currency
+ QuantLib.Instrument.Swap: nonstandardSwap :: SwapType -> [Double] -> [Double] -> Schedule -> [Double] -> DayCounter -> Schedule -> GenIborIndex ibor -> Double -> Double -> DayCounter -> Bool -> Bool -> Maybe BusinessDayConvention -> IO NonstandardSwap
+ QuantLib.Instrument.Swap: nonstandardSwap' :: SwapType -> [Double] -> [Double] -> Schedule -> [Double] -> DayCounter -> Schedule -> GenIborIndex ibor -> [Double] -> [Double] -> DayCounter -> Bool -> Bool -> Maybe BusinessDayConvention -> IO NonstandardSwap
+ QuantLib.Instrument.Swap: nonstandardSwapFromVanilla :: GenFixedVsFloatingSwap f -> IO NonstandardSwap
+ QuantLib.Instrument.Swap: nonstandardSwaption :: NonstandardSwap -> Exercise -> SettlementType -> SettlementMethod -> IO NonstandardSwaption
+ QuantLib.Instrument.Swap: nonstandardSwaptionFromSwaption :: Swaption -> IO NonstandardSwaption
+ QuantLib.Instrument.Swap: npvDateDiscounts :: GenConstNotionalCrossCurrencySwap x -> Word -> IO Double
+ QuantLib.Instrument.Swap: type ConstNotionalCrossCurrencyBasisSwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencyBasisSwap
+ QuantLib.Instrument.Swap: type ConstNotionalCrossCurrencyFixedVsFloatingSwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencyFixedVsFloatingSwap
+ QuantLib.Instrument.Swap: type ConstNotionalCrossCurrencySwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencySwap
+ QuantLib.Instrument.Swap: type FixedVsFloatingSwap = GenFixedVsFloatingSwap CFixedVsFloatingSwap
+ QuantLib.Instrument.Swap: type FloatFloatSwap = GenSwap CFloatFloatSwap
+ QuantLib.Instrument.Swap: type FloatFloatSwaption = GenOption CFloatFloatSwaption
+ QuantLib.Instrument.Swap: type NonstandardSwap = GenSwap CNonstandardSwap
+ QuantLib.Instrument.Swap: type NonstandardSwaption = GenOption CNonstandardSwaption
+ QuantLib.Instrument.Swap: xccyFairRate :: ConstNotionalCrossCurrencyFixedVsFloatingSwap -> IO Double
+ QuantLib.Model: asBlackCalibrationHelper :: GenBlackCalibrationHelper bch -> IO BlackCalibrationHelper
+ QuantLib.Model: g2AsAffineModel :: G2 -> IO AffineModel
+ QuantLib.Model: gsrAsGaussian1dModel :: Gsr -> IO Gaussian1dModel
+ QuantLib.Model: hullWhiteAsAffineModel :: HullWhite -> IO AffineModel
+ QuantLib.Model: liborForwardModelAsAffineModel :: LiborForwardModel -> IO AffineModel
+ QuantLib.Model: markovFunctionalAsGaussian1dModel :: MarkovFunctional -> IO Gaussian1dModel
+ QuantLib.Model: markovFunctionalCaplet :: GenYieldTermStructure y -> Double -> [Day] -> [Double] -> OptionletVolatilityStructure -> [Day] -> GenIborIndex ibor -> Word -> IO MarkovFunctional
+ QuantLib.Model: oneFactorAffineModelAsAffineModel :: OneFactorAffineModel -> IO AffineModel
+ QuantLib.Model: swaptionHelperSwaption :: SwaptionHelper -> IO Swaption
+ QuantLib.Model: swaptionHelperUnderlying :: SwaptionHelper -> IO FixedVsFloatingSwap
+ QuantLib.Model: type AffineModel = Standalone CAffineModel'
+ QuantLib.Model: type Gaussian1dModel = Standalone CGaussian1dModel'
+ QuantLib.Model: type GenBlackCalibrationHelper bch = GenCalibrationHelper AnyOf CBlackCalibrationHelper' bch
+ QuantLib.Model: type SwaptionHelper = GenBlackCalibrationHelper CSwaptionHelper
+ QuantLib.Model: volatility :: GenBlackCalibrationHelper bch -> IO Quote
+ QuantLib.PricingEngine: analyticHestonForwardEuropeanEngine :: GenHestonProcess hp -> Word -> IO PricingEngine
+ QuantLib.PricingEngine: analyticSimpleChooserEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: analyticSoftBarrierEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: analyticTwoAssetCorrelationEngine :: GeneralizedBlackScholesProcess -> GeneralizedBlackScholesProcess -> GenQuote q -> IO PricingEngine
+ QuantLib.PricingEngine: analyticWriterExtensibleOptionEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: discountingConstNotionalCrossCurrencySwapEngine :: Currency -> GenYieldTermStructure y1 -> Currency -> GenYieldTermStructure y2 -> GenQuote q -> Maybe Bool -> Maybe Day -> Maybe Day -> Maybe Day -> IO PricingEngine
+ QuantLib.PricingEngine: fdBlackScholesAsianEngine :: GeneralizedBlackScholesProcess -> Word -> Word -> Word -> FdmScheme -> IO PricingEngine
+ QuantLib.PricingEngine: forwardBaroneAdesiWhaleyEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: forwardBjerksundStenslandEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: forwardEuropeanEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: forwardFdBlackScholesVanillaEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: gaussian1dCapFloorEngine :: Gaussian1dModel -> Int -> Double -> Bool -> Bool -> Maybe (GenYieldTermStructure y) -> IO PricingEngine
+ QuantLib.PricingEngine: gaussian1dFloatFloatSwaptionEngine :: Gaussian1dModel -> Int -> Double -> Bool -> Bool -> Maybe (GenQuote q) -> Maybe (GenYieldTermStructure y) -> Bool -> Probabilities -> IO PricingEngine
+ QuantLib.PricingEngine: gaussian1dJamshidianSwaptionEngine :: Gaussian1dModel -> IO PricingEngine
+ QuantLib.PricingEngine: gaussian1dNonstandardSwaptionEngine :: Gaussian1dModel -> Int -> Double -> Bool -> Bool -> Maybe (GenQuote q) -> Maybe (GenYieldTermStructure y) -> Probabilities -> IO PricingEngine
+ QuantLib.PricingEngine: interpolatingCPICapFloorEngine :: CPICapFloorTermPriceSurface -> IO PricingEngine
+ QuantLib.PricingEngine: mcForwardEuropeanBSEngine :: RngTrait -> GeneralizedBlackScholesProcess -> Maybe Word -> Maybe Word -> Bool -> Bool -> Maybe Word -> Maybe Double -> Maybe Word -> Word -> IO PricingEngine
+ QuantLib.PricingEngine: turnbullWakemanAsianEngine :: GeneralizedBlackScholesProcess -> IO PricingEngine
+ QuantLib.PricingEngine: yoyInflationBachelierCapFloorEngine :: GenYoYInflationIndex yidx -> YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO PricingEngine
+ QuantLib.PricingEngine: yoyInflationBlackCapFloorEngine :: GenYoYInflationIndex yidx -> YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO PricingEngine
+ QuantLib.PricingEngine: yoyInflationUnitDisplacedBlackCapFloorEngine :: GenYoYInflationIndex yidx -> YoYOptionletVolatilitySurface -> GenYieldTermStructure y -> IO PricingEngine
+ QuantLib.TermStructure.Commodity: commodityCurve :: String -> CommodityType -> Currency -> UnitOfMeasure -> Calendar -> [Day] -> [Double] -> DayCounter -> IO CommodityCurve
+ QuantLib.TermStructure.Commodity: commodityCurveBasisOfCurve :: CommodityCurve -> IO (Maybe CommodityCurve)
+ QuantLib.TermStructure.Commodity: commodityCurveBasisOfPrice :: CommodityCurve -> Day -> IO Double
+ QuantLib.TermStructure.Commodity: commodityCurveCommodityType :: CommodityCurve -> IO CommodityType
+ QuantLib.TermStructure.Commodity: commodityCurveCurrency :: CommodityCurve -> IO Currency
+ QuantLib.TermStructure.Commodity: commodityCurveDates :: CommodityCurve -> IO [Day]
+ QuantLib.TermStructure.Commodity: commodityCurveEmpty :: CommodityCurve -> Bool
+ QuantLib.TermStructure.Commodity: commodityCurveName :: CommodityCurve -> IO String
+ QuantLib.TermStructure.Commodity: commodityCurvePrice :: CommodityCurve -> Day -> IO Double
+ QuantLib.TermStructure.Commodity: commodityCurvePriceNearby :: CommodityCurve -> Day -> ExchangeContracts -> Int -> IO Double
+ QuantLib.TermStructure.Commodity: commodityCurvePrices :: CommodityCurve -> IO [Double]
+ QuantLib.TermStructure.Commodity: commodityCurveUnderlyingPriceDate :: CommodityCurve -> Day -> ExchangeContracts -> Int -> IO Day
+ QuantLib.TermStructure.Commodity: commodityCurveUnitOfMeasure :: CommodityCurve -> IO UnitOfMeasure
+ QuantLib.TermStructure.Commodity: setCommodityCurveBasisOfCurve :: CommodityCurve -> CommodityCurve -> IO ()
+ QuantLib.TermStructure.Commodity: type CommodityCurve = GenTermStructure CCommodityCurve
+ QuantLib.TermStructure.Commodity: type ExchangeContract = (String, Day, Day, Day)
+ QuantLib.TermStructure.Commodity: type ExchangeContracts = [(Day, ExchangeContract)]
+ QuantLib.TermStructure.Inflation: interpolatedYoYInflationCurve :: Day -> [(Day, Double)] -> Frequency -> DayCounter -> Interpolation -> IO YoYInflationTermStructure
+ QuantLib.TermStructure.InflationVolatility: constantCPIVolatility :: GenQuote q -> Word -> Calendar -> BusinessDayConvention -> DayCounter -> (Word, TimeUnit) -> Frequency -> Bool -> IO CPIVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: constantYoYOptionletVolatility :: GenQuote q -> Word -> Calendar -> BusinessDayConvention -> DayCounter -> (Word, TimeUnit) -> Frequency -> Bool -> Double -> Double -> VolatilityType -> Double -> IO YoYOptionletVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: cpiCapFloorTermPriceSurface :: Double -> Double -> (Word, TimeUnit) -> Calendar -> BusinessDayConvention -> DayCounter -> ZeroInflationIndex -> CPIInterpolationType -> GenYieldTermStructure y -> [Double] -> [Double] -> [(Word, TimeUnit)] -> Matrix Double -> Matrix Double -> Interpolation2D -> IO CPICapFloorTermPriceSurface
+ QuantLib.TermStructure.InflationVolatility: cpiTotalVariance :: CPIVolatilitySurface -> Day -> Double -> Maybe (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.InflationVolatility: cpiVolatility :: CPIVolatilitySurface -> Day -> Double -> Maybe (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.InflationVolatility: kInterpolatedYoYOptionletVolatilitySurfaceBachelier :: Word -> Calendar -> BusinessDayConvention -> DayCounter -> YoYCapFloorTermPriceSurface -> YoYInflationIndex -> GenYieldTermStructure y -> Double -> Interpolation -> IO YoYOptionletVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: kInterpolatedYoYOptionletVolatilitySurfaceBlack :: Word -> Calendar -> BusinessDayConvention -> DayCounter -> YoYCapFloorTermPriceSurface -> YoYInflationIndex -> GenYieldTermStructure y -> Double -> Interpolation -> IO YoYOptionletVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack :: Word -> Calendar -> BusinessDayConvention -> DayCounter -> YoYCapFloorTermPriceSurface -> YoYInflationIndex -> GenYieldTermStructure y -> Double -> Interpolation -> IO YoYOptionletVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: type CPICapFloorTermPriceSurface = GenTermStructure CCPICapFloorTermPriceSurface
+ QuantLib.TermStructure.InflationVolatility: type CPIVolatilitySurface = GenVolatilityTermStructure CCPIVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: type YoYCapFloorTermPriceSurface = GenTermStructure CYoYCapFloorTermPriceSurface
+ QuantLib.TermStructure.InflationVolatility: type YoYOptionletVolatilitySurface = GenVolatilityTermStructure CYoYOptionletVolatilitySurface
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorAtmYoYRate :: YoYCapFloorTermPriceSurface -> Day -> Maybe (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorAtmYoYSwapDateRates :: YoYCapFloorTermPriceSurface -> IO [(Day, Double)]
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorAtmYoYSwapRate :: YoYCapFloorTermPriceSurface -> Day -> Bool -> IO Double
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorBaseDate :: YoYCapFloorTermPriceSurface -> IO Day
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorStrikes :: YoYCapFloorTermPriceSurface -> IO [Double]
+ QuantLib.TermStructure.InflationVolatility: yoyCapFloorTermPriceSurface :: Word -> (Word, TimeUnit) -> YoYInflationIndex -> CPIInterpolationType -> GenYieldTermStructure y -> DayCounter -> Calendar -> BusinessDayConvention -> [Double] -> [Double] -> [(Word, TimeUnit)] -> Matrix Double -> Matrix Double -> Interpolation2D -> Interpolation -> IO YoYCapFloorTermPriceSurface
+ QuantLib.TermStructure.InflationVolatility: yoyOptionletTotalVariance :: YoYOptionletVolatilitySurface -> Day -> Double -> Maybe (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.InflationVolatility: yoyOptionletVolatility :: YoYOptionletVolatilitySurface -> Day -> Double -> Maybe (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurve :: Word -> Calendar -> [(Word, TimeUnit)] -> [GenQuote q] -> [Bool] -> BusinessDayConvention -> DayCounter -> IO AbcdAtmVolCurve
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveA :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveB :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveC :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveD :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveEndCriteria :: AbcdAtmVolCurve -> IO EndCriteriaType
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveK :: AbcdAtmVolCurve -> IO [Double]
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveKAtTime :: AbcdAtmVolCurve -> Double -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveMaxError :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveOptionDates :: AbcdAtmVolCurve -> IO [Day]
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveOptionTenors :: AbcdAtmVolCurve -> IO [(Word, TimeUnit)]
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveOptionTenorsInInterpolation :: AbcdAtmVolCurve -> IO [(Word, TimeUnit)]
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveOptionTimes :: AbcdAtmVolCurve -> IO [Double]
+ QuantLib.TermStructure.Volatility: abcdAtmVolCurveRmsError :: AbcdAtmVolCurve -> IO Double
+ QuantLib.TermStructure.Volatility: atmVarianceForDate :: GenBlackAtmVolCurve b -> Day -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: atmVarianceForPeriod :: GenBlackAtmVolCurve b -> (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: atmVarianceForTime :: GenBlackAtmVolCurve b -> Double -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: atmVolForDate :: GenBlackAtmVolCurve b -> Day -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: atmVolForPeriod :: GenBlackAtmVolCurve b -> (Word, TimeUnit) -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: atmVolForTime :: GenBlackAtmVolCurve b -> Double -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: blackVolSurfaceSmileSectionForDate :: GenBlackVolSurface b -> Day -> Bool -> IO SmileSection
+ QuantLib.TermStructure.Volatility: blackVolSurfaceSmileSectionForPeriod :: GenBlackVolSurface b -> (Word, TimeUnit) -> Bool -> IO SmileSection
+ QuantLib.TermStructure.Volatility: blackVolSurfaceSmileSectionForTime :: GenBlackVolSurface b -> Double -> Bool -> IO SmileSection
+ QuantLib.TermStructure.Volatility: capFloorTermVolCurveOptionDates :: CapFloorTermVolCurve -> IO [Day]
+ QuantLib.TermStructure.Volatility: capFloorTermVolCurveOptionTimes :: CapFloorTermVolCurve -> IO [Double]
+ QuantLib.TermStructure.Volatility: capFloorTermVolSurfaceOptionDates :: CapFloorTermVolSurface -> IO [Day]
+ QuantLib.TermStructure.Volatility: capFloorTermVolSurfaceOptionTimes :: CapFloorTermVolSurface -> IO [Double]
+ QuantLib.TermStructure.Volatility: capFloorVolatilityForDate :: GenCapFloorTermVolatilityStructure c -> Day -> Double -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: capFloorVolatilityForPeriod :: GenCapFloorTermVolatilityStructure c -> (Word, TimeUnit) -> Double -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: capFloorVolatilityForTime :: GenCapFloorTermVolatilityStructure c -> Double -> Double -> Bool -> IO Double
+ QuantLib.TermStructure.Volatility: data OptionletStripper2
+ QuantLib.TermStructure.Volatility: optionletStripper2 :: CapFloorTermVolSurface -> GenIborIndex ibor -> Maybe Double -> Double -> Word -> Maybe (GenYieldTermStructure y) -> VolatilityType -> Double -> Bool -> Maybe (Word, TimeUnit) -> CapFloorTermVolCurve -> IO OptionletStripper2
+ QuantLib.TermStructure.Volatility: optionletStripper2AsOptionletVolatilityStructure :: OptionletStripper2 -> IO OptionletVolatilityStructure
+ QuantLib.TermStructure.Volatility: optionletStripper2AtmCapFloorPrices :: OptionletStripper2 -> IO [Double]
+ QuantLib.TermStructure.Volatility: optionletStripper2AtmCapFloorStrikes :: OptionletStripper2 -> IO [Double]
+ QuantLib.TermStructure.Volatility: optionletStripper2SpreadsVol :: OptionletStripper2 -> IO [Double]
+ QuantLib.TermStructure.Volatility: sabrVolSurface :: GenInterestRateIndex ix -> GenBlackAtmVolCurve b -> [(Word, TimeUnit)] -> [Double] -> Matrix (GenQuote q) -> IO SabrVolSurface
+ QuantLib.TermStructure.Volatility: sabrVolSurfaceAtmCurve :: SabrVolSurface -> IO BlackAtmVolCurve
+ QuantLib.TermStructure.Volatility: sabrVolSurfaceIndex :: SabrVolSurface -> IO InterestRateIndex
+ QuantLib.TermStructure.Volatility: sabrVolSurfaceOptionDateFromTenor :: SabrVolSurface -> (Word, TimeUnit) -> IO Day
+ QuantLib.TermStructure.Volatility: sabrVolSurfaceVolatilitySpreadsForDate :: SabrVolSurface -> Day -> IO [Double]
+ QuantLib.TermStructure.Volatility: sabrVolSurfaceVolatilitySpreadsForPeriod :: SabrVolSurface -> (Word, TimeUnit) -> IO [Double]
+ QuantLib.TermStructure.Volatility: type AbcdAtmVolCurve = GenBlackAtmVolCurve CAbcdAtmVolCurve
+ QuantLib.TermStructure.Volatility: type BlackAtmVolCurve = GenBlackAtmVolCurve CBlackAtmVolCurve
+ QuantLib.TermStructure.Volatility: type BlackVolSurface = GenBlackVolSurface CBlackVolSurface
+ QuantLib.TermStructure.Volatility: type CapFloorTermVolCurve = GenCapFloorTermVolatilityStructure CCapFloorTermVolCurve
+ QuantLib.TermStructure.Volatility: type CapFloorTermVolatilityStructure = GenCapFloorTermVolatilityStructure CCapFloorTermVolatilityStructure
+ QuantLib.TermStructure.Volatility: type GenBlackAtmVolCurve b = GenVolatilityTermStructure AnyOf CBlackAtmVolCurve' b
+ QuantLib.TermStructure.Volatility: type GenBlackVolSurface b = GenBlackAtmVolCurve AnyOf CBlackVolSurface' b
+ QuantLib.TermStructure.Volatility: type GenCapFloorTermVolatilityStructure c = GenVolatilityTermStructure AnyOf CCapFloorTermVolatilityStructure' c
+ QuantLib.TermStructure.Volatility: type SabrVolSurface = GenBlackVolSurface CSabrVolSurface
- QuantLib.CashFlow: yoyInflationLeg :: Schedule -> Calendar -> YoYInflationIndex -> (Word, TimeUnit) -> CPIInterpolationType -> [Double] -> DayCounter -> BusinessDayConvention -> [Word] -> [Double] -> [Double] -> IO Leg
+ QuantLib.CashFlow: yoyInflationLeg :: Schedule -> Calendar -> YoYInflationIndex -> (Word, TimeUnit) -> CPIInterpolationType -> [Double] -> DayCounter -> BusinessDayConvention -> [Word] -> [Double] -> [Double] -> [Double] -> [Double] -> IO Leg
- QuantLib.Instrument.Bond: maturityDate :: GenBond b -> Maybe Day
+ QuantLib.Instrument.Bond: maturityDate :: GenBond b -> IO (Maybe Day)
- QuantLib.Instrument.Swap: swaption :: VanillaSwap -> Exercise -> SettlementType -> SettlementMethod -> IO Swaption
+ QuantLib.Instrument.Swap: swaption :: GenFixedVsFloatingSwap f -> Exercise -> SettlementType -> SettlementMethod -> IO Swaption
- QuantLib.Instrument.Swap: type VanillaSwap = GenSwap CVanillaSwap
+ QuantLib.Instrument.Swap: type VanillaSwap = GenFixedVsFloatingSwap CVanillaSwap
- QuantLib.Model: blackPrice :: BlackCalibrationHelper -> Double -> IO Double
+ QuantLib.Model: blackPrice :: GenBlackCalibrationHelper bch -> Double -> IO Double
- QuantLib.Model: calibrateVolatilitiesIterative :: Gsr -> [BlackCalibrationHelper] -> OptimizationMethod -> EndCriteria -> Maybe Constraint -> [Double] -> IO ()
+ QuantLib.Model: calibrateVolatilitiesIterative :: Gsr -> [GenBlackCalibrationHelper bch] -> OptimizationMethod -> EndCriteria -> Maybe Constraint -> [Double] -> IO ()
- QuantLib.Model: calibrationError :: BlackCalibrationHelper -> IO Double
+ QuantLib.Model: calibrationError :: GenBlackCalibrationHelper bch -> IO Double
- QuantLib.Model: convexityBias :: Double -> Double -> Double -> Double -> Double -> Double
+ QuantLib.Model: convexityBias :: Double -> Double -> Double -> Double -> Double -> IO Double
- QuantLib.Model: impliedVolatility :: BlackCalibrationHelper -> Double -> Double -> Word -> Double -> Double -> IO Double
+ QuantLib.Model: impliedVolatility :: GenBlackCalibrationHelper bch -> Double -> Double -> Word -> Double -> Double -> IO Double
- QuantLib.Model: marketValue :: BlackCalibrationHelper -> IO Double
+ QuantLib.Model: marketValue :: GenBlackCalibrationHelper bch -> IO Double
- QuantLib.Model: modelValue :: BlackCalibrationHelper -> IO Double
+ QuantLib.Model: modelValue :: GenBlackCalibrationHelper bch -> IO Double
- QuantLib.Model: setPricingEngine :: BlackCalibrationHelper -> PricingEngine -> IO ()
+ QuantLib.Model: setPricingEngine :: GenBlackCalibrationHelper bch -> PricingEngine -> IO ()
- QuantLib.Model: swaptionHelper :: (Word, TimeUnit) -> (Word, TimeUnit) -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO BlackCalibrationHelper
+ QuantLib.Model: swaptionHelper :: (Word, TimeUnit) -> (Word, TimeUnit) -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO SwaptionHelper
- QuantLib.Model: swaptionHelperFromDate :: Day -> (Word, TimeUnit) -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO BlackCalibrationHelper
+ QuantLib.Model: swaptionHelperFromDate :: Day -> (Word, TimeUnit) -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO SwaptionHelper
- QuantLib.Model: swaptionHelperFromDates :: Day -> Day -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO BlackCalibrationHelper
+ QuantLib.Model: swaptionHelperFromDates :: Day -> Day -> GenQuote q -> GenIborIndex ibor -> (Word, TimeUnit) -> DayCounter -> DayCounter -> GenYieldTermStructure y -> CalibrationErrorType -> Maybe Double -> Double -> VolatilityType -> Double -> Maybe Word -> RateAveragingType -> IO SwaptionHelper
- QuantLib.Model: times :: BlackCalibrationHelper -> IO [Double]
+ QuantLib.Model: times :: GenBlackCalibrationHelper bch -> IO [Double]
- QuantLib.Model: type BlackCalibrationHelper = GenCalibrationHelper CBlackCalibrationHelper
+ QuantLib.Model: type BlackCalibrationHelper = GenBlackCalibrationHelper CBlackCalibrationHelper
- QuantLib.TermStructure.Volatility: capFloorTermVolCurve :: Word -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO VolatilityTermStructure
+ QuantLib.TermStructure.Volatility: capFloorTermVolCurve :: Word -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO CapFloorTermVolCurve
- QuantLib.TermStructure.Volatility: capFloorTermVolCurve' :: Day -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO VolatilityTermStructure
+ QuantLib.TermStructure.Volatility: capFloorTermVolCurve' :: Day -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO CapFloorTermVolCurve
- QuantLib.TermStructure.Volatility: constantCapFloorTermVolatility :: Word -> Calendar -> BusinessDayConvention -> GenQuote q -> DayCounter -> IO VolatilityTermStructure
+ QuantLib.TermStructure.Volatility: constantCapFloorTermVolatility :: Word -> Calendar -> BusinessDayConvention -> GenQuote q -> DayCounter -> IO CapFloorTermVolatilityStructure
- QuantLib.TermStructure.Volatility: constantCapFloorTermVolatility' :: Day -> Calendar -> BusinessDayConvention -> GenQuote q -> DayCounter -> IO VolatilityTermStructure
+ QuantLib.TermStructure.Volatility: constantCapFloorTermVolatility' :: Day -> Calendar -> BusinessDayConvention -> GenQuote q -> DayCounter -> IO CapFloorTermVolatilityStructure
- QuantLib.TermStructure.Volatility: type CapFloorTermVolSurface = GenVolatilityTermStructure CCapFloorTermVolSurface
+ QuantLib.TermStructure.Volatility: type CapFloorTermVolSurface = GenCapFloorTermVolatilityStructure CCapFloorTermVolSurface
- QuantLib.TermStructure.Yield: piecewiseZeroSpreadedTermStructure :: GenYieldTermStructure y -> [(Day, GenQuote q)] -> Compounding -> Frequency -> IO YieldTermStructure
+ QuantLib.TermStructure.Yield: piecewiseZeroSpreadedTermStructure :: GenYieldTermStructure y -> [(Day, GenQuote q)] -> Compounding -> Frequency -> Interpolation -> IO YieldTermStructure
- QuantLib.Time.Schedule: fromDates :: [Day] -> Calendar -> BusinessDayConvention -> IO Schedule
+ QuantLib.Time.Schedule: fromDates :: [Day] -> Calendar -> BusinessDayConvention -> Maybe BusinessDayConvention -> Maybe (Word, TimeUnit) -> Maybe DateGenerationRule -> Maybe Bool -> IO Schedule

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.6.0.0 (2026)++Rethought multiple inheritance for secondary interfaces (`AffineModel`, `Gaussian1dModel`): instead of a second `Upcastable` node, each leaf now gets a standalone, eagerly-materialized upcast (e.g. `hullWhiteAsAffineModel`). This traded a pure wrap at the call site for an explicit `IO`-sequenced conversion, so a few call sites that used to be pure functions are now `IO` actions — a small, deliberate cost for one fewer hand-rolled sum type per interface. Also generalized several accessor return types one `AnyOf` layer deeper (`SwaptionHelper`, `FixedVsFloatingSwap`) to keep them cast-free, and added a further batch of bindings: Gaussian1d model instruments/engines, YoY/CPI inflation vol surfaces and cap/floors, commodities, cross-currency swaps, and BlackAtmVolCurve/SabrVolSurface/OptionletStripper2.+ ## 0.5.0.2 (2026)  Support for RelinkableHandle has finally landed. As it turned out the current model is a perfect fit for it: term structures, quotes, and vol surfaces now relink uniformly, so building on top of a live quote or curve propagates updates correctly. Also removed all remaining `dynamic_cast` usage from the C++ shim in favor of dedicated typed bindings, and added a batch of further instrument/engine bindings (SABR vol cubes, Heston FD engines, CDS/counterparty engines, amortizing bonds, exchange rates, CMS legs, and more).
QuantLib/CashFlow.chs view
@@ -76,6 +76,11 @@   , rangeAccrualLeg   , cpiLeg   , yoyInflationLeg+  , YoYInflationCouponPricer+  , blackYoYInflationCouponPricer+  , unitDisplacedBlackYoYInflationCouponPricer+  , bachelierYoYInflationCouponPricer+  , setYoYInflationCouponPricer   , ZeroInflationCashFlow   , zeroInflationCashFlow   , zeroInflationCashFlowAmount@@ -111,10 +116,9 @@ import QuantLib.Internal {#import QuantLib.InterestRate#}(Compounding) {#import QuantLib.Time.Schedule#}(Frequency)-{#import QuantLib.Time.Calendar#}(BusinessDayConvention(..)) import QuantLib.Time.Calendar(calendar, CalendarConstructor(..)) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Syntax(deriveOptionsRecord) import Data.Maybe(fromMaybe) @@ -124,6 +128,7 @@  #include "ql.h" +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *Leg foreign -> CLeg' nocode#} {#pointer *CouponLeg foreign -> CCouponLeg' nocode#} {#pointer *QlQuote as Quote foreign -> CQuote' nocode#}@@ -477,14 +482,14 @@ -- |Build a leg of average-BMA coupons. {#fun qlAverageBMALeg as averageBMALeg{withSchedule*`Schedule',withBMAIndex*`BMAIndex'   ,withDoubleArray*`[Double]'& -- ^notionals-  ,withDayCounter*`DayCounter',`BusinessDayConvention',withDoubleArray*`[Double]'& -- ^gearings+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention',withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Build a leg of fixed-rate coupons. {#fun qlFixedRateLeg as fixedRateLeg{withSchedule*`Schedule',withDoubleArray*`[Double]'& -- ^notionals   ,withInterestRateArray*`[InterestRate]'& -- ^couponRates-  ,`BusinessDayConvention' -- ^paymentAdjustment+  ,fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withDayCounter*`DayCounter' -- ^firstPeriodDayCounter   ,withCalendar*`Calendar' -- ^paymentCalendar   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}@@ -516,7 +521,7 @@  -- |Raw binding for 'iborLeg'\/'iborLegFull': builds a leg of capped\/floored Ibor-rate coupons. {#fun qlIborLeg as iborLeg_{withSchedule*`Schedule',withIborIndex*`GenIborIndex ibor',withDoubleArray*`[Double]'& -- ^notionals-  ,withDayCounter*`DayCounter',`BusinessDayConvention' -- ^paymentAdjustment+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withIntArray*`[Word]'&  -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -528,9 +533,9 @@   ,withCalendar*`Calendar' -- ^paymentCalendar   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth-  ,`BusinessDayConvention' -- ^fixingConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixingConvention   ,fromMaybeBool`Maybe Bool' -- ^useIndexedCoupons   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#} @@ -557,7 +562,7 @@  -- |Raw binding for 'cmsLeg'\/'cmsLegFull': builds a leg of capped\/floored CMS-rate coupons. {#fun qlCmsLeg as cmsLeg_{withSchedule*`Schedule',withSwapIndex*`GenSwapIndex sidx',withDoubleArray*`[Double]'& -- ^notionals-  ,withDayCounter*`DayCounter',`BusinessDayConvention' -- ^paymentAdjustment+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withIntArray*`[Word]'&  -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -567,53 +572,62 @@   ,`Bool' -- ^zeroPayments   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth-  ,`BusinessDayConvention' -- ^fixingConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixingConvention   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Build a leg of overnight-index coupons. {#fun qlOvernightLeg as overnightLeg{withSchedule*`Schedule',withOvernightIborIndex*`OvernightIborIndex',withDoubleArray*`[Double]'& -- ^notionals'-  ,withDayCounter*`DayCounter',`BusinessDayConvention',withDoubleArray*`[Double]'& -- ^gearings+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention',withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Build a leg of range-accrual floating-rate coupons. {#fun qlRangeAccrualLeg as rangeAccrualLeg{withSchedule*`Schedule',withIborIndex*`GenIborIndex ibor',withDoubleArray*`[Double]'& -- ^notionals-  ,withDayCounter*`DayCounter',`BusinessDayConvention',withIntArray*`[Word]'& -- ^fixingDays+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention',withIntArray*`[Word]'& -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads   ,withDoubleArray*`[Double]'& -- ^lowerTriggers   ,withDoubleArray*`[Double]'& -- ^upperTriggers   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^observationTenor-  ,`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}+  ,fromEnumC`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Fixed-rate coupons scaled by the ratio of a 'ZeroInflationIndex' fixing to /baseCPI/--- (a 'CPICoupon' leg -- caps/floors are not exposed, see README.md's TODO).+-- (a 'CPICoupon' leg -- no capped\/floored variant, unlike 'yoyInflationLeg': QL 1.43 has no+-- @CappedFlooredCPICoupon@ class to build one from, see README.md's TODO). {#fun qlCPILeg as cpiLeg{withSchedule*`Schedule',withZeroInflationIndex*`ZeroInflationIndex'   ,`Double' -- ^baseCPI   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag   ,withDoubleArray*`[Double]'& -- ^notionals   ,withDoubleArray*`[Double]'& -- ^fixedRates   ,withDayCounter*`DayCounter' -- ^paymentDayCounter-  ,`BusinessDayConvention' -- ^paymentAdjustment+  ,fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withCalendar*`Calendar' -- ^paymentCalendar   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation   ,`Bool' -- ^subtractInflationNominal   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#} --- |Year-on-year inflation-linked coupons (a 'YoYInflationCoupon' leg -- caps/floors are not--- exposed, see README.md's TODO).+-- |Year-on-year inflation-linked coupons (a 'YoYInflationCoupon' leg). Non-empty /caps/\//floors/+-- build 'CappedFlooredYoYInflationCoupon's instead of plain ones -- but /any/ resulting coupon+-- (capped or not) still needs a pricer set via 'setYoYInflationCouponPricer' before its+-- 'QuantLib.CashFlow.npv'\/'amount' can be computed: upstream's @InflationCoupon::rate()@+-- requires @pricer_@ unconditionally, not just for the capped\/floored case (confirmed by reading+-- @inflationcoupon.cpp@). CPI-leg ('cpiLeg') caps\/floors have no equivalent in QL 1.43 (no+-- @CappedFlooredCPICoupon@ class exists upstream, see README.md's TODO) -- this is a+-- QuantLib-version limitation, not an unbound feature. {#fun qlYoYInflationLeg as yoyInflationLeg{withSchedule*`Schedule',withCalendar*`Calendar'   ,withYoYInflationIndex*`YoYInflationIndex'   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag   ,fromEnumC`CPIInterpolationType' -- ^interpolation   ,withDoubleArray*`[Double]'& -- ^notionals   ,withDayCounter*`DayCounter' -- ^paymentDayCounter-  ,`BusinessDayConvention' -- ^paymentAdjustment+  ,fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withIntArray*`[Word]'& -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads+  ,withDoubleArray*`[Double]'& -- ^caps+  ,withDoubleArray*`[Double]'& -- ^floors   ,preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#} {#pointer *QlZeroInflationCashFlow as ZeroInflationCashFlow foreign -> CZeroInflationCashFlow nocode#} {#pointer *QlCPICashFlow as CPICashFlow foreign -> CCPICashFlow nocode#}@@ -710,6 +724,8 @@  {#pointer *QlFloatingRateCouponPricer as FloatingRateCouponPricer foreign -> CFloatingRateCouponPricer nocode#} {#pointer *QlSmileSection as SmileSection foreign -> CSmileSection nocode#}+{#pointer *QlYoYOptionletVolatilitySurface as YoYOptionletVolatilitySurface foreign -> CYoYOptionletVolatilitySurface' nocode#}+{#pointer *QlYoYInflationCouponPricer as YoYInflationCouponPricer foreign -> CYoYInflationCouponPricer nocode#}  -- |Black-formula pricer for capped/floored Ibor coupons {#fun qlBlackIborCouponPricer as blackIborCouponPricer{withOptionletVolatilityStructure*`GenOptionletVolatilityStructure ov'@@ -726,6 +742,28 @@   ,`Bool' -- ^byCallSpread   ,preErrorCheck-`String'errorCheck*-}->`FloatingRateCouponPricer'peekFloatingRateCouponPricer*#} +-- |Black-formula pricer for capped\/floored 'yoyInflationLeg' coupons.+{#fun qlBlackYoYInflationCouponPricer as blackYoYInflationCouponPricer{withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface'+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCouponPricer'peekYoYInflationCouponPricer*#}++-- |Unit-Displaced-Black-formula pricer for capped\/floored 'yoyInflationLeg' coupons.+{#fun qlUnitDisplacedBlackYoYInflationCouponPricer as unitDisplacedBlackYoYInflationCouponPricer{withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface'+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCouponPricer'peekYoYInflationCouponPricer*#}++-- |Bachelier-formula pricer for capped\/floored 'yoyInflationLeg' coupons.+{#fun qlBachelierYoYInflationCouponPricer as bachelierYoYInflationCouponPricer{withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface'+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCouponPricer'peekYoYInflationCouponPricer*#}++-- |Set the pricer of every 'QuantLib.Instrument.InflationCapFloor.YoYInflationCapFloor'-ready+-- 'YoYInflationCoupon'\/'CappedFlooredYoYInflationCoupon' in /leg/. Required before pricing (via+-- 'QuantLib.CashFlow.npv' or an 'QuantLib.Instrument.setPricingEngine'd instrument built on the+-- leg) any 'yoyInflationLeg' built with non-empty caps\/floors -- 'yoyInflationLeg' auto-attaches+-- a default (non-vol) pricer only when caps and floors are both empty.+{#fun qlSetYoYInflationCouponPricer as setYoYInflationCouponPricer{withLeg*`GenLeg l',withYoYInflationCouponPricer*`YoYInflationCouponPricer',preErrorCheck-`String'errorCheck*-}->`()'#}+ -- |Set the pricer of every floating-rate coupon in /leg/. {#fun qlQuantLibSetCouponPricer as setCouponPricer{withLeg*`GenLeg l',withFloatingRateCouponPricer*`FloatingRateCouponPricer',preErrorCheck-`String'errorCheck*-}->`()'#} @@ -782,17 +820,19 @@     (maybe False (const True) bounds) lowerBound upperBound   where     (strategyTag, param) = case strat of-      LinearTsrRateBound        -> (0 :: Int, 0)-      LinearTsrVegaRatio p      -> (1, p)-      LinearTsrPriceThreshold p -> (2, p)-      LinearTsrBSStdDevs p      -> (3, p)+      LinearTsrRateBound        -> (fromEnum LinearTsrPricerRateBound, 0)+      LinearTsrVegaRatio p      -> (fromEnum LinearTsrPricerVegaRatio, p)+      LinearTsrPriceThreshold p -> (fromEnum LinearTsrPricerPriceThreshold, p)+      LinearTsrBSStdDevs p      -> (fromEnum LinearTsrPricerBSStdDevs, p)     (lowerBound, upperBound) = fromMaybe (0, 0) bounds +{#enum LinearTsrPricerStrategyType as LinearTsrPricerStrategyTag {} deriving (Show, Eq)#}+ -- |Raw binding for 'linearTsrPricer', taking the 'LinearTsrPricerSettings' unpacked into a -- strategy tag\/parameter and an explicit-bounds flag. {#fun qlLinearTsrPricer as linearTsrPricer_{withSwaptionVolatilityStructure*`GenSwaptionVolatilityStructure sv',withQuote*`GenQuote q' -- ^meanReversion   ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^couponDiscountCurve-  ,fromIntegral`Int' -- ^strategy tag: 0=RateBound, 1=VegaRatio, 2=PriceThreshold, 3=BSStdDevs+  ,fromIntegral`Int' -- ^strategy tag, see 'LinearTsrPricerStrategyTag'   ,`Double' -- ^strategy-specific parameter (unused for RateBound)   ,`Bool' -- ^haveBounds   ,`Double' -- ^lowerBound (ignored unless haveBounds)
+ QuantLib/Commodity.chs view
@@ -0,0 +1,344 @@+module QuantLib.Commodity+  (+    CommodityType+  , commodityType+  , nullCommodityType+  , commodityTypeCode+  , commodityTypeName+  , commodityTypeEmpty++  , UnitOfMeasure+  , UnitOfMeasureType(..)+  , unitOfMeasure+  , unitOfMeasureName+  , unitOfMeasureCode+  , unitOfMeasureType+  , unitOfMeasureEmpty+  , lotUnitOfMeasure+  , barrelUnitOfMeasure+  , mtUnitOfMeasure+  , mbUnitOfMeasure+  , gallonUnitOfMeasure+  , litreUnitOfMeasure+  , kilolitreUnitOfMeasure+  , tokyoKilolitreUnitOfMeasure++  , PaymentTerm+  , PaymentTermEventType(..)+  , paymentTerm+  , paymentTermName+  , paymentTermEventType+  , paymentTermOffsetDays+  , paymentTermCalendar+  , paymentTermEmpty+  , paymentTermGetPaymentDate++  , Quantity+  , roundedQuantity+  , closeQuantity+  , closeEnoughQuantity++  , CommodityUnitCost++  , DateInterval+  , isDateBetween+  , intersection++  , PricingPeriod+  , pricingPeriodStartDate+  , pricingPeriodEndDate+  , pricingPeriodPaymentDate+  , pricingPeriodQuantity+  , PricingPeriods+  , pricingPeriod++  , UnitOfMeasureConversion+  , UnitOfMeasureConversionType(..)+  , unitOfMeasureConversion+  , unitOfMeasureConversionSource+  , unitOfMeasureConversionTarget+  , unitOfMeasureConversionCommodityType+  , unitOfMeasureConversionType+  , unitOfMeasureConversionFactor+  , unitOfMeasureConversionCode+  , convertQuantity+  , chainUnitOfMeasureConversion++  , lookupUomConversion+  , addUomConversion+  , clearUomConversions++  , commoditySettingsCurrency+  , setCommoditySettingsCurrency+  , commoditySettingsUnitOfMeasure+  , setCommoditySettingsUnitOfMeasure+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type+import QuantLib.Internal.Common+import Foreign.Marshal.Alloc(alloca)++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++#include "ql.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *Currency foreign -> CCurrency nocode#}+{#pointer *CommodityType foreign -> CCommodityType nocode#}+{#pointer *UnitOfMeasure foreign -> CUnitOfMeasure nocode#}+{#pointer *PaymentTerm foreign -> CPaymentTerm nocode#}+{#pointer *UnitOfMeasureConversion foreign -> CUnitOfMeasureConversion nocode#}++{#enum UnitOfMeasureConversionType{} deriving(Show, Eq)#}++-- |Construct a custom commodity type identified by its code (e.g. \"HO\") and descriptive name+-- (e.g. \"Heating Oil\"). QuantLib has no fixed enum of commodity types -- every instance is+-- user-registered by code, the same way a custom 'QuantLib.Currency.currency'' is.+{#fun qlCommodityType as commodityType{`String' -- ^code+  ,`String' -- ^name+  ,preErrorCheck-`String'errorCheck*-}->`CommodityType'peekCommodityType*#}++-- |The fixed placeholder commodity type QuantLib itself uses where no real commodity type+-- applies (e.g. in unit-of-measure-only conversions).+{#fun qlNullCommodityType as nullCommodityType{preErrorCheck-`String'errorCheck*-}->`CommodityType'peekCommodityType*#}++-- |The commodity code, e.g. \"HO\".+{#fun pure qlCommodityTypeCode as commodityTypeCode{withCommodityType*`CommodityType'}->`String'peekDynString*#}++-- |The descriptive name, e.g. \"Heating Oil\".+{#fun pure qlCommodityTypeName as commodityTypeName{withCommodityType*`CommodityType'}->`String'peekDynString*#}++-- |Whether this is a usable instance (as opposed to one built via a default constructor).+{#fun pure qlCommodityTypeEmpty as commodityTypeEmpty{withCommodityType*`CommodityType'}->`Bool'#}++-- |Construct a custom unit of measure from its descriptive name (e.g. \"Barrels\"), code (e.g.+-- \"BBL\"), and type (mass/volume/energy/quantity).+{#fun qlUnitOfMeasure as unitOfMeasure{`String' -- ^name+  ,`String' -- ^code+  ,fromEnumC`UnitOfMeasureType'+  ,preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |The descriptive name, e.g. \"Barrels\".+{#fun pure qlUnitOfMeasureName as unitOfMeasureName{withUnitOfMeasure*`UnitOfMeasure'}->`String'peekDynString*#}++-- |The code, e.g. \"BBL\", \"MT\".+{#fun pure qlUnitOfMeasureCode as unitOfMeasureCode{withUnitOfMeasure*`UnitOfMeasure'}->`String'peekDynString*#}++-- |The unit's type (mass/volume/energy/quantity).+{#fun pure qlUnitOfMeasureUnitType as unitOfMeasureType{withUnitOfMeasure*`UnitOfMeasure'}->`UnitOfMeasureType'toEnumC#}++-- |Whether this is a usable instance (as opposed to one built via a default constructor).+{#fun pure qlUnitOfMeasureEmpty as unitOfMeasureEmpty{withUnitOfMeasure*`UnitOfMeasure'}->`Bool'#}++-- |The lot, a dimensionless 'UnitOfMeasure::Quantity' unit.+{#fun qlLotUnitOfMeasure as lotUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Barrels (BBL), the base petroleum volume unit.+{#fun qlBarrelUnitOfMeasure as barrelUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Metric tonnes (MT).+{#fun qlMTUnitOfMeasure as mtUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Thousand barrels (MB).+{#fun qlMBUnitOfMeasure as mbUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |US gallons.+{#fun qlGallonUnitOfMeasure as gallonUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Litres.+{#fun qlLitreUnitOfMeasure as litreUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Kilolitres.+{#fun qlKilolitreUnitOfMeasure as kilolitreUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}+-- |Tokyo kilolitres.+{#fun qlTokyoKilolitreUnitOfMeasure as tokyoKilolitreUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |Construct a payment term: a named offset (in calendar-adjusted days) from either the trade+-- date or the pricing-period end date.+{#fun qlPaymentTerm as paymentTerm{`String' -- ^name+  ,fromEnumC`PaymentTermEventType'+  ,`Int' -- ^offsetDays+  ,withCalendar*`Calendar'+  ,preErrorCheck-`String'errorCheck*-}->`PaymentTerm'peekPaymentTerm*#}++-- |The payment term's name, e.g. \"Pricing end + 5 days\".+{#fun pure qlPaymentTermName as paymentTermName{withPaymentTerm*`PaymentTerm'}->`String'peekDynString*#}++-- |Whether the offset is measured from the trade date or the pricing date.+{#fun pure qlPaymentTermEventType_ as paymentTermEventType{withPaymentTerm*`PaymentTerm'}->`PaymentTermEventType'toEnumC#}++-- |The number of (calendar-adjusted) offset days.+{#fun pure qlPaymentTermOffsetDays as paymentTermOffsetDays{withPaymentTerm*`PaymentTerm'}->`Int'#}++-- |The calendar used to adjust the payment date.+{#fun qlPaymentTermCalendar as paymentTermCalendar{withPaymentTerm*`PaymentTerm',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}++-- |Whether this is a usable instance (as opposed to one built via a default constructor).+{#fun pure qlPaymentTermEmpty as paymentTermEmpty{withPaymentTerm*`PaymentTerm'}->`Bool'#}++-- |Applies the term's offset (and calendar adjustment) to a trade or pricing-period-end date to+-- get the actual payment date.+{#fun qlPaymentTermGetPaymentDate as paymentTermGetPaymentDate+  {withPaymentTerm*`PaymentTerm',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Day'toDay#}++-- |An amount of a commodity: a 'CommodityType', a 'UnitOfMeasure', and a plain amount. Marshalled+-- as a flat triple rather than a wrapper type (per the @Money@-as-tuple convention) -- and, unlike+-- 'CommodityUnitCost' below, its three inspectors are just tuple projections, so they need no+-- binding at all. c2hs's @&@ tuple-splitter only ever consumes two C arguments (confirmed against+-- its source, not just by trial), so every function below that takes or returns a 'Quantity'+-- marshals it as three flat 'CommodityType'\/'UnitOfMeasure'\/'Double' arguments instead of one+-- combined tuple.+type Quantity = (CommodityType, UnitOfMeasure, Double)++{#fun pure qlQuantityRoundedAmount as quantityRoundedAmount{withUnitOfMeasure*`UnitOfMeasure',`Double'}->`Double'#}++-- |Round a quantity's amount per its unit of measure's rounding convention. The commodity type and+-- unit of measure are unaffected by rounding, so they're carried straight through in Haskell+-- rather than round-tripped through the C++ call.+roundedQuantity :: Quantity -> Quantity+roundedQuantity (ct, uom, amount) = (ct, uom, quantityRoundedAmount uom amount)++{#fun qlQuantityClose as qlQuantityClose_+  {withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,`Int',preErrorCheck-`String'errorCheck*-}->`Bool'#}++-- |Whether two quantities are close to within @n@ ULPs (default 42 upstream), after converting+-- the second to the first's unit of measure if their units differ (which throws unless a+-- conversion is reachable -- see 'lookupUomConversion').+closeQuantity :: Quantity -> Quantity -> Int -> IO Bool+closeQuantity (ct1, uom1, amt1) (ct2, uom2, amt2) n = qlQuantityClose_ ct1 uom1 amt1 ct2 uom2 amt2 n++{#fun qlQuantityCloseEnough as qlQuantityCloseEnough_+  {withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,`Int',preErrorCheck-`String'errorCheck*-}->`Bool'#}++-- |As 'closeQuantity', but using QuantLib's relative (rather than absolute) closeness test.+closeEnoughQuantity :: Quantity -> Quantity -> Int -> IO Bool+closeEnoughQuantity (ct1, uom1, amt1) (ct2, uom2, amt2) n = qlQuantityCloseEnough_ ct1 uom1 amt1 ct2 uom2 amt2 n++-- |A commodity's unit cost: a cash amount (a @(Double, Currency)@ pair, standing in for+-- QuantLib's @Money@) per 'UnitOfMeasure'. A plain tuple, like 'Quantity' -- it carries no+-- calculation of its own upstream.+type CommodityUnitCost = (Double, Currency, UnitOfMeasure)++-- |A date range, inclusive of both ends. No C++ call is needed for either operation below --+-- 'Day' (from @Data.Time.Calendar@) already has the 'Ord' instance QuantLib's own comparisons rely+-- on, so both are plain Haskell functions rather than shim calls.+type DateInterval = (Day, Day)++-- |Whether a date falls within the interval, optionally excluding either end.+isDateBetween :: DateInterval+              -> Day -- ^date+              -> Bool -- ^includeFirst+              -> Bool -- ^includeLast+              -> Bool+isDateBetween (startDate, endDate) date includeFirst includeLast =+  (if includeFirst then date >= startDate else date > startDate) &&+  (if includeLast then date <= endDate else date < endDate)++-- |The overlap of two date intervals, or 'Nothing' if they don't overlap at all (upstream returns+-- a default-constructed, both-dates-null 'DateInterval' in this case; a 'Maybe' is the natural+-- Haskell equivalent).+intersection :: DateInterval -> DateInterval -> Maybe DateInterval+intersection (s1, e1) (s2, e2)+  | (s1 < s2 && e1 < s2) || (s1 > e2 && e1 > e2) = Nothing+  | otherwise = Just (max s1 s2, min e1 e2)++-- |A 'DateInterval' over which a fixed 'Quantity' of a commodity is priced, paid on+-- 'pricingPeriodPaymentDate'. Unlike 'Quantity'\/'CommodityUnitCost', this is a real record+-- rather than a tuple, per the user's explicit choice -- it's used as a named unit across every+-- energy-swap constructor (Stage 6), where a flat tuple would be unreadable positionally.+data PricingPeriod = PricingPeriod+  { pricingPeriodStartDate :: Day+  , pricingPeriodEndDate :: Day+  , pricingPeriodPaymentDate :: Day+  , pricingPeriodQuantity :: Quantity+  } deriving (Show, Eq)++type PricingPeriods = [PricingPeriod]++-- |Construct a 'PricingPeriod', enforcing upstream's @DateInterval@ invariant that the end date+-- is not before the start date.+pricingPeriod :: Day -> Day -> Day -> Quantity -> PricingPeriod+pricingPeriod startDate endDate+  | endDate < startDate = error "pricingPeriod: end date must be >= start date"+  | otherwise = PricingPeriod startDate endDate++-- |Construct a conversion factor between two units of measure for a given commodity type: a unit+-- of @source@ is worth @conversionFactor@ units of @target@.+{#fun qlUnitOfMeasureConversion as unitOfMeasureConversion+  {withCommodityType*`CommodityType'+  ,withUnitOfMeasure*`UnitOfMeasure' -- ^source+  ,withUnitOfMeasure*`UnitOfMeasure' -- ^target+  ,`Double' -- ^conversionFactor+  ,preErrorCheck-`String'errorCheck*-}->`UnitOfMeasureConversion'peekUnitOfMeasureConversion*#}++-- |The source unit of measure.+{#fun qlUnitOfMeasureConversionSource as unitOfMeasureConversionSource{withUnitOfMeasureConversion*`UnitOfMeasureConversion',preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |The target unit of measure.+{#fun qlUnitOfMeasureConversionTarget as unitOfMeasureConversionTarget{withUnitOfMeasureConversion*`UnitOfMeasureConversion',preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |The commodity type this conversion applies to.+{#fun qlUnitOfMeasureConversionCommodityType as unitOfMeasureConversionCommodityType{withUnitOfMeasureConversion*`UnitOfMeasureConversion',preErrorCheck-`String'errorCheck*-}->`CommodityType'peekCommodityType*#}++-- |Whether the conversion was given directly, or derived by chaining two other conversions.+{#fun pure qlUnitOfMeasureConversionType_ as unitOfMeasureConversionType{withUnitOfMeasureConversion*`UnitOfMeasureConversion'}->`UnitOfMeasureConversionType'#}++-- |The conversion factor: a unit of the source is worth this many units of the target.+{#fun pure qlUnitOfMeasureConversionFactor as unitOfMeasureConversionFactor{withUnitOfMeasureConversion*`UnitOfMeasureConversion'}->`Double'#}++-- |A code identifying the conversion, e.g. \"Heating OilMTBBL\".+{#fun pure qlUnitOfMeasureConversionCode as unitOfMeasureConversionCode{withUnitOfMeasureConversion*`UnitOfMeasureConversion'}->`String'peekDynString*#}++{#fun qlUnitOfMeasureConversionConvert as qlUnitOfMeasureConversionConvert_+  {withUnitOfMeasureConversion*`UnitOfMeasureConversion'+  ,withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,alloca-`CommodityType'peekCommodityTypePtr*+  ,alloca-`UnitOfMeasure'peekUnitOfMeasurePtr*+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |Apply the conversion factor to a quantity, converting it from the conversion's source to its+-- target unit of measure (or vice versa). Throws if the quantity's unit of measure is on neither+-- side of the conversion.+convertQuantity :: UnitOfMeasureConversion -> Quantity -> IO Quantity+convertQuantity conv (ct, uom, amount) = do+  (amount', ct', uom') <- qlUnitOfMeasureConversionConvert_ conv ct uom amount+  pure (ct', uom', amount')++-- |Combine two conversions sharing a common unit of measure into a derived conversion between+-- their other two units. Throws if the conversions don't share a common unit.+{#fun qlUnitOfMeasureConversionChain as chainUnitOfMeasureConversion+  {withUnitOfMeasureConversion*`UnitOfMeasureConversion'+  ,withUnitOfMeasureConversion*`UnitOfMeasureConversion'+  ,preErrorCheck-`String'errorCheck*-}->`UnitOfMeasureConversion'peekUnitOfMeasureConversion*#}++-- |Look up a (possibly derived, via triangulation) conversion between two units of measure for a+-- given commodity type. Throws if none can be found. Pre-populated with a set of known petroleum+-- conversion factors even before any 'addUomConversion' call.+{#fun qlUnitOfMeasureConversionManagerLookup as lookupUomConversion+  {withCommodityType*`CommodityType'+  ,withUnitOfMeasure*`UnitOfMeasure' -- ^source+  ,withUnitOfMeasure*`UnitOfMeasure' -- ^target+  ,`UnitOfMeasureConversionType'+  ,preErrorCheck-`String'errorCheck*-}->`UnitOfMeasureConversion'peekUnitOfMeasureConversion*#}++-- |Register a conversion with the global unit-of-measure conversion repository, replacing any+-- existing conversion between the same commodity type and pair of units.+{#fun qlUnitOfMeasureConversionManagerAdd as addUomConversion{withUnitOfMeasureConversion*`UnitOfMeasureConversion'}->`()'#}++-- |Reset the unit-of-measure conversion repository back to its built-in set of known petroleum+-- conversion factors, discarding anything added via 'addUomConversion'.+{#fun qlUnitOfMeasureConversionManagerClear as clearUomConversions{}->`()'#}++-- |The global commodity currency setting (defaults to USD).+{#fun qlCommoditySettingsCurrency as commoditySettingsCurrency{preErrorCheck-`String'errorCheck*-}->`Currency'peekCurrency*#}++-- |Set the global commodity currency setting.+{#fun qlCommoditySettingsSetCurrency as setCommoditySettingsCurrency{withCurrency*`Currency'}->`()'#}++-- |The global commodity unit-of-measure setting (defaults to barrels).+{#fun qlCommoditySettingsUnitOfMeasure as commoditySettingsUnitOfMeasure{preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |Set the global commodity unit-of-measure setting.+{#fun qlCommoditySettingsSetUnitOfMeasure as setCommoditySettingsUnitOfMeasure{withUnitOfMeasure*`UnitOfMeasure'}->`()'#}++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Currency.chs view
@@ -28,8 +28,7 @@   ) where import QuantLib.Internal import QuantLib.Internal.Type-import QuantLib.Internal.Enum-import QuantLib.Time.Date(Day)+import QuantLib.Internal.Common import Foreign.Marshal.Alloc(alloca)  #include "qlTypesC2HS.h"@@ -83,6 +82,7 @@   {withCurrency*`Currency' -- ^source   ,withCurrency*`Currency' -- ^target   ,`Double' -- ^rate+  ,preErrorCheck-`String'errorCheck*-   }->`ExchangeRate'peekExchangeRate*#}  -- |The rate itself: a unit of the source currency is worth this many units of the target.@@ -111,7 +111,8 @@ -- |Register an exchange rate with the global exchange-rate repository, valid between the given -- dates (inclusive). Use 'minDate'/'maxDate' for an always-valid rate. {#fun qlExchangeRateManagerAdd as addExchangeRate-  {withExchangeRate*`ExchangeRate', withDay*`Day', withDay*`Day'}->`()'#}+  {withExchangeRate*`ExchangeRate', withDay*`Day', withDay*`Day'+  ,preErrorCheck-`String'errorCheck*-}->`()'#}  -- |Look up a (possibly derived) exchange rate between two currencies at a given date (or the -- current evaluation date if 'Nothing'). Throws if no rate can be found. Pre-populated with a@@ -133,7 +134,7 @@ {#fun qlMoneySettingsSetConversionType as setMoneyConversionType{`MoneyConversionType'}->`()'#}  -- |The global base currency used by 'MoneyConversionType' base-currency conversion, if set.-{#fun qlMoneySettingsBaseCurrency as moneyBaseCurrency{}->`Maybe Currency'peekMaybeCurrency*#}+{#fun qlMoneySettingsBaseCurrency as moneyBaseCurrency{preErrorCheck-`String'errorCheck*-}->`Maybe Currency'peekMaybeCurrency*#}  -- |Set the global base currency used by 'MoneyConversionType' base-currency conversion. {#fun qlMoneySettingsSetBaseCurrency as setMoneyBaseCurrency{withCurrency*`Currency'}->`()'#}
+ QuantLib/Index/Commodity.chs view
@@ -0,0 +1,56 @@+module QuantLib.Index.Commodity+  (+    CommodityIndex++  , commodityIndex++  , commodityIndexForwardPrice+  , commodityIndexLastQuoteDate+  , commodityIndexEmpty+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++#include "ql.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *Currency foreign -> CCurrency nocode#}+{#pointer *CommodityType foreign -> CCommodityType nocode#}+{#pointer *UnitOfMeasure foreign -> CUnitOfMeasure nocode#}+{#pointer *QlCommodityCurve as CommodityCurve foreign -> CCommodityCurve' nocode#}+{#pointer *QlCommodityIndex as CommodityIndex foreign -> CCommodityIndex' nocode#}++-- |A named commodity index, whose fixings forecast from an optional forward 'CommodityCurve'+-- (or fall back to a stored historical fixing when none is given -- add one via+-- 'QuantLib.Index.addFixing'). Upstream's constructor also takes an+-- @ExchangeContracts@\/nearby-offset pair for rolling onto nearby exchange contracts; this binds+-- only the no-rolling case (a null @exchangeContracts@ and offset 0), the same scope this module's+-- 'QuantLib.TermStructure.Commodity.CommodityCurve' already narrowed 'commodityCurvePrice' to.+-- No inspector is bound for commodity type\/currency\/unit of measure\/lot quantity\/forward+-- curve: each is a plain, never-mutated echo of this constructor's own argument -- the caller+-- already holds whatever it passed in, so a getter would tell it nothing new.+{#fun qlCommodityIndex as commodityIndex+  {`String' -- ^name+  ,withCommodityType*`CommodityType'+  ,withCurrency*`Currency'+  ,withUnitOfMeasure*`UnitOfMeasure'+  ,withCalendar*`Calendar'+  ,`Double' -- ^lotQuantity+  ,withMaybeCommodityCurve*`Maybe CommodityCurve' -- ^forwardCurve+  ,preErrorCheck-`String'errorCheck*-}->`CommodityIndex'peekCommodityIndex*#}++-- |The forecast forward price for a date, from the forward curve.+{#fun qlCommodityIndexForwardPrice as commodityIndexForwardPrice{withCommodityIndex*`CommodityIndex',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The most recent date with a stored historical fixing. Throws if none has been added yet --+-- check 'commodityIndexEmpty' first if that's a possibility.+{#fun qlCommodityIndexLastQuoteDate as commodityIndexLastQuoteDate{withCommodityIndex*`CommodityIndex',preErrorCheck-`String'errorCheck*-}->`Day'toDay#}++-- |Whether this index has any stored historical fixings.+{#fun pure qlCommodityIndexEmpty as commodityIndexEmpty{withCommodityIndex*`CommodityIndex'}->`Bool'#}++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Index/Equity.chs view
@@ -3,11 +3,6 @@     EquityIndex    , equityIndex--  , currency-  , equityInterestRateCurve-  , equityDividendCurve-  , spot   ) where import QuantLib.Internal import QuantLib.Internal.Type@@ -28,7 +23,10 @@ -- |A named equity total-return index, forecasting future fixings from an -- optional risk-free interest rate curve and dividend curve, and an optional -- spot 'QuantLib.Quote.Quote' -- today's fixing is used when no spot is given.--- Historical fixings are added via 'QuantLib.Index.addFixing'.+-- Historical fixings are added via 'QuantLib.Index.addFixing'. No inspector is bound for+-- currency\/interest curve\/dividend curve\/spot: each is a plain, never-mutated echo of this+-- constructor's own argument, same shape as the currency\/interest\/dividend\/spot fields on+-- 'QuantLib.Index.Commodity.CommodityIndex' -- the caller already holds whatever it passed in. {#fun qlEquityIndex as equityIndex{`String' -- ^name   ,withCalendar*`Calendar' -- ^fixingCalendar   ,withCurrency*`Currency'@@ -36,17 +34,5 @@   ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y2)' -- ^dividend   ,withMaybeQuote*`Maybe (GenQuote q)' -- ^spot   ,preErrorCheck-`String'errorCheck*-}->`EquityIndex'peekEquityIndex*#}---- |The index currency.-{#fun qlEquityIndexCurrency as currency{withEquityIndex*`EquityIndex',preErrorCheck-`String'errorCheck*-}->`Currency'peekCurrency*#}---- |The risk-free interest rate curve used to forecast this index's future fixings.-{#fun qlEquityIndexInterestRateCurve as equityInterestRateCurve{withEquityIndex*`EquityIndex',preErrorCheck-`String'errorCheck*-}->`YieldTermStructure'peekYieldTermStructure*#}---- |The dividend curve used to forecast this index's future fixings.-{#fun qlEquityIndexDividendCurve as equityDividendCurve{withEquityIndex*`EquityIndex',preErrorCheck-`String'errorCheck*-}->`YieldTermStructure'peekYieldTermStructure*#}---- |The index's spot quote; when empty, forecasting falls back to today's fixing.-{#fun qlEquityIndexSpot as spot{withEquityIndex*`EquityIndex',preErrorCheck-`String'errorCheck*-}->`Quote'peekQuote*#}  -- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Index/InterestRate.chs view
@@ -62,8 +62,7 @@   ) where import QuantLib.Internal import QuantLib.Internal.Syntax-{#import QuantLib.Time.Schedule#}(TimeUnit(..))-{#import QuantLib.Time.Calendar#}(BusinessDayConvention)+import QuantLib.Internal.Common import QuantLib.Internal.Type -- Plain (non-c2hs) import: QuantLib.CashFlow is later in exposed-modules than -- this file, so a {#import#} here would need its .chi before it exists.@@ -78,6 +77,9 @@ #include "ql.h"  {#pointer *Currency foreign -> CCurrency nocode#}+{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *DayCounter foreign -> CDayCounter nocode#}+{#pointer *Schedule foreign -> CSchedule nocode#}  {#pointer *QlInterestRateIndex as InterestRateIndex foreign -> CInterestRateIndex' nocode#} {#pointer *QlBMAIndex as BMAIndex foreign -> CBMAIndex' nocode#}@@ -284,14 +286,14 @@ -- |Creates a swap-rate index whose forwarding and discounting both come from the underlying ibor index's curve. {#fun qlSwapIndex as swapIndex{`String',fromEnumQuantity`(Int,TimeUnit)'&,fromIntegral`Word' -- ^settlementDays   ,withCurrency*`Currency',withCalendar*`Calendar',fromEnumQuantity`(Int,TimeUnit)'& -- ^fixedLegTenor-  ,`BusinessDayConvention',withDayCounter*`DayCounter',withIborIndex*`GenIborIndex ibor',preErrorCheck-`String'errorCheck*-}->`SwapIndex'peekSwapIndex*#}+  ,fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter',withIborIndex*`GenIborIndex ibor',preErrorCheck-`String'errorCheck*-}->`SwapIndex'peekSwapIndex*#}  -- |Creates a swap-rate index with a discounting curve distinct from the forwarding curve of the underlying ibor index. {#fun qlSwapIndex1 as swapIndex'{`String' -- ^familyName   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^settlementDays   ,withCurrency*`Currency',withCalendar*`Calendar',fromEnumQuantity`(Int,TimeUnit)'& -- ^fixedLegTenor-  ,`BusinessDayConvention' -- ^fixedLegConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixedLegConvention   ,withDayCounter*`DayCounter' -- ^fixedLegDayCounter   ,withIborIndex*`GenIborIndex ibor',withYieldTermStructure*`GenYieldTermStructure y',preErrorCheck-`String'errorCheck*-}->`SwapIndex'peekSwapIndex*#} @@ -299,7 +301,7 @@ {#fun qlIborIndex{`String' -- ^familyName   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^settlementDays-  ,withCurrency*`Currency',withCalendar*`Calendar',`BusinessDayConvention'+  ,withCurrency*`Currency',withCalendar*`Calendar',fromEnumC`BusinessDayConvention'   ,`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`IborIndex'peekIborIndex*#} @@ -320,7 +322,7 @@   ,withCurrency*`Currency',withCalendar*`Calendar' -- ^fixingCalendar   ,withCalendar*`Calendar' -- ^valueCalendar   ,withCalendar*`Calendar' -- ^maturityCalendar-  ,`BusinessDayConvention'+  ,fromEnumC`BusinessDayConvention'   ,`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`IborIndex'peekIborIndex*#} @@ -332,7 +334,7 @@   ,withCurrency*`Currency',withCalendar*`Calendar',withDayCounter*`DayCounter',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`OvernightIborIndex'peekOvernightIborIndex*#}  -- |Returns the business day convention used to adjust the index's value/maturity dates.-{#fun pure qlIborIndexBusinessDayConvention as businessDayConvention{withIborIndex*`GenIborIndex ibor'}->`BusinessDayConvention'#}+{#fun pure qlIborIndexBusinessDayConvention as businessDayConvention{withIborIndex*`GenIborIndex ibor'}->`BusinessDayConvention'toEnumC#}  -- |Returns whether the index's date calculations roll to the end of the month. {#fun pure qlIborIndexEndOfMonth as endOfMonth{withIborIndex*`GenIborIndex ibor'}->`Bool'#}
QuantLib/Instrument.chs view
@@ -29,13 +29,8 @@   , setPricingEngine   ) where import QuantLib.Internal-import QuantLib.Internal.Type hiding (ptr)-import QuantLib.Internal.Enum-import Foreign.Ptr(Ptr, castPtr)-import Foreign.C.String(CString, peekCString)-import Foreign.C.Types(CUInt, CInt, CDouble)-import Foreign.Storable(Storable(..))-import Foreign.Marshal.Array(peekArray)+import QuantLib.Internal.Type hiding(ptr)+import QuantLib.Internal.Common  #include "qlTypesC2HS.h" #include "qlEnumC2HS.h"@@ -68,63 +63,11 @@ -- |returns the date the net present value refers to. {#fun qlInstrumentValuationDate as valuationDate{withInstrument*`GenInstrument i',preErrorCheck-`String'errorCheck*-}->`Day'toDay#} --- |One value from QuantLib's `Instrument::additionalResults()` map. QuantLib stores the map as--- `ext::any`, so this Haskell view picks three concrete shapes -- `Real` (`Double`), `std::string`--- (`String`), `std::vector<Real>` (`[Double]`) -- plus an `UnsupportedVal` fallback recording the--- value's C++ RTTI type name, so no key is ever silently dropped or mislabelled.-data AdditionalResultVal = RealVal Double | StringVal String | RealVectorVal [Double] | UnsupportedVal String-  deriving (Show, Eq)---- |Discriminants for `QlAdditionalResult.type`, bound from `enum AdditionalResultType` in--- `cbits/qlInstrument.h` (read from the header, not hardcoded).-{#enum AdditionalResultType {} deriving (Show, Eq) #}---- |Registers `struct QlAdditionalResult*` with c2hs as `RawResultPtr`, `nocode` since we supply--- the Haskell type ourselves (below) rather than a c2hs-generated wrapper. This is what lets the--- `additionalResults` `{#fun#}` binding's low-level array-of-structs out-parameter (C type--- `struct QlAdditionalResult **`) be typed `Ptr RawResultPtr` = `Ptr (Ptr RawResult)`, instead of--- defaulting to an opaque `Ptr (Ptr ())`.+-- |Re-registers `struct QlAdditionalResult*` with c2hs as `RawResultPtr` (the type is defined in+-- `QuantLib.Internal.Common`, `nocode` here too) -- c2hs's pointer-type table is per-file, so+-- without this the `{#fun#}` below infers the out-parameter as the opaque `Ptr (Ptr ())` instead+-- of `Ptr RawResultPtr`, which fails to typecheck against `peekAdditionalResults`'s signature. {#pointer *QlAdditionalResult as RawResultPtr nocode#}-type RawResultPtr = Ptr RawResult---- |One raw `QlAdditionalResult` entry, peeked field-by-field via c2hs `{#get#}` hooks. Its--- `Storable` instance (`sizeOf`/`alignment` from `{#sizeof#}`/`{#alignof#}`, both read straight--- from the C struct layout, not hand-computed) is what lets `peekStructArray`--- (`QuantLib.Internal`) walk the C array via a plain `peekArray`, rather than hand-rolled pointer--- arithmetic.-data RawResult = RawResult-  { rKey :: CString, rType :: CInt, rDval :: CDouble-  , rSval :: CString, rVarr :: Ptr CDouble, rVlen :: CUInt }--instance Storable RawResult where-  sizeOf _ = {#sizeof QlAdditionalResult #}-  alignment _ = {#alignof QlAdditionalResult #}-  peek p = RawResult <$> {#get QlAdditionalResult.key #} p-                      <*> {#get QlAdditionalResult.type #} p-                      <*> {#get QlAdditionalResult.dval #} p-                      <*> {#get QlAdditionalResult.sval #} p-                      <*> {#get QlAdditionalResult.varr #} p-                      <*> {#get QlAdditionalResult.vlen #} p-  poke = error "RawResult is peek-only (read from C, never constructed in Haskell)"---- |Convert one raw entry into its keyed Haskell value. `sval`/`varr` are only read for the--- discriminant that owns them; their buffers are released in bulk afterwards, by--- `qlFreeAdditionalResults`, not per-field here.-convertResult :: RawResult -> IO (String, AdditionalResultVal)-convertResult r = do-  key <- peekCString (rKey r)-  val <- case toEnum (fromIntegral (rType r)) of-    AdditionalResultDouble -> return (RealVal (realToFrac (rDval r)))-    AdditionalResultString -> StringVal <$> peekCString (rSval r)-    AdditionalResultDoubleVector -> RealVectorVal . map realToFrac-                                       <$> peekArray (fromIntegral (rVlen r)) (rVarr r)-    AdditionalResultUnknown -> UnsupportedVal <$> peekCString (rSval r)-  return (key, val)---- |Peek the C array of `QlAdditionalResult` into a keyed list, then release the whole array (keys,--- `sval`/`varr` buffers, and the array itself) in one `qlFreeAdditionalResults` call.-peekAdditionalResults :: Ptr CUInt -> Ptr RawResultPtr -> IO [(String, AdditionalResultVal)]-peekAdditionalResults = peekStructArray convertResult (\l p -> qlFreeAdditionalResults l (castPtr p))  -- |Returns QuantLib's `additionalResults()` map for the given Instrument, as an association list -- keyed by the C++ result name. The map's values are populated by the pricing engine;
QuantLib/Instrument/Bond.chs view
@@ -85,12 +85,11 @@   , convertibleZeroCouponBond   ) where import QuantLib.Internal-{#import QuantLib.Time.Calendar#}(BusinessDayConvention(..)) import QuantLib.Internal.Type {#import QuantLib.Time.Schedule#}(Frequency) {#import QuantLib.CashFlow#}(DurationType) {#import QuantLib.InterestRate#}(Compounding)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Syntax(deriveOptionsRecord) import QuantLib.Time.Calendar(calendar, CalendarConstructor(..)) import Data.Maybe(fromMaybe)@@ -101,6 +100,7 @@  #include "ql.h" +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *Leg foreign -> CLeg' nocode#} {#pointer *QlQuote as Quote foreign -> CQuote nocode#} {#pointer *QlCallability foreign -> CQlCallability nocode#}@@ -166,7 +166,7 @@   ,preErrorCheck-`String'errorCheck*-}->`Bond'peekBond*#}  -- |Returns the maturity date of the bond-{#fun pure qlBondMaturityDate as maturityDate{withBond*`GenBond b'}->`Maybe Day' toMaybeDay#}+{#fun qlBondMaturityDate as maturityDate{withBond*`GenBond b',preErrorCheck-`String'errorCheck*-}->`Maybe Day' toMaybeDay#}  -- |generic compounding and frequency InterestRate coupons {#fun qlFixedRateBond as fixedRateBond{fromIntegral`Word' -- ^settlementDays@@ -174,13 +174,13 @@   ,withSchedule*`Schedule' -- ^schedule   ,withDoubleArray*`[Double]'& -- ^coupons   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,`Double' -- ^redemption   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,withCalendar*`Calendar' -- ^paymentCalendar   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,withDayCounter*`DayCounter' -- ^firstPeriodDayCounter   ,preErrorCheck-`String'errorCheck*-}->`FixedRateBond'peekFixedRateBond*#}@@ -192,11 +192,11 @@   ,withSchedule*`Schedule' -- ^schedule   ,withDoubleArray*`[Double]'& -- ^coupons   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,withDoubleArray*`[Double]'& -- ^redemptions   ,fromIntegral`Int' -- ^paymentLag@@ -228,12 +228,12 @@   ,withSchedule*`Schedule'   ,withDoubleArray*`[Double]'& -- ^coupons   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,withCalendar*`Calendar' -- ^paymentCalendar   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,preErrorCheck-`String'errorCheck*-}->`CPIBond'peekCPIBond*#} @@ -242,7 +242,7 @@   ,withCalendar*`Calendar'   ,`Double' -- ^faceAmount   ,withDay*`Day' -- ^maturityDate-  ,`BusinessDayConvention'+  ,fromEnumC`BusinessDayConvention'   ,`Double' -- ^redemption   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,preErrorCheck-`String'errorCheck*-}->`Bond'peekBond*#}@@ -253,7 +253,7 @@   ,withSchedule*`Schedule' -- ^schedule   ,withIborIndex*`GenIborIndex ibor'   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention'+  ,fromEnumC`BusinessDayConvention'   ,fromIntegral`Word' -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -264,9 +264,9 @@   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth-  ,`BusinessDayConvention' -- ^fixingConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixingConvention   ,preErrorCheck-`String'errorCheck*-}->`Bond'peekBond*#}  -- |CMS-rate bond@@ -275,7 +275,7 @@   ,withSchedule*`Schedule' -- ^schedule   ,withSwapIndex*`GenSwapIndex sidx'   ,withDayCounter*`DayCounter' -- ^paymentDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -294,7 +294,7 @@   ,withSchedule*`Schedule' -- ^schedule   ,withSwapIndex*`GenSwapIndex sidx'   ,withDayCounter*`DayCounter' -- ^paymentDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -327,7 +327,7 @@   ,withSchedule*`Schedule' -- ^schedule   ,withIborIndex*`GenIborIndex ibor'   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^fixingDays   ,withDoubleArray*`[Double]'& -- ^gearings   ,withDoubleArray*`[Double]'& -- ^spreads@@ -337,7 +337,7 @@   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,withDoubleArray*`[Double]'& -- ^redemptions   ,fromIntegral`Int' -- ^paymentLag@@ -520,13 +520,13 @@ {#fun qlCallableFixedRateBond as callableFixedRateBond{fromIntegral`Word' -- ^settlementDays   ,`Double' -- ^faceAmount   ,withSchedule*`Schedule',withDoubleArray*`[Double]'& -- ^coupons-  ,withDayCounter*`DayCounter',`BusinessDayConvention'+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention'   ,`Double' -- ^redemption   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,withCallabilityArray*`[Callability]'&   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,preErrorCheck-`String'errorCheck*-}->`CallableBond'peekCallableBond*#} @@ -534,7 +534,7 @@ {#fun qlCallableZeroCouponBond as callableZeroCouponBond{fromIntegral`Word' -- ^settlementDays   ,`Double' -- ^faceAmount   ,withCalendar*`Calendar',withDay*`Day' -- ^maturityDate-  ,withDayCounter*`DayCounter',`BusinessDayConvention'+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention'   ,`Double' -- ^redemption   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,withCallabilityArray*`[Callability]'&,preErrorCheck-`String'errorCheck*-}->`CallableBond'peekCallableBond*#}@@ -548,7 +548,7 @@   ,withDayCounter*`DayCounter',withSchedule*`Schedule',`Double' -- ^redemption   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,preErrorCheck-`String'errorCheck*-}->`ConvertibleBond'peekConvertibleBond*#} @@ -562,7 +562,7 @@   ,withDayCounter*`DayCounter',withSchedule*`Schedule',`Double' -- ^redemption   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^exCouponPeriod   ,withCalendar*`Calendar' -- ^exCouponCalendar-  ,`BusinessDayConvention' -- ^exCouponConvention+  ,fromEnumC`BusinessDayConvention' -- ^exCouponConvention   ,`Bool' -- ^exCouponEndOfMonth   ,preErrorCheck-`String'errorCheck*-}->`ConvertibleBond'peekConvertibleBond*#} 
QuantLib/Instrument/Credit.chs view
@@ -23,10 +23,9 @@   , upfrontNPV   ) where import QuantLib.Internal-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Type {#import QuantLib.Instrument#}(PricingModel)-{#import QuantLib.Time.Calendar#}(BusinessDayConvention)  #include "qlTypesC2HS.h" #include "qlEnumC2HS.h"@@ -52,7 +51,7 @@ -- side Whether the protection is bought or sold. notional Notional value spread Running spread in fractional units. schedule Coupon schedule. paymentConvention Business-day convention for payment-date adjustment. dayCounter Day-count convention for accrual. settlesAccrual Whether or not the accrued coupon is due in the event of a default. paysAtDefaultTime If set to true, any payments triggered by a default event are due at default time. If set to false, they are due at the end of the accrual period. protectionStart The first date where a default event will trigger the contract. {#fun qlCreditDefaultSwap as creditDefaultSwap{`ProtectionSide',`Double' -- ^notional   ,`Double' -- ^spread-  ,withSchedule*`Schedule',`BusinessDayConvention',withDayCounter*`DayCounter',`Bool' -- ^settlesAccrual+  ,withSchedule*`Schedule',fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter',`Bool' -- ^settlesAccrual   ,`Bool' -- ^paysAtDefaultTime   ,withMaybeDay*`Maybe Day' -- ^protectionStart   ,withClaim*`Claim'@@ -67,7 +66,7 @@ {#fun qlCreditDefaultSwap1 as creditDefaultSwap'{`ProtectionSide',`Double' -- ^notional   ,`Double' -- ^upfront   ,`Double' -- ^spread-  ,withSchedule*`Schedule',`BusinessDayConvention',withDayCounter*`DayCounter',`Bool' -- ^settlesAccrual+  ,withSchedule*`Schedule',fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter',`Bool' -- ^settlesAccrual   ,`Bool' -- ^paysAtDefaultTime   ,withMaybeDay*`Maybe Day' -- ^protectionStart   ,withMaybeDay*`Maybe Day' -- ^upfrontDate
+ QuantLib/Instrument/Energy.chs view
@@ -0,0 +1,405 @@+module QuantLib.Instrument.Energy+  (+    SecondaryCosts+  , SecondaryCostAmounts+  , PricingErrorLevel(..)+  , PricingError(..)+  , PricingErrors+  , EnergyDailyPosition(..)+  , EnergyDailyPositions+  , CommodityCashFlow+  , CommodityCashFlows++  , commodityCashFlowDate+  , commodityCashFlowDiscountedAmount+  , commodityCashFlowUndiscountedAmount+  , commodityCashFlowDiscountedPaymentAmount+  , commodityCashFlowUndiscountedPaymentAmount+  , commodityCashFlowDiscountFactor+  , commodityCashFlowPaymentDiscountFactor+  , commodityCashFlowFinalized++  , addPricingError+  , secondaryCostAmounts+  , pricingErrors++  , quantity++  , EnergyFuture+  , energyFuture++  , EnergySwap+  , dailyPositions+  , paymentCashFlows++  , EnergyVanillaSwap+  , energyVanillaSwap++  , EnergyBasisSwap+  , energyBasisSwap++  , DeliverySchedule(..)+  , QuantityPeriodicity(..)+  , createPricingPeriods+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type+import QuantLib.Internal.Common+import QuantLib.Commodity+import Foreign.Marshal.Alloc(alloca)+import Foreign.Marshal.Utils(fromBool)++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++#include "ql.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *Currency foreign -> CCurrency nocode#}+{#pointer *CommodityType foreign -> CCommodityType nocode#}+{#pointer *UnitOfMeasure foreign -> CUnitOfMeasure nocode#}+{#pointer *PaymentTerm foreign -> CPaymentTerm nocode#}+{#pointer *QlCommodityIndex as CommodityIndex foreign -> CCommodityIndex' nocode#}+{#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#}+{#pointer *QlCommodity as Commodity foreign -> CCommodity' nocode#}+{#pointer *QlEnergyCommodity as EnergyCommodity foreign -> CEnergyCommodity' nocode#}+{#pointer *QlEnergyFuture as EnergyFuture foreign -> CEnergyFuture' nocode#}+{#pointer *QlEnergySwap as EnergySwap foreign -> CEnergySwap' nocode#}+{#pointer *QlEnergyVanillaSwap as EnergyVanillaSwap foreign -> CEnergyVanillaSwap' nocode#}+{#pointer *QlEnergyBasisSwap as EnergyBasisSwap foreign -> CEnergyBasisSwap' nocode#}+{#pointer *QlCommodityCashFlow as CommodityCashFlow foreign -> CCommodityCashFlow nocode#}++-- |QuantLib's @map<string, ext::any>@, used with exactly two concrete alternatives across the+-- module (@CommodityUnitCost@\/@Money@, confirmed from @energycommodity.cpp@'s two @any_cast@+-- branches) -- bound as a real 2-variant sum rather than a generic @any@. Passed optionally to+-- every energy-instrument constructor below; @[]@ stands in for upstream's null @shared_ptr@.+type SecondaryCosts = [(String, Either CommodityUnitCost (Double, Currency))]++-- |The computed, currency-resolved output of 'SecondaryCosts' -- @Commodity::secondaryCostAmounts()@,+-- a @map<string, Money>@.+type SecondaryCostAmounts = [(String, (Double, Currency))]++-- |A single entry of 'PricingErrors' -- @tradeId@ is never set by any constructor path that+-- reaches 'addPricingError' (upstream's own call sites all default it to empty), so it isn't+-- bound.+data PricingError = PricingError+  { pricingErrorLevel :: PricingErrorLevel+  , pricingErrorMessage :: String+  , pricingErrorDetail :: String+  } deriving (Show, Eq)++type PricingErrors = [PricingError]++-- |One day's position detail from an 'EnergySwap' leaf's @dailyPositions()@ -- a flat record+-- rather than a @(Day, ...)@ pair, since 'edpDate' already carries the map key.+data EnergyDailyPosition = EnergyDailyPosition+  { edpDate :: Day+  , edpQuantityAmount :: Double+  , edpPayLegPrice :: Double+  , edpReceiveLegPrice :: Double+  , edpRiskDelta :: Double+  , edpUnrealized :: Bool+  } deriving (Show, Eq)++type EnergyDailyPositions = [EnergyDailyPosition]++type CommodityCashFlows = [CommodityCashFlow]++-- |The cash flow's date -- also the @paymentCashFlows()@ map's own key, so it isn't duplicated as+-- a separate tuple field alongside the list of 'CommodityCashFlow's.+{#fun pure qlCommodityCashFlowDate as commodityCashFlowDate{withCommodityCashFlow*`CommodityCashFlow'}->`Day'toDay#}++-- |The discounted amount, in the global commodity base currency ('QuantLib.Commodity.commoditySettingsCurrency').+--+-- Not 'pure': the shim's own @ret(new Currency(...))@ is a 'bad_alloc'-only throw point, and letting+-- a C++ exception unwind across the FFI boundary from an 'unsafePerformIO'-backed pure binding is+-- undefined behavior, so this needs the same 'char **e'\/'preErrorCheck' error channel as any other+-- throwing call.+{#fun qlCommodityCashFlowDiscountedAmount as commodityCashFlowDiscountedAmount{withCommodityCashFlow*`CommodityCashFlow',alloca-`Currency'peekCurrencyPtr*,preErrorCheck-`String'errorCheck*-}->`Double'#}+-- |As 'commodityCashFlowDiscountedAmount', without the discount factor applied.+{#fun qlCommodityCashFlowUndiscountedAmount as commodityCashFlowUndiscountedAmount{withCommodityCashFlow*`CommodityCashFlow',alloca-`Currency'peekCurrencyPtr*,preErrorCheck-`String'errorCheck*-}->`Double'#}+-- |The discounted amount, in the payment (leg) currency.+{#fun qlCommodityCashFlowDiscountedPaymentAmount as commodityCashFlowDiscountedPaymentAmount{withCommodityCashFlow*`CommodityCashFlow',alloca-`Currency'peekCurrencyPtr*,preErrorCheck-`String'errorCheck*-}->`Double'#}+-- |As 'commodityCashFlowDiscountedPaymentAmount', without the discount factor applied.+{#fun qlCommodityCashFlowUndiscountedPaymentAmount as commodityCashFlowUndiscountedPaymentAmount{withCommodityCashFlow*`CommodityCashFlow',alloca-`Currency'peekCurrencyPtr*,preErrorCheck-`String'errorCheck*-}->`Double'#}+-- |The discount factor applied to the base-currency amount.+{#fun pure qlCommodityCashFlowDiscountFactor as commodityCashFlowDiscountFactor{withCommodityCashFlow*`CommodityCashFlow'}->`Double'#}+-- |The discount factor applied to the payment-currency amount.+{#fun pure qlCommodityCashFlowPaymentDiscountFactor as commodityCashFlowPaymentDiscountFactor{withCommodityCashFlow*`CommodityCashFlow'}->`Double'#}+-- |Whether this cash flow's payment date has already occurred as of the evaluation date.+{#fun pure qlCommodityCashFlowFinalized as commodityCashFlowFinalized{withCommodityCashFlow*`CommodityCashFlow'}->`Bool'#}++-- |Record a pricing diagnostic against a 'Commodity'\/'EnergyCommodity' leaf (any of 'EnergyFuture',+-- 'EnergyVanillaSwap', 'EnergyBasisSwap'), retrievable afterwards via 'pricingErrors'. Mirrors+-- upstream's own default empty @detail@ with a plain @\"\"@ argument.+{#fun qlCommodityAddPricingError as addPricingError+  {withCommodity*`GenCommodity c'+  ,fromEnumC`PricingErrorLevel'+  ,`String'+  ,`String'}->`()'#}++{#fun qlCommoditySecondaryCostAmounts as qlCommoditySecondaryCostAmounts_+  {withCommodity*`GenCommodity c'+  ,preArray-`[String]'&peekCStringArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preArray-`[Currency]'&peekCurrencyArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |The currency-resolved secondary costs computed during the most recent pricing+-- (@performCalculations()@) of this 'Commodity'\/'EnergyCommodity' leaf -- a plain member read, not+-- itself a pricing trigger, so call 'QuantLib.Instrument.npv' first if it hasn't been priced yet.+secondaryCostAmounts :: GenCommodity c -> IO SecondaryCostAmounts+secondaryCostAmounts o = do+  (keys, amts, ccys) <- qlCommoditySecondaryCostAmounts_ o+  pure $ zip keys (zip amts ccys)++{#fun qlCommodityPricingErrors as qlCommodityPricingErrors_+  {withCommodity*`GenCommodity c'+  ,preArray-`[PricingErrorLevel]'&peekPricingErrorLevelArray*+  ,preArray-`[String]'&peekCStringArray*+  ,preArray-`[String]'&peekCStringArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |Every pricing diagnostic recorded so far (via upstream's own internal calls, or via+-- 'addPricingError') against this 'Commodity'\/'EnergyCommodity' leaf.+pricingErrors :: GenCommodity c -> IO PricingErrors+pricingErrors o = do+  (levels, errs, details) <- qlCommodityPricingErrors_ o+  pure $ zipWith3 PricingError levels errs details++{#fun qlEnergyCommodityQuantity as qlEnergyCommodityQuantity_+  {withEnergyCommodity*`GenEnergyCommodity e'+  ,alloca-`CommodityType'peekCommodityTypePtr*+  ,alloca-`UnitOfMeasure'peekUnitOfMeasurePtr*+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The commodity quantity of this 'EnergyCommodity' leaf -- either the plain quantity given at+-- construction ('EnergyFuture') or the sum across every 'PricingPeriod' ('EnergySwap' and its+-- leaves, a real computed sum -- see @energyswap.cpp@). One binding covers both, dispatched+-- virtually on the C++ side.+quantity :: GenEnergyCommodity e -> IO Quantity+quantity o = do+  (amt, ct, uom) <- qlEnergyCommodityQuantity_ o+  pure (ct, uom, amt)++-- |Construct an energy future: a single mark-to-market position against a 'CommodityIndex',+-- struck at a fixed 'CommodityUnitCost' trade price. @buySell@ is a signed multiplier (@1@ to buy,+-- @-1@ to sell), matching upstream's own @Integer buySell@ (not a @Bool@). @tradePrice@\/@index@+-- are not bound as getters -- both are plain, never-mutated echoes of these same constructor+-- arguments (per CLAUDE.md's trivial-getter rule); use 'quantity' for the one genuinely-shared+-- accessor.+energyFuture :: Int -- ^buySell+             -> Quantity+             -> CommodityUnitCost -- ^tradePrice+             -> CommodityIndex+             -> CommodityType+             -> SecondaryCosts+             -> IO EnergyFuture+energyFuture buySell (qCt, qUom, qAmt) (tpAmt, tpCcy, tpUom) index cmdType secCosts =+  qlEnergyFuture_ buySell qCt qUom qAmt tpAmt tpCcy tpUom index cmdType+    scKeys scIsUnitCost scAmts scCcys scUoms+  where (scKeys, scIsUnitCost, scAmts, scCcys, scUoms) = secondaryCostsFields secCosts++{#fun qlEnergyFuture as qlEnergyFuture_+  {`Int'+  ,withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,`Double',withCurrency*`Currency',withUnitOfMeasure*`UnitOfMeasure'+  ,withCommodityIndex*`CommodityIndex'+  ,withCommodityType*`CommodityType'+  ,withStringArray*`[String]'&+  ,withBoolArray*`[Bool]'&+  ,withDoubleArray*`[Double]'&+  ,withCurrencyArray*`[Currency]'&+  ,withMaybeUnitOfMeasureArray*`[Maybe UnitOfMeasure]'&+  ,preErrorCheck-`String'errorCheck*-}->`EnergyFuture'peekEnergyFuture*#}++{#fun qlEnergySwapDailyPositions as qlEnergySwapDailyPositions_+  {withEnergySwap*`GenEnergySwap s'+  ,preArray-`[Day]'&peekDayArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preArray-`[Bool]'&peekBoolArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |The per-day pricing breakdown computed during this 'EnergySwap' leaf's most recent+-- @performCalculations()@ -- populated only after pricing (call 'QuantLib.Instrument.npv' first).+dailyPositions :: GenEnergySwap s -> IO EnergyDailyPositions+dailyPositions s = do+  (dates, qtyAmts, payPrices, recvPrices, riskDeltas, unrealized) <- qlEnergySwapDailyPositions_ s+  pure $ zipWith6 EnergyDailyPosition dates qtyAmts payPrices recvPrices riskDeltas unrealized++-- |The realized\/unrealized payment cash flows computed during this 'EnergySwap' leaf's most+-- recent @performCalculations()@ -- populated only after pricing.+{#fun qlEnergySwapPaymentCashFlows as paymentCashFlows+  {withEnergySwap*`GenEnergySwap s'+  ,preArray-`[CommodityCashFlow]'&peekCommodityCashFlowArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |Split a 'SecondaryCosts' list into the five parallel arrays every energy-instrument+-- constructor's C shim consumes it as (keys, is-a-'CommodityUnitCost'-flag, amounts, currencies,+-- units-of-measure -- 'Nothing' for a plain 'Money' entry).+secondaryCostsFields :: SecondaryCosts -> ([String], [Bool], [Double], [Currency], [Maybe UnitOfMeasure])+secondaryCostsFields entries =+  ( map fst entries+  , map (either (const True) (const False) . snd) entries+  , map (either (\(a,_,_) -> a) fst . snd) entries+  , map (either (\(_,c,_) -> c) snd . snd) entries+  , map (either (\(_,_,u) -> Just u) (const Nothing) . snd) entries+  )++-- |Split a 'PricingPeriods' list into the six parallel arrays every energy-swap constructor's C+-- shim consumes it as (start dates, end dates, payment dates, quantity commodity types, quantity+-- units of measure, quantity amounts).+pricingPeriodsFields :: PricingPeriods -> ([Day], [Day], [Day], [CommodityType], [UnitOfMeasure], [Double])+pricingPeriodsFields pps =+  ( map pricingPeriodStartDate pps+  , map pricingPeriodEndDate pps+  , map pricingPeriodPaymentDate pps+  , map (\(t,_,_) -> t) qtys+  , map (\(_,u,_) -> u) qtys+  , map (\(_,_,a) -> a) qtys+  )+  where qtys = map pricingPeriodQuantity pps++-- |Construct a vanilla energy swap: fixed 'CommodityUnitCost' price against a floating+-- 'CommodityIndex' quote, over one or more 'PricingPeriod's. @payer@ selects which leg (fixed or+-- floating) is paid. @payReceive@\/@fixedPrice@\/@fixedPriceUnitOfMeasure@\/@index@ are not bound+-- as getters -- all are plain, never-mutated echoes of this constructor's own arguments (per+-- CLAUDE.md's trivial-getter rule; @payReceive@ specifically is just @if payer then 1 else 0@,+-- reproducible with no C++ call at all).+energyVanillaSwap :: Bool -- ^payer+                  -> Calendar+                  -> (Double, Currency) -- ^fixedPrice+                  -> UnitOfMeasure -- ^fixedPriceUnitOfMeasure+                  -> CommodityIndex+                  -> Currency -- ^payCurrency+                  -> Currency -- ^receiveCurrency+                  -> PricingPeriods+                  -> CommodityType+                  -> SecondaryCosts+                  -> GenYieldTermStructure y1 -- ^payLegTermStructure+                  -> GenYieldTermStructure y2 -- ^receiveLegTermStructure+                  -> GenYieldTermStructure y3 -- ^discountTermStructure+                  -> IO EnergyVanillaSwap+energyVanillaSwap payer calendar (fpAmt, fpCcy) fpUom index payCcy receiveCcy pps cmdType secCosts+                  payLegTS receiveLegTS discountTS =+  qlEnergyVanillaSwap_ payer calendar fpAmt fpCcy fpUom index payCcy receiveCcy+    ppStarts ppEnds ppPays ppTypes ppUoms ppAmts+    cmdType scKeys scIsUnitCost scAmts scCcys scUoms+    payLegTS receiveLegTS discountTS+  where+    (ppStarts, ppEnds, ppPays, ppTypes, ppUoms, ppAmts) = pricingPeriodsFields pps+    (scKeys, scIsUnitCost, scAmts, scCcys, scUoms) = secondaryCostsFields secCosts++{#fun qlEnergyVanillaSwap as qlEnergyVanillaSwap_+  {fromBool`Bool'+  ,withCalendar*`Calendar'+  ,`Double',withCurrency*`Currency'+  ,withUnitOfMeasure*`UnitOfMeasure'+  ,withCommodityIndex*`CommodityIndex'+  ,withCurrency*`Currency'+  ,withCurrency*`Currency'+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withCommodityTypeArray*`[CommodityType]'&+  ,withUnitOfMeasureArray*`[UnitOfMeasure]'&+  ,withDoubleArray*`[Double]'&+  ,withCommodityType*`CommodityType'+  ,withStringArray*`[String]'&+  ,withBoolArray*`[Bool]'&+  ,withDoubleArray*`[Double]'&+  ,withCurrencyArray*`[Currency]'&+  ,withMaybeUnitOfMeasureArray*`[Maybe UnitOfMeasure]'&+  ,withYieldTermStructure*`GenYieldTermStructure y1'+  ,withYieldTermStructure*`GenYieldTermStructure y2'+  ,withYieldTermStructure*`GenYieldTermStructure y3'+  ,preErrorCheck-`String'errorCheck*-}->`EnergyVanillaSwap'peekEnergyVanillaSwap*#}++-- |Construct an energy basis swap: two floating 'CommodityIndex' legs (pay\/receive), one of them+-- offset by a fixed 'CommodityUnitCost' basis, over one or more 'PricingPeriod's. @spreadToPayLeg@+-- selects which leg the basis is added to. @payIndex@\/@receiveIndex@\/@basis@ are not bound as+-- getters -- all are plain, never-mutated echoes of this constructor's own arguments.+energyBasisSwap :: Calendar+                -> CommodityIndex -- ^spreadIndex+                -> CommodityIndex -- ^payIndex+                -> CommodityIndex -- ^receiveIndex+                -> Bool -- ^spreadToPayLeg+                -> Currency -- ^payCurrency+                -> Currency -- ^receiveCurrency+                -> PricingPeriods+                -> CommodityUnitCost -- ^basis+                -> CommodityType+                -> SecondaryCosts+                -> GenYieldTermStructure y1 -- ^payLegTermStructure+                -> GenYieldTermStructure y2 -- ^receiveLegTermStructure+                -> GenYieldTermStructure y3 -- ^discountTermStructure+                -> IO EnergyBasisSwap+energyBasisSwap calendar spreadIndex payIndex receiveIndex spreadToPayLeg payCcy receiveCcy pps+                (basisAmt, basisCcy, basisUom) cmdType secCosts payLegTS receiveLegTS discountTS =+  qlEnergyBasisSwap_ calendar spreadIndex payIndex receiveIndex spreadToPayLeg payCcy receiveCcy+    ppStarts ppEnds ppPays ppTypes ppUoms ppAmts+    basisAmt basisCcy basisUom+    cmdType scKeys scIsUnitCost scAmts scCcys scUoms+    payLegTS receiveLegTS discountTS+  where+    (ppStarts, ppEnds, ppPays, ppTypes, ppUoms, ppAmts) = pricingPeriodsFields pps+    (scKeys, scIsUnitCost, scAmts, scCcys, scUoms) = secondaryCostsFields secCosts++{#fun qlEnergyBasisSwap as qlEnergyBasisSwap_+  {withCalendar*`Calendar'+  ,withCommodityIndex*`CommodityIndex'+  ,withCommodityIndex*`CommodityIndex'+  ,withCommodityIndex*`CommodityIndex'+  ,fromBool`Bool'+  ,withCurrency*`Currency'+  ,withCurrency*`Currency'+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withCommodityTypeArray*`[CommodityType]'&+  ,withUnitOfMeasureArray*`[UnitOfMeasure]'&+  ,withDoubleArray*`[Double]'&+  ,`Double',withCurrency*`Currency',withUnitOfMeasure*`UnitOfMeasure'+  ,withCommodityType*`CommodityType'+  ,withStringArray*`[String]'&+  ,withBoolArray*`[Bool]'&+  ,withDoubleArray*`[Double]'&+  ,withCurrencyArray*`[Currency]'&+  ,withMaybeUnitOfMeasureArray*`[Maybe UnitOfMeasure]'&+  ,withYieldTermStructure*`GenYieldTermStructure y1'+  ,withYieldTermStructure*`GenYieldTermStructure y2'+  ,withYieldTermStructure*`GenYieldTermStructure y3'+  ,preErrorCheck-`String'errorCheck*-}->`EnergyBasisSwap'peekEnergyBasisSwap*#}++{#fun qlCreatePricingPeriods as qlCreatePricingPeriods_+  {withDay*`Day'+  ,withDay*`Day'+  ,withCommodityType*`CommodityType',withUnitOfMeasure*`UnitOfMeasure',`Double'+  ,fromEnumC`DeliverySchedule'+  ,fromEnumC`QuantityPeriodicity'+  ,withPaymentTerm*`PaymentTerm'+  ,preArray-`[Day]'&peekDayArray*+  ,preArray-`[Day]'&peekDayArray*+  ,preArray-`[Day]'&peekDayArray*+  ,preArray-`[CommodityType]'&peekCommodityTypeArray*+  ,preArray-`[UnitOfMeasure]'&peekUnitOfMeasureArray*+  ,preArray-`[Double]'&peekDoubleArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |Split @[startDate, endDate)@ into 'PricingPeriod's of the given quantity, per a+-- 'DeliverySchedule'\/'QuantityPeriodicity'\/'PaymentTerm' combination --+-- @CommodityPricingHelper::createPricingPeriods@. Upstream only actually implements two+-- combinations ('Monthly' with 'PerMonth', 'Daily' with 'PerDay'); every other 'DeliverySchedule'+-- silently returns @[]@ (no periods, no error -- checked directly against+-- @commoditypricinghelpers.cpp@, not assumed from the header).+createPricingPeriods :: Day -> Day -> Quantity -> DeliverySchedule -> QuantityPeriodicity -> PaymentTerm -> IO PricingPeriods+createPricingPeriods startDate endDate (ct, uom, amt) deliverySchedule qtyPeriodicity pmtTerm = do+  (starts, ends, pays, types, uoms, amts) <-+    qlCreatePricingPeriods_ startDate endDate ct uom amt deliverySchedule qtyPeriodicity pmtTerm+  pure $ zipWith6 (\s e p t u a -> pricingPeriod s e p (t, u, a)) starts ends pays types uoms amts++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Instrument/Forward.chs view
@@ -25,8 +25,7 @@   , npvTargetCurrency   ) where import QuantLib.Internal-{#import QuantLib.Instrument#}-{#import QuantLib.Time.Calendar#}(BusinessDayConvention)+import QuantLib.Internal.Common import QuantLib.Internal.Type {#import QuantLib.InterestRate#} @@ -36,6 +35,7 @@  #include "ql.h" +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *QlBond as Bond foreign -> CBond' nocode#} {#pointer *QlForward as Forward foreign -> CForward' nocode#} {#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#}@@ -60,7 +60,7 @@   ,withDay*`Day' -- ^maturityDate   ,fromEnumC`PositionType',`Double' -- ^strike   ,fromIntegral`Word' -- ^settlementDays-  ,withDayCounter*`DayCounter',withCalendar*`Calendar',`BusinessDayConvention',withBond*`GenBond b',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y1)' -- ^discountCurve+  ,withDayCounter*`DayCounter',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withBond*`GenBond b',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y1)' -- ^discountCurve   ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y2)' -- ^incomeDiscountCurve   ,preErrorCheck-`String'errorCheck*-}->`BondForward'peekBondForward*#} 
+ QuantLib/Instrument/InflationCapFloor.chs view
@@ -0,0 +1,83 @@+module QuantLib.Instrument.InflationCapFloor+  (+    YoYInflationCapFloor+  , yoyInflationCap+  , yoyInflationCollar+  , yoyInflationFloor+  , yoyInflationCapFloorAtmRate+  , yoyInflationCapFloorOptionlet++  , CPICapFloor+  , cpiCapFloor+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type+import QuantLib.Internal.Common++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++#include "ql.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *Leg foreign -> CLeg' nocode#}+{#pointer *QlYoYInflationCapFloor as YoYInflationCapFloor foreign -> CYoYInflationCapFloor' nocode#}+{#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#}+{#pointer *QlInstrument as Instrument foreign -> CInstrument' nocode#}+{#pointer *QlZeroInflationIndex as ZeroInflationIndex foreign -> CZeroInflationIndex' nocode#}+{#pointer *QlCPICapFloor as CPICapFloor foreign -> CCPICapFloor' nocode#}++-- |Constructs a YoY-inflation cap: pays the excess of the YoY leg's rate over each exercise+-- rate, if positive. Unlike a nominal cap, the first optionlet is live (YoY inflation sets in+-- arrears, so there is no reason to omit it -- see upstream's own note on+-- 'YoYInflationCapFloor').+{#fun qlYoYInflationCap as yoyInflationCap{withLeg*`GenLeg l' -- ^yoyLeg+  ,withDoubleArray*`[Double]'& -- ^exerciseRates+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCapFloor'peekYoYInflationCapFloor*#}++-- |Constructs a YoY-inflation collar: a cap struck at the cap rates combined with a floor+-- struck at the floor rates.+{#fun qlYoYInflationCollar as yoyInflationCollar{withLeg*`GenLeg l' -- ^yoyLeg+  ,withDoubleArray*`[Double]'& -- ^capRates+  ,withDoubleArray*`[Double]'& -- ^floorRates+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCapFloor'peekYoYInflationCapFloor*#}++-- |Constructs a YoY-inflation floor: pays the excess of each exercise rate over the YoY leg's+-- rate, if positive.+{#fun qlYoYInflationFloor as yoyInflationFloor{withLeg*`GenLeg l' -- ^yoyLeg+  ,withDoubleArray*`[Double]'& -- ^exerciseRates+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCapFloor'peekYoYInflationCapFloor*#}++-- |The fair (at-the-money) rate for the cap\/floor's underlying YoY leg, discounted on the+-- given curve.+{#fun qlYoYInflationCapFloorAtmRate as yoyInflationCapFloorAtmRate{withGenInstrument*`YoYInflationCapFloor'+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^discountCurve+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |Returns the n-th optionlet as a new YoYInflationCapFloor with only one cash flow.+{#fun qlYoYInflationCapFloorOptionlet as yoyInflationCapFloorOptionlet{withGenInstrument*`YoYInflationCapFloor'+  ,fromIntegral`Word' -- ^n+  ,preErrorCheck-`String'errorCheck*-}->`YoYInflationCapFloor'peekYoYInflationCapFloor*#}++-- |A CPI cap or floor: a single cumulative option on cumulative inflation up to maturity+-- (@CPI(T)\/CPI(0)@), not a strip of optionlets like 'YoYInflationCapFloor' -- similar in shape+-- to a ZCIIS option. No implied-volatility inspector: pricing goes purely through+-- 'QuantLib.PricingEngine.interpolatingCPICapFloorEngine' off a market price surface, there is+-- no vol-driven engine for it in QL 1.43.+{#fun qlCPICapFloor as cpiCapFloor{fromEnumC`OptionType'+  ,`Double' -- ^nominal+  ,withDay*`Day' -- ^startDate+  ,`Double' -- ^baseCPI+  ,withDay*`Day' -- ^maturity+  ,withCalendar*`Calendar' -- ^fixCalendar+  ,fromEnumC`BusinessDayConvention' -- ^fixConvention+  ,withCalendar*`Calendar' -- ^payCalendar+  ,fromEnumC`BusinessDayConvention' -- ^payConvention+  ,`Double' -- ^strike+  ,withZeroInflationIndex*`ZeroInflationIndex'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag+  ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation+  ,preErrorCheck-`String'errorCheck*-}->`CPICapFloor'peekCPICapFloor*#}++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Instrument/Option.chs view
@@ -13,6 +13,7 @@   , QuantoBarrierOption   , QuantoForwardVanillaOption   , QuantoVanillaOption+  , SoftBarrierOption   , VanillaOption    , ExerciseType(..)@@ -40,6 +41,8 @@   , partialTimeBarrierOption   , doubleBarrierOption   , doubleBarrierOptionImpliedVolatility+  , softBarrierOption+  , softBarrierOptionImpliedVolatility   , forwardVanillaOption   , compoundOption   , delta1@@ -47,6 +50,9 @@   , gamma1   , gamma2   , margrabeOption+  , simpleChooserOption+  , twoAssetCorrelationOption+  , writerExtensibleOption    , multiAssetOption   , deltaForward@@ -84,13 +90,14 @@ import QuantLib.Internal {#import QuantLib.Instrument#}(AverageType, BarrierType, DoubleBarrierType, PartialBarrierRange) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common  {#pointer *QlOption as Option foreign -> COption' nocode#} {#pointer *QlCdsOption as CdsOption foreign -> CCdsOption' nocode#} {#pointer *QlInstrument as Instrument foreign -> CInstrument' nocode#} {#pointer *QlBarrierOption as BarrierOption foreign -> CBarrierOption' nocode#} {#pointer *QlDoubleBarrierOption as DoubleBarrierOption foreign -> CDoubleBarrierOption' nocode#}+{#pointer *QlSoftBarrierOption as SoftBarrierOption foreign -> CSoftBarrierOption' nocode#} {#pointer *QlMargrabeOption as MargrabeOption foreign -> CMargrabeOption' nocode#} {#pointer *QlMultiAssetOption as MultiAssetOption foreign -> CMultiAssetOption' nocode#} {#pointer *QlOneAssetOption as OneAssetOption foreign -> COneAssetOption' nocode#}@@ -140,6 +147,20 @@   ,`Double' -- ^rebate   ,withStrikedPayoff*`StrikedPayoff',withExercise*`Exercise',preErrorCheck-`String'errorCheck*-}->`DoubleBarrierOption'peekDoubleBarrierOption*#} +-- |Soft barrier option on a single asset: knocked in/out proportionally over a barrier range [barrierLo, barrierHi], rather than in full at a single hard barrier. European exercise only.+{#fun qlSoftBarrierOption as softBarrierOption{`BarrierType',`Double' -- ^barrierLo+  ,`Double' -- ^barrierHi+  ,withStrikedPayoff*`StrikedPayoff',withExercise*`Exercise',preErrorCheck-`String'errorCheck*-}->`SoftBarrierOption'peekSoftBarrierOption*#}++-- |Implied Black-Scholes volatility that reproduces the given price for a SoftBarrierOption; see VanillaOption's implied-volatility for the caveats on reliability.+{#fun qlSoftBarrierOptionImpliedVolatility as softBarrierOptionImpliedVolatility{withSoftBarrierOption*`SoftBarrierOption',`Double' -- ^price+  ,withGeneralizedBlackScholesProcess*`GenGeneralizedBlackScholesProcess gbs'+  ,`Double' -- ^accuracy+  ,fromIntegral`Word' -- ^maxEvaluations+  ,`Double' -- ^minVol+  ,`Double' -- ^maxVol+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}+ -- |Forward-starting (strike-resetting) version of a vanilla option. {#fun qlForwardVanillaOption as forwardVanillaOption{`Double' -- ^moneyness   ,withDay*`Day' -- ^resetDate@@ -152,6 +173,18 @@   ,withExercise*`Exercise' -- ^daughterExercise   ,preErrorCheck-`String'errorCheck*-}->`OneAssetOption'peekOneAssetOption*#} +-- |Simple chooser option on a single asset: the holder chooses, on the choosing date, whether the option is a call or a put; both share the same strike and exercise date.+{#fun qlSimpleChooserOption as simpleChooserOption{withDay*`Day' -- ^choosingDate+  ,`Double' -- ^strike+  ,withExercise*`Exercise',preErrorCheck-`String'errorCheck*-}->`OneAssetOption'peekOneAssetOption*#}++-- |Writer-extensible option on a single asset: if out of the money at the first exercise, it is extended to a second exercise with an amended payoff.+{#fun qlWriterExtensibleOption as writerExtensibleOption{withPlainVanillaPayoff*`PlainVanillaPayoff' -- ^payoff1+  ,withExercise*`Exercise' -- ^exercise1+  ,withPlainVanillaPayoff*`PlainVanillaPayoff' -- ^payoff2+  ,withExercise*`Exercise' -- ^exercise2+  ,preErrorCheck-`String'errorCheck*-}->`OneAssetOption'peekOneAssetOption*#}+ -- |Sensitivity of a MargrabeOption's value to the price of the first asset. {#fun qlMargrabeOptionDelta1 as delta1{withMargrabeOption*`MargrabeOption',preErrorCheck-`String'errorCheck*-}->`Double'#} @@ -183,6 +216,12 @@  -- |Base construction for an option on multiple assets. {#fun qlMultiAssetOption as multiAssetOption{withPayoff*`Payoff',withExercise*`Exercise',preErrorCheck-`String'errorCheck*-}->`MultiAssetOption'peekMultiAssetOption*#}++-- |Two-asset correlation option: pays a payoff based on the second asset's value against strike2 at exercise, but only if the first asset is also in the money against strike1; otherwise pays 0.+{#fun qlTwoAssetCorrelationOption as twoAssetCorrelationOption{fromEnumC`OptionType' -- ^type+  ,`Double' -- ^strike1+  ,`Double' -- ^strike2+  ,withExercise*`Exercise',preErrorCheck-`String'errorCheck*-}->`MultiAssetOption'peekMultiAssetOption*#}  -- |Probability of the option expiring in-the-money in a cash-or-nothing sense. {#fun qlOneAssetOptionItmCashProbability as itmCashProbability{withOneAssetOption*`GenOneAssetOption oo',preErrorCheck-`String'errorCheck*-}->`Double'#}
QuantLib/Instrument/Swap.chs view
@@ -1,9 +1,15 @@ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell #-} module QuantLib.Instrument.Swap   (     Swaption+  , NonstandardSwaption   , Swap+  , FixedVsFloatingSwap   , VanillaSwap+  , NonstandardSwap+  , FloatFloatSwap+  , FloatFloatSwaption   , AssetSwap   , OvernightIndexedSwap   , BMASwap@@ -14,6 +20,9 @@   , EquityTotalReturnSwap   , VarianceSwap   , VarianceOption+  , ConstNotionalCrossCurrencySwap+  , ConstNotionalCrossCurrencyBasisSwap+  , ConstNotionalCrossCurrencyFixedVsFloatingSwap    , asSwap @@ -21,11 +30,25 @@   , SwapType(..)   , SwaptionPriceType(..)   , CPIInterpolationType(..)+  , CalibrationBasketType(..)+  , FloatFloatSwapOpts(..)+  , defaultFloatFloatSwapOpts+  , FloatFloatSwapVaryingOpts(..)+  , defaultFloatFloatSwapVaryingOpts+  , ConstNotionalCrossCurrencyBasisSwapOpts(..)+  , defaultConstNotionalCrossCurrencyBasisSwapOpts    , swap'   , swap   , bmaSwap   , vanillaSwap+  , nonstandardSwapFromVanilla+  , nonstandardSwap+  , nonstandardSwap'+  , floatFloatSwap+  , floatFloatSwap'+  , fairSpread1+  , fairSpread2   , makeVanillaSwap   , makeCms   , zeroCouponInflationSwap@@ -56,6 +79,19 @@   , startDate   , startDiscounts +  -- ConstNotionalCrossCurrencySwap family+  , constNotionalCrossCurrencySwap+  , constNotionalCrossCurrencySwap'+  , legCurrency+  , inCcyLegBPS+  , inCcyLegNPV+  , npvDateDiscounts+  , constNotionalCrossCurrencyBasisSwap+  , fairPaySpread+  , fairRecSpread+  , constNotionalCrossCurrencyFixedVsFloatingSwap+  , xccyFairRate+   , bmaLeg   , bmaLegBPS   , bmaLegNPV@@ -67,6 +103,11 @@   , liborLegNPV    , swaption+  , nonstandardSwaptionFromSwaption+  , nonstandardSwaption+  , floatFloatSwaption+  , calibrationBasket+  , floatFloatSwaptionCalibrationBasket    -- AssetSwap   , assetSwap@@ -92,14 +133,15 @@   , HasSpread(..)   ) where import Data.Maybe(fromMaybe)+import QuantLib.Internal.Syntax(deriveOptionsRecord) import QuantLib.Internal {#import QuantLib.Instrument#} {#import QuantLib.InterestRate#}(VolatilityType)-{#import QuantLib.CashFlow#}(RateAveragingType)+{#import QuantLib.CashFlow#}(RateAveragingType(..)) import QuantLib.CashFlow(cmsLeg, iborLeg)-{#import QuantLib.Time.Calendar#}(BusinessDayConvention(..), adjust, advance)+{#import QuantLib.Time.Calendar#}(adjust, advance) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Time.Schedule(schedule, DateGenerationRule(..)) import QuantLib.Time.Date(addPeriod) import QuantLib.Settings(evaluationDate)@@ -131,7 +173,13 @@ {#pointer *Leg foreign -> CLeg' nocode#} {#pointer *QlSwaption as Swaption foreign -> CSwaption' nocode#} {#pointer *QlSwap as Swap foreign -> CSwap' nocode#}+{#pointer *QlFixedVsFloatingSwap as FixedVsFloatingSwap foreign -> CFixedVsFloatingSwap' nocode#} {#pointer *QlVanillaSwap as VanillaSwap foreign -> CVanillaSwap' nocode#}+{#pointer *QlNonstandardSwap as NonstandardSwap foreign -> CNonstandardSwap' nocode#}+{#pointer *QlNonstandardSwaption as NonstandardSwaption foreign -> CNonstandardSwaption' nocode#}+{#pointer *QlBlackCalibrationHelper as BlackCalibrationHelper foreign -> CBlackCalibrationHelper' nocode#}+{#pointer *QlSwapIndex as SwapIndex foreign -> CSwapIndex' nocode#}+{#pointer *QlSwaptionVolatilityStructure as SwaptionVolatilityStructure foreign -> CSwaptionVolatilityStructure' nocode#} {#pointer *QlAssetSwap as AssetSwap foreign -> CAssetSwap' nocode#} {#pointer *QlBMASwap as BMASwap foreign -> CBMASwap' nocode#} {#pointer *QlOvernightIndexedSwap as OvernightIndexedSwap foreign -> COvernightIndexedSwap' nocode#}@@ -141,7 +189,76 @@ {#pointer *QlZeroCouponSwap as ZeroCouponSwap foreign -> CZeroCouponSwap' nocode#} {#pointer *QlEquityTotalReturnSwap as EquityTotalReturnSwap foreign -> CEquityTotalReturnSwap' nocode#} {#pointer *QlEquityIndex as EquityIndex foreign -> CEquityIndex' nocode#}+{#pointer *QlFloatFloatSwap as FloatFloatSwap foreign -> CFloatFloatSwap' nocode#}+{#pointer *QlFloatFloatSwaption as FloatFloatSwaption foreign -> CFloatFloatSwaption' nocode#}+{#pointer *QlInterestRateIndex as InterestRateIndex foreign -> CInterestRateIndex' nocode#}+{#pointer *QlConstNotionalCrossCurrencySwap as ConstNotionalCrossCurrencySwap foreign -> CConstNotionalCrossCurrencySwap' nocode#}+{#pointer *QlConstNotionalCrossCurrencyBasisSwap as ConstNotionalCrossCurrencyBasisSwap foreign -> CConstNotionalCrossCurrencyBasisSwap' nocode#}+{#pointer *QlConstNotionalCrossCurrencyFixedVsFloatingSwap as ConstNotionalCrossCurrencyFixedVsFloatingSwap foreign -> CConstNotionalCrossCurrencyFixedVsFloatingSwap' nocode#}+{#pointer *Currency foreign -> CCurrency nocode#} +-- FloatFloatSwapOpts/FloatFloatSwapVaryingOpts bundle every trailing param of FloatFloatSwap's+-- two constructors (floatfloatswap.hpp) -- 12 trailing defaulted params each, past the+-- options-record threshold (see the add-quantlib-options-record skill). Two separate records+-- (not one shared) since the scalar ctor's gearing/spread/cappedRate/flooredRate are plain+-- Double/Maybe Double while the vector ctor's are [Double]. This splice must stay textually+-- before every {#fun#}-generated binding in this file -- see OISRateHelperOpts in+-- QuantLib/TermStructure/Yield.chs for why (c2hs always appends its raw foreign-import stubs at+-- the physical end of the generated module regardless of where in the .chs a {#fun#} hook+-- appears, so a top-level TH splice in between would split the file into declaration groups+-- that can't see each other).+$(deriveOptionsRecord "FloatFloatSwapOpts" []+  [ ("ffsIntermediateCapitalExchange", [t|Bool|], [|False|])+  , ("ffsFinalCapitalExchange", [t|Bool|], [|False|])+  , ("ffsGearing1", [t|Double|], [|1.0|])+  , ("ffsSpread1", [t|Double|], [|0.0|])+  , ("ffsCappedRate1", [t|Maybe Double|], [|Nothing|])+  , ("ffsFlooredRate1", [t|Maybe Double|], [|Nothing|])+  , ("ffsGearing2", [t|Double|], [|1.0|])+  , ("ffsSpread2", [t|Double|], [|0.0|])+  , ("ffsCappedRate2", [t|Maybe Double|], [|Nothing|])+  , ("ffsFlooredRate2", [t|Maybe Double|], [|Nothing|])+  , ("ffsPaymentConvention1", [t|Maybe BusinessDayConvention|], [|Nothing|])+  , ("ffsPaymentConvention2", [t|Maybe BusinessDayConvention|], [|Nothing|])+  ])+$(deriveOptionsRecord "FloatFloatSwapVaryingOpts" []+  [ ("ffsvIntermediateCapitalExchange", [t|Bool|], [|False|])+  , ("ffsvFinalCapitalExchange", [t|Bool|], [|False|])+  , ("ffsvGearing1", [t|[Double]|], [|[]|])+  , ("ffsvSpread1", [t|[Double]|], [|[]|])+  , ("ffsvCappedRate1", [t|[Double]|], [|[]|])+  , ("ffsvFlooredRate1", [t|[Double]|], [|[]|])+  , ("ffsvGearing2", [t|[Double]|], [|[]|])+  , ("ffsvSpread2", [t|[Double]|], [|[]|])+  , ("ffsvCappedRate2", [t|[Double]|], [|[]|])+  , ("ffsvFlooredRate2", [t|[Double]|], [|[]|])+  , ("ffsvPaymentConvention1", [t|Maybe BusinessDayConvention|], [|Nothing|])+  , ("ffsvPaymentConvention2", [t|Maybe BusinessDayConvention|], [|Nothing|])+  ])++-- ConstNotionalCrossCurrencyBasisSwapOpts bundles ConstNotionalCrossCurrencyBasisSwap's 13+-- trailing defaulted params (per-leg OIS-only payment lag, compound-spread, lookback,+-- observation shift, lockout, averaging method, plus a shared telescopicValueDates), past the+-- options-record threshold -- see FloatFloatSwapOpts above for why this splice must stay+-- textually before every {#fun#} in this file. ConstNotionalCrossCurrencyFixedVsFloatingSwap's+-- constructor has only 6 trailing defaults (under the threshold), so it's widened in place+-- instead -- see 'constNotionalCrossCurrencyFixedVsFloatingSwap' below.+$(deriveOptionsRecord "ConstNotionalCrossCurrencyBasisSwapOpts" []+  [ ("cccbsPayPaymentLag", [t|Int|], [|0|])+  , ("cccbsRecPaymentLag", [t|Int|], [|0|])+  , ("cccbsPayCompoundSpread", [t|Bool|], [|False|])+  , ("cccbsPayLookbackDays", [t|Maybe Word|], [|Nothing|])+  , ("cccbsPayObservationShift", [t|Bool|], [|False|])+  , ("cccbsPayLockoutDays", [t|Word|], [|0|])+  , ("cccbsPayAveragingMethod", [t|RateAveragingType|], [|AveragingCompound|])+  , ("cccbsRecCompoundSpread", [t|Bool|], [|False|])+  , ("cccbsRecLookbackDays", [t|Maybe Word|], [|Nothing|])+  , ("cccbsRecObservationShift", [t|Bool|], [|False|])+  , ("cccbsRecLockoutDays", [t|Word|], [|0|])+  , ("cccbsRecAveragingMethod", [t|RateAveragingType|], [|AveragingCompound|])+  , ("cccbsTelescopicValueDates", [t|Bool|], [|False|])+  ])+ -- |implied volatility {#fun qlSwaptionImpliedVolatility as impliedVolatility{withSwaption*`Swaption',`Double' -- ^price   ,withYieldTermStructure*`GenYieldTermStructure y',`Double' -- ^guess@@ -183,6 +300,126 @@   ,fromMaybeBool`Maybe Bool' -- ^useIndexedCoupons   ,preErrorCheck-`String'errorCheck*-}->`VanillaSwap'peekVanillaSwap*#} +-- |Converts an existing 'FixedVsFloatingSwap' (e.g. a 'VanillaSwap') into a 'NonstandardSwap'+-- (upstream's own conversion constructor, @NonstandardSwap(const FixedVsFloatingSwap&)@).+{#fun qlNonstandardSwap1 as nonstandardSwapFromVanilla{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f'+  ,preErrorCheck-`String'errorCheck*-}->`NonstandardSwap'peekNonstandardSwap*#}++-- |'VanillaSwap' generalized to per-period fixed/floating nominals and fixed rates, plus+-- optional intermediate\/final notional exchange -- a single 'Double' gearing\/spread shared+-- across all floating periods. See 'nonstandardSwap'' for a per-period gearing\/spread.+{#fun qlNonstandardSwap as nonstandardSwap{`SwapType'+  ,withDoubleArray*`[Double]'& -- ^fixedNominal+  ,withDoubleArray*`[Double]'& -- ^floatingNominal+  ,withSchedule*`Schedule' -- ^fixedSchedule+  ,withDoubleArray*`[Double]'& -- ^fixedRate+  ,withDayCounter*`DayCounter' -- ^fixedDayCount+  ,withSchedule*`Schedule' -- ^floatingSchedule+  ,withIborIndex*`GenIborIndex ibor'+  ,`Double' -- ^gearing+  ,`Double' -- ^spread+  ,withDayCounter*`DayCounter' -- ^floatingDayCount+  ,`Bool' -- ^intermediateCapitalExchange+  ,`Bool' -- ^finalCapitalExchange+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention+  ,preErrorCheck-`String'errorCheck*-}->`NonstandardSwap'peekNonstandardSwap*#}++-- |As 'nonstandardSwap', but with a per-period gearing and spread instead of one shared value.+{#fun qlNonstandardSwap2 as nonstandardSwap'{`SwapType'+  ,withDoubleArray*`[Double]'& -- ^fixedNominal+  ,withDoubleArray*`[Double]'& -- ^floatingNominal+  ,withSchedule*`Schedule' -- ^fixedSchedule+  ,withDoubleArray*`[Double]'& -- ^fixedRate+  ,withDayCounter*`DayCounter' -- ^fixedDayCount+  ,withSchedule*`Schedule' -- ^floatingSchedule+  ,withIborIndex*`GenIborIndex ibor'+  ,withDoubleArray*`[Double]'& -- ^gearing+  ,withDoubleArray*`[Double]'& -- ^spread+  ,withDayCounter*`DayCounter' -- ^floatingDayCount+  ,`Bool' -- ^intermediateCapitalExchange+  ,`Bool' -- ^finalCapitalExchange+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention+  ,preErrorCheck-`String'errorCheck*-}->`NonstandardSwap'peekNonstandardSwap*#}++-- |Swap exchanging capped\/floored Libor or CMS coupons with a single flat nominal on each leg.+-- 'FloatFloatSwapOpts' bundles every trailing param the C++ constructor defaults (gearing\/+-- spread\/cap\/floor per leg, capital exchange, payment conventions); override only what's+-- needed via record-update syntax on 'defaultFloatFloatSwapOpts'. See 'floatFloatSwap'' for the+-- per-period-nominal overload.+floatFloatSwap :: SwapType -> Double -> Double -> Schedule -> GenInterestRateIndex ridx1+  -> DayCounter -> Schedule -> GenInterestRateIndex ridx2 -> DayCounter -> FloatFloatSwapOpts+  -> IO FloatFloatSwap+floatFloatSwap ty nominal1 nominal2 schedule1 index1 dayCount1 schedule2 index2 dayCount2 opts =+  floatFloatSwap_ ty nominal1 nominal2 schedule1 index1 dayCount1 schedule2 index2 dayCount2+    (ffsIntermediateCapitalExchange opts) (ffsFinalCapitalExchange opts)+    (ffsGearing1 opts) (ffsSpread1 opts) (ffsCappedRate1 opts) (ffsFlooredRate1 opts)+    (ffsGearing2 opts) (ffsSpread2 opts) (ffsCappedRate2 opts) (ffsFlooredRate2 opts)+    (ffsPaymentConvention1 opts) (ffsPaymentConvention2 opts)++{#fun qlFloatFloatSwap as floatFloatSwap_{`SwapType'+  ,`Double' -- ^nominal1+  ,`Double' -- ^nominal2+  ,withSchedule*`Schedule' -- ^schedule1+  ,withInterestRateIndex*`GenInterestRateIndex ridx1'+  ,withDayCounter*`DayCounter' -- ^dayCount1+  ,withSchedule*`Schedule' -- ^schedule2+  ,withInterestRateIndex*`GenInterestRateIndex ridx2'+  ,withDayCounter*`DayCounter' -- ^dayCount2+  ,`Bool' -- ^intermediateCapitalExchange+  ,`Bool' -- ^finalCapitalExchange+  ,`Double' -- ^gearing1+  ,`Double' -- ^spread1+  ,fromMaybeDouble`Maybe Double' -- ^cappedRate1+  ,fromMaybeDouble`Maybe Double' -- ^flooredRate1+  ,`Double' -- ^gearing2+  ,`Double' -- ^spread2+  ,fromMaybeDouble`Maybe Double' -- ^cappedRate2+  ,fromMaybeDouble`Maybe Double' -- ^flooredRate2+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention1+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention2+  ,preErrorCheck-`String'errorCheck*-}->`FloatFloatSwap'peekFloatFloatSwap*#}++-- |As 'floatFloatSwap', but with a per-period nominal on each leg instead of a single flat value+-- (full coverage; not used by the upstream example).+floatFloatSwap' :: SwapType -> [Double] -> [Double] -> Schedule -> GenInterestRateIndex ridx1+  -> DayCounter -> Schedule -> GenInterestRateIndex ridx2 -> DayCounter+  -> FloatFloatSwapVaryingOpts -> IO FloatFloatSwap+floatFloatSwap' ty nominal1 nominal2 schedule1 index1 dayCount1 schedule2 index2 dayCount2 opts =+  floatFloatSwap2_ ty nominal1 nominal2 schedule1 index1 dayCount1 schedule2 index2 dayCount2+    (ffsvIntermediateCapitalExchange opts) (ffsvFinalCapitalExchange opts)+    (ffsvGearing1 opts) (ffsvSpread1 opts) (ffsvCappedRate1 opts) (ffsvFlooredRate1 opts)+    (ffsvGearing2 opts) (ffsvSpread2 opts) (ffsvCappedRate2 opts) (ffsvFlooredRate2 opts)+    (ffsvPaymentConvention1 opts) (ffsvPaymentConvention2 opts)++{#fun qlFloatFloatSwap2 as floatFloatSwap2_{`SwapType'+  ,withDoubleArray*`[Double]'& -- ^nominal1+  ,withDoubleArray*`[Double]'& -- ^nominal2+  ,withSchedule*`Schedule' -- ^schedule1+  ,withInterestRateIndex*`GenInterestRateIndex ridx1'+  ,withDayCounter*`DayCounter' -- ^dayCount1+  ,withSchedule*`Schedule' -- ^schedule2+  ,withInterestRateIndex*`GenInterestRateIndex ridx2'+  ,withDayCounter*`DayCounter' -- ^dayCount2+  ,`Bool' -- ^intermediateCapitalExchange+  ,`Bool' -- ^finalCapitalExchange+  ,withDoubleArray*`[Double]'& -- ^gearing1+  ,withDoubleArray*`[Double]'& -- ^spread1+  ,withDoubleArray*`[Double]'& -- ^cappedRate1+  ,withDoubleArray*`[Double]'& -- ^flooredRate1+  ,withDoubleArray*`[Double]'& -- ^gearing2+  ,withDoubleArray*`[Double]'& -- ^spread2+  ,withDoubleArray*`[Double]'& -- ^cappedRate2+  ,withDoubleArray*`[Double]'& -- ^flooredRate2+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention1+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^paymentConvention2+  ,preErrorCheck-`String'errorCheck*-}->`FloatFloatSwap'peekFloatFloatSwap*#}++-- |The spread on leg 1 that would make the swap's NPV zero.+{#fun qlFloatFloatSwapFairSpread1 as fairSpread1{withFloatFloatSwap*`FloatFloatSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The spread on leg 2 that would make the swap's NPV zero.+{#fun qlFloatFloatSwapFairSpread2 as fairSpread2{withFloatFloatSwap*`FloatFloatSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+ -- | Haskell equivalent of QuantLib's fluent @MakeVanillaSwap@ builder -- a -- single function with 'Maybe'-wrapped optional parameters instead of -- chained @.with*@ calls, covering the subset of @makevanillaswap.hpp@'s@@ -330,9 +567,162 @@ -- |Discount factor at leg j's start date. {#fun qlSwapStartDiscounts as startDiscounts{withSwap*`GenSwap s',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`Double'#} +-- ConstNotionalCrossCurrencySwap+-- |Constructs a cross-currency swap from two legs and their currencies; the first leg is paid, the second received.+{#fun qlConstNotionalCrossCurrencySwap as constNotionalCrossCurrencySwap{withLeg*`GenLeg l1'+  ,withCurrency*`Currency' -- ^firstLegCcy+  ,withLeg*`GenLeg l2'+  ,withCurrency*`Currency' -- ^secondLegCcy+  ,preErrorCheck-`String'errorCheck*-}->`ConstNotionalCrossCurrencySwap'peekConstNotionalCrossCurrencySwap*#}++-- |Multi-leg constructor.+constNotionalCrossCurrencySwap' :: [(Leg, Bool)] -- ^(legs, payer)+  -> [Currency] -> IO ConstNotionalCrossCurrencySwap+constNotionalCrossCurrencySwap' legsPayer = qlConstNotionalCrossCurrencySwap1 legs payer+  where (legs, payer) = unzip legsPayer+{#fun qlConstNotionalCrossCurrencySwap1{withLegArray*`[Leg]'&,withBoolArray*`[Bool]'&,withCurrencyArray*`[Currency]'&,preErrorCheck-`String'errorCheck*-}->`ConstNotionalCrossCurrencySwap'peekConstNotionalCrossCurrencySwap*#}++-- |Leg j's currency.+{#fun qlConstNotionalCrossCurrencySwapLegCurrency as legCurrency{withConstNotionalCrossCurrencySwap*`GenConstNotionalCrossCurrencySwap x',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`Currency'peekCurrency*#}++-- |Basis-point sensitivity of leg j, expressed in the leg's own currency (contrast 'legBPS', in the swap's NPV currency).+{#fun qlConstNotionalCrossCurrencySwapInCcyLegBPS as inCcyLegBPS{withConstNotionalCrossCurrencySwap*`GenConstNotionalCrossCurrencySwap x',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |NPV of leg j, expressed in the leg's own currency (contrast 'legNPV', in the swap's NPV currency).+{#fun qlConstNotionalCrossCurrencySwapInCcyLegNPV as inCcyLegNPV{withConstNotionalCrossCurrencySwap*`GenConstNotionalCrossCurrencySwap x',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |Discount factor at the instrument's NPV date, for leg j.+{#fun qlConstNotionalCrossCurrencySwapNpvDateDiscounts as npvDateDiscounts{withConstNotionalCrossCurrencySwap*`GenConstNotionalCrossCurrencySwap x',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- ConstNotionalCrossCurrencyBasisSwap+-- |Cross-currency basis swap: pay-currency cashflows on leg 0, receive-currency on leg 1.+-- 'ConstNotionalCrossCurrencyBasisSwapOpts' bundles every trailing param the C++ constructor+-- defaults (all OIS-only -- payment lag, compound-spread, lookback, observation shift, lockout,+-- averaging method per leg, plus a shared telescopic-value-dates flag; ignored for a plain Ibor+-- 'payIndex'\/'recIndex', since upstream itself only consults them when the index is an overnight+-- index); override only what's needed via record-update syntax on+-- 'defaultConstNotionalCrossCurrencyBasisSwapOpts'.+constNotionalCrossCurrencyBasisSwap :: Double -> Currency -> Schedule -> GenIborIndex ibor1 -> Double -> Double+  -> Double -> Currency -> Schedule -> GenIborIndex ibor2 -> Double -> Double+  -> ConstNotionalCrossCurrencyBasisSwapOpts -> IO ConstNotionalCrossCurrencyBasisSwap+constNotionalCrossCurrencyBasisSwap payNominal payCurrency paySchedule payIndex paySpread payGearing+    recNominal recCurrency recSchedule recIndex recSpread recGearing opts =+  constNotionalCrossCurrencyBasisSwap_ payNominal payCurrency paySchedule payIndex paySpread payGearing+    recNominal recCurrency recSchedule recIndex recSpread recGearing+    (cccbsPayPaymentLag opts) (cccbsRecPaymentLag opts)+    (cccbsPayCompoundSpread opts) (cccbsPayLookbackDays opts) (cccbsPayObservationShift opts)+    (cccbsPayLockoutDays opts) (cccbsPayAveragingMethod opts)+    (cccbsRecCompoundSpread opts) (cccbsRecLookbackDays opts) (cccbsRecObservationShift opts)+    (cccbsRecLockoutDays opts) (cccbsRecAveragingMethod opts)+    (cccbsTelescopicValueDates opts)++{#fun qlConstNotionalCrossCurrencyBasisSwap as constNotionalCrossCurrencyBasisSwap_{`Double' -- ^payNominal+  ,withCurrency*`Currency' -- ^payCurrency+  ,withSchedule*`Schedule' -- ^paySchedule+  ,withIborIndex*`GenIborIndex ibor1' -- ^payIndex+  ,`Double' -- ^paySpread+  ,`Double' -- ^payGearing+  ,`Double' -- ^recNominal+  ,withCurrency*`Currency' -- ^recCurrency+  ,withSchedule*`Schedule' -- ^recSchedule+  ,withIborIndex*`GenIborIndex ibor2' -- ^recIndex+  ,`Double' -- ^recSpread+  ,`Double' -- ^recGearing+  ,fromIntegral`Int' -- ^payPaymentLag+  ,fromIntegral`Int' -- ^recPaymentLag+  ,`Bool' -- ^payCompoundSpread+  ,fromMaybeInt`Maybe Word' -- ^payLookbackDays+  ,`Bool' -- ^payObservationShift+  ,fromIntegral`Word' -- ^payLockoutDays+  ,`RateAveragingType' -- ^payAveragingMethod+  ,`Bool' -- ^recCompoundSpread+  ,fromMaybeInt`Maybe Word' -- ^recLookbackDays+  ,`Bool' -- ^recObservationShift+  ,fromIntegral`Word' -- ^recLockoutDays+  ,`RateAveragingType' -- ^recAveragingMethod+  ,`Bool' -- ^telescopicValueDates+  ,preErrorCheck-`String'errorCheck*-}->`ConstNotionalCrossCurrencyBasisSwap'peekConstNotionalCrossCurrencyBasisSwap*#}++-- |The pay-leg spread that would make the swap's NPV zero.+{#fun qlConstNotionalCrossCurrencyBasisSwapFairPaySpread as fairPaySpread{withConstNotionalCrossCurrencyBasisSwap*`ConstNotionalCrossCurrencyBasisSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The receive-leg spread that would make the swap's NPV zero.+{#fun qlConstNotionalCrossCurrencyBasisSwapFairRecSpread as fairRecSpread{withConstNotionalCrossCurrencyBasisSwap*`ConstNotionalCrossCurrencyBasisSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- ConstNotionalCrossCurrencyFixedVsFloatingSwap+-- |Cross-currency fixed-vs-floating swap: 'Payer' pays the fixed leg (leg 0) and receives the+-- floating leg (leg 1); 'Receiver' the reverse. Every trailing defaulted param of the upstream+-- constructor is a required argument here (only 6 trailing defaults, under the options-record+-- threshold -- see 'ConstNotionalCrossCurrencyBasisSwapOpts' above) -- pass @False@\/@False@\/+-- 'Nothing'\/@False@\/@0@\/'AveragingCompound' to reproduce upstream's own defaults; the+-- OIS-only ones are ignored for a plain Ibor 'floatIndex'.+{#fun qlConstNotionalCrossCurrencyFixedVsFloatingSwap as constNotionalCrossCurrencyFixedVsFloatingSwap{`SwapType'+  ,`Double' -- ^fixedNominal+  ,withCurrency*`Currency' -- ^fixedCurrency+  ,withSchedule*`Schedule' -- ^fixedSchedule+  ,`Double' -- ^fixedRate+  ,withDayCounter*`DayCounter' -- ^fixedDayCount+  ,fromEnumC`BusinessDayConvention' -- ^fixedPaymentBdc+  ,fromIntegral`Word' -- ^fixedPaymentLag+  ,withCalendar*`Calendar' -- ^fixedPaymentCalendar+  ,`Double' -- ^floatNominal+  ,withCurrency*`Currency' -- ^floatCurrency+  ,withSchedule*`Schedule' -- ^floatSchedule+  ,withIborIndex*`GenIborIndex ibor' -- ^floatIndex+  ,`Double' -- ^floatSpread+  ,fromEnumC`BusinessDayConvention' -- ^floatPaymentBdc+  ,fromIntegral`Word' -- ^floatPaymentLag+  ,withCalendar*`Calendar' -- ^floatPaymentCalendar+  ,`Bool' -- ^telescopicValueDates+  ,`Bool' -- ^floatCompoundSpread+  ,fromMaybeInt`Maybe Word' -- ^floatLookbackDays+  ,`Bool' -- ^floatObservationShift+  ,fromIntegral`Word' -- ^floatLockoutDays+  ,`RateAveragingType' -- ^floatAveragingMethod+  ,preErrorCheck-`String'errorCheck*-}->`ConstNotionalCrossCurrencyFixedVsFloatingSwap'peekConstNotionalCrossCurrencyFixedVsFloatingSwap*#}++-- |The fixed rate that would make the swap's NPV zero. Named distinctly from 'fairRate' -- that+-- name belongs to the 'HasFixedLeg' class, which this type doesn't implement (upstream gives it+-- no fixedLeg\/fixedLegBPS\/fixedLegNPV getters); 'fairSpread' (via 'HasSpread') is available.+{#fun qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairRate as xccyFairRate{withConstNotionalCrossCurrencyFixedVsFloatingSwap*`ConstNotionalCrossCurrencyFixedVsFloatingSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}++instance HasSpread ConstNotionalCrossCurrencyFixedVsFloatingSwap where+  fairSpread = qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairSpread+{#fun qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairSpread{withConstNotionalCrossCurrencyFixedVsFloatingSwap*`ConstNotionalCrossCurrencyFixedVsFloatingSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+ -- |An option on a 'VanillaSwap'.-{#fun qlSwaption as swaption{withVanillaSwap*`VanillaSwap',withExercise*`Exercise',`SettlementType',`SettlementMethod',preErrorCheck-`String'errorCheck*-}->`Swaption'peekSwaption*#}+{#fun qlSwaption as swaption{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',withExercise*`Exercise',`SettlementType',`SettlementMethod',preErrorCheck-`String'errorCheck*-}->`Swaption'peekSwaption*#} +-- |Converts an existing 'Swaption' into a 'NonstandardSwaption' (upstream's own conversion+-- constructor).+{#fun qlNonstandardSwaption1 as nonstandardSwaptionFromSwaption{withSwaption*`Swaption'+  ,preErrorCheck-`String'errorCheck*-}->`NonstandardSwaption'peekNonstandardSwaption*#}++-- |An option on a 'NonstandardSwap'.+{#fun qlNonstandardSwaption as nonstandardSwaption{withNonstandardSwap*`NonstandardSwap',withExercise*`Exercise',`SettlementType',`SettlementMethod',preErrorCheck-`String'errorCheck*-}->`NonstandardSwaption'peekNonstandardSwaption*#}++-- |Auto-generates a basket of plain 'Swaption's used to calibrate a model to price a+-- 'NonstandardSwaption' -- either ATM swaptions adapted to the exercise dates ('Naive') or+-- swaptions whose maturity\/strike\/nominal match the underlying's NPV, delta and gamma at each+-- exercise date ('MaturityStrikeByDeltaGamma').+{#fun qlNonstandardSwaptionCalibrationBasket as calibrationBasket{withNonstandardSwaption*`NonstandardSwaption'+  ,withSwapIndex*`GenSwapIndex sidx' -- ^standardSwapBase+  ,withSwaptionVolatilityStructure*`GenSwaptionVolatilityStructure sv' -- ^swaptionVolatility+  ,fromEnumC`CalibrationBasketType'+  ,preArray-`[BlackCalibrationHelper]'&peekBlackCalibrationHelperArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |An option on a 'FloatFloatSwap'.+{#fun qlFloatFloatSwaption as floatFloatSwaption{withFloatFloatSwap*`FloatFloatSwap',withExercise*`Exercise',`SettlementType',`SettlementMethod',preErrorCheck-`String'errorCheck*-}->`FloatFloatSwaption'peekFloatFloatSwaption*#}++-- |As 'calibrationBasket', for a 'FloatFloatSwaption'.+{#fun qlFloatFloatSwaptionCalibrationBasket as floatFloatSwaptionCalibrationBasket{withFloatFloatSwaption*`FloatFloatSwaption'+  ,withSwapIndex*`GenSwapIndex sidx' -- ^standardSwapBase+  ,withSwaptionVolatilityStructure*`GenSwaptionVolatilityStructure sv' -- ^swaptionVolatility+  ,fromEnumC`CalibrationBasketType'+  ,preArray-`[BlackCalibrationHelper]'&peekBlackCalibrationHelperArray*+  ,preErrorCheck-`String'errorCheck*-}->`()'#}+ -- AssetSwap -- |Bullet bond vs Libor swap (par or market asset swap, per /parAssetSwap/). {#fun qlAssetSwap as assetSwap{`Bool' -- ^payBondCoupon@@ -352,7 +742,7 @@   ,withDayCounter*`DayCounter' -- ^fixedDC   ,withOvernightIborIndex*`OvernightIborIndex',`Double' -- ^spread   ,fromIntegral`Int' -- ^paymentLag-  ,`BusinessDayConvention' -- ^paymentAdjustment+  ,fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withCalendar*`Calendar' -- ^paymentCalendar   ,`Bool' -- ^telescopicValueDates   ,`RateAveragingType' -- ^averagingMethod@@ -368,7 +758,7 @@   ,withDayCounter*`DayCounter' -- ^fixedDC   ,withOvernightIborIndex*`OvernightIborIndex',`Double' -- ^spread   ,fromIntegral`Int' -- ^paymentLag-  ,`BusinessDayConvention' -- ^paymentAdjustment+  ,fromEnumC`BusinessDayConvention' -- ^paymentAdjustment   ,withCalendar*`Calendar' -- ^paymentCalendar   ,`Bool' -- ^telescopicValueDates   ,`RateAveragingType' -- ^averagingMethod@@ -451,7 +841,7 @@   ,withDay*`Day' -- ^startDate   ,withDay*`Day' -- ^maturity   ,withCalendar*`Calendar'-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withDayCounter*`DayCounter'   ,`Double' -- ^fixedRate   ,withZeroInflationIndex*`ZeroInflationIndex'@@ -459,7 +849,7 @@   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation   ,`Bool' -- ^adjustInfObsDates   ,withCalendar*`Calendar' -- ^infCalendar-  ,`BusinessDayConvention' -- ^infConvention+  ,fromEnumC`BusinessDayConvention' -- ^infConvention   ,preErrorCheck-`String'errorCheck*-}->`ZeroCouponInflationSwap'peekZeroCouponInflationSwap*#}  -- |The fixed rate that would make the swap's NPV zero.@@ -478,7 +868,7 @@   ,`Double' -- ^spread   ,withDayCounter*`DayCounter' -- ^yoyDayCount   ,withCalendar*`Calendar' -- ^paymentCalendar-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,preErrorCheck-`String'errorCheck*-}->`YearOnYearInflationSwap'peekYearOnYearInflationSwap*#}  -- |The fixed rate that would make the swap's NPV zero.@@ -496,14 +886,14 @@   ,`Double' -- ^spread   ,withDayCounter*`DayCounter' -- ^floatDayCount   ,withSchedule*`Schedule' -- ^floatSchedule-  ,`BusinessDayConvention' -- ^floatRoll+  ,fromEnumC`BusinessDayConvention' -- ^floatRoll   ,fromIntegral`Word' -- ^fixingDays   ,withIborIndex*`GenIborIndex ibor' -- ^floatIndex   ,`Double' -- ^fixedRate   ,`Double' -- ^baseCPI   ,withDayCounter*`DayCounter' -- ^fixedDayCount   ,withSchedule*`Schedule' -- ^fixedSchedule-  ,`BusinessDayConvention' -- ^fixedRoll+  ,fromEnumC`BusinessDayConvention' -- ^fixedRoll   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag   ,withZeroInflationIndex*`ZeroInflationIndex' -- ^fixedIndex   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation@@ -522,7 +912,7 @@   ,withDay*`Day' -- ^maturityDate   ,`Double' -- ^fixedPayment   ,withIborIndex*`GenIborIndex ibor',withCalendar*`Calendar' -- ^paymentCalendar-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^paymentDelay   ,preErrorCheck-`String'errorCheck*-}->`ZeroCouponSwap'peekZeroCouponSwap*#} @@ -533,7 +923,7 @@   ,`Double' -- ^fixedRate   ,withDayCounter*`DayCounter' -- ^fixedDayCounter   ,withIborIndex*`GenIborIndex ibor',withCalendar*`Calendar' -- ^paymentCalendar-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^paymentDelay   ,preErrorCheck-`String'errorCheck*-}->`ZeroCouponSwap'peekZeroCouponSwap*#} @@ -553,7 +943,7 @@   ,`Double' -- ^margin   ,`Double' -- ^gearing   ,withCalendar*`Calendar' -- ^paymentCalendar-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^paymentDelay   ,preErrorCheck-`String'errorCheck*-}->`EquityTotalReturnSwap'peekEquityTotalReturnSwap*#} @@ -567,7 +957,7 @@   ,`Double' -- ^margin   ,`Double' -- ^gearing   ,withCalendar*`Calendar' -- ^paymentCalendar-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,fromIntegral`Word' -- ^paymentDelay   ,preErrorCheck-`String'errorCheck*-}->`EquityTotalReturnSwap'peekEquityTotalReturnSwap*#} @@ -590,16 +980,16 @@   fixedLeg = qlOvernightIndexedSwapFixedLeg   fixedLegBPS = qlOvernightIndexedSwapFixedLegBPS   fixedLegNPV = qlOvernightIndexedSwapFixedLegNPV-instance HasFixedLeg VanillaSwap where-  fairRate = qlVanillaSwapFairRate-  fixedLeg = qlVanillaSwapFixedLeg-  fixedLegBPS = qlVanillaSwapFixedLegBPS-  fixedLegNPV = qlVanillaSwapFixedLegNPV+instance HasFixedLeg (GenFixedVsFloatingSwap f) where+  fairRate = qlFixedVsFloatingSwapFairRate+  fixedLeg = qlFixedVsFloatingSwapFixedLeg+  fixedLegBPS = qlFixedVsFloatingSwapFixedLegBPS+  fixedLegNPV = qlFixedVsFloatingSwapFixedLegNPV  class HasSpread a where   fairSpread :: a -> IO Double-instance HasSpread VanillaSwap where-  fairSpread = qlVanillaSwapFairSpread+instance HasSpread (GenFixedVsFloatingSwap f) where+  fairSpread = qlFixedVsFloatingSwapFairSpread instance HasSpread OvernightIndexedSwap where   fairSpread = qlOvernightIndexedSwapFairSpread instance HasSpread AssetSwap where@@ -615,32 +1005,32 @@   floatingLeg :: a -> IO Leg   floatingLegBPS :: a -> IO Double   floatingLegNPV :: a -> IO Double-instance HasFloatingLeg VanillaSwap where-  floatingLeg = qlVanillaSwapFloatingLeg-  floatingLegBPS = qlVanillaSwapFloatingLegBPS-  floatingLegNPV = qlVanillaSwapFloatingLegNPV+instance HasFloatingLeg (GenFixedVsFloatingSwap f) where+  floatingLeg = qlFixedVsFloatingSwapFloatingLeg+  floatingLegBPS = qlFixedVsFloatingSwapFloatingLegBPS+  floatingLegNPV = qlFixedVsFloatingSwapFloatingLegNPV instance HasFloatingLeg AssetSwap where   floatingLeg = qlAssetSwapFloatingLeg   floatingLegBPS = qlAssetSwapFloatingLegBPS   floatingLegNPV = qlAssetSwapFloatingLegNPV  -- |The spread that would make the swap's NPV zero.-{#fun qlVanillaSwapFairSpread{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFairSpread{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The spread that would make the swap's NPV zero. {#fun qlAssetSwapFairSpread{withAssetSwap*`AssetSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The fixed rate that would make the swap's NPV zero.-{#fun qlVanillaSwapFairRate{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFairRate{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The fixed leg's cash flows.-{#fun qlVanillaSwapFixedLeg{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}+{#fun qlFixedVsFloatingSwapFixedLeg{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Basis-point sensitivity of the fixed leg.-{#fun qlVanillaSwapFixedLegBPS{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFixedLegBPS{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |NPV of the fixed leg.-{#fun qlVanillaSwapFixedLegNPV{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFixedLegNPV{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The fixed rate that would make the swap's NPV zero. {#fun qlOvernightIndexedSwapFairRate{withOvernightIndexedSwap*`OvernightIndexedSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}@@ -661,13 +1051,13 @@ {#fun qlCreditDefaultSwapFairSpread{withGenInstrument*`CreditDefaultSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The floating leg's cash flows.-{#fun qlVanillaSwapFloatingLeg{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}+{#fun qlFixedVsFloatingSwapFloatingLeg{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}  -- |Basis-point sensitivity of the floating leg.-{#fun qlVanillaSwapFloatingLegBPS{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFloatingLegBPS{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |NPV of the floating leg.-{#fun qlVanillaSwapFloatingLegNPV{withVanillaSwap*`VanillaSwap',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlFixedVsFloatingSwapFloatingLegNPV{withFixedVsFloatingSwap*`GenFixedVsFloatingSwap f',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |The floating leg's cash flows. {#fun qlAssetSwapFloatingLeg{withAssetSwap*`AssetSwap',preErrorCheck-`String'errorCheck*-}->`Leg'peekLeg*#}
QuantLib/Internal.hs view
@@ -24,11 +24,14 @@   , withNonEmptyDoubleArray   , withDoubleArrayRaw   , withDayPtr+  , withStringArray+  , peekCStringArray   , fromEnumQuantity   , toEnumQuantity   , fromEnumDouble   , toEnumDouble   , fromEnumC+  , toEnumC    , withDay   , toDay@@ -47,10 +50,13 @@   , qlFreeSavedSettings   , fromMaybeDouble   , fromMaybeEnum+  , fromMaybeEnumQuantity   , peekIntArray+  , peekIntArray'   , peekUIntArray   , peekWord   , peekStructArray+  , peekPtrArray   , Matrix(..)   , realMatrix   , objectMatrix@@ -58,15 +64,16 @@   , qlFreeAdditionalResults    , uncurryNested+  , zipWith6   ) where  import Foreign.C.Types(CUInt(..), CInt(..), CDouble(..))-import Foreign.C.String(CString, peekCString)-import Foreign.Ptr(Ptr, nullPtr)+import Foreign.C.String(CString, peekCString, withCString)+import Foreign.Ptr(Ptr, nullPtr, castPtr) import Foreign.ForeignPtr(FinalizerPtr, newForeignPtr) import Foreign.Marshal.Array(peekArray, withArray)-import Foreign.Marshal.Utils(with, toBool, fromBool)+import Foreign.Marshal.Utils(with, toBool, fromBool, withMany) import Foreign.Storable(peek, Storable) import Foreign.Marshal.Alloc(alloca) @@ -108,6 +115,11 @@ fromMaybeEnum :: Enum a => Maybe a -> CInt fromMaybeEnum = maybe (-1) (fromIntegral . fromEnum) +-- |'Nothing' emits the enum's -1 sentinel (same convention as 'fromMaybeEnum'), paired with a+-- placeholder quantity of 0 -- for enums like 'TimeUnit' that start at 0 and can't self-sentinel.+fromMaybeEnumQuantity :: Enum a => Maybe (Word, a) -> (CInt, CInt)+fromMaybeEnumQuantity = maybe (0, -1) fromEnumQuantity+ toMaybeBool :: CInt -> Maybe Bool toMaybeBool x = if x == -1 then Nothing else Just $ toBool x @@ -135,8 +147,9 @@ foreign import ccall safe "ql.h qlFreeUInts" qlFreeUInts :: Ptr CUInt -> IO () foreign import ccall safe "ql.h qlFreeDoubles" qlFreeDoubles :: Ptr CDouble -> IO () foreign import ccall safe "ql.h &qlFreeDoubles" qlFreeDoublesFin :: FinalizerPtr CDouble---foreign import ccall safe "ql.h qlFreePointerArray" qlFreePointerArray :: Ptr (Ptr ()) -> IO ()+foreign import ccall safe "ql.h qlFreePointerArray" qlFreePointerArray :: Ptr (Ptr ()) -> IO () foreign import ccall safe "ql.h qlFreeAdditionalResults" qlFreeAdditionalResults :: CUInt -> Ptr () -> IO ()+foreign import ccall safe "ql.h qlFreeStringArray" qlFreeStringArray :: CUInt -> Ptr CString -> IO () foreign import ccall safe "ql.h qlSavedSettings" qlSavedSettings :: IO (Ptr ()) foreign import ccall safe "ql.h qlFreeSavedSettings" qlFreeSavedSettings :: Ptr () -> IO () @@ -167,6 +180,12 @@ withDayPtr :: [Day] -> (Ptr CInt -> IO a) -> IO a withDayPtr x f = mapM toSerial x >>= (`withArray` f) +-- |An array of plain C strings, for a function taking a @std::vector<std::string>@-shaped+-- argument as a flat @(count, char**)@ pair (the input-side counterpart of 'peekCStringArray'+-- below) -- first needed for @SecondaryCosts@' string keys (@QuantLib.Instrument.Energy@).+withStringArray :: [String] -> ((CUInt, Ptr CString) -> IO b) -> IO b+withStringArray xs f = withMany withCString xs (\ps -> withArray ps (\p -> f (fromIntegral (length xs), p)))+ prePtr :: (Storable a) => (Ptr a -> IO b) -> IO b prePtr = alloca @@ -190,6 +209,18 @@ peekIntArray :: Ptr CUInt -> Ptr (Ptr CInt) -> IO [Int] peekIntArray = peekIntArray' fromIntegral +-- |An array of freshly heap-allocated (@DUP@'d) C strings -- the output-side counterpart of+-- 'withStringArray'. Each element is read via 'peekCString' and the whole array (including every+-- individual string) is then released via 'qlFreeStringArray' in one call, mirroring+-- 'peekDoubleArray'\/'peekIntArray'\''s read-then-free shape.+peekCStringArray :: Ptr CUInt -> Ptr (Ptr CString) -> IO [String]+peekCStringArray pl pp = do+  l <- peek pl+  p <- peek pp+  raws <- peekArray (fromIntegral l) p+  strs <- mapM peekCString raws+  strs <$ qlFreeStringArray l p+ peekBoolArray :: Ptr CUInt -> Ptr (Ptr CInt) -> IO [Bool] peekBoolArray = peekIntArray' toBool @@ -223,6 +254,18 @@   results <- mapM convert raws   results <$ freeFn l p +-- |Like 'peekStructArray' but for a @T**@ array of C++-owned pointers to live objects: peeks the+-- length/pointer out-params, converts each raw pointer to a live Haskell value via @peekOne@+-- (installing that value's own finalizer over the pointee), then frees only the array spine via+-- 'qlFreePointerArray' -- not the pointees, whose lifetime @peekOne@ has now taken over.+peekPtrArray :: (Ptr a -> IO b) -> Ptr CUInt -> Ptr (Ptr (Ptr a)) -> IO [b]+peekPtrArray peekOne pl pp = do+  l <- peek pl+  p <- peek pp+  ptrs <- peekArray (fromIntegral l) p+  xs <- mapM peekOne ptrs+  xs <$ qlFreePointerArray (castPtr p)+ fromEnumQuantity :: (Enum a, Integral b, Integral c) => (b, a) -> (CInt, c) fromEnumQuantity (x, u) = (fromIntegral x, fromIntegral $ fromEnum u) @@ -303,7 +346,18 @@ fromEnumC :: (Enum a, Integral b) => a -> b fromEnumC = fromIntegral . fromEnum +-- output-direction counterpart to 'fromEnumC', for a {#fun#} returning a bare enum value+-- (not through a pointer out-param, see 'peekEnum' for that case) across the same module-dep boundary+toEnumC :: (Enum a, Integral b) => b -> a+toEnumC = toEnum . fromIntegral+ uncurryNested :: (a -> b -> c -> d) -> (a, (b, c)) -> d uncurryNested f (x, (y, z)) = f x y z++-- |'Prelude' only goes up to 'zipWith3'; this fills the gap for unpacking a C-side+-- structure-of-parallel-arrays result into one Haskell record/tuple per element.+zipWith6 :: (a -> b -> c -> d -> e -> f -> g) -> [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]+zipWith6 f (a:as) (b:bs) (c:cs) (d:ds) (e:es) (g:gs) = f a b c d e g : zipWith6 f as bs cs ds es gs+zipWith6 _ _ _ _ _ _ _ = []  -- vim: set ff=unix ts=8 sts=2 sw=2 et:
+ QuantLib/Internal/Common.chs view
@@ -0,0 +1,972 @@+{-# LANGUAGE TemplateHaskell, StandaloneDeriving, EmptyDataDecls #-}+-- internal utilities to convert special enums: either complex ones or represented as QuantLib objects that I didn't want to expose so I represented them as ADTs+{-# OPTIONS_GHC -Wno-unused-top-binds #-}+module QuantLib.Internal.Common+  (+    qlInterpolation+  , qlInterpolation'+  , Approximation(..)+  , Interpolation(..)+  , Interpolation2D(..)++  , ExerciseType(..)+  , Exercise(..)+  , QlExercise+  , EuropeanExercise(..)+  , BermudanExercise(..)+  , QlEuropeanExercise+  , QlBermudanExercise+  , SwingExercise(..)+  , QlSwingExercise++  , OptionType(..)+  , PositionType(..)+  , BondPriceType(..)++  , StrikedPayoff(..)+  , PlainVanillaPayoff(..)+  , PercentageStrikePayoff(..)+  , QlPlainVanillaPayoff+  , QlPercentageStrikePayoff+  , QlStrikedTypePayoff+  , Payoff(..)+  , QlPayoff+  , BasketPayoff(..)+  , QlBasketPayoff+  , TypePayoff(..)+  , QlTypePayoff++  , CallabilityType(..)+  , Callability(..)+  , QlCallability++  , Claim(..)+  , QlClaim+  , withClaim++  , FittingMethod(..)+  , QlFittedBondDiscountCurveFittingMethod+  , withFittedBondDiscountCurveFittingMethod++  , FdmSchemeType(..)+  , FdmScheme(..)+  , QlFdmSchemeDesc+  , withFdmSchemeDesc++  , CPIInterpolationType(..)++  , Constraint(..)+  , QlConstraint+  , withConstraint+  , withMaybeConstraint+  , OptimizationMethod(..)+  , QlOptimizationMethod+  , withOptimizationMethod+  , EndCriteria(..)+  , QlEndCriteria+  , withEndCriteria++  , QlRounding+  , RoundingType(..)+  , Rounding(..)+  , withRounding+  , withMaybeRounding++  , withCallability+  , withCallabilityArray++  , QlLmVolatilityModel+  , LmVolatilityModel(..)+  , QlLmCorrelationModel+  , LmCorrelationModel(..)+  , withLmCorrelationModel+  , withLmVolatilityModel++  , TimeUnit(..)+  , BusinessDayConvention(..)++  , withEuropeanExercise+  , withSwingExercise+  , withBermudanExercise+  , withExercise+  , withPercentageStrikePayoff+  , withPlainVanillaPayoff+  , withStrikedPayoff+  , withTypePayoff+  , withBasketPayoff+  , withPayoff++  , strikedPayoff+  , percentageStrikePayoff+  , plainVanillaPayoff+  , swingExercise++  , CalibrationBasketType(..)++  , UnitOfMeasureType(..)+  , PaymentTermEventType(..)+  , PricingErrorLevel(..)+  , peekPricingErrorLevelArray+  , DeliverySchedule(..)+  , QuantityPeriodicity(..)++  , AdditionalResultType(..)+  , AdditionalResultVal(..)+  , RawResultPtr+  , RawResult(..)+  , convertResult+  , peekAdditionalResults+  ) where+import Foreign.Ptr(Ptr, nullPtr, castPtr)+import Foreign.C.Types(CUInt, CInt, CDouble)+import Foreign.C.String(CString, peekCString)+import Foreign.Storable(Storable(..))+import Foreign.Marshal.Utils(withMany)+import Foreign.Marshal.Array(withArray, peekArray)+import Control.Exception(finally)++import QuantLib.Internal+import QuantLib.Internal.Type hiding(ptr)+import QuantLib.Internal.Syntax++#include "qlTypesC2HS.h"+#include "ql.h"++#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++-- this enum is not special, just used in many places and was put here to avoid cyclic dependencies+{#enum TimeUnit{} deriving(Show, Eq, Bounded)#}+-- moved from QuantLib.Time.Calendar, its "natural" home, for the same reason as TimeUnit above --+-- needed directly here for RebatedExercise's rebatePaymentConvention param. Like TimeUnit, every+-- cross-module use marshals through a manual fromEnumC/toEnumC/fromMaybeEnum function rather than+-- a bare c2hs backtick spec: a bare `` `BusinessDayConvention' `` needs the type's own module's+-- .chi already built, which this other-modules-listed module isn't guaranteed to have by the time+-- an early exposed-modules file (e.g. QuantLib.Time.Calendar itself) is processed.+{#enum BusinessDayConvention{} deriving(Show, Eq)#}+{#enum ApproximationType{} add prefix="Approximation__" deriving(Show, Eq)#}+{#enum InterpolationType{} add prefix="Interpolation" deriving(Show, Eq)#}+-- 2-D interpolators for a BlackVarianceSurface. Unlike InterpolationType/ApproximationType+-- above (merged into the public Interpolation ADT by deriveCrossEnum), this enum is itself the+-- public type: setInterpolation on a surface is a member template over a default-constructed+-- interpolator, so there is no approximator to pair it with. Declared here rather than in+-- QuantLib.TermStructure.Volatility for the usual cross-module {#import#} ordering reason.+{#enum Interpolation2D{} deriving (Show, Eq, Bounded)#}+{#enum ExerciseType{} add prefix = "ExerciseType" deriving (Show, Eq)#}+{#enum OptionType{} deriving (Show, Eq)#}+{#enum PositionType{} deriving (Show, Eq)#}+{#enum BondPriceType{} deriving (Show, Eq)#}+{#enum CallabilityType{} add prefix="Callability" deriving(Show, Eq)#}+{#enum FdmSchemeType{} deriving(Show, Eq)#}+{#enum RoundingType{} deriving (Show, Eq)#}+-- experimental/commodities: cross-cutting the same way TimeUnit is (UnitOfMeasureType is used by+-- both UnitOfMeasure itself and, in a later stage, CommodityPricingHelper/EnergyCommodity).+-- Quantity's C tag is renamed QuantityUnit in cbits/qlEnumC2HS.h to avoid colliding with the+-- Quantity class bound in QuantLib.Commodity.+{#enum UnitOfMeasureType{} deriving (Show, Eq, Bounded)#}+{#enum PaymentTermEventType{} deriving (Show, Eq, Bounded)#}+-- experimental/commodities/commodity.hpp (PricingError::Level) and+-- experimental/commodities/energycommodity.hpp (EnergyCommodity::DeliverySchedule,+-- EnergyCommodity::QuantityPeriodicity), homed here for the same cross-cutting reason as+-- UnitOfMeasureType above (used by both EnergyCommodity's leaf constructors and+-- CommodityPricingHelper::createPricingPeriods, both in QuantLib.Instrument.Energy -- a later+-- stage than this module).+{#enum PricingErrorLevel{} deriving (Show, Eq, Bounded)#}+peekPricingErrorLevelArray :: Ptr CUInt -> Ptr (Ptr CInt) -> IO [PricingErrorLevel]+peekPricingErrorLevelArray = peekIntArray' toEnumC+-- Confirmed clash (a real one, caught by the build, not assumed): 4 of DeliverySchedule's 8 tags+-- (Daily/Weekly/Monthly/Quarterly) collide with QuantLib.Time.Schedule's own Frequency enum, whose+-- module this file is imported into unqualified. Prefixed Haskell-side only (c2hs's own "add+-- prefix", not a cbits/qlEnumC2HS.h rename) -- same targeted-rename convention as+-- UnitOfMeasureType's Quantity->QuantityUnit above, not a blanket defensive prefix.+{#enum DeliverySchedule{} add prefix = "Delivery" deriving (Show, Eq, Bounded)#}+{#enum QuantityPeriodicity{} deriving (Show, Eq, Bounded)#}+-- flat/linear interpolation of a CPI index between its publication dates -- skips the+-- deprecated AsIndex upstream case, so cbits/qlEnumObjects.h's values (and thus this+-- c2hs-derived enum's fromEnum) start at 1, not 0; see that header's comment for why a+-- renumbered-from-0 enum here would silently alias to the wrong upstream case. Declared here+-- (not in QuantLib.TermStructure.Inflation, its "natural" home) for the same reason as+-- TimeUnit above: needed by several modules whose build order can't all safely {#import#} that+-- module (built before it, or -- for QuantLib.TermStructure.Yield -- mutually dependent with+-- it already).+{#enum CPIInterpolationType{} deriving (Show, Eq, Bounded)#}+{#enum CalibrationBasketType{} deriving (Show, Eq, Bounded)#}++-- Payoff/Exercise pointer hierarchy: the Finalizable/Upcastable instances and raw phantom+-- tags (CPayoff' etc.) live in QuantLib.Internal.Type alongside every other class hierarchy;+-- these are just c2hs-local aliases so {#fun#} specs below can keep writing the bare `QlX'+-- names, resolving to a raw, unwrapped Ptr (no auto-generated foreign-pointer code) since+-- construction/upcasting is handled by hand in the with* functions further down.+type QlPayoff = Ptr CPayoff'+type QlBasketPayoff = Ptr CBasketPayoff'+type QlTypePayoff = Ptr CTypePayoff'+type QlStrikedTypePayoff = Ptr CStrikedTypePayoff'+type QlPercentageStrikePayoff = Ptr CPercentageStrikePayoff'+type QlPlainVanillaPayoff = Ptr CPlainVanillaPayoff'+type QlExercise = Ptr CExercise'+type QlEuropeanExercise = Ptr CEuropeanExercise'+type QlAmericanExercise = Ptr CAmericanExercise'+type QlSwingExercise = Ptr CSwingExercise'+type QlBermudanExercise = Ptr CBermudanExercise'+type QlRebatedExercise = Ptr CRebatedExercise'+-- identity peek function: c2hs {#fun#} return specs always need a named out-marshaller,+-- even when (as here) construction should just hand back the raw, un-wrapped pointer.+peekPtr :: Ptr a -> IO (Ptr a)+peekPtr = pure+{#pointer *QlPayoff nocode#}+{#pointer *QlBasketPayoff nocode#}+{#pointer *QlTypePayoff nocode#}+{#pointer *QlStrikedTypePayoff nocode#}+{#pointer *QlPercentageStrikePayoff nocode#}+{#pointer *QlPlainVanillaPayoff nocode#}+{#pointer *QlExercise nocode#}+{#pointer *QlEuropeanExercise nocode#}+{#pointer *QlAmericanExercise nocode#}+{#pointer *QlSwingExercise nocode#}+{#pointer *QlBermudanExercise nocode#}+{#pointer *QlRebatedExercise nocode#}+{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *QlCallability foreign -> CQlCallability nocode#}+{#pointer *OptimizationMethod as QlOptimizationMethod foreign -> COptimizationMethod nocode#}+{#pointer *EndCriteria as QlEndCriteria foreign -> CEndCriteria nocode#}+{#pointer *Constraint as QlConstraint foreign -> CConstraint nocode#}+{#pointer *FdmSchemeDesc as QlFdmSchemeDesc foreign -> CFdmSchemeDesc nocode#}+{#pointer *FittedBondDiscountCurveFittingMethod as QlFittedBondDiscountCurveFittingMethod foreign -> CFittedBondDiscountCurveFittingMethod nocode#}+{#pointer *QlClaim as Claim foreign -> CQlClaim nocode#}+{#pointer *QlBond as Bond foreign -> CBond' nocode#}+{#pointer *QlLmCorrelationModel foreign -> CLmCorrelationModel nocode#}+{#pointer *QlLmVolatilityModel foreign -> CLmVolatilityModel nocode#}+{#pointer *Rounding as QlRounding foreign -> CRounding nocode#}++-- monotonic flag for CubicInterpolation::Spline/::Parabolic -- tells deriveCrossEnum to give+-- these two values a runtime Bool field instead of cross-producting named sub-values (same+-- pattern as Actual360Convention etc. in CalendarEnum.chs). Order matters here in a way it+-- doesn't for the ApproximationType enum itself: these two type synonyms (and ApproximationExtra+-- below) must be declared textually *above* the deriveCrossEnum splice, since a TH splice can+-- only see top-level declarations that already exist earlier in the same module -- classifySub's+-- lookupTypeName would silently miss them (falling back to NoSub, dropping the Bool field) if+-- they were moved below the splice.+type NaturalSplineMonotonic = Bool+type ParabolicMonotonic = Bool++-- every Approximation case is driven by ApproximationType itself, so unlike+-- CalendarExtra/DayCounterExtra/IborExtra there are no non-enum-driven cases to add here+data ApproximationExtra++$(deriveCrossEnum CrossEnumSpec+    { crossTypeName = "Approximation"+    , crossMapperFn = "qlApproximation"+    , crossMainEnum = ''ApproximationType+    , crossSubSuffix = "Monotonic"+    , crossExtraType = ''ApproximationExtra+    })++deriving instance Show Approximation+deriving instance Eq Approximation++-- Remaining cpp<->hs lockstep, unlike CalendarConstructor/DayCounterConstructor/IborConstructor:+-- those own a full C-side array/table, so *every* lockstep edit needed for a new value stays+-- inside cbits/. Approximation/Interpolation instead get dispatched via symbolic switch-case on+-- the shared enum (cbits/qlTermStructure.cpp's setInterpolation, and ~18 duplicated+-- switch(interpolator){switch(approximator){...}} sites in cbits/qlTermStructureAux.cpp, one per+-- PiecewiseYieldCurve trait/interpolator instantiation). Adding a new ApproximationType/+-- InterpolationType value to cbits/qlEnumObjects.h is zero-touch here on the Haskell side+-- (deriveCrossEnum picks it up automatically, defaulting to a nullary constructor unless a+-- <Value>Monotonic marker is added above), but each cbits switch still needs a matching+-- `case hasquant::NewValue:` by hand -- a missed one isn't a compile error, just a runtime+-- QL_FAIL("Unsupported ..."), exactly the pre-existing gap Abcd fell into (see the comment next+-- to setInterpolation's default case in qlTermStructure.cpp).++qlInterpolation :: Interpolation -> (Int, (Int, Int))+qlInterpolation BackwardFlat = (fromEnum InterpolationBackwardFlat, (0, 0))+qlInterpolation ForwardFlat = (fromEnum InterpolationForwardFlat, (0, 0))+qlInterpolation Linear = (fromEnum InterpolationLinear, (0, 0))+qlInterpolation LogLinear = (fromEnum InterpolationLogLinear, (0, 0))+qlInterpolation (Cubic x) = (fromEnum InterpolationCubic, qlApproximation x)+qlInterpolation (LogCubic x) = (fromEnum InterpolationLogCubic, qlApproximation x)+qlInterpolation Abcd = (fromEnum InterpolationAbcd, (0, 0))++qlInterpolation' :: Maybe Interpolation -> (Int, (Int, Int))+qlInterpolation' Nothing = (fromIntegral qlNullInteger, (0, 0))+qlInterpolation' (Just i) = qlInterpolation i++data Interpolation =+  BackwardFlat+  | ForwardFlat+  | Linear+  | LogLinear+  | Cubic !Approximation+  | LogCubic !Approximation+  | Abcd+  deriving (Show, Eq)++data EuropeanExercise = EuropeanExercise Day+-- | Use 'swingExerice' to construct 'Exercise'+data SwingExercise =+    SwingListExercise ![(Day, Word)] -- ^(dates, seconds)+    | SwingIntervalExercise !Day !Day !Word -- ^stepSizeSecs+data BermudanExercise =+    BermudanExercise ![Day] !Bool+    | Swing SwingExercise++-- | > Exercise+-- >  American+-- >  Early+-- >  Vanilla+-- >  EuropeanExercise+-- >  BermudanExercise+-- >    SwingExercise+-- >  Rebated (wraps another Exercise)+data Exercise =+    American+      !(Maybe Day) -- ^earliestDate+      !Day -- ^latestDate+      !Bool -- ^paoffAtExpiry+    | Early !ExerciseType !Bool+    | Vanilla !ExerciseType+    | European !EuropeanExercise+    | Bermudan !BermudanExercise+    | Rebated+        !Exercise -- ^wrapped exercise+        !Double -- ^rebate+        !Word -- ^rebateSettlementDays+        !Calendar -- ^rebatePaymentCalendar+        !BusinessDayConvention -- ^rebatePaymentConvention++{#fun qlExercise{`ExerciseType',preErrorCheck-`String'errorCheck*-}->`QlExercise'peekPtr*#}+{#fun qlAmericanExercise{withDay*`Day',withDay*`Day',`Bool',preErrorCheck-`String'errorCheck*-}->`QlAmericanExercise'peekPtr*#}+{#fun qlAmericanExercise1{withDay*`Day',`Bool',preErrorCheck-`String'errorCheck*-}->`QlAmericanExercise'peekPtr*#}+{#fun qlBermudanExercise{withDayArray*`[Day]'&,`Bool',preErrorCheck-`String'errorCheck*-}->`QlBermudanExercise'peekPtr*#}+{#fun qlEarlyExercise{`ExerciseType',`Bool',preErrorCheck-`String'errorCheck*-}->`QlExercise'peekPtr*#}+{#fun qlEuropeanExercise{withDay*`Day',preErrorCheck-`String'errorCheck*-}->`QlEuropeanExercise'peekPtr*#}+{#fun qlSwingExercise{withDayArray*`[Day]'&,withIntArray*`[Word]'&,preErrorCheck-`String'errorCheck*-}->`QlSwingExercise'peekPtr*#}+{#fun qlSwingExercise1{withDay*`Day',withDay*`Day',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlSwingExercise'peekPtr*#}+{#fun qlRebatedExercise{`QlExercise',`Double',fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`QlRebatedExercise'peekPtr*#}++withEuropeanExercise :: EuropeanExercise -> (QlEuropeanExercise -> IO a) -> IO a+withEuropeanExercise (EuropeanExercise d) f = qlEuropeanExercise d >>= newCastForeignPtr >>= flip withGenForeignPtr f++withSwingExercise :: SwingExercise -> (QlSwingExercise -> IO a) -> IO a+withSwingExercise (SwingListExercise ds) f = uncurry qlSwingExercise (unzip ds) >>= newCastForeignPtr >>= flip withGenForeignPtr f+withSwingExercise (SwingIntervalExercise d1 d2 s) f = qlSwingExercise1 d1 d2 s >>= newCastForeignPtr >>= flip withGenForeignPtr f++withBermudanExercise :: BermudanExercise -> (QlBermudanExercise -> IO a) -> IO a+withBermudanExercise (BermudanExercise d p) f = qlBermudanExercise d p >>= newCastForeignPtr >>= flip withGenForeignPtr f+withBermudanExercise (Swing e) f = withSwingExercise e (\sp -> upcast sp >>= \bp -> f bp `finally` freeUpcast bp)++withExercise :: Exercise -> (QlExercise -> IO a) -> IO a+withExercise (American Nothing d p) f = qlAmericanExercise1 d p >>= newGenForeignPtr >>= flip withGenForeignPtr f+withExercise (American (Just d0) d p) f = qlAmericanExercise d0 d p >>= newGenForeignPtr >>= flip withGenForeignPtr f+withExercise (Early t p) f = qlEarlyExercise t p >>= newCastForeignPtr >>= flip withGenForeignPtr f+withExercise (Vanilla t) f = qlExercise t >>= newCastForeignPtr >>= flip withGenForeignPtr f+withExercise (European e) f = withEuropeanExercise e (\ep -> upcast ep >>= \xp -> f xp `finally` freeUpcast xp)+withExercise (Bermudan e) f = withBermudanExercise e (\bp -> upcast bp >>= \xp -> f xp `finally` freeUpcast xp)+withExercise (Rebated e rebate days cal bdc) f = withExercise e (\ep -> qlRebatedExercise ep rebate days cal bdc >>= newGenForeignPtr >>= flip withGenForeignPtr f)++-- | use 'percentageStrikePayoff' to construct 'Payoff'+data PercentageStrikePayoff = PercentageStrikePayoff+      !OptionType -- ^type+      !Double -- ^moneyness++-- | use 'plainVanillaPayoff' to construct 'Payoff'+data PlainVanillaPayoff = PlainVanillaPayoff+      !OptionType -- ^type+      !Double -- ^strike++-- | use 'strikedPayoff' to construct 'Payoff'+data StrikedPayoff =+  AssetOrNothing+    !OptionType -- ^type+    !Double -- ^strike+  | CashOrNothing+      !OptionType -- ^type+      !Double -- ^strike+      !Double -- ^cashPayoff+  | Gap+      !OptionType -- ^type+      !Double -- ^strike+      !Double -- ^secondStrike+  | PercentageStrike !PercentageStrikePayoff+  | PlainVanilla !PlainVanillaPayoff+  | SuperFund+      !Double -- ^strike+      !Double -- ^secondStrike+  | SuperSharePayoff+      !Double -- ^strike+      !Double -- ^secondStrike+      !Double -- ^cashPayoff++withPercentageStrikePayoff :: PercentageStrikePayoff -> (QlPercentageStrikePayoff -> IO a) -> IO a+withPercentageStrikePayoff (PercentageStrikePayoff t m) f = qlPercentageStrikePayoff t m >>= newCastForeignPtr >>= flip withGenForeignPtr f++withPlainVanillaPayoff :: PlainVanillaPayoff -> (QlPlainVanillaPayoff -> IO a) -> IO a+withPlainVanillaPayoff (PlainVanillaPayoff t s) f = qlPlainVanillaPayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f++withStrikedPayoff :: StrikedPayoff -> (QlStrikedTypePayoff -> IO a) -> IO a+withStrikedPayoff (AssetOrNothing t s) f = qlAssetOrNothingPayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f+withStrikedPayoff (CashOrNothing t s c) f = qlCashOrNothingPayoff t s c >>= newCastForeignPtr >>= flip withGenForeignPtr f+withStrikedPayoff (Gap t s ss) f = qlGapPayoff t s ss >>= newCastForeignPtr >>= flip withGenForeignPtr f+withStrikedPayoff (PercentageStrike p) f = withPercentageStrikePayoff p (\pp -> upcast pp >>= \sp -> f sp `finally` freeUpcast sp)+withStrikedPayoff (PlainVanilla p) f = withPlainVanillaPayoff p (\pp -> upcast pp >>= \sp -> f sp `finally` freeUpcast sp)+withStrikedPayoff (SuperFund s ss) f = qlSuperFundPayoff s ss >>= newCastForeignPtr >>= flip withGenForeignPtr f+withStrikedPayoff (SuperSharePayoff s ss c) f = qlSuperSharePayoff s ss c >>= newCastForeignPtr >>= flip withGenForeignPtr f++data TypePayoff = Striked !StrikedPayoff+  | Floating !OptionType -- ^type+data BasketPayoff =+    Average+      !Payoff -- ^p+      !Word -- ^n+  | AverageMultiple+      !Payoff -- ^p+      ![Double] -- ^a+  | Max+      !Payoff -- ^p+  | Min+      !Payoff -- ^p+  | Spread+      !Payoff -- ^p++withTypePayoff :: TypePayoff -> (QlTypePayoff -> IO a) -> IO a+withTypePayoff (Floating t) f = qlFloatingTypePayoff t >>= newCastForeignPtr >>= flip withGenForeignPtr f+withTypePayoff (Striked s) f = withStrikedPayoff s (\sp -> upcast sp >>= \tp -> f tp `finally` freeUpcast tp)++withBasketPayoff :: BasketPayoff -> (QlBasketPayoff -> IO a) -> IO a+withBasketPayoff (Average p n) f = withPayoff p (\pp -> qlAverageBasketPayoff pp n >>= newCastForeignPtr >>= flip withGenForeignPtr f)+withBasketPayoff (AverageMultiple p a) f = withPayoff p (\pp -> qlAverageBasketPayoff1 pp a >>= newCastForeignPtr >>= flip withGenForeignPtr f)+withBasketPayoff (Max p) f = withPayoff p (\pp -> qlMaxBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)+withBasketPayoff (Min p) f = withPayoff p (\pp -> qlMinBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)+withBasketPayoff (Spread p) f = withPayoff p (\pp -> qlSpreadBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)++-- | > Payoff+-- >  DoubleStickyRatchet+-- >  ForwardType+-- >  RatchettMax+-- >  RatchetMin+-- >  StickyMax+-- >  StickyMin+-- >  Sticky+-- >  TypePayoff+-- >    Floating+-- >    Striked+-- >      AssetOrNothing+-- >      CashOrNothing+-- >      Gap+-- >      PercentageStrike+-- >      PlainVanilla+-- >      SuperFund+-- >      SuperSharePayoff+-- >  BasketPayoff+-- >    Average+-- >    AverageMultiple+-- >    Max+-- >    Min+-- >    Spread+data Payoff =+    DoubleStickyRatchet+      !Double -- ^type1+      !Double -- ^type2+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^gearing3+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^spread3+      !Double -- ^initialValue1+      !Double -- ^initialValue2+      !Double -- ^accrualFactor+  | ForwardType+      !PositionType -- ^type+      !Double -- ^strike+  | RatchetMax+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^gearing3+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^spread3+      !Double -- ^initialValue1+      !Double -- ^initialValue2+      !Double -- ^accrualFactor+  | RatchetMin+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^gearing3+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^spread3+      !Double -- ^initialValue1+      !Double -- ^initialValue2+      !Double -- ^accrualFactor+  | Ratchet+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^initialValue+      !Double -- ^accrualFactor+  | StickyMax+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^gearing3+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^spread3+      !Double -- ^initialValue1+      !Double -- ^initialValue2+      !Double -- ^accrualFactor+  | StickyMin+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^gearing3+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^spread3+      !Double -- ^initialValue1+      !Double -- ^initialValue2+      !Double -- ^accrualFactor+  | Sticky+      !Double -- ^gearing1+      !Double -- ^gearing2+      !Double -- ^spread1+      !Double -- ^spread2+      !Double -- ^initialValue+      !Double -- ^accrualFactor+  | Type !TypePayoff+  | Basket !BasketPayoff+++{#fun qlAssetOrNothingPayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}+{#fun qlAverageBasketPayoff{`QlPayoff',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}+{#fun qlCashOrNothingPayoff{`OptionType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}+{#fun qlDoubleStickyRatchetPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlFloatingTypePayoff{`OptionType',preErrorCheck-`String'errorCheck*-}->`QlTypePayoff'peekPtr*#}+{#fun qlForwardTypePayoff{`PositionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlGapPayoff{`OptionType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}+{#fun qlMaxBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}+{#fun qlMinBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}+{#fun qlPercentageStrikePayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPercentageStrikePayoff'peekPtr*#}+{#fun qlPlainVanillaPayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPlainVanillaPayoff'peekPtr*#}+{#fun qlRatchetMaxPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlRatchetMinPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlRatchetPayoff{`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlSpreadBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}+{#fun qlStickyMaxPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlStickyMinPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlStickyPayoff{`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}+{#fun qlSuperFundPayoff{`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}+{#fun qlSuperSharePayoff{`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}+{#fun qlAverageBasketPayoff1{`QlPayoff',withDoubleArray*`[Double]'&,preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}++withPayoff :: Payoff -> (QlPayoff -> IO a) -> IO a+withPayoff (DoubleStickyRatchet t1 t2 g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlDoubleStickyRatchetPayoff t1 t2 g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (ForwardType t s) f = qlForwardTypePayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (RatchetMax g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlRatchetMaxPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (RatchetMin g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlRatchetMinPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (Ratchet g1 g2 s1 s2 i a) f = qlRatchetPayoff g1 g2 s1 s2 i a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (StickyMax g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlStickyMaxPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (StickyMin g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlStickyMinPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (Sticky g1 g2 s1 s2 i a) f = qlStickyPayoff g1 g2 s1 s2 i a >>= newCastForeignPtr >>= flip withGenForeignPtr f+withPayoff (Type t) f = withTypePayoff t (\tp -> upcast tp >>= \pp -> f pp `finally` freeUpcast pp)+withPayoff (Basket b) f = withBasketPayoff b (\bp -> upcast bp >>= \pp -> f pp `finally` freeUpcast pp)++data Callability =+  Soft+    !(Double, BondPriceType)+    !Day+    !Double -- ^trigger+  | Callability+      !(Double, BondPriceType)+      !CallabilityType+      !Day++callability :: Callability -> IO (Standalone CQlCallability)+callability (Soft (p, t) d tg) = qlSoftCallability p t d tg+callability (Callability (p, t) ct d) = qlCallability p t ct d++newtype EnumMeta a b = EnumMeta (a -> IO (Standalone b))++withEnumType :: EnumMeta a b -> a -> (Ptr b -> IO c) -> IO c+withEnumType (EnumMeta t) x f = t x >>= (`withStandalone` f)++withMaybeEnumType :: EnumMeta a b -> Maybe a -> (Ptr b -> IO c) -> IO c+withMaybeEnumType (EnumMeta t) x f = maybe (f nullPtr) (\xx -> t xx >>= (`withStandalone` f)) x++withEnumTypeArray :: EnumMeta a b -> [a] -> ((CUInt, Ptr (Ptr b)) -> IO c) -> IO c+withEnumTypeArray m x f = withMany (withEnumType m) x (`withArray` (\px -> f (fromIntegral $ length x, px)))++callabilityMeta :: EnumMeta Callability CQlCallability+callabilityMeta = EnumMeta callability++withCallability :: Callability -> (Ptr CQlCallability -> IO a) -> IO a+withCallability = withEnumType callabilityMeta++withCallabilityArray :: [Callability] -> ((CUInt, Ptr (Ptr CQlCallability)) -> IO c) -> IO c+withCallabilityArray = withEnumTypeArray callabilityMeta++constraintMeta :: EnumMeta Constraint CConstraint+constraintMeta = EnumMeta constraint++roundingMeta :: EnumMeta Rounding CRounding+roundingMeta = EnumMeta rounding++withMaybeConstraint :: Maybe Constraint -> (Ptr CConstraint -> IO a) -> IO a+withMaybeConstraint = withMaybeEnumType constraintMeta++withMaybeRounding :: Maybe Rounding -> (Ptr CRounding -> IO a) -> IO a+withMaybeRounding = withMaybeEnumType roundingMeta++withConstraint :: Constraint -> (Ptr CConstraint -> IO a) -> IO a+withConstraint = withEnumType constraintMeta++withRounding :: Rounding -> (Ptr CRounding -> IO a) -> IO a+withRounding = withEnumType roundingMeta++fittedBondDiscountFittingMethodMeta :: EnumMeta FittingMethod CFittedBondDiscountCurveFittingMethod+fittedBondDiscountFittingMethodMeta = EnumMeta fittingMethod++withFittedBondDiscountCurveFittingMethod :: FittingMethod -> (Ptr CFittedBondDiscountCurveFittingMethod -> IO a) -> IO a+withFittedBondDiscountCurveFittingMethod = withEnumType fittedBondDiscountFittingMethodMeta++endCriteriaMeta :: EnumMeta EndCriteria CEndCriteria+endCriteriaMeta = EnumMeta endCriteria++withEndCriteria :: EndCriteria -> (Ptr CEndCriteria -> IO a) -> IO a+withEndCriteria = withEnumType endCriteriaMeta++fdmSchemeDescMeta :: EnumMeta FdmScheme CFdmSchemeDesc+fdmSchemeDescMeta = EnumMeta fdmScheme++withFdmSchemeDesc :: FdmScheme -> (Ptr CFdmSchemeDesc -> IO a) -> IO a+withFdmSchemeDesc = withEnumType fdmSchemeDescMeta++optimizationMethodMeta :: EnumMeta OptimizationMethod COptimizationMethod+optimizationMethodMeta = EnumMeta optimizationMethod++withOptimizationMethod :: OptimizationMethod -> (Ptr COptimizationMethod -> IO a) -> IO a+withOptimizationMethod = withEnumType optimizationMethodMeta++-- Payoff/Exercise with* functions are now defined directly, near their ADTs, using+-- Upcastable/GenForeignPtr (see QuantLib.Internal.Type) instead of EnumMeta'/IsQlPayoff/IsQlExercise.++-- |callability leaving to the holder the possibility to convert+{#fun qlSoftCallability{`Double',`BondPriceType',withDay*`Day',`Double',preErrorCheck-`String'errorCheck*-}->`QlCallability'peekCallability*#}+{#fun qlCallability{`Double',`BondPriceType',`CallabilityType',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`QlCallability'peekCallability*#}++-- Every constructor below binds the QuantLib overload that omits the leading+-- optimizationMethod param (see the qlTermStructure.cpp comment above the+-- qlXxxFitting shims for why: OptimizationMethod's hasquant-side handle is a+-- raw, Haskell-finalized pointer, not a QlXxx shared_ptr box, and+-- FittedBondDiscountCurve additionally clones its fitting method -- passing+-- one through safely needs a real ownership-representation change).+data FittingMethod =+  CubicBSplines+    ![Double] -- ^knotVector (year fraction)+    !Bool -- ^constrainAtZero+    ![Double] -- ^weights+    ![Double] -- ^l2+    !Double -- ^minCutoffTime+    !Double -- ^maxCutoffTime+    !(Maybe Constraint)+  | ExponentialSplines+    !Bool -- ^constrainAtZero+    ![Double] -- ^weights+    ![Double] -- ^l2+    !Double -- ^minCutoffTime+    !Double -- ^maxCutoffTime+    !Word -- ^numCoeffs+    !(Maybe Double) -- ^fixedKappa+    !(Maybe Constraint)+  | NelsonSiegel+    ![Double] -- ^weights+    ![Double] -- ^l2+    !Double -- ^minCutoffTime+    !Double -- ^maxCutoffTime+    !(Maybe Constraint)+  | SimplePolynomial+    !Word -- ^degree+    !Bool -- ^constrainAtZero+    ![Double] -- ^weights+    ![Double] -- ^l2+    !Double -- ^minCutoffTime+    !Double -- ^maxCutoffTime+    !(Maybe Constraint)+  | Svensson+    ![Double] -- ^weights+    ![Double] -- ^l2+    !Double -- ^minCutoffTime+    !Double -- ^maxCutoffTime+    !(Maybe Constraint)++fittingMethod :: FittingMethod -> IO QlFittedBondDiscountCurveFittingMethod+fittingMethod (CubicBSplines k c w l2 mn mx cn) = qlCubicBSplinesFitting k c w l2 mn mx cn+fittingMethod (ExponentialSplines c w l2 mn mx n fk cn) = qlExponentialSplinesFitting c w l2 mn mx n fk cn+fittingMethod (NelsonSiegel w l2 mn mx cn) = qlNelsonSiegelFitting w l2 mn mx cn+fittingMethod (SimplePolynomial d c w l2 mn mx cn) = qlSimplePolynomialFitting d c w l2 mn mx cn+fittingMethod (Svensson w l2 mn mx cn) = qlSvenssonFitting w l2 mn mx cn++{#fun qlCubicBSplinesFitting{withDoubleArray*`[Double]'&,`Bool'+  ,withDoubleArray*`[Double]'& -- ^weights+  ,withDoubleArray*`[Double]'& -- ^l2+  ,`Double' -- ^minCutoffTime+  ,`Double' -- ^maxCutoffTime+  ,withMaybeConstraint*`Maybe Constraint'+  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}+{#fun qlExponentialSplinesFitting{`Bool'+  ,withDoubleArray*`[Double]'& -- ^weights+  ,withDoubleArray*`[Double]'& -- ^l2+  ,`Double' -- ^minCutoffTime+  ,`Double' -- ^maxCutoffTime+  ,fromIntegral`Word' -- ^numCoeffs+  ,fromMaybeDouble`Maybe Double' -- ^fixedKappa+  ,withMaybeConstraint*`Maybe Constraint'+  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}+{#fun qlNelsonSiegelFitting{withDoubleArray*`[Double]'& -- ^weights+  ,withDoubleArray*`[Double]'& -- ^l2+  ,`Double' -- ^minCutoffTime+  ,`Double' -- ^maxCutoffTime+  ,withMaybeConstraint*`Maybe Constraint'+  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}+{#fun qlSimplePolynomialFitting{fromIntegral`Word',`Bool'+  ,withDoubleArray*`[Double]'& -- ^weights+  ,withDoubleArray*`[Double]'& -- ^l2+  ,`Double' -- ^minCutoffTime+  ,`Double' -- ^maxCutoffTime+  ,withMaybeConstraint*`Maybe Constraint'+  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}+{#fun qlSvenssonFitting{withDoubleArray*`[Double]'& -- ^weights+  ,withDoubleArray*`[Double]'& -- ^l2+  ,`Double' -- ^minCutoffTime+  ,`Double' -- ^maxCutoffTime+  ,withMaybeConstraint*`Maybe Constraint'+  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}++data FdmScheme =+  FdmScheme+    !FdmSchemeType -- ^type+    !Double -- ^theta+    !Double -- ^mu+  | CraigSneyd+  | Douglas+  | ExplicitEuler+  | Hundsdorfer+  | ImplicitEuler+  | ModifiedCraigSneyd+  | ModifiedHundsdorfer++{#fun qlFdmSchemeDesc{`FdmSchemeType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescCraigSneyd{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescDouglas{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescExplicitEuler{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescHundsdorfer{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescImplicitEuler{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescModifiedCraigSneyd{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}+{#fun qlFdmSchemeDescModifiedHundsdorfer{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}++fdmScheme :: FdmScheme -> IO QlFdmSchemeDesc+fdmScheme (FdmScheme t th mu) = qlFdmSchemeDesc t th mu+fdmScheme CraigSneyd = qlFdmSchemeDescCraigSneyd+fdmScheme Douglas = qlFdmSchemeDescDouglas+fdmScheme ExplicitEuler = qlFdmSchemeDescExplicitEuler+fdmScheme Hundsdorfer = qlFdmSchemeDescHundsdorfer+fdmScheme ImplicitEuler = qlFdmSchemeDescImplicitEuler+fdmScheme ModifiedCraigSneyd = qlFdmSchemeDescModifiedCraigSneyd+fdmScheme ModifiedHundsdorfer = qlFdmSchemeDescModifiedHundsdorfer++data Constraint =+  Boundary+    !Double -- ^low+    !Double -- ^high+  | Composite+    !Constraint -- ^c1+    !Constraint -- ^c2+  | NoConstraint+  | PositiveConstraint++constraint :: Constraint -> IO QlConstraint+constraint (Boundary l h) = qlBoundaryConstraint l h+constraint (Composite c1 c2) = qlCompositeConstraint c1 c2+constraint NoConstraint = qlNoConstraint+constraint PositiveConstraint = qlPositiveConstraint++{#fun qlBoundaryConstraint{`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}+{#fun qlCompositeConstraint{withConstraint*`Constraint',withConstraint*`Constraint',preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}+{#fun qlNoConstraint{preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}+{#fun qlPositiveConstraint{preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}++data OptimizationMethod =+  LevenbergMarquardt+    !Double -- ^epsfcn+    !Double -- ^xtol+    !Double -- ^gtol+    !Bool -- ^useCostFunctionsJacobian+  | Simplex !Double -- ^lambda, characteristic length++optimizationMethod :: OptimizationMethod -> IO QlOptimizationMethod+optimizationMethod (LevenbergMarquardt e x g j) = qlLevenbergMarquardt e x g j+optimizationMethod (Simplex l) = qlSimplex l+{#fun qlLevenbergMarquardt{`Double',`Double',`Double',`Bool',preErrorCheck-`String'errorCheck*-}->`QlOptimizationMethod'peekOptimizationMethod*#}+{#fun qlSimplex{`Double',preErrorCheck-`String'errorCheck*-}->`QlOptimizationMethod'peekOptimizationMethod*#}++data EndCriteria =+  EndCriteria+    !Word -- ^maxIterations+    !Word -- ^maxStationaryStateIterations+    !Double -- ^rootEpsilon+    !Double -- ^functionEpsilon+    !Double -- ^gradientNormEpsilon++endCriteria :: EndCriteria -> IO QlEndCriteria+endCriteria (EndCriteria m1 m2 e f g) = qlEndCriteria m1 m2 e f g+{#fun qlEndCriteria{fromIntegral`Word',fromIntegral`Word',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlEndCriteria'peekEndCriteria*#}++data Rounding = NoRounding+  | Rounding+    !Int -- ^precision+    !RoundingType+    !Int -- ^digit+  deriving (Show, Eq)++rounding :: Rounding -> IO QlRounding+rounding NoRounding = qlRounding+rounding (Rounding p t d) = qlRounding1 p t d++{#fun qlRounding{preErrorCheck-`String'errorCheck*-}->`QlRounding'peekRounding*#}+{#fun qlRounding1{`Int',`RoundingType',`Int',preErrorCheck-`String'errorCheck*-}->`QlRounding'peekRounding*#}++data LmCorrelationModel = ConstWrapperCorrelation LmCorrelationModel+  | ExponentialCorrelation Word -- ^size+    !Double -- ^rho+  | LinearExponentialCorrelation Word -- ^size+    !Double -- ^rho+    !Double -- ^beta+    !Word -- ^factors+  deriving (Show, Eq)++{#fun qlLmConstWrapperCorrelationModel{withStandalone*`QlLmCorrelationModel',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}+{#fun qlLmExponentialCorrelationModel{fromIntegral`Word',`Double',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}+{#fun qlLmLinearExponentialCorrelationModel{fromIntegral`Word',`Double',`Double',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}++correlationModel :: LmCorrelationModel -> IO QlLmCorrelationModel+correlationModel (ConstWrapperCorrelation m) = correlationModel m >>= qlLmConstWrapperCorrelationModel+correlationModel (ExponentialCorrelation s r) = qlLmExponentialCorrelationModel s r+correlationModel (LinearExponentialCorrelation s r b f) = qlLmLinearExponentialCorrelationModel s r b f++correlationModelMeta :: EnumMeta LmCorrelationModel CLmCorrelationModel+correlationModelMeta = EnumMeta correlationModel++withLmCorrelationModel :: LmCorrelationModel -> (Ptr CLmCorrelationModel -> IO a) -> IO a+withLmCorrelationModel = withEnumType correlationModelMeta++data LmVolatilityModel = ConstWrapperVolatility LmVolatilityModel+  | FixedVolatility ![Double] ![Double]+  | LinearExponentialVolatility ![Double] -- ^fixing times+    !Double -- ^a+    !Double -- ^b+    !Double -- ^c+    !Double -- ^d+  deriving (Show, Eq)++{#fun qlLmConstWrapperVolatilityModel{withStandalone*`QlLmVolatilityModel',preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}+{#fun qlLmFixedVolatilityModel{withDoubleArray*`[Double]'&,withDoubleArray*`[Double]'&,preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}+{#fun qlLmLinearExponentialVolatilityModel{withDoubleArray*`[Double]'&,`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}++volatilityModel :: LmVolatilityModel -> IO QlLmVolatilityModel+volatilityModel (ConstWrapperVolatility m) = volatilityModel m >>= qlLmConstWrapperVolatilityModel+volatilityModel (FixedVolatility d1 d2) = qlLmFixedVolatilityModel d1 d2+volatilityModel (LinearExponentialVolatility s a b c d) = qlLmLinearExponentialVolatilityModel s a b c d++volatilityModelMeta :: EnumMeta LmVolatilityModel CLmVolatilityModel+volatilityModelMeta = EnumMeta volatilityModel++withLmVolatilityModel :: LmVolatilityModel -> (Ptr CLmVolatilityModel -> IO a) -> IO a+withLmVolatilityModel = withEnumType volatilityModelMeta++data Claim = FaceValue | FaceValueAccrual Bond+claimMeta :: EnumMeta Claim CQlClaim+claimMeta = EnumMeta claim++withClaim :: Claim -> (Ptr CQlClaim -> IO a) -> IO a+withClaim = withEnumType claimMeta++claim :: Claim -> IO QlClaim+claim FaceValue = qlFaceValueClaim+claim (FaceValueAccrual b) = qlFaceValueAccrualClaim b++-- |Claim on a notional+{#fun qlFaceValueClaim{preErrorCheck-`String'errorCheck*-}->`QlClaim'peekClaim*#}++-- |Claim on the notional of a reference security, including accrual+{#fun qlFaceValueAccrualClaim{withBond*`Bond',preErrorCheck-`String'errorCheck*-}->`QlClaim'peekClaim*#}++strikedPayoff :: StrikedPayoff -> Payoff+strikedPayoff = Type . Striked++percentageStrikePayoff :: PercentageStrikePayoff -> Payoff+percentageStrikePayoff = Type . Striked . PercentageStrike++plainVanillaPayoff :: PlainVanillaPayoff -> Payoff+plainVanillaPayoff = Type . Striked . PlainVanilla++swingExercise :: SwingExercise -> Exercise+swingExercise = Bermudan . Swing++-- |One value from QuantLib's `Instrument::additionalResults()` map. QuantLib stores the map as+-- `ext::any`, so this Haskell view picks three concrete shapes -- `Real` (`Double`), `std::string`+-- (`String`), `std::vector<Real>` (`[Double]`) -- plus an `UnsupportedVal` fallback recording the+-- value's C++ RTTI type name, so no key is ever silently dropped or mislabelled.+data AdditionalResultVal = RealVal Double | StringVal String | RealVectorVal [Double] | UnsupportedVal String+  deriving (Show, Eq)++-- |Discriminants for `QlAdditionalResult.type`, bound from `enum AdditionalResultType` in+-- `cbits/qlInstrument.h` (read from the header, not hardcoded).+{#enum AdditionalResultType {} deriving (Show, Eq) #}++-- |Registers `struct QlAdditionalResult*` with c2hs as `RawResultPtr`, `nocode` since we supply+-- the Haskell type ourselves (below) rather than a c2hs-generated wrapper. This is what lets the+-- `additionalResults` `{#fun#}` binding (in `QuantLib.Instrument`)'s low-level array-of-structs+-- out-parameter (C type `struct QlAdditionalResult **`) be typed `Ptr RawResultPtr` =+-- `Ptr (Ptr RawResult)`, instead of defaulting to an opaque `Ptr (Ptr ())`.+{#pointer *QlAdditionalResult as RawResultPtr nocode#}+type RawResultPtr = Ptr RawResult++-- |One raw `QlAdditionalResult` entry, peeked field-by-field via c2hs `{#get#}` hooks. Its+-- `Storable` instance (`sizeOf`/`alignment` from `{#sizeof#}`/`{#alignof#}`, both read straight+-- from the C struct layout, not hand-computed) is what lets `peekStructArray`+-- (`QuantLib.Internal`) walk the C array via a plain `peekArray`, rather than hand-rolled pointer+-- arithmetic.+data RawResult = RawResult+  { rKey :: CString, rType :: CInt, rDval :: CDouble+  , rSval :: CString, rVarr :: Ptr CDouble, rVlen :: CUInt }++instance Storable RawResult where+  sizeOf _ = {#sizeof QlAdditionalResult #}+  alignment _ = {#alignof QlAdditionalResult #}+  peek p = RawResult <$> {#get QlAdditionalResult.key #} p+                      <*> {#get QlAdditionalResult.type #} p+                      <*> {#get QlAdditionalResult.dval #} p+                      <*> {#get QlAdditionalResult.sval #} p+                      <*> {#get QlAdditionalResult.varr #} p+                      <*> {#get QlAdditionalResult.vlen #} p+  poke = error "RawResult is peek-only (read from C, never constructed in Haskell)"++-- |Convert one raw entry into its keyed Haskell value. `sval`/`varr` are only read for the+-- discriminant that owns them; their buffers are released in bulk afterwards, by+-- `qlFreeAdditionalResults`, not per-field here.+convertResult :: RawResult -> IO (String, AdditionalResultVal)+convertResult r = do+  key <- peekCString (rKey r)+  val <- case toEnum (fromIntegral (rType r)) of+    AdditionalResultDouble -> return (RealVal (realToFrac (rDval r)))+    AdditionalResultString -> StringVal <$> peekCString (rSval r)+    AdditionalResultDoubleVector -> RealVectorVal . map realToFrac+                                       <$> peekArray (fromIntegral (rVlen r)) (rVarr r)+    AdditionalResultUnknown -> UnsupportedVal <$> peekCString (rSval r)+  return (key, val)++-- |Peek the C array of `QlAdditionalResult` into a keyed list, then release the whole array (keys,+-- `sval`/`varr` buffers, and the array itself) in one `qlFreeAdditionalResults` call.+peekAdditionalResults :: Ptr CUInt -> Ptr RawResultPtr -> IO [(String, AdditionalResultVal)]+peekAdditionalResults = peekStructArray convertResult (\l p -> qlFreeAdditionalResults l (castPtr p))++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
− QuantLib/Internal/Enum.chs
@@ -1,853 +0,0 @@-{-# LANGUAGE TemplateHaskell, StandaloneDeriving, EmptyDataDecls #-}--- internal utilities to convert special enums: either complex ones or represented as QuantLib objects that I didn't want to expose so I represented them as ADTs-{-# OPTIONS_GHC -Wno-unused-top-binds #-}-module QuantLib.Internal.Enum-  (-    qlInterpolation-  , qlInterpolation'-  , Approximation(..)-  , Interpolation(..)-  , Interpolation2D(..)--  , ExerciseType(..)-  , Exercise(..)-  , QlExercise-  , EuropeanExercise(..)-  , BermudanExercise(..)-  , QlEuropeanExercise-  , QlBermudanExercise-  , SwingExercise(..)-  , QlSwingExercise--  , OptionType(..)-  , PositionType(..)-  , BondPriceType(..)--  , StrikedPayoff(..)-  , PlainVanillaPayoff(..)-  , PercentageStrikePayoff(..)-  , QlPlainVanillaPayoff-  , QlPercentageStrikePayoff-  , QlStrikedTypePayoff-  , Payoff(..)-  , QlPayoff-  , BasketPayoff(..)-  , QlBasketPayoff-  , TypePayoff(..)-  , QlTypePayoff--  , CallabilityType(..)-  , Callability(..)-  , QlCallability--  , Claim(..)-  , QlClaim-  , withClaim--  , FittingMethod(..)-  , QlFittedBondDiscountCurveFittingMethod-  , withFittedBondDiscountCurveFittingMethod--  , FdmSchemeType(..)-  , FdmScheme(..)-  , QlFdmSchemeDesc-  , withFdmSchemeDesc--  , CPIInterpolationType(..)--  , Constraint(..)-  , QlConstraint-  , withConstraint-  , withMaybeConstraint-  , OptimizationMethod(..)-  , QlOptimizationMethod-  , withOptimizationMethod-  , EndCriteria(..)-  , QlEndCriteria-  , withEndCriteria--  , QlRounding-  , RoundingType(..)-  , Rounding(..)-  , withRounding-  , withMaybeRounding--  , withCallability-  , withCallabilityArray--  , QlLmVolatilityModel-  , LmVolatilityModel(..)-  , QlLmCorrelationModel-  , LmCorrelationModel(..)-  , withLmCorrelationModel-  , withLmVolatilityModel--  , TimeUnit(..)--  , withEuropeanExercise-  , withSwingExercise-  , withBermudanExercise-  , withExercise-  , withPercentageStrikePayoff-  , withPlainVanillaPayoff-  , withStrikedPayoff-  , withTypePayoff-  , withBasketPayoff-  , withPayoff--  , strikedPayoff-  , percentageStrikePayoff-  , plainVanillaPayoff-  , swingExercise-  ) where-import Foreign.Ptr(Ptr, nullPtr)-import Foreign.C.Types(CUInt)-import Foreign.Marshal.Utils(withMany)-import Foreign.Marshal.Array(withArray)-import Control.Exception(finally)--import QuantLib.Internal-import QuantLib.Internal.Type-import QuantLib.Internal.Syntax--#include "qlTypesC2HS.h"-#include "ql.h"--#include "qlEnumC2HS.h"-#include "qlEnumObjects.h"---- this enum is not special, just used in many places and was put here to avoid cyclic dependencies-{#enum TimeUnit{} deriving(Show, Eq, Bounded)#}-{#enum ApproximationType{} add prefix="Approximation__" deriving(Show, Eq)#}-{#enum InterpolationType{} add prefix="Interpolation" deriving(Show, Eq)#}--- 2-D interpolators for a BlackVarianceSurface. Unlike InterpolationType/ApproximationType--- above (merged into the public Interpolation ADT by deriveCrossEnum), this enum is itself the--- public type: setInterpolation on a surface is a member template over a default-constructed--- interpolator, so there is no approximator to pair it with. Declared here rather than in--- QuantLib.TermStructure.Volatility for the usual cross-module {#import#} ordering reason.-{#enum Interpolation2D{} deriving (Show, Eq, Bounded)#}-{#enum ExerciseType{} add prefix = "ExerciseType" deriving (Show, Eq)#}-{#enum OptionType{} deriving (Show, Eq)#}-{#enum PositionType{} deriving (Show, Eq)#}-{#enum BondPriceType{} deriving (Show, Eq)#}-{#enum CallabilityType{} add prefix="Callability" deriving(Show, Eq)#}-{#enum FdmSchemeType{} deriving(Show, Eq)#}-{#enum RoundingType{} deriving (Show, Eq)#}--- flat/linear interpolation of a CPI index between its publication dates -- skips the--- deprecated AsIndex upstream case, so cbits/qlEnumObjects.h's values (and thus this--- c2hs-derived enum's fromEnum) start at 1, not 0; see that header's comment for why a--- renumbered-from-0 enum here would silently alias to the wrong upstream case. Declared here--- (not in QuantLib.TermStructure.Inflation, its "natural" home) for the same reason as--- TimeUnit above: needed by several modules whose build order can't all safely {#import#} that--- module (built before it, or -- for QuantLib.TermStructure.Yield -- mutually dependent with--- it already).-{#enum CPIInterpolationType{} deriving (Show, Eq, Bounded)#}---- Payoff/Exercise pointer hierarchy: the Finalizable/Upcastable instances and raw phantom--- tags (CPayoff' etc.) live in QuantLib.Internal.Type alongside every other class hierarchy;--- these are just c2hs-local aliases so {#fun#} specs below can keep writing the bare `QlX'--- names, resolving to a raw, unwrapped Ptr (no auto-generated foreign-pointer code) since--- construction/upcasting is handled by hand in the with* functions further down.-type QlPayoff = Ptr CPayoff'-type QlBasketPayoff = Ptr CBasketPayoff'-type QlTypePayoff = Ptr CTypePayoff'-type QlStrikedTypePayoff = Ptr CStrikedTypePayoff'-type QlPercentageStrikePayoff = Ptr CPercentageStrikePayoff'-type QlPlainVanillaPayoff = Ptr CPlainVanillaPayoff'-type QlExercise = Ptr CExercise'-type QlEuropeanExercise = Ptr CEuropeanExercise'-type QlAmericanExercise = Ptr CAmericanExercise'-type QlSwingExercise = Ptr CSwingExercise'-type QlBermudanExercise = Ptr CBermudanExercise'--- identity peek function: c2hs {#fun#} return specs always need a named out-marshaller,--- even when (as here) construction should just hand back the raw, un-wrapped pointer.-peekPtr :: Ptr a -> IO (Ptr a)-peekPtr = pure-{#pointer *QlPayoff nocode#}-{#pointer *QlBasketPayoff nocode#}-{#pointer *QlTypePayoff nocode#}-{#pointer *QlStrikedTypePayoff nocode#}-{#pointer *QlPercentageStrikePayoff nocode#}-{#pointer *QlPlainVanillaPayoff nocode#}-{#pointer *QlExercise nocode#}-{#pointer *QlEuropeanExercise nocode#}-{#pointer *QlAmericanExercise nocode#}-{#pointer *QlSwingExercise nocode#}-{#pointer *QlBermudanExercise nocode#}-{#pointer *QlCallability foreign -> CQlCallability nocode#}-{#pointer *OptimizationMethod as QlOptimizationMethod foreign -> COptimizationMethod nocode#}-{#pointer *EndCriteria as QlEndCriteria foreign -> CEndCriteria nocode#}-{#pointer *Constraint as QlConstraint foreign -> CConstraint nocode#}-{#pointer *FdmSchemeDesc as QlFdmSchemeDesc foreign -> CFdmSchemeDesc nocode#}-{#pointer *FittedBondDiscountCurveFittingMethod as QlFittedBondDiscountCurveFittingMethod foreign -> CFittedBondDiscountCurveFittingMethod nocode#}-{#pointer *QlClaim as Claim foreign -> CQlClaim nocode#}-{#pointer *QlBond as Bond foreign -> CBond' nocode#}-{#pointer *QlLmCorrelationModel foreign -> CLmCorrelationModel nocode#}-{#pointer *QlLmVolatilityModel foreign -> CLmVolatilityModel nocode#}-{#pointer *Rounding as QlRounding foreign -> CRounding nocode#}---- monotonic flag for CubicInterpolation::Spline/::Parabolic -- tells deriveCrossEnum to give--- these two values a runtime Bool field instead of cross-producting named sub-values (same--- pattern as Actual360Convention etc. in CalendarEnum.chs). Order matters here in a way it--- doesn't for the ApproximationType enum itself: these two type synonyms (and ApproximationExtra--- below) must be declared textually *above* the deriveCrossEnum splice, since a TH splice can--- only see top-level declarations that already exist earlier in the same module -- classifySub's--- lookupTypeName would silently miss them (falling back to NoSub, dropping the Bool field) if--- they were moved below the splice.-type NaturalSplineMonotonic = Bool-type ParabolicMonotonic = Bool---- every Approximation case is driven by ApproximationType itself, so unlike--- CalendarExtra/DayCounterExtra/IborExtra there are no non-enum-driven cases to add here-data ApproximationExtra--$(deriveCrossEnum CrossEnumSpec-    { crossTypeName = "Approximation"-    , crossMapperFn = "qlApproximation"-    , crossMainEnum = ''ApproximationType-    , crossSubSuffix = "Monotonic"-    , crossExtraType = ''ApproximationExtra-    })--deriving instance Show Approximation-deriving instance Eq Approximation---- Remaining cpp<->hs lockstep, unlike CalendarConstructor/DayCounterConstructor/IborConstructor:--- those own a full C-side array/table, so *every* lockstep edit needed for a new value stays--- inside cbits/. Approximation/Interpolation instead get dispatched via symbolic switch-case on--- the shared enum (cbits/qlTermStructure.cpp's setInterpolation, and ~18 duplicated--- switch(interpolator){switch(approximator){...}} sites in cbits/qlTermStructureAux.cpp, one per--- PiecewiseYieldCurve trait/interpolator instantiation). Adding a new ApproximationType/--- InterpolationType value to cbits/qlEnumObjects.h is zero-touch here on the Haskell side--- (deriveCrossEnum picks it up automatically, defaulting to a nullary constructor unless a--- <Value>Monotonic marker is added above), but each cbits switch still needs a matching--- `case hasquant::NewValue:` by hand -- a missed one isn't a compile error, just a runtime--- QL_FAIL("Unsupported ..."), exactly the pre-existing gap Abcd fell into (see the comment next--- to setInterpolation's default case in qlTermStructure.cpp).--qlInterpolation :: Interpolation -> (Int, (Int, Int))-qlInterpolation BackwardFlat = (fromEnum InterpolationBackwardFlat, (0, 0))-qlInterpolation ForwardFlat = (fromEnum InterpolationForwardFlat, (0, 0))-qlInterpolation Linear = (fromEnum InterpolationLinear, (0, 0))-qlInterpolation LogLinear = (fromEnum InterpolationLogLinear, (0, 0))-qlInterpolation (Cubic x) = (fromEnum InterpolationCubic, qlApproximation x)-qlInterpolation (LogCubic x) = (fromEnum InterpolationLogCubic, qlApproximation x)-qlInterpolation Abcd = (fromEnum InterpolationAbcd, (0, 0))--qlInterpolation' :: Maybe Interpolation -> (Int, (Int, Int))-qlInterpolation' Nothing = (fromIntegral qlNullInteger, (0, 0))-qlInterpolation' (Just i) = qlInterpolation i--data Interpolation =-  BackwardFlat-  | ForwardFlat-  | Linear-  | LogLinear-  | Cubic !Approximation-  | LogCubic !Approximation-  | Abcd-  deriving (Show, Eq)--data EuropeanExercise = EuropeanExercise Day--- | Use 'swingExerice' to construct 'Exercise'-data SwingExercise =-    SwingListExercise ![(Day, Word)] -- ^(dates, seconds)-    | SwingIntervalExercise !Day !Day !Word -- ^stepSizeSecs-data BermudanExercise =-    BermudanExercise ![Day] !Bool-    | Swing SwingExercise---- | > Exercise--- >  American--- >  Early--- >  Vanilla--- >  EuropeanExercise--- >  BermudanExercise--- >    SwingExercise-data Exercise =-    American-      !(Maybe Day) -- ^earliestDate-      !Day -- ^latestDate-      !Bool -- ^paoffAtExpiry-    | Early !ExerciseType !Bool-    | Vanilla !ExerciseType-    | European !EuropeanExercise-    | Bermudan !BermudanExercise--{#fun qlExercise{`ExerciseType',preErrorCheck-`String'errorCheck*-}->`QlExercise'peekPtr*#}-{#fun qlAmericanExercise{withDay*`Day',withDay*`Day',`Bool',preErrorCheck-`String'errorCheck*-}->`QlAmericanExercise'peekPtr*#}-{#fun qlAmericanExercise1{withDay*`Day',`Bool',preErrorCheck-`String'errorCheck*-}->`QlAmericanExercise'peekPtr*#}-{#fun qlBermudanExercise{withDayArray*`[Day]'&,`Bool',preErrorCheck-`String'errorCheck*-}->`QlBermudanExercise'peekPtr*#}-{#fun qlEarlyExercise{`ExerciseType',`Bool',preErrorCheck-`String'errorCheck*-}->`QlExercise'peekPtr*#}-{#fun qlEuropeanExercise{withDay*`Day',preErrorCheck-`String'errorCheck*-}->`QlEuropeanExercise'peekPtr*#}-{#fun qlSwingExercise{withDayArray*`[Day]'&,withIntArray*`[Word]'&,preErrorCheck-`String'errorCheck*-}->`QlSwingExercise'peekPtr*#}-{#fun qlSwingExercise1{withDay*`Day',withDay*`Day',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlSwingExercise'peekPtr*#}--withEuropeanExercise :: EuropeanExercise -> (QlEuropeanExercise -> IO a) -> IO a-withEuropeanExercise (EuropeanExercise d) f = qlEuropeanExercise d >>= newCastForeignPtr >>= flip withGenForeignPtr f--withSwingExercise :: SwingExercise -> (QlSwingExercise -> IO a) -> IO a-withSwingExercise (SwingListExercise ds) f = uncurry qlSwingExercise (unzip ds) >>= newCastForeignPtr >>= flip withGenForeignPtr f-withSwingExercise (SwingIntervalExercise d1 d2 s) f = qlSwingExercise1 d1 d2 s >>= newCastForeignPtr >>= flip withGenForeignPtr f--withBermudanExercise :: BermudanExercise -> (QlBermudanExercise -> IO a) -> IO a-withBermudanExercise (BermudanExercise d p) f = qlBermudanExercise d p >>= newCastForeignPtr >>= flip withGenForeignPtr f-withBermudanExercise (Swing e) f = withSwingExercise e (\sp -> upcast sp >>= \bp -> f bp `finally` freeUpcast bp)--withExercise :: Exercise -> (QlExercise -> IO a) -> IO a-withExercise (American Nothing d p) f = qlAmericanExercise1 d p >>= newGenForeignPtr >>= flip withGenForeignPtr f-withExercise (American (Just d0) d p) f = qlAmericanExercise d0 d p >>= newGenForeignPtr >>= flip withGenForeignPtr f-withExercise (Early t p) f = qlEarlyExercise t p >>= newCastForeignPtr >>= flip withGenForeignPtr f-withExercise (Vanilla t) f = qlExercise t >>= newCastForeignPtr >>= flip withGenForeignPtr f-withExercise (European e) f = withEuropeanExercise e (\ep -> upcast ep >>= \xp -> f xp `finally` freeUpcast xp)-withExercise (Bermudan e) f = withBermudanExercise e (\bp -> upcast bp >>= \xp -> f xp `finally` freeUpcast xp)---- | use 'percentageStrikePayoff' to construct 'Payoff'-data PercentageStrikePayoff = PercentageStrikePayoff-      !OptionType -- ^type-      !Double -- ^moneyness---- | use 'plainVanillaPayoff' to construct 'Payoff'-data PlainVanillaPayoff = PlainVanillaPayoff-      !OptionType -- ^type-      !Double -- ^strike---- | use 'strikedPayoff' to construct 'Payoff'-data StrikedPayoff =-  AssetOrNothing-    !OptionType -- ^type-    !Double -- ^strike-  | CashOrNothing-      !OptionType -- ^type-      !Double -- ^strike-      !Double -- ^cashPayoff-  | Gap-      !OptionType -- ^type-      !Double -- ^strike-      !Double -- ^secondStrike-  | PercentageStrike !PercentageStrikePayoff-  | PlainVanilla !PlainVanillaPayoff-  | SuperFund-      !Double -- ^strike-      !Double -- ^secondStrike-  | SuperSharePayoff-      !Double -- ^strike-      !Double -- ^secondStrike-      !Double -- ^cashPayoff--withPercentageStrikePayoff :: PercentageStrikePayoff -> (QlPercentageStrikePayoff -> IO a) -> IO a-withPercentageStrikePayoff (PercentageStrikePayoff t m) f = qlPercentageStrikePayoff t m >>= newCastForeignPtr >>= flip withGenForeignPtr f--withPlainVanillaPayoff :: PlainVanillaPayoff -> (QlPlainVanillaPayoff -> IO a) -> IO a-withPlainVanillaPayoff (PlainVanillaPayoff t s) f = qlPlainVanillaPayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f--withStrikedPayoff :: StrikedPayoff -> (QlStrikedTypePayoff -> IO a) -> IO a-withStrikedPayoff (AssetOrNothing t s) f = qlAssetOrNothingPayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f-withStrikedPayoff (CashOrNothing t s c) f = qlCashOrNothingPayoff t s c >>= newCastForeignPtr >>= flip withGenForeignPtr f-withStrikedPayoff (Gap t s ss) f = qlGapPayoff t s ss >>= newCastForeignPtr >>= flip withGenForeignPtr f-withStrikedPayoff (PercentageStrike p) f = withPercentageStrikePayoff p (\pp -> upcast pp >>= \sp -> f sp `finally` freeUpcast sp)-withStrikedPayoff (PlainVanilla p) f = withPlainVanillaPayoff p (\pp -> upcast pp >>= \sp -> f sp `finally` freeUpcast sp)-withStrikedPayoff (SuperFund s ss) f = qlSuperFundPayoff s ss >>= newCastForeignPtr >>= flip withGenForeignPtr f-withStrikedPayoff (SuperSharePayoff s ss c) f = qlSuperSharePayoff s ss c >>= newCastForeignPtr >>= flip withGenForeignPtr f--data TypePayoff = Striked !StrikedPayoff-  | Floating !OptionType -- ^type-data BasketPayoff =-    Average-      !Payoff -- ^p-      !Word -- ^n-  | AverageMultiple-      !Payoff -- ^p-      ![Double] -- ^a-  | Max-      !Payoff -- ^p-  | Min-      !Payoff -- ^p-  | Spread-      !Payoff -- ^p--withTypePayoff :: TypePayoff -> (QlTypePayoff -> IO a) -> IO a-withTypePayoff (Floating t) f = qlFloatingTypePayoff t >>= newCastForeignPtr >>= flip withGenForeignPtr f-withTypePayoff (Striked s) f = withStrikedPayoff s (\sp -> upcast sp >>= \tp -> f tp `finally` freeUpcast tp)--withBasketPayoff :: BasketPayoff -> (QlBasketPayoff -> IO a) -> IO a-withBasketPayoff (Average p n) f = withPayoff p (\pp -> qlAverageBasketPayoff pp n >>= newCastForeignPtr >>= flip withGenForeignPtr f)-withBasketPayoff (AverageMultiple p a) f = withPayoff p (\pp -> qlAverageBasketPayoff1 pp a >>= newCastForeignPtr >>= flip withGenForeignPtr f)-withBasketPayoff (Max p) f = withPayoff p (\pp -> qlMaxBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)-withBasketPayoff (Min p) f = withPayoff p (\pp -> qlMinBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)-withBasketPayoff (Spread p) f = withPayoff p (\pp -> qlSpreadBasketPayoff pp >>= newCastForeignPtr >>= flip withGenForeignPtr f)---- | > Payoff--- >  DoubleStickyRatchet--- >  ForwardType--- >  RatchettMax--- >  RatchetMin--- >  StickyMax--- >  StickyMin--- >  Sticky--- >  TypePayoff--- >    Floating--- >    Striked--- >      AssetOrNothing--- >      CashOrNothing--- >      Gap--- >      PercentageStrike--- >      PlainVanilla--- >      SuperFund--- >      SuperSharePayoff--- >  BasketPayoff--- >    Average--- >    AverageMultiple--- >    Max--- >    Min--- >    Spread-data Payoff =-    DoubleStickyRatchet-      !Double -- ^type1-      !Double -- ^type2-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^gearing3-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^spread3-      !Double -- ^initialValue1-      !Double -- ^initialValue2-      !Double -- ^accrualFactor-  | ForwardType-      !PositionType -- ^type-      !Double -- ^strike-  | RatchetMax-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^gearing3-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^spread3-      !Double -- ^initialValue1-      !Double -- ^initialValue2-      !Double -- ^accrualFactor-  | RatchetMin-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^gearing3-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^spread3-      !Double -- ^initialValue1-      !Double -- ^initialValue2-      !Double -- ^accrualFactor-  | Ratchet-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^initialValue-      !Double -- ^accrualFactor-  | StickyMax-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^gearing3-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^spread3-      !Double -- ^initialValue1-      !Double -- ^initialValue2-      !Double -- ^accrualFactor-  | StickyMin-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^gearing3-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^spread3-      !Double -- ^initialValue1-      !Double -- ^initialValue2-      !Double -- ^accrualFactor-  | Sticky-      !Double -- ^gearing1-      !Double -- ^gearing2-      !Double -- ^spread1-      !Double -- ^spread2-      !Double -- ^initialValue-      !Double -- ^accrualFactor-  | Type !TypePayoff-  | Basket !BasketPayoff---{#fun qlAssetOrNothingPayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}-{#fun qlAverageBasketPayoff{`QlPayoff',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}-{#fun qlCashOrNothingPayoff{`OptionType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}-{#fun qlDoubleStickyRatchetPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlFloatingTypePayoff{`OptionType',preErrorCheck-`String'errorCheck*-}->`QlTypePayoff'peekPtr*#}-{#fun qlForwardTypePayoff{`PositionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlGapPayoff{`OptionType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}-{#fun qlMaxBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}-{#fun qlMinBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}-{#fun qlPercentageStrikePayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPercentageStrikePayoff'peekPtr*#}-{#fun qlPlainVanillaPayoff{`OptionType',`Double',preErrorCheck-`String'errorCheck*-}->`QlPlainVanillaPayoff'peekPtr*#}-{#fun qlRatchetMaxPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlRatchetMinPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlRatchetPayoff{`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlSpreadBasketPayoff{`QlPayoff',preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}-{#fun qlStickyMaxPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlStickyMinPayoff{`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlStickyPayoff{`Double',`Double',`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlPayoff'peekPtr*#}-{#fun qlSuperFundPayoff{`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}-{#fun qlSuperSharePayoff{`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlStrikedTypePayoff'peekPtr*#}-{#fun qlAverageBasketPayoff1{`QlPayoff',withDoubleArray*`[Double]'&,preErrorCheck-`String'errorCheck*-}->`QlBasketPayoff'peekPtr*#}--withPayoff :: Payoff -> (QlPayoff -> IO a) -> IO a-withPayoff (DoubleStickyRatchet t1 t2 g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlDoubleStickyRatchetPayoff t1 t2 g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (ForwardType t s) f = qlForwardTypePayoff t s >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (RatchetMax g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlRatchetMaxPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (RatchetMin g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlRatchetMinPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (Ratchet g1 g2 s1 s2 i a) f = qlRatchetPayoff g1 g2 s1 s2 i a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (StickyMax g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlStickyMaxPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (StickyMin g1 g2 g3 s1 s2 s3 i1 i2 a) f = qlStickyMinPayoff g1 g2 g3 s1 s2 s3 i1 i2 a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (Sticky g1 g2 s1 s2 i a) f = qlStickyPayoff g1 g2 s1 s2 i a >>= newCastForeignPtr >>= flip withGenForeignPtr f-withPayoff (Type t) f = withTypePayoff t (\tp -> upcast tp >>= \pp -> f pp `finally` freeUpcast pp)-withPayoff (Basket b) f = withBasketPayoff b (\bp -> upcast bp >>= \pp -> f pp `finally` freeUpcast pp)--data Callability =-  Soft-    !(Double, BondPriceType)-    !Day-    !Double -- ^trigger-  | Callability-      !(Double, BondPriceType)-      !CallabilityType-      !Day--callability :: Callability -> IO (Standalone CQlCallability)-callability (Soft (p, t) d tg) = qlSoftCallability p t d tg-callability (Callability (p, t) ct d) = qlCallability p t ct d--newtype EnumMeta a b = EnumMeta (a -> IO (Standalone b))--withEnumType :: EnumMeta a b -> a -> (Ptr b -> IO c) -> IO c-withEnumType (EnumMeta t) x f = t x >>= (`withStandalone` f)--withMaybeEnumType :: EnumMeta a b -> Maybe a -> (Ptr b -> IO c) -> IO c-withMaybeEnumType (EnumMeta t) x f = maybe (f nullPtr) (\xx -> t xx >>= (`withStandalone` f)) x--withEnumTypeArray :: EnumMeta a b -> [a] -> ((CUInt, Ptr (Ptr b)) -> IO c) -> IO c-withEnumTypeArray m x f = withMany (withEnumType m) x (`withArray` (\px -> f (fromIntegral $ length x, px)))--callabilityMeta :: EnumMeta Callability CQlCallability-callabilityMeta = EnumMeta callability--withCallability :: Callability -> (Ptr CQlCallability -> IO a) -> IO a-withCallability = withEnumType callabilityMeta--withCallabilityArray :: [Callability] -> ((CUInt, Ptr (Ptr CQlCallability)) -> IO c) -> IO c-withCallabilityArray = withEnumTypeArray callabilityMeta--constraintMeta :: EnumMeta Constraint CConstraint-constraintMeta = EnumMeta constraint--roundingMeta :: EnumMeta Rounding CRounding-roundingMeta = EnumMeta rounding--withMaybeConstraint :: Maybe Constraint -> (Ptr CConstraint -> IO a) -> IO a-withMaybeConstraint = withMaybeEnumType constraintMeta--withMaybeRounding :: Maybe Rounding -> (Ptr CRounding -> IO a) -> IO a-withMaybeRounding = withMaybeEnumType roundingMeta--withConstraint :: Constraint -> (Ptr CConstraint -> IO a) -> IO a-withConstraint = withEnumType constraintMeta--withRounding :: Rounding -> (Ptr CRounding -> IO a) -> IO a-withRounding = withEnumType roundingMeta--fittedBondDiscountFittingMethodMeta :: EnumMeta FittingMethod CFittedBondDiscountCurveFittingMethod-fittedBondDiscountFittingMethodMeta = EnumMeta fittingMethod--withFittedBondDiscountCurveFittingMethod :: FittingMethod -> (Ptr CFittedBondDiscountCurveFittingMethod -> IO a) -> IO a-withFittedBondDiscountCurveFittingMethod = withEnumType fittedBondDiscountFittingMethodMeta--endCriteriaMeta :: EnumMeta EndCriteria CEndCriteria-endCriteriaMeta = EnumMeta endCriteria--withEndCriteria :: EndCriteria -> (Ptr CEndCriteria -> IO a) -> IO a-withEndCriteria = withEnumType endCriteriaMeta--fdmSchemeDescMeta :: EnumMeta FdmScheme CFdmSchemeDesc-fdmSchemeDescMeta = EnumMeta fdmScheme--withFdmSchemeDesc :: FdmScheme -> (Ptr CFdmSchemeDesc -> IO a) -> IO a-withFdmSchemeDesc = withEnumType fdmSchemeDescMeta--optimizationMethodMeta :: EnumMeta OptimizationMethod COptimizationMethod-optimizationMethodMeta = EnumMeta optimizationMethod--withOptimizationMethod :: OptimizationMethod -> (Ptr COptimizationMethod -> IO a) -> IO a-withOptimizationMethod = withEnumType optimizationMethodMeta---- Payoff/Exercise with* functions are now defined directly, near their ADTs, using--- Upcastable/GenForeignPtr (see QuantLib.Internal.Type) instead of EnumMeta'/IsQlPayoff/IsQlExercise.---- |callability leaving to the holder the possibility to convert-{#fun qlSoftCallability{`Double',`BondPriceType',withDay*`Day',`Double',preErrorCheck-`String'errorCheck*-}->`QlCallability'peekCallability*#}-{#fun qlCallability{`Double',`BondPriceType',`CallabilityType',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`QlCallability'peekCallability*#}---- Every constructor below binds the QuantLib overload that omits the leading--- optimizationMethod param (see the qlTermStructure.cpp comment above the--- qlXxxFitting shims for why: OptimizationMethod's hasquant-side handle is a--- raw, Haskell-finalized pointer, not a QlXxx shared_ptr box, and--- FittedBondDiscountCurve additionally clones its fitting method -- passing--- one through safely needs a real ownership-representation change).-data FittingMethod =-  CubicBSplines-    ![Double] -- ^knotVector (year fraction)-    !Bool -- ^constrainAtZero-    ![Double] -- ^weights-    ![Double] -- ^l2-    !Double -- ^minCutoffTime-    !Double -- ^maxCutoffTime-    !(Maybe Constraint)-  | ExponentialSplines-    !Bool -- ^constrainAtZero-    ![Double] -- ^weights-    ![Double] -- ^l2-    !Double -- ^minCutoffTime-    !Double -- ^maxCutoffTime-    !Word -- ^numCoeffs-    !(Maybe Double) -- ^fixedKappa-    !(Maybe Constraint)-  | NelsonSiegel-    ![Double] -- ^weights-    ![Double] -- ^l2-    !Double -- ^minCutoffTime-    !Double -- ^maxCutoffTime-    !(Maybe Constraint)-  | SimplePolynomial-    !Word -- ^degree-    !Bool -- ^constrainAtZero-    ![Double] -- ^weights-    ![Double] -- ^l2-    !Double -- ^minCutoffTime-    !Double -- ^maxCutoffTime-    !(Maybe Constraint)-  | Svensson-    ![Double] -- ^weights-    ![Double] -- ^l2-    !Double -- ^minCutoffTime-    !Double -- ^maxCutoffTime-    !(Maybe Constraint)--fittingMethod :: FittingMethod -> IO QlFittedBondDiscountCurveFittingMethod-fittingMethod (CubicBSplines k c w l2 mn mx cn) = qlCubicBSplinesFitting k c w l2 mn mx cn-fittingMethod (ExponentialSplines c w l2 mn mx n fk cn) = qlExponentialSplinesFitting c w l2 mn mx n fk cn-fittingMethod (NelsonSiegel w l2 mn mx cn) = qlNelsonSiegelFitting w l2 mn mx cn-fittingMethod (SimplePolynomial d c w l2 mn mx cn) = qlSimplePolynomialFitting d c w l2 mn mx cn-fittingMethod (Svensson w l2 mn mx cn) = qlSvenssonFitting w l2 mn mx cn--{#fun qlCubicBSplinesFitting{withDoubleArray*`[Double]'&,`Bool'-  ,withDoubleArray*`[Double]'& -- ^weights-  ,withDoubleArray*`[Double]'& -- ^l2-  ,`Double' -- ^minCutoffTime-  ,`Double' -- ^maxCutoffTime-  ,withMaybeConstraint*`Maybe Constraint'-  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}-{#fun qlExponentialSplinesFitting{`Bool'-  ,withDoubleArray*`[Double]'& -- ^weights-  ,withDoubleArray*`[Double]'& -- ^l2-  ,`Double' -- ^minCutoffTime-  ,`Double' -- ^maxCutoffTime-  ,fromIntegral`Word' -- ^numCoeffs-  ,fromMaybeDouble`Maybe Double' -- ^fixedKappa-  ,withMaybeConstraint*`Maybe Constraint'-  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}-{#fun qlNelsonSiegelFitting{withDoubleArray*`[Double]'& -- ^weights-  ,withDoubleArray*`[Double]'& -- ^l2-  ,`Double' -- ^minCutoffTime-  ,`Double' -- ^maxCutoffTime-  ,withMaybeConstraint*`Maybe Constraint'-  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}-{#fun qlSimplePolynomialFitting{fromIntegral`Word',`Bool'-  ,withDoubleArray*`[Double]'& -- ^weights-  ,withDoubleArray*`[Double]'& -- ^l2-  ,`Double' -- ^minCutoffTime-  ,`Double' -- ^maxCutoffTime-  ,withMaybeConstraint*`Maybe Constraint'-  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}-{#fun qlSvenssonFitting{withDoubleArray*`[Double]'& -- ^weights-  ,withDoubleArray*`[Double]'& -- ^l2-  ,`Double' -- ^minCutoffTime-  ,`Double' -- ^maxCutoffTime-  ,withMaybeConstraint*`Maybe Constraint'-  ,preErrorCheck-`String'errorCheck*-}->`QlFittedBondDiscountCurveFittingMethod'peekFittedBondDiscountCurveFittingMethod*#}--data FdmScheme =-  FdmScheme-    !FdmSchemeType -- ^type-    !Double -- ^theta-    !Double -- ^mu-  | CraigSneyd-  | Douglas-  | ExplicitEuler-  | Hundsdorfer-  | ImplicitEuler-  | ModifiedCraigSneyd-  | ModifiedHundsdorfer--{#fun qlFdmSchemeDesc{`FdmSchemeType',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescCraigSneyd{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescDouglas{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescExplicitEuler{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescHundsdorfer{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescImplicitEuler{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescModifiedCraigSneyd{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}-{#fun qlFdmSchemeDescModifiedHundsdorfer{preErrorCheck-`String'errorCheck*-}->`QlFdmSchemeDesc'peekFdmSchemeDesc*#}--fdmScheme :: FdmScheme -> IO QlFdmSchemeDesc-fdmScheme (FdmScheme t th mu) = qlFdmSchemeDesc t th mu-fdmScheme CraigSneyd = qlFdmSchemeDescCraigSneyd-fdmScheme Douglas = qlFdmSchemeDescDouglas-fdmScheme ExplicitEuler = qlFdmSchemeDescExplicitEuler-fdmScheme Hundsdorfer = qlFdmSchemeDescHundsdorfer-fdmScheme ImplicitEuler = qlFdmSchemeDescImplicitEuler-fdmScheme ModifiedCraigSneyd = qlFdmSchemeDescModifiedCraigSneyd-fdmScheme ModifiedHundsdorfer = qlFdmSchemeDescModifiedHundsdorfer--data Constraint =-  Boundary-    !Double -- ^low-    !Double -- ^high-  | Composite-    !Constraint -- ^c1-    !Constraint -- ^c2-  | NoConstraint-  | PositiveConstraint--constraint :: Constraint -> IO QlConstraint-constraint (Boundary l h) = qlBoundaryConstraint l h-constraint (Composite c1 c2) = qlCompositeConstraint c1 c2-constraint NoConstraint = qlNoConstraint-constraint PositiveConstraint = qlPositiveConstraint--{#fun qlBoundaryConstraint{`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}-{#fun qlCompositeConstraint{withConstraint*`Constraint',withConstraint*`Constraint',preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}-{#fun qlNoConstraint{preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}-{#fun qlPositiveConstraint{preErrorCheck-`String'errorCheck*-}->`QlConstraint'peekConstraint*#}--data OptimizationMethod =-  LevenbergMarquardt-    !Double -- ^epsfcn-    !Double -- ^xtol-    !Double -- ^gtol-    !Bool -- ^useCostFunctionsJacobian-  | Simplex !Double -- ^lambda, characteristic length--optimizationMethod :: OptimizationMethod -> IO QlOptimizationMethod-optimizationMethod (LevenbergMarquardt e x g j) = qlLevenbergMarquardt e x g j-optimizationMethod (Simplex l) = qlSimplex l-{#fun qlLevenbergMarquardt{`Double',`Double',`Double',`Bool',preErrorCheck-`String'errorCheck*-}->`QlOptimizationMethod'peekOptimizationMethod*#}-{#fun qlSimplex{`Double',preErrorCheck-`String'errorCheck*-}->`QlOptimizationMethod'peekOptimizationMethod*#}--data EndCriteria =-  EndCriteria-    !Word -- ^maxIterations-    !Word -- ^maxStationaryStateIterations-    !Double -- ^rootEpsilon-    !Double -- ^functionEpsilon-    !Double -- ^gradientNormEpsilon--endCriteria :: EndCriteria -> IO QlEndCriteria-endCriteria (EndCriteria m1 m2 e f g) = qlEndCriteria m1 m2 e f g-{#fun qlEndCriteria{fromIntegral`Word',fromIntegral`Word',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlEndCriteria'peekEndCriteria*#}--data Rounding = NoRounding-  | Rounding-    !Int -- ^precision-    !RoundingType-    !Int -- ^digit-  deriving (Show, Eq)--rounding :: Rounding -> IO QlRounding-rounding NoRounding = qlRounding-rounding (Rounding p t d) = qlRounding1 p t d--{#fun qlRounding{preErrorCheck-`String'errorCheck*-}->`QlRounding'peekRounding*#}-{#fun qlRounding1{`Int',`RoundingType',`Int',preErrorCheck-`String'errorCheck*-}->`QlRounding'peekRounding*#}--data LmCorrelationModel = ConstWrapperCorrelation LmCorrelationModel-  | ExponentialCorrelation Word -- ^size-    !Double -- ^rho-  | LinearExponentialCorrelation Word -- ^size-    !Double -- ^rho-    !Double -- ^beta-    !Word -- ^factors-  deriving (Show, Eq)--{#fun qlLmConstWrapperCorrelationModel{withStandalone*`QlLmCorrelationModel',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}-{#fun qlLmExponentialCorrelationModel{fromIntegral`Word',`Double',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}-{#fun qlLmLinearExponentialCorrelationModel{fromIntegral`Word',`Double',`Double',fromIntegral`Word',preErrorCheck-`String'errorCheck*-}->`QlLmCorrelationModel'peekLmCorrelationModel*#}--correlationModel :: LmCorrelationModel -> IO QlLmCorrelationModel-correlationModel (ConstWrapperCorrelation m) = correlationModel m >>= qlLmConstWrapperCorrelationModel-correlationModel (ExponentialCorrelation s r) = qlLmExponentialCorrelationModel s r-correlationModel (LinearExponentialCorrelation s r b f) = qlLmLinearExponentialCorrelationModel s r b f--correlationModelMeta :: EnumMeta LmCorrelationModel CLmCorrelationModel-correlationModelMeta = EnumMeta correlationModel--withLmCorrelationModel :: LmCorrelationModel -> (Ptr CLmCorrelationModel -> IO a) -> IO a-withLmCorrelationModel = withEnumType correlationModelMeta--data LmVolatilityModel = ConstWrapperVolatility LmVolatilityModel-  | FixedVolatility ![Double] ![Double]-  | LinearExponentialVolatility ![Double] -- ^fixing times-    !Double -- ^a-    !Double -- ^b-    !Double -- ^c-    !Double -- ^d-  deriving (Show, Eq)--{#fun qlLmConstWrapperVolatilityModel{withStandalone*`QlLmVolatilityModel',preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}-{#fun qlLmFixedVolatilityModel{withDoubleArray*`[Double]'&,withDoubleArray*`[Double]'&,preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}-{#fun qlLmLinearExponentialVolatilityModel{withDoubleArray*`[Double]'&,`Double',`Double',`Double',`Double',preErrorCheck-`String'errorCheck*-}->`QlLmVolatilityModel'peekLmVolatilityModel*#}--volatilityModel :: LmVolatilityModel -> IO QlLmVolatilityModel-volatilityModel (ConstWrapperVolatility m) = volatilityModel m >>= qlLmConstWrapperVolatilityModel-volatilityModel (FixedVolatility d1 d2) = qlLmFixedVolatilityModel d1 d2-volatilityModel (LinearExponentialVolatility s a b c d) = qlLmLinearExponentialVolatilityModel s a b c d--volatilityModelMeta :: EnumMeta LmVolatilityModel CLmVolatilityModel-volatilityModelMeta = EnumMeta volatilityModel--withLmVolatilityModel :: LmVolatilityModel -> (Ptr CLmVolatilityModel -> IO a) -> IO a-withLmVolatilityModel = withEnumType volatilityModelMeta--data Claim = FaceValue | FaceValueAccrual Bond-claimMeta :: EnumMeta Claim CQlClaim-claimMeta = EnumMeta claim--withClaim :: Claim -> (Ptr CQlClaim -> IO a) -> IO a-withClaim = withEnumType claimMeta--claim :: Claim -> IO QlClaim-claim FaceValue = qlFaceValueClaim-claim (FaceValueAccrual b) = qlFaceValueAccrualClaim b---- |Claim on a notional-{#fun qlFaceValueClaim{preErrorCheck-`String'errorCheck*-}->`QlClaim'peekClaim*#}---- |Claim on the notional of a reference security, including accrual-{#fun qlFaceValueAccrualClaim{withBond*`Bond',preErrorCheck-`String'errorCheck*-}->`QlClaim'peekClaim*#}--strikedPayoff :: StrikedPayoff -> Payoff-strikedPayoff = Type . Striked--percentageStrikePayoff :: PercentageStrikePayoff -> Payoff-percentageStrikePayoff = Type . Striked . PercentageStrike--plainVanillaPayoff :: PlainVanillaPayoff -> Payoff-plainVanillaPayoff = Type . Striked . PlainVanilla--swingExercise :: SwingExercise -> Exercise-swingExercise = Bermudan . Swing---- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/Internal/Type.hs view
@@ -11,8 +11,8 @@ import Control.Monad((>=>)) import System.IO.Unsafe(unsafePerformIO) -import QuantLib.Internal(peekDynString, preArray, peekDayArray)-import Control.Exception (finally, bracket, mask)+import QuantLib.Internal(peekDynString, preArray, peekDayArray, peekPtrArray)+import Control.Exception (finally, mask)  (<.>) :: Functor f => (b -> r) -> (a -> f b) -> a -> f r f1 <.> f2 = fmap f1 . f2@@ -90,6 +90,80 @@ instance Show Currency where show x = showStandalone qlCurrencyName (getCCurrency x) instance Eq Currency where x == y = show x == show y +data CCommodityType+newtype CommodityType = CommodityType {getCCommodityType :: Standalone CCommodityType}+foreign import ccall unsafe "ql.h &qlFreeCommodityType" qlFreeCommodityType :: FinalizerPtr CCommodityType+instance Finalizable CCommodityType where finalize = qlFreeCommodityType+peekCommodityType :: Ptr CCommodityType -> IO CommodityType+peekCommodityType = CommodityType <.> peekStandalone+withCommodityType :: CommodityType -> (Ptr CCommodityType -> IO b) -> IO b+withCommodityType = withStandalone . getCCommodityType+withMaybeCommodityType :: Maybe CommodityType -> (Ptr CCommodityType -> IO b) -> IO b+withMaybeCommodityType = withMaybeStandalone . (getCCommodityType <$>)+peekMaybeCommodityType :: Ptr CCommodityType -> IO (Maybe CommodityType)+peekMaybeCommodityType p+  | p == nullPtr = pure Nothing+  | otherwise = Just <$> peekCommodityType p+foreign import ccall safe "ql.h qlCommodityTypeCode" qlCommodityTypeCode :: Ptr CCommodityType -> IO CString+instance Show CommodityType where show x = showStandalone qlCommodityTypeCode (getCCommodityType x)+instance Eq CommodityType where x == y = show x == show y+-- |Peek a 'CommodityType' out of a @CommodityType**@ out-parameter (as opposed to+-- 'peekCommodityType', which peeks it directly out of a @CommodityType*@ primary return).+peekCommodityTypePtr :: Ptr (Ptr CCommodityType) -> IO CommodityType+peekCommodityTypePtr = peek >=> peekCommodityType++data CUnitOfMeasure+newtype UnitOfMeasure = UnitOfMeasure {getCUnitOfMeasure :: Standalone CUnitOfMeasure}+foreign import ccall unsafe "ql.h &qlFreeUnitOfMeasure" qlFreeUnitOfMeasure :: FinalizerPtr CUnitOfMeasure+instance Finalizable CUnitOfMeasure where finalize = qlFreeUnitOfMeasure+peekUnitOfMeasure :: Ptr CUnitOfMeasure -> IO UnitOfMeasure+peekUnitOfMeasure = UnitOfMeasure <.> peekStandalone+withUnitOfMeasure :: UnitOfMeasure -> (Ptr CUnitOfMeasure -> IO b) -> IO b+withUnitOfMeasure = withStandalone . getCUnitOfMeasure+withMaybeUnitOfMeasure :: Maybe UnitOfMeasure -> (Ptr CUnitOfMeasure -> IO b) -> IO b+withMaybeUnitOfMeasure = withMaybeStandalone . (getCUnitOfMeasure <$>)+peekMaybeUnitOfMeasure :: Ptr CUnitOfMeasure -> IO (Maybe UnitOfMeasure)+peekMaybeUnitOfMeasure p+  | p == nullPtr = pure Nothing+  | otherwise = Just <$> peekUnitOfMeasure p+foreign import ccall safe "ql.h qlUnitOfMeasureCode" qlUnitOfMeasureCode :: Ptr CUnitOfMeasure -> IO CString+instance Show UnitOfMeasure where show x = showStandalone qlUnitOfMeasureCode (getCUnitOfMeasure x)+instance Eq UnitOfMeasure where x == y = show x == show y+-- |Peek a 'UnitOfMeasure' out of a @UnitOfMeasure**@ out-parameter (as opposed to+-- 'peekUnitOfMeasure', which peeks it directly out of a @UnitOfMeasure*@ primary return).+peekUnitOfMeasurePtr :: Ptr (Ptr CUnitOfMeasure) -> IO UnitOfMeasure+peekUnitOfMeasurePtr = peek >=> peekUnitOfMeasure++data CPaymentTerm+newtype PaymentTerm = PaymentTerm {getCPaymentTerm :: Standalone CPaymentTerm}+foreign import ccall unsafe "ql.h &qlFreePaymentTerm" qlFreePaymentTerm :: FinalizerPtr CPaymentTerm+instance Finalizable CPaymentTerm where finalize = qlFreePaymentTerm+peekPaymentTerm :: Ptr CPaymentTerm -> IO PaymentTerm+peekPaymentTerm = PaymentTerm <.> peekStandalone+withPaymentTerm :: PaymentTerm -> (Ptr CPaymentTerm -> IO b) -> IO b+withPaymentTerm = withStandalone . getCPaymentTerm+withMaybePaymentTerm :: Maybe PaymentTerm -> (Ptr CPaymentTerm -> IO b) -> IO b+withMaybePaymentTerm = withMaybeStandalone . (getCPaymentTerm <$>)+peekMaybePaymentTerm :: Ptr CPaymentTerm -> IO (Maybe PaymentTerm)+peekMaybePaymentTerm p+  | p == nullPtr = pure Nothing+  | otherwise = Just <$> peekPaymentTerm p+foreign import ccall safe "ql.h qlPaymentTermName" qlPaymentTermName :: Ptr CPaymentTerm -> IO CString+instance Show PaymentTerm where show x = showStandalone qlPaymentTermName (getCPaymentTerm x)+instance Eq PaymentTerm where x == y = show x == show y++data CUnitOfMeasureConversion+newtype UnitOfMeasureConversion = UnitOfMeasureConversion {getCUnitOfMeasureConversion :: Standalone CUnitOfMeasureConversion}+foreign import ccall unsafe "ql.h &qlFreeUnitOfMeasureConversion" qlFreeUnitOfMeasureConversion :: FinalizerPtr CUnitOfMeasureConversion+instance Finalizable CUnitOfMeasureConversion where finalize = qlFreeUnitOfMeasureConversion+peekUnitOfMeasureConversion :: Ptr CUnitOfMeasureConversion -> IO UnitOfMeasureConversion+peekUnitOfMeasureConversion = UnitOfMeasureConversion <.> peekStandalone+withUnitOfMeasureConversion :: UnitOfMeasureConversion -> (Ptr CUnitOfMeasureConversion -> IO b) -> IO b+withUnitOfMeasureConversion = withStandalone . getCUnitOfMeasureConversion+foreign import ccall safe "ql.h qlUnitOfMeasureConversionCode" qlUnitOfMeasureConversionCode :: Ptr CUnitOfMeasureConversion -> IO CString+instance Show UnitOfMeasureConversion where show x = showStandalone qlUnitOfMeasureConversionCode (getCUnitOfMeasureConversion x)+instance Eq UnitOfMeasureConversion where x == y = show x == show y+ data CExchangeRate newtype ExchangeRate = ExchangeRate {getCExchangeRate :: Standalone CExchangeRate} foreign import ccall unsafe "ql.h &qlFreeExchangeRate" qlFreeExchangeRate :: FinalizerPtr CExchangeRate@@ -234,6 +308,22 @@ withSabrInterpolatedSmileSection :: SabrInterpolatedSmileSection -> (Ptr CSabrInterpolatedSmileSection -> IO b) -> IO b withSabrInterpolatedSmileSection = withStandalone . getCSabrInterpolatedSmileSection +-- |a dedicated leaf, not a downcast target: 'QuantLib.TermStructure.Volatility.optionletStripper2'+-- fuses construction of an 'OptionletStripper1' underneath (never exposed to Haskell, mirroring+-- 'QuantLib.TermStructure.Volatility.optionletStripper1') and stores the resulting+-- @OptionletStripper2@ itself, so its own diagnostic getters (atmCapFloorStrikes\/atmCapFloorPrices\/+-- spreadsVol) need no runtime cast. Use+-- 'QuantLib.TermStructure.Volatility.optionletStripper2AsOptionletVolatilityStructure' to pass one+-- into anything that wants the generic 'OptionletVolatilityStructure' interface.+data COptionletStripper2+newtype OptionletStripper2 = OptionletStripper2 {getCOptionletStripper2 :: Standalone COptionletStripper2}+foreign import ccall unsafe "ql.h &qlFreeOptionletStripper2" qlFreeOptionletStripper2 :: FinalizerPtr COptionletStripper2+instance Finalizable COptionletStripper2 where finalize = qlFreeOptionletStripper2+peekOptionletStripper2 :: Ptr COptionletStripper2 -> IO OptionletStripper2+peekOptionletStripper2 = OptionletStripper2 <.> peekStandalone+withOptionletStripper2 :: OptionletStripper2 -> (Ptr COptionletStripper2 -> IO b) -> IO b+withOptionletStripper2 = withStandalone . getCOptionletStripper2+ data CPricingEngine newtype PricingEngine = PricingEngine {getCPricingEngine :: Standalone CPricingEngine} foreign import ccall unsafe "ql.h &qlFreePricingEngine" qlFreePricingEngine :: FinalizerPtr CPricingEngine@@ -274,6 +364,19 @@ withEquityCashFlowPricer :: EquityCashFlowPricer -> (Ptr CEquityCashFlowPricer -> IO b) -> IO b withEquityCashFlowPricer = withStandalone . getCEquityCashFlowPricer +data CYoYInflationCouponPricer+-- | Pricer for capped\/floored 'QuantLib.CashFlow.yoyInflationLeg' coupons. All 3 concrete+-- upstream pricers (Black\/UnitDisplacedBlack\/Bachelier) share one ctor shape and are bound as+-- constructors of this single type, mirroring 'FloatingRateCouponPricer'\/'EquityCashFlowPricer'+-- (a standalone pricer type, not part of any 'GenX' hierarchy).+newtype YoYInflationCouponPricer = YoYInflationCouponPricer {getCYoYInflationCouponPricer :: Standalone CYoYInflationCouponPricer}+foreign import ccall unsafe "ql.h &qlFreeYoYInflationCouponPricer" qlFreeYoYInflationCouponPricer :: FinalizerPtr CYoYInflationCouponPricer+instance Finalizable CYoYInflationCouponPricer where finalize = qlFreeYoYInflationCouponPricer+peekYoYInflationCouponPricer :: Ptr CYoYInflationCouponPricer -> IO YoYInflationCouponPricer+peekYoYInflationCouponPricer = YoYInflationCouponPricer <.> peekStandalone+withYoYInflationCouponPricer :: YoYInflationCouponPricer -> (Ptr CYoYInflationCouponPricer -> IO b) -> IO b+withYoYInflationCouponPricer = withStandalone . getCYoYInflationCouponPricer+ data CDefaultProbabilityHelper newtype DefaultProbabilityHelper = DefaultProbabilityHelper {getCDefaultProbabilityHelper :: Standalone CDefaultProbabilityHelper} foreign import ccall unsafe "ql.h &qlFreeDefaultProbabilityHelper" qlFreeDefaultProbabilityHelper :: FinalizerPtr CDefaultProbabilityHelper@@ -418,8 +521,9 @@ --                upstream but unconstructible here, while Quote/Index/TermStructure are --                pure-virtual upstream yet routinely returned by bindings. Marks are --                added where established; an unmarked node is not a claim of the opposite.---   `X + Y'      X also reaches secondary interface Y, via the standalone qlXAsY shim and---                the hand-written Y ADT (see CAffineModel' below), not via Upcastable.+--   `X + Y'      X also reaches secondary interface Y, via the standalone qlXAsY shim,+--                materialized eagerly into a `Standalone Y' value by a per-leaf `xAsY'+--                function (see CAffineModel' below), not via Upcastable. --   X (CFoo')    X's C type, given only where it is not the expected C<X>'. -- Payoff and Exercise are documented in the files that define them, not here. -- the original pointer to `a' with a way to marshal it to `b'@@ -462,7 +566,7 @@ -- `access' performs the upcast, which allocates a fresh handle that `mfree' must release, so -- acquiring it and installing the handler have to be atomic -- `mask' covers the upcast -- happening inside `access', and `restore' hands `f' back the caller's masking state. This--- is `bracket' semantics (cf. `withUpcast' below) expressed around a continuation that+-- is `bracket' semantics expressed around a continuation that -- allocates internally. Nesting is fine: an inner level's `restore' only wraps the -- continuation that contains the outer `restore', so `f' still runs unmasked. withGenForeignPtr :: GenForeignPtr a b -> (Ptr b -> IO r) -> IO r@@ -479,6 +583,36 @@ peel :: GenForeignPtr (AnyOf b a) c -> GenForeignPtr a b peel = getAnyOf . ptr +-- |Arrays of 'CommodityType'\/'UnitOfMeasure' values, first needed by 'QuantLib.Instrument.Energy'+-- for marshalling a 'QuantLib.Commodity.PricingPeriods' list to\/from its C-side+-- structure-of-parallel-arrays representation (@Quantity@'s @CommodityType@\/@UnitOfMeasure@+-- component, split out one array per field, alongside 'QuantLib.Internal.withDayArray'\/'peekDayArray'+-- for the date fields and 'QuantLib.Internal.withDoubleArray'\/'peekDoubleArray' for the amount) --+-- reusing 'withGenArray'\/'peekPtrArray' exactly as 'withBlackCalibrationHelperArray' does.+withCommodityTypeArray :: [CommodityType] -> ((CUInt, Ptr (Ptr CCommodityType)) -> IO b) -> IO b+withCommodityTypeArray = withGenArray withCommodityType+-- |Output side, first needed by 'QuantLib.Instrument.Energy.createPricingPeriods' (the only+-- producer of a fresh 'QuantLib.Commodity.PricingPeriods' list -- every constructor instead+-- *consumes* one via 'withCommodityTypeArray').+peekCommodityTypeArray :: Ptr CUInt -> Ptr (Ptr (Ptr CCommodityType)) -> IO [CommodityType]+peekCommodityTypeArray = peekPtrArray peekCommodityType++withUnitOfMeasureArray :: [UnitOfMeasure] -> ((CUInt, Ptr (Ptr CUnitOfMeasure)) -> IO b) -> IO b+withUnitOfMeasureArray = withGenArray withUnitOfMeasure+peekUnitOfMeasureArray :: Ptr CUInt -> Ptr (Ptr (Ptr CUnitOfMeasure)) -> IO [UnitOfMeasure]+peekUnitOfMeasureArray = peekPtrArray peekUnitOfMeasure++-- |A nullable-per-entry array of 'UnitOfMeasure's -- @SecondaryCosts@' per-entry unit of measure,+-- present only for its @CommodityUnitCost@ alternative (null for its @Money@ alternative).+withMaybeUnitOfMeasureArray :: [Maybe UnitOfMeasure] -> ((CUInt, Ptr (Ptr CUnitOfMeasure)) -> IO b) -> IO b+withMaybeUnitOfMeasureArray = withGenArray withMaybeUnitOfMeasure++-- |An array of 'Currency' values -- @SecondaryCosts@'\/@SecondaryCostAmounts@'s per-entry currency.+withCurrencyArray :: [Currency] -> ((CUInt, Ptr (Ptr CCurrency)) -> IO b) -> IO b+withCurrencyArray = withGenArray withCurrency+peekCurrencyArray :: Ptr CUInt -> Ptr (Ptr (Ptr CCurrency)) -> IO [Currency]+peekCurrencyArray = peekPtrArray peekCurrency+ -- | > Quote -- >   SimpleQuote -- >   DeltaVolQuote@@ -535,7 +669,7 @@ withQuoteArrayRaw :: [GenQuote q] -> (Ptr (Ptr CQuote') -> IO b) -> IO b withQuoteArrayRaw x f = withMany withQuote x (`withArray` f) --- PAYOFF/EXERCISE upcast targets used by QuantLib.Internal.Enum's Payoff/Exercise ADT dispatch+-- PAYOFF/EXERCISE upcast targets used by QuantLib.Internal.Common's Payoff/Exercise ADT dispatch -- (the ADTs themselves stay in Enum.chs; only the pointer hierarchy plumbing lives here, -- matching every other hierarchy in this module) data CPayoff'@@ -600,6 +734,12 @@ instance Upcastable CSwingExercise' where {type Base CSwingExercise' = CBermudanExercise'; upcast = qlSwingExerciseAsBermudanExercise} foreign import ccall "ql.h qlSwingExerciseAsBermudanExercise" qlSwingExerciseAsBermudanExercise :: Ptr CSwingExercise' -> IO (Ptr CBermudanExercise') +data CRebatedExercise'+foreign import ccall unsafe "ql.h &qlFreeRebatedExercise" qlFreeRebatedExercise :: FinalizerPtr CRebatedExercise'+instance Finalizable CRebatedExercise' where finalize = qlFreeRebatedExercise+instance Upcastable CRebatedExercise' where {type Base CRebatedExercise' = CExercise'; upcast = qlRebatedExerciseAsExercise}+foreign import ccall "ql.h qlRebatedExerciseAsExercise" qlRebatedExerciseAsExercise :: Ptr CRebatedExercise' -> IO (Ptr CExercise')+ data CLeg' data CCouponLeg' newtype GenLeg l = GenLeg {getLeg :: GenForeignPtr l CLeg'}@@ -677,14 +817,23 @@ peekOISRateHelper = GenRateHelper <.> newGenForeignPtr  -- | > CalibrationHelper--- >   BlackCalibrationHelper+-- >   BlackCalibrationHelper*+-- >     SwaptionHelper+-- BlackCalibrationHelper is a proper one-AnyOf-layer family (mirrors GenSwap/GenOption under+-- GenInstrument), not a plain leaf directly under CalibrationHelper as before, so a concrete+-- subtype (SwaptionHelper) can be given its own getters without a runtime cast: SwaptionHelper's+-- own underlying()/swaption() need the real SwaptionHelper pointer, while the pre-existing+-- BlackCalibrationHelper-level accessors (times, blackPrice, impliedVolatility, ...) are+-- generalized to 'GenBlackCalibrationHelper bch' so they keep working on any leaf, SwaptionHelper+-- included, without an explicit upcast at each call site. type CalibrationHelper = GenCalibrationHelper CCalibrationHelper data CCalibrationHelper' data CBlackCalibrationHelper' newtype GenCalibrationHelper ch = GenCalibrationHelper {getCalibrationHelper :: GenForeignPtr ch CCalibrationHelper'} type CCalibrationHelper = ForeignPtr CCalibrationHelper'+type GenBlackCalibrationHelper bch = GenCalibrationHelper (AnyOf CBlackCalibrationHelper' bch) type CBlackCalibrationHelper = ForeignPtr CBlackCalibrationHelper'-type BlackCalibrationHelper = GenCalibrationHelper CBlackCalibrationHelper+type BlackCalibrationHelper = GenBlackCalibrationHelper CBlackCalibrationHelper foreign import ccall unsafe "ql.h &qlFreeCalibrationHelper" qlFreeCalibrationHelper :: FinalizerPtr CCalibrationHelper' foreign import ccall unsafe "ql.h &qlFreeBlackCalibrationHelper" qlFreeBlackCalibrationHelper :: FinalizerPtr CBlackCalibrationHelper' instance Finalizable CCalibrationHelper' where finalize = qlFreeCalibrationHelper@@ -697,15 +846,43 @@ peekCalibrationHelper = GenCalibrationHelper <.> newCastForeignPtr withCalibrationHelper :: GenCalibrationHelper ch -> (Ptr CCalibrationHelper' -> IO b) -> IO b withCalibrationHelper = withGenForeignPtr . getCalibrationHelper-withGenCalibrationHelper :: GenCalibrationHelper (ForeignPtr ch) -> (Ptr ch -> IO b) -> IO b-withGenCalibrationHelper = withForeignPtr . ptr . getCalibrationHelper+-- hands back the raw stored leaf pointer (e.g. Ptr CSwaptionHelper'); for a marshaller that+-- upcasts to the concrete Ptr CBlackCalibrationHelper', see 'withBlackCalibrationHelper' below.+withGenCalibrationHelper :: GenBlackCalibrationHelper (ForeignPtr ch) -> (Ptr ch -> IO b) -> IO b+withGenCalibrationHelper = withForeignPtr . ptr . peel . getCalibrationHelper+asBlackCalibrationHelper :: GenBlackCalibrationHelper bch -> IO BlackCalibrationHelper+asBlackCalibrationHelper = transferGenForeignPtr peekBlackCalibrationHelper . peel . getCalibrationHelper peekBlackCalibrationHelper :: Ptr CBlackCalibrationHelper' -> IO BlackCalibrationHelper-peekBlackCalibrationHelper = GenCalibrationHelper <.> newGenForeignPtr+peekBlackCalibrationHelper = newCastForeignPtr >=> newGenBlackCalibrationHelper+withBlackCalibrationHelper :: GenBlackCalibrationHelper bch -> (Ptr CBlackCalibrationHelper' -> IO b) -> IO b+withBlackCalibrationHelper = withGenForeignPtr . peel . getCalibrationHelper+newGenBlackCalibrationHelper :: GenForeignPtr bch CBlackCalibrationHelper' -> IO (GenBlackCalibrationHelper bch)+newGenBlackCalibrationHelper = pure . GenCalibrationHelper . newAnyOf withCalibrationHelperArray :: [GenCalibrationHelper ch] -> ((CUInt, Ptr (Ptr CCalibrationHelper')) -> IO b) -> IO b withCalibrationHelperArray = withGenArray withCalibrationHelper-withBlackCalibrationHelperArray :: [BlackCalibrationHelper] -> ((CUInt, Ptr (Ptr CBlackCalibrationHelper')) -> IO b) -> IO b-withBlackCalibrationHelperArray = withGenArray withGenCalibrationHelper+withBlackCalibrationHelperArray :: [GenBlackCalibrationHelper bch] -> ((CUInt, Ptr (Ptr CBlackCalibrationHelper')) -> IO b) -> IO b+withBlackCalibrationHelperArray = withGenArray withBlackCalibrationHelper+peekBlackCalibrationHelperArray :: Ptr CUInt -> Ptr (Ptr (Ptr CBlackCalibrationHelper')) -> IO [BlackCalibrationHelper]+peekBlackCalibrationHelperArray = peekPtrArray peekBlackCalibrationHelper +-- SwaptionHelper is only reachable as this concrete type when hasquant itself constructs it+-- (Model.chs's swaptionHelper/swaptionHelperFromDate/swaptionHelperFromDates); a basket returned+-- by NonstandardSwaption/FloatFloatSwaption's calibrationBasket is erased to plain+-- BlackCalibrationHelper by QuantLib's own calibrationBasket signature before it ever reaches+-- this binding, so underlying/swaption are not reachable on basket elements without a cast --+-- deliberately not offered there.+data CSwaptionHelper'+type CSwaptionHelper = ForeignPtr CSwaptionHelper'+type SwaptionHelper = GenBlackCalibrationHelper CSwaptionHelper+foreign import ccall unsafe "ql.h &qlFreeSwaptionHelper" qlFreeSwaptionHelper :: FinalizerPtr CSwaptionHelper'+instance Finalizable CSwaptionHelper' where finalize = qlFreeSwaptionHelper+foreign import ccall "ql.h qlSwaptionHelperAsBlackCalibrationHelper" qlSwaptionHelperAsBlackCalibrationHelper :: Ptr CSwaptionHelper' -> IO (Ptr CBlackCalibrationHelper')+instance Upcastable CSwaptionHelper' where {type Base CSwaptionHelper' = CBlackCalibrationHelper'; upcast = qlSwaptionHelperAsBlackCalibrationHelper}+peekSwaptionHelper :: Ptr CSwaptionHelper' -> IO SwaptionHelper+peekSwaptionHelper = newGenForeignPtr >=> newGenBlackCalibrationHelper+withSwaptionHelper :: SwaptionHelper -> (Ptr CSwaptionHelper' -> IO b) -> IO b+withSwaptionHelper = withForeignPtr . ptr . peel . getCalibrationHelper+ -- | > BlackCalculator -- >   BlackScholesCalculator type BlackCalculator = GenBlackCalculator CBlackCalculator@@ -756,6 +933,7 @@ -- >    YoYInflationIndex -- >    ZeroInflationIndex -- >  EquityIndex+-- >  CommodityIndex type Index = GenIndex CIndex data CIndex' data CInterestRateIndex'@@ -924,6 +1102,19 @@ withEquityIndex :: EquityIndex -> (Ptr CEquityIndex' -> IO b) -> IO b withEquityIndex = withForeignPtr . ptr . getIndex +-- | A plain 'Index' leaf, mirroring 'EquityIndex' -- no subclasses upstream.+data CCommodityIndex'+type CCommodityIndex = ForeignPtr CCommodityIndex'+type CommodityIndex = GenIndex CCommodityIndex+foreign import ccall unsafe "ql.h &qlFreeCommodityIndex" qlFreeCommodityIndex :: FinalizerPtr CCommodityIndex'+instance Finalizable CCommodityIndex' where finalize = qlFreeCommodityIndex+foreign import ccall "ql.h qlCommodityIndexAsIndex" qlCommodityIndexAsIndex :: Ptr CCommodityIndex' -> IO (Ptr CIndex')+instance Upcastable CCommodityIndex' where {type Base CCommodityIndex' = CIndex'; upcast = qlCommodityIndexAsIndex}+peekCommodityIndex :: Ptr CCommodityIndex' -> IO CommodityIndex+peekCommodityIndex = GenIndex <.> newGenForeignPtr+withCommodityIndex :: CommodityIndex -> (Ptr CCommodityIndex' -> IO b) -> IO b+withCommodityIndex = withForeignPtr . ptr . getIndex+ -- | > TermStructure = GenTermStructure t -- >  YieldTermStructure = GenYieldTermStructure y = GenTermStructure t -- >    FittedBondDiscountCurve = GenYieldTermStructure ...@@ -942,12 +1133,23 @@ -- >      RelinkableSwaptionVolatilityStructure -- >      SabrSwaptionVolatilityCube -- >      InterpolatedSwaptionVolatilityCube--- >    CapFloorTermVolSurface+-- >    CapFloorTermVolatilityStructure*+-- >      CapFloorTermVolCurve+-- >      CapFloorTermVolSurface+-- >    BlackAtmVolCurve*+-- >      AbcdAtmVolCurve+-- >      BlackVolSurface*+-- >        SabrVolSurface -- >    LocalVolTermStructure+-- >    YoYOptionletVolatilitySurface+-- >    CPIVolatilitySurface -- >  CallableBondVolatilityStructure -- >  DefaultProbabilityTermStructure -- >  ZeroInflationTermStructure -- >  YoYInflationTermStructure+-- >  YoYCapFloorTermPriceSurface+-- >  CPICapFloorTermPriceSurface+-- >  CommodityCurve type TermStructure = GenTermStructure CTermStructure data CTermStructure' data CVolatilityTermStructure'@@ -957,8 +1159,12 @@ data CRelinkableSwaptionVolatilityStructure' data CSabrSwaptionVolatilityCube' data CInterpolatedSwaptionVolatilityCube'+data CCapFloorTermVolatilityStructure'+data CCapFloorTermVolCurve' data CCapFloorTermVolSurface' data CLocalVolTermStructure'+data CYoYOptionletVolatilitySurface'+data CCPIVolatilitySurface' data CBlackVolTermStructure' data CRelinkableBlackVolTermStructure' data CBlackVarianceCurve'@@ -970,6 +1176,7 @@ data CDefaultProbabilityTermStructure' data CZeroInflationTermStructure' data CYoYInflationTermStructure'+data CCommodityCurve' newtype GenTermStructure t = GenTermStructure {getTermStructure :: GenForeignPtr t CTermStructure'} type CTermStructure = ForeignPtr CTermStructure' type GenYieldTermStructure y = GenTermStructure (AnyOf CYieldTermStructure' y)@@ -996,8 +1203,26 @@ -- 'QuantLib.TermStructure.Volatility.linkOptionletVolTo' reaches everything already built on -- it. Mirrors 'RelinkableSwaptionVolatilityStructure'. type RelinkableOptionletVolatilityStructure = GenOptionletVolatilityStructure CRelinkableOptionletVolatilityStructure+type GenCapFloorTermVolatilityStructure c = GenVolatilityTermStructure (AnyOf CCapFloorTermVolatilityStructure' c)+type CCapFloorTermVolatilityStructure = ForeignPtr CCapFloorTermVolatilityStructure'+-- | The abstract root shared by 'ConstantCapFloorTermVolatility' (erased straight to this type at+-- construction, having no calc\/getter of its own beyond 'capFloorVolatilityForPeriod' et al.,+-- mirroring 'ConstantOptionletVolatility' \/\'OptionletVolatilityStructure'), and the two dedicated+-- leaves below. Promoted out of a flat 'VolatilityTermStructure' leaf (the way+-- 'YoYOptionletVolatilitySurface' still is) specifically so 'capFloorVolatilityForPeriod'\/+-- 'capFloorVolatilityForDate'\/'capFloorVolatilityForTime' -- declared on+-- @CapFloorTermVolatilityStructure@ upstream, not on 'VolatilityTermStructure' -- can be bound+-- generically without a @dynamic_pointer_cast@ in the shim.+type CapFloorTermVolatilityStructure = GenCapFloorTermVolatilityStructure CCapFloorTermVolatilityStructure+type CCapFloorTermVolCurve = ForeignPtr CCapFloorTermVolCurve'+-- | An ATM-only cap\/floor term vol curve (no strike dimension, unlike 'CapFloorTermVolSurface').+-- Gets its own dedicated leaf (rather than erasing to 'CapFloorTermVolatilityStructure' the way+-- 'ConstantCapFloorTermVolatility' does) so a future binding of @OptionletStripper2@ -- which takes+-- a concrete @Handle\<CapFloorTermVolCurve\>@ upstream -- has a type to reach for without another+-- breaking change here.+type CapFloorTermVolCurve = GenCapFloorTermVolatilityStructure CCapFloorTermVolCurve type CCapFloorTermVolSurface = ForeignPtr CCapFloorTermVolSurface'-type CapFloorTermVolSurface = GenVolatilityTermStructure CCapFloorTermVolSurface+type CapFloorTermVolSurface = GenCapFloorTermVolatilityStructure CCapFloorTermVolSurface type GenSwaptionVolatilityStructure sv = GenVolatilityTermStructure (AnyOf CSwaptionVolatilityStructure' sv) type CSwaptionVolatilityStructure = ForeignPtr CSwaptionVolatilityStructure' type SwaptionVolatilityStructure = GenSwaptionVolatilityStructure CSwaptionVolatilityStructure@@ -1022,8 +1247,65 @@ -- treatment as 'SabrSwaptionVolatilityCube' for its 'atmStrike' getter (inherited, in upstream, -- from the same abstract @SwaptionVolatilityCube@ base both concrete cubes share). type InterpolatedSwaptionVolatilityCube = GenSwaptionVolatilityStructure CInterpolatedSwaptionVolatilityCube+-- | Black at-the-money (no-smile) volatility curve, abstract here (hasquant binds no+-- @qlBlackAtmVolCurve@ constructor -- @BlackAtmVolCurve@ has no bindable constructor upstream+-- either, only its concrete subclasses do). A sibling of 'OptionletVolatilityStructure'\/+-- 'CapFloorTermVolatilityStructure'\/'SwaptionVolatilityStructure' directly off+-- 'VolatilityTermStructure'. Reachable as a value via 'SabrVolSurface''s @atmCurve@ getter (any+-- concrete member may be held there), and as the argument type of 'sabrVolSurface'.+type GenBlackAtmVolCurve b = GenVolatilityTermStructure (AnyOf CBlackAtmVolCurve' b)+data CBlackAtmVolCurve'+type CBlackAtmVolCurve = ForeignPtr CBlackAtmVolCurve'+type BlackAtmVolCurve = GenBlackAtmVolCurve CBlackAtmVolCurve+-- | Black volatility (smile) surface: adds a strike\/smile dimension over 'BlackAtmVolCurve'.+-- Abstract here (no bindable constructor of its own -- only 'SabrVolSurface' constructs one in+-- this binding), but earns its own hierarchy level rather than folding into 'BlackAtmVolCurve'+-- (unlike @InterestRateVolSurface@, deliberately not given its own level -- see 'SabrVolSurface')+-- because its own calculation, @smileSection@, is the defining feature of the "surface" vs+-- "curve" distinction, not a thin pass-through inspector.+type GenBlackVolSurface b = GenBlackAtmVolCurve (AnyOf CBlackVolSurface' b)+data CBlackVolSurface'+type CBlackVolSurface = ForeignPtr CBlackVolSurface'+type BlackVolSurface = GenBlackVolSurface CBlackVolSurface+data CAbcdAtmVolCurve'+type CAbcdAtmVolCurve = ForeignPtr CAbcdAtmVolCurve'+-- | ABCD-parametric fit to a set of (tenor, quote) at-the-money vols. A dedicated+-- 'BlackAtmVolCurve' leaf (real calc\/getters of its own -- @a@\/@b@\/@c@\/@d@\/@rmsError@\/etc --+-- per the API-design rule in CLAUDE.md), one 'AnyOf' layer under 'GenBlackAtmVolCurve', same depth+-- as 'CapFloorTermVolCurve' under 'GenCapFloorTermVolatilityStructure'.+type AbcdAtmVolCurve = GenBlackAtmVolCurve CAbcdAtmVolCurve+data CSabrVolSurface'+type CSabrVolSurface = ForeignPtr CSabrVolSurface'+-- | SABR-smile surface built from an interest-rate index, an ATM 'BlackAtmVolCurve', and+-- per-tenor vol spreads. A dedicated 'BlackVolSurface' leaf (own getters: @atmCurve@,+-- @volatilitySpreads@; plus @index@\/@optionDateFromTenor@ folded in directly from upstream's+-- @InterestRateVolSurface@, which is not given its own hierarchy level here since+-- 'SabrVolSurface' is its only concrete member in this binding -- per CLAUDE.md's "don't mirror+-- the C++ hierarchy 1:1" rule). Two 'AnyOf' layers under 'GenBlackVolSurface' (mirrors+-- 'VanillaSwap' under 'FixedVsFloatingSwap' under 'GenSwap').+type SabrVolSurface = GenBlackVolSurface CSabrVolSurface type CLocalVolTermStructure = ForeignPtr CLocalVolTermStructure' type LocalVolTermStructure = GenVolatilityTermStructure CLocalVolTermStructure+type CYoYOptionletVolatilitySurface = ForeignPtr CYoYOptionletVolatilitySurface'+-- | A YoY-inflation optionlet vol surface, quoted via 'volatility'\/'totalVariance' at+-- (maturity, strike) pairs rather than QuantLib's usual (option date, tenor, strike) grid, since+-- inflation caplets observe a single index fixing rather than a forward rate. A plain+-- 'VolatilityTermStructure' leaf like 'CapFloorTermVolSurface', constructed and consumed via a+-- @Handle@ (mirroring 'OptionletVolatilityStructure', since it feeds+-- 'QuantLib.PricingEngine.yoyInflationBlackCapFloorEngine' et al. exactly the way+-- 'OptionletVolatilityStructure' feeds 'QuantLib.PricingEngine.blackCapFloorEngine'').+type YoYOptionletVolatilitySurface = GenVolatilityTermStructure CYoYOptionletVolatilitySurface+type CCPIVolatilitySurface = ForeignPtr CCPIVolatilitySurface'+-- | A CPI (zero-inflation) volatility surface, quoted via 'volatility'\/'totalVariance' at+-- (maturity, strike) pairs -- same shape as 'YoYOptionletVolatilitySurface', a plain+-- 'VolatilityTermStructure' leaf constructed and consumed via a @Handle@. Unlike+-- 'YoYOptionletVolatilitySurface' it feeds no pricing engine in QL 1.43: 'CPICapFloor' prices+-- purely off 'QuantLib.TermStructure.InflationVolatility.CPICapFloorTermPriceSurface' via+-- 'QuantLib.PricingEngine.interpolatingCPICapFloorEngine', and 'CPICouponPricer' (the type that+-- would consume this) is itself explicitly unfinished upstream for vol-dependent coupons (no+-- concrete descendant exists to bind, unlike 'YoYInflationCouponPricer's three) -- so this type+-- stands alone as a queryable surface, not (yet) as engine\/pricer plumbing.+type CPIVolatilitySurface = GenVolatilityTermStructure CCPIVolatilitySurface type GenBlackVolTermStructure bv = GenVolatilityTermStructure (AnyOf CBlackVolTermStructure' bv) type CBlackVolTermStructure = ForeignPtr CBlackVolTermStructure' type BlackVolTermStructure = GenBlackVolTermStructure CBlackVolTermStructure@@ -1045,6 +1327,34 @@ type ZeroInflationTermStructure = GenTermStructure CZeroInflationTermStructure type CYoYInflationTermStructure = ForeignPtr CYoYInflationTermStructure' type YoYInflationTermStructure = GenTermStructure CYoYInflationTermStructure+type CCommodityCurve = ForeignPtr CCommodityCurve'+-- | A plain 'TermStructure' leaf (not a 'YieldTermStructure' -- it has no discount-factor+-- semantics, just an interpolated price curve), constructed and consumed by @shared_ptr@ like+-- 'CallableBondVolatilityStructure'\/'DefaultProbabilityTermStructure', never a @Handle@.+type CommodityCurve = GenTermStructure CCommodityCurve+data CYoYCapFloorTermPriceSurface'+type CYoYCapFloorTermPriceSurface = ForeignPtr CYoYCapFloorTermPriceSurface'+-- | Prices YoY cap\/floors by cap\/floor-surface intersection and put\/call parity, deriving an+-- ATM YoY swap curve as a side effect -- the market-data input the YoY optionlet stripper+-- ('QuantLib.TermStructure.InflationVolatility.kInterpolatedYoYOptionletVolatilitySurfaceBlack'+-- et al.) bootstraps from. A plain 'TermStructure' leaf, constructed and consumed by+-- @shared_ptr@ like 'CPICapFloorTermPriceSurface', never a @Handle@. Takes independent+-- 'Interpolation2D' (cap\/floor price grid) and 'Interpolation' (per-maturity) choices --+-- a different template (@InterpolatedYoYCapFloorTermPriceSurface@) from+-- 'CPICapFloorTermPriceSurface's @InterpolatedCPICapFloorTermPriceSurface@, hence the separate+-- 2-D\/1-D pair rather than 'CPICapFloorTermPriceSurface's single 'Interpolation2D'.+type YoYCapFloorTermPriceSurface = GenTermStructure CYoYCapFloorTermPriceSurface+data CCPICapFloorTermPriceSurface'+type CCPICapFloorTermPriceSurface = ForeignPtr CCPICapFloorTermPriceSurface'+-- | Prices CPI cap\/floors by interpolation and put\/call parity off a market strike\/maturity+-- price grid, not by any vol model (see 'CPICapFloor's own comment) -- a plain 'TermStructure'+-- leaf, constructed and consumed by @shared_ptr@ like 'CommodityCurve', never a @Handle@ (wrapped+-- into one at the point of use, e.g. 'QuantLib.PricingEngine.interpolatingCPICapFloorEngine').+-- Takes an 'Interpolation2D' choice for the cap\/floor price grid -- a different template+-- (@InterpolatedCPICapFloorTermPriceSurface@) from 'YoYCapFloorTermPriceSurface's+-- @InterpolatedYoYCapFloorTermPriceSurface@, hence its own single 2-D slot rather than+-- 'YoYCapFloorTermPriceSurface's separate 2-D\/1-D pair.+type CPICapFloorTermPriceSurface = GenTermStructure CCPICapFloorTermPriceSurface foreign import ccall unsafe "ql.h &qlFreeTermStructure" qlFreeTermStructure :: FinalizerPtr CTermStructure' foreign import ccall unsafe "ql.h &qlFreeVolatilityTermStructure" qlFreeVolatilityTermStructure :: FinalizerPtr CVolatilityTermStructure' foreign import ccall unsafe "ql.h &qlFreeOptionletVolatilityStructure" qlFreeOptionletVolatilityStructure :: FinalizerPtr COptionletVolatilityStructure'@@ -1053,8 +1363,16 @@ foreign import ccall unsafe "ql.h &qlFreeRelinkableSwaptionVolatilityStructure" qlFreeRelinkableSwaptionVolatilityStructure :: FinalizerPtr CRelinkableSwaptionVolatilityStructure' foreign import ccall unsafe "ql.h &qlFreeSabrSwaptionVolatilityCube" qlFreeSabrSwaptionVolatilityCube :: FinalizerPtr CSabrSwaptionVolatilityCube' foreign import ccall unsafe "ql.h &qlFreeInterpolatedSwaptionVolatilityCube" qlFreeInterpolatedSwaptionVolatilityCube :: FinalizerPtr CInterpolatedSwaptionVolatilityCube'+foreign import ccall unsafe "ql.h &qlFreeCapFloorTermVolatilityStructure" qlFreeCapFloorTermVolatilityStructure :: FinalizerPtr CCapFloorTermVolatilityStructure'+foreign import ccall unsafe "ql.h &qlFreeCapFloorTermVolCurve" qlFreeCapFloorTermVolCurve :: FinalizerPtr CCapFloorTermVolCurve' foreign import ccall unsafe "ql.h &qlFreeCapFloorTermVolSurface" qlFreeCapFloorTermVolSurface :: FinalizerPtr CCapFloorTermVolSurface'+foreign import ccall unsafe "ql.h &qlFreeBlackAtmVolCurve" qlFreeBlackAtmVolCurve :: FinalizerPtr CBlackAtmVolCurve'+foreign import ccall unsafe "ql.h &qlFreeBlackVolSurface" qlFreeBlackVolSurface :: FinalizerPtr CBlackVolSurface'+foreign import ccall unsafe "ql.h &qlFreeAbcdAtmVolCurve" qlFreeAbcdAtmVolCurve :: FinalizerPtr CAbcdAtmVolCurve'+foreign import ccall unsafe "ql.h &qlFreeSabrVolSurface" qlFreeSabrVolSurface :: FinalizerPtr CSabrVolSurface' foreign import ccall unsafe "ql.h &qlFreeLocalVolTermStructure" qlFreeLocalVolTermStructure :: FinalizerPtr CLocalVolTermStructure'+foreign import ccall unsafe "ql.h &qlFreeYoYOptionletVolatilitySurface" qlFreeYoYOptionletVolatilitySurface :: FinalizerPtr CYoYOptionletVolatilitySurface'+foreign import ccall unsafe "ql.h &qlFreeCPIVolatilitySurface" qlFreeCPIVolatilitySurface :: FinalizerPtr CCPIVolatilitySurface' foreign import ccall unsafe "ql.h &qlFreeBlackVolTermStructure" qlFreeBlackVolTermStructure :: FinalizerPtr CBlackVolTermStructure' foreign import ccall unsafe "ql.h &qlFreeRelinkableBlackVolTermStructure" qlFreeRelinkableBlackVolTermStructure :: FinalizerPtr CRelinkableBlackVolTermStructure' foreign import ccall unsafe "ql.h &qlFreeBlackVarianceCurve" qlFreeBlackVarianceCurve :: FinalizerPtr CBlackVarianceCurve'@@ -1066,6 +1384,9 @@ foreign import ccall unsafe "ql.h &qlFreeDefaultProbabilityTermStructure" qlFreeDefaultProbabilityTermStructure :: FinalizerPtr CDefaultProbabilityTermStructure' foreign import ccall unsafe "ql.h &qlFreeZeroInflationTermStructure" qlFreeZeroInflationTermStructure :: FinalizerPtr CZeroInflationTermStructure' foreign import ccall unsafe "ql.h &qlFreeYoYInflationTermStructure" qlFreeYoYInflationTermStructure :: FinalizerPtr CYoYInflationTermStructure'+foreign import ccall unsafe "ql.h &qlFreeYoYCapFloorTermPriceSurface" qlFreeYoYCapFloorTermPriceSurface :: FinalizerPtr CYoYCapFloorTermPriceSurface'+foreign import ccall unsafe "ql.h &qlFreeCPICapFloorTermPriceSurface" qlFreeCPICapFloorTermPriceSurface :: FinalizerPtr CCPICapFloorTermPriceSurface'+foreign import ccall unsafe "ql.h &qlFreeCommodityCurve" qlFreeCommodityCurve :: FinalizerPtr CCommodityCurve' instance Finalizable CTermStructure' where finalize = qlFreeTermStructure instance Finalizable CVolatilityTermStructure' where finalize = qlFreeVolatilityTermStructure instance Finalizable COptionletVolatilityStructure' where finalize = qlFreeOptionletVolatilityStructure@@ -1074,8 +1395,16 @@ instance Finalizable CRelinkableSwaptionVolatilityStructure' where finalize = qlFreeRelinkableSwaptionVolatilityStructure instance Finalizable CSabrSwaptionVolatilityCube' where finalize = qlFreeSabrSwaptionVolatilityCube instance Finalizable CInterpolatedSwaptionVolatilityCube' where finalize = qlFreeInterpolatedSwaptionVolatilityCube+instance Finalizable CCapFloorTermVolatilityStructure' where finalize = qlFreeCapFloorTermVolatilityStructure+instance Finalizable CCapFloorTermVolCurve' where finalize = qlFreeCapFloorTermVolCurve instance Finalizable CCapFloorTermVolSurface' where finalize = qlFreeCapFloorTermVolSurface+instance Finalizable CBlackAtmVolCurve' where finalize = qlFreeBlackAtmVolCurve+instance Finalizable CBlackVolSurface' where finalize = qlFreeBlackVolSurface+instance Finalizable CAbcdAtmVolCurve' where finalize = qlFreeAbcdAtmVolCurve+instance Finalizable CSabrVolSurface' where finalize = qlFreeSabrVolSurface instance Finalizable CLocalVolTermStructure' where finalize = qlFreeLocalVolTermStructure+instance Finalizable CYoYOptionletVolatilitySurface' where finalize = qlFreeYoYOptionletVolatilitySurface+instance Finalizable CCPIVolatilitySurface' where finalize = qlFreeCPIVolatilitySurface instance Finalizable CBlackVolTermStructure' where finalize = qlFreeBlackVolTermStructure instance Finalizable CRelinkableBlackVolTermStructure' where finalize = qlFreeRelinkableBlackVolTermStructure instance Finalizable CBlackVarianceCurve' where finalize = qlFreeBlackVarianceCurve@@ -1087,6 +1416,9 @@ instance Finalizable CDefaultProbabilityTermStructure' where finalize = qlFreeDefaultProbabilityTermStructure instance Finalizable CZeroInflationTermStructure' where finalize = qlFreeZeroInflationTermStructure instance Finalizable CYoYInflationTermStructure' where finalize = qlFreeYoYInflationTermStructure+instance Finalizable CYoYCapFloorTermPriceSurface' where finalize = qlFreeYoYCapFloorTermPriceSurface+instance Finalizable CCPICapFloorTermPriceSurface' where finalize = qlFreeCPICapFloorTermPriceSurface+instance Finalizable CCommodityCurve' where finalize = qlFreeCommodityCurve foreign import ccall "ql.h qlYieldTermStructureAsTermStructure" qlYieldTermStructureAsTermStructure :: Ptr CYieldTermStructure' -> IO (Ptr CTermStructure') foreign import ccall "ql.h qlFittedBondDiscountCurveAsYieldTermStructure" qlFittedBondDiscountCurveAsYieldTermStructure :: Ptr CFittedBondDiscountCurve' -> IO (Ptr CYieldTermStructure') foreign import ccall "ql.h qlRelinkableYieldTermStructureAsYieldTermStructure" qlRelinkableYieldTermStructureAsYieldTermStructure :: Ptr CRelinkableYieldTermStructure' -> IO (Ptr CYieldTermStructure')@@ -1101,12 +1433,23 @@ foreign import ccall "ql.h qlRelinkableSwaptionVolatilityStructureAsSwaptionVolatilityStructure" qlRelinkableSwaptionVolatilityStructureAsSwaptionVolatilityStructure :: Ptr CRelinkableSwaptionVolatilityStructure' -> IO (Ptr CSwaptionVolatilityStructure') foreign import ccall "ql.h qlSabrSwaptionVolatilityCubeAsSwaptionVolatilityStructure" qlSabrSwaptionVolatilityCubeAsSwaptionVolatilityStructure :: Ptr CSabrSwaptionVolatilityCube' -> IO (Ptr CSwaptionVolatilityStructure') foreign import ccall "ql.h qlInterpolatedSwaptionVolatilityCubeAsSwaptionVolatilityStructure" qlInterpolatedSwaptionVolatilityCubeAsSwaptionVolatilityStructure :: Ptr CInterpolatedSwaptionVolatilityCube' -> IO (Ptr CSwaptionVolatilityStructure')-foreign import ccall "ql.h qlCapFloorTermVolSurfaceAsVolatilityTermStructure" qlCapFloorTermVolSurfaceAsVolatilityTermStructure :: Ptr CCapFloorTermVolSurface' -> IO (Ptr CVolatilityTermStructure')+foreign import ccall "ql.h qlCapFloorTermVolatilityStructureAsVolatilityTermStructure" qlCapFloorTermVolatilityStructureAsVolatilityTermStructure :: Ptr CCapFloorTermVolatilityStructure' -> IO (Ptr CVolatilityTermStructure')+foreign import ccall "ql.h qlCapFloorTermVolCurveAsCapFloorTermVolatilityStructure" qlCapFloorTermVolCurveAsCapFloorTermVolatilityStructure :: Ptr CCapFloorTermVolCurve' -> IO (Ptr CCapFloorTermVolatilityStructure')+foreign import ccall "ql.h qlCapFloorTermVolSurfaceAsCapFloorTermVolatilityStructure" qlCapFloorTermVolSurfaceAsCapFloorTermVolatilityStructure :: Ptr CCapFloorTermVolSurface' -> IO (Ptr CCapFloorTermVolatilityStructure')+foreign import ccall "ql.h qlBlackAtmVolCurveAsVolatilityTermStructure" qlBlackAtmVolCurveAsVolatilityTermStructure :: Ptr CBlackAtmVolCurve' -> IO (Ptr CVolatilityTermStructure')+foreign import ccall "ql.h qlBlackVolSurfaceAsBlackAtmVolCurve" qlBlackVolSurfaceAsBlackAtmVolCurve :: Ptr CBlackVolSurface' -> IO (Ptr CBlackAtmVolCurve')+foreign import ccall "ql.h qlAbcdAtmVolCurveAsBlackAtmVolCurve" qlAbcdAtmVolCurveAsBlackAtmVolCurve :: Ptr CAbcdAtmVolCurve' -> IO (Ptr CBlackAtmVolCurve')+foreign import ccall "ql.h qlSabrVolSurfaceAsBlackVolSurface" qlSabrVolSurfaceAsBlackVolSurface :: Ptr CSabrVolSurface' -> IO (Ptr CBlackVolSurface') foreign import ccall "ql.h qlLocalVolTermStructureAsVolatilityTermStructure" qlLocalVolTermStructureAsVolatilityTermStructure :: Ptr CLocalVolTermStructure' -> IO (Ptr CVolatilityTermStructure')+foreign import ccall "ql.h qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure" qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure :: Ptr CYoYOptionletVolatilitySurface' -> IO (Ptr CVolatilityTermStructure')+foreign import ccall "ql.h qlCPIVolatilitySurfaceAsVolatilityTermStructure" qlCPIVolatilitySurfaceAsVolatilityTermStructure :: Ptr CCPIVolatilitySurface' -> IO (Ptr CVolatilityTermStructure') foreign import ccall "ql.h qlCallableBondVolatilityStructureAsTermStructure" qlCallableBondVolatilityStructureAsTermStructure :: Ptr CCallableBondVolatilityStructure' -> IO (Ptr CTermStructure') foreign import ccall "ql.h qlDefaultProbabilityTermStructureAsTermStructure" qlDefaultProbabilityTermStructureAsTermStructure :: Ptr CDefaultProbabilityTermStructure' -> IO (Ptr CTermStructure') foreign import ccall "ql.h qlZeroInflationTermStructureAsTermStructure" qlZeroInflationTermStructureAsTermStructure :: Ptr CZeroInflationTermStructure' -> IO (Ptr CTermStructure') foreign import ccall "ql.h qlYoYInflationTermStructureAsTermStructure" qlYoYInflationTermStructureAsTermStructure :: Ptr CYoYInflationTermStructure' -> IO (Ptr CTermStructure')+foreign import ccall "ql.h qlYoYCapFloorTermPriceSurfaceAsTermStructure" qlYoYCapFloorTermPriceSurfaceAsTermStructure :: Ptr CYoYCapFloorTermPriceSurface' -> IO (Ptr CTermStructure')+foreign import ccall "ql.h qlCPICapFloorTermPriceSurfaceAsTermStructure" qlCPICapFloorTermPriceSurfaceAsTermStructure :: Ptr CCPICapFloorTermPriceSurface' -> IO (Ptr CTermStructure')+foreign import ccall "ql.h qlCommodityCurveAsTermStructure" qlCommodityCurveAsTermStructure :: Ptr CCommodityCurve' -> IO (Ptr CTermStructure') instance Upcastable CYieldTermStructure' where {type Base CYieldTermStructure' = CTermStructure'; upcast = qlYieldTermStructureAsTermStructure} instance Upcastable CFittedBondDiscountCurve' where {type Base CFittedBondDiscountCurve' = CYieldTermStructure'; upcast = qlFittedBondDiscountCurveAsYieldTermStructure} instance Upcastable CRelinkableYieldTermStructure' where {type Base CRelinkableYieldTermStructure' = CYieldTermStructure'; upcast = qlRelinkableYieldTermStructureAsYieldTermStructure}@@ -1115,6 +1458,9 @@ instance Upcastable CDefaultProbabilityTermStructure' where {type Base CDefaultProbabilityTermStructure' = CTermStructure'; upcast = qlDefaultProbabilityTermStructureAsTermStructure} instance Upcastable CZeroInflationTermStructure' where {type Base CZeroInflationTermStructure' = CTermStructure'; upcast = qlZeroInflationTermStructureAsTermStructure} instance Upcastable CYoYInflationTermStructure' where {type Base CYoYInflationTermStructure' = CTermStructure'; upcast = qlYoYInflationTermStructureAsTermStructure}+instance Upcastable CYoYCapFloorTermPriceSurface' where {type Base CYoYCapFloorTermPriceSurface' = CTermStructure'; upcast = qlYoYCapFloorTermPriceSurfaceAsTermStructure}+instance Upcastable CCPICapFloorTermPriceSurface' where {type Base CCPICapFloorTermPriceSurface' = CTermStructure'; upcast = qlCPICapFloorTermPriceSurfaceAsTermStructure}+instance Upcastable CCommodityCurve' where {type Base CCommodityCurve' = CTermStructure'; upcast = qlCommodityCurveAsTermStructure} instance Upcastable CBlackVolTermStructure' where {type Base CBlackVolTermStructure' = CVolatilityTermStructure'; upcast = qlBlackVolTermStructureAsVolatilityTermStructure} instance Upcastable CRelinkableBlackVolTermStructure' where {type Base CRelinkableBlackVolTermStructure' = CBlackVolTermStructure'; upcast = qlRelinkableBlackVolTermStructureAsBlackVolTermStructure} instance Upcastable CBlackVarianceCurve' where {type Base CBlackVarianceCurve' = CBlackVolTermStructure'; upcast = qlBlackVarianceCurveAsBlackVolTermStructure}@@ -1125,8 +1471,16 @@ instance Upcastable CRelinkableSwaptionVolatilityStructure' where {type Base CRelinkableSwaptionVolatilityStructure' = CSwaptionVolatilityStructure'; upcast = qlRelinkableSwaptionVolatilityStructureAsSwaptionVolatilityStructure} instance Upcastable CSabrSwaptionVolatilityCube' where {type Base CSabrSwaptionVolatilityCube' = CSwaptionVolatilityStructure'; upcast = qlSabrSwaptionVolatilityCubeAsSwaptionVolatilityStructure} instance Upcastable CInterpolatedSwaptionVolatilityCube' where {type Base CInterpolatedSwaptionVolatilityCube' = CSwaptionVolatilityStructure'; upcast = qlInterpolatedSwaptionVolatilityCubeAsSwaptionVolatilityStructure}-instance Upcastable CCapFloorTermVolSurface' where {type Base CCapFloorTermVolSurface' = CVolatilityTermStructure'; upcast = qlCapFloorTermVolSurfaceAsVolatilityTermStructure}+instance Upcastable CCapFloorTermVolatilityStructure' where {type Base CCapFloorTermVolatilityStructure' = CVolatilityTermStructure'; upcast = qlCapFloorTermVolatilityStructureAsVolatilityTermStructure}+instance Upcastable CCapFloorTermVolCurve' where {type Base CCapFloorTermVolCurve' = CCapFloorTermVolatilityStructure'; upcast = qlCapFloorTermVolCurveAsCapFloorTermVolatilityStructure}+instance Upcastable CCapFloorTermVolSurface' where {type Base CCapFloorTermVolSurface' = CCapFloorTermVolatilityStructure'; upcast = qlCapFloorTermVolSurfaceAsCapFloorTermVolatilityStructure}+instance Upcastable CBlackAtmVolCurve' where {type Base CBlackAtmVolCurve' = CVolatilityTermStructure'; upcast = qlBlackAtmVolCurveAsVolatilityTermStructure}+instance Upcastable CBlackVolSurface' where {type Base CBlackVolSurface' = CBlackAtmVolCurve'; upcast = qlBlackVolSurfaceAsBlackAtmVolCurve}+instance Upcastable CAbcdAtmVolCurve' where {type Base CAbcdAtmVolCurve' = CBlackAtmVolCurve'; upcast = qlAbcdAtmVolCurveAsBlackAtmVolCurve}+instance Upcastable CSabrVolSurface' where {type Base CSabrVolSurface' = CBlackVolSurface'; upcast = qlSabrVolSurfaceAsBlackVolSurface} instance Upcastable CLocalVolTermStructure' where {type Base CLocalVolTermStructure' = CVolatilityTermStructure'; upcast = qlLocalVolTermStructureAsVolatilityTermStructure}+instance Upcastable CYoYOptionletVolatilitySurface' where {type Base CYoYOptionletVolatilitySurface' = CVolatilityTermStructure'; upcast = qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure}+instance Upcastable CCPIVolatilitySurface' where {type Base CCPIVolatilitySurface' = CVolatilityTermStructure'; upcast = qlCPIVolatilitySurfaceAsVolatilityTermStructure} asTermStructure :: GenTermStructure t -> IO TermStructure asTermStructure = transferGenForeignPtr peekTermStructure . getTermStructure withTermStructure :: GenTermStructure t  -> (Ptr CTermStructure' -> IO b) -> IO b@@ -1205,10 +1559,44 @@ peekInterpolatedSwaptionVolatilityCube = newGenForeignPtr >=> newGenSwaptionVolatilityStructure withInterpolatedSwaptionVolatilityCube :: InterpolatedSwaptionVolatilityCube -> (Ptr CInterpolatedSwaptionVolatilityCube' -> IO b) -> IO b withInterpolatedSwaptionVolatilityCube = withForeignPtr . ptr . peel . peel . getTermStructure+peekCapFloorTermVolatilityStructure :: Ptr CCapFloorTermVolatilityStructure' -> IO CapFloorTermVolatilityStructure+peekCapFloorTermVolatilityStructure = newCastForeignPtr >=> newGenCapFloorTermVolatilityStructure+withGenCapFloorTermVolatilityStructure :: GenCapFloorTermVolatilityStructure c -> (Ptr CCapFloorTermVolatilityStructure' -> IO b) -> IO b+withGenCapFloorTermVolatilityStructure = withGenForeignPtr . peel . peel . getTermStructure+newGenCapFloorTermVolatilityStructure :: GenForeignPtr c CCapFloorTermVolatilityStructure' -> IO (GenCapFloorTermVolatilityStructure c)+newGenCapFloorTermVolatilityStructure = pure . GenTermStructure . newAnyOf . newAnyOf+peekCapFloorTermVolCurve :: Ptr CCapFloorTermVolCurve' -> IO CapFloorTermVolCurve+peekCapFloorTermVolCurve = newGenForeignPtr >=> newGenCapFloorTermVolatilityStructure+withCapFloorTermVolCurve :: CapFloorTermVolCurve -> (Ptr CCapFloorTermVolCurve' -> IO b) -> IO b+withCapFloorTermVolCurve = withForeignPtr . ptr . peel . peel . getTermStructure peekCapFloorTermVolSurface :: Ptr CCapFloorTermVolSurface' -> IO CapFloorTermVolSurface-peekCapFloorTermVolSurface = peekGenVolatilityTermStructure+peekCapFloorTermVolSurface = newGenForeignPtr >=> newGenCapFloorTermVolatilityStructure+withCapFloorTermVolSurface :: CapFloorTermVolSurface -> (Ptr CCapFloorTermVolSurface' -> IO b) -> IO b+withCapFloorTermVolSurface = withForeignPtr . ptr . peel . peel . getTermStructure+peekBlackAtmVolCurve :: Ptr CBlackAtmVolCurve' -> IO BlackAtmVolCurve+peekBlackAtmVolCurve = newCastForeignPtr >=> newGenBlackAtmVolCurve+withGenBlackAtmVolCurve :: GenBlackAtmVolCurve b -> (Ptr CBlackAtmVolCurve' -> IO r) -> IO r+withGenBlackAtmVolCurve = withGenForeignPtr . peel . peel . getTermStructure+newGenBlackAtmVolCurve :: GenForeignPtr b CBlackAtmVolCurve' -> IO (GenBlackAtmVolCurve b)+newGenBlackAtmVolCurve = pure . GenTermStructure . newAnyOf . newAnyOf+peekAbcdAtmVolCurve :: Ptr CAbcdAtmVolCurve' -> IO AbcdAtmVolCurve+peekAbcdAtmVolCurve = newGenForeignPtr >=> newGenBlackAtmVolCurve+withAbcdAtmVolCurve :: AbcdAtmVolCurve -> (Ptr CAbcdAtmVolCurve' -> IO b) -> IO b+withAbcdAtmVolCurve = withForeignPtr . ptr . peel . peel . getTermStructure+withGenBlackVolSurface :: GenBlackVolSurface b -> (Ptr CBlackVolSurface' -> IO r) -> IO r+withGenBlackVolSurface = withGenForeignPtr . peel . peel . peel . getTermStructure+newGenBlackVolSurface :: GenForeignPtr b CBlackVolSurface' -> IO (GenBlackVolSurface b)+newGenBlackVolSurface = pure . GenTermStructure . newAnyOf . newAnyOf . newAnyOf+peekSabrVolSurface :: Ptr CSabrVolSurface' -> IO SabrVolSurface+peekSabrVolSurface = newGenForeignPtr >=> newGenBlackVolSurface+withSabrVolSurface :: SabrVolSurface -> (Ptr CSabrVolSurface' -> IO b) -> IO b+withSabrVolSurface = withForeignPtr . ptr . peel . peel . peel . getTermStructure peekLocalVolTermStructure :: Ptr CLocalVolTermStructure' -> IO LocalVolTermStructure peekLocalVolTermStructure = peekGenVolatilityTermStructure+peekYoYOptionletVolatilityStructure :: Ptr CYoYOptionletVolatilitySurface' -> IO YoYOptionletVolatilitySurface+peekYoYOptionletVolatilityStructure = peekGenVolatilityTermStructure+peekCPIVolatilitySurface :: Ptr CCPIVolatilitySurface' -> IO CPIVolatilitySurface+peekCPIVolatilitySurface = peekGenVolatilityTermStructure withLocalVolTermStructure :: LocalVolTermStructure -> (Ptr CLocalVolTermStructure' -> IO b) -> IO b withLocalVolTermStructure = withGenVolatilityTermStructure withMaybeLocalVolTermStructure :: Maybe LocalVolTermStructure -> (Ptr CLocalVolTermStructure' -> IO b) -> IO b@@ -1227,6 +1615,21 @@ peekYoYInflationTermStructure = GenTermStructure <.> newGenForeignPtr withMaybeYoYInflationTermStructure :: Maybe YoYInflationTermStructure -> (Ptr CYoYInflationTermStructure' -> IO b) -> IO b withMaybeYoYInflationTermStructure x f = maybe (f nullPtr) (`withGenTermStructure` f) x+peekYoYCapFloorTermPriceSurface :: Ptr CYoYCapFloorTermPriceSurface' -> IO YoYCapFloorTermPriceSurface+peekYoYCapFloorTermPriceSurface = GenTermStructure <.> newGenForeignPtr+peekCPICapFloorTermPriceSurface :: Ptr CCPICapFloorTermPriceSurface' -> IO CPICapFloorTermPriceSurface+peekCPICapFloorTermPriceSurface = GenTermStructure <.> newGenForeignPtr+peekCommodityCurve :: Ptr CCommodityCurve' -> IO CommodityCurve+peekCommodityCurve = GenTermStructure <.> newGenForeignPtr+withMaybeCommodityCurve :: Maybe CommodityCurve -> (Ptr CCommodityCurve' -> IO b) -> IO b+withMaybeCommodityCurve x f = maybe (f nullPtr) (`withGenTermStructure` f) x+-- |Peek a possibly-null @CommodityCurve*@ -- @basisOfCurve_@ is a @nullptr@ 'shared_ptr' when no+-- basis curve has been set via 'QuantLib.TermStructure.Commodity.setCommodityCurveBasisOfCurve',+-- not an empty-'Data'-style placeholder (unlike 'peekMaybeCommodityType' et al.).+peekMaybeCommodityCurve :: Ptr CCommodityCurve' -> IO (Maybe CommodityCurve)+peekMaybeCommodityCurve p+  | p == nullPtr = pure Nothing+  | otherwise = Just <$> peekCommodityCurve p  asYieldTermStructure :: GenYieldTermStructure y -> IO YieldTermStructure asYieldTermStructure = transferGenForeignPtr peekYieldTermStructure . peel . getTermStructure@@ -1676,24 +2079,26 @@ foreign import ccall "ql.h qlG2AsAffineModel" qlG2AsAffineModel :: Ptr CG2' -> IO (Ptr CAffineModel') foreign import ccall "ql.h qlHullWhiteAsAffineModel" qlHullWhiteAsAffineModel :: Ptr CHullWhite' -> IO (Ptr CAffineModel') -data AffineModel = HullWhite HullWhite | G2 G2 | OneFactorAffineModel OneFactorAffineModel | LiborForwardModel LiborForwardModel-withUpcast :: Finalizable b => (Ptr a -> IO (Ptr b)) -> (Ptr b -> IO r) -> Ptr a -> IO r-withUpcast up f p = bracket (up p) freeUpcast f-withAffineModel :: AffineModel -> (Ptr CAffineModel' -> IO b) -> IO b-withAffineModel (HullWhite m) f = withHullWhite m (withUpcast qlHullWhiteAsAffineModel f)-withAffineModel (G2 m) f = withG2 m (withUpcast qlG2AsAffineModel f)-withAffineModel (OneFactorAffineModel m) f = withOneFactorAffineModel m (withUpcast qlOneFactorAffineModelAsAffineModel f)-withAffineModel (LiborForwardModel m) f = withGenCalibratedModel m (withUpcast qlLiborForwardModelAsAffineModel f)+type AffineModel = Standalone CAffineModel'+hullWhiteAsAffineModel :: HullWhite -> IO AffineModel+hullWhiteAsAffineModel m = withHullWhite m qlHullWhiteAsAffineModel >>= peekStandalone+g2AsAffineModel :: G2 -> IO AffineModel+g2AsAffineModel m = withG2 m qlG2AsAffineModel >>= peekStandalone+oneFactorAffineModelAsAffineModel :: OneFactorAffineModel -> IO AffineModel+oneFactorAffineModelAsAffineModel m = withOneFactorAffineModel m qlOneFactorAffineModelAsAffineModel >>= peekStandalone+liborForwardModelAsAffineModel :: LiborForwardModel -> IO AffineModel+liborForwardModelAsAffineModel m = withGenCalibratedModel m qlLiborForwardModelAsAffineModel >>= peekStandalone  data CGaussian1dModel' foreign import ccall unsafe "ql.h &qlFreeGaussian1dModel" qlFreeGaussian1dModel :: FinalizerPtr CGaussian1dModel' instance Finalizable CGaussian1dModel' where finalize = qlFreeGaussian1dModel foreign import ccall "ql.h qlGsrAsGaussian1dModel" qlGsrAsGaussian1dModel :: Ptr CGsr' -> IO (Ptr CGaussian1dModel') foreign import ccall "ql.h qlMarkovFunctionalAsGaussian1dModel" qlMarkovFunctionalAsGaussian1dModel :: Ptr CMarkovFunctional' -> IO (Ptr CGaussian1dModel')-data Gaussian1dModel = Gsr Gsr | MarkovFunctional MarkovFunctional-withGaussian1dModel :: Gaussian1dModel -> (Ptr CGaussian1dModel' -> IO b) -> IO b-withGaussian1dModel (Gsr m) f = withGenCalibratedModel m (withUpcast qlGsrAsGaussian1dModel f)-withGaussian1dModel (MarkovFunctional m) f = withGenCalibratedModel m (withUpcast qlMarkovFunctionalAsGaussian1dModel f)+type Gaussian1dModel = Standalone CGaussian1dModel'+gsrAsGaussian1dModel :: Gsr -> IO Gaussian1dModel+gsrAsGaussian1dModel m = withGenCalibratedModel m qlGsrAsGaussian1dModel >>= peekStandalone+markovFunctionalAsGaussian1dModel :: MarkovFunctional -> IO Gaussian1dModel+markovFunctionalAsGaussian1dModel m = withGenCalibratedModel m qlMarkovFunctionalAsGaussian1dModel >>= peekStandalone  -- | > Instrument* -- >  Forward*@@ -1709,13 +2114,19 @@ -- >    OneAssetOption -- >      BarrierOption -- >      DoubleBarrierOption+-- >      SoftBarrierOption -- >      VanillaOption -- >      QuantoVanillaOption -- >      QuantoForwardVanillaOption -- >      QuantoBarrierOption -- >    Swaption+-- >    NonstandardSwaption+-- >    FloatFloatSwaption -- >  Swap*--- >    VanillaSwap+-- >    FixedVsFloatingSwap*+-- >      VanillaSwap+-- >    NonstandardSwap+-- >    FloatFloatSwap -- >    AssetSwap -- >    BMASwap -- >    OvernightIndexedSwap@@ -1724,13 +2135,24 @@ -- >    CPISwap -- >    ZeroCouponSwap -- >    EquityTotalReturnSwap+-- >    ConstNotionalCrossCurrencySwap+-- >      ConstNotionalCrossCurrencyBasisSwap+-- >      ConstNotionalCrossCurrencyFixedVsFloatingSwap -- >  CreditDefaultSwap -- >  CapFloor+-- >  YoYInflationCapFloor+-- >  CPICapFloor -- >  Bond -- >    ConvertibleBond -- >    FixedRateBond -- >    CallableBond -- >    CPIBond+-- >  Commodity*+-- >    EnergyCommodity*+-- >      EnergyFuture+-- >      EnergySwap*+-- >        EnergyVanillaSwap+-- >        EnergyBasisSwap type Instrument = GenInstrument CInstrument data CInstrument' newtype GenInstrument i = GenInstrument {getInstrument :: GenForeignPtr i CInstrument'}@@ -1806,6 +2228,35 @@ peekCapFloor :: Ptr CCapFloor' -> IO CapFloor peekCapFloor = GenInstrument <.> newGenForeignPtr +data CYoYInflationCapFloor'+type CYoYInflationCapFloor = ForeignPtr CYoYInflationCapFloor'+-- | A YoY-inflation cap\/floor\/collar (all three are thin ctor-only subclasses upstream with+-- no logic of their own, so 'QuantLib.Instrument.InflationCapFloor.yoyInflationCap'\/+-- 'yoyInflationCollar'\/'yoyInflationFloor' each construct this one flat leaf directly, mirroring+-- how 'CapFloor' collapses @Cap@\/@Collar@\/@Floor@). Unlike 'CapFloor', it shares no C++ base+-- below 'Instrument' with the nominal cap/floor, so it's a separate sibling leaf, not a subtype.+type YoYInflationCapFloor = GenInstrument CYoYInflationCapFloor+foreign import ccall unsafe "ql.h &qlFreeYoYInflationCapFloor" qlFreeYoYInflationCapFloor :: FinalizerPtr CYoYInflationCapFloor'+instance Finalizable CYoYInflationCapFloor' where finalize = qlFreeYoYInflationCapFloor+foreign import ccall "ql.h qlYoYInflationCapFloorAsInstrument" qlYoYInflationCapFloorAsInstrument :: Ptr CYoYInflationCapFloor' -> IO (Ptr CInstrument')+instance Upcastable CYoYInflationCapFloor' where {type Base CYoYInflationCapFloor' = CInstrument'; upcast = qlYoYInflationCapFloorAsInstrument}+peekYoYInflationCapFloor :: Ptr CYoYInflationCapFloor' -> IO YoYInflationCapFloor+peekYoYInflationCapFloor = GenInstrument <.> newGenForeignPtr++data CCPICapFloor'+type CCPICapFloor = ForeignPtr CCPICapFloor'+-- | A CPI cap\/floor: unlike 'YoYInflationCapFloor', a single cumulative option (observes+-- cumulative inflation up to maturity, like a ZCIIS option) rather than a strip of optionlets --+-- flat sibling leaf under 'Instrument', sharing no C++ base with either 'CapFloor' or+-- 'YoYInflationCapFloor'.+type CPICapFloor = GenInstrument CCPICapFloor+foreign import ccall unsafe "ql.h &qlFreeCPICapFloor" qlFreeCPICapFloor :: FinalizerPtr CCPICapFloor'+instance Finalizable CCPICapFloor' where finalize = qlFreeCPICapFloor+foreign import ccall "ql.h qlCPICapFloorAsInstrument" qlCPICapFloorAsInstrument :: Ptr CCPICapFloor' -> IO (Ptr CInstrument')+instance Upcastable CCPICapFloor' where {type Base CCPICapFloor' = CInstrument'; upcast = qlCPICapFloorAsInstrument}+peekCPICapFloor :: Ptr CCPICapFloor' -> IO CPICapFloor+peekCPICapFloor = GenInstrument <.> newGenForeignPtr+ data CForward' type GenForward f = GenInstrument (AnyOf CForward' f) type CForward = ForeignPtr CForward'@@ -1950,18 +2401,114 @@ withCallableBond :: CallableBond -> (Ptr CCallableBond' -> IO b) -> IO b withCallableBond = withForeignPtr . ptr . peel . getInstrument +-- FixedVsFloatingSwap sits between Swap and VanillaSwap (upstream: VanillaSwap, OvernightIndexedSwap+-- and MultipleResetsSwap all derive from it, but only VanillaSwap is modelled through it here --+-- the others still upcast straight to Swap, collapsing the intermediate level as usual). It earns+-- its own family level (mirrors MultiAssetOption/MargrabeOption's one-more-AnyOf-layer shape)+-- because SwaptionHelper::underlying() (QuantLib/Model.chs) returns exactly this type, and its own+-- getters (fairRate, fairSpread, fixedLeg*, floatingLeg*) are inherited, not VanillaSwap-specific --+-- binding them generically over 'GenFixedVsFloatingSwap' avoids a cast to reach them from that+-- getter's result. FixedVsFloatingSwap itself is abstract upstream (pure virtual+-- setupFloatingArguments), so hasquant binds no constructor for it directly.+data CFixedVsFloatingSwap'+type GenFixedVsFloatingSwap f = GenSwap (AnyOf CFixedVsFloatingSwap' f)+type CFixedVsFloatingSwap = ForeignPtr CFixedVsFloatingSwap'+type FixedVsFloatingSwap = GenFixedVsFloatingSwap CFixedVsFloatingSwap data CVanillaSwap' type CVanillaSwap = ForeignPtr CVanillaSwap'-type VanillaSwap = GenSwap CVanillaSwap+type VanillaSwap = GenFixedVsFloatingSwap CVanillaSwap+foreign import ccall unsafe "ql.h &qlFreeFixedVsFloatingSwap" qlFreeFixedVsFloatingSwap :: FinalizerPtr CFixedVsFloatingSwap' foreign import ccall unsafe "ql.h &qlFreeVanillaSwap" qlFreeVanillaSwap :: FinalizerPtr CVanillaSwap'+instance Finalizable CFixedVsFloatingSwap' where finalize = qlFreeFixedVsFloatingSwap instance Finalizable CVanillaSwap' where finalize = qlFreeVanillaSwap-foreign import ccall "ql.h qlVanillaSwapAsSwap" qlVanillaSwapAsSwap :: Ptr CVanillaSwap' -> IO (Ptr CSwap')-instance Upcastable CVanillaSwap' where {type Base CVanillaSwap' = CSwap'; upcast = qlVanillaSwapAsSwap}+foreign import ccall "ql.h qlFixedVsFloatingSwapAsSwap" qlFixedVsFloatingSwapAsSwap :: Ptr CFixedVsFloatingSwap' -> IO (Ptr CSwap')+foreign import ccall "ql.h qlVanillaSwapAsFixedVsFloatingSwap" qlVanillaSwapAsFixedVsFloatingSwap :: Ptr CVanillaSwap' -> IO (Ptr CFixedVsFloatingSwap')+instance Upcastable CFixedVsFloatingSwap' where {type Base CFixedVsFloatingSwap' = CSwap'; upcast = qlFixedVsFloatingSwapAsSwap}+instance Upcastable CVanillaSwap' where {type Base CVanillaSwap' = CFixedVsFloatingSwap'; upcast = qlVanillaSwapAsFixedVsFloatingSwap}+asFixedVsFloatingSwap :: GenFixedVsFloatingSwap f -> IO FixedVsFloatingSwap+asFixedVsFloatingSwap = transferGenForeignPtr peekFixedVsFloatingSwap . peel . peel . getInstrument+peekFixedVsFloatingSwap :: Ptr CFixedVsFloatingSwap' -> IO FixedVsFloatingSwap+peekFixedVsFloatingSwap = newCastForeignPtr >=> newGenFixedVsFloatingSwap+withFixedVsFloatingSwap :: GenFixedVsFloatingSwap f -> (Ptr CFixedVsFloatingSwap' -> IO b) -> IO b+withFixedVsFloatingSwap = withGenForeignPtr . peel . peel . getInstrument+newGenFixedVsFloatingSwap :: GenForeignPtr f CFixedVsFloatingSwap' -> IO (GenFixedVsFloatingSwap f)+newGenFixedVsFloatingSwap = pure . GenInstrument . newAnyOf . newAnyOf peekVanillaSwap :: Ptr CVanillaSwap' -> IO VanillaSwap-peekVanillaSwap = peekGenSwap+peekVanillaSwap = newGenForeignPtr >=> newGenFixedVsFloatingSwap withVanillaSwap :: VanillaSwap -> (Ptr CVanillaSwap' -> IO b) -> IO b-withVanillaSwap = withForeignPtr . ptr . peel . getInstrument+withVanillaSwap = withForeignPtr . ptr . peel . peel . getInstrument +-- ConstNotionalCrossCurrencySwap sits between Swap and its two owned leaves+-- (ConstNotionalCrossCurrencyBasisSwap, ConstNotionalCrossCurrencyFixedVsFloatingSwap). It earns+-- its own family level (mirrors FixedVsFloatingSwap/VanillaSwap just above) because its own+-- getters (legCurrency, inCcyLegBPS, inCcyLegNPV, npvDateDiscounts) are inherited by both leaves+-- and are bound generically over 'GenConstNotionalCrossCurrencySwap', while each leaf keeps its+-- own engine-dispatched getters (fairPaySpread/fairRecSpread, fairRate/fairSpread) reachable only+-- through the real leaf pointer. Unlike FixedVsFloatingSwap, the base class is concrete upstream+-- and hasquant binds its own 2-leg/N-leg constructors directly at this level.+data CConstNotionalCrossCurrencySwap'+type GenConstNotionalCrossCurrencySwap x = GenSwap (AnyOf CConstNotionalCrossCurrencySwap' x)+type CConstNotionalCrossCurrencySwap = ForeignPtr CConstNotionalCrossCurrencySwap'+type ConstNotionalCrossCurrencySwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencySwap+data CConstNotionalCrossCurrencyBasisSwap'+type CConstNotionalCrossCurrencyBasisSwap = ForeignPtr CConstNotionalCrossCurrencyBasisSwap'+type ConstNotionalCrossCurrencyBasisSwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencyBasisSwap+data CConstNotionalCrossCurrencyFixedVsFloatingSwap'+type CConstNotionalCrossCurrencyFixedVsFloatingSwap = ForeignPtr CConstNotionalCrossCurrencyFixedVsFloatingSwap'+type ConstNotionalCrossCurrencyFixedVsFloatingSwap = GenConstNotionalCrossCurrencySwap CConstNotionalCrossCurrencyFixedVsFloatingSwap+foreign import ccall unsafe "ql.h &qlFreeConstNotionalCrossCurrencySwap" qlFreeConstNotionalCrossCurrencySwap :: FinalizerPtr CConstNotionalCrossCurrencySwap'+foreign import ccall unsafe "ql.h &qlFreeConstNotionalCrossCurrencyBasisSwap" qlFreeConstNotionalCrossCurrencyBasisSwap :: FinalizerPtr CConstNotionalCrossCurrencyBasisSwap'+foreign import ccall unsafe "ql.h &qlFreeConstNotionalCrossCurrencyFixedVsFloatingSwap" qlFreeConstNotionalCrossCurrencyFixedVsFloatingSwap :: FinalizerPtr CConstNotionalCrossCurrencyFixedVsFloatingSwap'+instance Finalizable CConstNotionalCrossCurrencySwap' where finalize = qlFreeConstNotionalCrossCurrencySwap+instance Finalizable CConstNotionalCrossCurrencyBasisSwap' where finalize = qlFreeConstNotionalCrossCurrencyBasisSwap+instance Finalizable CConstNotionalCrossCurrencyFixedVsFloatingSwap' where finalize = qlFreeConstNotionalCrossCurrencyFixedVsFloatingSwap+foreign import ccall "ql.h qlConstNotionalCrossCurrencySwapAsSwap" qlConstNotionalCrossCurrencySwapAsSwap :: Ptr CConstNotionalCrossCurrencySwap' -> IO (Ptr CSwap')+foreign import ccall "ql.h qlConstNotionalCrossCurrencyBasisSwapAsConstNotionalCrossCurrencySwap" qlConstNotionalCrossCurrencyBasisSwapAsConstNotionalCrossCurrencySwap :: Ptr CConstNotionalCrossCurrencyBasisSwap' -> IO (Ptr CConstNotionalCrossCurrencySwap')+foreign import ccall "ql.h qlConstNotionalCrossCurrencyFixedVsFloatingSwapAsConstNotionalCrossCurrencySwap" qlConstNotionalCrossCurrencyFixedVsFloatingSwapAsConstNotionalCrossCurrencySwap :: Ptr CConstNotionalCrossCurrencyFixedVsFloatingSwap' -> IO (Ptr CConstNotionalCrossCurrencySwap')+instance Upcastable CConstNotionalCrossCurrencySwap' where {type Base CConstNotionalCrossCurrencySwap' = CSwap'; upcast = qlConstNotionalCrossCurrencySwapAsSwap}+instance Upcastable CConstNotionalCrossCurrencyBasisSwap' where {type Base CConstNotionalCrossCurrencyBasisSwap' = CConstNotionalCrossCurrencySwap'; upcast = qlConstNotionalCrossCurrencyBasisSwapAsConstNotionalCrossCurrencySwap}+instance Upcastable CConstNotionalCrossCurrencyFixedVsFloatingSwap' where {type Base CConstNotionalCrossCurrencyFixedVsFloatingSwap' = CConstNotionalCrossCurrencySwap'; upcast = qlConstNotionalCrossCurrencyFixedVsFloatingSwapAsConstNotionalCrossCurrencySwap}+asConstNotionalCrossCurrencySwap :: GenConstNotionalCrossCurrencySwap x -> IO ConstNotionalCrossCurrencySwap+asConstNotionalCrossCurrencySwap = transferGenForeignPtr peekConstNotionalCrossCurrencySwap . peel . peel . getInstrument+peekConstNotionalCrossCurrencySwap :: Ptr CConstNotionalCrossCurrencySwap' -> IO ConstNotionalCrossCurrencySwap+peekConstNotionalCrossCurrencySwap = newCastForeignPtr >=> newGenConstNotionalCrossCurrencySwap+withConstNotionalCrossCurrencySwap :: GenConstNotionalCrossCurrencySwap x -> (Ptr CConstNotionalCrossCurrencySwap' -> IO b) -> IO b+withConstNotionalCrossCurrencySwap = withGenForeignPtr . peel . peel . getInstrument+newGenConstNotionalCrossCurrencySwap :: GenForeignPtr x CConstNotionalCrossCurrencySwap' -> IO (GenConstNotionalCrossCurrencySwap x)+newGenConstNotionalCrossCurrencySwap = pure . GenInstrument . newAnyOf . newAnyOf+peekConstNotionalCrossCurrencyBasisSwap :: Ptr CConstNotionalCrossCurrencyBasisSwap' -> IO ConstNotionalCrossCurrencyBasisSwap+peekConstNotionalCrossCurrencyBasisSwap = newGenForeignPtr >=> newGenConstNotionalCrossCurrencySwap+withConstNotionalCrossCurrencyBasisSwap :: ConstNotionalCrossCurrencyBasisSwap -> (Ptr CConstNotionalCrossCurrencyBasisSwap' -> IO b) -> IO b+withConstNotionalCrossCurrencyBasisSwap = withForeignPtr . ptr . peel . peel . getInstrument+peekConstNotionalCrossCurrencyFixedVsFloatingSwap :: Ptr CConstNotionalCrossCurrencyFixedVsFloatingSwap' -> IO ConstNotionalCrossCurrencyFixedVsFloatingSwap+peekConstNotionalCrossCurrencyFixedVsFloatingSwap = newGenForeignPtr >=> newGenConstNotionalCrossCurrencySwap+withConstNotionalCrossCurrencyFixedVsFloatingSwap :: ConstNotionalCrossCurrencyFixedVsFloatingSwap -> (Ptr CConstNotionalCrossCurrencyFixedVsFloatingSwap' -> IO b) -> IO b+withConstNotionalCrossCurrencyFixedVsFloatingSwap = withForeignPtr . ptr . peel . peel . getInstrument++data CNonstandardSwap'+type CNonstandardSwap = ForeignPtr CNonstandardSwap'+type NonstandardSwap = GenSwap CNonstandardSwap+foreign import ccall unsafe "ql.h &qlFreeNonstandardSwap" qlFreeNonstandardSwap :: FinalizerPtr CNonstandardSwap'+instance Finalizable CNonstandardSwap' where finalize = qlFreeNonstandardSwap+foreign import ccall "ql.h qlNonstandardSwapAsSwap" qlNonstandardSwapAsSwap :: Ptr CNonstandardSwap' -> IO (Ptr CSwap')+instance Upcastable CNonstandardSwap' where {type Base CNonstandardSwap' = CSwap'; upcast = qlNonstandardSwapAsSwap}+peekNonstandardSwap :: Ptr CNonstandardSwap' -> IO NonstandardSwap+peekNonstandardSwap = peekGenSwap+withNonstandardSwap :: NonstandardSwap -> (Ptr CNonstandardSwap' -> IO b) -> IO b+withNonstandardSwap = withForeignPtr . ptr . peel . getInstrument++data CFloatFloatSwap'+type CFloatFloatSwap = ForeignPtr CFloatFloatSwap'+type FloatFloatSwap = GenSwap CFloatFloatSwap+foreign import ccall unsafe "ql.h &qlFreeFloatFloatSwap" qlFreeFloatFloatSwap :: FinalizerPtr CFloatFloatSwap'+instance Finalizable CFloatFloatSwap' where finalize = qlFreeFloatFloatSwap+foreign import ccall "ql.h qlFloatFloatSwapAsSwap" qlFloatFloatSwapAsSwap :: Ptr CFloatFloatSwap' -> IO (Ptr CSwap')+instance Upcastable CFloatFloatSwap' where {type Base CFloatFloatSwap' = CSwap'; upcast = qlFloatFloatSwapAsSwap}+peekFloatFloatSwap :: Ptr CFloatFloatSwap' -> IO FloatFloatSwap+peekFloatFloatSwap = peekGenSwap+withFloatFloatSwap :: FloatFloatSwap -> (Ptr CFloatFloatSwap' -> IO b) -> IO b+withFloatFloatSwap = withForeignPtr . ptr . peel . getInstrument+ data CAssetSwap' type CAssetSwap = ForeignPtr CAssetSwap' type AssetSwap = GenSwap CAssetSwap@@ -2082,6 +2629,30 @@ withSwaption :: Swaption -> (Ptr CSwaption' -> IO b) -> IO b withSwaption = withForeignPtr . ptr . peel . getInstrument +data CNonstandardSwaption'+type CNonstandardSwaption = ForeignPtr CNonstandardSwaption'+type NonstandardSwaption = GenOption CNonstandardSwaption+foreign import ccall unsafe "ql.h &qlFreeNonstandardSwaption" qlFreeNonstandardSwaption :: FinalizerPtr CNonstandardSwaption'+instance Finalizable CNonstandardSwaption' where finalize = qlFreeNonstandardSwaption+foreign import ccall "ql.h qlNonstandardSwaptionAsOption" qlNonstandardSwaptionAsOption :: Ptr CNonstandardSwaption' -> IO (Ptr COption')+instance Upcastable CNonstandardSwaption' where {type Base CNonstandardSwaption' = COption'; upcast = qlNonstandardSwaptionAsOption}+peekNonstandardSwaption :: Ptr CNonstandardSwaption' -> IO NonstandardSwaption+peekNonstandardSwaption = peekGenOption+withNonstandardSwaption :: NonstandardSwaption -> (Ptr CNonstandardSwaption' -> IO b) -> IO b+withNonstandardSwaption = withForeignPtr . ptr . peel . getInstrument++data CFloatFloatSwaption'+type CFloatFloatSwaption = ForeignPtr CFloatFloatSwaption'+type FloatFloatSwaption = GenOption CFloatFloatSwaption+foreign import ccall unsafe "ql.h &qlFreeFloatFloatSwaption" qlFreeFloatFloatSwaption :: FinalizerPtr CFloatFloatSwaption'+instance Finalizable CFloatFloatSwaption' where finalize = qlFreeFloatFloatSwaption+foreign import ccall "ql.h qlFloatFloatSwaptionAsOption" qlFloatFloatSwaptionAsOption :: Ptr CFloatFloatSwaption' -> IO (Ptr COption')+instance Upcastable CFloatFloatSwaption' where {type Base CFloatFloatSwaption' = COption'; upcast = qlFloatFloatSwaptionAsOption}+peekFloatFloatSwaption :: Ptr CFloatFloatSwaption' -> IO FloatFloatSwaption+peekFloatFloatSwaption = peekGenOption+withFloatFloatSwaption :: FloatFloatSwaption -> (Ptr CFloatFloatSwaption' -> IO b) -> IO b+withFloatFloatSwaption = withForeignPtr . ptr . peel . getInstrument+ data CMultiAssetOption' data CMargrabeOption' type GenMultiAssetOption mo = GenOption (AnyOf CMultiAssetOption' mo)@@ -2140,6 +2711,18 @@ withBarrierOption :: BarrierOption -> (Ptr CBarrierOption' -> IO b) -> IO b withBarrierOption = withForeignPtr . ptr . peel . peel . getInstrument +data CSoftBarrierOption'+type CSoftBarrierOption = ForeignPtr CSoftBarrierOption'+type SoftBarrierOption = GenOneAssetOption CSoftBarrierOption+foreign import ccall unsafe "ql.h &qlFreeSoftBarrierOption" qlFreeSoftBarrierOption :: FinalizerPtr CSoftBarrierOption'+instance Finalizable CSoftBarrierOption' where finalize = qlFreeSoftBarrierOption+foreign import ccall "ql.h qlSoftBarrierOptionAsOneAssetOption" qlSoftBarrierOptionAsOneAssetOption :: Ptr CSoftBarrierOption' -> IO (Ptr COneAssetOption')+instance Upcastable CSoftBarrierOption' where {type Base CSoftBarrierOption' = COneAssetOption'; upcast = qlSoftBarrierOptionAsOneAssetOption}+peekSoftBarrierOption :: Ptr CSoftBarrierOption' -> IO SoftBarrierOption+peekSoftBarrierOption = newGenForeignPtr >=> newGenOneAssetOption+withSoftBarrierOption :: SoftBarrierOption -> (Ptr CSoftBarrierOption' -> IO b) -> IO b+withSoftBarrierOption = withForeignPtr . ptr . peel . peel . getInstrument+ data CDoubleBarrierOption' type CDoubleBarrierOption = ForeignPtr CDoubleBarrierOption' type DoubleBarrierOption = GenOneAssetOption CDoubleBarrierOption@@ -2199,6 +2782,134 @@ peekQuantoBarrierOption = newGenForeignPtr >=> newGenOneAssetOption withQuantoBarrierOption :: QuantoBarrierOption -> (Ptr CQuantoBarrierOption' -> IO b) -> IO b withQuantoBarrierOption = withForeignPtr . ptr . peel . peel . getInstrument++-- Commodity/EnergyCommodity are abstract-here: Commodity's own constructor is never called+-- directly upstream (every concrete instrument goes through EnergyCommodity), and+-- EnergyCommodity::quantity() is pure virtual, so neither binds a constructor here -- both are+-- reachable only as upcast targets once a Stage-6 leaf (EnergyFuture, EnergyVanillaSwap,+-- EnergyBasisSwap) exists. Commodity::secondaryCosts()/EnergyCommodity::commodityType() are plain,+-- never-mutated echoes of each class's own constructor argument (commodity.hpp/energycommodity.hpp's+-- inline getters each just `return foo_;`) -- not bound, per CLAUDE.md's trivial-getter rule.+-- secondaryCostAmounts()/pricingErrors()/addPricingError are genuine (mutable, computed during+-- pricing); their generalized 'withCommodity' accessor and marshalling live below, next to the+-- Stage-6 leaves that finally give them a producer to verify against.+data CCommodity'+type GenCommodity c = GenInstrument (AnyOf CCommodity' c)+type CCommodity = ForeignPtr CCommodity'+type Commodity = GenCommodity CCommodity+foreign import ccall unsafe "ql.h &qlFreeCommodity" qlFreeCommodity :: FinalizerPtr CCommodity'+instance Finalizable CCommodity' where finalize = qlFreeCommodity+foreign import ccall "ql.h qlCommodityAsInstrument" qlCommodityAsInstrument :: Ptr CCommodity' -> IO (Ptr CInstrument')+instance Upcastable CCommodity' where {type Base CCommodity' = CInstrument'; upcast = qlCommodityAsInstrument}++data CEnergyCommodity'+type GenEnergyCommodity e = GenCommodity (AnyOf CEnergyCommodity' e)+type CEnergyCommodity = ForeignPtr CEnergyCommodity'+type EnergyCommodity = GenEnergyCommodity CEnergyCommodity+foreign import ccall unsafe "ql.h &qlFreeEnergyCommodity" qlFreeEnergyCommodity :: FinalizerPtr CEnergyCommodity'+instance Finalizable CEnergyCommodity' where finalize = qlFreeEnergyCommodity+foreign import ccall "ql.h qlEnergyCommodityAsCommodity" qlEnergyCommodityAsCommodity :: Ptr CEnergyCommodity' -> IO (Ptr CCommodity')+instance Upcastable CEnergyCommodity' where {type Base CEnergyCommodity' = CCommodity'; upcast = qlEnergyCommodityAsCommodity}++-- |Generalizes 'Commodity's base-level getters (secondaryCostAmounts, pricingErrors,+-- addPricingError) across every leaf in the Commodity\/EnergyCommodity\/EnergySwap subtree -- the+-- same move as 'withFixedVsFloatingSwap' generalizing its own base-level getters. One peel:+-- Commodity is the (only, so far) 'AnyOf' layer directly under 'GenInstrument' here.+withCommodity :: GenCommodity c -> (Ptr CCommodity' -> IO b) -> IO b+withCommodity = withGenForeignPtr . peel . getInstrument++-- |'newGenEnergyCommodity' wraps the 2 'AnyOf' layers (Commodity, EnergyCommodity) shared by every+-- 'EnergyCommodity' leaf -- the same helper role 'newGenFixedVsFloatingSwap' plays for 'VanillaSwap'.+newGenEnergyCommodity :: GenForeignPtr e CEnergyCommodity' -> IO (GenEnergyCommodity e)+newGenEnergyCommodity = pure . GenInstrument . newAnyOf . newAnyOf++-- |Generalizes 'EnergyCommodity's one pure-virtual interface method, @quantity()@, across every+-- leaf (EnergyFuture, EnergyVanillaSwap, EnergyBasisSwap): one shim, dispatched virtually on the+-- C++ side, rather than a per-leaf binding -- EnergyFuture's own override is a plain echo of its+-- constructor argument, but EnergySwap's is a real computed sum over its pricing periods+-- (energyswap.cpp), so the binding as a whole is not a redundant echo even though one leaf's+-- override happens to be.+withEnergyCommodity :: GenEnergyCommodity e -> (Ptr CEnergyCommodity' -> IO b) -> IO b+withEnergyCommodity = withGenForeignPtr . peel . peel . getInstrument++-- |'EnergyFuture': a leaf directly under 'EnergyCommodity' (Stage 6). 2 peels reach+-- 'CEnergyFuture'' -- through the Commodity and EnergyCommodity layers -- the same depth+-- 'VanillaSwap' needs under 'GenFixedVsFloatingSwap' (Swap + FixedVsFloatingSwap).+data CEnergyFuture'+type CEnergyFuture = ForeignPtr CEnergyFuture'+type EnergyFuture = GenEnergyCommodity CEnergyFuture+foreign import ccall unsafe "ql.h &qlFreeEnergyFuture" qlFreeEnergyFuture :: FinalizerPtr CEnergyFuture'+instance Finalizable CEnergyFuture' where finalize = qlFreeEnergyFuture+foreign import ccall "ql.h qlEnergyFutureAsEnergyCommodity" qlEnergyFutureAsEnergyCommodity :: Ptr CEnergyFuture' -> IO (Ptr CEnergyCommodity')+instance Upcastable CEnergyFuture' where {type Base CEnergyFuture' = CEnergyCommodity'; upcast = qlEnergyFutureAsEnergyCommodity}+peekEnergyFuture :: Ptr CEnergyFuture' -> IO EnergyFuture+peekEnergyFuture = newGenForeignPtr >=> newGenEnergyCommodity+withEnergyFuture :: EnergyFuture -> (Ptr CEnergyFuture' -> IO b) -> IO b+withEnergyFuture = withForeignPtr . ptr . peel . peel . getInstrument++-- |'EnergySwap' is abstract-here: it binds a public constructor upstream, but never overrides+-- 'performCalculations', so calling it directly falls through to 'Instrument's null-engine+-- @QL_REQUIRE@ and throws -- reachable only as an upcast target from 'EnergyVanillaSwap'\/+-- 'EnergyBasisSwap', exactly like 'FixedVsFloatingSwap'\/'VanillaSwap'. Its own accessors+-- (calendar, payCurrency, receiveCurrency, pricingPeriods, dailyPositions, paymentCashFlows,+-- commodityType, quantity) are bound generically over 'GenEnergySwap' in+-- 'QuantLib.Instrument.Energy' so both leaves inherit them for free, mirroring+-- 'GenFixedVsFloatingSwap's fairRate\/fixedLeg*\/floatingLeg* getters.+data CEnergySwap'+type GenEnergySwap s = GenEnergyCommodity (AnyOf CEnergySwap' s)+type CEnergySwap = ForeignPtr CEnergySwap'+type EnergySwap = GenEnergySwap CEnergySwap+foreign import ccall unsafe "ql.h &qlFreeEnergySwap" qlFreeEnergySwap :: FinalizerPtr CEnergySwap'+instance Finalizable CEnergySwap' where finalize = qlFreeEnergySwap+foreign import ccall "ql.h qlEnergySwapAsEnergyCommodity" qlEnergySwapAsEnergyCommodity :: Ptr CEnergySwap' -> IO (Ptr CEnergyCommodity')+instance Upcastable CEnergySwap' where {type Base CEnergySwap' = CEnergyCommodity'; upcast = qlEnergySwapAsEnergyCommodity}+newGenEnergySwap :: GenForeignPtr s CEnergySwap' -> IO (GenEnergySwap s)+newGenEnergySwap = pure . GenInstrument . newAnyOf . newAnyOf . newAnyOf+withEnergySwap :: GenEnergySwap s -> (Ptr CEnergySwap' -> IO b) -> IO b+withEnergySwap = withGenForeignPtr . peel . peel . peel . getInstrument++data CEnergyVanillaSwap'+type CEnergyVanillaSwap = ForeignPtr CEnergyVanillaSwap'+type EnergyVanillaSwap = GenEnergySwap CEnergyVanillaSwap+foreign import ccall unsafe "ql.h &qlFreeEnergyVanillaSwap" qlFreeEnergyVanillaSwap :: FinalizerPtr CEnergyVanillaSwap'+instance Finalizable CEnergyVanillaSwap' where finalize = qlFreeEnergyVanillaSwap+foreign import ccall "ql.h qlEnergyVanillaSwapAsEnergySwap" qlEnergyVanillaSwapAsEnergySwap :: Ptr CEnergyVanillaSwap' -> IO (Ptr CEnergySwap')+instance Upcastable CEnergyVanillaSwap' where {type Base CEnergyVanillaSwap' = CEnergySwap'; upcast = qlEnergyVanillaSwapAsEnergySwap}+peekEnergyVanillaSwap :: Ptr CEnergyVanillaSwap' -> IO EnergyVanillaSwap+peekEnergyVanillaSwap = newGenForeignPtr >=> newGenEnergySwap+withEnergyVanillaSwap :: EnergyVanillaSwap -> (Ptr CEnergyVanillaSwap' -> IO b) -> IO b+withEnergyVanillaSwap = withForeignPtr . ptr . peel . peel . peel . getInstrument++data CEnergyBasisSwap'+type CEnergyBasisSwap = ForeignPtr CEnergyBasisSwap'+type EnergyBasisSwap = GenEnergySwap CEnergyBasisSwap+foreign import ccall unsafe "ql.h &qlFreeEnergyBasisSwap" qlFreeEnergyBasisSwap :: FinalizerPtr CEnergyBasisSwap'+instance Finalizable CEnergyBasisSwap' where finalize = qlFreeEnergyBasisSwap+foreign import ccall "ql.h qlEnergyBasisSwapAsEnergySwap" qlEnergyBasisSwapAsEnergySwap :: Ptr CEnergyBasisSwap' -> IO (Ptr CEnergySwap')+instance Upcastable CEnergyBasisSwap' where {type Base CEnergyBasisSwap' = CEnergySwap'; upcast = qlEnergyBasisSwapAsEnergySwap}+peekEnergyBasisSwap :: Ptr CEnergyBasisSwap' -> IO EnergyBasisSwap+peekEnergyBasisSwap = newGenForeignPtr >=> newGenEnergySwap+withEnergyBasisSwap :: EnergyBasisSwap -> (Ptr CEnergyBasisSwap' -> IO b) -> IO b+withEnergyBasisSwap = withForeignPtr . ptr . peel . peel . peel . getInstrument++-- |'CommodityCashFlow': a standalone 'CashFlow' subclass, following the same+-- ZeroInflationCashFlow\/CPICashFlow\/EquityCashFlow precedent (no polymorphic @CashFlow@ family is+-- modelled here -- see those types in 'QuantLib.CashFlow' -- each concrete cash flow class is its+-- own standalone foreign-pointer type instead).+data CCommodityCashFlow+newtype CommodityCashFlow = CommodityCashFlow {getCCommodityCashFlow :: Standalone CCommodityCashFlow}+foreign import ccall unsafe "ql.h &qlFreeCommodityCashFlow" qlFreeCommodityCashFlow :: FinalizerPtr CCommodityCashFlow+instance Finalizable CCommodityCashFlow where finalize = qlFreeCommodityCashFlow+peekCommodityCashFlow :: Ptr CCommodityCashFlow -> IO CommodityCashFlow+peekCommodityCashFlow = CommodityCashFlow <.> peekStandalone+withCommodityCashFlow :: CommodityCashFlow -> (Ptr CCommodityCashFlow -> IO b) -> IO b+withCommodityCashFlow = withStandalone . getCCommodityCashFlow+-- |An array of freshly-constructed 'CommodityCashFlow's -- 'EnergySwap.paymentCashFlows()''s+-- @map<Date, shared_ptr<CommodityCashFlow>>@, read as a plain list (each element's own+-- 'QuantLib.Instrument.Energy.commodityCashFlowDate' already carries the map key, so it isn't+-- duplicated as a separate tuple field).+peekCommodityCashFlowArray :: Ptr CUInt -> Ptr (Ptr (Ptr CCommodityCashFlow)) -> IO [CommodityCashFlow]+peekCommodityCashFlowArray = peekPtrArray peekCommodityCashFlow  withInstrumentArray :: [GenInstrument i] -> ((CUInt, Ptr (Ptr CInstrument')) -> IO b) -> IO b withInstrumentArray = withGenArray withInstrument
QuantLib/Math.chs view
@@ -38,7 +38,7 @@   , points'   ) where import QuantLib.Internal-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Type import Foreign.C.Types(CDouble) import Data.Vector.Storable(Vector)
QuantLib/Model.chs view
@@ -9,8 +9,8 @@   , PiecewiseTimeDependentHestonModel   , ShortRateModel   , GenShortRateModel-  , AffineModel(..)-  , Gaussian1dModel(..)+  , AffineModel+  , Gaussian1dModel   , OneFactorAffineModel   , GenOneFactorAffineModel   , LiborForwardModel@@ -28,8 +28,11 @@   , LmVolatilityModel(..)   , CalibrationHelper   , BlackCalibrationHelper+  , GenBlackCalibrationHelper+  , SwaptionHelper   , GenCalibrationHelper   , asCalibrationHelper+  , asBlackCalibrationHelper    , asCalibratedModel   , asHestonModel@@ -37,6 +40,12 @@   , asOneFactorAffineModel   , asBatesModel   , asBatesDoubleExpModel+  , hullWhiteAsAffineModel+  , g2AsAffineModel+  , oneFactorAffineModelAsAffineModel+  , liborForwardModelAsAffineModel+  , gsrAsGaussian1dModel+  , markovFunctionalAsGaussian1dModel    , batesModel   , blackKarasinski@@ -52,6 +61,7 @@   , liborForwardModel   , gsr   , markovFunctional+  , markovFunctionalCaplet    , calibrate   , calibrateVolatilitiesIterative@@ -60,6 +70,8 @@   , swaptionHelper   , swaptionHelperFromDate   , swaptionHelperFromDates+  , swaptionHelperUnderlying+  , swaptionHelperSwaption   , times    , discountBond@@ -74,6 +86,7 @@   , impliedVolatility   , marketValue   , modelValue+  , volatility   , setPricingEngine   ) where #include "qlTypesC2HS.h"@@ -88,7 +101,7 @@ {#import QuantLib.InterestRate#}(VolatilityType) {#import QuantLib.CashFlow#}(RateAveragingType) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common  {#enum CalibrationErrorType{} deriving(Show, Eq)#} @@ -122,6 +135,9 @@  {#pointer *QlCalibrationHelper as CalibrationHelper foreign -> CCalibrationHelper' nocode#} {#pointer *QlBlackCalibrationHelper as BlackCalibrationHelper foreign -> CBlackCalibrationHelper' nocode#}+{#pointer *QlSwaptionHelper as SwaptionHelper foreign -> CSwaptionHelper' nocode#}+{#pointer *QlFixedVsFloatingSwap as FixedVsFloatingSwap foreign -> CFixedVsFloatingSwap' nocode#}+{#pointer *QlSwaption as Swaption foreign -> CSwaption' nocode#}  {#pointer *QlGeneralizedBlackScholesProcess as GeneralizedBlackScholesProcess foreign -> CGeneralizedBlackScholesProcess' nocode#} {#pointer *QlStochasticProcess1D as StochasticProcess1D foreign -> CStochasticProcess1D' nocode#}@@ -173,7 +189,7 @@ {#fun qlOneFactorAffineModelDiscountBond as discountBond{withOneFactorAffineModel*`GenOneFactorAffineModel om',`Double' -- ^now   ,`Double' -- ^maturity   ,`Double' -- ^rate-  }->`Double'#}+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |Two-additive-factor Gaussian (G2) short-rate model: the sum of two correlated Ornstein-Uhlenbeck factors. {#fun qlG2 as g2{withYieldTermStructure*`GenYieldTermStructure y',`Double' -- ^y@@ -202,12 +218,15 @@   ,preErrorCheck-`String'errorCheck*-}->`HullWhite'peekHullWhite*#}  -- |Futures convexity bias (difference between futures implied rate and forward rate), per G. Kirikos, D. Novak, \"Convexity Conundrums\", Risk Magazine, March 1997. @t@/@T@ are in yearfraction using the deposit day counter, @futurePrice@ is the futures' market price.-{#fun pure qlHullWhiteConvexityBias as convexityBias{`Double' -- ^futurePrice+-- Not 'pure': 'HullWhite.convexityBias' can throw ('QL_REQUIRE' on its inputs), and letting a C+++-- exception unwind across the FFI boundary from an 'unsafePerformIO'-backed pure binding is undefined+-- behavior, so this needs the same 'char **e'/'preErrorCheck' error channel as any other throwing call.+{#fun qlHullWhiteConvexityBias as convexityBias{`Double' -- ^futurePrice   ,`Double' -- ^t   ,`Double' -- ^T   ,`Double' -- ^sigma   ,`Double' -- ^a-  }->`Double'#}+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |Marks the reversion (@a@) fixed and volatility (@sigma@) free for 'calibrate''s @fixParameters@ argument. Mirrors @HullWhite::FixedReversion()@. fixedReversion :: [Bool]@@ -223,7 +242,7 @@ {#fun qlGsrVolatility as gsrVolatility{withGenCalibratedModel*`Gsr',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}  -- |Iteratively calibrates the volatility step values, one at a time, to the given helpers (assumed to have step dates matching the model's volatility step dates).-{#fun qlGsrCalibrateVolatilitiesIterative as calibrateVolatilitiesIterative{withGenCalibratedModel*`Gsr',withBlackCalibrationHelperArray*`[BlackCalibrationHelper]'&,withOptimizationMethod*`OptimizationMethod',withEndCriteria*`EndCriteria'+{#fun qlGsrCalibrateVolatilitiesIterative as calibrateVolatilitiesIterative{withGenCalibratedModel*`Gsr',withBlackCalibrationHelperArray*`[GenBlackCalibrationHelper bch]'&,withOptimizationMethod*`OptimizationMethod',withEndCriteria*`EndCriteria'   ,withMaybeConstraint*`Maybe Constraint'   ,withDoubleArray*`[Double]'&   ,preErrorCheck-`String'errorCheck*-}->`()'#}@@ -249,6 +268,16 @@   ,fromIntegral`Word'   ,preErrorCheck-`String'errorCheck*-}->`MarkovFunctional'peekMarkovFunctional*#} +-- |Markov-functional interest-rate model, calibrated to a caplet volatility structure against @iborIndex@.+{#fun qlMarkovFunctionalCaplet as markovFunctionalCaplet{withYieldTermStructure*`GenYieldTermStructure y',`Double' -- ^reversion+  ,withDayArray*`[Day]'& -- ^volstepdates+  ,withDoubleArray*`[Double]'& -- ^volatilities+  ,withOptionletVolatilityStructure*`OptionletVolatilityStructure' -- ^capletVol+  ,withDayArray*`[Day]'& -- ^capletExpiries+  ,withIborIndex*`GenIborIndex ibor' -- ^iborIndex+  ,fromIntegral`Word' -- ^yGridPoints+  ,preErrorCheck-`String'errorCheck*-}->`MarkovFunctional'peekMarkovFunctional*#}+ -- |Volatility step values, as calibrated so far. {#fun qlMarkovFunctionalVolatility as markovFunctionalVolatility{withGenCalibratedModel*`MarkovFunctional',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#} @@ -312,7 +341,7 @@   ,`Double' -- ^shift   ,fromMaybeInt`Maybe Word' -- ^settlementDays   ,`RateAveragingType' -- ^averagingMethod-  ,preErrorCheck-`String'errorCheck*-}->`BlackCalibrationHelper'peekBlackCalibrationHelper*#}+  ,preErrorCheck-`String'errorCheck*-}->`SwaptionHelper'peekSwaptionHelper*#}  -- |Like 'swaptionHelper', but the option's exercise is given as an explicit date rather than a maturity 'Period'. {#fun qlSwaptionHelperFromDate as swaptionHelperFromDate{withDay*`Day' -- ^exerciseDate@@ -328,7 +357,7 @@   ,`Double' -- ^shift   ,fromMaybeInt`Maybe Word' -- ^settlementDays   ,`RateAveragingType' -- ^averagingMethod-  ,preErrorCheck-`String'errorCheck*-}->`BlackCalibrationHelper'peekBlackCalibrationHelper*#}+  ,preErrorCheck-`String'errorCheck*-}->`SwaptionHelper'peekSwaptionHelper*#}  -- |Like 'swaptionHelper', but both the option's exercise and the underlying swap's end are given as explicit dates. {#fun qlSwaptionHelperFromDates as swaptionHelperFromDates{withDay*`Day' -- ^exerciseDate@@ -344,23 +373,29 @@   ,`Double' -- ^shift   ,fromMaybeInt`Maybe Word' -- ^settlementDays   ,`RateAveragingType' -- ^averagingMethod-  ,preErrorCheck-`String'errorCheck*-}->`BlackCalibrationHelper'peekBlackCalibrationHelper*#}+  ,preErrorCheck-`String'errorCheck*-}->`SwaptionHelper'peekSwaptionHelper*#} +-- |Upstream's own vanilla swap underlying this helper's swaption.+{#fun qlSwaptionHelperUnderlying as swaptionHelperUnderlying{withSwaptionHelper*`SwaptionHelper',preErrorCheck-`String'errorCheck*-}->`FixedVsFloatingSwap'peekFixedVsFloatingSwap*#}++-- |The 'QuantLib.Instrument.Swap.Swaption' this helper prices internally to compute 'modelValue'.+{#fun qlSwaptionHelperSwaption as swaptionHelperSwaption{withSwaptionHelper*`SwaptionHelper',preErrorCheck-`String'errorCheck*-}->`Swaption'peekSwaption*#}+ -- |Times relevant to pricing this calibration helper's instrument, to be added to the model's evolution time grid.-{#fun qlBlackCalibrationHelperTimes as times{withGenCalibrationHelper*`BlackCalibrationHelper',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}+{#fun qlBlackCalibrationHelperTimes as times{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}  -- |Returns array of arguments on which calibration is done. {#fun qlCalibratedModelParams as params{withCalibratedModel*`GenCalibratedModel m',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}  -- |Black price given a volatility.-{#fun qlBlackCalibrationHelperBlackPrice as blackPrice{withGenCalibrationHelper*`BlackCalibrationHelper',`Double' -- ^volatility+{#fun qlBlackCalibrationHelperBlackPrice as blackPrice{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',`Double' -- ^volatility   ,preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |returns the error resulting from the model valuation-{#fun qlBlackCalibrationHelperCalibrationError as calibrationError{withGenCalibrationHelper*`BlackCalibrationHelper',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlBlackCalibrationHelperCalibrationError as calibrationError{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |Black volatility implied by the model.-{#fun qlBlackCalibrationHelperImpliedVolatility as impliedVolatility{withGenCalibrationHelper*`BlackCalibrationHelper',`Double' -- ^targetValue+{#fun qlBlackCalibrationHelperImpliedVolatility as impliedVolatility{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',`Double' -- ^targetValue   ,`Double' -- ^accuracy   ,fromIntegral`Word' -- ^maxEvaluations   ,`Double' -- ^minVol@@ -368,12 +403,15 @@   ,preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |returns the actual price of the instrument (from volatility)-{#fun qlBlackCalibrationHelperMarketValue as marketValue{withGenCalibrationHelper*`BlackCalibrationHelper',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlBlackCalibrationHelperMarketValue as marketValue{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',preErrorCheck-`String'errorCheck*-}->`Double'#}  -- |returns the price of the instrument according to the model-{#fun qlBlackCalibrationHelperModelValue as modelValue{withGenCalibrationHelper*`BlackCalibrationHelper',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlBlackCalibrationHelperModelValue as modelValue{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',preErrorCheck-`String'errorCheck*-}->`Double'#} +-- |The quoted market volatility this helper was built with.+{#fun qlBlackCalibrationHelperVolatility as volatility{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',preErrorCheck-`String'errorCheck*-}->`Quote'peekQuote*#}+ -- |Sets the pricing engine used to compute this calibration helper's model value.-{#fun qlBlackCalibrationHelperSetPricingEngine as setPricingEngine{withGenCalibrationHelper*`BlackCalibrationHelper',withPricingEngine*`PricingEngine',preErrorCheck-`String'errorCheck*-}->`()'#}+{#fun qlBlackCalibrationHelperSetPricingEngine as setPricingEngine{withBlackCalibrationHelper*`GenBlackCalibrationHelper bch',withPricingEngine*`PricingEngine',preErrorCheck-`String'errorCheck*-}->`()'#}  -- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/PricingEngine.chs view
@@ -20,11 +20,16 @@   , riskyBondEngine   , discountingSwapEngine   , discountingFxForwardEngine+  , discountingConstNotionalCrossCurrencySwapEngine   , counterpartyAdjSwapEngine    , analyticBarrierEngine+  , analyticSoftBarrierEngine   , analyticPartialTimeBarrierOptionEngine   , analyticBinaryBarrierEngine+  , analyticSimpleChooserEngine+  , analyticTwoAssetCorrelationEngine+  , analyticWriterExtensibleOptionEngine   , fdBlackScholesBarrierEngine   , fdHestonBarrierEngine   , fdHestonBarrierEngine'@@ -43,19 +48,32 @@   , analyticDigitalAmericanEngine   , analyticDiscreteGeometricAveragePriceAsianEngine   , analyticDiscreteGeometricAverageStrikeAsianEngine+  , turnbullWakemanAsianEngine+  , fdBlackScholesAsianEngine   , analyticDividendEuropeanEngine   , analyticEuropeanEngine   , analyticPerformanceEngine+  , forwardEuropeanEngine+  , forwardBaroneAdesiWhaleyEngine+  , forwardBjerksundStenslandEngine+  , forwardFdBlackScholesVanillaEngine+  , mcForwardEuropeanBSEngine+  , analyticHestonForwardEuropeanEngine   , blackCapFloorEngine'   , blackCapFloorEngine   , blackSwaptionEngine   , blackSwaptionEngine'   , bachelierCapFloorEngine'   , bachelierCapFloorEngine+  , yoyInflationBlackCapFloorEngine+  , yoyInflationUnitDisplacedBlackCapFloorEngine+  , yoyInflationBachelierCapFloorEngine+  , interpolatingCPICapFloorEngine   , bachelierSwaptionEngine   , bachelierSwaptionEngine'   , analyticBSMHullWhiteEngine   , analyticCapFloorEngine+  , gaussian1dCapFloorEngine   , analyticGJRGARCHEngine   , analyticHestonEngine   , analyticHestonHullWhiteEngine@@ -99,6 +117,9 @@   , isdaCdsEngine   , jamshidianSwaptionEngine   , gaussian1dSwaptionEngine+  , gaussian1dNonstandardSwaptionEngine+  , gaussian1dFloatFloatSwaptionEngine+  , gaussian1dJamshidianSwaptionEngine   , juQuadraticApproximationEngine   , kirkEngine   , midPointCdsEngine@@ -223,7 +244,7 @@ {#import QuantLib.Math#} {#import QuantLib.Quote#}(DeltaType, AtmType) {#import QuantLib.Instrument.Option#} hiding(itmCashProbability, deltaForward, strikeSensitivity, dividendRho, rho, vega)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common  {#enum CashAnnuityModel{} deriving(Show, Eq)#} {#enum Probabilities{} deriving(Show, Eq)#}@@ -233,6 +254,7 @@ {#enum ForwardsInCouponPeriod{} deriving(Show, Eq)#}  {#pointer *DayCounter foreign -> CDayCounter nocode#}+{#pointer *Currency foreign -> CCurrency nocode#}  {#pointer *QlDividend as Dividend foreign -> CDividend nocode#} {#pointer *QlQuote as Quote foreign -> CQuote' nocode#}@@ -243,6 +265,9 @@ {#pointer *QlDefaultProbabilityTermStructure as DefaultProbabilityTermStructure foreign -> CDefaultProbabilityTermStructure' nocode#} {#pointer *QlSwaptionVolatilityStructure as SwaptionVolatilityStructure foreign -> CSwaptionVolatilityStructure' nocode#} {#pointer *QlOptionletVolatilityStructure as OptionletVolatilityStructure foreign -> COptionletVolatilityStructure' nocode#}+{#pointer *QlYoYOptionletVolatilitySurface as YoYOptionletVolatilitySurface foreign -> CYoYOptionletVolatilitySurface' nocode#}+{#pointer *QlYoYInflationIndex as YoYInflationIndex foreign -> CYoYInflationIndex' nocode#}+{#pointer *QlCPICapFloorTermPriceSurface as CPICapFloorTermPriceSurface foreign -> CCPICapFloorTermPriceSurface' nocode#}  {#pointer *QlGJRGARCHModel as GJRGARCHModel foreign -> CGJRGARCHModel' nocode#} {#pointer *QlHestonModel as HestonModel foreign -> CHestonModel' nocode#}@@ -307,6 +332,22 @@   ,withQuote*`GenQuote q' -- ^spotFx   ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |Discounts each leg of a 'QuantLib.Instrument.Swap.ConstNotionalCrossCurrencySwap' (or either+-- of its two leaves) off its own currency's discount curve, converting to @domesticCcy@ via+-- @spotFX@ (quoted as units of @domesticCcy@ per unit of @foreignCcy@, w.r.t. a settlement equal+-- to the npv date unless @spotFXSettleDate@ says otherwise). Each leg's stored currency must equal+-- @domesticCcy@ or @foreignCcy@; the two discount curves must share the same reference date.+{#fun qlDiscountingConstNotionalCrossCurrencySwapEngine as discountingConstNotionalCrossCurrencySwapEngine{withCurrency*`Currency' -- ^domesticCcy+  ,withYieldTermStructure*`GenYieldTermStructure y1' -- ^domesticCcyDiscountCurve+  ,withCurrency*`Currency' -- ^foreignCcy+  ,withYieldTermStructure*`GenYieldTermStructure y2' -- ^foreignCcyDiscountCurve+  ,withQuote*`GenQuote q' -- ^spotFX+  ,fromMaybeBool`Maybe Bool' -- ^includeSettlementDateFlows+  ,withMaybeDay*`Maybe Day' -- ^settlementDate+  ,withMaybeDay*`Maybe Day' -- ^npvDate+  ,withMaybeDay*`Maybe Day' -- ^spotFXSettleDate+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- | CVA/DVA-adjusted swap pricing engine. @invstDTS@\/@invstRecoveryRate@ are the -- own (investor-side) default probability curve and recovery rate for bilateral -- CVA\/DVA; pass 'Nothing' for @invstDTS@ and @0.999@ for @invstRecoveryRate@ to@@ -322,6 +363,21 @@ -- |analytic pricing engine for barrier options {#fun qlAnalyticBarrierEngine as analyticBarrierEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |analytic pricing engine for soft barrier options, knocked in/out proportionally over a barrier range+{#fun qlAnalyticSoftBarrierEngine as analyticSoftBarrierEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |analytic pricing engine for simple chooser options+{#fun qlAnalyticSimpleChooserEngine as analyticSimpleChooserEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |analytic pricing engine for two-asset correlation options+{#fun qlAnalyticTwoAssetCorrelationEngine as analyticTwoAssetCorrelationEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess' -- ^process1+  ,withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess' -- ^process2+  ,withQuote*`GenQuote q' -- ^correlation+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |analytic pricing engine for writer-extensible options+{#fun qlAnalyticWriterExtensibleOptionEngine as analyticWriterExtensibleOptionEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |analytic pricing engine for partial-time barrier options {#fun qlAnalyticPartialTimeBarrierOptionEngine as analyticPartialTimeBarrierOptionEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} @@ -400,6 +456,9 @@ -- |analytic pricing engine for European discrete geometric average-strike Asian options {#fun qlAnalyticDiscreteGeometricAverageStrikeAsianEngine as analyticDiscreteGeometricAverageStrikeAsianEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |Turnbull-Wakeman moment-matching pricing engine for discrete arithmetic average-price\/-strike Asian options+{#fun qlTurnbullWakemanAsianEngine as turnbullWakemanAsianEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |analytic pricing engine for European options with discrete dividends {#fun qlAnalyticDividendEuropeanEngine as analyticDividendEuropeanEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',withDividendArray*`[Dividend]'&,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} @@ -411,6 +470,33 @@ -- |analytic pricing engine for performance (return) options {#fun qlAnalyticPerformanceEngine as analyticPerformanceEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |analytic pricing engine for forward-starting European options; binds the @AnalyticEuropeanEngine@ instantiation of upstream's @ForwardVanillaEngine\<Engine\>@ template+{#fun qlForwardEuropeanEngine as forwardEuropeanEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |Barone-Adesi\/Whaley approximation pricing engine for forward-starting American options; binds the @BaroneAdesiWhaleyApproximationEngine@ instantiation of @ForwardVanillaEngine\<Engine\>@+{#fun qlForwardBaroneAdesiWhaleyEngine as forwardBaroneAdesiWhaleyEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |Bjerksund\/Stensland approximation pricing engine for forward-starting American options; binds the @BjerksundStenslandApproximationEngine@ instantiation of @ForwardVanillaEngine\<Engine\>@+{#fun qlForwardBjerksundStenslandEngine as forwardBjerksundStenslandEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |finite-differences Black-Scholes pricing engine for forward-starting vanilla options, with the wrapped engine's grid\/scheme params fixed at their QuantLib defaults; binds the @FdBlackScholesVanillaEngine@ instantiation of @ForwardVanillaEngine\<Engine\>@+{#fun qlForwardFdBlackScholesVanillaEngine as forwardFdBlackScholesVanillaEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |Monte Carlo pricing engine for forward-starting European options under a Black-Scholes process+{#fun qlMCForwardEuropeanBSEngine1 as mcForwardEuropeanBSEngine{`RngTrait',withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',fromMaybeInt`Maybe Word' -- ^timeSteps+  ,fromMaybeInt`Maybe Word' -- ^timeStepsPerYear+  ,`Bool' -- ^brownianBridge+  ,`Bool' -- ^antitheticVariate+  ,fromMaybeInt`Maybe Word' -- ^requiredSamples+  ,fromMaybeDouble`Maybe Double' -- ^requiredTolerance+  ,fromMaybeInt`Maybe Word' -- ^maxSamples+  ,fromIntegral`Word' -- ^seed+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |analytic pricing engine for forward-starting European options under a Heston process+{#fun qlAnalyticHestonForwardEuropeanEngine as analyticHestonForwardEuropeanEngine{withHestonProcess*`GenHestonProcess hp',fromIntegral`Word' -- ^integrationOrder+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |Black-formula cap\/floor engine, taking an optionlet volatility structure {#fun qlBlackCapFloorEngine1 as blackCapFloorEngine'{withYieldTermStructure*`GenYieldTermStructure y',withOptionletVolatilityStructure*`GenOptionletVolatilityStructure ov',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} @@ -434,6 +520,32 @@ -- |Bachelier (normal) cap\/floor engine, taking a flat volatility quote {#fun qlBachelierCapFloorEngine as bachelierCapFloorEngine{withYieldTermStructure*`GenYieldTermStructure y',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |Black-formula YoY inflation cap\/floor engine. The nominal discount curve and the index's+-- own linked 'QuantLib.TermStructure.Inflation.YoYInflationTermStructure' are separate --+-- @nominalTermStructure@ discounts cashflows, while the index forecasts them.+{#fun qlYoYInflationBlackCapFloorEngine as yoyInflationBlackCapFloorEngine{withYoYInflationIndex*`GenYoYInflationIndex yidx'+  ,withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface' -- ^vol+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |as 'yoyInflationBlackCapFloorEngine', but unit-displaced Black+{#fun qlYoYInflationUnitDisplacedBlackCapFloorEngine as yoyInflationUnitDisplacedBlackCapFloorEngine{withYoYInflationIndex*`GenYoYInflationIndex yidx'+  ,withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface' -- ^vol+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |as 'yoyInflationBlackCapFloorEngine', but Bachelier (normal model)+{#fun qlYoYInflationBachelierCapFloorEngine as yoyInflationBachelierCapFloorEngine{withYoYInflationIndex*`GenYoYInflationIndex yidx'+  ,withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface' -- ^vol+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |The only 'QuantLib.Instrument.InflationCapFloor.CPICapFloor' pricing engine in QL 1.43 --+-- prices purely by interpolating a market price surface, no stochastic-vol model (see that+-- type's own haddock for the CPI\/YoY asymmetry).+{#fun qlInterpolatingCPICapFloorEngine as interpolatingCPICapFloorEngine{withGenTermStructure*`CPICapFloorTermPriceSurface'+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |Bachelier (normal) swaption engine, taking a flat volatility quote {#fun qlBachelierSwaptionEngine as bachelierSwaptionEngine{withYieldTermStructure*`GenYieldTermStructure y',withQuote*`GenQuote q',withDayCounter*`DayCounter',`CashAnnuityModel' -- ^model   ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}@@ -445,8 +557,19 @@ {#fun qlAnalyticBSMHullWhiteEngine as analyticBSMHullWhiteEngine{`Double',withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',withHullWhite*`HullWhite',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}  -- |the term structure is only needed when the short-rate model cannot provide one itself.-{#fun qlAnalyticCapFloorEngine as analyticCapFloorEngine{withAffineModel*`AffineModel',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+{#fun qlAnalyticCapFloorEngine as analyticCapFloorEngine{withStandalone*`AffineModel',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |cap\/floor pricing engine for any one-factor Gaussian short-rate model, evaluated by+-- integration over the model's state variable. As 'gaussian1dSwaptionEngine', without+-- 'Probabilities'.+{#fun qlGaussian1dCapFloorEngine as gaussian1dCapFloorEngine{withStandalone*`Gaussian1dModel'+  ,fromIntegral`Int' -- ^integrationPoints+  ,`Double' -- ^stddevs+  ,`Bool' -- ^extrapolatePayoff+  ,`Bool' -- ^flatPayoffExtrapolation+  ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discountCurve+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |analytic pricing engine for vanilla options under a GJR-GARCH process {#fun qlAnalyticGJRGARCHEngine as analyticGJRGARCHEngine{withGenCalibratedModel*`GJRGARCHModel',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} @@ -558,7 +681,7 @@ {#fun qlJamshidianSwaptionEngine as jamshidianSwaptionEngine{withOneFactorAffineModel*`GenOneFactorAffineModel om',withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}  -- |swaption pricing engine for any one-factor Gaussian short-rate model, evaluated by integration over the model's state variable-{#fun qlGaussian1dSwaptionEngine as gaussian1dSwaptionEngine{withGaussian1dModel*`Gaussian1dModel'+{#fun qlGaussian1dSwaptionEngine as gaussian1dSwaptionEngine{withStandalone*`Gaussian1dModel'   ,fromIntegral`Int' -- ^integrationPoints   ,`Double' -- ^stddevs   ,`Bool' -- ^extrapolatePayoff@@ -567,6 +690,37 @@   ,`Probabilities' -- ^probabilities   ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} +-- |As 'gaussian1dSwaptionEngine', for a 'QuantLib.Instrument.Swap.NonstandardSwaption'. Adds+-- an optional OAS ('oas', continuously compounded w.r.t. the discount curve's day counter) on+-- top of the shared parameters.+{#fun qlGaussian1dNonstandardSwaptionEngine as gaussian1dNonstandardSwaptionEngine{withStandalone*`Gaussian1dModel'+  ,fromIntegral`Int' -- ^integrationPoints+  ,`Double' -- ^stddevs+  ,`Bool' -- ^extrapolatePayoff+  ,`Bool' -- ^flatPayoffExtrapolation+  ,withMaybeQuote*`Maybe (GenQuote q)' -- ^oas+  ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discountCurve+  ,`Probabilities' -- ^probabilities+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |As 'gaussian1dNonstandardSwaptionEngine', for a+-- 'QuantLib.Instrument.Swap.FloatFloatSwaption'. Adds 'includeTodaysExercise' -- whether a+-- fixing due exactly \"today\" counts as part of the exercise-into leg.+{#fun qlGaussian1dFloatFloatSwaptionEngine as gaussian1dFloatFloatSwaptionEngine{withStandalone*`Gaussian1dModel'+  ,fromIntegral`Int' -- ^integrationPoints+  ,`Double' -- ^stddevs+  ,`Bool' -- ^extrapolatePayoff+  ,`Bool' -- ^flatPayoffExtrapolation+  ,withMaybeQuote*`Maybe (GenQuote q)' -- ^oas+  ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discountCurve+  ,`Bool' -- ^includeTodaysExercise+  ,`Probabilities' -- ^probabilities+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |swaption pricing engine using Jamshidian's decomposition, for any one-factor Gaussian+-- short-rate model.+{#fun qlGaussian1dJamshidianSwaptionEngine as gaussian1dJamshidianSwaptionEngine{withStandalone*`Gaussian1dModel',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}+ -- |Ju (1999) quadratic-approximation engine for American options {#fun qlJuQuadraticApproximationEngine as juQuadraticApproximationEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#} @@ -842,6 +996,13 @@  -- |pricing engine for vanilla options using binomial trees {#fun qlBinomialVanillaEngine as binomialVanillaEngine{`BinomialTree',withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',fromIntegral`Word' -- ^timeSteps+  ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}++-- |finite-differences Black-Scholes pricing engine for discrete-averaging Asian options+{#fun qlFdBlackScholesAsianEngine as fdBlackScholesAsianEngine{withGeneralizedBlackScholesProcess*`GeneralizedBlackScholesProcess',fromIntegral`Word' -- ^tGrid+  ,fromIntegral`Word' -- ^xGrid+  ,fromIntegral`Word' -- ^aGrid+  ,withFdmSchemeDesc*`FdmScheme'   ,preErrorCheck-`String'errorCheck*-}->`PricingEngine'peekPricingEngine*#}  -- |finite-differences Black-Scholes pricing engine for vanilla options
QuantLib/Quote.chs view
@@ -29,7 +29,7 @@   , linkTo   ) where import QuantLib.Internal-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Type  #include "qlTypesC2HS.h"
+ QuantLib/TermStructure/Commodity.chs view
@@ -0,0 +1,157 @@+module QuantLib.TermStructure.Commodity+  (+    CommodityCurve+  , commodityCurve+  , commodityCurveName+  , commodityCurveCommodityType+  , commodityCurveUnitOfMeasure+  , commodityCurveCurrency+  , commodityCurveDates+  , commodityCurvePrices+  , commodityCurveEmpty+  , commodityCurveBasisOfCurve+  , setCommodityCurveBasisOfCurve+  , commodityCurvePrice+  , commodityCurveBasisOfPrice+  , ExchangeContract+  , ExchangeContracts+  , commodityCurvePriceNearby+  , commodityCurveUnderlyingPriceDate+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "qlEnumObjects.h"++#include "ql.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *Currency foreign -> CCurrency nocode#}+{#pointer *CommodityType foreign -> CCommodityType nocode#}+{#pointer *UnitOfMeasure foreign -> CUnitOfMeasure nocode#}+{#pointer *DayCounter foreign -> CDayCounter nocode#}+{#pointer *QlCommodityCurve as CommodityCurve foreign -> CCommodityCurve' nocode#}++-- |Construct a commodity price curve: a named, interpolated (forward-flat) price curve over a+-- fixed set of dates, for a given commodity type\/currency\/unit of measure. QuantLib's no-dates+-- constructor (populated later via the mutator @setPrices@) is not bound -- per the standing+-- setter-confirmation rule, only 'setCommodityCurveBasisOfCurve' was confirmed, not @setPrices@ --+-- so this with-dates constructor is the only way to build one.+{#fun qlCommodityCurve as commodityCurve+  {`String' -- ^name+  ,withCommodityType*`CommodityType'+  ,withCurrency*`Currency'+  ,withUnitOfMeasure*`UnitOfMeasure'+  ,withCalendar*`Calendar'+  ,withDayArray*`[Day]'&+  ,withDoubleArray*`[Double]'&+  ,withDayCounter*`DayCounter'+  ,preErrorCheck-`String'errorCheck*-}->`CommodityCurve'peekCommodityCurve*#}++-- |The curve's name, as given at construction.+{#fun qlCommodityCurveName as commodityCurveName{withGenTermStructure*`CommodityCurve'}->`String'peekDynString*#}++-- |The commodity type this curve prices.+{#fun qlCommodityCurveCommodityType as commodityCurveCommodityType{withGenTermStructure*`CommodityCurve',preErrorCheck-`String'errorCheck*-}->`CommodityType'peekCommodityType*#}++-- |The unit of measure this curve's prices are quoted in.+{#fun qlCommodityCurveUnitOfMeasure as commodityCurveUnitOfMeasure{withGenTermStructure*`CommodityCurve',preErrorCheck-`String'errorCheck*-}->`UnitOfMeasure'peekUnitOfMeasure*#}++-- |The currency this curve's prices are quoted in.+{#fun qlCommodityCurveCurrency as commodityCurveCurrency{withGenTermStructure*`CommodityCurve',preErrorCheck-`String'errorCheck*-}->`Currency'peekCurrency*#}++-- |The curve's node dates, as given at construction.+{#fun qlCommodityCurveDates as commodityCurveDates{withGenTermStructure*`CommodityCurve',preArray-`[Day]'&peekDayArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |The curve's node prices, as given at construction. Paired positionally with 'commodityCurveDates'+-- -- upstream's own @nodes()@ getter is just their zip, so it isn't bound separately (per "bind+-- few inspectors").+{#fun qlCommodityCurvePrices as commodityCurvePrices{withGenTermStructure*`CommodityCurve',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |Whether this curve has any nodes.+{#fun pure qlCommodityCurveEmpty as commodityCurveEmpty{withGenTermStructure*`CommodityCurve'}->`Bool'#}++-- |The basis curve this curve was chained to via 'setCommodityCurveBasisOfCurve', if any.+{#fun qlCommodityCurveBasisOfCurve as commodityCurveBasisOfCurve{withGenTermStructure*`CommodityCurve'}->`Maybe CommodityCurve'peekMaybeCommodityCurve*#}++-- |Chain this curve to a basis curve: prices returned by 'commodityCurvePrice'\/'commodityCurveBasisOfPrice'+-- then include the basis curve's price on top of this curve's own. Confirmed with the user as the+-- one 'CommodityCurve' mutator worth binding (unlike @setPrices@, which stays unbound).+{#fun qlCommodityCurveSetBasisOfCurve as setCommodityCurveBasisOfCurve{withGenTermStructure*`CommodityCurve',withGenTermStructure*`CommodityCurve',preErrorCheck-`String'errorCheck*-}->`()'#}++-- |A dated exchange contract: a code, its expiration date, and the start/end dates of the+-- underlying delivery period it corresponds to. A plain tuple, per the @Money@/'Quantity'-as-tuple+-- convention -- it carries no calculation of its own upstream, only three inspectors that would+-- just be tuple projections.+type ExchangeContract = (String, Day, Day, Day) -- ^code, expirationDate, underlyingStartDate, underlyingEndDate++-- |QuantLib's @std::map\<Date,ExchangeContract\>@: a set of exchange contracts, keyed by the date+-- 'commodityCurvePriceNearby'\/'commodityCurveUnderlyingPriceDate' roll onto (upstream's own+-- @lower_bound@ walk finds the first key at or after the query date, then steps @nearbyOffset - 1@+-- further). Marshalled as an association list, not an actual 'Data.Map.Map' -- the C shim rebuilds+-- the real @std::map@ itself so key order doesn't need to be pre-sorted on the Haskell side.+type ExchangeContracts = [(Day, ExchangeContract)]++-- |Split an 'ExchangeContracts' into the five parallel lists the low-level bindings below take.+-- Not a single combined marshaller: c2hs's @&@ tuple-splitter only ever consumes two C arguments+-- (confirmed against its source, same reasoning as 'QuantLib.Commodity.Quantity'), so each list is+-- passed as its own flat, individually-marshalled argument instead of one bundled continuation.+splitExchangeContracts :: ExchangeContracts -> ([Day], [String], [Day], [Day], [Day])+splitExchangeContracts ecs =+  ( map fst ecs+  , [c | (_, (c, _, _, _)) <- ecs]+  , [x | (_, (_, x, _, _)) <- ecs]+  , [s | (_, (_, _, s, _)) <- ecs]+  , [e | (_, (_, _, _, e)) <- ecs] )++{#fun qlCommodityCurvePrice as qlCommodityCurvePrice_+  {withGenTermStructure*`CommodityCurve'+  ,withDay*`Day'+  ,withDayArray*`[Day]'&+  ,withStringArray*`[String]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,`Int' -- ^nearbyOffset+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The curve's price for a date, plus any chained basis curve's price, rolling forward onto+-- nearby exchange contracts when @nearbyOffset > 0@ (upstream's own @price@ never touches+-- @exchangeContracts@ otherwise). 'commodityCurvePrice' is this with no exchange contracts and+-- offset @0@, which reproduces the flat (no-rolling) case exactly.+commodityCurvePriceNearby :: CommodityCurve -> Day -> ExchangeContracts -> Int -> IO Double+commodityCurvePriceNearby curve date ecs nearbyOffset =+  qlCommodityCurvePrice_ curve date keys codes expirations starts ends nearbyOffset+  where (keys, codes, expirations, starts, ends) = splitExchangeContracts ecs++-- |The curve's price for a date, plus any chained basis curve's price. This is+-- 'commodityCurvePriceNearby' with no exchange contracts and offset @0@ -- the flat (no+-- nearby-rolling) case, which never touches @exchangeContracts@ upstream either way.+commodityCurvePrice :: CommodityCurve -> Day -> IO Double+commodityCurvePrice curve date = commodityCurvePriceNearby curve date [] 0++-- |The chained basis curve's price alone (excluding this curve's own price), for a date.+{#fun qlCommodityCurveBasisOfPrice as commodityCurveBasisOfPrice{withGenTermStructure*`CommodityCurve',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Double'#}++{#fun qlCommodityCurveUnderlyingPriceDate as qlCommodityCurveUnderlyingPriceDate_+  {withGenTermStructure*`CommodityCurve'+  ,withDay*`Day'+  ,withDayArray*`[Day]'&+  ,withStringArray*`[String]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,withDayArray*`[Day]'&+  ,`Int' -- ^nearbyOffset+  ,preErrorCheck-`String'errorCheck*-}->`Day'toDay#}++-- |The date whose price a nearby roll (@nearbyOffset > 0@) actually reads: the underlying+-- contract's start date at the @nearbyOffset@\'th exchange contract at or after @date@. Throws if+-- @nearbyOffset <= 0@, or if fewer than @nearbyOffset@ contracts are available from @date@ onward.+commodityCurveUnderlyingPriceDate :: CommodityCurve -> Day -> ExchangeContracts -> Int -> IO Day+commodityCurveUnderlyingPriceDate curve date ecs nearbyOffset =+  qlCommodityCurveUnderlyingPriceDate_ curve date keys codes expirations starts ends nearbyOffset+  where (keys, codes, expirations, starts, ends) = splitExchangeContracts ecs++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
QuantLib/TermStructure/Credit.chs view
@@ -31,14 +31,14 @@ #include "qlEnumObjects.h"  import QuantLib.Internal-{#import QuantLib.Time.Calendar#}(BusinessDayConvention) {#import QuantLib.Instrument#}(PricingModel) import QuantLib.Internal.Type {#import QuantLib.Time.Schedule#}(DateGenerationRule, Frequency)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common  {#enum ProbabilityTrait{} deriving(Show, Eq)#} +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *QlDefaultProbabilityTermStructure as DefaultProbabilityTermStructure foreign -> CDefaultProbabilityTermStructure' nocode#} {#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#} {#pointer *QlTermStructure as TermStructure foreign -> CTermStructure' nocode#}@@ -102,7 +102,7 @@ {#fun qlSpreadCdsHelper as spreadCdsHelper{withQuote*`GenQuote q' -- ^runningSpread   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^tenor   ,`Int' -- ^settlementDays-  ,withCalendar*`Calendar',`Frequency',`BusinessDayConvention',`DateGenerationRule',withDayCounter*`DayCounter'+  ,withCalendar*`Calendar',`Frequency',fromEnumC`BusinessDayConvention',`DateGenerationRule',withDayCounter*`DayCounter'   ,`Double' -- recoveryRate   ,withYieldTermStructure*`GenYieldTermStructure y' -- ^discountCurve   ,`Bool' -- ^settlesAccrual@@ -118,7 +118,7 @@   ,`Double' -- ^runningSpread   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^tenor   ,`Int' -- ^settlementDays-  ,withCalendar*`Calendar',`Frequency',`BusinessDayConvention',`DateGenerationRule',withDayCounter*`DayCounter'+  ,withCalendar*`Calendar',`Frequency',fromEnumC`BusinessDayConvention',`DateGenerationRule',withDayCounter*`DayCounter'   ,`Double' -- ^recoveryDate   ,withYieldTermStructure*`GenYieldTermStructure y' -- ^discountCurve   ,fromIntegral`Word' -- ^upfrontSettlementDays
QuantLib/TermStructure/Inflation.chs view
@@ -5,7 +5,7 @@   , ZeroCouponInflationSwapHelper   , YearOnYearInflationSwapHelper -  , CPIInterpolationType(..) -- ^re-exported from "QuantLib.Internal.Enum"+  , CPIInterpolationType(..) -- ^re-exported from "QuantLib.Internal.Common"    , zeroCouponInflationSwapHelper   , yearOnYearInflationSwapHelper@@ -14,15 +14,15 @@    , piecewiseZeroInflationCurve   , piecewiseYoYInflationCurve+  , interpolatedYoYInflationCurve    , zeroRate   , yoyRate   ) where import QuantLib.Internal-{#import QuantLib.Time.Calendar#}(BusinessDayConvention) import QuantLib.Internal.Type {#import QuantLib.Time.Schedule#}(Frequency)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common {#import QuantLib.TermStructure.Yield#}(PillarChoice)  #include "qlTypesC2HS.h"@@ -31,6 +31,7 @@  #include "ql.h" +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *QlQuote as Quote foreign -> CQuote' nocode#} {#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#} {#pointer *QlZeroInflationTermStructure as ZeroInflationTermStructure foreign -> CZeroInflationTermStructure' nocode#}@@ -47,7 +48,7 @@   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^swapObsLag   ,withDay*`Day' -- ^maturity   ,withCalendar*`Calendar'-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withDayCounter*`DayCounter'   ,withZeroInflationIndex*`ZeroInflationIndex'   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation@@ -61,7 +62,7 @@   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^swapObsLag   ,withDay*`Day' -- ^maturity   ,withCalendar*`Calendar'-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withDayCounter*`DayCounter'   ,withYoYInflationIndex*`YoYInflationIndex'   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation@@ -97,6 +98,20 @@ -- interpolating between the bootstrapped nodes with the given 'Interpolation'. {#fun qlPiecewiseYoYInflationCurve{withDay*`Day',withDay*`Day',`Double',`Frequency',withDayCounter*`DayCounter'   ,withYearOnYearInflationSwapHelperArray*`[YearOnYearInflationSwapHelper]'&+  ,`Int',`Int',`Int',preErrorCheck-`String'errorCheck*-}->`YoYInflationTermStructure'peekYoYInflationTermStructure*#}++-- |A YoY-inflation curve interpolating directly between given (date, rate) nodes, unlike+-- 'piecewiseYoYInflationCurve''s bootstrap from swap helpers -- useful when the rates are+-- already known market YoY levels rather than swap quotes to calibrate against. The first+-- node is the curve's own base date\/rate.+interpolatedYoYInflationCurve :: Day -- ^referenceDate+  -> [(Day, Double)] -- ^dates, rates+  -> Frequency -> DayCounter -> Interpolation+  -> IO YoYInflationTermStructure+interpolatedYoYInflationCurve r dr f dc i = uncurryNested (qlInterpolatedYoYInflationCurve r ds rs f dc) (qlInterpolation i)+  where (ds, rs) = unzip dr+{#fun qlInterpolatedYoYInflationCurve{withDay*`Day',withDayArray*`[Day]'&,withDoubleArrayRaw*`[Double]'+  ,`Frequency',withDayCounter*`DayCounter'   ,`Int',`Int',`Int',preErrorCheck-`String'errorCheck*-}->`YoYInflationTermStructure'peekYoYInflationTermStructure*#}  -- |Zero-coupon inflation rate implied by the curve.
+ QuantLib/TermStructure/InflationVolatility.chs view
@@ -0,0 +1,297 @@+module QuantLib.TermStructure.InflationVolatility+  (+    YoYOptionletVolatilitySurface++  , constantYoYOptionletVolatility+  , kInterpolatedYoYOptionletVolatilitySurfaceBlack+  , kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack+  , kInterpolatedYoYOptionletVolatilitySurfaceBachelier++  , yoyOptionletVolatility+  , yoyOptionletTotalVariance++  , YoYCapFloorTermPriceSurface+  , yoyCapFloorTermPriceSurface++  , yoyCapFloorBaseDate+  , yoyCapFloorAtmYoYSwapDateRates+  , yoyCapFloorAtmYoYSwapRate+  , yoyCapFloorAtmYoYRate+  , yoyCapFloorStrikes++  , CPICapFloorTermPriceSurface+  , cpiCapFloorTermPriceSurface++  , CPIVolatilitySurface+  , constantCPIVolatility++  , cpiVolatility+  , cpiTotalVariance+  ) where+import QuantLib.Internal+import QuantLib.Internal.Type+{#import QuantLib.InterestRate#}(VolatilityType)+{#import QuantLib.Time.Schedule#}(Frequency)+import QuantLib.Internal.Common++#include "qlTypesC2HS.h"+#include "qlEnumC2HS.h"+#include "ql.h"+#include "qlEnumObjects.h"++{#pointer *Calendar foreign -> CCalendar nocode#}+{#pointer *DayCounter foreign -> CDayCounter nocode#}+{#pointer *QlQuote as Quote foreign -> CQuote' nocode#}+{#pointer *QlYieldTermStructure as YieldTermStructure foreign -> CYieldTermStructure' nocode#}+{#pointer *QlZeroInflationIndex as ZeroInflationIndex foreign -> CZeroInflationIndex' nocode#}+{#pointer *QlYoYInflationIndex as YoYInflationIndex foreign -> CYoYInflationIndex' nocode#}+{#pointer *QlYoYOptionletVolatilitySurface as YoYOptionletVolatilitySurface foreign -> CYoYOptionletVolatilitySurface' nocode#}+{#pointer *QlYoYCapFloorTermPriceSurface as YoYCapFloorTermPriceSurface foreign -> CYoYCapFloorTermPriceSurface' nocode#}+{#pointer *QlCPICapFloorTermPriceSurface as CPICapFloorTermPriceSurface foreign -> CCPICapFloorTermPriceSurface' nocode#}+{#pointer *QlCPIVolatilitySurface as CPIVolatilitySurface foreign -> CCPIVolatilitySurface' nocode#}++-- |Constant YoY-inflation optionlet vol surface, no maturity\/strike dependence. Mirrors+-- 'QuantLib.TermStructure.Volatility.constantOptionletVolatility', taking a 'GenQuote' rather+-- than a plain 'Double' per the @std::variant@\/overload-collapse rule (the flat case is already+-- reachable via 'QuantLib.Quote.simpleQuote'). Not the only concrete leaf of this type any+-- more -- see 'kInterpolatedYoYOptionletVolatilitySurfaceBlack' for the market-quote-bootstrapped+-- alternative.+{#fun qlConstantYoYOptionletVolatility as constantYoYOptionletVolatility{withQuote*`GenQuote q'+  ,fromIntegral`Word' -- ^settlementDays+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDayCounter*`DayCounter'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag+  ,`Frequency'+  ,`Bool' -- ^indexIsInterpolated+  ,`Double' -- ^minStrike+  ,`Double' -- ^maxStrike+  ,`VolatilityType'+  ,`Double' -- ^displacement+  ,preErrorCheck-`String'errorCheck*-}->`YoYOptionletVolatilitySurface'peekYoYOptionletVolatilityStructure*#}++-- |The volatility for a given maturity date and strike, observed with the given observation+-- lag (or the surface's own lag when 'Nothing').+{#fun qlYoYOptionletVolatilitySurfaceVolatility as yoyOptionletVolatility{withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface'+  ,withDay*`Day'+  ,`Double' -- ^strike+  ,fromMaybeEnumQuantity`Maybe (Word,TimeUnit)'& -- ^obsLag+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The total integrated variance for a given exercise date and strike -- useful because it+-- scales out time from the optionlet pricing formulae. As 'yoyOptionletVolatility', a+-- 'Nothing' observation lag uses the surface's own.+{#fun qlYoYOptionletVolatilitySurfaceTotalVariance as yoyOptionletTotalVariance{withGenVolatilityTermStructure*`YoYOptionletVolatilitySurface'+  ,withDay*`Day'+  ,`Double' -- ^strike+  ,fromMaybeEnumQuantity`Maybe (Word,TimeUnit)'& -- ^obsLag+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |Prices YoY cap\/floors by cap\/floor-surface intersection and put\/call parity, deriving an+-- ATM YoY swap curve as a side effect. 'Interpolation2D' chooses the cap\/floor price-grid+-- interpolator, 'Interpolation' the per-maturity one.+yoyCapFloorTermPriceSurface :: Word -- ^fixingDays+  -> (Word, TimeUnit) -- ^yyLag+  -> YoYInflationIndex -> CPIInterpolationType -> GenYieldTermStructure y -- ^nominal+  -> DayCounter -> Calendar -> BusinessDayConvention+  -> [Double] -- ^cStrikes+  -> [Double] -- ^fStrikes+  -> [(Word, TimeUnit)] -- ^cfMaturities+  -> Matrix Double -- ^cPrice+  -> Matrix Double -- ^fPrice+  -> Interpolation2D -> Interpolation+  -> IO YoYCapFloorTermPriceSurface+yoyCapFloorTermPriceSurface fixingDays yyLag yii interp nominal dc cal bdc cStrikes fStrikes cfMaturities (Matrix cr cc cd) (Matrix fr fc fd) i2d i1d =+  uncurryNested (qlYoYCapFloorTermPriceSurface fixingDays yyLag yii interp nominal dc cal bdc cStrikes fStrikes maturityNums maturityUnits cr cc cd fr fc fd (fromEnum i2d)) (qlInterpolation i1d)+  where (maturityNums, maturityUnits) = unzip cfMaturities+{#fun qlYoYCapFloorTermPriceSurface{fromIntegral`Word' -- ^fixingDays+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^yyLag+  ,withYoYInflationIndex*`YoYInflationIndex'+  ,fromEnumC`CPIInterpolationType'+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominal+  ,withDayCounter*`DayCounter'+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDoubleArray*`[Double]'& -- ^cStrikes+  ,withDoubleArray*`[Double]'& -- ^fStrikes+  ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'& -- ^cfMaturities+  ,fromIntegral`Word',fromIntegral`Word',withDoubleArrayRaw*`[Double]' -- ^cPrice+  ,fromIntegral`Word',fromIntegral`Word',withDoubleArrayRaw*`[Double]' -- ^fPrice+  ,`Int' -- ^interpolator2D+  ,`Int',`Int',`Int' -- ^interpolator1D, approximator, approximatorArg+  ,preErrorCheck-`String'errorCheck*-}->`YoYCapFloorTermPriceSurface'peekYoYCapFloorTermPriceSurface*#}++-- |The date the surface's own YoY term structure (and hence any 'YoYOptionletVolatilitySurface'+-- stripped from it) treats as its base -- referenceDate minus the observation lag, rounded to+-- the containing inflation period's start.+{#fun qlYoYCapFloorTermPriceSurfaceBaseDate as yoyCapFloorBaseDate{withGenTermStructure*`YoYCapFloorTermPriceSurface'+  ,preErrorCheck-`String'errorCheck*-}->`Day'toDay#}++-- |The ATM YoY swap curve derived from cap\/floor-surface intersection, as (date, rate) pairs.+yoyCapFloorAtmYoYSwapDateRates :: YoYCapFloorTermPriceSurface -> IO [(Day, Double)]+yoyCapFloorAtmYoYSwapDateRates s = do+  (ds, rs) <- qlYoYCapFloorTermPriceSurfaceAtmYoYSwapDateRates s+  return $ zip ds rs+{#fun qlYoYCapFloorTermPriceSurfaceAtmYoYSwapDateRates{withGenTermStructure*`YoYCapFloorTermPriceSurface'+  ,preArray-`[Day]'&peekDayArray*,preArray-`[Double]'&peekDoubleArray*}->`()'#}++-- |The ATM YoY swap rate at the given maturity date, from put\/call parity on the surface's+-- cap\/floor price data.+{#fun qlYoYCapFloorTermPriceSurfaceAtmYoYSwapRate as yoyCapFloorAtmYoYSwapRate{withGenTermStructure*`YoYCapFloorTermPriceSurface'+  ,withDay*`Day'+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The ATM YoY inflation rate at the given maturity date and observation lag (or the surface's+-- own lag when 'Nothing'), derived from the swap-rate curve above.+{#fun qlYoYCapFloorTermPriceSurfaceAtmYoYRate as yoyCapFloorAtmYoYRate{withGenTermStructure*`YoYCapFloorTermPriceSurface'+  ,withDay*`Day'+  ,fromMaybeEnumQuantity`Maybe (Word,TimeUnit)'& -- ^obsLag+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The union of cap and floor strikes in the surface's price grid -- the strikes a stripped+-- 'YoYOptionletVolatilitySurface' (via 'kInterpolatedYoYOptionletVolatilitySurfaceBlack' et al.)+-- has a bootstrapped vol curve for.+{#fun qlYoYCapFloorTermPriceSurfaceStrikes as yoyCapFloorStrikes{withGenTermStructure*`YoYCapFloorTermPriceSurface'+  ,preArray-`[Double]'&peekDoubleArray*}->`()'#}++-- |Strips a 'YoYOptionletVolatilitySurface' from a 'YoYCapFloorTermPriceSurface' by bootstrapping+-- a per-strike vol curve against Black-priced YoY caps\/floors (mirrors upstream's own+-- @testYoYPriceSurfaceToVol@: an @InterpolatedYoYOptionletStripper@ solving each strike's initial+-- vol, then a @KInterpolatedYoYOptionletVolatilitySurface@ interpolating across strikes, both+-- sharing the given 'Interpolation' -- neither is exposed as its own type, since nothing in+-- upstream reaches them from outside this one bootstrap; see this function's C shim for the full+-- pipeline). /index/\//nominalTermStructure/ price the null-vol engine the stripper solves+-- against; /slope/ is the assumed initial caplet-vol slope for strikes past the edge of good+-- price data (a negative slope for typically low\/flat short-dated extreme-strike prices, per+-- upstream's own comment -- too extreme a slope can leave no arbitrage-free solution).+kInterpolatedYoYOptionletVolatilitySurfaceBlack :: Word -- ^settlementDays+  -> Calendar -> BusinessDayConvention -> DayCounter+  -> YoYCapFloorTermPriceSurface -- ^capFloorPrices+  -> YoYInflationIndex -- ^index+  -> GenYieldTermStructure y -- ^nominalTermStructure+  -> Double -- ^slope+  -> Interpolation+  -> IO YoYOptionletVolatilitySurface+kInterpolatedYoYOptionletVolatilitySurfaceBlack settlementDays cal bdc dc capFloorPrices index nominalTs slope i1d =+  uncurryNested (qlKInterpolatedYoYOptionletVolatilitySurfaceBlack settlementDays cal bdc dc capFloorPrices index nominalTs slope) (qlInterpolation i1d)+{#fun qlKInterpolatedYoYOptionletVolatilitySurfaceBlack{fromIntegral`Word' -- ^settlementDays+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDayCounter*`DayCounter'+  ,withGenTermStructure*`YoYCapFloorTermPriceSurface' -- ^capFloorPrices+  ,withYoYInflationIndex*`YoYInflationIndex' -- ^index+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,`Double' -- ^slope+  ,`Int',`Int',`Int' -- ^interpolator, approximator, approximatorArg+  ,preErrorCheck-`String'errorCheck*-}->`YoYOptionletVolatilitySurface'peekYoYOptionletVolatilityStructure*#}++-- |As 'kInterpolatedYoYOptionletVolatilitySurfaceBlack', but unit-displaced Black.+kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack :: Word -- ^settlementDays+  -> Calendar -> BusinessDayConvention -> DayCounter+  -> YoYCapFloorTermPriceSurface -- ^capFloorPrices+  -> YoYInflationIndex -- ^index+  -> GenYieldTermStructure y -- ^nominalTermStructure+  -> Double -- ^slope+  -> Interpolation+  -> IO YoYOptionletVolatilitySurface+kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack settlementDays cal bdc dc capFloorPrices index nominalTs slope i1d =+  uncurryNested (qlKInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack settlementDays cal bdc dc capFloorPrices index nominalTs slope) (qlInterpolation i1d)+{#fun qlKInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack{fromIntegral`Word' -- ^settlementDays+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDayCounter*`DayCounter'+  ,withGenTermStructure*`YoYCapFloorTermPriceSurface' -- ^capFloorPrices+  ,withYoYInflationIndex*`YoYInflationIndex' -- ^index+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,`Double' -- ^slope+  ,`Int',`Int',`Int' -- ^interpolator, approximator, approximatorArg+  ,preErrorCheck-`String'errorCheck*-}->`YoYOptionletVolatilitySurface'peekYoYOptionletVolatilityStructure*#}++-- |As 'kInterpolatedYoYOptionletVolatilitySurfaceBlack', but Bachelier (normal model).+kInterpolatedYoYOptionletVolatilitySurfaceBachelier :: Word -- ^settlementDays+  -> Calendar -> BusinessDayConvention -> DayCounter+  -> YoYCapFloorTermPriceSurface -- ^capFloorPrices+  -> YoYInflationIndex -- ^index+  -> GenYieldTermStructure y -- ^nominalTermStructure+  -> Double -- ^slope+  -> Interpolation+  -> IO YoYOptionletVolatilitySurface+kInterpolatedYoYOptionletVolatilitySurfaceBachelier settlementDays cal bdc dc capFloorPrices index nominalTs slope i1d =+  uncurryNested (qlKInterpolatedYoYOptionletVolatilitySurfaceBachelier settlementDays cal bdc dc capFloorPrices index nominalTs slope) (qlInterpolation i1d)+{#fun qlKInterpolatedYoYOptionletVolatilitySurfaceBachelier{fromIntegral`Word' -- ^settlementDays+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDayCounter*`DayCounter'+  ,withGenTermStructure*`YoYCapFloorTermPriceSurface' -- ^capFloorPrices+  ,withYoYInflationIndex*`YoYInflationIndex' -- ^index+  ,withYieldTermStructure*`GenYieldTermStructure y' -- ^nominalTermStructure+  ,`Double' -- ^slope+  ,`Int',`Int',`Int' -- ^interpolator, approximator, approximatorArg+  ,preErrorCheck-`String'errorCheck*-}->`YoYOptionletVolatilitySurface'peekYoYOptionletVolatilityStructure*#}++-- |Prices CPI cap\/floors by interpolation and put\/call parity off a market strike\/maturity+-- price grid. 'Interpolation2D' chooses the cap\/floor price-grid interpolator. @cPrice@\/+-- @fPrice@ are plain price matrices (rows = strikes, columns = maturities), not quote-linked+-- like 'QuantLib.TermStructure.Volatility.capFloorTermVolSurface's volatility matrix.+cpiCapFloorTermPriceSurface :: Double -- ^nominal+  -> Double -- ^baseRate+  -> (Word, TimeUnit) -- ^observationLag+  -> Calendar -> BusinessDayConvention -> DayCounter+  -> ZeroInflationIndex -> CPIInterpolationType -> GenYieldTermStructure y+  -> [Double] -- ^cStrikes+  -> [Double] -- ^fStrikes+  -> [(Word, TimeUnit)] -- ^cfMaturities+  -> Matrix Double -- ^cPrice+  -> Matrix Double -- ^fPrice+  -> Interpolation2D+  -> IO CPICapFloorTermPriceSurface+cpiCapFloorTermPriceSurface nom baseRate obsLag cal bdc dc zii interp yts cStrikes fStrikes cfMaturities (Matrix cr cc cd) (Matrix fr fc fd) i2d =+  qlCPICapFloorTermPriceSurface nom baseRate obsLag cal bdc dc zii interp yts cStrikes fStrikes maturityNums maturityUnits cr cc cd fr fc fd (fromEnum i2d)+  where (maturityNums, maturityUnits) = unzip cfMaturities+{#fun qlCPICapFloorTermPriceSurface{`Double',`Double',fromEnumQuantity`(Word,TimeUnit)'&+  ,withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter'+  ,withZeroInflationIndex*`ZeroInflationIndex',fromEnumC`CPIInterpolationType'+  ,withYieldTermStructure*`GenYieldTermStructure y'+  ,withDoubleArray*`[Double]'& -- ^cStrikes+  ,withDoubleArray*`[Double]'& -- ^fStrikes+  ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'& -- ^cfMaturities+  ,fromIntegral`Word',fromIntegral`Word',withDoubleArrayRaw*`[Double]' -- ^cPrice+  ,fromIntegral`Word',fromIntegral`Word',withDoubleArrayRaw*`[Double]' -- ^fPrice+  ,`Int' -- ^interpolator2D+  ,preErrorCheck-`String'errorCheck*-}->`CPICapFloorTermPriceSurface'peekCPICapFloorTermPriceSurface*#}++-- |Constant CPI (zero-inflation) volatility surface, no maturity\/strike dependence -- the only+-- concrete leaf bound here, mirroring 'constantYoYOptionletVolatility'. No engine or coupon+-- pricer consumes this in QL 1.43 (see this type's own haddock in "QuantLib.Internal.Type"), so+-- it is queryable via 'cpiVolatility'\/'cpiTotalVariance' but not otherwise wired up.+{#fun qlConstantCPIVolatility as constantCPIVolatility{withQuote*`GenQuote q'+  ,fromIntegral`Word' -- ^settlementDays+  ,withCalendar*`Calendar'+  ,fromEnumC`BusinessDayConvention'+  ,withDayCounter*`DayCounter'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^observationLag+  ,`Frequency'+  ,`Bool' -- ^indexIsInterpolated+  ,preErrorCheck-`String'errorCheck*-}->`CPIVolatilitySurface'peekCPIVolatilitySurface*#}++-- |The volatility for a given maturity date and strike, observed with the given observation+-- lag (or the surface's own lag when 'Nothing').+{#fun qlCPIVolatilitySurfaceVolatility as cpiVolatility{withGenVolatilityTermStructure*`CPIVolatilitySurface'+  ,withDay*`Day'+  ,`Double' -- ^strike+  ,fromMaybeEnumQuantity`Maybe (Word,TimeUnit)'& -- ^obsLag+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The total integrated variance for a given exercise date and strike. As 'cpiVolatility', a+-- 'Nothing' observation lag uses the surface's own.+{#fun qlCPIVolatilitySurfaceTotalVariance as cpiTotalVariance{withGenVolatilityTermStructure*`CPIVolatilitySurface'+  ,withDay*`Day'+  ,`Double' -- ^strike+  ,fromMaybeEnumQuantity`Maybe (Word,TimeUnit)'& -- ^obsLag+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}
QuantLib/TermStructure/Volatility.chs view
@@ -15,6 +15,9 @@   , GenBlackVolTermStructure   , RelinkableBlackVolTermStructure   , CallableBondVolatilityStructure+  , CapFloorTermVolatilityStructure+  , GenCapFloorTermVolatilityStructure+  , CapFloorTermVolCurve   , CapFloorTermVolSurface   , LocalVolTermStructure   , OptionletVolatilityStructure@@ -26,6 +29,13 @@   , RelinkableSwaptionVolatilityStructure   , VolatilityTermStructure   , GenVolatilityTermStructure+  , BlackAtmVolCurve+  , GenBlackAtmVolCurve+  , BlackVolSurface+  , GenBlackVolSurface+  , AbcdAtmVolCurve+  , SabrVolSurface+  , OptionletStripper2    , asVolatilityTermStructure   , asBlackVolTermStructure@@ -34,6 +44,11 @@   , constantOptionletVolatility   , constantOptionletVolatility'   , optionletStripper1+  , optionletStripper2+  , optionletStripper2AsOptionletVolatilityStructure+  , optionletStripper2AtmCapFloorStrikes+  , optionletStripper2AtmCapFloorPrices+  , optionletStripper2SpreadsVol    , impliedVolTermStructure   , blackConstantVol'@@ -85,6 +100,42 @@   , callableBondConstantVolatility   , constantCapFloorTermVolatility'   , constantCapFloorTermVolatility+  , capFloorVolatilityForPeriod+  , capFloorVolatilityForDate+  , capFloorVolatilityForTime+  , capFloorTermVolCurveOptionDates+  , capFloorTermVolCurveOptionTimes+  , capFloorTermVolSurfaceOptionDates+  , capFloorTermVolSurfaceOptionTimes+  , atmVolForPeriod+  , atmVolForDate+  , atmVolForTime+  , atmVarianceForPeriod+  , atmVarianceForDate+  , atmVarianceForTime+  , blackVolSurfaceSmileSectionForPeriod+  , blackVolSurfaceSmileSectionForDate+  , blackVolSurfaceSmileSectionForTime+  , abcdAtmVolCurve+  , abcdAtmVolCurveA+  , abcdAtmVolCurveB+  , abcdAtmVolCurveC+  , abcdAtmVolCurveD+  , abcdAtmVolCurveRmsError+  , abcdAtmVolCurveMaxError+  , abcdAtmVolCurveEndCriteria+  , abcdAtmVolCurveK+  , abcdAtmVolCurveKAtTime+  , abcdAtmVolCurveOptionTenors+  , abcdAtmVolCurveOptionTenorsInInterpolation+  , abcdAtmVolCurveOptionDates+  , abcdAtmVolCurveOptionTimes+  , sabrVolSurface+  , sabrVolSurfaceAtmCurve+  , sabrVolSurfaceVolatilitySpreadsForPeriod+  , sabrVolSurfaceVolatilitySpreadsForDate+  , sabrVolSurfaceIndex+  , sabrVolSurfaceOptionDateFromTenor   , spreadedSwaptionVolatility   , relinkableSwaptionVolatilityStructure   , linkSwaptionVolTo@@ -128,13 +179,11 @@   , atmSmileSection   ) where import QuantLib.Internal-import Foreign.C.Types(CInt)-{#import QuantLib.Time.Calendar#}(BusinessDayConvention) {#import QuantLib.InterestRate#}(VolatilityType) {#import QuantLib.Math#}(EndCriteriaType) {#import QuantLib.Quote#}(DeltaType(..), AtmType(..)) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Syntax(deriveOptionsRecord) import QuantLib.Time.Schedule(dayCounter, DayCounterConstructor(..)) @@ -143,6 +192,7 @@ #include "ql.h" #include "qlEnumObjects.h" +{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *DayCounter foreign -> CDayCounter nocode#} {#pointer *QlQuote as Quote foreign -> CQuote' nocode#} {#pointer *QlIborIndex as IborIndex foreign -> CIborIndex' nocode#}@@ -160,18 +210,26 @@ {#pointer *QlBlackVolTermStructure as BlackVolTermStructure foreign -> CBlackVolTermStructure' nocode#} {#pointer *QlRelinkableBlackVolTermStructure as RelinkableBlackVolTermStructure foreign -> CRelinkableBlackVolTermStructure' nocode#} {#pointer *QlCallableBondVolatilityStructure as CallableBondVolatilityStructure foreign -> CCallableBondVolatilityStructure' nocode#}+{#pointer *QlCapFloorTermVolatilityStructure as CapFloorTermVolatilityStructure foreign -> CCapFloorTermVolatilityStructure' nocode#}+{#pointer *QlCapFloorTermVolCurve as CapFloorTermVolCurve foreign -> CCapFloorTermVolCurve' nocode#} {#pointer *QlCapFloorTermVolSurface as CapFloorTermVolSurface foreign -> CCapFloorTermVolSurface' nocode#} {#pointer *QlSwaptionVolatilityStructure as SwaptionVolatilityStructure foreign -> CSwaptionVolatilityStructure' nocode#} {#pointer *QlRelinkableSwaptionVolatilityStructure as RelinkableSwaptionVolatilityStructure foreign -> CRelinkableSwaptionVolatilityStructure' nocode#} {#pointer *QlSabrSwaptionVolatilityCube as SabrSwaptionVolatilityCube foreign -> CSabrSwaptionVolatilityCube' nocode#} {#pointer *QlInterpolatedSwaptionVolatilityCube as InterpolatedSwaptionVolatilityCube foreign -> CInterpolatedSwaptionVolatilityCube' nocode#} {#pointer *QlSwapIndex as SwapIndex foreign -> CSwapIndex' nocode#}+{#pointer *QlBlackAtmVolCurve as BlackAtmVolCurve foreign -> CBlackAtmVolCurve' nocode#}+{#pointer *QlBlackVolSurface as BlackVolSurface foreign -> CBlackVolSurface' nocode#}+{#pointer *QlAbcdAtmVolCurve as AbcdAtmVolCurve foreign -> CAbcdAtmVolCurve' nocode#}+{#pointer *QlSabrVolSurface as SabrVolSurface foreign -> CSabrVolSurface' nocode#}+{#pointer *QlInterestRateIndex as InterestRateIndex foreign -> CInterestRateIndex' nocode#}+{#pointer *QlOptionletStripper2 as OptionletStripper2 foreign -> COptionletStripper2 nocode#}  {#enum BlackVarianceSurfaceExtrapolation{} deriving(Show, Eq)#} {#enum ExtendedBlackVarianceSurfaceExtrapolation{} deriving(Show, Eq)#}  -- |'BlackVolatilitySurfaceDelta::SmileInterpolationMethod', local to that class -- not shared--- with any other binding, so declared here rather than in 'QuantLib.Internal.Enum'.+-- with any other binding, so declared here rather than in 'QuantLib.Internal.Common'. {#enum SmileInterpolationMethod{} deriving(Show, Eq)#}  -- |'BlackVolTimeExtrapolation::Type', consumed only by 'blackVolatilitySurfaceDelta' today --@@ -264,28 +322,23 @@  -- |Constant caplet volatility, no time-strike dependence -- floating reference date, floating market data-{#fun qlConstantOptionletVol1 as constantOptionletVolatility'{fromIntegral`Word',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'+{#fun qlConstantOptionletVol1 as constantOptionletVolatility'{fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'   ,`VolatilityType' -- ^type   ,`Double' -- ^displacement   ,preErrorCheck-`String'errorCheck*-}->`OptionletVolatilityStructure'peekOptionletVolatilityStructure*#}  -- |fixed reference date, floating market data-{#fun qlConstantOptionletVolatility as constantOptionletVolatility{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'+{#fun qlConstantOptionletVolatility as constantOptionletVolatility{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'   ,`VolatilityType' -- ^type   ,`Double' -- ^displacement   ,preErrorCheck-`String'errorCheck*-}->`OptionletVolatilityStructure'peekOptionletVolatilityStructure*#} --- |'Nothing' emits 'TimeUnit''s -1 sentinel (same convention as 'fromMaybeEnum'), since 'TimeUnit'--- itself starts at 0 and can't self-sentinel -- used for 'optionletStripper1''s optionletFrequency.-fromMaybeEnumQuantity :: Maybe (Word, TimeUnit) -> (CInt, CInt)-fromMaybeEnumQuantity = maybe (0, -1) fromEnumQuantity- -- |Strips a 'CapFloorTermVolSurface' (quoted cap\/floor term vols) into caplet\/floorlet vols via -- 'OptionletStripper1', immediately wrapping the result behind 'StrippedOptionletAdapter' in one -- step -- 'OptionletStripper1' itself is never exposed as a Haskell type, since none of its own -- getters (capFloorPrices\/capletVols\/etc.) are needed beyond feeding the adapter, per the "bind -- few inspectors" rule.-{#fun qlOptionletStripper1 as optionletStripper1{withGenVolatilityTermStructure*`CapFloorTermVolSurface'+{#fun qlOptionletStripper1 as optionletStripper1{withCapFloorTermVolSurface*`CapFloorTermVolSurface'   ,withIborIndex*`GenIborIndex ibor'   ,fromMaybeDouble`Maybe Double' -- ^switchStrikes   ,`Double' -- ^accuracy@@ -297,6 +350,37 @@   ,fromMaybeEnumQuantity`Maybe (Word, TimeUnit)'& -- ^optionletFrequency   ,preErrorCheck-`String'errorCheck*-}->`OptionletVolatilityStructure'peekOptionletVolatilityStructure*#} +-- |Extends an 'OptionletStripper1' (built internally, never exposed as its own Haskell type --+-- same fusion as 'optionletStripper1') by reconciling it against an ATM 'CapFloorTermVolCurve',+-- producing forward-forward optionlet vols. Unlike 'optionletStripper1', this keeps its own+-- concrete 'OptionletStripper2' object around, since it has real diagnostic getters+-- ('optionletStripper2AtmCapFloorStrikes'\/'optionletStripper2AtmCapFloorPrices'\/+-- 'optionletStripper2SpreadsVol') not reachable through the generic+-- 'OptionletVolatilityStructure' interface. Use 'optionletStripper2AsOptionletVolatilityStructure'+-- to pass one into anything expecting the generic interface.+{#fun qlOptionletStripper2 as optionletStripper2{withCapFloorTermVolSurface*`CapFloorTermVolSurface'+  ,withIborIndex*`GenIborIndex ibor'+  ,fromMaybeDouble`Maybe Double' -- ^switchStrikes+  ,`Double' -- ^accuracy+  ,fromIntegral`Word' -- ^maxIter+  ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discount+  ,`VolatilityType' -- ^type+  ,`Double' -- ^displacement+  ,`Bool' -- ^dontThrow+  ,fromMaybeEnumQuantity`Maybe (Word, TimeUnit)'& -- ^optionletFrequency+  ,withCapFloorTermVolCurve*`CapFloorTermVolCurve' -- ^atmCapFloorTermVolCurve+  ,preErrorCheck-`String'errorCheck*-}->`OptionletStripper2'peekOptionletStripper2*#}++-- |Fresh construction (a 'StrippedOptionletAdapter' wrapping the 'OptionletStripper2' itself),+-- never a cast -- same idiom as 'sabrInterpolatedSmileSectionAsSmileSection'.+{#fun qlOptionletStripper2AsOptionletVolatilityStructure as optionletStripper2AsOptionletVolatilityStructure{withOptionletStripper2*`OptionletStripper2',preErrorCheck-`String'errorCheck*-}->`OptionletVolatilityStructure'peekOptionletVolatilityStructure*#}++{#fun qlOptionletStripper2AtmCapFloorStrikes as optionletStripper2AtmCapFloorStrikes{withOptionletStripper2*`OptionletStripper2',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++{#fun qlOptionletStripper2AtmCapFloorPrices as optionletStripper2AtmCapFloorPrices{withOptionletStripper2*`OptionletStripper2',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++{#fun qlOptionletStripper2SpreadsVol as optionletStripper2SpreadsVol{withOptionletStripper2*`OptionletStripper2',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}+ -- |An optionlet vol surface behind a relinkable handle. The result /is/ an -- 'OptionletVolatilityStructure': pass it anywhere one is expected and everything built on it -- keeps tracking whatever the handle currently points at, so a later 'linkOptionletVolTo'@@ -334,13 +418,13 @@   ,withBlackVolTermStructure*`GenBlackVolTermStructure bv',preErrorCheck-`String'errorCheck*-}->`()'#}  -- |fixed reference date, floating market data-{#fun qlConstantSwaptionVolatility1 as constantSwaptionVolatility'{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'+{#fun qlConstantSwaptionVolatility1 as constantSwaptionVolatility'{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'   ,`VolatilityType' -- ^type   ,`Double' -- ^shift   ,preErrorCheck-`String'errorCheck*-}->`SwaptionVolatilityStructure'peekSwaptionVolatilityStructure*#}  -- |floating reference date, floating market data-{#fun qlConstantSwaptionVolatility as constantSwaptionVolatility{fromIntegral`Word',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'+{#fun qlConstantSwaptionVolatility as constantSwaptionVolatility{fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter'   ,`VolatilityType' -- ^type   ,`Double' -- ^shift   ,preErrorCheck-`String'errorCheck*-}->`SwaptionVolatilityStructure'peekSwaptionVolatilityStructure*#}@@ -536,7 +620,7 @@ -- are the SABR calibration's initial guess and fixed\/free flags; endCriteria\/optimization -- method are left at QuantLib's own internal defaults (a raw, Haskell-finalized EndCriteria or -- OptimizationMethod handle can't safely be stored for this object's full lifetime -- see the--- qlXxxFitting comment in "QuantLib.Internal.Enum" for the same ownership hazard elsewhere).+-- qlXxxFitting comment in "QuantLib.Internal.Common" for the same ownership hazard elsewhere). sabrInterpolatedSmileSection :: Day -- ^optionDate   -> GenQuote q1 -- ^forward   -> [Double] -- ^strikes@@ -665,11 +749,182 @@ {#fun qlCallableBondConstantVolatility as callableBondConstantVolatility{withDay*`Day',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CallableBondVolatilityStructure'peekCallableBondVolatilityStructure*#}  -- |fixed reference date, floating market data-{#fun qlConstantCapFloorTermVolatility1 as constantCapFloorTermVolatility'{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`VolatilityTermStructure'peekVolatilityTermStructure*#}+{#fun qlConstantCapFloorTermVolatility1 as constantCapFloorTermVolatility'{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolatilityStructure'peekCapFloorTermVolatilityStructure*#}  -- |floating reference date, floating market data-{#fun qlConstantCapFloorTermVolatility as constantCapFloorTermVolatility{fromIntegral`Word',withCalendar*`Calendar',`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`VolatilityTermStructure'peekVolatilityTermStructure*#}+{#fun qlConstantCapFloorTermVolatility as constantCapFloorTermVolatility{fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withQuote*`GenQuote q',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolatilityStructure'peekCapFloorTermVolatilityStructure*#} +-- |returns the volatility for a given option tenor and strike+{#fun qlCapFloorTermVolatilityStructureVolatilityForPeriod as capFloorVolatilityForPeriod{withGenCapFloorTermVolatilityStructure*`GenCapFloorTermVolatilityStructure c'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,`Double' -- ^strike+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |returns the volatility for a given option date and strike+{#fun qlCapFloorTermVolatilityStructureVolatilityForDate as capFloorVolatilityForDate{withGenCapFloorTermVolatilityStructure*`GenCapFloorTermVolatilityStructure c'+  ,withDay*`Day' -- ^optionDate+  ,`Double' -- ^strike+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |returns the volatility for a given option time and strike+{#fun qlCapFloorTermVolatilityStructureVolatilityForTime as capFloorVolatilityForTime{withGenCapFloorTermVolatilityStructure*`GenCapFloorTermVolatilityStructure c'+  ,`Double' -- ^optionTime+  ,`Double' -- ^strike+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |The option-tenor grid's dates, calendar-advanced from the curve's reference date.+{#fun qlCapFloorTermVolCurveOptionDates as capFloorTermVolCurveOptionDates{withCapFloorTermVolCurve*`CapFloorTermVolCurve',preArray-`[Day]'&peekDayArray*}->`()'#}++-- |As 'capFloorTermVolCurveOptionDates', in year fractions from the curve's reference date.+{#fun qlCapFloorTermVolCurveOptionTimes as capFloorTermVolCurveOptionTimes{withCapFloorTermVolCurve*`CapFloorTermVolCurve',preArray-`[Double]'&peekDoubleArray*}->`()'#}++-- |The option-tenor grid's dates, calendar-advanced from the surface's reference date.+{#fun qlCapFloorTermVolSurfaceOptionDates as capFloorTermVolSurfaceOptionDates{withCapFloorTermVolSurface*`CapFloorTermVolSurface',preArray-`[Day]'&peekDayArray*}->`()'#}++-- |As 'capFloorTermVolSurfaceOptionDates', in year fractions from the surface's reference date.+{#fun qlCapFloorTermVolSurfaceOptionTimes as capFloorTermVolSurfaceOptionTimes{withCapFloorTermVolSurface*`CapFloorTermVolSurface',preArray-`[Double]'&peekDoubleArray*}->`()'#}++-- |spot at-the-money volatility for a given option tenor+{#fun qlBlackAtmVolCurveAtmVolForPeriod as atmVolForPeriod{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |spot at-the-money volatility for a given option maturity date+{#fun qlBlackAtmVolCurveAtmVolForDate as atmVolForDate{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,withDay*`Day' -- ^maturity+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |spot at-the-money volatility for a given option maturity time+{#fun qlBlackAtmVolCurveAtmVolForTime as atmVolForTime{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,`Double' -- ^maturity+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |spot at-the-money variance for a given option tenor+{#fun qlBlackAtmVolCurveAtmVarianceForPeriod as atmVarianceForPeriod{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |spot at-the-money variance for a given option maturity date+{#fun qlBlackAtmVolCurveAtmVarianceForDate as atmVarianceForDate{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,withDay*`Day' -- ^maturity+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |spot at-the-money variance for a given option maturity time+{#fun qlBlackAtmVolCurveAtmVarianceForTime as atmVarianceForTime{withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,`Double' -- ^maturity+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |returns the smile for a given option tenor+{#fun qlBlackVolSurfaceSmileSectionForPeriod as blackVolSurfaceSmileSectionForPeriod{withGenBlackVolSurface*`GenBlackVolSurface b'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`SmileSection'peekSmileSection*#}++-- |returns the smile for a given option date+{#fun qlBlackVolSurfaceSmileSectionForDate as blackVolSurfaceSmileSectionForDate{withGenBlackVolSurface*`GenBlackVolSurface b'+  ,withDay*`Day' -- ^optionDate+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`SmileSection'peekSmileSection*#}++-- |returns the smile for a given option time+{#fun qlBlackVolSurfaceSmileSectionForTime as blackVolSurfaceSmileSectionForTime{withGenBlackVolSurface*`GenBlackVolSurface b'+  ,`Double' -- ^optionTime+  ,`Bool' -- ^extrapolate+  ,preErrorCheck-`String'errorCheck*-}->`SmileSection'peekSmileSection*#}++-- |Abcd-interpolated at-the-money (no-smile) volatility curve -- floating reference date,+-- floating market data. @inclusionInInterpolationFlag@ selects which quotes feed the ABCD fit+-- (upstream defaults this to all-'True' when omitted; hasquant always requires it explicitly,+-- per the widen-in-place convention for a handful of trailing defaulted params).+abcdAtmVolCurve :: Word -> Calendar -> [(Word, TimeUnit)] -- ^optionTenors+  -> [GenQuote q] -- ^volsHandles+  -> [Bool] -- ^inclusionInInterpolationFlag+  -> BusinessDayConvention -> DayCounter -> IO AbcdAtmVolCurve+abcdAtmVolCurve d c ntenors qs flags bdc dc = qlAbcdAtmVolCurve d c n t qs flags bdc dc+  where (n, t) = unzip ntenors+{#fun qlAbcdAtmVolCurve{fromIntegral`Word',withCalendar*`Calendar',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withQuoteArray*`[GenQuote q]'&,withBoolArray*`[Bool]'&,fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`AbcdAtmVolCurve'peekAbcdAtmVolCurve*#}++{#fun qlAbcdAtmVolCurveA as abcdAtmVolCurveA{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveB as abcdAtmVolCurveB{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveC as abcdAtmVolCurveC{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveD as abcdAtmVolCurveD{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveRmsError as abcdAtmVolCurveRmsError{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveMaxError as abcdAtmVolCurveMaxError{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`Double'#}+{#fun qlAbcdAtmVolCurveEndCriteria as abcdAtmVolCurveEndCriteria{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preErrorCheck-`String'errorCheck*-}->`EndCriteriaType'#}++-- |@k@ adjustment factor at a given time+{#fun qlAbcdAtmVolCurveKAtTime as abcdAtmVolCurveKAtTime{withAbcdAtmVolCurve*`AbcdAtmVolCurve',`Double',preErrorCheck-`String'errorCheck*-}->`Double'#}++-- |@k@ adjustment factors for every option tenor used in interpolation+{#fun qlAbcdAtmVolCurveK as abcdAtmVolCurveK{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++abcdAtmVolCurveOptionTenors :: AbcdAtmVolCurve -> IO [(Word, TimeUnit)]+abcdAtmVolCurveOptionTenors o = do+  (ns, us) <- qlAbcdAtmVolCurveOptionTenors o+  pure $ zip (map fromIntegral ns) (map toEnum us)+{#fun qlAbcdAtmVolCurveOptionTenors{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preArray-`[Int]'&peekIntArray*,preArray-`[Int]'&peekIntArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |As 'abcdAtmVolCurveOptionTenors', but only the tenors actually used in the ABCD fit.+abcdAtmVolCurveOptionTenorsInInterpolation :: AbcdAtmVolCurve -> IO [(Word, TimeUnit)]+abcdAtmVolCurveOptionTenorsInInterpolation o = do+  (ns, us) <- qlAbcdAtmVolCurveOptionTenorsInInterpolation o+  pure $ zip (map fromIntegral ns) (map toEnum us)+{#fun qlAbcdAtmVolCurveOptionTenorsInInterpolation{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preArray-`[Int]'&peekIntArray*,preArray-`[Int]'&peekIntArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++{#fun qlAbcdAtmVolCurveOptionDates as abcdAtmVolCurveOptionDates{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preArray-`[Day]'&peekDayArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |As 'abcdAtmVolCurveOptionDates', in year fractions from the curve's reference date.+{#fun qlAbcdAtmVolCurveOptionTimes as abcdAtmVolCurveOptionTimes{withAbcdAtmVolCurve*`AbcdAtmVolCurve',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |SABR-smile 'BlackVolSurface' built from an interest-rate index, an ATM 'BlackAtmVolCurve', and+-- per-tenor ATM-rate spreads\/vol-spread matrix. @volSpreads@'s rows follow @optionTenors@ and+-- columns follow @atmRateSpreads@ (same row\/column convention as 'sabrSwaptionVolatilityCube's+-- @volSpreads@).+sabrVolSurface :: GenInterestRateIndex ix -> GenBlackAtmVolCurve b -> [(Word, TimeUnit)] -- ^optionTenors+  -> [Double] -- ^atmRateSpreads+  -> Matrix (GenQuote q) -- ^volSpreads+  -> IO SabrVolSurface+sabrVolSurface ix atm ntenors spreads (Matrix vr vc vd) =+  qlSabrVolSurface ix atm n t spreads vr vc vd+  where (n, t) = unzip ntenors+{#fun qlSabrVolSurface{withInterestRateIndex*`GenInterestRateIndex ix',withGenBlackAtmVolCurve*`GenBlackAtmVolCurve b'+  ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&+  ,withDoubleArray*`[Double]'&+  ,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]'+  ,preErrorCheck-`String'errorCheck*-}->`SabrVolSurface'peekSabrVolSurface*#}++-- |the 'BlackAtmVolCurve' this surface's ATM level is anchored to+{#fun qlSabrVolSurfaceAtmCurve as sabrVolSurfaceAtmCurve{withSabrVolSurface*`SabrVolSurface',preErrorCheck-`String'errorCheck*-}->`BlackAtmVolCurve'peekBlackAtmVolCurve*#}++-- |per-@atmRateSpreads@-column volatility spreads for a given option tenor+{#fun qlSabrVolSurfaceVolatilitySpreadsForPeriod as sabrVolSurfaceVolatilitySpreadsForPeriod{withSabrVolSurface*`SabrVolSurface'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |as 'sabrVolSurfaceVolatilitySpreadsForPeriod', for a given option date+{#fun qlSabrVolSurfaceVolatilitySpreadsForDate as sabrVolSurfaceVolatilitySpreadsForDate{withSabrVolSurface*`SabrVolSurface'+  ,withDay*`Day' -- ^optionDate+  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}++-- |the interest rate index this surface was built from (folded in from upstream's+-- @InterestRateVolSurface@, not given its own hierarchy level here -- see 'SabrVolSurface').+{#fun qlSabrVolSurfaceIndex as sabrVolSurfaceIndex{withSabrVolSurface*`SabrVolSurface',preErrorCheck-`String'errorCheck*-}->`InterestRateIndex'peekInterestRateIndex*#}++-- |as 'sabrVolSurfaceIndex', converts an option tenor to its option date (folded in from+-- @InterestRateVolSurface@)+{#fun qlSabrVolSurfaceOptionDateFromTenor as sabrVolSurfaceOptionDateFromTenor{withSabrVolSurface*`SabrVolSurface'+  ,fromEnumQuantity`(Word,TimeUnit)'& -- ^optionTenor+  ,preErrorCheck-`String'errorCheck*-}->`Day'toDay#}+ -- |A 'SwaptionVolatilityStructure' whose volatility at every point is @source@'s plus @spread@ -- (which may change over time, since it's a live 'GenQuote' rather than a fixed number) {#fun qlSpreadedSwaptionVolatility as spreadedSwaptionVolatility{withSwaptionVolatilityStructure*`GenSwaptionVolatilityStructure sv',withQuote*`GenQuote q',preErrorCheck-`String'errorCheck*-}->`SwaptionVolatilityStructure'peekSwaptionVolatilityStructure*#}@@ -712,14 +967,14 @@ {#fun qlImpliedVolTermStructure as impliedVolTermStructure{withBlackVolTermStructure*`GenBlackVolTermStructure bv',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`BlackVolTermStructure'peekBlackVolTermStructure*#}  -- |fixed reference date, floating market data-capFloorTermVolCurve' :: Day -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO VolatilityTermStructure+capFloorTermVolCurve' :: Day -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO CapFloorTermVolCurve capFloorTermVolCurve' d c bd ntq = qlCapFloorTermVolCurve1 d c bd n t q where (n, t, q) = unzip3 ntq-{#fun qlCapFloorTermVolCurve1{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withQuoteArray*`[GenQuote q]'&,withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`VolatilityTermStructure'peekVolatilityTermStructure*#}+{#fun qlCapFloorTermVolCurve1{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withQuoteArray*`[GenQuote q]'&,withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolCurve'peekCapFloorTermVolCurve*#}  -- |floating reference date, floating market data-capFloorTermVolCurve :: Word -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO VolatilityTermStructure+capFloorTermVolCurve :: Word -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit, GenQuote q)] -> DayCounter -> IO CapFloorTermVolCurve capFloorTermVolCurve d c bd ntq = qlCapFloorTermVolCurve d c bd n t q where (n, t, q) = unzip3 ntq-{#fun qlCapFloorTermVolCurve{fromIntegral`Word',withCalendar*`Calendar',`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withQuoteArray*`[GenQuote q]'&,withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`VolatilityTermStructure'peekVolatilityTermStructure*#}+{#fun qlCapFloorTermVolCurve{fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withQuoteArray*`[GenQuote q]'&,withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolCurve'peekCapFloorTermVolCurve*#}  -- |A Black volatility curve built from time-dependent (ATM) market vols, interpolating on total -- variance (linear by default, or the given 'Interpolation') -- no strike dependence; see@@ -821,7 +1076,7 @@   -> Matrix (GenQuote q) -- ^volatilities   -> DayCounter -> IO CapFloorTermVolSurface capFloorTermVolSurface d c bd t s (Matrix mr mc md) = qlCapFloorTermVolSurface d c bd pl pu s mr mc md where (pl, pu) = unzip t-{#fun qlCapFloorTermVolSurface{fromIntegral`Word',withCalendar*`Calendar',`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withDoubleArray*`[Double]'&,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolSurface'peekCapFloorTermVolSurface*#}+{#fun qlCapFloorTermVolSurface{fromIntegral`Word',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withDoubleArray*`[Double]'&,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolSurface'peekCapFloorTermVolSurface*#}  -- |fixed reference date, floating market data capFloorTermVolSurface' :: Day -> Calendar -> BusinessDayConvention -> [(Word, TimeUnit)] -- ^optionTenors@@ -829,7 +1084,7 @@   -> Matrix (GenQuote q) -- ^volatilities   -> DayCounter -> IO CapFloorTermVolSurface capFloorTermVolSurface' d c bd t s (Matrix mr mc md) = qlCapFloorTermVolSurface1 d c bd pl pu s mr mc md where (pl, pu) = unzip t-{#fun qlCapFloorTermVolSurface1{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withDoubleArray*`[Double]'&,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolSurface'peekCapFloorTermVolSurface*#}+{#fun qlCapFloorTermVolSurface1{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention',withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&,withDoubleArray*`[Double]'&,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]',withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`CapFloorTermVolSurface'peekCapFloorTermVolSurface*#}  -- |fixed reference date, floating market data. Pass an empty 'Matrix' (@Matrix 0 0 []@) for @shifts@ -- when no shift is needed -- upstream treats a zero-row shift matrix as all-zero.@@ -845,7 +1100,7 @@ swaptionVolatilityMatrix' d c bdc ot st (Matrix vr vc vd) dc' fe ty (Matrix sr sc sd) =   qlSwaptionVolatilityMatrix d c bdc opl opu spl spu vr vc vd dc' fe ty sr sc sd   where (opl, opu) = unzip ot; (spl, spu) = unzip st-{#fun qlSwaptionVolatilityMatrix{withDay*`Day',withCalendar*`Calendar',`BusinessDayConvention'+{#fun qlSwaptionVolatilityMatrix{withDay*`Day',withCalendar*`Calendar',fromEnumC`BusinessDayConvention'   ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&   ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&   ,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]'@@ -867,7 +1122,7 @@ swaptionVolatilityMatrix c bdc ot st (Matrix vr vc vd) dc' fe ty (Matrix sr sc sd) =   qlSwaptionVolatilityMatrix1 c bdc opl opu spl spu vr vc vd dc' fe ty sr sc sd   where (opl, opu) = unzip ot; (spl, spu) = unzip st-{#fun qlSwaptionVolatilityMatrix1{withCalendar*`Calendar',`BusinessDayConvention'+{#fun qlSwaptionVolatilityMatrix1{withCalendar*`Calendar',fromEnumC`BusinessDayConvention'   ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&   ,withIntArray*`[Word]'&,withEnumArray*`[TimeUnit]'&   ,fromIntegral`Word',fromIntegral`Word',withQuoteArrayRaw*`[GenQuote q]'
QuantLib/TermStructure/Yield.chs view
@@ -99,7 +99,7 @@   , oisRateHelperSwap   ) where import QuantLib.Internal hiding(maxDate)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.Syntax(deriveOptionsRecord) import Language.Haskell.TH(mkName) import Language.Haskell.TH.Lib(varT)@@ -108,7 +108,6 @@ import qualified QuantLib.Instrument.Bond as Bond (BondPriceType) {#import QuantLib.InterestRate#}(Compounding) {#import QuantLib.CashFlow#}(RateAveragingType(..))-{#import QuantLib.Time.Calendar#}(BusinessDayConvention(..)) import QuantLib.Time.Calendar(calendar, CalendarConstructor(..)) import QuantLib.Internal.Type {#import QuantLib.Time.Schedule#}(Frequency(..), DateGenerationRule(..))@@ -124,6 +123,7 @@ -- if you put all pointer declarations in a separate module -- ch2s will not attach finalizers to foreign ptrs in other modules -- I don't want to create extra modules just to workaround the issue with cyclic dependencies and this will not help with finalizers anyway+{#pointer *Calendar foreign -> CCalendar nocode#} {#pointer *QlIborIndex as IborIndex foreign -> CIborIndex' nocode#} {#pointer *QlOvernightIndex as OvernightIndex foreign -> COvernightIndex' nocode#} {#pointer *QlBMAIndex as BMAIndex foreign -> CBMAIndex' nocode#}@@ -221,7 +221,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter',preErrorCheck-`String'errorCheck*-}->`RateHelper'peekRateHelper*#} @@ -230,7 +230,7 @@ {#fun qlFixedRateBondHelper as fixedRateBondHelper{withQuote*`GenQuote q',fromIntegral`Word' -- ^settlementDays   ,`Double' -- ^faceAmount   ,withSchedule*`Schedule',withDoubleArray*`[Double]'& -- ^coupons-  ,withDayCounter*`DayCounter',`BusinessDayConvention' -- ^paymentConvention+  ,withDayCounter*`DayCounter',fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,`Double' -- ^redemption   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,preErrorCheck-`String'errorCheck*-}->`BondHelper'peekBondHelper*#}@@ -246,7 +246,7 @@   ,fromEnumC`CPIInterpolationType' -- ^observationInterpolation   ,withSchedule*`Schedule',withDoubleArray*`[Double]'& -- ^coupons   ,withDayCounter*`DayCounter' -- ^accrualDayCounter-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,withMaybeDay*`Maybe Day' -- ^issueDate   ,withCalendar*`Calendar' -- ^paymentCalendar   ,preErrorCheck-`String'errorCheck*-}->`BondHelper'peekBondHelper*#}@@ -264,7 +264,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,withCalendar*`Calendar' -- ^calendar   ,`Frequency' -- ^fixedFrequency-  ,`BusinessDayConvention' -- ^fixedConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixedConvention   ,withDayCounter*`DayCounter' -- ^fixedDayCount   ,withIborIndex*`GenIborIndex ibor' -- ^iborIndex   ,withMaybeQuote*`Maybe (GenQuote q2)' -- ^spread@@ -321,7 +321,7 @@   ,fromIntegral`Word' -- ^monthsToEnd   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter'   ,`PillarChoice' -- ^pillar@@ -338,7 +338,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^settlementDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withIborIndex*`GenIborIndex ibor1' -- ^baseIndex   ,withIborIndex*`GenIborIndex ibor2' -- ^otherIndex@@ -353,7 +353,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^settlementDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withOvernightIborIndex*`OvernightIborIndex' -- ^baseIndex   ,withIborIndex*`GenIborIndex ibor' -- ^otherIndex@@ -368,7 +368,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withIborIndex*`GenIborIndex ibor1' -- ^baseCurrencyIndex   ,withIborIndex*`GenIborIndex ibor2' -- ^quoteCurrencyIndex@@ -387,7 +387,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,withIborIndex*`GenIborIndex ibor1' -- ^baseCurrencyIndex   ,withIborIndex*`GenIborIndex ibor2' -- ^quoteCurrencyIndex@@ -407,7 +407,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,`Frequency' -- ^fixedFrequency   ,withDayCounter*`DayCounter' -- ^fixedDayCount@@ -425,7 +425,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^fixingDays   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^convention   ,`Bool' -- ^endOfMonth   ,`Bool' -- ^isFxBaseCurrencyCollateralCurrency   ,withYieldTermStructure*`GenYieldTermStructure y' -- ^collateralCurve@@ -479,7 +479,7 @@   ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discountingCurve   ,`Bool' -- ^telescopicValueDates   ,fromIntegral`Int' -- ^paymentLag-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,`Frequency' -- ^paymentFrequency   ,withCalendar*`Calendar' -- ^paymentCalendar   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^forwardStart@@ -496,7 +496,7 @@   ,withMaybeFloatingRateCouponPricer*`Maybe FloatingRateCouponPricer' -- ^pricer   ,`DateGenerationRule' -- ^rule   ,withCalendar*`Calendar' -- ^overnightCalendar-  ,`BusinessDayConvention' -- ^convention (q1.k.q1. overnightConvention)+  ,fromEnumC`BusinessDayConvention' -- ^convention (q1.k.q1. overnightConvention)   ,preErrorCheck-`String'errorCheck*-}->`OISRateHelper'peekOISRateHelper*#} {#fun qlOISRateHelper2 as oisRateHelper2_{withDay*`Day' -- ^startDate   ,withDay*`Day' -- ^endDate@@ -505,7 +505,7 @@   ,withMaybeYieldTermStructure*`Maybe (GenYieldTermStructure y)' -- ^discountingCurve   ,`Bool' -- ^telescopicValueDates   ,fromIntegral`Int' -- ^paymentLag-  ,`BusinessDayConvention' -- ^paymentConvention+  ,fromEnumC`BusinessDayConvention' -- ^paymentConvention   ,`Frequency' -- ^paymentFrequency   ,withCalendar*`Calendar' -- ^paymentCalendar   ,withMaybeQuote*`Maybe (GenQuote q2)' -- ^overnightSpread@@ -521,7 +521,7 @@   ,withMaybeFloatingRateCouponPricer*`Maybe FloatingRateCouponPricer' -- ^pricer   ,`DateGenerationRule' -- ^rule   ,withCalendar*`Calendar' -- ^overnightCalendar-  ,`BusinessDayConvention' -- ^convention (q1.k.q1. overnightConvention)+  ,fromEnumC`BusinessDayConvention' -- ^convention (q1.k.q1. overnightConvention)   ,preErrorCheck-`String'errorCheck*-}->`OISRateHelper'peekOISRateHelper*#}  oisRateHelperFull :: Word -> (Int, TimeUnit) -> GenQuote q -> OvernightIborIndex@@ -576,7 +576,7 @@   ,fromEnumQuantity`(Int,TimeUnit)'& -- ^tenor   ,fromIntegral`Word' -- ^settlementDAys   ,withCalendar*`Calendar',fromEnumQuantity`(Int,TimeUnit)'& -- ^bmpPeriod-  ,`BusinessDayConvention',withDayCounter*`DayCounter',withBMAIndex*`BMAIndex',withIborIndex*`GenIborIndex ibor',preErrorCheck-`String'errorCheck*-}->`RateHelper'peekRateHelper*#}+  ,fromEnumC`BusinessDayConvention',withDayCounter*`DayCounter',withBMAIndex*`BMAIndex',withIborIndex*`GenIborIndex ibor',preErrorCheck-`String'errorCheck*-}->`RateHelper'peekRateHelper*#}  -- |Rate helper for bootstrapping from multiple-resets swap quotes (a floating leg that resets -- several times per fixed-leg coupon period).@@ -590,7 +590,7 @@   ,`Double' -- ^spread   ,`Frequency' -- ^fixedFrequency   ,withDayCounter*`DayCounter' -- ^fixedDayCount-  ,`BusinessDayConvention' -- ^fixedConvention+  ,fromEnumC`BusinessDayConvention' -- ^fixedConvention   ,preErrorCheck-`String'errorCheck*-}->`RateHelper'peekRateHelper*#}  -- |Rate helper for bootstrapping over FRA rates, taking its fixing/day-count conventions from an@@ -607,7 +607,7 @@ {#fun qlFraRateHelper2 as fraRateHelper'{withQuote*`GenQuote q',fromEnumQuantity`(Int,TimeUnit)'& -- ^periodToStart   ,fromIntegral`Word' -- ^lengthInMonths   ,fromIntegral`Word' -- ^fixingDays-  ,withCalendar*`Calendar',`BusinessDayConvention',`Bool' -- ^endOfMonth+  ,withCalendar*`Calendar',fromEnumC`BusinessDayConvention',`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter'   ,`PillarChoice' -- ^pillar   ,withMaybeDay*`Maybe Day' -- ^customPillarDate@@ -639,7 +639,7 @@ -- calendar\/convention\/day-counter conventions. {#fun qlFuturesRateHelper as futuresRateHelper{withQuote*`GenQuote q1',withDay*`Day' -- ^immDate   ,fromIntegral`Word' -- ^lengthInMonths-  ,withCalendar*`Calendar',`BusinessDayConvention',`Bool' -- ^endOfMonth+  ,withCalendar*`Calendar',fromEnumC`BusinessDayConvention',`Bool' -- ^endOfMonth   ,withDayCounter*`DayCounter',withMaybeQuote*`Maybe (GenQuote q2)' -- ^convexityAdjustment   ,`FuturesType' -- ^type   ,preErrorCheck-`String'errorCheck*-}->`RateHelper'peekRateHelper*#}@@ -674,13 +674,16 @@ -- and stays linked to 'baseCurve'. {#fun qlImpliedTermStructure as impliedTermStructure{withYieldTermStructure*`GenYieldTermStructure y',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`YieldTermStructure'peekYieldTermStructure*#} --- |A yield curve with a vector of zero-yield spreads added to 'baseCurve', interpolated linearly--- between the given dates. Remains linked to changes in 'baseCurve' or the spread quotes.+-- |A yield curve with a vector of zero-yield spreads added to 'baseCurve', interpolating+-- between the given dates with the given 'Interpolation'. Remains linked to changes in+-- 'baseCurve' or the spread quotes. piecewiseZeroSpreadedTermStructure :: GenYieldTermStructure y   -> [(Day, GenQuote q)]  -- ^spreads-  -> Compounding -> Frequency -> IO YieldTermStructure-piecewiseZeroSpreadedTermStructure ts qd = qlPiecewiseZeroSpreadedTermStructure ts qs ds where (ds, qs) = unzip qd-{#fun qlPiecewiseZeroSpreadedTermStructure{withYieldTermStructure*`GenYieldTermStructure y',withQuoteArray*`[GenQuote q]'&,withDayArray*`[Day]'&,`Compounding',`Frequency',preErrorCheck-`String'errorCheck*-}->`YieldTermStructure'peekYieldTermStructure*#}+  -> Compounding -> Frequency -> Interpolation -> IO YieldTermStructure+piecewiseZeroSpreadedTermStructure ts qd c f i = uncurryNested (qlPiecewiseZeroSpreadedTermStructure ts qs ds c f) (qlInterpolation i)+  where (ds, qs) = unzip qd+{#fun qlPiecewiseZeroSpreadedTermStructure{withYieldTermStructure*`GenYieldTermStructure y',withQuoteArray*`[GenQuote q]'&,withDayArray*`[Day]'&,`Compounding',`Frequency'+  ,`Int',`Int',`Int',preErrorCheck-`String'errorCheck*-}->`YieldTermStructure'peekYieldTermStructure*#}  -- |Quanto term structure, modelling the quanto effect in option pricing. Stays linked to all -- four inputs.
QuantLib/Time/Calendar.chs view
@@ -21,7 +21,7 @@ import QuantLib.Internal import QuantLib.Internal.Type {#import QuantLib.Time.Date#}(Weekday)-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.CalendarEnum  #include "qlTypesC2HS.h"@@ -32,8 +32,6 @@  {#pointer *Calendar foreign -> CCalendar nocode#} -{#enum BusinessDayConvention{} deriving(Show, Eq)#}- -- |Constructs the calendar for the given country, with an optional market variant. {#fun qlCalendar{`Int',`Int',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#} @@ -45,11 +43,11 @@ calendar x = uncurry qlCalendar $ mapCalendar x  -- |Adjusts a non-business day to the appropriate near business day with respect to the given convention-{#fun qlCalendarAdjust as adjust{withCalendar*`Calendar',withDay*`Day',`BusinessDayConvention'}->`Day'toDay#}+{#fun qlCalendarAdjust as adjust{withCalendar*`Calendar',withDay*`Day',fromEnumC`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`Day'toDay#}  -- |Advances the given date of the given number of business days and returns the result using business day convention and the EOM flag-{#fun qlCalendarAdvance as advance{withCalendar*`Calendar',withDay*`Day',fromEnumQuantity`(Int,TimeUnit)'&,`BusinessDayConvention',`Bool' -- ^endOfMonth-  }->`Day'toDay#}+{#fun qlCalendarAdvance as advance{withCalendar*`Calendar',withDay*`Day',fromEnumQuantity`(Int,TimeUnit)'&,fromEnumC`BusinessDayConvention',`Bool' -- ^endOfMonth+  ,preErrorCheck-`String'errorCheck*-}->`Day'toDay#}  -- |Adds a date to the set of holidays for the given calendar. {#fun qlCalendarAddHoliday as addHoliday{withCalendar*`Calendar',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`()'#}
QuantLib/Time/Date.chs view
@@ -64,7 +64,7 @@ import Data.Time.LocalTime(localDay, getTimeZone, utcToLocalTime)  import QuantLib.Internal-import QuantLib.Internal.Enum+import QuantLib.Internal.Common  #include "qlTypesC2HS.h" #include "ql.h"
QuantLib/Time/Schedule.chs view
@@ -27,9 +27,8 @@  import QuantLib.Time.Date import QuantLib.Internal-{#import QuantLib.Time.Calendar#}(BusinessDayConvention) import QuantLib.Internal.Type-import QuantLib.Internal.Enum+import QuantLib.Internal.Common import QuantLib.Internal.CalendarEnum  #include "qlTypesC2HS.h"@@ -43,6 +42,7 @@  {#pointer *DayCounter foreign -> CDayCounter nocode#} {#pointer *Schedule foreign -> CSchedule nocode#}+{#pointer *Calendar foreign -> CCalendar nocode#}  -- |Constructs a day counter of the given type and (where applicable) convention. {#fun qlDayCounter{`Int',`Int',preErrorCheck-`String'errorCheck*-}->`DayCounter'peekDayCounter*#}@@ -73,8 +73,8 @@   ,withDay*`Day' -- ^terminationDate   ,fromEnumQuantity`(Word,TimeUnit)'& -- ^tenor   ,withCalendar*`Calendar' -- ^calendar-  ,`BusinessDayConvention' -- ^convention-  ,`BusinessDayConvention' -- ^terminationDateConvention+  ,fromEnumC`BusinessDayConvention' -- ^convention+  ,fromEnumC`BusinessDayConvention' -- ^terminationDateConvention   ,`DateGenerationRule' -- ^rule   ,`Bool' -- ^endOfMonth   ,withMaybeDay*`Maybe Day' -- ^firstDate@@ -82,8 +82,14 @@   ,preErrorCheck-`String'errorCheck*-}->`Schedule'peekSchedule*#}  -- |Builds a payment schedule from an explicit list of dates, without checking them for plausibility.--- TODO add other parameters, provide a more user-friendly way to build schedules-{#fun qlSchedule1 as fromDates{withDayArray*`[Day]'&,withCalendar*`Calendar',`BusinessDayConvention',preErrorCheck-`String'errorCheck*-}->`Schedule'peekSchedule*#}+{#fun qlSchedule1 as fromDates{withDayArray*`[Day]'&+  ,withCalendar*`Calendar' -- ^calendar+  ,fromEnumC`BusinessDayConvention' -- ^convention+  ,fromMaybeEnum`Maybe BusinessDayConvention' -- ^terminationDateConvention+  ,fromMaybeEnumQuantity`Maybe (Word, TimeUnit)'& -- ^tenor+  ,fromMaybeEnum`Maybe DateGenerationRule' -- ^rule+  ,fromMaybeBool`Maybe Bool' -- ^endOfMonth+  ,preErrorCheck-`String'errorCheck*-}->`Schedule'peekSchedule*#}  -- |truncated schedule -- TODO Introduce another Schedule type with restricted interface?
README.md view
@@ -1,4 +1,4 @@-Haskell bindings to [QuantLib](https://www.quantlib.org/), the free/open-source C++ library for quantitative finance — rates, bonds, options, swaps, credit, inflation, and equity derivatives, with the associated term structures, indexes, and pricing engines. 1100+ constructors and non-trivial methods are bound so far, covering roughly a tenth of QuantLib's surface.+Haskell bindings to [QuantLib](https://www.quantlib.org/), the free/open-source C++ library for quantitative finance — rates, bonds, options, swaps, credit, inflation, and equity derivatives, with the associated term structures, indexes, and pricing engines. 1300+ constructors and non-trivial methods are bound so far, covering roughly a tenth of QuantLib's surface.  hasquant gives Haskell direct access to production-grade pricing, curve-building, and risk models from QuantLib. Rather than wrapping it in a new framework, it stays a thin, close-to-1:1 layer over the C++ API, so it composes into whatever architecture you're already building instead of dictating one. @@ -6,13 +6,13 @@  Type safety is held to a noticeably higher bar than a typical C++ binding. QuantLib's class hierarchies are mirrored with phantom-typed pointers (`GenBond a`, `GenQuote a`, …) rather than one flat handle type, so passing the wrong kind of object is a compile error, not a runtime crash; upcasting is the only implicit conversion, and it's structurally guaranteed safe. Declarations on the C++ and Haskell sides are kept in step by `c2hs` rather than by hand-written FFI stubs. The C++ shim layer has zero `dynamic_cast`/`dynamic_pointer_cast` call sites — classes that need runtime-checked downcasts upstream get a dedicated leaf type instead — and enum-like C++ types are bound with explicit value mirroring rather than an unchecked numeric cast, closing off a whole class of silent-corruption bugs that plain FFI bindings are prone to. -The main departures from a thin wrapper are enums and ADTs standing in for things that are classes on the C++ side (see "On Types" below), and the ownership layer that makes the pointer types safe; individual calls still map close to 1:1 onto the underlying QuantLib call.+The main departures from a thin wrapper are enums and ADTs standing in for things that are classes on the C++ side (see "On Types" below), and the ownership layer that makes the pointer types safe; individual calls still map close to 1:1 onto the underlying QuantLib call. Coverage is curated rather than exhaustive: getters that only echo a value the caller already passed to the constructor are deliberately left unbound, so the binding surface tracks what's actually useful to call rather than every method QuantLib happens to expose.  This started as a hand-written project in 2012 (see "Project History" below) and has gone through several architecture rewrites since. The core design — the pointer-ownership model, the enum/ADT scheme, the C shim conventions — is hand-designed and predates any AI involvement. More recently I've used AI assistance to extend coverage faster: new classes, methods, day counters, indexes. Every generated binding is still reviewed against the pattern it's supposed to follow, checked against the upstream C++ signature, and covered by a test before it counts as done — see "Testing" below for what that means in practice.  Worked examples live in `test/example/QuantLib/Example`. They're direct translations of QuantLib's own examples and test suite, not idiomatic Haskell — the goal there is fidelity to a known-correct reference, not style. The test suite proper is `test/main/QuantLib/MainTest.hs`, a dispatcher over the topic modules in `test/hspec/QuantLib/Spec`. -Haddock documentation is published at https://khorser.github.io/hasquant+The package is published on Hackage at https://hackage.haskell.org/package/hasquant, with Haddock documentation for the current `master` available at https://khorser.github.io/hasquant  # Testing @@ -75,11 +75,11 @@ ## Docker  The repo contains docker compose files for a custom Linux x86_64 image. You can use it like this to run tests using GHC-8.10.6:-`docker compose run --rm -it hasquant stack --resolver lts-18.8 test`+`docker compose build`, `docker compose run --rm -it hasquant stack --resolver lts-18.8 test`  Drop `-it` when running without a TTY (CI, or a scripted check) — it fails there. -The config mounts `/root/.stack`, `/root/.ghcup`, and `/root/.cabal` as named volumes so everything installed with stack/ghcup/cabal will persist across runs.+The config mounts `~/.stack`, `~/.ghcup`, and `~/.cabal` as named volumes so everything installed with stack/ghcup/cabal will persist across runs. `/hasquant/.stack-work` and `/hasquant/dist-newstyle` are mounted as anonymous volumes to avoid polluting host filesystem.  # On Types@@ -102,10 +102,8 @@ While this is convenient, it leads to some allocation and deallocation on each call, so you might consider using `asBond` and `asInstrument` to get an object of the required type.  # TODO-- `EndCriteria`/`OptimizationMethod` are bound as raw, Haskell-GC-finalized (`delete`-based) pointers rather than `shared_ptr`-boxed like every other bound class (no `QlEndCriteria`/`QlOptimizationMethod` `typedef shared_ptr<...>` exists anywhere in `cbits/`). This is why every constructor that needs to *store* one long-term as a member (`FittedBondDiscountCurve`'s fitting methods, `sabrInterpolatedSmileSection`, `sabrSwaptionVolatilityCube`) has to hardcode QuantLib-internal defaults instead of accepting a caller-supplied one — a constructor that only *uses* them transiently within one call (`Gsr::calibrateVolatilitiesIterative`, `CalibratedModel::calibrate`) can safely pass the raw pointer through, but nothing that retains one can. The real fix — re-typedef'ing both as `shared_ptr` boxes — would also touch `qlGsrCalibrateVolatilitiesIterative`/`qlCalibratedModelCalibrate`, the two call sites that currently pass them through transiently.-- `GlobalBootstrap` is bound for two trait x interpolator combinations only — `Discount`x`LogLinear` (`piecewiseYieldCurveGlobalBootstrap'`) and `SimpleZeroYield`x`Linear` (`piecewiseYieldCurveGlobalBootstrapSimpleZeroLinear'`) — not the full matrix `IterativeBootstrap` supports. Deliberate: QuantLib-SWIG itself only ever binds one `GlobalBootstrap` combination (`GlobalLinearSimpleZeroCurve`), each combination is a separate template instantiation with its own `[temp.inst]` trap (see `CLAUDE.md`), and widening happens per concrete use case, not speculatively.-- `GlobalBootstrap`'s functor-callback constructors (`ql/termstructures/globalbootstrap.hpp`): `additionalHelpers`/`additionalDates` are bound for `SimpleZeroYield`x`Linear` only, via `piecewiseYieldCurveGlobalBootstrapSimpleZeroLinearFull'`, using upstream QuantLib-SWIG's canned `AdditionalErrors`/`AdditionalDates` functors (fixed formulas, not user callbacks — no Haskell-side marshalling needed). `additionalDates` must have exactly `length additionalHelpers - 2` entries (`AdditionalErrors`' fixed output size); a mismatch raises a clear error. `additionalPenalties`/`additionalVariables` remain unbound — real optimizer callbacks, a materially larger feature. - (Perpetual) Add more classes and methods. You will need to update `cbits/qlaux.h`, `cbits/qlTypesC2HS.h`, and then add some boilerplate to corresponding `.h`, `.cpp`, `Internal/Type.hs` and `.chs` files. This can be simplified with scripting/LLMs. Refer to `CLAUDE.md`, `.claude/skills`, and `tools` for more detailed information useful even for manual steps.+- Evaluate whether some [OpenSourceRiskEngine](https://opensourcerisk.org) functionality should be bound - Add more nonempty lists or vectors for some functions where applicable - Design a declarative embedded DSL - Review interfaces for consistency, add obviously missing features and fix contradictions to the current design
cbits/qlEnumC2HS.h view
@@ -252,6 +252,11 @@   ParYieldCurve }; +// pricingengines/swaption/basketgeneratingengine.hpp+// CalibrationBasketNaive is prefixed because plain "Naive" already belongs to Probabilities+// above -- C enumerators share one namespace per TU.+enum CalibrationBasketType {CalibrationBasketNaive, MaturityStrikeByDeltaGamma};+ // instruments/callabilityschedule.hpp enum CallabilityType {Call, Put}; @@ -526,5 +531,29 @@  // termstructures/volatility/equityfx/blackvoltimeextrapolation.hpp (BlackVolTimeExtrapolation::Type) enum BlackVolTimeExtrapolationType {FlatVolatility, UseInterpolator, LinearVariance};++// experimental/commodities/unitofmeasure.hpp (UnitOfMeasure::Type). Quantity renamed to+// QuantityUnit -- it would otherwise collide with the Quantity class itself.+enum UnitOfMeasureType {Mass, Volume, Energy, QuantityUnit};++// experimental/commodities/paymentterm.hpp (PaymentTerm::EventType)+enum PaymentTermEventType {TradeDate, PricingDate};++// experimental/commodities/unitofmeasureconversion.hpp (UnitOfMeasureConversion::Type). Tags+// prefixed Uom -- confirmed clash with the already-bound ExchangeRateType{Direct,Derived}.+enum UnitOfMeasureConversionType {UomDirect, UomDerived};++// experimental/commodities/commodity.hpp (PricingError::Level). Grepped clean of any clash --+// 'Error' the data constructor doesn't collide with QuantLib.Type's 'Error' type (separate+// namespaces), and 'Info'/'Warning'/'Fatal' are otherwise unused as constructors here.+enum PricingErrorLevel {Info, Warning, Error, Fatal};++// experimental/commodities/energycommodity.hpp (EnergyCommodity::DeliverySchedule,+// EnergyCommodity::QuantityPeriodicity). Cross-cutting the same way UnitOfMeasureType is: both+// are used by EnergyCommodity's own constructors' callers and by+// CommodityPricingHelper::createPricingPeriods, so they're homed here rather than hand-rolled in+// QuantLib.Instrument.Energy.+enum DeliverySchedule {Constant, Window, Hourly, Daily, Weekly, Monthly, Quarterly, Yearly};+enum QuantityPeriodicity {Absolute, PerHour, PerDay, PerWeek, PerMonth, PerQuarter, PerYear};  /* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
cbits/qlEnumObjects.h view
@@ -349,6 +349,15 @@   , DefaultDensity }; +// dispatch tag for which LinearTsrPricer::Settings::withX builder to call; see+// qlInstrument.cpp:qlLinearTsrPricer+enum LinearTsrPricerStrategyType {+  LinearTsrPricerRateBound = 0+  , LinearTsrPricerVegaRatio+  , LinearTsrPricerPriceThreshold+  , LinearTsrPricerBSStdDevs+};+ // must match the order of qlTermStructure.cpp:zeroInflationIndices enum ZeroInflationIndexType {   AUCPI = 0
cbits/qlInstrument.cpp view
@@ -1,9 +1,17 @@ #include <ql/instrument.hpp> #include <ql/exercise.hpp>+namespace hasquant {+#include "qlEnumObjects.h"+}+#include <ql/rebatedexercise.hpp> #include <ql/payoff.hpp> #include <ql/instruments/basketoption.hpp> #include <ql/instruments/compositeinstrument.hpp> #include <ql/instruments/stickyratchet.hpp>+#include <ql/instruments/simplechooseroption.hpp>+#include <ql/instruments/softbarrieroption.hpp>+#include <ql/instruments/twoassetcorrelationoption.hpp>+#include <ql/instruments/writerextensibleoption.hpp> #include <ql/instruments/forward.hpp> #include <ql/instruments/vanillaswingoption.hpp> #include <ql/instruments/capfloor.hpp>@@ -16,9 +24,24 @@ #include <ql/instruments/claim.hpp> #include <ql/termstructures/yieldtermstructure.hpp> #include <ql/instruments/vanillaswap.hpp>+#include <ql/instruments/nonstandardswap.hpp>+#include <ql/instruments/nonstandardswaption.hpp>+#include <ql/instruments/floatfloatswap.hpp>+#include <ql/instruments/floatfloatswaption.hpp>+#include <ql/pricingengines/swaption/basketgeneratingengine.hpp> #include <ql/instruments/bmaswap.hpp> #include <ql/instruments/overnightindexedswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencyswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencybasisswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencyfixedvsfloatingswap.hpp> #include <ql/instruments/assetswap.hpp>+#include <ql/experimental/commodities/energycommodity.hpp>+#include <ql/experimental/commodities/energyfuture.hpp>+#include <ql/experimental/commodities/energyswap.hpp>+#include <ql/experimental/commodities/energyvanillaswap.hpp>+#include <ql/experimental/commodities/energybasisswap.hpp>+#include <ql/experimental/commodities/commoditypricinghelpers.hpp>+#include <ql/experimental/commodities/commoditycashflow.hpp> #include <ql/instruments/zerocouponinflationswap.hpp> #include <ql/instruments/yearonyearinflationswap.hpp> #include <ql/instruments/cpiswap.hpp>@@ -62,6 +85,8 @@ #include <ql/cashflows/simplecashflow.hpp> #include <ql/cashflows/cpicoupon.hpp> #include <ql/cashflows/yoyinflationcoupon.hpp>+#include <ql/cashflows/capflooredinflationcoupon.hpp>+#include <ql/cashflows/inflationcouponpricer.hpp> #include <ql/cashflows/zeroinflationcashflow.hpp> #include <ql/cashflows/couponpricer.hpp> #include <ql/cashflows/dividend.hpp>@@ -70,6 +95,8 @@ #include <ql/cashflows/lineartsrpricer.hpp> #include <ql/cashflows/equitycashflow.hpp> #include <ql/indexes/equityindex.hpp>+#include <ql/instruments/inflationcapfloor.hpp>+#include <ql/instruments/cpicapfloor.hpp>  #include "qlaux.h" using namespace QuantLib;@@ -85,40 +112,68 @@ template <> class ObjClassName<QlAdditionalResult*> {public: static void output(std::ostream& os) {os << "QlAdditionalResult";}}; #endif -extern "C" {-double qlInstrumentNPV(QlInstrument *instr, char **e) {try {return (*arg(instr))->NPV();} catch (std::exception& er) {return handleException<double>(e, er);}}-void qlInstrumentSetPricingEngine(QlInstrument *instr, QlPricingEngine *eng, char **e) {try {(*arg(instr))->setPricingEngine(*arg(eng));} catch (std::exception& er) {(void)handleException<int>(e, er);}}-void qlFreeInstrument(QlInstrument *instr) {del(instr);}+// SecondaryCosts = map<string, ext::any>, used with exactly two concrete alternatives+// (CommodityUnitCost/Money -- see energycommodity.cpp's two any_cast branches), bound as a real+// 2-variant sum: scIsUnitCost[i] selects which of (scAmounts[i], scCurrencies[i]) alone (Money)+// or paired with scUoms[i] (CommodityUnitCost) fills entry i. An empty (n==0) list stands in for+// upstream's nullptr shared_ptr, matching every constructor's own optional-secondaryCosts default.+shared_ptr<SecondaryCosts> qlBuildSecondaryCosts(unsigned n, char **keys, int *isUnitCost, double *amounts,+                                                 Currency **currencies, UnitOfMeasure **uoms) {+  if (n == 0) return shared_ptr<SecondaryCosts>();+  auto sc = ext::make_shared<SecondaryCosts>();+  for (unsigned i = 0; i < n; ++i) {+    Money amount(*arg(currencies[i]), amounts[i]);+    if (isUnitCost[i])+      (*sc)[keys[i]] = CommodityUnitCost(amount, *arg(uoms[i]));+    else+      (*sc)[keys[i]] = amount;+  }+  return sc;+} -namespace {-  // ext::any is std::any in the Homebrew build and boost::any in the Docker build; both expose-  // .type() returning a std::type_info-compatible name, so we classify by typeid equality rather-  // than by a string name (which differs between the two).-  //-  // r's fields are all zero/null on entry (the caller value-initialises the whole array), so any-  // field this leaves untouched is already the correct "unset" value.-  void fillResult(struct QlAdditionalResult &r, const ext::any &v) {-    if (v.type() == typeid(double)) {-      r.type = AdditionalResultDouble;-      r.dval = ext::any_cast<double>(v);-    } else if (v.type() == typeid(std::string)) {-      r.type = AdditionalResultString;-      r.sval = DUP(ext::any_cast<std::string>(v).c_str());-    } else if (v.type() == typeid(std::vector<double>)) {-      r.type = AdditionalResultDoubleVector;-      const std::vector<double> &vec = ext::any_cast<const std::vector<double>&>(v);-      r.vlen = static_cast<unsigned>(vec.size());-      if (r.vlen) {-        double *varr = alloc(new double[r.vlen]);-        for (unsigned i = 0; i < r.vlen; ++i) varr[i] = vec[i];-        r.varr = varr;-      }-    } else {-      r.type = AdditionalResultUnknown;-      r.sval = DUP(v.type().name());+// The structure-of-parallel-arrays representation of a PricingPeriods list, shared by every+// EnergySwap-family constructor's own pricingPeriods argument and by createPricingPeriods'+// output below.+PricingPeriods qlPricingPeriodVector(unsigned n, int *startDates, int *endDates, int *paymentDates,+                                     CommodityType **types, UnitOfMeasure **uoms, double *amounts) {+  PricingPeriods pps;+  pps.reserve(n);+  for (unsigned i = 0; i < n; ++i)+    pps.push_back(ext::make_shared<PricingPeriod>(Date(startDates[i]), Date(endDates[i]), Date(paymentDates[i]),+                                                  Quantity(*arg(types[i]), *arg(uoms[i]), amounts[i])));+  return pps;+}+// ext::any is std::any in the Homebrew build and boost::any in the Docker build; both expose+// .type() returning a std::type_info-compatible name, so we classify by typeid equality rather+// than by a string name (which differs between the two).+//+// r's fields are all zero/null on entry (the caller value-initialises the whole array), so any+// field this leaves untouched is already the correct "unset" value.+void fillResult(struct QlAdditionalResult &r, const ext::any &v) {+  if (v.type() == typeid(double)) {+    r.type = AdditionalResultDouble;+    r.dval = ext::any_cast<double>(v);+  } else if (v.type() == typeid(std::string)) {+    r.type = AdditionalResultString;+    r.sval = DUP(ext::any_cast<std::string>(v).c_str());+  } else if (v.type() == typeid(std::vector<double>)) {+    r.type = AdditionalResultDoubleVector;+    const std::vector<double> &vec = ext::any_cast<const std::vector<double>&>(v);+    r.vlen = static_cast<unsigned>(vec.size());+    if (r.vlen) {+      double *varr = alloc(new double[r.vlen]);+      for (unsigned i = 0; i < r.vlen; ++i) varr[i] = vec[i];+      r.varr = varr;     }+  } else {+    r.type = AdditionalResultUnknown;+    r.sval = DUP(v.type().name());   } }+extern "C" {+double qlInstrumentNPV(QlInstrument *instr, char **e) {try {return (*arg(instr))->NPV();} catch (std::exception& er) {return handleException<double>(e, er);}}+void qlInstrumentSetPricingEngine(QlInstrument *instr, QlPricingEngine *eng, char **e) {try {(*arg(instr))->setPricingEngine(*arg(eng));} catch (std::exception& er) {(void)handleException<int>(e, er);}}+void qlFreeInstrument(QlInstrument *instr) {del(instr);}  void qlInstrumentAdditionalResults(QlInstrument *instr, unsigned *len,     struct QlAdditionalResult **out, char **e) {@@ -267,6 +322,12 @@   try {return ret(new QlSwingExercise(alloc(new SwingExercise(Date(from), Date(to), stepSizeSecs))));   } catch (std::exception& er) {return handleException<QlSwingExercise*>(e, er);}} QlExercise* qlSwingExerciseAsExercise(QlSwingExercise *o) {return ret(new QlExercise(*arg(o)));}++void qlFreeRebatedExercise(QlRebatedExercise *o) {del(o);}+QlExercise* qlRebatedExerciseAsExercise(QlRebatedExercise *o) {return ret(new QlExercise(*arg(o)));}+QlRebatedExercise* qlRebatedExercise(QlExercise* exercise, double rebate, unsigned rebateSettlementDays, Calendar* rebatePaymentCalendar, int rebatePaymentConvention, char **e) {+  try {return ret(new QlRebatedExercise(alloc(new RebatedExercise(**arg(exercise), rebate, rebateSettlementDays, *arg(rebatePaymentCalendar), (BusinessDayConvention)rebatePaymentConvention))));+  } catch (std::exception& er) {return handleException<QlRebatedExercise*>(e, er);}} QlAmericanExercise* qlAmericanExercise1(int latestDate, int payoffAtExpiry, char **e) {   try {return ret(new QlAmericanExercise(alloc(new AmericanExercise(Date(latestDate), payoffAtExpiry))));   } catch (std::exception& er) {return handleException<QlAmericanExercise*>(e, er);}}@@ -344,8 +405,12 @@  void qlFreeSwap(QlSwap *o) {del(o);} QlInstrument* qlSwapAsInstrument(QlSwap *o) {return ret(new QlInstrument(*arg(o)));}+void qlFreeFixedVsFloatingSwap(QlFixedVsFloatingSwap *o) {del(o);}+QlSwap* qlFixedVsFloatingSwapAsSwap(QlFixedVsFloatingSwap *o) {return ret(new QlSwap(*arg(o)));} void qlFreeVanillaSwap(QlVanillaSwap *o) {del(o);}-QlSwap* qlVanillaSwapAsSwap(QlVanillaSwap *o) {return ret(new QlSwap(*arg(o)));}+QlFixedVsFloatingSwap* qlVanillaSwapAsFixedVsFloatingSwap(QlVanillaSwap *o) {return ret(new QlFixedVsFloatingSwap(*arg(o)));}+void qlFreeNonstandardSwap(QlNonstandardSwap *o) {del(o);}+QlSwap* qlNonstandardSwapAsSwap(QlNonstandardSwap *o) {return ret(new QlSwap(*arg(o)));} void qlFreeBMASwap(QlBMASwap *o) {del(o);} QlSwap* qlBMASwapAsSwap(QlBMASwap *o) {return ret(new QlSwap(*arg(o)));} void qlFreeOvernightIndexedSwap(QlOvernightIndexedSwap *o) {del(o);}@@ -367,6 +432,36 @@   try {return ret(new QlVanillaSwap(alloc(new VanillaSwap((VanillaSwap::Type)type, nominal, *arg(fixedSchedule), fixedRate, *arg(fixedDayCount), *arg(floatSchedule), *arg(iborIndex), spread, *arg(floatingDayCount), qlOptBusinessDayConvention(paymentConvention), qlOptBool(useIndexedCoupons)))));   } catch (std::exception& er) {return handleException<QlVanillaSwap*>(e, er);}} +// Converts an existing FixedVsFloatingSwap (e.g. a VanillaSwap) into a NonstandardSwap+// (upstream's own conversion ctor, not a delegating convenience overload).+QlNonstandardSwap* qlNonstandardSwap1(QlFixedVsFloatingSwap* v, char **e) {+  try {return ret(new QlNonstandardSwap(alloc(new NonstandardSwap(**arg(v)))));+  } catch (std::exception& er) {return handleException<QlNonstandardSwap*>(e, er);}}+// Scalar gearing/spread ctor; fixedNominal/floatingNominal/fixedRate are still per-period vectors+// upstream (see nonstandardswap.hpp).+QlNonstandardSwap* qlNonstandardSwap(int type, unsigned fixedNominalLen, double* fixedNominal, unsigned floatingNominalLen, double* floatingNominal, Schedule* fixedSchedule, unsigned fixedRateLen, double* fixedRate, DayCounter* fixedDayCount, Schedule* floatingSchedule, QlIborIndex* iborIndex, double gearing, double spread, DayCounter* floatingDayCount, int intermediateCapitalExchange, int finalCapitalExchange, int paymentConvention, char **e) {+  try {return ret(new QlNonstandardSwap(alloc(new NonstandardSwap((Swap::Type)type, std::vector<double>(fixedNominal, fixedNominal+fixedNominalLen), std::vector<double>(floatingNominal, floatingNominal+floatingNominalLen), *arg(fixedSchedule), std::vector<double>(fixedRate, fixedRate+fixedRateLen), *arg(fixedDayCount), *arg(floatingSchedule), *arg(iborIndex), gearing, spread, *arg(floatingDayCount), intermediateCapitalExchange, finalCapitalExchange, qlOptBusinessDayConvention(paymentConvention)))));+  } catch (std::exception& er) {return handleException<QlNonstandardSwap*>(e, er);}}+// Vector gearing/spread ctor (full coverage: the example only uses the scalar form above).+QlNonstandardSwap* qlNonstandardSwap2(int type, unsigned fixedNominalLen, double* fixedNominal, unsigned floatingNominalLen, double* floatingNominal, Schedule* fixedSchedule, unsigned fixedRateLen, double* fixedRate, DayCounter* fixedDayCount, Schedule* floatingSchedule, QlIborIndex* iborIndex, unsigned gearingLen, double* gearing, unsigned spreadLen, double* spread, DayCounter* floatingDayCount, int intermediateCapitalExchange, int finalCapitalExchange, int paymentConvention, char **e) {+  try {return ret(new QlNonstandardSwap(alloc(new NonstandardSwap((Swap::Type)type, std::vector<double>(fixedNominal, fixedNominal+fixedNominalLen), std::vector<double>(floatingNominal, floatingNominal+floatingNominalLen), *arg(fixedSchedule), std::vector<double>(fixedRate, fixedRate+fixedRateLen), *arg(fixedDayCount), *arg(floatingSchedule), *arg(iborIndex), std::vector<double>(gearing, gearing+gearingLen), std::vector<double>(spread, spread+spreadLen), *arg(floatingDayCount), intermediateCapitalExchange, finalCapitalExchange, qlOptBusinessDayConvention(paymentConvention)))));+  } catch (std::exception& er) {return handleException<QlNonstandardSwap*>(e, er);}}++void qlFreeFloatFloatSwap(QlFloatFloatSwap *o) {del(o);}+QlSwap* qlFloatFloatSwapAsSwap(QlFloatFloatSwap *o) {return ret(new QlSwap(*arg(o)));}+// Scalar-nominal ctor. cappedRate1/flooredRate1/cappedRate2/flooredRate2 take Null<Real>()+// (via fromMaybeDouble's qlNullReal sentinel on the Haskell side) unchanged for "no cap/floor",+// matching upstream's own default -- no separate presence flag needed.+QlFloatFloatSwap* qlFloatFloatSwap(int type, double nominal1, double nominal2, Schedule* schedule1, QlInterestRateIndex* index1, DayCounter* dayCount1, Schedule* schedule2, QlInterestRateIndex* index2, DayCounter* dayCount2, int intermediateCapitalExchange, int finalCapitalExchange, double gearing1, double spread1, double cappedRate1, double flooredRate1, double gearing2, double spread2, double cappedRate2, double flooredRate2, int paymentConvention1, int paymentConvention2, char **e) {+  try {return ret(new QlFloatFloatSwap(alloc(new FloatFloatSwap((Swap::Type)type, nominal1, nominal2, *arg(schedule1), *arg(index1), *arg(dayCount1), *arg(schedule2), *arg(index2), *arg(dayCount2), intermediateCapitalExchange, finalCapitalExchange, gearing1, spread1, cappedRate1, flooredRate1, gearing2, spread2, cappedRate2, flooredRate2, qlOptBusinessDayConvention(paymentConvention1), qlOptBusinessDayConvention(paymentConvention2)))));+  } catch (std::exception& er) {return handleException<QlFloatFloatSwap*>(e, er);}}+// Vector-nominal ctor (full coverage; not used by the upstream example).+QlFloatFloatSwap* qlFloatFloatSwap2(int type, unsigned nominal1Len, double* nominal1, unsigned nominal2Len, double* nominal2, Schedule* schedule1, QlInterestRateIndex* index1, DayCounter* dayCount1, Schedule* schedule2, QlInterestRateIndex* index2, DayCounter* dayCount2, int intermediateCapitalExchange, int finalCapitalExchange, unsigned gearing1Len, double* gearing1, unsigned spread1Len, double* spread1, unsigned cappedRate1Len, double* cappedRate1, unsigned flooredRate1Len, double* flooredRate1, unsigned gearing2Len, double* gearing2, unsigned spread2Len, double* spread2, unsigned cappedRate2Len, double* cappedRate2, unsigned flooredRate2Len, double* flooredRate2, int paymentConvention1, int paymentConvention2, char **e) {+  try {return ret(new QlFloatFloatSwap(alloc(new FloatFloatSwap((Swap::Type)type, std::vector<double>(nominal1, nominal1+nominal1Len), std::vector<double>(nominal2, nominal2+nominal2Len), *arg(schedule1), *arg(index1), *arg(dayCount1), *arg(schedule2), *arg(index2), *arg(dayCount2), intermediateCapitalExchange, finalCapitalExchange, std::vector<double>(gearing1, gearing1+gearing1Len), std::vector<double>(spread1, spread1+spread1Len), std::vector<double>(cappedRate1, cappedRate1+cappedRate1Len), std::vector<double>(flooredRate1, flooredRate1+flooredRate1Len), std::vector<double>(gearing2, gearing2+gearing2Len), std::vector<double>(spread2, spread2+spread2Len), std::vector<double>(cappedRate2, cappedRate2+cappedRate2Len), std::vector<double>(flooredRate2, flooredRate2+flooredRate2Len), qlOptBusinessDayConvention(paymentConvention1), qlOptBusinessDayConvention(paymentConvention2)))));+  } catch (std::exception& er) {return handleException<QlFloatFloatSwap*>(e, er);}}+double qlFloatFloatSwapFairSpread1(QlFloatFloatSwap* o, char **e) {try {return (*arg(o))->fairSpread1();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlFloatFloatSwapFairSpread2(QlFloatFloatSwap* o, char **e) {try {return (*arg(o))->fairSpread2();} catch (std::exception& er) {return handleException<double>(e, er);}}+ QlSwap* qlSwap(Leg* firstLeg, Leg* secondLeg, char **e) {try {return ret(new QlSwap(alloc(new Swap(*arg(firstLeg), *arg(secondLeg)))));} catch (std::exception& er) {return handleException<QlSwap*>(e, er);} } double qlSwapEndDiscounts(QlSwap* o, unsigned j, char **e) {try {return (*arg(o))->endDiscounts(j);} catch (std::exception& er) {return handleException<double>(e, er);}} Leg* qlSwapLeg(QlSwap* o, unsigned j, char **e) {try {return ret(new Leg((*arg(o))->leg(j)));} catch (std::exception& er) {return handleException<Leg*>(e, er);}}@@ -376,14 +471,14 @@ double qlSwapNpvDateDiscount(QlSwap* o, char **e) {try {return (*arg(o))->npvDateDiscount();} catch (std::exception& er) {return handleException<double>(e, er);}} int qlSwapStartDate(QlSwap* o, char **e) {try {return qlNullableDate((*arg(o))->startDate());} catch (std::exception& er) {return handleException<int>(e, er);}} double qlSwapStartDiscounts(QlSwap* o, unsigned j, char **e) {try {return (*arg(o))->startDiscounts(j);} catch (std::exception& er) {return handleException<double>(e, er);}}-double qlVanillaSwapFairRate(QlVanillaSwap* o, char **e) {try {return (*arg(o))->fairRate();} catch (std::exception& er) {return handleException<double>(e, er);}}-double qlVanillaSwapFairSpread(QlVanillaSwap* o, char **e) {try {return (*arg(o))->fairSpread();} catch (std::exception& er) {return handleException<double>(e, er);}}-Leg* qlVanillaSwapFixedLeg(QlVanillaSwap* o, char **e) {try {return ret(new Leg((*arg(o))->fixedLeg()));} catch (std::exception& er) {return handleException<Leg*>(e, er);}}-double qlVanillaSwapFixedLegBPS(QlVanillaSwap* o, char **e) {try {return (*arg(o))->fixedLegBPS();} catch (std::exception& er) {return handleException<double>(e, er);}}-double qlVanillaSwapFixedLegNPV(QlVanillaSwap* o, char **e) {try {return (*arg(o))->fixedLegNPV();} catch (std::exception& er) {return handleException<double>(e, er);}}-Leg* qlVanillaSwapFloatingLeg(QlVanillaSwap* o, char **e) {try {return ret(new Leg((*arg(o))->floatingLeg()));} catch (std::exception& er) {return handleException<Leg*>(e, er);}}-double qlVanillaSwapFloatingLegBPS(QlVanillaSwap* o, char **e) {try {return (*arg(o))->floatingLegBPS();} catch (std::exception& er) {return handleException<double>(e, er);}}-double qlVanillaSwapFloatingLegNPV(QlVanillaSwap* o, char **e) {try {return (*arg(o))->floatingLegNPV();} catch (std::exception& er) {return handleException<double>(e, er);} }+double qlFixedVsFloatingSwapFairRate(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fairRate();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlFixedVsFloatingSwapFairSpread(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fairSpread();} catch (std::exception& er) {return handleException<double>(e, er);}}+Leg* qlFixedVsFloatingSwapFixedLeg(QlFixedVsFloatingSwap* o, char **e) {try {return ret(new Leg((*arg(o))->fixedLeg()));} catch (std::exception& er) {return handleException<Leg*>(e, er);}}+double qlFixedVsFloatingSwapFixedLegBPS(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fixedLegBPS();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlFixedVsFloatingSwapFixedLegNPV(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fixedLegNPV();} catch (std::exception& er) {return handleException<double>(e, er);}}+Leg* qlFixedVsFloatingSwapFloatingLeg(QlFixedVsFloatingSwap* o, char **e) {try {return ret(new Leg((*arg(o))->floatingLeg()));} catch (std::exception& er) {return handleException<Leg*>(e, er);}}+double qlFixedVsFloatingSwapFloatingLegBPS(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->floatingLegBPS();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlFixedVsFloatingSwapFloatingLegNPV(QlFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->floatingLegNPV();} catch (std::exception& er) {return handleException<double>(e, er);} }  void qlFreeEquityTotalReturnSwap(QlEquityTotalReturnSwap *o) {del(o);} QlSwap* qlEquityTotalReturnSwapAsSwap(QlEquityTotalReturnSwap *o) {return ret(new QlSwap(*arg(o)));}@@ -406,6 +501,59 @@ QlOvernightIndexedSwap* qlOvernightIndexedSwap1(int type, unsigned nominalsLen, double* nominals, Schedule* schedule, double fixedRate, DayCounter* fixedDC, QlOvernightIndex* overnightIndex, double spread, int paymentLag, int paymentAdjustment, Calendar* paymentCalendar, int telescopicValueDates, int averagingMethod, unsigned lookbackDays, unsigned lockoutDays, int applyObservationShift, char **e) {   try {return ret(new QlOvernightIndexedSwap(alloc(new OvernightIndexedSwap((OvernightIndexedSwap::Type)type, std::vector<double>(nominals, nominals+nominalsLen), *arg(schedule), fixedRate, *arg(fixedDC), *arg(overnightIndex), spread, paymentLag, (BusinessDayConvention)paymentAdjustment, *arg(paymentCalendar), telescopicValueDates, (RateAveraging::Type)averagingMethod, lookbackDays, lockoutDays, applyObservationShift))));   } catch (std::exception& er) {return handleException<QlOvernightIndexedSwap*>(e, er);}}+void qlFreeConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencySwap *o) {del(o);}+QlSwap* qlConstNotionalCrossCurrencySwapAsSwap(QlConstNotionalCrossCurrencySwap *o) {return ret(new QlSwap(*arg(o)));}+QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencySwap(Leg* firstLeg, Currency* firstLegCcy, Leg* secondLeg, Currency* secondLegCcy, char **e) {+  try {return ret(new QlConstNotionalCrossCurrencySwap(alloc(new ConstNotionalCrossCurrencySwap(*arg(firstLeg), *arg(firstLegCcy), *arg(secondLeg), *arg(secondLegCcy)))));+  } catch (std::exception& er) {return handleException<QlConstNotionalCrossCurrencySwap*>(e, er);}}+QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencySwap1(unsigned legsLen, Leg** legs, unsigned payerLen, int* payer, unsigned currenciesLen, Currency** currencies, char **e) {+  try {return ret(new QlConstNotionalCrossCurrencySwap(alloc(new ConstNotionalCrossCurrencySwap(qlVector(legs, legsLen), std::vector<bool>(payer, payer+payerLen), qlVector(currencies, currenciesLen)))));+  } catch (std::exception& er) {return handleException<QlConstNotionalCrossCurrencySwap*>(e, er);}}+Currency* qlConstNotionalCrossCurrencySwapLegCurrency(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e) {try {return alloc(new Currency((*arg(o))->legCurrency(j)));} catch (std::exception& er) {return handleException<Currency*>(e, er);}}+double qlConstNotionalCrossCurrencySwapInCcyLegBPS(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e) {try {return (*arg(o))->inCcyLegBPS(j);} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlConstNotionalCrossCurrencySwapInCcyLegNPV(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e) {try {return (*arg(o))->inCcyLegNPV(j);} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlConstNotionalCrossCurrencySwapNpvDateDiscounts(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e) {try {return (*arg(o))->npvDateDiscounts(j);} catch (std::exception& er) {return handleException<double>(e, er);}}++void qlFreeConstNotionalCrossCurrencyBasisSwap(QlConstNotionalCrossCurrencyBasisSwap *o) {del(o);}+QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencyBasisSwapAsConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencyBasisSwap *o) {return ret(new QlConstNotionalCrossCurrencySwap(*arg(o)));}+QlConstNotionalCrossCurrencyBasisSwap* qlConstNotionalCrossCurrencyBasisSwap(+    double payNominal, Currency* payCurrency, Schedule* paySchedule, QlIborIndex* payIndex, double paySpread, double payGearing,+    double recNominal, Currency* recCurrency, Schedule* recSchedule, QlIborIndex* recIndex, double recSpread, double recGearing,+    int payPaymentLag, int recPaymentLag,+    int payCompoundSpread, unsigned payLookbackDays, int payObservationShift, unsigned payLockoutDays, int payAveragingMethod,+    int recCompoundSpread, unsigned recLookbackDays, int recObservationShift, unsigned recLockoutDays, int recAveragingMethod,+    int telescopicValueDates, char **e) {+  try {return ret(new QlConstNotionalCrossCurrencyBasisSwap(alloc(new ConstNotionalCrossCurrencyBasisSwap(+    payNominal, *arg(payCurrency), *arg(paySchedule), *arg(payIndex), paySpread, payGearing,+    recNominal, *arg(recCurrency), *arg(recSchedule), *arg(recIndex), recSpread, recGearing,+    payPaymentLag, recPaymentLag,+    payCompoundSpread, payLookbackDays, payObservationShift, payLockoutDays, (RateAveraging::Type)payAveragingMethod,+    recCompoundSpread, recLookbackDays, recObservationShift, recLockoutDays, (RateAveraging::Type)recAveragingMethod,+    telescopicValueDates))));+  } catch (std::exception& er) {return handleException<QlConstNotionalCrossCurrencyBasisSwap*>(e, er);}}+double qlConstNotionalCrossCurrencyBasisSwapFairPaySpread(QlConstNotionalCrossCurrencyBasisSwap* o, char **e) {try {return (*arg(o))->fairPaySpread();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlConstNotionalCrossCurrencyBasisSwapFairRecSpread(QlConstNotionalCrossCurrencyBasisSwap* o, char **e) {try {return (*arg(o))->fairRecSpread();} catch (std::exception& er) {return handleException<double>(e, er);}}++void qlFreeConstNotionalCrossCurrencyFixedVsFloatingSwap(QlConstNotionalCrossCurrencyFixedVsFloatingSwap *o) {del(o);}+QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencyFixedVsFloatingSwapAsConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencyFixedVsFloatingSwap *o) {return ret(new QlConstNotionalCrossCurrencySwap(*arg(o)));}+QlConstNotionalCrossCurrencyFixedVsFloatingSwap* qlConstNotionalCrossCurrencyFixedVsFloatingSwap(+    int type, double fixedNominal, Currency* fixedCurrency, Schedule* fixedSchedule, double fixedRate,+    DayCounter* fixedDayCount, int fixedPaymentBdc, unsigned fixedPaymentLag, Calendar* fixedPaymentCalendar,+    double floatNominal, Currency* floatCurrency, Schedule* floatSchedule, QlIborIndex* floatIndex, double floatSpread,+    int floatPaymentBdc, unsigned floatPaymentLag, Calendar* floatPaymentCalendar,+    int telescopicValueDates, int floatCompoundSpread, unsigned floatLookbackDays, int floatObservationShift,+    unsigned floatLockoutDays, int floatAveragingMethod, char **e) {+  try {return ret(new QlConstNotionalCrossCurrencyFixedVsFloatingSwap(alloc(new ConstNotionalCrossCurrencyFixedVsFloatingSwap(+    (Swap::Type)type, fixedNominal, *arg(fixedCurrency), *arg(fixedSchedule), fixedRate, *arg(fixedDayCount),+    (BusinessDayConvention)fixedPaymentBdc, fixedPaymentLag, *arg(fixedPaymentCalendar),+    floatNominal, *arg(floatCurrency), *arg(floatSchedule), *arg(floatIndex), floatSpread,+    (BusinessDayConvention)floatPaymentBdc, floatPaymentLag, *arg(floatPaymentCalendar),+    telescopicValueDates, floatCompoundSpread, floatLookbackDays, floatObservationShift,+    floatLockoutDays, (RateAveraging::Type)floatAveragingMethod))));+  } catch (std::exception& er) {return handleException<QlConstNotionalCrossCurrencyFixedVsFloatingSwap*>(e, er);}}+double qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairRate(QlConstNotionalCrossCurrencyFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fairRate();} catch (std::exception& er) {return handleException<double>(e, er);}}+double qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairSpread(QlConstNotionalCrossCurrencyFixedVsFloatingSwap* o, char **e) {try {return (*arg(o))->fairSpread();} catch (std::exception& er) {return handleException<double>(e, er);}}+ Leg* qlAssetSwapBondLeg(QlAssetSwap* o, char **e) {try {return ret(new Leg((*arg(o))->bondLeg()));} catch (std::exception& er) {return handleException<Leg*>(e, er);}} double qlAssetSwapCleanPrice(QlAssetSwap* o, char **e) {try {return (*arg(o))->cleanPrice();} catch (std::exception& er) {return handleException<double>(e, er);}} double qlAssetSwapFairCleanPrice(QlAssetSwap* o, char **e) {try {return (*arg(o))->fairCleanPrice();} catch (std::exception& er) {return handleException<double>(e, er);}}@@ -504,6 +652,8 @@ QlOneAssetOption* qlBarrierOptionAsOneAssetOption(QlBarrierOption *o) {return ret(new QlOneAssetOption(*arg(o)));} void qlFreeDoubleBarrierOption(QlDoubleBarrierOption *o) {del(o);} QlOneAssetOption* qlDoubleBarrierOptionAsOneAssetOption(QlDoubleBarrierOption *o) {return ret(new QlOneAssetOption(*arg(o)));}+void qlFreeSoftBarrierOption(QlSoftBarrierOption *o) {del(o);}+QlOneAssetOption* qlSoftBarrierOptionAsOneAssetOption(QlSoftBarrierOption *o) {return ret(new QlOneAssetOption(*arg(o)));} void qlFreeMargrabeOption(QlMargrabeOption *o) {del(o);} QlMultiAssetOption* qlMargrabeOptionAsMultiAssetOption(QlMargrabeOption *o) {return ret(new QlMultiAssetOption(*arg(o)));} void qlFreeMultiAssetOption(QlMultiAssetOption *o) {del(o);}@@ -533,10 +683,63 @@ double qlSwaptionImpliedVolatility(QlSwaption* o, double price, QlYieldTermStructure* discountCurve, double guess, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, int type, double displacement, int priceType, char **e) {   try {return (*arg(o))->impliedVolatility(price, *arg(discountCurve), guess, accuracy, maxEvaluations, minVol, maxVol, (VolatilityType)type, displacement, (Swaption::PriceType)priceType);   } catch (std::exception& er) {return handleException<double>(e, er);}}-QlSwaption* qlSwaption(QlVanillaSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e) {+QlSwaption* qlSwaption(QlFixedVsFloatingSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e) {   try {return ret(new QlSwaption(alloc(new Swaption(*arg(swap), *arg(exercise), (Settlement::Type) delivery, (Settlement::Method) settlementMethod))));   } catch (std::exception& er) {return handleException<QlSwaption*>(e, er);}} +void qlFreeNonstandardSwaption(QlNonstandardSwaption *o) {del(o);}+QlOption* qlNonstandardSwaptionAsOption(QlNonstandardSwaption *o) {return ret(new QlOption(*arg(o)));}+// Converts an existing Swaption into a NonstandardSwaption (upstream's own conversion ctor).+QlNonstandardSwaption* qlNonstandardSwaption1(QlSwaption* fromSwaption, char **e) {+  try {return ret(new QlNonstandardSwaption(alloc(new NonstandardSwaption(**arg(fromSwaption)))));+  } catch (std::exception& er) {return handleException<QlNonstandardSwaption*>(e, er);}}+QlNonstandardSwaption* qlNonstandardSwaption(QlNonstandardSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e) {+  try {return ret(new QlNonstandardSwaption(alloc(new NonstandardSwaption(*arg(swap), *arg(exercise), (Settlement::Type) delivery, (Settlement::Method) settlementMethod))));+  } catch (std::exception& er) {return handleException<QlNonstandardSwaption*>(e, er);}}+// Basket is computed internally by QuantLib's calibration-basket algorithm (per CalibrationBasketType);+// *helpers is written before anything can throw so a mid-loop exception still leaves a safe, freeable array.+void qlNonstandardSwaptionCalibrationBasket(QlNonstandardSwaption* o, QlSwapIndex* swapBase, QlSwaptionVolatilityStructure* swaptionVol, int basketType, unsigned* len, QlBlackCalibrationHelper*** helpers, char **e) {+  *len = 0; *helpers = nullptr;+  unsigned n = 0;+  QlBlackCalibrationHelper **hs = 0;+  try {+    std::vector<ext::shared_ptr<BlackCalibrationHelper>> basket = (*arg(o))->calibrationBasket(*arg(swapBase), (*arg(swaptionVol)).currentLink(), (BasketGeneratingEngine::CalibrationBasketType)basketType);+    n = (unsigned)basket.size();+    // Value-initialised, like qlInstrumentAdditionalResults above: a mid-loop exception leaves+    // every not-yet-filled slot null, so the catch below can free exactly `n` slots regardless of+    // how far the loop got.+    hs = new QlBlackCalibrationHelper*[n]();+    for (unsigned i = 0; i < n; ++i) hs[i] = ret(new QlBlackCalibrationHelper(alloc(basket[i])));+    *helpers = hs;+    *len = n;+  } catch (std::exception& er) {+    if (hs) { for (unsigned i = 0; i < n; ++i) delete hs[i]; delete[] hs; }+    handleException<int>(e, er);+  }}++void qlFreeFloatFloatSwaption(QlFloatFloatSwaption *o) {del(o);}+QlOption* qlFloatFloatSwaptionAsOption(QlFloatFloatSwaption *o) {return ret(new QlOption(*arg(o)));}+QlFloatFloatSwaption* qlFloatFloatSwaption(QlFloatFloatSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e) {+  try {return ret(new QlFloatFloatSwaption(alloc(new FloatFloatSwaption(*arg(swap), *arg(exercise), (Settlement::Type) delivery, (Settlement::Method) settlementMethod))));+  } catch (std::exception& er) {return handleException<QlFloatFloatSwaption*>(e, er);}}+// Same shape as qlNonstandardSwaptionCalibrationBasket above, retargeted to FloatFloatSwaption.+void qlFloatFloatSwaptionCalibrationBasket(QlFloatFloatSwaption* o, QlSwapIndex* swapBase, QlSwaptionVolatilityStructure* swaptionVol, int basketType, unsigned* len, QlBlackCalibrationHelper*** helpers, char **e) {+  *len = 0; *helpers = nullptr;+  unsigned n = 0;+  QlBlackCalibrationHelper **hs = 0;+  try {+    std::vector<ext::shared_ptr<BlackCalibrationHelper>> basket = (*arg(o))->calibrationBasket(*arg(swapBase), (*arg(swaptionVol)).currentLink(), (BasketGeneratingEngine::CalibrationBasketType)basketType);+    n = (unsigned)basket.size();+    // Same idiom as qlNonstandardSwaptionCalibrationBasket above.+    hs = new QlBlackCalibrationHelper*[n]();+    for (unsigned i = 0; i < n; ++i) hs[i] = ret(new QlBlackCalibrationHelper(alloc(basket[i])));+    *helpers = hs;+    *len = n;+  } catch (std::exception& er) {+    if (hs) { for (unsigned i = 0; i < n; ++i) delete hs[i]; delete[] hs; }+    handleException<int>(e, er);+  }}+ void qlFreeQuantoBarrierOption(QlQuantoBarrierOption *o) {del(o);} QlOneAssetOption* qlQuantoBarrierOptionAsOneAssetOption(QlQuantoBarrierOption *o) {return ret(new QlOneAssetOption(*arg(o)));} void qlFreeQuantoForwardVanillaOption(QlQuantoForwardVanillaOption *o) {del(o);}@@ -558,6 +761,21 @@ double qlDoubleBarrierOptionImpliedVolatility(QlDoubleBarrierOption* o, double price, QlGeneralizedBlackScholesProcess* process, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e) {   try {return (*arg(o))->impliedVolatility(price, *arg(process), accuracy, maxEvaluations, minVol, maxVol);   } catch (std::exception& er) {return handleException<double>(e, er);}}+QlSoftBarrierOption* qlSoftBarrierOption(int barrierType, double barrierLo, double barrierHi, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e) {+  try {return ret(new QlSoftBarrierOption(alloc(new SoftBarrierOption((Barrier::Type)barrierType, barrierLo, barrierHi, *arg(payoff), *arg(exercise)))));+  } catch (std::exception& er) {return handleException<QlSoftBarrierOption*>(e, er);}}+double qlSoftBarrierOptionImpliedVolatility(QlSoftBarrierOption* o, double price, QlGeneralizedBlackScholesProcess* process, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e) {+  try {return (*arg(o))->impliedVolatility(price, *arg(process), accuracy, maxEvaluations, minVol, maxVol);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+QlOneAssetOption* qlSimpleChooserOption(int choosingDate, double strike, QlExercise* exercise, char **e) {+  try {return ret(new QlOneAssetOption(alloc(new SimpleChooserOption(Date(choosingDate), strike, *arg(exercise)))));+  } catch (std::exception& er) {return handleException<QlOneAssetOption*>(e, er);}}+QlMultiAssetOption* qlTwoAssetCorrelationOption(int type, double strike1, double strike2, QlExercise* exercise, char **e) {+  try {return ret(new QlMultiAssetOption(alloc(new TwoAssetCorrelationOption((Option::Type)type, strike1, strike2, *arg(exercise)))));+  } catch (std::exception& er) {return handleException<QlMultiAssetOption*>(e, er);}}+QlOneAssetOption* qlWriterExtensibleOption(QlPlainVanillaPayoff* payoff1, QlExercise* exercise1, QlPlainVanillaPayoff* payoff2, QlExercise* exercise2, char **e) {+  try {return ret(new QlOneAssetOption(alloc(new WriterExtensibleOption(*arg(payoff1), *arg(exercise1), *arg(payoff2), *arg(exercise2)))));+  } catch (std::exception& er) {return handleException<QlOneAssetOption*>(e, er);}} QlOneAssetOption* qlForwardVanillaOption(double moneyness, int resetDate, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e) {   try {return ret(new QlOneAssetOption(alloc(new ForwardVanillaOption(moneyness, Date(resetDate), *arg(payoff), *arg(exercise)))));   } catch (std::exception& er) {return handleException<QlOneAssetOption*>(e, er);}}@@ -651,7 +869,9 @@   try {return ret(new QlBond(alloc(new Bond(settlDays, *arg(calendar), faceAmount, qlNullableDate(maturityDate), qlNullableDate(issueDate), *arg(cashFlows)))));   } catch (std::exception& er) {return handleException<QlBond *>(e, er);}} -int qlBondMaturityDate(QlBond *bond) {return qlNullableDate((*arg(bond))->maturityDate());}+int qlBondMaturityDate(QlBond *bond, char **e) {+  try {return qlNullableDate((*arg(bond))->maturityDate());+  } catch (std::exception& er) {return handleException<int>(e, er);}} void qlFreeBond(QlBond *bond) {del(bond);} void qlFreeFixedRateBond(QlFixedRateBond *bond) {del(bond);} QlBond *qlFixedRateBondAsBond(QlFixedRateBond *bond) {return ret(new QlBond(*arg(bond)));}@@ -1046,15 +1266,18 @@ void qlQuantLibSetCouponPricers(Leg* leg, unsigned x1Len, QlFloatingRateCouponPricer** x1, char **e) {try {return setCouponPricers(*arg(leg), qlVector(x1, x1Len));} catch (std::exception& er) {(void)handleException<int>(e, er);}}  void qlCouponAccrualStartDates(CouponLeg* o, unsigned *len, int **days, char **e) {-  int* dates = 0;+  *len = 0; *days = 0;   try {*days = qlAllocateInts(o->size()); *len = o->size();     for (unsigned i = 0; i < o->size(); ++i)       (*days)[i] = ((*o)[i]->accrualStartDate()).serialNumber();-  } catch (std::exception& er) {qlFreeInts(dates);handleException<int*>(e, er);}}+  } catch (std::exception& er) {+    qlFreeInts(*days); *days = 0; *len = 0;+    handleException<int*>(e, er);+  }}  void qlFreeDividend(QlDividend *o) {del(o);} void qlFreeCouponLeg(CouponLeg *o) {del(o);}-Leg* qlCouponLegAsLeg(CouponLeg *o) {Leg *l = new Leg(); std::copy(o->begin(), o->end(), l->begin()); return alloc(l);}+Leg* qlCouponLegAsLeg(CouponLeg *o) {return alloc(new Leg(o->begin(), o->end()));} void qlFreeFloatingCouponPricer(QlFloatingRateCouponPricer *p) {del(p);}  QlDividend* qlFixedDividend(double amount, int date, char **e) {try {return ret(new QlDividend(alloc(new FixedDividend(amount, Date(date)))));} catch (std::exception& er) {return handleException<QlDividend*>(e, er);} }@@ -1108,13 +1331,29 @@         .withPaymentDayCounter(*arg(paymentDayCounter)).withPaymentAdjustment((BusinessDayConvention)paymentAdjustment).withPaymentCalendar(*arg(paymentCalendar))         .withObservationInterpolation((CPI::InterpolationType)observationInterpolation).withSubtractInflationNominal(subtractInflationNominal)));   } catch (std::exception& er) {return handleException<Leg*>(e, er);}}-Leg* qlYoYInflationLeg(Schedule* schedule, Calendar* cal, QlYoYInflationIndex* index, int obsLagLen, int obsLagUnit, int interpolation, unsigned notionalsLen, double* notionals, DayCounter* paymentDayCounter, int paymentAdjustment, unsigned fixingDaysLen, unsigned* fixingDays, unsigned gearingsLen, double* gearings, unsigned spreadsLen, double* spreads, char **e) {+Leg* qlYoYInflationLeg(Schedule* schedule, Calendar* cal, QlYoYInflationIndex* index, int obsLagLen, int obsLagUnit, int interpolation, unsigned notionalsLen, double* notionals, DayCounter* paymentDayCounter, int paymentAdjustment, unsigned fixingDaysLen, unsigned* fixingDays, unsigned gearingsLen, double* gearings, unsigned spreadsLen, double* spreads, unsigned capsLen, double* caps, unsigned floorsLen, double* floors, char **e) {   try {return alloc(new Leg(yoyInflationLeg(*arg(schedule), *arg(cal), *arg(index), Period(obsLagLen, (TimeUnit)obsLagUnit), (CPI::InterpolationType)interpolation)         .withNotionals(std::vector<double>(notionals, notionals+notionalsLen)).withPaymentDayCounter(*arg(paymentDayCounter))         .withPaymentAdjustment((BusinessDayConvention)paymentAdjustment).withFixingDays(std::vector<Natural>(fixingDays, fixingDays+fixingDaysLen))-        .withGearings(std::vector<double>(gearings, gearings+gearingsLen)).withSpreads(std::vector<double>(spreads, spreads+spreadsLen))));+        .withGearings(std::vector<double>(gearings, gearings+gearingsLen)).withSpreads(std::vector<double>(spreads, spreads+spreadsLen))+        .withCaps(std::vector<double>(caps, caps+capsLen)).withFloors(std::vector<double>(floors, floors+floorsLen))));   } catch (std::exception& er) {return handleException<Leg*>(e, er);}} +/* YoYInflationCouponPricer -- all 3 concrete pricers share this ctor shape (caplet vol handle,+   nominal discount curve handle); mirrors the 3 YoY cap/floor engines in qlInflationVol.cpp. */+QlYoYInflationCouponPricer *qlBlackYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlYoYInflationCouponPricer(alloc(new BlackYoYInflationCouponPricer(*arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCouponPricer*>(e, er);}}+QlYoYInflationCouponPricer *qlUnitDisplacedBlackYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlYoYInflationCouponPricer(alloc(new UnitDisplacedBlackYoYInflationCouponPricer(*arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCouponPricer*>(e, er);}}+QlYoYInflationCouponPricer *qlBachelierYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlYoYInflationCouponPricer(alloc(new BachelierYoYInflationCouponPricer(*arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCouponPricer*>(e, er);}}+void qlFreeYoYInflationCouponPricer(QlYoYInflationCouponPricer *p) {del(p);}+void qlSetYoYInflationCouponPricer(Leg* leg, QlYoYInflationCouponPricer* pricer, char **e) {+  try {return setCouponPricer(*arg(leg), *arg(pricer));} catch (std::exception& er) {(void)handleException<int>(e, er);}}+ void qlFreeZeroInflationCashFlow(QlZeroInflationCashFlow *o) {del(o);} QlZeroInflationCashFlow* qlZeroInflationCashFlow(double notional, QlZeroInflationIndex* index, int observationInterpolation, int startDate, int endDate, int obsLagLen, int obsLagUnit, int paymentDate, int growthOnly, char **e) {   try {return ret(new QlZeroInflationCashFlow(alloc(new ZeroInflationCashFlow(notional, *arg(index), (CPI::InterpolationType)observationInterpolation,@@ -1179,10 +1418,10 @@   try {     LinearTsrPricer::Settings settings;     switch (strategy) {-      case 0: haveBounds ? settings.withRateBound(lowerBound, upperBound) : settings.withRateBound(); break;-      case 1: haveBounds ? settings.withVegaRatio(param, lowerBound, upperBound) : settings.withVegaRatio(param); break;-      case 2: haveBounds ? settings.withPriceThreshold(param, lowerBound, upperBound) : settings.withPriceThreshold(param); break;-      case 3: haveBounds ? settings.withBSStdDevs(param, lowerBound, upperBound) : settings.withBSStdDevs(param); break;+      case hasquant::LinearTsrPricerRateBound: haveBounds ? settings.withRateBound(lowerBound, upperBound) : settings.withRateBound(); break;+      case hasquant::LinearTsrPricerVegaRatio: haveBounds ? settings.withVegaRatio(param, lowerBound, upperBound) : settings.withVegaRatio(param); break;+      case hasquant::LinearTsrPricerPriceThreshold: haveBounds ? settings.withPriceThreshold(param, lowerBound, upperBound) : settings.withPriceThreshold(param); break;+      case hasquant::LinearTsrPricerBSStdDevs: haveBounds ? settings.withBSStdDevs(param, lowerBound, upperBound) : settings.withBSStdDevs(param); break;       default: QL_FAIL("unknown LinearTsrPricer strategy " << strategy);     }     return ret(new QlFloatingRateCouponPricer(alloc(new LinearTsrPricer(*arg(swaptionVol), *arg(meanReversion),@@ -1204,5 +1443,380 @@ QlVarianceOption* qlVarianceOption(QlPayoff* payoff, double notional, int startDate, int maturityDate, char **e) {   try {return ret(new QlVarianceOption(alloc(new VarianceOption(*arg(payoff), notional, Date(startDate), Date(maturityDate)))));   } catch (std::exception& er) {return handleException<QlVarianceOption*>(e, er);}}++// Commodity/EnergyCommodity bind no constructor -- both are abstract-here (Commodity is never+// constructed directly upstream; EnergyCommodity::quantity() is pure virtual). They're reachable+// only as upcast targets once a Stage-6 leaf (EnergyFuture, EnergyVanillaSwap, EnergyBasisSwap)+// exists. secondaryCosts()/commodityType() are plain, never-mutated echoes of each class's own+// constructor argument -- not bound, per CLAUDE.md's trivial-getter rule.+void qlFreeCommodity(QlCommodity *o) {del(o);}+QlInstrument* qlCommodityAsInstrument(QlCommodity *o) {return ret(new QlInstrument(*arg(o)));}+void qlFreeEnergyCommodity(QlEnergyCommodity *o) {del(o);}+QlCommodity* qlEnergyCommodityAsCommodity(QlEnergyCommodity *o) {return ret(new QlCommodity(*arg(o)));}++/* Commodity -- base-level getters generalized over any leaf (Stage 6). Neither can throw: both+   are plain reads of (or, for addPricingError, a push_back onto) already-computed mutable state. */+void qlCommodityAddPricingError(QlCommodity *o, int level, char *error, char *detail) {+  (*arg(o))->addPricingError((PricingError::Level)level, arg(error), arg(detail));+}++void qlCommoditySecondaryCostAmounts(QlCommodity *o, unsigned *len, char ***keys,+    unsigned *len2, double **amounts, unsigned *len3, Currency ***currencies, char **e) {+  *len = 0; *len2 = 0; *len3 = 0; *keys = 0; *amounts = 0; *currencies = 0;+  unsigned n = 0;+  char **ks = 0;+  double *am = 0;+  Currency **cs = 0;+  try {+    const SecondaryCostAmounts &m = (*arg(o))->secondaryCostAmounts();+    n = (unsigned)m.size();+    // Value-initialised, like qlInstrumentAdditionalResults above: a mid-loop exception leaves+    // every not-yet-filled slot null, so the catch below can free exactly `n` slots regardless of+    // how far the loop got.+    ks = new char*[n]();+    am = qlAllocateDoubles(n);+    cs = new Currency*[n]();+    unsigned i = 0;+    for (SecondaryCostAmounts::const_iterator it = m.begin(); it != m.end(); ++it, ++i) {+      ks[i] = DUP(it->first.c_str());+      am[i] = it->second.value();+      cs[i] = ret(new Currency(it->second.currency()));+    }+    *keys = ks; *amounts = am; *currencies = cs;+    *len = n; *len2 = n; *len3 = n;+  } catch (std::exception& er) {+    if (ks) { for (unsigned i = 0; i < n; ++i) qlFreeString(ks[i]); delete[] ks; }+    delete[] am;+    if (cs) { for (unsigned i = 0; i < n; ++i) delete cs[i]; delete[] cs; }+    handleException<int>(e, er);+  }+}++void qlCommodityPricingErrors(QlCommodity *o, unsigned *len, int **levels,+    unsigned *len2, char ***errors, unsigned *len3, char ***details, char **e) {+  *len = 0; *len2 = 0; *len3 = 0; *levels = 0; *errors = 0; *details = 0;+  unsigned n = 0;+  int *lv = 0;+  char **errs2 = 0, **dets = 0;+  try {+    const PricingErrors &errs = (*arg(o))->pricingErrors();+    n = (unsigned)errs.size();+    lv = qlAllocateInts(n);+    // Value-initialised, like qlInstrumentAdditionalResults above: a mid-loop exception leaves+    // every not-yet-filled slot null, so the catch below can free exactly `n` slots regardless of+    // how far the loop got.+    errs2 = new char*[n]();+    dets = new char*[n]();+    for (unsigned i = 0; i < n; ++i) {+      lv[i] = errs[i].errorLevel;+      errs2[i] = DUP(errs[i].error.c_str());+      dets[i] = DUP(errs[i].detail.c_str());+    }+    *levels = lv; *errors = errs2; *details = dets;+    *len = n; *len2 = n; *len3 = n;+  } catch (std::exception& er) {+    delete[] lv;+    if (errs2) { for (unsigned i = 0; i < n; ++i) qlFreeString(errs2[i]); delete[] errs2; }+    if (dets) { for (unsigned i = 0; i < n; ++i) qlFreeString(dets[i]); delete[] dets; }+    handleException<int>(e, er);+  }+}++/* EnergyCommodity -- quantity() is pure virtual upstream; one shim, dispatched virtually, covers+   every leaf (EnergyFuture's own override is a plain echo of its constructor argument, but+   EnergySwap's is a real computed sum -- see energyswap.cpp). */+double qlEnergyCommodityQuantity(QlEnergyCommodity *o, CommodityType **outCt, UnitOfMeasure **outUom, char **e) {+  *outCt = 0; *outUom = 0;+  CommodityType *ct = 0;+  try {+    Quantity q = (*arg(o))->quantity();+    ct = ret(new CommodityType(q.commodityType()));+    UnitOfMeasure *uom = ret(new UnitOfMeasure(q.unitOfMeasure()));+    *outCt = ct; *outUom = uom;+    return q.amount();+  } catch (std::exception& er) {+    delete ct;+    return handleException<double>(e, er);+  }+}++/* EnergyFuture -- tradePrice()/index() are plain, never-mutated echoes of this constructor's own+   arguments (energyfuture.hpp's inline getters each just `return foo_;`) -- not bound, per+   CLAUDE.md's trivial-getter rule (the same call Stage 4 made for CommodityIndex's own+   constructor-echo getters). quantity() is bound once, generically, above. */+void qlFreeEnergyFuture(QlEnergyFuture *o) {del(o);}+QlEnergyCommodity* qlEnergyFutureAsEnergyCommodity(QlEnergyFuture *o) {return ret(new QlEnergyCommodity(*arg(o)));}+QlEnergyFuture* qlEnergyFuture(int buySell,+    CommodityType *qCt, UnitOfMeasure *qUom, double qAmount,+    double tpAmount, Currency *tpCcy, UnitOfMeasure *tpUom,+    QlCommodityIndex *index, CommodityType *commodityType,+    unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+    unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+    char **e) {+  try {+    return ret(new QlEnergyFuture(alloc(new EnergyFuture(+        buySell,+        Quantity(*arg(qCt), *arg(qUom), qAmount),+        CommodityUnitCost(Money(*arg(tpCcy), tpAmount), *arg(tpUom)),+        *arg(index),+        *arg(commodityType),+        qlBuildSecondaryCosts(scLen, scKeys, scIsUnitCost, scAmounts, scCurrencies, scUoms)))));+  } catch (std::exception& er) {return handleException<QlEnergyFuture*>(e, er);}}++/* EnergySwap -- binds no constructor (falls through to Instrument's null-engine QL_REQUIRE, see+   qlaux.h); calendar/payCurrency/receiveCurrency/pricingPeriods/commodityType are all plain,+   never-mutated echoes of (or, for commodityType/quantity, pure functions of) each leaf's own+   constructor arguments -- not bound. dailyPositions/paymentCashFlows are genuinely computed+   during performCalculations, so those are the two worth binding, generalized over both leaves. */+void qlFreeEnergySwap(QlEnergySwap *o) {del(o);}+QlEnergyCommodity* qlEnergySwapAsEnergyCommodity(QlEnergySwap *o) {return ret(new QlEnergyCommodity(*arg(o)));}++void qlEnergySwapDailyPositions(QlEnergySwap *o, unsigned *len, int **dates,+    unsigned *len2, double **quantityAmounts, unsigned *len3, double **payLegPrices,+    unsigned *len4, double **receiveLegPrices, unsigned *len5, double **riskDeltas,+    unsigned *len6, int **unrealized, char **e) {+  *len = 0; *len2 = 0; *len3 = 0; *len4 = 0; *len5 = 0; *len6 = 0;+  *dates = 0; *quantityAmounts = 0; *payLegPrices = 0; *receiveLegPrices = 0; *riskDeltas = 0; *unrealized = 0;+  int *ds = 0, *ur = 0;+  double *qa = 0, *plp = 0, *rlp = 0, *rd = 0;+  try {+    const EnergyDailyPositions &m = (*arg(o))->dailyPositions();+    unsigned n = (unsigned)m.size();+    ds = qlAllocateInts(n);+    qa = qlAllocateDoubles(n);+    plp = qlAllocateDoubles(n);+    rlp = qlAllocateDoubles(n);+    rd = qlAllocateDoubles(n);+    ur = qlAllocateInts(n);+    unsigned i = 0;+    for (EnergyDailyPositions::const_iterator it = m.begin(); it != m.end(); ++it, ++i) {+      ds[i] = it->first.serialNumber();+      qa[i] = it->second.quantityAmount;+      plp[i] = it->second.payLegPrice;+      rlp[i] = it->second.receiveLegPrice;+      rd[i] = it->second.riskDelta;+      ur[i] = it->second.unrealized;+    }+    *dates = ds; *quantityAmounts = qa; *payLegPrices = plp; *receiveLegPrices = rlp; *riskDeltas = rd; *unrealized = ur;+    *len = n; *len2 = n; *len3 = n; *len4 = n; *len5 = n; *len6 = n;+  } catch (std::exception& er) {+    delete[] ds; delete[] qa; delete[] plp; delete[] rlp; delete[] rd; delete[] ur;+    handleException<int>(e, er);+  }+}++void qlEnergySwapPaymentCashFlows(QlEnergySwap *o, unsigned *len, QlCommodityCashFlow ***out, char **e) {+  *len = 0; *out = 0;+  unsigned n = 0;+  QlCommodityCashFlow **cs = 0;+  try {+    const CommodityCashFlows &m = (*arg(o))->paymentCashFlows();+    n = (unsigned)m.size();+    // Value-initialised, like qlInstrumentAdditionalResults above: a mid-loop exception leaves+    // every not-yet-filled slot null, so the catch below can free exactly `n` slots regardless of+    // how far the loop got.+    cs = new QlCommodityCashFlow*[n]();+    unsigned i = 0;+    for (CommodityCashFlows::const_iterator it = m.begin(); it != m.end(); ++it, ++i)+      cs[i] = ret(new QlCommodityCashFlow(alloc(it->second)));+    *out = cs;+    *len = n;+  } catch (std::exception& er) {+    if (cs) { for (unsigned i = 0; i < n; ++i) delete cs[i]; delete[] cs; }+    handleException<int>(e, er);+  }+}++/* EnergyVanillaSwap -- payReceive()/fixedPrice()/fixedPriceUnitOfMeasure()/index() are all plain,+   never-mutated echoes of this constructor's own arguments -- not bound (payReceive_ is a trivial+   `payer ? 1 : 0` of the ctor's own bool, reproducible in Haskell with no C++ call at all). */+void qlFreeEnergyVanillaSwap(QlEnergyVanillaSwap *o) {del(o);}+QlEnergySwap* qlEnergyVanillaSwapAsEnergySwap(QlEnergyVanillaSwap *o) {return ret(new QlEnergySwap(*arg(o)));}+QlEnergyVanillaSwap* qlEnergyVanillaSwap(int payer, Calendar *calendar,+    double fixedPriceAmount, Currency *fixedPriceCurrency, UnitOfMeasure *fixedPriceUnitOfMeasure,+    QlCommodityIndex *index, Currency *payCurrency, Currency *receiveCurrency,+    unsigned ppLen, int *ppStartDates, unsigned, int *ppEndDates, unsigned, int *ppPaymentDates,+    unsigned, CommodityType **ppTypes, unsigned, UnitOfMeasure **ppUoms, unsigned, double *ppAmounts,+    CommodityType *commodityType,+    unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+    unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+    QlYieldTermStructure *payLegTS, QlYieldTermStructure *receiveLegTS, QlYieldTermStructure *discountTS,+    char **e) {+  try {+    return ret(new QlEnergyVanillaSwap(alloc(new EnergyVanillaSwap(+        payer,+        *arg(calendar),+        Money(*arg(fixedPriceCurrency), fixedPriceAmount),+        *arg(fixedPriceUnitOfMeasure),+        *arg(index),+        *arg(payCurrency),+        *arg(receiveCurrency),+        qlPricingPeriodVector(ppLen, ppStartDates, ppEndDates, ppPaymentDates, ppTypes, ppUoms, ppAmounts),+        *arg(commodityType),+        qlBuildSecondaryCosts(scLen, scKeys, scIsUnitCost, scAmounts, scCurrencies, scUoms),+        *arg(payLegTS), *arg(receiveLegTS), *arg(discountTS)))));+  } catch (std::exception& er) {return handleException<QlEnergyVanillaSwap*>(e, er);}}++/* EnergyBasisSwap -- payIndex()/receiveIndex()/basis() are likewise plain constructor-argument+   echoes -- not bound. */+void qlFreeEnergyBasisSwap(QlEnergyBasisSwap *o) {del(o);}+QlEnergySwap* qlEnergyBasisSwapAsEnergySwap(QlEnergyBasisSwap *o) {return ret(new QlEnergySwap(*arg(o)));}+QlEnergyBasisSwap* qlEnergyBasisSwap(Calendar *calendar,+    QlCommodityIndex *spreadIndex, QlCommodityIndex *payIndex, QlCommodityIndex *receiveIndex,+    int spreadToPayLeg, Currency *payCurrency, Currency *receiveCurrency,+    unsigned ppLen, int *ppStartDates, unsigned, int *ppEndDates, unsigned, int *ppPaymentDates,+    unsigned, CommodityType **ppTypes, unsigned, UnitOfMeasure **ppUoms, unsigned, double *ppAmounts,+    double basisAmount, Currency *basisCurrency, UnitOfMeasure *basisUnitOfMeasure,+    CommodityType *commodityType,+    unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+    unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+    QlYieldTermStructure *payLegTS, QlYieldTermStructure *receiveLegTS, QlYieldTermStructure *discountTS,+    char **e) {+  try {+    return ret(new QlEnergyBasisSwap(alloc(new EnergyBasisSwap(+        *arg(calendar),+        *arg(spreadIndex), *arg(payIndex), *arg(receiveIndex),+        spreadToPayLeg,+        *arg(payCurrency), *arg(receiveCurrency),+        qlPricingPeriodVector(ppLen, ppStartDates, ppEndDates, ppPaymentDates, ppTypes, ppUoms, ppAmounts),+        CommodityUnitCost(Money(*arg(basisCurrency), basisAmount), *arg(basisUnitOfMeasure)),+        *arg(commodityType),+        qlBuildSecondaryCosts(scLen, scKeys, scIsUnitCost, scAmounts, scCurrencies, scUoms),+        *arg(payLegTS), *arg(receiveLegTS), *arg(discountTS)))));+  } catch (std::exception& er) {return handleException<QlEnergyBasisSwap*>(e, er);}}++/* CommodityCashFlow -- a standalone CashFlow leaf, never Haskell-constructed (only ever produced+   by EnergySwap::paymentCashFlows() above). The upstream field reads themselves can't throw, but+   each shim also does `ret(new Currency(...))`, which is a bad_alloc-only throw point -- char **e+   guards that, not the upstream call. */+void qlFreeCommodityCashFlow(QlCommodityCashFlow *o) {del(o);}+int qlCommodityCashFlowDate(QlCommodityCashFlow *o) {return (*arg(o))->date().serialNumber();}+double qlCommodityCashFlowDiscountedAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e) {+  *outCcy = 0;+  try {+    const Money &m = (*arg(o))->discountedAmount();+    *outCcy = ret(new Currency(m.currency()));+    return m.value();+  } catch (std::exception& er) {return handleException<double>(e, er);}+}+double qlCommodityCashFlowUndiscountedAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e) {+  *outCcy = 0;+  try {+    const Money &m = (*arg(o))->undiscountedAmount();+    *outCcy = ret(new Currency(m.currency()));+    return m.value();+  } catch (std::exception& er) {return handleException<double>(e, er);}+}+double qlCommodityCashFlowDiscountedPaymentAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e) {+  *outCcy = 0;+  try {+    const Money &m = (*arg(o))->discountedPaymentAmount();+    *outCcy = ret(new Currency(m.currency()));+    return m.value();+  } catch (std::exception& er) {return handleException<double>(e, er);}+}+double qlCommodityCashFlowUndiscountedPaymentAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e) {+  *outCcy = 0;+  try {+    const Money &m = (*arg(o))->undiscountedPaymentAmount();+    *outCcy = ret(new Currency(m.currency()));+    return m.value();+  } catch (std::exception& er) {return handleException<double>(e, er);}+}+double qlCommodityCashFlowDiscountFactor(QlCommodityCashFlow *o) {return (*arg(o))->discountFactor();}+double qlCommodityCashFlowPaymentDiscountFactor(QlCommodityCashFlow *o) {return (*arg(o))->paymentDiscountFactor();}+int qlCommodityCashFlowFinalized(QlCommodityCashFlow *o) {return (*arg(o))->finalized();}++/* CommodityPricingHelper::createPricingPeriods -- the one static method worth binding (the other+   three -- calculateFxConversionFactor/calculateUomConversionFactor/calculateUnitCost -- duplicate+   logic already reachable via lookupUomConversion/lookupExchangeRate (Stage 2) and are skipped per+   minimalism, per the plan). */+void qlCreatePricingPeriods(int startDate, int endDate, CommodityType *qCt, UnitOfMeasure *qUom, double qAmount,+    int deliverySchedule, int qtyPeriodicity, PaymentTerm *paymentTerm,+    unsigned *len, int **ppStartDates, unsigned *len2, int **ppEndDates, unsigned *len3, int **ppPaymentDates,+    unsigned *len4, CommodityType ***ppTypes, unsigned *len5, UnitOfMeasure ***ppUoms, unsigned *len6, double **ppAmounts,+    char **e) {+  *len = 0; *len2 = 0; *len3 = 0; *len4 = 0; *len5 = 0; *len6 = 0;+  *ppStartDates = 0; *ppEndDates = 0; *ppPaymentDates = 0; *ppTypes = 0; *ppUoms = 0; *ppAmounts = 0;+  unsigned n = 0;+  int *starts = 0, *ends = 0, *pays = 0;+  CommodityType **types = 0;+  UnitOfMeasure **uoms = 0;+  double *amounts = 0;+  try {+    PricingPeriods pps;+    CommodityPricingHelper::createPricingPeriods(Date(startDate), Date(endDate),+        Quantity(*arg(qCt), *arg(qUom), qAmount),+        (EnergyCommodity::DeliverySchedule)deliverySchedule,+        (EnergyCommodity::QuantityPeriodicity)qtyPeriodicity,+        *arg(paymentTerm), pps);+    n = (unsigned)pps.size();+    starts = qlAllocateInts(n); ends = qlAllocateInts(n); pays = qlAllocateInts(n);+    amounts = qlAllocateDoubles(n);+    // Value-initialised, like qlInstrumentAdditionalResults above: a mid-loop exception leaves+    // every not-yet-filled slot null, so the catch below can free exactly `n` slots regardless of+    // how far the loop got.+    types = new CommodityType*[n]();+    uoms = new UnitOfMeasure*[n]();+    for (unsigned i = 0; i < n; ++i) {+      starts[i] = pps[i]->startDate().serialNumber();+      ends[i] = pps[i]->endDate().serialNumber();+      pays[i] = pps[i]->paymentDate().serialNumber();+      types[i] = ret(new CommodityType(pps[i]->quantity().commodityType()));+      uoms[i] = ret(new UnitOfMeasure(pps[i]->quantity().unitOfMeasure()));+      amounts[i] = pps[i]->quantity().amount();+    }+    *ppStartDates = starts; *ppEndDates = ends; *ppPaymentDates = pays;+    *ppTypes = types; *ppUoms = uoms; *ppAmounts = amounts;+    *len = n; *len2 = n; *len3 = n; *len4 = n; *len5 = n; *len6 = n;+  } catch (std::exception& er) {+    delete[] starts; delete[] ends; delete[] pays; delete[] amounts;+    if (types) { for (unsigned i = 0; i < n; ++i) delete types[i]; delete[] types; }+    if (uoms) { for (unsigned i = 0; i < n; ++i) delete uoms[i]; delete[] uoms; }+    handleException<int>(e, er);+  }+}++void qlFreeYoYInflationCapFloor(QlYoYInflationCapFloor *o) {del(o);}+QlInstrument *qlYoYInflationCapFloorAsInstrument(QlYoYInflationCapFloor *o) {return ret(new QlInstrument(*arg(o)));}++QlYoYInflationCapFloor *qlYoYInflationCap(Leg *yoyLeg, unsigned exerciseRatesLen, double *exerciseRates, char **e) {+  try {return ret(new QlYoYInflationCapFloor(alloc(new YoYInflationCapFloor(YoYInflationCapFloor::Cap, *arg(yoyLeg),+      std::vector<double>(exerciseRates, exerciseRates+exerciseRatesLen), std::vector<double>()))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCapFloor*>(e, er);}}++QlYoYInflationCapFloor *qlYoYInflationFloor(Leg *yoyLeg, unsigned exerciseRatesLen, double *exerciseRates, char **e) {+  try {return ret(new QlYoYInflationCapFloor(alloc(new YoYInflationCapFloor(YoYInflationCapFloor::Floor, *arg(yoyLeg),+      std::vector<double>(), std::vector<double>(exerciseRates, exerciseRates+exerciseRatesLen)))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCapFloor*>(e, er);}}++QlYoYInflationCapFloor *qlYoYInflationCollar(Leg *yoyLeg, unsigned capRatesLen, double *capRates,+    unsigned floorRatesLen, double *floorRates, char **e) {+  try {return ret(new QlYoYInflationCapFloor(alloc(new YoYInflationCapFloor(YoYInflationCapFloor::Collar, *arg(yoyLeg),+      std::vector<double>(capRates, capRates+capRatesLen), std::vector<double>(floorRates, floorRates+floorRatesLen)))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCapFloor*>(e, er);}}++// atmRate takes a plain YieldTermStructure& (not a Handle), same reasoning as qlCapFloorAtmRate.+double qlYoYInflationCapFloorAtmRate(QlYoYInflationCapFloor *o, QlYieldTermStructure *discountCurve, char **e) {+  try {return (*arg(o))->atmRate(handleRef(arg(discountCurve)));+  } catch (std::exception& er) {return handleException<double>(e, er);}}++QlYoYInflationCapFloor *qlYoYInflationCapFloorOptionlet(QlYoYInflationCapFloor *o, unsigned n, char **e) {+  try {return ret(new QlYoYInflationCapFloor(alloc((*arg(o))->optionlet(n))));+  } catch (std::exception& er) {return handleException<QlYoYInflationCapFloor*>(e, er);}}++void qlFreeCPICapFloor(QlCPICapFloor *o) {del(o);}+QlInstrument *qlCPICapFloorAsInstrument(QlCPICapFloor *o) {return ret(new QlInstrument(*arg(o)));}++QlCPICapFloor *qlCPICapFloor(int type, double nominal, int startDate, double baseCPI, int maturity,+    Calendar *fixCalendar, int fixConvention, Calendar *payCalendar, int payConvention, double strike,+    QlZeroInflationIndex *index, int observationLagLen, int observationLagUnit, int observationInterpolation,+    char **e) {+  try {return ret(new QlCPICapFloor(alloc(new CPICapFloor((Option::Type)type, nominal, Date(startDate), baseCPI,+      Date(maturity), *arg(fixCalendar), (BusinessDayConvention)fixConvention, *arg(payCalendar),+      (BusinessDayConvention)payConvention, strike, *arg(index),+      Period(observationLagLen, (TimeUnit)observationLagUnit), (CPI::InterpolationType)observationInterpolation))));+  } catch (std::exception& er) {return handleException<QlCPICapFloor*>(e, er);}}+ } /* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
cbits/qlInstrument.h view
@@ -90,6 +90,10 @@   QlSwingExercise* qlSwingExercise1(int from, int to, unsigned stepSizeSecs, char **e);   QlExercise* qlSwingExerciseAsExercise(QlSwingExercise *o); +  void qlFreeRebatedExercise(QlRebatedExercise *o);+  QlExercise* qlRebatedExerciseAsExercise(QlRebatedExercise *o);+  QlRebatedExercise* qlRebatedExercise(QlExercise* exercise, double rebate, unsigned rebateSettlementDays, Calendar* rebatePaymentCalendar, int rebatePaymentConvention, char **e);+   void qlFreeCapFloor(QlCapFloor *o);   QlInstrument* qlCapFloorAsInstrument(QlCapFloor *o);   QlCapFloor* qlCap(Leg* floatingLeg, unsigned exerciseRatesLen, double* exerciseRates, char **e);@@ -129,8 +133,14 @@    void qlFreeSwap(QlSwap *o);   QlInstrument* qlSwapAsInstrument(QlSwap *o);+  void qlFreeFixedVsFloatingSwap(QlFixedVsFloatingSwap *o);+  QlSwap* qlFixedVsFloatingSwapAsSwap(QlFixedVsFloatingSwap *o);   void qlFreeVanillaSwap(QlVanillaSwap *o);-  QlSwap* qlVanillaSwapAsSwap(QlVanillaSwap *o);+  QlFixedVsFloatingSwap* qlVanillaSwapAsFixedVsFloatingSwap(QlVanillaSwap *o);+  void qlFreeNonstandardSwap(QlNonstandardSwap *o);+  QlSwap* qlNonstandardSwapAsSwap(QlNonstandardSwap *o);+  void qlFreeFloatFloatSwap(QlFloatFloatSwap *o);+  QlSwap* qlFloatFloatSwapAsSwap(QlFloatFloatSwap *o);   void qlFreeBMASwap(QlBMASwap *o);   QlSwap* qlBMASwapAsSwap(QlBMASwap *o);   void qlFreeOvernightIndexedSwap(QlOvernightIndexedSwap *o);@@ -163,10 +173,50 @@   QlAssetSwap* qlAssetSwap(int payBondCoupon, QlBond* bond, double bondCleanPrice, QlIborIndex* iborIndex, double spread, Schedule* floatSchedule, DayCounter* floatingDayCount, int parAssetSwap, double gearing, double nonParRepayment, int dealMaturity, char **e);   QlBMASwap* qlBMASwap(int type, double nominal, Schedule* liborSchedule, double liborFraction, double liborSpread, QlIborIndex* liborIndex, DayCounter* liborDayCount, Schedule* bmaSchedule, QlBMAIndex* bmaIndex, DayCounter* bmaDayCount, char **e);   QlVanillaSwap* qlVanillaSwap(int type, double nominal, Schedule* fixedSchedule, double fixedRate, DayCounter* fixedDayCount, Schedule* floatSchedule, QlIborIndex* iborIndex, double spread, DayCounter* floatingDayCount, int paymentConvention, int useIndexedCoupons, char **e);+  QlNonstandardSwap* qlNonstandardSwap1(QlFixedVsFloatingSwap* v, char **e);+  QlNonstandardSwap* qlNonstandardSwap(int type, unsigned fixedNominalLen, double* fixedNominal, unsigned floatingNominalLen, double* floatingNominal, Schedule* fixedSchedule, unsigned fixedRateLen, double* fixedRate, DayCounter* fixedDayCount, Schedule* floatingSchedule, QlIborIndex* iborIndex, double gearing, double spread, DayCounter* floatingDayCount, int intermediateCapitalExchange, int finalCapitalExchange, int paymentConvention, char **e);+  QlNonstandardSwap* qlNonstandardSwap2(int type, unsigned fixedNominalLen, double* fixedNominal, unsigned floatingNominalLen, double* floatingNominal, Schedule* fixedSchedule, unsigned fixedRateLen, double* fixedRate, DayCounter* fixedDayCount, Schedule* floatingSchedule, QlIborIndex* iborIndex, unsigned gearingLen, double* gearing, unsigned spreadLen, double* spread, DayCounter* floatingDayCount, int intermediateCapitalExchange, int finalCapitalExchange, int paymentConvention, char **e);+  QlFloatFloatSwap* qlFloatFloatSwap(int type, double nominal1, double nominal2, Schedule* schedule1, QlInterestRateIndex* index1, DayCounter* dayCount1, Schedule* schedule2, QlInterestRateIndex* index2, DayCounter* dayCount2, int intermediateCapitalExchange, int finalCapitalExchange, double gearing1, double spread1, double cappedRate1, double flooredRate1, double gearing2, double spread2, double cappedRate2, double flooredRate2, int paymentConvention1, int paymentConvention2, char **e);+  QlFloatFloatSwap* qlFloatFloatSwap2(int type, unsigned nominal1Len, double* nominal1, unsigned nominal2Len, double* nominal2, Schedule* schedule1, QlInterestRateIndex* index1, DayCounter* dayCount1, Schedule* schedule2, QlInterestRateIndex* index2, DayCounter* dayCount2, int intermediateCapitalExchange, int finalCapitalExchange, unsigned gearing1Len, double* gearing1, unsigned spread1Len, double* spread1, unsigned cappedRate1Len, double* cappedRate1, unsigned flooredRate1Len, double* flooredRate1, unsigned gearing2Len, double* gearing2, unsigned spread2Len, double* spread2, unsigned cappedRate2Len, double* cappedRate2, unsigned flooredRate2Len, double* flooredRate2, int paymentConvention1, int paymentConvention2, char **e);+  double qlFloatFloatSwapFairSpread1(QlFloatFloatSwap* o, char **e);+  double qlFloatFloatSwapFairSpread2(QlFloatFloatSwap* o, char **e);   QlSwap* qlSwap(Leg* firstLeg, Leg* secondLeg, char **e);   Leg* qlSwapLeg(QlSwap* o, unsigned j, char **e);-  Leg* qlVanillaSwapFixedLeg(QlVanillaSwap* o, char **e);-  Leg* qlVanillaSwapFloatingLeg(QlVanillaSwap* o, char **e);+  Leg* qlFixedVsFloatingSwapFixedLeg(QlFixedVsFloatingSwap* o, char **e);+  Leg* qlFixedVsFloatingSwapFloatingLeg(QlFixedVsFloatingSwap* o, char **e);+  void qlFreeConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencySwap *o);+  QlSwap* qlConstNotionalCrossCurrencySwapAsSwap(QlConstNotionalCrossCurrencySwap *o);+  QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencySwap(Leg* firstLeg, Currency* firstLegCcy, Leg* secondLeg, Currency* secondLegCcy, char **e);+  QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencySwap1(unsigned legsLen, Leg** legs, unsigned payerLen, int* payer, unsigned currenciesLen, Currency** currencies, char **e);+  Currency* qlConstNotionalCrossCurrencySwapLegCurrency(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e);+  double qlConstNotionalCrossCurrencySwapInCcyLegBPS(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e);+  double qlConstNotionalCrossCurrencySwapInCcyLegNPV(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e);+  double qlConstNotionalCrossCurrencySwapNpvDateDiscounts(QlConstNotionalCrossCurrencySwap* o, unsigned j, char **e);++  void qlFreeConstNotionalCrossCurrencyBasisSwap(QlConstNotionalCrossCurrencyBasisSwap *o);+  QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencyBasisSwapAsConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencyBasisSwap *o);+  QlConstNotionalCrossCurrencyBasisSwap* qlConstNotionalCrossCurrencyBasisSwap(+    double payNominal, Currency* payCurrency, Schedule* paySchedule, QlIborIndex* payIndex, double paySpread, double payGearing,+    double recNominal, Currency* recCurrency, Schedule* recSchedule, QlIborIndex* recIndex, double recSpread, double recGearing,+    int payPaymentLag, int recPaymentLag,+    int payCompoundSpread, unsigned payLookbackDays, int payObservationShift, unsigned payLockoutDays, int payAveragingMethod,+    int recCompoundSpread, unsigned recLookbackDays, int recObservationShift, unsigned recLockoutDays, int recAveragingMethod,+    int telescopicValueDates, char **e);+  double qlConstNotionalCrossCurrencyBasisSwapFairPaySpread(QlConstNotionalCrossCurrencyBasisSwap* o, char **e);+  double qlConstNotionalCrossCurrencyBasisSwapFairRecSpread(QlConstNotionalCrossCurrencyBasisSwap* o, char **e);++  void qlFreeConstNotionalCrossCurrencyFixedVsFloatingSwap(QlConstNotionalCrossCurrencyFixedVsFloatingSwap *o);+  QlConstNotionalCrossCurrencySwap* qlConstNotionalCrossCurrencyFixedVsFloatingSwapAsConstNotionalCrossCurrencySwap(QlConstNotionalCrossCurrencyFixedVsFloatingSwap *o);+  QlConstNotionalCrossCurrencyFixedVsFloatingSwap* qlConstNotionalCrossCurrencyFixedVsFloatingSwap(+    int type, double fixedNominal, Currency* fixedCurrency, Schedule* fixedSchedule, double fixedRate,+    DayCounter* fixedDayCount, int fixedPaymentBdc, unsigned fixedPaymentLag, Calendar* fixedPaymentCalendar,+    double floatNominal, Currency* floatCurrency, Schedule* floatSchedule, QlIborIndex* floatIndex, double floatSpread,+    int floatPaymentBdc, unsigned floatPaymentLag, Calendar* floatPaymentCalendar,+    int telescopicValueDates, int floatCompoundSpread, unsigned floatLookbackDays, int floatObservationShift,+    unsigned floatLockoutDays, int floatAveragingMethod, char **e);+  double qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairRate(QlConstNotionalCrossCurrencyFixedVsFloatingSwap* o, char **e);+  double qlConstNotionalCrossCurrencyFixedVsFloatingSwapFairSpread(QlConstNotionalCrossCurrencyFixedVsFloatingSwap* o, char **e);+   Leg* qlAssetSwapBondLeg(QlAssetSwap* o, char **e);   Leg* qlAssetSwapFloatingLeg(QlAssetSwap* o, char **e);   Leg* qlBMASwapBmaLeg(QlBMASwap* o, char **e);@@ -202,12 +252,12 @@   double qlSwapNpvDateDiscount(QlSwap* o, char **e);   int qlSwapStartDate(QlSwap* o, char **e);   double qlSwapStartDiscounts(QlSwap* o, unsigned j, char **e);-  double qlVanillaSwapFairRate(QlVanillaSwap* o, char **e);-  double qlVanillaSwapFairSpread(QlVanillaSwap* o, char **e);-  double qlVanillaSwapFixedLegBPS(QlVanillaSwap* o, char **e);-  double qlVanillaSwapFixedLegNPV(QlVanillaSwap* o, char **e);-  double qlVanillaSwapFloatingLegBPS(QlVanillaSwap* o, char **e);-  double qlVanillaSwapFloatingLegNPV(QlVanillaSwap* o, char **e);+  double qlFixedVsFloatingSwapFairRate(QlFixedVsFloatingSwap* o, char **e);+  double qlFixedVsFloatingSwapFairSpread(QlFixedVsFloatingSwap* o, char **e);+  double qlFixedVsFloatingSwapFixedLegBPS(QlFixedVsFloatingSwap* o, char **e);+  double qlFixedVsFloatingSwapFixedLegNPV(QlFixedVsFloatingSwap* o, char **e);+  double qlFixedVsFloatingSwapFloatingLegBPS(QlFixedVsFloatingSwap* o, char **e);+  double qlFixedVsFloatingSwapFloatingLegNPV(QlFixedVsFloatingSwap* o, char **e);    void qlFreeEquityTotalReturnSwap(QlEquityTotalReturnSwap *o);   QlSwap* qlEquityTotalReturnSwapAsSwap(QlEquityTotalReturnSwap *o);@@ -240,6 +290,8 @@   QlOneAssetOption* qlBarrierOptionAsOneAssetOption(QlBarrierOption *o);   void qlFreeDoubleBarrierOption(QlDoubleBarrierOption *o);   QlOneAssetOption* qlDoubleBarrierOptionAsOneAssetOption(QlDoubleBarrierOption *o);+  void qlFreeSoftBarrierOption(QlSoftBarrierOption *o);+  QlOneAssetOption* qlSoftBarrierOptionAsOneAssetOption(QlSoftBarrierOption *o);   void qlFreeMargrabeOption(QlMargrabeOption *o);   QlMultiAssetOption* qlMargrabeOptionAsMultiAssetOption(QlMargrabeOption *o);   void qlFreeMultiAssetOption(QlMultiAssetOption *o);@@ -261,7 +313,16 @@   double qlCdsOptionImpliedVolatility(QlCdsOption* o, double price, QlYieldTermStructure* termStructure, QlDefaultProbabilityTermStructure* x3, double recoveryRate, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e);   double qlCdsOptionRiskyAnnuity(QlCdsOption* o, char **e);   double qlSwaptionImpliedVolatility(QlSwaption* o, double price, QlYieldTermStructure* discountCurve, double guess, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, int type, double displacement, int priceType, char **e);-  QlSwaption* qlSwaption(QlVanillaSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e);+  QlSwaption* qlSwaption(QlFixedVsFloatingSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e);+  void qlFreeNonstandardSwaption(QlNonstandardSwaption *o);+  QlOption* qlNonstandardSwaptionAsOption(QlNonstandardSwaption *o);+  QlNonstandardSwaption* qlNonstandardSwaption1(QlSwaption* fromSwaption, char **e);+  QlNonstandardSwaption* qlNonstandardSwaption(QlNonstandardSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e);+  void qlNonstandardSwaptionCalibrationBasket(QlNonstandardSwaption* o, QlSwapIndex* swapBase, QlSwaptionVolatilityStructure* swaptionVol, int basketType, unsigned* len, QlBlackCalibrationHelper*** helpers, char **e);+  void qlFreeFloatFloatSwaption(QlFloatFloatSwaption *o);+  QlOption* qlFloatFloatSwaptionAsOption(QlFloatFloatSwaption *o);+  QlFloatFloatSwaption* qlFloatFloatSwaption(QlFloatFloatSwap* swap, QlExercise* exercise, int delivery, int settlementMethod, char **e);+  void qlFloatFloatSwaptionCalibrationBasket(QlFloatFloatSwaption* o, QlSwapIndex* swapBase, QlSwaptionVolatilityStructure* swaptionVol, int basketType, unsigned* len, QlBlackCalibrationHelper*** helpers, char **e);   void qlFreeQuantoBarrierOption(QlQuantoBarrierOption *o);   QlOneAssetOption* qlQuantoBarrierOptionAsOneAssetOption(QlQuantoBarrierOption *o);   void qlFreeQuantoForwardVanillaOption(QlQuantoForwardVanillaOption *o);@@ -272,6 +333,11 @@   QlOneAssetOption* qlPartialTimeBarrierOption(int barrierType, int barrierRange, double barrier, double rebate, int coverEventDate, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e);   QlDoubleBarrierOption* qlDoubleBarrierOption(int barrierType, double barrierLo, double barrierHi, double rebate, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e);   double qlDoubleBarrierOptionImpliedVolatility(QlDoubleBarrierOption* o, double price, QlGeneralizedBlackScholesProcess* process, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e);+  QlSoftBarrierOption* qlSoftBarrierOption(int barrierType, double barrierLo, double barrierHi, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e);+  double qlSoftBarrierOptionImpliedVolatility(QlSoftBarrierOption* o, double price, QlGeneralizedBlackScholesProcess* process, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e);+  QlOneAssetOption* qlSimpleChooserOption(int choosingDate, double strike, QlExercise* exercise, char **e);+  QlMultiAssetOption* qlTwoAssetCorrelationOption(int type, double strike1, double strike2, QlExercise* exercise, char **e);+  QlOneAssetOption* qlWriterExtensibleOption(QlPlainVanillaPayoff* payoff1, QlExercise* exercise1, QlPlainVanillaPayoff* payoff2, QlExercise* exercise2, char **e);   QlOneAssetOption* qlForwardVanillaOption(double moneyness, int resetDate, QlStrikedTypePayoff* payoff, QlExercise* exercise, char **e);   QlOneAssetOption* qlCompoundOption(QlStrikedTypePayoff* motherPayoff, QlExercise* motherExercise, QlStrikedTypePayoff* daughterPayoff, QlExercise* daughterExercise, char **e);   double qlMargrabeOptionDelta1(QlMargrabeOption* o, char **e);@@ -330,7 +396,7 @@   Leg* qlBondRedemptions(QlBond* o, char **e);   int qlBondSettlementDate(QlBond* o, int d, char **e);   int qlBondStartDate(QlBond* o, char **e);-  int qlBondMaturityDate(QlBond *bond);+  int qlBondMaturityDate(QlBond *bond, char **e);   QlInstrument *qlBondAsInstrument(QlBond *bond);    QlFixedRateBond *qlFixedRateBond(unsigned settlDays, double face, Schedule *schedule, unsigned cLen, double *coupons, DayCounter *counter, int payConv, double redemption, int issue, Calendar *payCal, int exCouponPeriodLen, int exCouponPeriodUnit, Calendar* exCouponCalendar, int exCouponConvention, int exCouponEndOfMonth, DayCounter* firstPeriodDayCounter, char **e);@@ -492,8 +558,15 @@    CouponLeg* qlLegToCouponLeg(Leg *o, char **e);   Leg* qlCPILeg(Schedule* schedule, QlZeroInflationIndex* index, double baseCPI, int obsLagLen, int obsLagUnit, unsigned notionalsLen, double* notionals, unsigned fixedRatesLen, double* fixedRates, DayCounter* paymentDayCounter, int paymentAdjustment, Calendar* paymentCalendar, int observationInterpolation, int subtractInflationNominal, char **e);-  Leg* qlYoYInflationLeg(Schedule* schedule, Calendar* cal, QlYoYInflationIndex* index, int obsLagLen, int obsLagUnit, int interpolation, unsigned notionalsLen, double* notionals, DayCounter* paymentDayCounter, int paymentAdjustment, unsigned fixingDaysLen, unsigned* fixingDays, unsigned gearingsLen, double* gearings, unsigned spreadsLen, double* spreads, char **e);+  Leg* qlYoYInflationLeg(Schedule* schedule, Calendar* cal, QlYoYInflationIndex* index, int obsLagLen, int obsLagUnit, int interpolation, unsigned notionalsLen, double* notionals, DayCounter* paymentDayCounter, int paymentAdjustment, unsigned fixingDaysLen, unsigned* fixingDays, unsigned gearingsLen, double* gearings, unsigned spreadsLen, double* spreads, unsigned capsLen, double* caps, unsigned floorsLen, double* floors, char **e); +  /* YoYInflationCouponPricer -- all 3 concrete pricers share this ctor shape */+  QlYoYInflationCouponPricer *qlBlackYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e);+  QlYoYInflationCouponPricer *qlUnitDisplacedBlackYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e);+  QlYoYInflationCouponPricer *qlBachelierYoYInflationCouponPricer(QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e);+  void qlFreeYoYInflationCouponPricer(QlYoYInflationCouponPricer *p);+  void qlSetYoYInflationCouponPricer(Leg* leg, QlYoYInflationCouponPricer* pricer, char **e);+   void qlFreeZeroInflationCashFlow(QlZeroInflationCashFlow *o);   QlZeroInflationCashFlow* qlZeroInflationCashFlow(double notional, QlZeroInflationIndex* index, int observationInterpolation, int startDate, int endDate, int obsLagLen, int obsLagUnit, int paymentDate, int growthOnly, char **e);   double qlZeroInflationCashFlowAmount(QlZeroInflationCashFlow* o, char **e);@@ -532,6 +605,116 @@   void qlFreeVarianceOption(QlVarianceOption *o);   QlInstrument* qlVarianceOptionAsInstrument(QlVarianceOption *o);   QlVarianceOption* qlVarianceOption(QlPayoff* payoff, double notional, int startDate, int maturityDate, char **e);++  void qlFreeCommodity(QlCommodity *o);+  QlInstrument* qlCommodityAsInstrument(QlCommodity *o);+  void qlFreeEnergyCommodity(QlEnergyCommodity *o);+  QlCommodity* qlEnergyCommodityAsCommodity(QlEnergyCommodity *o);++  /* Commodity -- base-level getters generalized over any leaf (Stage 6). Each output array below+     is its own independent c2hs `preArray-` out-parameter pair (its own `unsigned*` length cell,+     even though every array in one call always carries the same length), mirroring+     qlInstrumentAdditionalResults' own multi-out-param shape. */+  void qlCommodityAddPricingError(QlCommodity *o, int level, char *error, char *detail);+  void qlCommoditySecondaryCostAmounts(QlCommodity *o, unsigned *len, char ***keys,+      unsigned *len2, double **amounts, unsigned *len3, Currency ***currencies, char **e);+  void qlCommodityPricingErrors(QlCommodity *o, unsigned *len, int **levels,+      unsigned *len2, char ***errors, unsigned *len3, char ***details, char **e);++  /* EnergyCommodity -- quantity() is pure virtual upstream; one shim covers every leaf. */+  double qlEnergyCommodityQuantity(QlEnergyCommodity *o, CommodityType **outCt, UnitOfMeasure **outUom, char **e);++  /* EnergyFuture. secondaryCosts is 5 c2hs-marshalled arrays (keys/isUnitCost/amounts/currencies/+     uoms), each an independent `withXArray*&` clause -- c2hs emits one length parameter per array+     clause even though all 5 always carry the same Haskell-side length, so 4 of the 5 `unsigned`s+     below are deliberately unnamed (same convention as qlCompositeInstrument's `unsigned, double+     *coeff` above) and only the first (scLen) is read. */+  QlEnergyFuture* qlEnergyFuture(int buySell,+      CommodityType *qCt, UnitOfMeasure *qUom, double qAmount,+      double tpAmount, Currency *tpCcy, UnitOfMeasure *tpUom,+      QlCommodityIndex *index, CommodityType *commodityType,+      unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+      unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+      char **e);++  /* EnergySwap -- binds no constructor (see qlaux.h); base-level getters generalized over both+     leaves below. */+  void qlFreeEnergySwap(QlEnergySwap *o);+  QlEnergyCommodity* qlEnergySwapAsEnergyCommodity(QlEnergySwap *o);+  void qlEnergySwapDailyPositions(QlEnergySwap *o, unsigned *len, int **dates,+      unsigned *len2, double **quantityAmounts, unsigned *len3, double **payLegPrices,+      unsigned *len4, double **receiveLegPrices, unsigned *len5, double **riskDeltas,+      unsigned *len6, int **unrealized, char **e);+  void qlEnergySwapPaymentCashFlows(QlEnergySwap *o, unsigned *len, QlCommodityCashFlow ***out, char **e);++  /* EnergyVanillaSwap. pricingPeriods is 6 parallel arrays (start/end/payment dates, quantity+     type/uom/amount); like secondaryCosts above, only the first length parameter of each group+     (ppLen, scLen) is read. */+  void qlFreeEnergyVanillaSwap(QlEnergyVanillaSwap *o);+  QlEnergySwap* qlEnergyVanillaSwapAsEnergySwap(QlEnergyVanillaSwap *o);+  QlEnergyVanillaSwap* qlEnergyVanillaSwap(int payer, Calendar *calendar,+      double fixedPriceAmount, Currency *fixedPriceCurrency, UnitOfMeasure *fixedPriceUnitOfMeasure,+      QlCommodityIndex *index, Currency *payCurrency, Currency *receiveCurrency,+      unsigned ppLen, int *ppStartDates, unsigned, int *ppEndDates, unsigned, int *ppPaymentDates,+      unsigned, CommodityType **ppTypes, unsigned, UnitOfMeasure **ppUoms, unsigned, double *ppAmounts,+      CommodityType *commodityType,+      unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+      unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+      QlYieldTermStructure *payLegTS, QlYieldTermStructure *receiveLegTS, QlYieldTermStructure *discountTS,+      char **e);++  /* EnergyBasisSwap -- same pricingPeriods/secondaryCosts array-group shape as EnergyVanillaSwap. */+  void qlFreeEnergyBasisSwap(QlEnergyBasisSwap *o);+  QlEnergySwap* qlEnergyBasisSwapAsEnergySwap(QlEnergyBasisSwap *o);+  QlEnergyBasisSwap* qlEnergyBasisSwap(Calendar *calendar,+      QlCommodityIndex *spreadIndex, QlCommodityIndex *payIndex, QlCommodityIndex *receiveIndex,+      int spreadToPayLeg, Currency *payCurrency, Currency *receiveCurrency,+      unsigned ppLen, int *ppStartDates, unsigned, int *ppEndDates, unsigned, int *ppPaymentDates,+      unsigned, CommodityType **ppTypes, unsigned, UnitOfMeasure **ppUoms, unsigned, double *ppAmounts,+      double basisAmount, Currency *basisCurrency, UnitOfMeasure *basisUnitOfMeasure,+      CommodityType *commodityType,+      unsigned scLen, char **scKeys, unsigned, int *scIsUnitCost, unsigned, double *scAmounts,+      unsigned, Currency **scCurrencies, unsigned, UnitOfMeasure **scUoms,+      QlYieldTermStructure *payLegTS, QlYieldTermStructure *receiveLegTS, QlYieldTermStructure *discountTS,+      char **e);++  /* CommodityCashFlow -- a standalone CashFlow leaf, never Haskell-constructed (only ever produced+     by EnergySwap::paymentCashFlows()). */+  void qlFreeCommodityCashFlow(QlCommodityCashFlow *o);+  int qlCommodityCashFlowDate(QlCommodityCashFlow *o);+  double qlCommodityCashFlowDiscountedAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e);+  double qlCommodityCashFlowUndiscountedAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e);+  double qlCommodityCashFlowDiscountedPaymentAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e);+  double qlCommodityCashFlowUndiscountedPaymentAmount(QlCommodityCashFlow *o, Currency **outCcy, char **e);+  double qlCommodityCashFlowDiscountFactor(QlCommodityCashFlow *o);+  double qlCommodityCashFlowPaymentDiscountFactor(QlCommodityCashFlow *o);+  int qlCommodityCashFlowFinalized(QlCommodityCashFlow *o);++  /* CommodityPricingHelper::createPricingPeriods */+  void qlCreatePricingPeriods(int startDate, int endDate, CommodityType *qCt, UnitOfMeasure *qUom, double qAmount,+      int deliverySchedule, int qtyPeriodicity, PaymentTerm *paymentTerm,+      unsigned *len, int **ppStartDates, unsigned *len2, int **ppEndDates, unsigned *len3, int **ppPaymentDates,+      unsigned *len4, CommodityType ***ppTypes, unsigned *len5, UnitOfMeasure ***ppUoms, unsigned *len6, double **ppAmounts,+      char **e);+  /* YoYInflationCapFloor -- constructed directly at the given Type (Cap/Floor/Collar are thin+     ctor-only subclasses upstream with no logic of their own, so there's no need to touch them). */+  QlYoYInflationCapFloor *qlYoYInflationCap(Leg *yoyLeg, unsigned exerciseRatesLen, double *exerciseRates, char **e);+  QlYoYInflationCapFloor *qlYoYInflationFloor(Leg *yoyLeg, unsigned exerciseRatesLen, double *exerciseRates, char **e);+  QlYoYInflationCapFloor *qlYoYInflationCollar(Leg *yoyLeg, unsigned capRatesLen, double *capRates,+      unsigned floorRatesLen, double *floorRates, char **e);+  void qlFreeYoYInflationCapFloor(QlYoYInflationCapFloor *o);+  QlInstrument *qlYoYInflationCapFloorAsInstrument(QlYoYInflationCapFloor *o);+  double qlYoYInflationCapFloorAtmRate(QlYoYInflationCapFloor *o, QlYieldTermStructure *discountCurve, char **e);+  QlYoYInflationCapFloor *qlYoYInflationCapFloorOptionlet(QlYoYInflationCapFloor *o, unsigned n, char **e);++  /* CPICapFloor -- a single cumulative option, unlike YoYInflationCapFloor; no impliedVolatility+     (no vol-driven engine exists for it in QL 1.43, see qlInterpolatingCPICapFloorEngine below). */+  QlCPICapFloor *qlCPICapFloor(int type, double nominal, int startDate, double baseCPI, int maturity,+      Calendar *fixCalendar, int fixConvention, Calendar *payCalendar, int payConvention, double strike,+      QlZeroInflationIndex *index, int observationLagLen, int observationLagUnit, int observationInterpolation,+      char **e);+  void qlFreeCPICapFloor(QlCPICapFloor *o);+  QlInstrument *qlCPICapFloorAsInstrument(QlCPICapFloor *o); #ifdef __cplusplus } #endif
cbits/qlMisc.cpp view
@@ -20,6 +20,14 @@ #include <ql/time/period.hpp> #include <ql/utilities/dataparsers.hpp> #include <ql/time/daycounters/all.hpp>+#include <ql/experimental/commodities/commoditytype.hpp>+#include <ql/experimental/commodities/unitofmeasure.hpp>+#include <ql/experimental/commodities/petroleumunitsofmeasure.hpp>+#include <ql/experimental/commodities/paymentterm.hpp>+#include <ql/experimental/commodities/quantity.hpp>+#include <ql/experimental/commodities/unitofmeasureconversion.hpp>+#include <ql/experimental/commodities/unitofmeasureconversionmanager.hpp>+#include <ql/experimental/commodities/commoditysettings.hpp>  #ifdef QLTRACK_ALLOCATIONS # include <cstdlib>@@ -184,6 +192,11 @@ void qlFreeUInts(unsigned *p) {delete[] p;} void qlFreeDoubles(double *p) {delete[] p;} void qlFreePointerArray(void **p) {delete[] p;}+void qlFreeStringArray(unsigned n, char **p) {+  if (!p) return;+  for (unsigned i = 0; i < n; ++i) qlFreeString(p[i]);+  delete[] p;+} int qlNullInteger() {return Null<Integer>();} double qlNullReal() {return Null<Real>();} double qlEpsilon() {return QL_EPSILON;}@@ -252,8 +265,9 @@           rounding, triangulationCurrency));   } catch (std::exception& er) {return handleException<Currency*>(e, er);}} -ExchangeRate *qlExchangeRate(Currency *source, Currency *target, double rate) {-  return alloc(new ExchangeRate(*arg(source), *arg(target), rate));+ExchangeRate *qlExchangeRate(Currency *source, Currency *target, double rate, char **e) {+  try {return alloc(new ExchangeRate(*arg(source), *arg(target), rate));+  } catch (std::exception& er) {return handleException<ExchangeRate*>(e, er);} } void qlFreeExchangeRate(ExchangeRate *o) {del(o);} double qlExchangeRateRate(ExchangeRate *o) {return arg(o)->rate();}@@ -274,8 +288,9 @@   } catch (std::exception& er) {return handleException<ExchangeRate*>(e, er);} } -void qlExchangeRateManagerAdd(ExchangeRate *rate, int startSerial, int endSerial) {-  ExchangeRateManager::instance().add(*arg(rate), qlNullableDate(startSerial), qlNullableDate(endSerial));+void qlExchangeRateManagerAdd(ExchangeRate *rate, int startSerial, int endSerial, char **e) {+  try {ExchangeRateManager::instance().add(*arg(rate), qlNullableDate(startSerial), qlNullableDate(endSerial));+  } catch (std::exception& er) {*e = DUP(er.what());} }  ExchangeRate *qlExchangeRateManagerLookup(Currency *source, Currency *target, int dateSerial, int type, char **e) {@@ -289,9 +304,11 @@  int qlMoneySettingsConversionType() {return Money::Settings::instance().conversionType();} void qlMoneySettingsSetConversionType(int t) {Money::Settings::instance().conversionType() = (Money::ConversionType)t;}-Currency *qlMoneySettingsBaseCurrency() {-  const Currency &base = Money::Settings::instance().baseCurrency();-  return base.empty() ? 0 : ret(new Currency(base));+Currency *qlMoneySettingsBaseCurrency(char **e) {+  try {+    const Currency &base = Money::Settings::instance().baseCurrency();+    return base.empty() ? 0 : ret(new Currency(base));+  } catch (std::exception& er) {return handleException<Currency*>(e, er);} } void qlMoneySettingsSetBaseCurrency(Currency *c) {Money::Settings::instance().baseCurrency() = *arg(c);} @@ -563,8 +580,12 @@     return alloc(calendars[country](market));   } catch (std::exception& er) {return handleException<Calendar *>(e, er);}} -int qlCalendarAdjust(Calendar *c, int date, int conv) {return arg(c)->adjust(Date(date), (BusinessDayConvention) conv).serialNumber();}-int qlCalendarAdvance(Calendar *c, int date, int n, int unit, int conv, int eom) {return arg(c)->advance(Date(date), n, (TimeUnit) unit,(BusinessDayConvention) conv, eom).serialNumber();}+int qlCalendarAdjust(Calendar *c, int date, int conv, char **e) {+  try {return arg(c)->adjust(Date(date), (BusinessDayConvention) conv).serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}}+int qlCalendarAdvance(Calendar *c, int date, int n, int unit, int conv, int eom, char **e) {+  try {return arg(c)->advance(Date(date), n, (TimeUnit) unit,(BusinessDayConvention) conv, eom).serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}} void qlCalendarAddHoliday(Calendar* o, int x0, char **e) {try {arg(o)->addHoliday(Date(x0));} catch (std::exception& er) {(void)handleException<int>(e, er);}}  int qlCalendarBusinessDaysBetween(Calendar* o, int from, int to, int includeFirst, int includeLast, char **e) {@@ -611,11 +632,15 @@     for (size_t i = 0; i < dates.size(); ++i)       (*days)[i] = dates[i].serialNumber();   } catch (std::exception& er) {(void)handleException<int*>(e, er);}}-Schedule *qlSchedule1(unsigned len, int *dates, Calendar *cal, int conv, char **e) {+Schedule *qlSchedule1(unsigned len, int *dates, Calendar *cal, int conv, int termConv, int tenorLen, int tenorUnit, int rule, int eom, char **e) {   try {std::vector<Date> d; d.reserve(len);     for (unsigned i = 0; i < len; ++i)       d.push_back(Date(dates[i]));-    return alloc(new Schedule(d, *arg(cal), (BusinessDayConvention) conv));+    return alloc(new Schedule(d, *arg(cal), (BusinessDayConvention) conv,+      qlOptBusinessDayConvention(termConv),+      tenorUnit < 0 ? ext::optional<Period>() : ext::optional<Period>(Period(tenorLen, (TimeUnit)tenorUnit)),+      rule < 0 ? ext::optional<DateGeneration::Rule>() : ext::optional<DateGeneration::Rule>((DateGeneration::Rule)rule),+      qlOptBool(eom)));   } catch (std::exception& er) {return handleException<Schedule *>(e, er);}} Schedule *qlSchedule(int eff, int term, int l, int u, Calendar *cal, int conv, int termConv, int rule, int eom, int first, int nextToLast, char **e) {   try {return alloc(new Schedule(qlNullableDate(eff), Date(term), Period(l, (TimeUnit)u), *arg(cal),@@ -689,5 +714,159 @@ double qlDayCounterYearFraction(DayCounter* o, int x0, int x1, int refPeriodStart, int refPeriodEnd, char **e) {   try {return arg(o)->yearFraction(Date(x0), Date(x1), qlNullableDate(refPeriodStart), qlNullableDate(refPeriodEnd));   } catch (std::exception& er) {return handleException<double>(e, er);}}++/* CommodityType */++CommodityType *qlCommodityType(char *code, char *name, char **e) {+  // commoditytype.hpp's declaration names its params (code, name), but the out-of-line+  // definition in commoditytype.cpp takes (name, code) -- and that's what actually executes.+  try {return alloc(new CommodityType(arg(name), arg(code)));+  } catch (std::exception& er) {return handleException<CommodityType*>(e, er);}}++CommodityType *qlNullCommodityType(char **e) {+  try {return alloc(new CommodityType(NullCommodityType()));+  } catch (std::exception& er) {return handleException<CommodityType*>(e, er);}}++void qlFreeCommodityType(CommodityType *o) {del(o);}+char *qlCommodityTypeCode(CommodityType *o) {return DUP(arg(o)->code().c_str());}+char *qlCommodityTypeName(CommodityType *o) {return DUP(arg(o)->name().c_str());}+int qlCommodityTypeEmpty(CommodityType *o) {return arg(o)->empty();}++/* UnitOfMeasure */++UnitOfMeasure *qlUnitOfMeasure(char *name, char *code, int unitType, char **e) {+  try {return alloc(new UnitOfMeasure(arg(name), arg(code), (UnitOfMeasure::Type)unitType));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}++void qlFreeUnitOfMeasure(UnitOfMeasure *o) {del(o);}+char *qlUnitOfMeasureName(UnitOfMeasure *o) {return DUP(arg(o)->name().c_str());}+char *qlUnitOfMeasureCode(UnitOfMeasure *o) {return DUP(arg(o)->code().c_str());}+int qlUnitOfMeasureUnitType(UnitOfMeasure *o) {return arg(o)->unitType();}+int qlUnitOfMeasureEmpty(UnitOfMeasure *o) {return arg(o)->empty();}++UnitOfMeasure *qlLotUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(LotUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlBarrelUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(BarrelUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlMTUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(MTUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlMBUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(MBUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlGallonUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(GallonUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlLitreUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(LitreUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlKilolitreUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(KilolitreUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlTokyoKilolitreUnitOfMeasure(char **e) {+  try {return alloc(new UnitOfMeasure(TokyoKilolitreUnitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}++/* PaymentTerm */++PaymentTerm *qlPaymentTerm(char *name, int eventType, int offsetDays, Calendar *calendar, char **e) {+  try {return alloc(new PaymentTerm(arg(name), (PaymentTerm::EventType)eventType, offsetDays, *arg(calendar)));+  } catch (std::exception& er) {return handleException<PaymentTerm*>(e, er);}}++void qlFreePaymentTerm(PaymentTerm *o) {del(o);}+char *qlPaymentTermName(PaymentTerm *o) {return DUP(arg(o)->name().c_str());}+int qlPaymentTermEventType_(PaymentTerm *o) {return arg(o)->eventType();}+int qlPaymentTermOffsetDays(PaymentTerm *o) {return arg(o)->offsetDays();}+Calendar *qlPaymentTermCalendar(PaymentTerm *o, char **e) {+  try {return ret(new Calendar(arg(o)->calendar()));+  } catch (std::exception& er) {return handleException<Calendar*>(e, er);}}+int qlPaymentTermEmpty(PaymentTerm *o) {return arg(o)->empty();}++int qlPaymentTermGetPaymentDate(PaymentTerm *o, int date, char **e) {+  try {return arg(o)->getPaymentDate(qlNullableDate(date)).serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}}++/* Quantity -- see qlCommodity.h on why this is three flat arguments, not one tuple. */++double qlQuantityRoundedAmount(UnitOfMeasure *uom, double amount) {+  return arg(uom)->rounding()(amount);}++int qlQuantityClose(CommodityType *ct1, UnitOfMeasure *uom1, double amount1,+                    CommodityType *ct2, UnitOfMeasure *uom2, double amount2, int n, char **e) {+  try {return close(Quantity(*arg(ct1), *arg(uom1), amount1),+                    Quantity(*arg(ct2), *arg(uom2), amount2), n);+  } catch (std::exception& er) {return handleException<int>(e, er);}}++int qlQuantityCloseEnough(CommodityType *ct1, UnitOfMeasure *uom1, double amount1,+                          CommodityType *ct2, UnitOfMeasure *uom2, double amount2, int n, char **e) {+  try {return close_enough(Quantity(*arg(ct1), *arg(uom1), amount1),+                           Quantity(*arg(ct2), *arg(uom2), amount2), n);+  } catch (std::exception& er) {return handleException<int>(e, er);}}++/* UnitOfMeasureConversion */++UnitOfMeasureConversion *qlUnitOfMeasureConversion(CommodityType *commodityType, UnitOfMeasure *source,+                                                   UnitOfMeasure *target, double conversionFactor, char **e) {+  try {return alloc(new UnitOfMeasureConversion(*arg(commodityType), *arg(source), *arg(target), conversionFactor));+  } catch (std::exception& er) {return handleException<UnitOfMeasureConversion*>(e, er);}}++void qlFreeUnitOfMeasureConversion(UnitOfMeasureConversion *o) {del(o);}+UnitOfMeasure *qlUnitOfMeasureConversionSource(UnitOfMeasureConversion *o, char **e) {+  try {return ret(new UnitOfMeasure(arg(o)->source()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+UnitOfMeasure *qlUnitOfMeasureConversionTarget(UnitOfMeasureConversion *o, char **e) {+  try {return ret(new UnitOfMeasure(arg(o)->target()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+CommodityType *qlUnitOfMeasureConversionCommodityType(UnitOfMeasureConversion *o, char **e) {+  try {return ret(new CommodityType(arg(o)->commodityType()));+  } catch (std::exception& er) {return handleException<CommodityType*>(e, er);}}+int qlUnitOfMeasureConversionType_(UnitOfMeasureConversion *o) {return arg(o)->type();}+double qlUnitOfMeasureConversionFactor(UnitOfMeasureConversion *o) {return arg(o)->conversionFactor();}+char *qlUnitOfMeasureConversionCode(UnitOfMeasureConversion *o) {return DUP(arg(o)->code().c_str());}++double qlUnitOfMeasureConversionConvert(UnitOfMeasureConversion *o, CommodityType *ct, UnitOfMeasure *uom,+                                        double amount, CommodityType **outCt, UnitOfMeasure **outUom, char **e) {+  *outCt = 0; *outUom = 0;+  CommodityType *ct2 = 0;+  try {+    Quantity r = arg(o)->convert(Quantity(*arg(ct), *arg(uom), amount));+    ct2 = ret(new CommodityType(r.commodityType()));+    UnitOfMeasure *uom2 = ret(new UnitOfMeasure(r.unitOfMeasure()));+    *outCt = ct2; *outUom = uom2;+    return r.amount();+  } catch (std::exception& er) {+    delete ct2;+    return handleException<double>(e, er);+  }}++UnitOfMeasureConversion *qlUnitOfMeasureConversionChain(UnitOfMeasureConversion *r1, UnitOfMeasureConversion *r2, char **e) {+  try {return alloc(new UnitOfMeasureConversion(UnitOfMeasureConversion::chain(*arg(r1), *arg(r2))));+  } catch (std::exception& er) {return handleException<UnitOfMeasureConversion*>(e, er);}}++/* UnitOfMeasureConversionManager */++UnitOfMeasureConversion *qlUnitOfMeasureConversionManagerLookup(+    CommodityType *commodityType, UnitOfMeasure *source, UnitOfMeasure *target, int type, char **e) {+  try {return alloc(new UnitOfMeasureConversion(UnitOfMeasureConversionManager::instance().lookup(+      *arg(commodityType), *arg(source), *arg(target), (UnitOfMeasureConversion::Type)type)));+  } catch (std::exception& er) {return handleException<UnitOfMeasureConversion*>(e, er);}}++void qlUnitOfMeasureConversionManagerAdd(UnitOfMeasureConversion *c) {+  UnitOfMeasureConversionManager::instance().add(*arg(c));}++void qlUnitOfMeasureConversionManagerClear() {UnitOfMeasureConversionManager::instance().clear();}++/* CommoditySettings */++Currency *qlCommoditySettingsCurrency(char **e) {+  try {return ret(new Currency(CommoditySettings::instance().currency()));+  } catch (std::exception& er) {return handleException<Currency*>(e, er);}}+void qlCommoditySettingsSetCurrency(Currency *c) {CommoditySettings::instance().currency() = *arg(c);}+UnitOfMeasure *qlCommoditySettingsUnitOfMeasure(char **e) {+  try {return ret(new UnitOfMeasure(CommoditySettings::instance().unitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+void qlCommoditySettingsSetUnitOfMeasure(UnitOfMeasure *u) {CommoditySettings::instance().unitOfMeasure() = *arg(u);} } /* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
cbits/qlMisc.h view
@@ -19,6 +19,7 @@   void qlFreeUInts(unsigned *p);   void qlFreeDoubles(double *p);   void qlFreePointerArray(void **p);+  void qlFreeStringArray(unsigned n, char **p);   int qlNullInteger();   double qlNullReal();   double qlEpsilon();@@ -34,20 +35,20 @@   char* qlCurrencySymbol(Currency* o);   Currency* qlCreateCurrency(char* name, char* code, int numericCode, char* symbol, char* fractionSymbol, int fractionsPerUnit, Rounding* rounding, Currency* triangulationCurrency, char **e); -  ExchangeRate *qlExchangeRate(Currency *source, Currency *target, double rate);+  ExchangeRate *qlExchangeRate(Currency *source, Currency *target, double rate, char **e);   void qlFreeExchangeRate(ExchangeRate *o);   double qlExchangeRateRate(ExchangeRate *o);   int qlExchangeRateType_(ExchangeRate *o);   double qlExchangeRateExchange(ExchangeRate *o, double amount, Currency *ccy, Currency **outCcy, char **e);   ExchangeRate *qlExchangeRateChain(ExchangeRate *r1, ExchangeRate *r2, char **e); -  void qlExchangeRateManagerAdd(ExchangeRate *rate, int startSerial, int endSerial);+  void qlExchangeRateManagerAdd(ExchangeRate *rate, int startSerial, int endSerial, char **e);   ExchangeRate *qlExchangeRateManagerLookup(Currency *source, Currency *target, int dateSerial, int type, char **e);   void qlExchangeRateManagerClear();    int qlMoneySettingsConversionType();   void qlMoneySettingsSetConversionType(int t);-  Currency *qlMoneySettingsBaseCurrency();+  Currency *qlMoneySettingsBaseCurrency(char **e);   void qlMoneySettingsSetBaseCurrency(Currency *c);   double qlConvertToBaseCurrency(double amount, Currency *ccy, Currency **outCcy, char **e); @@ -151,8 +152,8 @@    Calendar *qlCalendar(int country, int market, char **e);   const char *qlCalendarName(Calendar *calendar);-  int qlCalendarAdjust(Calendar *c, int date, int conv);-  int qlCalendarAdvance(Calendar *c, int date, int n, int unit, int conv, int eom);+  int qlCalendarAdjust(Calendar *c, int date, int conv, char **e);+  int qlCalendarAdvance(Calendar *c, int date, int n, int unit, int conv, int eom, char **e);   void qlCalendarAddHoliday(Calendar* o, int x0, char **e);   int qlCalendarBusinessDaysBetween(Calendar* o, int from, int to, int includeFirst, int includeLast, char **e);   int qlCalendarEndOfMonth(Calendar* o, int d, char **e);@@ -170,7 +171,7 @@   void qlFreeCalendar(Calendar *calendar);    Schedule *qlSchedule(int eff, int term, int, int, Calendar *cal, int conv, int termConv, int rule, int eom, int first, int nextToLast, char **e);-  Schedule *qlSchedule1(unsigned len, int *dates, Calendar *cal, int conv, char **e);+  Schedule *qlSchedule1(unsigned len, int *dates, Calendar *cal, int conv, int termConv, int tenorLen, int tenorUnit, int rule, int eom, char **e);   Schedule *qlScheduleUntil(Schedule *sched, int date, char **e);   void qlScheduleDates(Schedule *sched, unsigned *count, int **days);   void qlFreeSchedule(Schedule *s);@@ -192,6 +193,75 @@   double qlDayCounterYearFraction(DayCounter* o, int x0, int x1, int refPeriodStart, int refPeriodEnd, char **e);    void qlFreeDayCounter(DayCounter *counter);++  /* CommodityType */+  CommodityType *qlCommodityType(char *code, char *name, char **e);+  CommodityType *qlNullCommodityType(char **e);+  void qlFreeCommodityType(CommodityType *o);+  char *qlCommodityTypeCode(CommodityType *o);+  char *qlCommodityTypeName(CommodityType *o);+  int qlCommodityTypeEmpty(CommodityType *o);++  /* UnitOfMeasure */+  UnitOfMeasure *qlUnitOfMeasure(char *name, char *code, int unitType, char **e);+  void qlFreeUnitOfMeasure(UnitOfMeasure *o);+  char *qlUnitOfMeasureName(UnitOfMeasure *o);+  char *qlUnitOfMeasureCode(UnitOfMeasure *o);+  int qlUnitOfMeasureUnitType(UnitOfMeasure *o);+  int qlUnitOfMeasureEmpty(UnitOfMeasure *o);+  UnitOfMeasure *qlLotUnitOfMeasure(char **e);+  UnitOfMeasure *qlBarrelUnitOfMeasure(char **e);+  UnitOfMeasure *qlMTUnitOfMeasure(char **e);+  UnitOfMeasure *qlMBUnitOfMeasure(char **e);+  UnitOfMeasure *qlGallonUnitOfMeasure(char **e);+  UnitOfMeasure *qlLitreUnitOfMeasure(char **e);+  UnitOfMeasure *qlKilolitreUnitOfMeasure(char **e);+  UnitOfMeasure *qlTokyoKilolitreUnitOfMeasure(char **e);++  /* PaymentTerm */+  PaymentTerm *qlPaymentTerm(char *name, int eventType, int offsetDays, Calendar *calendar, char **e);+  void qlFreePaymentTerm(PaymentTerm *o);+  char *qlPaymentTermName(PaymentTerm *o);+  int qlPaymentTermEventType_(PaymentTerm *o);+  int qlPaymentTermOffsetDays(PaymentTerm *o);+  Calendar *qlPaymentTermCalendar(PaymentTerm *o, char **e);+  int qlPaymentTermEmpty(PaymentTerm *o);+  int qlPaymentTermGetPaymentDate(PaymentTerm *o, int date, char **e);++  /* Quantity -- marshalled as flat (CommodityType, UnitOfMeasure, double) triples throughout,+     since c2hs's `&` tuple-splitter caps at two C arguments (confirmed against its source: the+     `twoCVal` marshaller consumes exactly [ct1, ct2], with no three-way variant). */+  double qlQuantityRoundedAmount(UnitOfMeasure *uom, double amount);+  int qlQuantityClose(CommodityType *ct1, UnitOfMeasure *uom1, double amount1,+                      CommodityType *ct2, UnitOfMeasure *uom2, double amount2, int n, char **e);+  int qlQuantityCloseEnough(CommodityType *ct1, UnitOfMeasure *uom1, double amount1,+                            CommodityType *ct2, UnitOfMeasure *uom2, double amount2, int n, char **e);++  /* UnitOfMeasureConversion */+  UnitOfMeasureConversion *qlUnitOfMeasureConversion(CommodityType *commodityType, UnitOfMeasure *source,+                                                     UnitOfMeasure *target, double conversionFactor, char **e);+  void qlFreeUnitOfMeasureConversion(UnitOfMeasureConversion *o);+  UnitOfMeasure *qlUnitOfMeasureConversionSource(UnitOfMeasureConversion *o, char **e);+  UnitOfMeasure *qlUnitOfMeasureConversionTarget(UnitOfMeasureConversion *o, char **e);+  CommodityType *qlUnitOfMeasureConversionCommodityType(UnitOfMeasureConversion *o, char **e);+  int qlUnitOfMeasureConversionType_(UnitOfMeasureConversion *o);+  double qlUnitOfMeasureConversionFactor(UnitOfMeasureConversion *o);+  char *qlUnitOfMeasureConversionCode(UnitOfMeasureConversion *o);+  double qlUnitOfMeasureConversionConvert(UnitOfMeasureConversion *o, CommodityType *ct, UnitOfMeasure *uom,+                                          double amount, CommodityType **outCt, UnitOfMeasure **outUom, char **e);+  UnitOfMeasureConversion *qlUnitOfMeasureConversionChain(UnitOfMeasureConversion *r1, UnitOfMeasureConversion *r2, char **e);++  /* UnitOfMeasureConversionManager (singleton) */+  UnitOfMeasureConversion *qlUnitOfMeasureConversionManagerLookup(+      CommodityType *commodityType, UnitOfMeasure *source, UnitOfMeasure *target, int type, char **e);+  void qlUnitOfMeasureConversionManagerAdd(UnitOfMeasureConversion *c);+  void qlUnitOfMeasureConversionManagerClear(void);++  /* CommoditySettings (singleton) */+  Currency *qlCommoditySettingsCurrency(char **e);+  void qlCommoditySettingsSetCurrency(Currency *c);+  UnitOfMeasure *qlCommoditySettingsUnitOfMeasure(char **e);+  void qlCommoditySettingsSetUnitOfMeasure(UnitOfMeasure *u); #ifdef __cplusplus } #endif
cbits/qlPricingEngine.cpp view
@@ -9,8 +9,18 @@ #include <ql/pricingengines/asian/analytic_cont_geom_av_price.hpp> #include <ql/pricingengines/asian/analytic_discr_geom_av_strike.hpp> #include <ql/pricingengines/asian/mc_discr_arith_av_price.hpp>+#include <ql/pricingengines/asian/turnbullwakemanasianengine.hpp>+#include <ql/pricingengines/asian/fdblackscholesasianengine.hpp>+#include <ql/pricingengines/forward/forwardengine.hpp>+#include <ql/pricingengines/vanilla/fdblackscholesvanillaengine.hpp>+#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>+#include <ql/experimental/forward/analytichestonforwardeuropeanengine.hpp> #include <ql/experimental/barrieroption/vannavolgadoublebarrierengine.hpp> #include <ql/pricingengines/barrier/analyticbarrierengine.hpp>+#include <ql/pricingengines/barrier/analyticsoftbarrierengine.hpp>+#include <ql/pricingengines/exotic/analyticsimplechooserengine.hpp>+#include <ql/pricingengines/exotic/analytictwoassetcorrelationengine.hpp>+#include <ql/pricingengines/exotic/analyticwriterextensibleoptionengine.hpp> #include <ql/pricingengines/barrier/analyticpartialtimebarrieroptionengine.hpp> #include <ql/pricingengines/barrier/analyticbinarybarrierengine.hpp> #include <ql/pricingengines/barrier/analyticdoublebarrierengine.hpp>@@ -42,13 +52,19 @@ #include <ql/pricingengines/lookback/analyticcontinuousfloatinglookback.hpp> #include <ql/pricingengines/swap/cvaswapengine.hpp> #include <ql/pricingengines/swap/treeswapengine.hpp>+#include <ql/pricingengines/swap/discountingconstnotionalcrosscurrencyswapengine.hpp> #include <ql/pricingengines/swaption/blackswaptionengine.hpp> #include <ql/termstructures/volatility/sabr.hpp> #include <ql/pricingengines/swaption/fdg2swaptionengine.hpp> #include <ql/pricingengines/swaption/fdg2swaptionengine.hpp> #include <ql/pricingengines/swaption/fdhullwhiteswaptionengine.hpp> #include <ql/pricingengines/swaption/g2swaptionengine.hpp>+#include <ql/pricingengines/capfloor/gaussian1dcapfloorengine.hpp> #include <ql/pricingengines/swaption/gaussian1dswaptionengine.hpp>+#include <ql/pricingengines/swaption/gaussian1dnonstandardswaptionengine.hpp>+#include <ql/pricingengines/swaption/gaussian1dfloatfloatswaptionengine.hpp>+#include <ql/pricingengines/swaption/gaussian1djamshidianswaptionengine.hpp>+#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp> #include <ql/pricingengines/swaption/jamshidianswaptionengine.hpp> #include <ql/pricingengines/swaption/treeswaptionengine.hpp> #include <ql/pricingengines/vanilla/analyticbsmhullwhiteengine.hpp>@@ -126,12 +142,27 @@ QlPricingEngine* qlDiscountingFxForwardEngine(QlYieldTermStructure* sourceCurrencyDiscountCurve, QlYieldTermStructure* targetCurrencyDiscountCurve, QlQuote* spotFx, char **e) {   try {return ret(new QlPricingEngine(alloc(new DiscountingFxForwardEngine(*arg(sourceCurrencyDiscountCurve), *arg(targetCurrencyDiscountCurve), *arg(spotFx)))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlDiscountingConstNotionalCrossCurrencySwapEngine(Currency* domesticCcy, QlYieldTermStructure* domesticCcyDiscountCurve, Currency* foreignCcy, QlYieldTermStructure* foreignCcyDiscountCurve, QlQuote* spotFX, int includeSettlementDateFlows, int settlementDate, int npvDate, int spotFXSettleDate, char **e) {+  try {return ret(new QlPricingEngine(alloc(new DiscountingConstNotionalCrossCurrencySwapEngine(*arg(domesticCcy), *arg(domesticCcyDiscountCurve), *arg(foreignCcy), *arg(foreignCcyDiscountCurve), *arg(spotFX), qlOptBool(includeSettlementDateFlows), qlNullableDate(settlementDate), qlNullableDate(npvDate), qlNullableDate(spotFXSettleDate)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}} QlPricingEngine* qlCounterpartyAdjSwapEngine(QlYieldTermStructure* discountCurve, QlQuote* blackVol, QlDefaultProbabilityTermStructure* ctptyDTS, double ctptyRecoveryRate, QlDefaultProbabilityTermStructure* invstDTS, double invstRecoveryRate, char **e) {   try {return ret(new QlPricingEngine(alloc(new CounterpartyAdjSwapEngine(*arg(discountCurve), *arg(blackVol), Handle<DefaultProbabilityTermStructure>(*arg(ctptyDTS)), ctptyRecoveryRate, qlNullableHandle(arg(invstDTS)), invstRecoveryRate))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}} QlPricingEngine* qlAnalyticBarrierEngine(QlGeneralizedBlackScholesProcess* process, char **e) {   try {return ret(new QlPricingEngine(alloc(new AnalyticBarrierEngine(*arg(process)))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlAnalyticSoftBarrierEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new AnalyticSoftBarrierEngine(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlAnalyticSimpleChooserEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new AnalyticSimpleChooserEngine(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlAnalyticTwoAssetCorrelationEngine(QlGeneralizedBlackScholesProcess* process1, QlGeneralizedBlackScholesProcess* process2, QlQuote* correlation, char **e) {+  try {return ret(new QlPricingEngine(alloc(new AnalyticTwoAssetCorrelationEngine(*arg(process1), *arg(process2), *arg(correlation)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlAnalyticWriterExtensibleOptionEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new AnalyticWriterExtensibleOptionEngine(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}} QlPricingEngine* qlAnalyticPartialTimeBarrierOptionEngine(QlGeneralizedBlackScholesProcess* process, char **e) {   try {return ret(new QlPricingEngine(alloc(new AnalyticPartialTimeBarrierOptionEngine(*arg(process)))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}@@ -192,6 +223,27 @@ QlPricingEngine* qlAnalyticDiscreteGeometricAverageStrikeAsianEngine(QlGeneralizedBlackScholesProcess* process, char **e) {   try {return ret(new QlPricingEngine(alloc(new AnalyticDiscreteGeometricAverageStrikeAsianEngine(*arg(process)))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlTurnbullWakemanAsianEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new TurnbullWakemanAsianEngine(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlFdBlackScholesAsianEngine(QlGeneralizedBlackScholesProcess* process, unsigned tGrid, unsigned xGrid, unsigned aGrid, FdmSchemeDesc *fdScheme, char **e) {+  try {return ret(new QlPricingEngine(alloc(new FdBlackScholesAsianEngine(*arg(process), tGrid, xGrid, aGrid, *arg(fdScheme)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlForwardEuropeanEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new ForwardVanillaEngine<AnalyticEuropeanEngine>(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlForwardBaroneAdesiWhaleyEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new ForwardVanillaEngine<BaroneAdesiWhaleyApproximationEngine>(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlForwardBjerksundStenslandEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new ForwardVanillaEngine<BjerksundStenslandApproximationEngine>(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlForwardFdBlackScholesVanillaEngine(QlGeneralizedBlackScholesProcess* process, char **e) {+  try {return ret(new QlPricingEngine(alloc(new ForwardVanillaEngine<FdBlackScholesVanillaEngine>(*arg(process)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlAnalyticHestonForwardEuropeanEngine(QlHestonProcess* process, unsigned integrationOrder, char **e) {+  try {return ret(new QlPricingEngine(alloc(new AnalyticHestonForwardEuropeanEngine(*arg(process), integrationOrder))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}} QlPricingEngine* qlAnalyticDividendEuropeanEngine(QlGeneralizedBlackScholesProcess* x0, unsigned dividendsLen, QlDividend** dividends, char **e) {   try {DividendSchedule d = qlVector(dividends, dividendsLen);     return ret(new QlPricingEngine(alloc(new AnalyticDividendEuropeanEngine(*arg(x0), d))));@@ -482,6 +534,9 @@ QlPricingEngine* qlMCDigitalEngine1(int rngtrait, QlGeneralizedBlackScholesProcess* x0, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, char **e) {   try {return ret(new QlPricingEngine(alloc(qlMCDigitalEngine1Aux(rngtrait, *arg(x0), timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlMCForwardEuropeanBSEngine1(int rngtrait, QlGeneralizedBlackScholesProcess* process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, char **e) {+  try {return ret(new QlPricingEngine(alloc(qlMCForwardEuropeanBSEngine1Aux(rngtrait, *arg(process), timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}} QlPricingEngine* qlMCDiscreteArithmeticAPEngine1(int rngtrait, QlGeneralizedBlackScholesProcess* process, int brownianBridge, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, char **e) {   try {return ret(new QlPricingEngine(alloc(qlMCDiscreteArithmeticAPEngine1Aux(rngtrait, *arg(process), brownianBridge, antitheticVariate, controlVariate, requiredSamples, requiredTolerance, maxSamples, seed))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}@@ -590,8 +645,12 @@ void qlFreeShortRateModel(QlShortRateModel *o) {del(o);} void qlFreeAffineModel(QlAffineModel *o) {del(o);} void qlFreeOneFactorAffineModel(QlOneFactorAffineModel *o) {del(o);}-double qlOneFactorAffineModelDiscountBond(QlOneFactorAffineModel* o, double now, double maturity, double rate) {return (*arg(o))->discountBond(now, maturity, rate);}-double qlHullWhiteConvexityBias(double futurePrice, double t, double T, double sigma, double a) {return HullWhite::convexityBias(futurePrice, t, T, sigma, a);}+double qlOneFactorAffineModelDiscountBond(QlOneFactorAffineModel* o, double now, double maturity, double rate, char **e) {+  try {return (*arg(o))->discountBond(now, maturity, rate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlHullWhiteConvexityBias(double futurePrice, double t, double T, double sigma, double a, char **e) {+  try {return HullWhite::convexityBias(futurePrice, t, T, sigma, a);+  } catch (std::exception& er) {return handleException<double>(e, er);}} QlAffineModel* qlHullWhiteAsAffineModel(QlHullWhite *o) {return ret(new QlAffineModel(*arg(o)));} QlAffineModel* qlOneFactorAffineModelAsAffineModel(QlOneFactorAffineModel *o) {return ret(new QlAffineModel(*arg(o)));} void qlFreeLiborForwardModel(QlLiborForwardModel *o) {del(o);}@@ -681,12 +740,29 @@ QlMarkovFunctional* qlMarkovFunctional(QlYieldTermStructure* termStructure, double reversion, unsigned volstepdatesLen, int* volstepdates, unsigned volatilitiesLen, double* volatilities, QlSwaptionVolatilityStructure* swaptionVol, unsigned expiriesLen, int* swaptionExpiries, unsigned tenorsLen, int* tenorQuantity, unsigned, int* tenorUnit, QlSwapIndex* swapIndexBase, unsigned yGridPoints, char **e) {   try {return ret(new QlMarkovFunctional(alloc(new MarkovFunctional(*arg(termStructure), reversion, qlDateVector(volstepdates, volstepdatesLen), std::vector<double>(volatilities, volatilities+volatilitiesLen), *arg(swaptionVol), qlDateVector(swaptionExpiries, expiriesLen), qlPeriodVector(tenorQuantity, tenorUnit, tenorsLen), *arg(swapIndexBase), MarkovFunctional::ModelSettings().withYGridPoints(yGridPoints)))));   } catch (std::exception& er) {return handleException<QlMarkovFunctional*>(e, er);}}+QlMarkovFunctional* qlMarkovFunctionalCaplet(QlYieldTermStructure* termStructure, double reversion, unsigned volstepdatesLen, int* volstepdates, unsigned volatilitiesLen, double* volatilities, QlOptionletVolatilityStructure* capletVol, unsigned expiriesLen, int* capletExpiries, QlIborIndex* iborIndex, unsigned yGridPoints, char **e) {+  try {return ret(new QlMarkovFunctional(alloc(new MarkovFunctional(*arg(termStructure), reversion, qlDateVector(volstepdates, volstepdatesLen), std::vector<double>(volatilities, volatilities+volatilitiesLen), *arg(capletVol), qlDateVector(capletExpiries, expiriesLen), *arg(iborIndex), MarkovFunctional::ModelSettings().withYGridPoints(yGridPoints)))));+  } catch (std::exception& er) {return handleException<QlMarkovFunctional*>(e, er);}} void qlMarkovFunctionalVolatility(QlMarkovFunctional* o, unsigned *len, double **vs, char **e) {   try {Array vol = (*arg(o))->volatility(); *len = vol.size(); *vs = qlAllocateDoubles(*len); std::copy(vol.begin(), vol.end(), *vs);   } catch (std::exception& er) {handleException<double*>(e, er);}} QlPricingEngine* qlGaussian1dSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlYieldTermStructure* discountCurve, int probabilities, char **e) {   try {return ret(new QlPricingEngine(alloc(new Gaussian1dSwaptionEngine(*arg(model), integrationPoints, stddevs, extrapolatePayoff, flatPayoffExtrapolation, qlNullableHandle(discountCurve), (Gaussian1dSwaptionEngine::Probabilities)probabilities))));   } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlGaussian1dNonstandardSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlQuote* oas, QlYieldTermStructure* discountCurve, int probabilities, char **e) {+  try {return ret(new QlPricingEngine(alloc(new Gaussian1dNonstandardSwaptionEngine(*arg(model), integrationPoints, stddevs, extrapolatePayoff, flatPayoffExtrapolation, qlNullableHandle(oas), qlNullableHandle(discountCurve), (Gaussian1dNonstandardSwaptionEngine::Probabilities)probabilities))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+// As qlGaussian1dNonstandardSwaptionEngine, plus a trailing includeTodaysExercise bool before+// probabilities (gaussian1dfloatfloatswaptionengine.hpp).+QlPricingEngine* qlGaussian1dFloatFloatSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlQuote* oas, QlYieldTermStructure* discountCurve, int includeTodaysExercise, int probabilities, char **e) {+  try {return ret(new QlPricingEngine(alloc(new Gaussian1dFloatFloatSwaptionEngine(*arg(model), integrationPoints, stddevs, extrapolatePayoff, flatPayoffExtrapolation, qlNullableHandle(oas), qlNullableHandle(discountCurve), includeTodaysExercise, (Gaussian1dFloatFloatSwaptionEngine::Probabilities)probabilities))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlGaussian1dJamshidianSwaptionEngine(QlGaussian1dModel* model, char **e) {+  try {return ret(new QlPricingEngine(alloc(new Gaussian1dJamshidianSwaptionEngine(*arg(model)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}+QlPricingEngine* qlGaussian1dCapFloorEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlYieldTermStructure* discountCurve, char **e) {+  try {return ret(new QlPricingEngine(alloc(new Gaussian1dCapFloorEngine(*arg(model), integrationPoints, stddevs, extrapolatePayoff, flatPayoffExtrapolation, qlNullableHandle(discountCurve)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}  QlCalibratedModel* qlGJRGARCHModelAsCalibratedModel(QlGJRGARCHModel *o) {return ret(new QlCalibratedModel(*arg(o)));} QlCalibratedModel* qlHestonModelAsCalibratedModel(QlHestonModel *o) {return ret(new QlCalibratedModel(*arg(o)));}@@ -714,15 +790,25 @@ QlBlackCalibrationHelper* qlHestonModelHelper(int l, int u, Calendar* calendar, QlQuote* s0, double strikePrice, QlQuote* volatility, QlYieldTermStructure* riskFreeRate, QlYieldTermStructure* dividendYield, int errorType, char **e) {   try {return ret(new QlBlackCalibrationHelper(alloc(new HestonModelHelper(Period(l, (TimeUnit)u), *arg(calendar), *arg(s0), strikePrice, *arg(volatility), *arg(riskFreeRate), *arg(dividendYield), (BlackCalibrationHelper::CalibrationErrorType)errorType))));   } catch (std::exception& er) {return handleException<QlBlackCalibrationHelper*>(e, er);}}-QlBlackCalibrationHelper* qlSwaptionHelper(int l, int u, int ll, int lu, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {-  try {return ret(new QlBlackCalibrationHelper(alloc(new SwaptionHelper(Period(l, (TimeUnit)u), Period(ll, (TimeUnit)lu), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));-  } catch (std::exception& er) {return handleException<QlBlackCalibrationHelper*>(e, er);}}-QlBlackCalibrationHelper* qlSwaptionHelperFromDate(int exerciseDate, int ll, int lu, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {-  try {return ret(new QlBlackCalibrationHelper(alloc(new SwaptionHelper(Date(exerciseDate), Period(ll, (TimeUnit)lu), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));-  } catch (std::exception& er) {return handleException<QlBlackCalibrationHelper*>(e, er);}}-QlBlackCalibrationHelper* qlSwaptionHelperFromDates(int exerciseDate, int endDate, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {-  try {return ret(new QlBlackCalibrationHelper(alloc(new SwaptionHelper(Date(exerciseDate), Date(endDate), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));-  } catch (std::exception& er) {return handleException<QlBlackCalibrationHelper*>(e, er);}}+void qlFreeSwaptionHelper(QlSwaptionHelper *o) {del(o);}+QlBlackCalibrationHelper* qlSwaptionHelperAsBlackCalibrationHelper(QlSwaptionHelper *o) {return ret(new QlBlackCalibrationHelper(*arg(o)));}+QlSwaptionHelper* qlSwaptionHelper(int l, int u, int ll, int lu, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {+  try {return ret(new QlSwaptionHelper(alloc(new SwaptionHelper(Period(l, (TimeUnit)u), Period(ll, (TimeUnit)lu), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));+  } catch (std::exception& er) {return handleException<QlSwaptionHelper*>(e, er);}}+QlSwaptionHelper* qlSwaptionHelperFromDate(int exerciseDate, int ll, int lu, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {+  try {return ret(new QlSwaptionHelper(alloc(new SwaptionHelper(Date(exerciseDate), Period(ll, (TimeUnit)lu), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));+  } catch (std::exception& er) {return handleException<QlSwaptionHelper*>(e, er);}}+QlSwaptionHelper* qlSwaptionHelperFromDates(int exerciseDate, int endDate, QlQuote* volatility, QlIborIndex* index, int fl, int fu, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e) {+  try {return ret(new QlSwaptionHelper(alloc(new SwaptionHelper(Date(exerciseDate), Date(endDate), *arg(volatility), *arg(index), Period(fl, (TimeUnit)fu), *arg(fixedLegDayCounter), *arg(floatingLegDayCounter), *arg(termStructure), (BlackCalibrationHelper::CalibrationErrorType)errorType, strike, nominal, (VolatilityType)volatilityType, shift, settlementDays, (RateAveraging::Type)averagingMethod))));+  } catch (std::exception& er) {return handleException<QlSwaptionHelper*>(e, er);}}+// Both accessors are cast-free: o is already a genuine SwaptionHelper (constructed as one above),+// so underlying()/swaption() are plain method calls, not a downcast from a type-erased base.+QlFixedVsFloatingSwap* qlSwaptionHelperUnderlying(QlSwaptionHelper* o, char **e) {+  try {return ret(new QlFixedVsFloatingSwap((*arg(o))->underlying()));+  } catch (std::exception& er) {return handleException<QlFixedVsFloatingSwap*>(e, er);}}+QlSwaption* qlSwaptionHelperSwaption(QlSwaptionHelper* o, char **e) {+  try {return ret(new QlSwaption((*arg(o))->swaption()));+  } catch (std::exception& er) {return handleException<QlSwaption*>(e, er);}} void qlBlackCalibrationHelperTimes(QlBlackCalibrationHelper* o, unsigned *len, double **ts, char **e) {   try {std::list<double> times;(*arg(o))->addTimesTo(times);*len = times.size();*ts = qlAllocateDoubles(*len);std::copy(times.begin(), times.end(), *ts);   } catch (std::exception& er) {handleException<double*>(e, er);}}@@ -736,6 +822,9 @@   } catch (std::exception& er) {return handleException<double>(e, er);}} double qlBlackCalibrationHelperMarketValue(QlBlackCalibrationHelper* o, char **e) {try {return (*arg(o))->marketValue();} catch (std::exception& er) {return handleException<double>(e, er);}} double qlBlackCalibrationHelperModelValue(QlBlackCalibrationHelper* o, char **e) {try {return (*arg(o))->modelValue();} catch (std::exception& er) {return handleException<double>(e, er);}}+QlQuote* qlBlackCalibrationHelperVolatility(QlBlackCalibrationHelper* o, char **e) {+  try {return ret(new QlQuote((*arg(o))->volatility().currentLink()));+  } catch (std::exception& er) {return handleException<QlQuote*>(e, er);}}  void qlFreeStochasticProcess1D(QlStochasticProcess1D *o) {del(o);} QlStochasticProcess* qlStochasticProcess1DAsStochasticProcess(QlStochasticProcess1D *o) {return ret(new QlStochasticProcess(*arg(o)));}
cbits/qlPricingEngine.h view
@@ -5,8 +5,13 @@   QlPricingEngine* qlRiskyBondEngine(QlDefaultProbabilityTermStructure* defaultTS, double recoveryRate, QlYieldTermStructure* yieldTS, char **e);   QlPricingEngine* qlDiscountingSwapEngine(QlYieldTermStructure* discountCurve, int includeSettlementDateFlows, int settlementDate, int npvDate, char **e);   QlPricingEngine* qlDiscountingFxForwardEngine(QlYieldTermStructure* sourceCurrencyDiscountCurve, QlYieldTermStructure* targetCurrencyDiscountCurve, QlQuote* spotFx, char **e);+  QlPricingEngine* qlDiscountingConstNotionalCrossCurrencySwapEngine(Currency* domesticCcy, QlYieldTermStructure* domesticCcyDiscountCurve, Currency* foreignCcy, QlYieldTermStructure* foreignCcyDiscountCurve, QlQuote* spotFX, int includeSettlementDateFlows, int settlementDate, int npvDate, int spotFXSettleDate, char **e);   QlPricingEngine* qlCounterpartyAdjSwapEngine(QlYieldTermStructure* discountCurve, QlQuote* blackVol, QlDefaultProbabilityTermStructure* ctptyDTS, double ctptyRecoveryRate, QlDefaultProbabilityTermStructure* invstDTS, double invstRecoveryRate, char **e);   QlPricingEngine* qlAnalyticBarrierEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlAnalyticSoftBarrierEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlAnalyticSimpleChooserEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlAnalyticTwoAssetCorrelationEngine(QlGeneralizedBlackScholesProcess* process1, QlGeneralizedBlackScholesProcess* process2, QlQuote* correlation, char **e);+  QlPricingEngine* qlAnalyticWriterExtensibleOptionEngine(QlGeneralizedBlackScholesProcess* process, char **e);   QlPricingEngine* qlAnalyticPartialTimeBarrierOptionEngine(QlGeneralizedBlackScholesProcess* process, char **e);   QlPricingEngine* qlAnalyticBinaryBarrierEngine(QlGeneralizedBlackScholesProcess* process, char **e);   QlPricingEngine* qlFdBlackScholesBarrierEngine(QlGeneralizedBlackScholesProcess* process, unsigned tGrid, unsigned xGrid, unsigned dampingSteps, FdmSchemeDesc *fdScheme, int localVol, double illegalLocalVolOverwrite, char **e);@@ -27,9 +32,17 @@   QlPricingEngine* qlAnalyticDigitalAmericanEngine(QlGeneralizedBlackScholesProcess* x0, char **e);   QlPricingEngine* qlAnalyticDiscreteGeometricAveragePriceAsianEngine(QlGeneralizedBlackScholesProcess* process, char **e);   QlPricingEngine* qlAnalyticDiscreteGeometricAverageStrikeAsianEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlTurnbullWakemanAsianEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlFdBlackScholesAsianEngine(QlGeneralizedBlackScholesProcess* process, unsigned tGrid, unsigned xGrid, unsigned aGrid, FdmSchemeDesc *fdScheme, char **e);   QlPricingEngine* qlAnalyticDividendEuropeanEngine(QlGeneralizedBlackScholesProcess* x0, unsigned dividendsLen, QlDividend** dividends, char **e);   QlPricingEngine* qlAnalyticEuropeanEngine(QlGeneralizedBlackScholesProcess* x0, QlYieldTermStructure* discountCurve, char **e);   QlPricingEngine* qlAnalyticPerformanceEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlForwardEuropeanEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlForwardBaroneAdesiWhaleyEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlForwardBjerksundStenslandEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlForwardFdBlackScholesVanillaEngine(QlGeneralizedBlackScholesProcess* process, char **e);+  QlPricingEngine* qlMCForwardEuropeanBSEngine1(int rngtrait, QlGeneralizedBlackScholesProcess* process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, char **e);+  QlPricingEngine* qlAnalyticHestonForwardEuropeanEngine(QlHestonProcess* process, unsigned integrationOrder, char **e);   QlPricingEngine* qlBlackCapFloorEngine1(QlYieldTermStructure* discountCurve, QlOptionletVolatilityStructure* vol, char **e);   QlPricingEngine* qlBlackCapFloorEngine(QlYieldTermStructure* discountCurve, QlQuote* vol, DayCounter* dc, double displacement, char **e);   QlPricingEngine* qlBlackSwaptionEngine(QlYieldTermStructure* discountCurve, QlQuote* vol, DayCounter* dc, double displacement, int model, char **e);@@ -215,8 +228,8 @@   void qlFreeShortRateModel(QlShortRateModel *o);   void qlFreeAffineModel(QlAffineModel *o);   void qlFreeOneFactorAffineModel(QlOneFactorAffineModel *o);-  double qlOneFactorAffineModelDiscountBond(QlOneFactorAffineModel* o, double now, double maturity, double rate);-  double qlHullWhiteConvexityBias(double futurePrice, double t, double T, double sigma, double a);+  double qlOneFactorAffineModelDiscountBond(QlOneFactorAffineModel* o, double now, double maturity, double rate, char **e);+  double qlHullWhiteConvexityBias(double futurePrice, double t, double T, double sigma, double a, char **e);   QlAffineModel* qlHullWhiteAsAffineModel(QlHullWhite *o);   QlAffineModel* qlOneFactorAffineModelAsAffineModel(QlOneFactorAffineModel *o);   void qlFreeLiborForwardModel(QlLiborForwardModel *o);@@ -266,8 +279,13 @@   void qlGsrVolatility(QlGsr* o, unsigned *len, double **vs, char **e);   void qlGsrCalibrateVolatilitiesIterative(QlGsr* o, unsigned helpersLen, QlBlackCalibrationHelper** helpers, OptimizationMethod* method, EndCriteria* endCriteria, Constraint* constraint, unsigned weightsLen, double* weights, char **e);   QlMarkovFunctional* qlMarkovFunctional(QlYieldTermStructure* termStructure, double reversion, unsigned volstepdatesLen, int* volstepdates, unsigned volatilitiesLen, double* volatilities, QlSwaptionVolatilityStructure* swaptionVol, unsigned expiriesLen, int* swaptionExpiries, unsigned tenorsLen, int* tenorQuantity, unsigned, int* tenorUnit, QlSwapIndex* swapIndexBase, unsigned yGridPoints, char **e);+  QlMarkovFunctional* qlMarkovFunctionalCaplet(QlYieldTermStructure* termStructure, double reversion, unsigned volstepdatesLen, int* volstepdates, unsigned volatilitiesLen, double* volatilities, QlOptionletVolatilityStructure* capletVol, unsigned expiriesLen, int* capletExpiries, QlIborIndex* iborIndex, unsigned yGridPoints, char **e);   void qlMarkovFunctionalVolatility(QlMarkovFunctional* o, unsigned *len, double **vs, char **e);   QlPricingEngine* qlGaussian1dSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlYieldTermStructure* discountCurve, int probabilities, char **e);+  QlPricingEngine* qlGaussian1dNonstandardSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlQuote* oas, QlYieldTermStructure* discountCurve, int probabilities, char **e);+  QlPricingEngine* qlGaussian1dFloatFloatSwaptionEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlQuote* oas, QlYieldTermStructure* discountCurve, int includeTodaysExercise, int probabilities, char **e);+  QlPricingEngine* qlGaussian1dJamshidianSwaptionEngine(QlGaussian1dModel* model, char **e);+  QlPricingEngine* qlGaussian1dCapFloorEngine(QlGaussian1dModel* model, int integrationPoints, double stddevs, int extrapolatePayoff, int flatPayoffExtrapolation, QlYieldTermStructure* discountCurve, char **e);    QlCalibratedModel* qlGJRGARCHModelAsCalibratedModel(QlGJRGARCHModel *o);   QlCalibratedModel* qlHestonModelAsCalibratedModel(QlHestonModel *o);@@ -286,9 +304,13 @@   void qlBlackCalibrationHelperSetPricingEngine(QlBlackCalibrationHelper* o, QlPricingEngine* engine, char **e);   QlBlackCalibrationHelper* qlCapHelper(int, int, QlQuote* volatility, QlIborIndex* index, int fixedLegFrequency, DayCounter* fixedLegDayCounter, int includeFirstSwaplet, QlYieldTermStructure* termStructure, int errorType, int type, double shift, char **e);   QlBlackCalibrationHelper* qlHestonModelHelper(int, int, Calendar* calendar, QlQuote* s0, double strikePrice, QlQuote* volatility, QlYieldTermStructure* riskFreeRate, QlYieldTermStructure* dividendYield, int errorType, char **e);-  QlBlackCalibrationHelper* qlSwaptionHelper(int, int, int, int, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);-  QlBlackCalibrationHelper* qlSwaptionHelperFromDate(int exerciseDate, int, int, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);-  QlBlackCalibrationHelper* qlSwaptionHelperFromDates(int exerciseDate, int endDate, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);+  void qlFreeSwaptionHelper(QlSwaptionHelper *o);+  QlBlackCalibrationHelper* qlSwaptionHelperAsBlackCalibrationHelper(QlSwaptionHelper *o);+  QlSwaptionHelper* qlSwaptionHelper(int, int, int, int, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);+  QlSwaptionHelper* qlSwaptionHelperFromDate(int exerciseDate, int, int, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);+  QlSwaptionHelper* qlSwaptionHelperFromDates(int exerciseDate, int endDate, QlQuote* volatility, QlIborIndex* index, int, int, DayCounter* fixedLegDayCounter, DayCounter* floatingLegDayCounter, QlYieldTermStructure* termStructure, int errorType, double strike, double nominal, int volatilityType, double shift, unsigned settlementDays, int averagingMethod, char **e);+  QlFixedVsFloatingSwap* qlSwaptionHelperUnderlying(QlSwaptionHelper* o, char **e);+  QlSwaption* qlSwaptionHelperSwaption(QlSwaptionHelper* o, char **e);   void qlBlackCalibrationHelperTimes(QlBlackCalibrationHelper* o, unsigned *len, double **ts, char **e);    void qlCalibratedModelParams(QlCalibratedModel* o, unsigned *len, double** ps, char **e);@@ -297,6 +319,7 @@   double qlBlackCalibrationHelperImpliedVolatility(QlBlackCalibrationHelper* o, double targetValue, double accuracy, unsigned maxEvaluations, double minVol, double maxVol, char **e);   double qlBlackCalibrationHelperMarketValue(QlBlackCalibrationHelper* o, char **e);   double qlBlackCalibrationHelperModelValue(QlBlackCalibrationHelper* o, char **e);+  QlQuote* qlBlackCalibrationHelperVolatility(QlBlackCalibrationHelper* o, char **e);    void qlFreeBlackProcess(QlBlackProcess *o);   QlGeneralizedBlackScholesProcess* qlBlackProcessAsGeneralizedBlackScholesProcess(QlBlackProcess *o);
cbits/qlPricingEngineAux.cpp view
@@ -17,6 +17,7 @@ #include <ql/methods/montecarlo/multipathgenerator.hpp> #include <ql/experimental/exoticoptions/mchimalayaengine.hpp> #include <ql/experimental/exoticoptions/mcpagodaengine.hpp>+#include <ql/pricingengines/forward/mcforwardeuropeanbsengine.hpp>  namespace hasquant { #include "qlEnumObjects.h"@@ -239,6 +240,19 @@     return new MCDigitalEngine<LowDiscrepancy>(x0, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);   case hasquant::Ziggurat:     return new MCDigitalEngine<Ziggurat>(x0, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);+  };+  QL_FAIL("Unknown RNG "<< rngtrait);+}+PricingEngine* qlMCForwardEuropeanBSEngine1Aux(int rngtrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {+  switch (rngtrait) {+  case hasquant::PseudoRandom:+    return new MCForwardEuropeanBSEngine<PseudoRandom>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);+  case hasquant::PoissonPseudoRandom:+    return new MCForwardEuropeanBSEngine<PoissonPseudoRandom>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);+  case hasquant::LowDiscrepancy:+    return new MCForwardEuropeanBSEngine<LowDiscrepancy>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);+  case hasquant::Ziggurat:+    return new MCForwardEuropeanBSEngine<Ziggurat>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);   };   QL_FAIL("Unknown RNG "<< rngtrait); }
cbits/qlPricingEngineAux.h view
@@ -9,6 +9,7 @@ QuantLib::PricingEngine* qlMCAmericanEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, unsigned polynomOrder, QuantLib::LsmBasisSystem::PolynomialType polynomType, unsigned nCalibrationSamples, QuantLib::ext::optional<bool> antitheticVariateCalibration, unsigned seedCalibration); QuantLib::PricingEngine* qlMCBarrierEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, int isBiased, unsigned seed); QuantLib::PricingEngine* qlMCDigitalEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> x0, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed);+QuantLib::PricingEngine* qlMCForwardEuropeanBSEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed); QuantLib::PricingEngine* qlMCDiscreteArithmeticAPEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed); QuantLib::PricingEngine* qlMCDiscreteArithmeticASEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed); QuantLib::PricingEngine* qlMCDiscreteGeometricAPEngine1Aux(int rngtrait, const shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed);
cbits/qlTermStructure.cpp view
@@ -16,6 +16,11 @@ #include <ql/termstructures/volatility/sabrsmilesection.hpp> #include <ql/termstructures/volatility/sabrinterpolatedsmilesection.hpp> #include <ql/experimental/volatility/noarbsabrsmilesection.hpp>+#include <ql/experimental/volatility/blackatmvolcurve.hpp>+#include <ql/experimental/volatility/blackvolsurface.hpp>+#include <ql/experimental/volatility/abcdatmvolcurve.hpp>+#include <ql/experimental/volatility/sabrvolsurface.hpp>+#include <ql/termstructures/volatility/optionlet/optionletstripper2.hpp> #include <ql/instruments/capfloor.hpp> #include <ql/termstructures/volatility/capfloor/all.hpp> #include <ql/math/interpolations/all.hpp>@@ -38,7 +43,18 @@ #include <ql/indexes/ibor/all.hpp> #include <ql/indexes/inflation/all.hpp> #include <ql/termstructures/inflation/inflationhelpers.hpp>+#include <ql/termstructures/inflation/interpolatedyoyinflationcurve.hpp> #include <ql/indexes/equityindex.hpp>+#include <ql/experimental/commodities/commoditycurve.hpp>+#include <ql/experimental/commodities/commodityindex.hpp>+#include <ql/termstructures/volatility/inflation/yoyinflationoptionletvolatilitystructure.hpp>+#include <ql/pricingengines/inflation/inflationcapfloorengines.hpp>+#include <ql/experimental/inflation/cpicapfloortermpricesurface.hpp>+#include <ql/experimental/inflation/cpicapfloorengines.hpp>+#include <ql/termstructures/volatility/inflation/constantcpivolatility.hpp>+#include <ql/experimental/inflation/yoycapfloortermpricesurface.hpp>+#include <ql/experimental/inflation/interpolatedyoyoptionletstripper.hpp>+#include <ql/experimental/inflation/kinterpolatedyoyoptionletvolatilitysurface.hpp>  #include "qlaux.h" using namespace QuantLib;@@ -103,7 +119,7 @@   // hasquant::Abcd (InterpolationType's 7th case) has no case here -- QuantLib's Abcd   // interpolation isn't wired up to setInterpolation on this codepath; falls through to the   // default QL_FAIL below. Pre-existing gap, not something the Interpolation/Approximation TH-  // refactor (see deriveCrossEnum in QuantLib/Internal/Enum.chs) introduced or touches.+  // refactor (see deriveCrossEnum in QuantLib/Internal/Common.chs) introduced or touches.   default: QL_FAIL("Unsupported interpolation " << interpolator);   } }@@ -121,14 +137,161 @@   } } -namespace { void fillMatrixOut(const Matrix& m, unsigned* rows, unsigned* cols, unsigned* len, double** vs) {   *rows = (unsigned)m.rows(); *cols = (unsigned)m.columns(); *len = (unsigned)(m.rows() * m.columns());   *vs = qlAllocateDoubles(*len);   std::copy(m.begin(), m.end(), *vs); }++template <class I2D>+static CPICapFloorTermPriceSurface *makeCPICapFloorTermPriceSurface(+    double nominal, double baseRate, const Period &observationLag, const Calendar &cal,+    BusinessDayConvention bdc, const DayCounter &dc, const shared_ptr<ZeroInflationIndex> &zii,+    CPI::InterpolationType interpolationType, const Handle<YieldTermStructure> &yts,+    const std::vector<Rate> &cStrikes, const std::vector<Rate> &fStrikes,+    const std::vector<Period> &cfMaturities, const Matrix &cPrice, const Matrix &fPrice) {+  return new InterpolatedCPICapFloorTermPriceSurface<I2D>(nominal, baseRate, observationLag, cal, bdc,+      dc, zii, interpolationType, yts, cStrikes, fStrikes, cfMaturities, cPrice, fPrice); } +// Inner (1-D, per-maturity) interpolator dispatch, templated on the already-resolved 2-D+// (cap/floor price grid) interpolator -- mirrors qlInterpolatedZeroCurveAux's switch shape.+template <class I2D>+YoYCapFloorTermPriceSurface *makeYoYCapFloorTermPriceSurface(+    Natural fixingDays, const Period &yyLag, const shared_ptr<YoYInflationIndex>& yii,+    CPI::InterpolationType interpolation, const Handle<YieldTermStructure> &nominal,+    const DayCounter &dc, const Calendar &cal, BusinessDayConvention bdc,+    const std::vector<Rate> &cStrikes, const std::vector<Rate> &fStrikes,+    const std::vector<Period> &cfMaturities, const Matrix &cPrice, const Matrix &fPrice,+    int interpolator1D, int approximator, int approximatorArg) {+  switch (interpolator1D) {+  case hasquant::BackwardFlat:+    return new InterpolatedYoYCapFloorTermPriceSurface<I2D, BackwardFlat>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice);+  case hasquant::ForwardFlat:+    return new InterpolatedYoYCapFloorTermPriceSurface<I2D, ForwardFlat>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice);+  case hasquant::Linear:+    return new InterpolatedYoYCapFloorTermPriceSurface<I2D, Linear>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice);+  case hasquant::LogLinear:+    return new InterpolatedYoYCapFloorTermPriceSurface<I2D, LogLinear>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice);+  case hasquant::Cubic:+    switch (approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, Cubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), Cubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, Cubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), Cubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, Cubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), Cubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, Cubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), Cubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  case hasquant::LogCubic:+    switch (approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, LogCubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), LogCubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, LogCubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), LogCubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, LogCubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), LogCubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedYoYCapFloorTermPriceSurface<I2D, LogCubic>(fixingDays, yyLag, yii, interpolation, nominal, dc, cal, bdc, cStrikes, fStrikes, cfMaturities, cPrice, fPrice,+          I2D(), LogCubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  default:+    QL_FAIL("Unsupported interpolation " << interpolator1D);+  }+}++// The stripper sets the real vol on this engine as it bootstraps each strike's curve+// (interpolatedyoyoptionletstripper.hpp), so it is constructed with a deliberately null+// vol handle -- same idiom as the upstream test (inflationvolatility.cpp's testYoYPriceSurfaceToVol).+Handle<YoYOptionletVolatilitySurface> qlNullYoYOptionletVolatilitySurfaceHandle() {+  return Handle<YoYOptionletVolatilitySurface>(shared_ptr<YoYOptionletVolatilitySurface>(), false);+}++// The stripper's own internal PiecewiseYoYOptionletVolatilityCurve<Interpolator1D> always+// default-constructs its interpolator (interpolatedyoyoptionletstripper.hpp's initialize()+// never passes one) -- only the surface's own K-direction interpolator (factory1D_) takes an+// explicit instance, so only that one needs the Cubic/LogCubic approximator-specific+// construction, mirroring makeYoYCapFloorTermPriceSurface's shape above.+template <class Interpolator1D>+YoYOptionletVolatilitySurface *makeKInterpolatedYoYOptionletVolatilitySurface(+                                                                              unsigned settlementDays, const Calendar &cal, BusinessDayConvention bdc, const DayCounter &dc,+                                                                              const shared_ptr<YoYCapFloorTermPriceSurface> &capFloorPrices,+                                                                              const shared_ptr<YoYInflationCapFloorEngine> &engine,+                                                                              const shared_ptr<YoYOptionletStripper> &stripper, double slope,+                                                                              const Interpolator1D &interpolator) {+  return new KInterpolatedYoYOptionletVolatilitySurface<Interpolator1D>(+                                                                        settlementDays, cal, bdc, dc, capFloorPrices->observationLag(), capFloorPrices, engine, stripper,+                                                                        slope, interpolator);+}++YoYOptionletVolatilitySurface *dispatchKInterpolatedYoYOptionletVolatilitySurface(+                                                                                  unsigned settlementDays, const Calendar &cal, BusinessDayConvention bdc, const DayCounter &dc,+                                                                                  const shared_ptr<YoYCapFloorTermPriceSurface> &capFloorPrices,+                                                                                  const shared_ptr<YoYInflationCapFloorEngine> &engine, double slope,+                                                                                  int interpolator1D, int approximator, int approximatorArg) {+  switch (interpolator1D) {+  case hasquant::BackwardFlat:+    return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine,+                                                          shared_ptr<YoYOptionletStripper>(new InterpolatedYoYOptionletStripper<BackwardFlat>()), slope, BackwardFlat());+  case hasquant::ForwardFlat:+    return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine,+                                                          shared_ptr<YoYOptionletStripper>(new InterpolatedYoYOptionletStripper<ForwardFlat>()), slope, ForwardFlat());+  case hasquant::Linear:+    return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine,+                                                          shared_ptr<YoYOptionletStripper>(new InterpolatedYoYOptionletStripper<Linear>()), slope, Linear());+  case hasquant::LogLinear:+    return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine,+                                                          shared_ptr<YoYOptionletStripper>(new InterpolatedYoYOptionletStripper<LogLinear>()), slope, LogLinear());+  case hasquant::Cubic: {+    shared_ptr<YoYOptionletStripper> stripper(new InterpolatedYoYOptionletStripper<Cubic>());+    switch (approximator) {+    case hasquant::NaturalSpline:+      return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine, stripper, slope,+                                                            Cubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine, stripper, slope,+                                                            Cubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine, stripper, slope,+                                                            Cubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return makeKInterpolatedYoYOptionletVolatilitySurface(settlementDays, cal, bdc, dc, capFloorPrices, engine, stripper, slope,+                                                            Cubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  }+  // LogCubic is deliberately not instantiated here: unlike Cubic, QuantLib's LogCubic+  // (ql/math/interpolations/loginterpolation.hpp) has no default constructor -- its+  // DerivativeApprox parameter is required, no default value. InterpolatedYoYOptionletStripper's+  // own initialize() (interpolatedyoyoptionletstripper.hpp) builds a+  // PiecewiseYoYOptionletVolatilityCurve<Interpolator1D> via that curve's own default-arg'd+  // Interpolator1D ctor parameter -- and since that's a virtual member, instantiating+  // InterpolatedYoYOptionletStripper<LogCubic> at all (even just to hold it in a shared_ptr,+  // never calling initialize) forces the compiler to instantiate initialize() to build the+  // vtable, which fails to compile: "no matching constructor for initialization of+  // QuantLib::LogCubic". This is a real upstream restriction, not a hasquant gap -- confirmed+  // by reading loginterpolation.hpp's LogCubic ctor (no default 'da' argument, unlike Cubic's).+  case hasquant::LogCubic:+    QL_FAIL("LogCubic cannot back InterpolatedYoYOptionletStripper/KInterpolatedYoYOptionletVolatilitySurface -- "+            "see the comment above this case");+  default:+    QL_FAIL("Unsupported interpolation " << interpolator1D);+  }+}+ extern "C" { QlOptionletVolatilityStructure *qlConstantOptionletVol1(unsigned days, Calendar *cal, int conv, QlQuote *q, DayCounter *dc, int type, double displacement, char **e) {   try {return ret(new QlOptionletVolatilityStructure(shared_ptr<OptionletVolatilityStructure>(alloc(new ConstantOptionletVolatility(days, *arg(cal), (BusinessDayConvention) conv, *arg(q), *arg(dc), (VolatilityType)type, displacement)))));@@ -174,6 +337,163 @@ QlBlackVolTermStructure* qlRelinkableBlackVolTermStructureAsBlackVolTermStructure(QlRelinkableBlackVolTermStructure *o) {return ret(new QlBlackVolTermStructure(*arg(o)));} void qlFreeVolatilityTermStructure(QlVolatilityTermStructure *o) {del(o);} QlTermStructure* qlVolatilityTermStructureAsTermStructure(QlVolatilityTermStructure *o) {return ret(new QlTermStructure(*arg(o)));}+void qlFreeBlackAtmVolCurve(QlBlackAtmVolCurve *o) {del(o);}+QlVolatilityTermStructure* qlBlackAtmVolCurveAsVolatilityTermStructure(QlBlackAtmVolCurve *o) {return ret(new QlVolatilityTermStructure(handlePtr(arg(o))));}+void qlFreeBlackVolSurface(QlBlackVolSurface *o) {del(o);}+QlBlackAtmVolCurve* qlBlackVolSurfaceAsBlackAtmVolCurve(QlBlackVolSurface *o) {return ret(new QlBlackAtmVolCurve(*arg(o)));}+void qlFreeAbcdAtmVolCurve(QlAbcdAtmVolCurve *o) {del(o);}+QlBlackAtmVolCurve* qlAbcdAtmVolCurveAsBlackAtmVolCurve(QlAbcdAtmVolCurve *o) {return ret(new QlBlackAtmVolCurve(*arg(o)));}+void qlFreeSabrVolSurface(QlSabrVolSurface *o) {del(o);}+QlBlackVolSurface* qlSabrVolSurfaceAsBlackVolSurface(QlSabrVolSurface *o) {return ret(new QlBlackVolSurface(*arg(o)));}+double qlBlackAtmVolCurveAtmVolForPeriod(QlBlackAtmVolCurve* o, int n, int u, int extrapolate, char **e) {+  try {return (*arg(o))->atmVol(Period(n, (TimeUnit)u), extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlBlackAtmVolCurveAtmVolForDate(QlBlackAtmVolCurve* o, int date, int extrapolate, char **e) {+  try {return (*arg(o))->atmVol(Date(date), extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlBlackAtmVolCurveAtmVolForTime(QlBlackAtmVolCurve* o, double t, int extrapolate, char **e) {+  try {return (*arg(o))->atmVol(t, extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlBlackAtmVolCurveAtmVarianceForPeriod(QlBlackAtmVolCurve* o, int n, int u, int extrapolate, char **e) {+  try {return (*arg(o))->atmVariance(Period(n, (TimeUnit)u), extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlBlackAtmVolCurveAtmVarianceForDate(QlBlackAtmVolCurve* o, int date, int extrapolate, char **e) {+  try {return (*arg(o))->atmVariance(Date(date), extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlBlackAtmVolCurveAtmVarianceForTime(QlBlackAtmVolCurve* o, double t, int extrapolate, char **e) {+  try {return (*arg(o))->atmVariance(t, extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+QlSmileSection* qlBlackVolSurfaceSmileSectionForPeriod(QlBlackVolSurface* o, int n, int u, int extrapolate, char **e) {+  try {return ret(new QlSmileSection(alloc((*arg(o))->smileSection(Period(n, (TimeUnit)u), extrapolate))));+  } catch (std::exception& er) {return handleException<QlSmileSection*>(e, er);}}+QlSmileSection* qlBlackVolSurfaceSmileSectionForDate(QlBlackVolSurface* o, int date, int extrapolate, char **e) {+  try {return ret(new QlSmileSection(alloc((*arg(o))->smileSection(Date(date), extrapolate))));+  } catch (std::exception& er) {return handleException<QlSmileSection*>(e, er);}}+QlSmileSection* qlBlackVolSurfaceSmileSectionForTime(QlBlackVolSurface* o, double t, int extrapolate, char **e) {+  try {return ret(new QlSmileSection(alloc((*arg(o))->smileSection(t, extrapolate))));+  } catch (std::exception& er) {return handleException<QlSmileSection*>(e, er);}}+QlAbcdAtmVolCurve* qlAbcdAtmVolCurve(unsigned settlementDays, Calendar* calendar, unsigned optionTenorsLen, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, unsigned flagsLen, int *flags, int bdc, DayCounter* dc, char **e) {+  try {return ret(new QlAbcdAtmVolCurve(alloc(new AbcdAtmVolCurve(settlementDays, *arg(calendar),+              qlPeriodVector(n, u, optionTenorsLen), qlHandleVector(vols, volsLen),+              std::vector<bool>(flags, flags+flagsLen), (BusinessDayConvention)bdc, *arg(dc)))));+  } catch (std::exception& er) {return handleException<QlAbcdAtmVolCurve*>(e, er);}}+double qlAbcdAtmVolCurveA(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->a();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlAbcdAtmVolCurveB(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->b();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlAbcdAtmVolCurveC(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->c();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlAbcdAtmVolCurveD(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->d();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlAbcdAtmVolCurveRmsError(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->rmsError();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlAbcdAtmVolCurveMaxError(QlAbcdAtmVolCurve* o, char **e) {+  try {return (*arg(o))->maxError();+  } catch (std::exception& er) {return handleException<double>(e, er);}}+int qlAbcdAtmVolCurveEndCriteria(QlAbcdAtmVolCurve* o, char **e) {+  try {return (int)(*arg(o))->endCriteria();+  } catch (std::exception& er) {return handleException<int>(e, er);}}+double qlAbcdAtmVolCurveKAtTime(QlAbcdAtmVolCurve* o, double t, char **e) {+  try {return (*arg(o))->k(t);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+void qlAbcdAtmVolCurveK(QlAbcdAtmVolCurve* o, unsigned *count, double **ks, char **e) {+  try {+    std::vector<Real> k = (*arg(o))->k();+    *count = k.size(); *ks = qlAllocateDoubles(*count);+    for (size_t i = 0; i < k.size(); ++i) (*ks)[i] = k[i];+  } catch (std::exception& er) {*count = 0; *ks = 0; handleException<int>(e, er);}}+void qlAbcdAtmVolCurveOptionTenors(QlAbcdAtmVolCurve* o, unsigned *count, int **n, unsigned *count2, int **u, char **e) {+  try {+    const std::vector<Period> &p = (*arg(o))->optionTenors();+    *count = *count2 = p.size(); *n = qlAllocateInts(*count); *u = qlAllocateInts(*count);+    for (size_t i = 0; i < p.size(); ++i) {(*n)[i] = p[i].length(); (*u)[i] = (int)p[i].units();}+  } catch (std::exception& er) {*count = *count2 = 0; *n = 0; *u = 0; handleException<int>(e, er);}}+void qlAbcdAtmVolCurveOptionTenorsInInterpolation(QlAbcdAtmVolCurve* o, unsigned *count, int **n, unsigned *count2, int **u, char **e) {+  try {+    const std::vector<Period> &p = (*arg(o))->optionTenorsInInterpolation();+    *count = *count2 = p.size(); *n = qlAllocateInts(*count); *u = qlAllocateInts(*count);+    for (size_t i = 0; i < p.size(); ++i) {(*n)[i] = p[i].length(); (*u)[i] = (int)p[i].units();}+  } catch (std::exception& er) {*count = *count2 = 0; *n = 0; *u = 0; handleException<int>(e, er);}}+void qlAbcdAtmVolCurveOptionDates(QlAbcdAtmVolCurve* o, unsigned *count, int **days, char **e) {+  try {+    const std::vector<Date> &dates = (*arg(o))->optionDates();+    *count = dates.size(); *days = qlAllocateInts(*count);+    for (size_t i = 0; i < dates.size(); ++i) (*days)[i] = dates[i].serialNumber();+  } catch (std::exception& er) {*count = 0; *days = 0; handleException<int>(e, er);}}+void qlAbcdAtmVolCurveOptionTimes(QlAbcdAtmVolCurve* o, unsigned *count, double **times, char **e) {+  try {+    const std::vector<Time> &t = (*arg(o))->optionTimes();+    *count = t.size(); *times = qlAllocateDoubles(*count);+    for (size_t i = 0; i < t.size(); ++i) (*times)[i] = t[i];+  } catch (std::exception& er) {*count = 0; *times = 0; handleException<int>(e, er);}}+QlSabrVolSurface* qlSabrVolSurface(QlInterestRateIndex* index, QlBlackAtmVolCurve* atmCurve, unsigned tenorsLen, int *n, unsigned, int *u, unsigned spreadsLen, double *atmRateSpreads, unsigned volRows, unsigned volCols, QlQuote** volSpreads, char **e) {+  try {return ret(new QlSabrVolSurface(alloc(new SabrVolSurface(*arg(index), Handle<BlackAtmVolCurve>(*arg(atmCurve)),+      qlPeriodVector(n, u, tenorsLen), std::vector<Spread>(atmRateSpreads, atmRateSpreads+spreadsLen),+      qlHandleMatrix(volSpreads, volRows, volCols)))));+  } catch (std::exception& er) {return handleException<QlSabrVolSurface*>(e, er);}}+QlBlackAtmVolCurve* qlSabrVolSurfaceAtmCurve(QlSabrVolSurface* o, char **e) {+  try {return ret(new QlBlackAtmVolCurve((*arg(o))->atmCurve().currentLink()));+  } catch (std::exception& er) {return handleException<QlBlackAtmVolCurve*>(e, er);}}+void qlSabrVolSurfaceVolatilitySpreadsForPeriod(QlSabrVolSurface* o, int n, int u, unsigned *count, double **vols, char **e) {+  try {+    std::vector<Volatility> v = (*arg(o))->volatilitySpreads(Period(n, (TimeUnit)u));+    *count = v.size(); *vols = qlAllocateDoubles(*count);+    for (size_t i = 0; i < v.size(); ++i) (*vols)[i] = v[i];+  } catch (std::exception& er) {*count = 0; *vols = 0; handleException<int>(e, er);}}+void qlSabrVolSurfaceVolatilitySpreadsForDate(QlSabrVolSurface* o, int date, unsigned *count, double **vols, char **e) {+  try {+    std::vector<Volatility> v = (*arg(o))->volatilitySpreads(Date(date));+    *count = v.size(); *vols = qlAllocateDoubles(*count);+    for (size_t i = 0; i < v.size(); ++i) (*vols)[i] = v[i];+  } catch (std::exception& er) {*count = 0; *vols = 0; handleException<int>(e, er);}}+QlInterestRateIndex* qlSabrVolSurfaceIndex(QlSabrVolSurface* o, char **e) {+  try {return ret(new QlInterestRateIndex((*arg(o))->index()));+  } catch (std::exception& er) {return handleException<QlInterestRateIndex*>(e, er);}}+int qlSabrVolSurfaceOptionDateFromTenor(QlSabrVolSurface* o, int n, int u, char **e) {+  try {return (*arg(o))->optionDateFromTenor(Period(n, (TimeUnit)u)).serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}}++// OptionletStripper2 builds an OptionletStripper1 internally (never exposed to Haskell, same+// fusion as qlOptionletStripper1 above) then wraps OptionletStripper2 itself around it, keeping+// the OptionletStripper2 shared_ptr so its own diagnostic getters below are reachable with no cast.+QlOptionletStripper2* qlOptionletStripper2(QlCapFloorTermVolSurface* surface, QlIborIndex* index, double switchStrikes, double accuracy, unsigned maxIter, QlYieldTermStructure* discount, int type, double displacement, int dontThrow, int optionletFrequencyLen, int optionletFrequencyUnit, QlCapFloorTermVolCurve* atmCurve, char **e) {+  try {+    auto stripper1 = shared_ptr<OptionletStripper1>(alloc(new OptionletStripper1(*arg(surface), *arg(index),+        switchStrikes, accuracy, maxIter, qlNullableHandle(arg(discount)), (VolatilityType)type, displacement,+        (bool)dontThrow, optionletFrequencyUnit < 0 ? ext::optional<Period>() : ext::optional<Period>(Period(optionletFrequencyLen, (TimeUnit)optionletFrequencyUnit)))));+    return ret(new QlOptionletStripper2(alloc(new OptionletStripper2(stripper1, Handle<CapFloorTermVolCurve>(*arg(atmCurve))))));+  } catch (std::exception& er) {return handleException<QlOptionletStripper2*>(e, er);}}+void qlFreeOptionletStripper2(QlOptionletStripper2 *o) {del(o);}+// Fresh construction (StrippedOptionletAdapter around the OptionletStripper2 itself), never a+// cast -- same idiom as qlSabrInterpolatedSmileSectionAsSmileSection.+QlOptionletVolatilityStructure* qlOptionletStripper2AsOptionletVolatilityStructure(QlOptionletStripper2 *o, char **e) {+  try {return ret(new QlOptionletVolatilityStructure(shared_ptr<OptionletVolatilityStructure>(+      alloc(new StrippedOptionletAdapter(*arg(o))))));+  } catch (std::exception& er) {return handleException<QlOptionletVolatilityStructure*>(e, er);}}+void qlOptionletStripper2AtmCapFloorStrikes(QlOptionletStripper2* o, unsigned *count, double **vs, char **e) {+  try {+    const std::vector<Rate> &v = (*arg(o))->atmCapFloorStrikes();+    *count = v.size(); *vs = qlAllocateDoubles(*count);+    for (size_t i = 0; i < v.size(); ++i) (*vs)[i] = v[i];+  } catch (std::exception& er) {*count = 0; *vs = 0; handleException<int>(e, er);}}+void qlOptionletStripper2AtmCapFloorPrices(QlOptionletStripper2* o, unsigned *count, double **vs, char **e) {+  try {+    const std::vector<Real> &v = (*arg(o))->atmCapFloorPrices();+    *count = v.size(); *vs = qlAllocateDoubles(*count);+    for (size_t i = 0; i < v.size(); ++i) (*vs)[i] = v[i];+  } catch (std::exception& er) {*count = 0; *vs = 0; handleException<int>(e, er);}}+void qlOptionletStripper2SpreadsVol(QlOptionletStripper2* o, unsigned *count, double **vs, char **e) {+  try {+    const std::vector<Volatility> &v = (*arg(o))->spreadsVol();+    *count = v.size(); *vs = qlAllocateDoubles(*count);+    for (size_t i = 0; i < v.size(); ++i) (*vs)[i] = v[i];+  } catch (std::exception& er) {*count = 0; *vs = 0; handleException<int>(e, er);}}+ void qlFreeSwaptionVolatilityStructure(QlSwaptionVolatilityStructure *o) {del(o);} // Deliberate snapshot detach, same reasoning as qlBlackVolTermStructureAsVolatilityTermStructure. QlVolatilityTermStructure* qlSwaptionVolatilityStructureAsVolatilityTermStructure(QlSwaptionVolatilityStructure *o) {return ret(new QlVolatilityTermStructure(handlePtr(arg(o))));}@@ -366,20 +686,29 @@ double qlSwaptionVolatilityStructureVolatility(QlSwaptionVolatilityStructure* o, int n, int u, int n1, int u1, double strike, int extrapolate, char **e) {   try {return (*arg(o))->volatility(Period(n, (TimeUnit)u), Period(n1, (TimeUnit)u1), strike, extrapolate);   } catch (std::exception& er) {return handleException<double>(e, er);}}-QlVolatilityTermStructure* qlCapFloorTermVolCurve1(int settlementDate, Calendar* calendar, int bdc, unsigned l, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e) {-  try {return ret(new QlVolatilityTermStructure(alloc(new CapFloorTermVolCurve(Date(settlementDate), *arg(calendar), (BusinessDayConvention)bdc,+QlCapFloorTermVolCurve* qlCapFloorTermVolCurve1(int settlementDate, Calendar* calendar, int bdc, unsigned l, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e) {+  try {return ret(new QlCapFloorTermVolCurve(alloc(new CapFloorTermVolCurve(Date(settlementDate), *arg(calendar), (BusinessDayConvention)bdc,               qlPeriodVector(n, u, l), qlHandleVector(vols, volsLen), *arg(dc)))));-  } catch (std::exception& er) {return handleException<QlVolatilityTermStructure*>(e, er);}}-QlVolatilityTermStructure* qlCapFloorTermVolCurve(unsigned settlementDays, Calendar* calendar, int bdc, unsigned l, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e) {-  try {return ret(new QlVolatilityTermStructure(alloc(new CapFloorTermVolCurve(settlementDays, *arg(calendar), (BusinessDayConvention)bdc,+  } catch (std::exception& er) {return handleException<QlCapFloorTermVolCurve*>(e, er);}}+QlCapFloorTermVolCurve* qlCapFloorTermVolCurve(unsigned settlementDays, Calendar* calendar, int bdc, unsigned l, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e) {+  try {return ret(new QlCapFloorTermVolCurve(alloc(new CapFloorTermVolCurve(settlementDays, *arg(calendar), (BusinessDayConvention)bdc,               qlPeriodVector(n, u, l), qlHandleVector(vols, volsLen), *arg(dc)))));-  } catch (std::exception& er) {return handleException<QlVolatilityTermStructure*>(e, er);}}-QlVolatilityTermStructure* qlConstantCapFloorTermVolatility1(int referenceDate, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e) {-  try {return ret(new QlVolatilityTermStructure(alloc(new ConstantCapFloorTermVolatility(Date(referenceDate), *arg(cal), (BusinessDayConvention)bdc, *arg(volatility), *arg(dc)))));-  } catch (std::exception& er) {return handleException<QlVolatilityTermStructure*>(e, er);}}-QlVolatilityTermStructure* qlConstantCapFloorTermVolatility(unsigned settlementDays, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e) {-  try {return ret(new QlVolatilityTermStructure(alloc(new ConstantCapFloorTermVolatility(settlementDays, *arg(cal), (BusinessDayConvention)bdc, *arg(volatility), *arg(dc)))));-  } catch (std::exception& er) {return handleException<QlVolatilityTermStructure*>(e, er);}}+  } catch (std::exception& er) {return handleException<QlCapFloorTermVolCurve*>(e, er);}}+QlCapFloorTermVolatilityStructure* qlConstantCapFloorTermVolatility1(int referenceDate, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e) {+  try {return ret(new QlCapFloorTermVolatilityStructure(alloc(new ConstantCapFloorTermVolatility(Date(referenceDate), *arg(cal), (BusinessDayConvention)bdc, *arg(volatility), *arg(dc)))));+  } catch (std::exception& er) {return handleException<QlCapFloorTermVolatilityStructure*>(e, er);}}+QlCapFloorTermVolatilityStructure* qlConstantCapFloorTermVolatility(unsigned settlementDays, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e) {+  try {return ret(new QlCapFloorTermVolatilityStructure(alloc(new ConstantCapFloorTermVolatility(settlementDays, *arg(cal), (BusinessDayConvention)bdc, *arg(volatility), *arg(dc)))));+  } catch (std::exception& er) {return handleException<QlCapFloorTermVolatilityStructure*>(e, er);}}+double qlCapFloorTermVolatilityStructureVolatilityForPeriod(QlCapFloorTermVolatilityStructure* o, int n, int u, double strike, int extrapolate, char **e) {+  try {return (*arg(o))->volatility(Period(n, (TimeUnit)u), strike, extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlCapFloorTermVolatilityStructureVolatilityForDate(QlCapFloorTermVolatilityStructure* o, int date, double strike, int extrapolate, char **e) {+  try {return (*arg(o))->volatility(Date(date), strike, extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}+double qlCapFloorTermVolatilityStructureVolatilityForTime(QlCapFloorTermVolatilityStructure* o, double t, double strike, int extrapolate, char **e) {+  try {return (*arg(o))->volatility(t, strike, extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}} QlSwaptionVolatilityStructure* qlSpreadedSwaptionVolatility(QlSwaptionVolatilityStructure* x0, QlQuote* spread, char **e) {   try {return ret(new QlSwaptionVolatilityStructure(shared_ptr<SwaptionVolatilityStructure>(alloc(new SpreadedSwaptionVolatility(*arg(x0), *arg(spread))))));   } catch (std::exception& er) {return handleException<QlSwaptionVolatilityStructure*>(e, er);}}@@ -387,8 +716,33 @@   try {return ret(new QlOptionletVolatilityStructure(shared_ptr<OptionletVolatilityStructure>(alloc(new SpreadedOptionletVolatility(*arg(x0), *arg(spread))))));   } catch (std::exception& er) {return handleException<QlOptionletVolatilityStructure*>(e, er);}} +void qlFreeCapFloorTermVolatilityStructure(QlCapFloorTermVolatilityStructure *o) {del(o);}+QlVolatilityTermStructure* qlCapFloorTermVolatilityStructureAsVolatilityTermStructure(QlCapFloorTermVolatilityStructure *o) {return ret(new QlVolatilityTermStructure(*arg(o)));}+void qlFreeCapFloorTermVolCurve(QlCapFloorTermVolCurve *o) {del(o);}+QlCapFloorTermVolatilityStructure* qlCapFloorTermVolCurveAsCapFloorTermVolatilityStructure(QlCapFloorTermVolCurve *o) {return ret(new QlCapFloorTermVolatilityStructure(*arg(o)));}+void qlCapFloorTermVolCurveOptionDates(QlCapFloorTermVolCurve *o, unsigned *count, int **days) {+  const std::vector<Date> &dates = (*arg(o))->optionDates();+  *count = dates.size(); *days = qlAllocateInts(*count);+  for (size_t i = 0; i < dates.size(); ++i) (*days)[i] = dates[i].serialNumber();+}+void qlCapFloorTermVolCurveOptionTimes(QlCapFloorTermVolCurve *o, unsigned *count, double **times) {+  const std::vector<Time> &t = (*arg(o))->optionTimes();+  *count = t.size(); *times = qlAllocateDoubles(*count);+  for (size_t i = 0; i < t.size(); ++i) (*times)[i] = t[i];+}+ void qlFreeCapFloorTermVolSurface(QlCapFloorTermVolSurface *o) {del(o);}-QlVolatilityTermStructure* qlCapFloorTermVolSurfaceAsVolatilityTermStructure(QlCapFloorTermVolSurface *o) {return ret(new QlVolatilityTermStructure(*arg(o)));}+QlCapFloorTermVolatilityStructure* qlCapFloorTermVolSurfaceAsCapFloorTermVolatilityStructure(QlCapFloorTermVolSurface *o) {return ret(new QlCapFloorTermVolatilityStructure(*arg(o)));}+void qlCapFloorTermVolSurfaceOptionDates(QlCapFloorTermVolSurface *o, unsigned *count, int **days) {+  const std::vector<Date> &dates = (*arg(o))->optionDates();+  *count = dates.size(); *days = qlAllocateInts(*count);+  for (size_t i = 0; i < dates.size(); ++i) (*days)[i] = dates[i].serialNumber();+}+void qlCapFloorTermVolSurfaceOptionTimes(QlCapFloorTermVolSurface *o, unsigned *count, double **times) {+  const std::vector<Time> &t = (*arg(o))->optionTimes();+  *count = t.size(); *times = qlAllocateDoubles(*count);+  for (size_t i = 0; i < t.size(); ++i) (*times)[i] = t[i];+} void qlFreeLocalVolTermStructure(QlLocalVolTermStructure *o) {del(o);} QlVolatilityTermStructure* qlLocalVolTermStructureAsVolatilityTermStructure(QlLocalVolTermStructure *o) {return ret(new QlVolatilityTermStructure(*arg(o)));} double qlLocalVolTermStructureLocalVol(QlLocalVolTermStructure* o, int d, double underlyingLevel, int extrapolate, char **e) {@@ -659,11 +1013,12 @@   try {return ret(new QlDefaultProbabilityTermStructure(alloc(qlInterpolatedDefaultDensityCurveAux(qlDateVector(dates, datesLen), std::vector<double>(densities, densities+densitiesLen), *arg(dayCounter), *arg(calendar), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), interpolator, approximator, approximatorArg))));   } catch (std::exception& er) {return handleException<QlDefaultProbabilityTermStructure*>(e, er);}} QlDefaultProbabilityTermStructure* qlInterpolatedHazardRateCurve(unsigned datesLen, int* dates, unsigned hazardRatesLen, double* hazardRates, DayCounter* dayCounter, Calendar* cal, unsigned jumpsLen, QlQuote** jumps, unsigned jDatesLen, int* jumpDates, int interpolator, int approximator, int approximatorArg, int extrapolate, char **e) {+  DefaultProbabilityTermStructure *ts = 0;   try {-    DefaultProbabilityTermStructure *ts = qlInterpolatedHazardRateCurveAux(qlDateVector(dates, datesLen), std::vector<double>(hazardRates, hazardRates+hazardRatesLen), *arg(dayCounter), *arg(cal), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), interpolator, approximator, approximatorArg);+    ts = qlInterpolatedHazardRateCurveAux(qlDateVector(dates, datesLen), std::vector<double>(hazardRates, hazardRates+hazardRatesLen), *arg(dayCounter), *arg(cal), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), interpolator, approximator, approximatorArg);     if (extrapolate) ts->enableExtrapolation();     return ret(new QlDefaultProbabilityTermStructure(alloc(ts)));-  } catch (std::exception& er) {return handleException<QlDefaultProbabilityTermStructure*>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlDefaultProbabilityTermStructure*>(e, er);}} QlDefaultProbabilityTermStructure* qlInterpolatedSurvivalProbabilityCurve(unsigned datesLen, int* dates, unsigned probabilitiesLen, double* probabilities, DayCounter* dayCounter, Calendar* calendar, unsigned jumpsLen, QlQuote** jumps, unsigned jDatesLen, int* jumpDates, int interpolator, int approximator, int approximatorArg, char **e) {   try {return ret(new QlDefaultProbabilityTermStructure(alloc(qlInterpolatedSurvivalProbabilityCurveAux(qlDateVector(dates, datesLen), std::vector<double>(probabilities, probabilities+probabilitiesLen), *arg(dayCounter), *arg(calendar), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), interpolator, approximator, approximatorArg))));   } catch (std::exception& er) {return handleException<QlDefaultProbabilityTermStructure*>(e, er);}}@@ -679,15 +1034,17 @@             qlNullableDate(startDate), *arg(lastPeriodDayCounter), rebatesAccrual, (CreditDefaultSwap::PricingModel)model))));   } catch (std::exception& er) {return handleException<QlDefaultProbabilityHelper*>(e, er);}} QlDefaultProbabilityTermStructure* qlPiecewiseDefaultCurve(int referenceDate, unsigned instrumentsLen, QlDefaultProbabilityHelper** instruments, DayCounter* dayCounter, unsigned jumpsLen, QlQuote** jumps, unsigned jDatesLen, int* jumpDates, int trait, int interpolator, int approximator, int approximatorArg, char **e) {+  DefaultProbabilityTermStructure *ts = 0;   try {-    DefaultProbabilityTermStructure *ts = qlPiecewiseDefaultCurveAux(Date(referenceDate), qlVector(instruments, instrumentsLen), *arg(dayCounter), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), trait, interpolator, approximator, approximatorArg);+    ts = qlPiecewiseDefaultCurveAux(Date(referenceDate), qlVector(instruments, instrumentsLen), *arg(dayCounter), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), trait, interpolator, approximator, approximatorArg);     return ret(new QlDefaultProbabilityTermStructure(alloc(ts)));-  } catch (std::exception& er) {return handleException<QlDefaultProbabilityTermStructure*>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlDefaultProbabilityTermStructure*>(e, er);}} QlDefaultProbabilityTermStructure* qlPiecewiseDefaultCurve1(unsigned settlementDays, Calendar *calendar, unsigned instrumentsLen, QlDefaultProbabilityHelper** instruments, DayCounter* dayCounter, unsigned jumpsLen, QlQuote** jumps, unsigned jDatesLen, int* jumpDates, int trait, int interpolator, int approximator, int approximatorArg, char **e) {+  DefaultProbabilityTermStructure *ts = 0;   try {-    DefaultProbabilityTermStructure *ts = qlPiecewiseDefaultCurveAux1(settlementDays, *arg(calendar), qlVector(instruments, instrumentsLen), *arg(dayCounter), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), trait, interpolator, approximator, approximatorArg);+    ts = qlPiecewiseDefaultCurveAux1(settlementDays, *arg(calendar), qlVector(instruments, instrumentsLen), *arg(dayCounter), qlHandleVector(jumps, jumpsLen), qlDateVector(jumpDates, jDatesLen), trait, interpolator, approximator, approximatorArg);     return ret(new QlDefaultProbabilityTermStructure(alloc(ts)));-  } catch (std::exception& er) {return handleException<QlDefaultProbabilityTermStructure*>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlDefaultProbabilityTermStructure*>(e, er);}} double qlDefaultProbabilityTermStructureDefaultDensity1(QlDefaultProbabilityTermStructure* o, double t, int extrapolate, char **e) {   try {return (*arg(o))->defaultDensity(t, extrapolate);   } catch (std::exception& er) {return handleException<double>(e, er);}}@@ -730,6 +1087,141 @@   try {return (*arg(o))->yoyRate(Date(d), extrapolate);   } catch (std::exception& er) {return handleException<double>(e, er);}} +/* CommodityCurve */++QlCommodityCurve* qlCommodityCurve(char *name, CommodityType *commodityType, Currency *currency,+                                   UnitOfMeasure *unitOfMeasure, Calendar *calendar,+                                   unsigned datesLen, int *dates, unsigned pricesLen, double *prices,+                                   DayCounter *dayCounter, char **e) {+  try {return ret(new QlCommodityCurve(alloc(new CommodityCurve(+      arg(name), *arg(commodityType), *arg(currency), *arg(unitOfMeasure), *arg(calendar),+      qlDateVector(dates, datesLen), std::vector<Real>(prices, prices+pricesLen), *arg(dayCounter)))));+  } catch (std::exception& er) {return handleException<QlCommodityCurve*>(e, er);}}++void qlFreeCommodityCurve(QlCommodityCurve *o) {del(o);}+QlTermStructure* qlCommodityCurveAsTermStructure(QlCommodityCurve *o) {return ret(new QlTermStructure(*arg(o)));}+char *qlCommodityCurveName(QlCommodityCurve *o) {return DUP((*arg(o))->name().c_str());}+CommodityType *qlCommodityCurveCommodityType(QlCommodityCurve *o, char **e) {+  try {return ret(new CommodityType((*arg(o))->commodityType()));+  } catch (std::exception& er) {return handleException<CommodityType*>(e, er);}}+UnitOfMeasure *qlCommodityCurveUnitOfMeasure(QlCommodityCurve *o, char **e) {+  try {return ret(new UnitOfMeasure((*arg(o))->unitOfMeasure()));+  } catch (std::exception& er) {return handleException<UnitOfMeasure*>(e, er);}}+Currency *qlCommodityCurveCurrency(QlCommodityCurve *o, char **e) {+  try {return ret(new Currency((*arg(o))->currency()));+  } catch (std::exception& er) {return handleException<Currency*>(e, er);}}++void qlCommodityCurveDates(QlCommodityCurve *o, unsigned *count, int **days, char **e) {+  *count = 0; *days = 0;+  try {+    const std::vector<Date> &dates = (*arg(o))->dates();+    unsigned n = (unsigned)dates.size();+    int *ds = qlAllocateInts(n);+    for (size_t i = 0; i < dates.size(); ++i)+      ds[i] = dates[i].serialNumber();+    *count = n; *days = ds;+  } catch (std::exception& er) {*e = DUP(er.what());}+}++void qlCommodityCurvePrices(QlCommodityCurve *o, unsigned *count, double **prices, char **e) {+  *count = 0; *prices = 0;+  try {+    const std::vector<Real> &p = (*arg(o))->prices();+    unsigned n = (unsigned)p.size();+    double *ps = qlAllocateDoubles(n);+    for (size_t i = 0; i < p.size(); ++i)+      ps[i] = p[i];+    *count = n; *prices = ps;+  } catch (std::exception& er) {*e = DUP(er.what());}+}++int qlCommodityCurveEmpty(QlCommodityCurve *o) {return (*arg(o))->empty();}++// basisOfCurve_ is a nullptr shared_ptr when unset -- returned as-is (not via ret(), nothing new+// is allocated here) so the Haskell side's peekMaybeCommodityCurve can null-check it directly.+QlCommodityCurve *qlCommodityCurveBasisOfCurve(QlCommodityCurve *o) {+  const shared_ptr<CommodityCurve> &b = (*arg(o))->basisOfCurve();+  return b ? ret(new QlCommodityCurve(b)) : nullptr;+}++// Not bad_alloc-only: setBasisOfCurve() itself calls+// CommodityPricingHelper::calculateUomConversionFactor, which QL_REQUIRE-throws via+// UnitOfMeasureConversionManager::lookup when no matching conversion is registered.+void qlCommodityCurveSetBasisOfCurve(QlCommodityCurve *o, QlCommodityCurve *basisOfCurve, char **e) {+  try {(*arg(o))->setBasisOfCurve(*arg(basisOfCurve));+  } catch (std::exception& er) {*e = DUP(er.what());}+}++// Builds the ExchangeContracts map the nearby-rolling price()/underlyingPriceDate() calls take.+// Always constructed (even when n==0): price() only dereferences it when nearbyOffset>0, and+// underlyingPriceDate() requires nearbyOffset>0 too (QL_REQUIRE'd before any lower_bound call), so+// an empty-but-non-null map is exactly as safe as a null one for every reachable call shape here,+// and skips a conditional the two call sites would otherwise have to repeat.+static shared_ptr<ExchangeContracts> qlBuildExchangeContracts(+    unsigned n, int *ecKeys, char **ecCodes, int *ecExpirations, int *ecStarts, int *ecEnds) {+  auto ecs = ext::make_shared<ExchangeContracts>();+  for (unsigned i = 0; i < n; ++i)+    (*ecs)[Date(ecKeys[i])] = ExchangeContract(ecCodes[i], Date(ecExpirations[i]),+                                                Date(ecStarts[i]), Date(ecEnds[i]));+  return ecs;+}++// nearbyOffset<=0 never touches exchangeContracts (see commoditycurve.hpp's inline price()), so+// this also serves the plain flat-price case when called with an empty map and offset 0.+double qlCommodityCurvePrice(QlCommodityCurve *o, int date,+    unsigned ecLen1, int *ecKeys, unsigned, char **ecCodes,+    unsigned, int *ecExpirations, unsigned, int *ecStarts,+    unsigned, int *ecEnds, int nearbyOffset, char **e) {+  try {+    auto ecs = qlBuildExchangeContracts(ecLen1, ecKeys, ecCodes, ecExpirations, ecStarts, ecEnds);+    return (*arg(o))->price(Date(date), ecs, nearbyOffset);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++double qlCommodityCurveBasisOfPrice(QlCommodityCurve *o, int date, char **e) {+  try {return (*arg(o))->basisOfPrice(Date(date));+  } catch (std::exception& er) {return handleException<double>(e, er);}}++int qlCommodityCurveUnderlyingPriceDate(QlCommodityCurve *o, int date,+    unsigned ecLen1, int *ecKeys, unsigned, char **ecCodes,+    unsigned, int *ecExpirations, unsigned, int *ecStarts,+    unsigned, int *ecEnds, int nearbyOffset, char **e) {+  try {+    auto ecs = qlBuildExchangeContracts(ecLen1, ecKeys, ecCodes, ecExpirations, ecStarts, ecEnds);+    return (*arg(o))->underlyingPriceDate(Date(date), ecs, nearbyOffset).serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}}++/* CommodityIndex */++// exchangeContracts/nearbyOffset are hardcoded to null/0 -- see qlTermStructure.h's comment;+// forwardCurve is nullable, matching upstream's own nullable ext::shared_ptr<CommodityCurve>.+QlCommodityIndex* qlCommodityIndex(char *name, CommodityType *commodityType, Currency *currency,+                                   UnitOfMeasure *unitOfMeasure, Calendar *calendar,+                                   double lotQuantity, QlCommodityCurve *forwardCurve, char **e) {+  try {return ret(new QlCommodityIndex(alloc(new CommodityIndex(+      name, *arg(commodityType), *arg(currency), *arg(unitOfMeasure), *arg(calendar), lotQuantity,+      forwardCurve ? *arg(forwardCurve) : shared_ptr<CommodityCurve>(),+      shared_ptr<ExchangeContracts>(), 0))));+  } catch (std::exception& er) {return handleException<QlCommodityIndex*>(e, er);}}++void qlFreeCommodityIndex(QlCommodityIndex *o) {del(o);}+QlIndex* qlCommodityIndexAsIndex(QlCommodityIndex *o) {return ret(new QlIndex(*arg(o)));}++// commodityType()/currency()/unitOfMeasure()/lotQuantity()/forwardCurve() are all plain,+// never-mutated echoes of the constructor's own arguments (commodityindex.hpp's inline getters+// each just `return foo_;`) -- not bound, per CLAUDE.md's trivial-getter rule.++double qlCommodityIndexForwardPrice(QlCommodityIndex *o, int date, char **e) {+  try {return (*arg(o))->forwardPrice(Date(date));+  } catch (std::exception& er) {return handleException<double>(e, er);}}++// lastQuoteDate() -> timeSeries().lastDate(), which QL_REQUIREs a non-empty historical fixing+// series -- check emptiness first (via CommodityIndex::empty(), itself just timeSeries().empty())+// rather than catching the exception, so callers can check commodityIndexEmpty first if they want.+int qlCommodityIndexLastQuoteDate(QlCommodityIndex *o, char **e) {+  try {return (*arg(o))->lastQuoteDate().serialNumber();+  } catch (std::exception& er) {return handleException<int>(e, er);}}+int qlCommodityIndexEmpty(QlCommodityIndex *o) {return (*arg(o))->empty();}+ void qlFreeZeroCouponInflationSwapHelper(QlZeroCouponInflationSwapHelper *o) {del(o);} QlZeroCouponInflationSwapHelper* qlZeroCouponInflationSwapHelper(QlQuote* quote, int n, int u, int maturity, Calendar* calendar, int paymentConvention, DayCounter* dayCounter, QlZeroInflationIndex* zii, int observationInterpolation, int pillar, int customPillarDate, char **e) {   try {return ret(new QlZeroCouponInflationSwapHelper(alloc(new ZeroCouponInflationSwapHelper(*arg(quote), Period(n, (TimeUnit)u), Date(maturity),@@ -748,6 +1240,7 @@ QlYearOnYearInflationSwap* qlYearOnYearInflationSwapHelperSwap(QlYearOnYearInflationSwapHelper* o, char **e) {try {return ret(new QlYearOnYearInflationSwap((*arg(o))->swap()));} catch (std::exception& er) {return handleException<QlYearOnYearInflationSwap*>(e, er);}}  QlZeroInflationTermStructure* qlPiecewiseZeroInflationCurve(int referenceDate, int baseDate, int frequency, DayCounter* dayCounter, unsigned instrumentsLen, QlZeroCouponInflationSwapHelper** instruments, int interpolator, int approximator, int approximatorArg, char **e) {+  ZeroInflationTermStructure *ts = 0;   try {     // instruments[i] is shared_ptr<ZeroCouponInflationSwapHelper>*; push_back upcasts each     // element to shared_ptr<BootstrapHelper<ZeroInflationTermStructure>> (PiecewiseZeroInflationCurve's@@ -756,20 +1249,36 @@     std::vector<shared_ptr<BootstrapHelper<ZeroInflationTermStructure> > > instr;     instr.reserve(instrumentsLen);     for (unsigned i = 0; i < instrumentsLen; ++i) instr.push_back(*instruments[i]);-    ZeroInflationTermStructure *ts = qlPiecewiseZeroInflationCurveAux(Date(referenceDate), Date(baseDate), (Frequency)frequency, *arg(dayCounter),+    ts = qlPiecewiseZeroInflationCurveAux(Date(referenceDate), Date(baseDate), (Frequency)frequency, *arg(dayCounter),         instr, interpolator, approximator, approximatorArg);     return ret(new QlZeroInflationTermStructure(alloc(ts)));-  } catch (std::exception& er) {return handleException<QlZeroInflationTermStructure*>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlZeroInflationTermStructure*>(e, er);}} QlYoYInflationTermStructure* qlPiecewiseYoYInflationCurve(int referenceDate, int baseDate, double baseYoYRate, int frequency, DayCounter* dayCounter, unsigned instrumentsLen, QlYearOnYearInflationSwapHelper** instruments, int interpolator, int approximator, int approximatorArg, char **e) {+  YoYInflationTermStructure *ts = 0;   try {     std::vector<shared_ptr<BootstrapHelper<YoYInflationTermStructure> > > instr;     instr.reserve(instrumentsLen);     for (unsigned i = 0; i < instrumentsLen; ++i) instr.push_back(*instruments[i]);-    YoYInflationTermStructure *ts = qlPiecewiseYoYInflationCurveAux(Date(referenceDate), Date(baseDate), baseYoYRate, (Frequency)frequency, *arg(dayCounter),+    ts = qlPiecewiseYoYInflationCurveAux(Date(referenceDate), Date(baseDate), baseYoYRate, (Frequency)frequency, *arg(dayCounter),         instr, interpolator, approximator, approximatorArg);     return ret(new QlYoYInflationTermStructure(alloc(ts)));-  } catch (std::exception& er) {return handleException<QlYoYInflationTermStructure*>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYoYInflationTermStructure*>(e, er);}} +// InterpolatedYoYInflationCurve<Interpolator> -- direct (dates, rates) curve, unlike+// qlPiecewiseYoYInflationCurve's bootstrap from swap helpers. No seasonality (unbound elsewhere+// in hasquant).+QlYoYInflationTermStructure* qlInterpolatedYoYInflationCurve(int referenceDate,+    unsigned datesLen, int *dates, double *rates, int frequency, DayCounter *dayCounter,+    int interpolator, int approximator, int approximatorArg, char **e) {+  YoYInflationTermStructure *ts = 0;+  try {+    std::vector<Date> ds(datesLen);+    for (unsigned i = 0; i < datesLen; ++i) ds[i] = Date(dates[i]);+    ts = qlInterpolatedYoYInflationCurveAux(Date(referenceDate), ds, std::vector<Rate>(rates, rates+datesLen),+        (Frequency)frequency, *arg(dayCounter), interpolator, approximator, approximatorArg);+    return ret(new QlYoYInflationTermStructure(alloc(ts)));+  } catch (std::exception& er) {delete ts; return handleException<QlYoYInflationTermStructure*>(e, er);}}+ QlRateHelper *qlDepositRateHelper(QlQuote *quote, int l, int u, unsigned fixDays, Calendar *calendar, int conv, int eom, DayCounter *dayCount, char **e) {   try {return ret(new QlRateHelper(new DepositRateHelper( *arg(quote), Period(l, (TimeUnit)u), fixDays,           *arg(calendar), (BusinessDayConvention) conv, eom, *arg(dayCount))));@@ -837,11 +1346,12 @@  QlYieldTermStructure *qlInterpolatedCurve(curveBuilder builder, unsigned rateLen, double *rates, unsigned rateDatesLen, int *rateDates,   DayCounter *dayCount, Calendar *cal, unsigned quoteLen, QlQuote **quotes, unsigned datesLen, int *dates, int interpolator, int approximator, int approximatorArg, char **e) {+  YieldTermStructure *ts = 0;   try {-    YieldTermStructure *ts = builder(qlDateVector(rateDates, rateDatesLen), std::vector<double>(rates, rates+rateLen), *arg(dayCount), *arg(cal),+    ts = builder(qlDateVector(rateDates, rateDatesLen), std::vector<double>(rates, rates+rateLen), *arg(dayCount), *arg(cal),         qlHandleVector(quotes, quoteLen), qlDateVector(dates, datesLen), interpolator, approximator, approximatorArg);     return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure *>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYieldTermStructure *>(e, er);}} QlYieldTermStructure *qlInterpolatedDiscountCurve(unsigned dfsLen, double *dfs, unsigned dfdatesLen, int *dfsDates, DayCounter *dayCount, Calendar *cal,   unsigned quoteLen, QlQuote **quotes, unsigned datesLen, int *dates, int interpolator, int approximator, int approximatorArg, char **e) {   return qlInterpolatedCurve(&qlInterpolatedDiscountCurveAux, dfsLen, dfs, dfdatesLen, dfsDates,@@ -859,13 +1369,14 @@ } static QlYieldTermStructure *piecewiseYieldCurve1Impl(unsigned settl, Calendar *cal, unsigned rateLen, QlRateHelper **ratehelpers, DayCounter *dayCount, unsigned quoteLen,   QlQuote **quotes, unsigned datesLen, int *dates, int trait, int interpolator, int approximator, int approximatorArg, const QlIterativeBootstrapOpts& b, int extrapolate, char **e) {+  YieldTermStructure *ts = 0;   try {-    YieldTermStructure *ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),+    ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),         qlDateVector(dates, datesLen), trait, interpolator, approximator, approximatorArg, /*bootstrap=*/0, /*accuracy=*/0.0,         std::vector<double>(), b);     if (extrapolate) ts->enableExtrapolation();     return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure *>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYieldTermStructure *>(e, er);}}  QlYieldTermStructure *qlPiecewiseYieldCurve1(unsigned settl, Calendar *cal, unsigned rateLen, QlRateHelper **ratehelpers, DayCounter *dayCount, unsigned quoteLen,   QlQuote **quotes, unsigned datesLen, int *dates, int trait, int interpolator, int approximator, int approximatorArg, int extrapolate, char **e) {@@ -882,33 +1393,36 @@ } QlYieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrap1(unsigned settl, Calendar *cal, unsigned rateLen, QlRateHelper **ratehelpers, DayCounter *dayCount, unsigned quoteLen,   QlQuote **quotes, unsigned datesLen, int *dates, double accuracy, unsigned weightsLen, double *weights, int extrapolate, char **e) {+  YieldTermStructure *ts = 0;   try {-    YieldTermStructure *ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),+    ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),         qlDateVector(dates, datesLen), hasquant::Discount, hasquant::LogLinear, /*approximator=*/0, /*approximatorArg=*/0, /*bootstrap=*/1, accuracy,         std::vector<double>(weights, weights + weightsLen), defaultBootstrapOpts());     if (extrapolate) ts->enableExtrapolation();     return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure *>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYieldTermStructure *>(e, er);}}  QlYieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrap2(unsigned settl, Calendar *cal, unsigned rateLen, QlRateHelper **ratehelpers, DayCounter *dayCount, unsigned quoteLen,   QlQuote **quotes, unsigned datesLen, int *dates, double accuracy, unsigned weightsLen, double *weights, int extrapolate, char **e) {+  YieldTermStructure *ts = 0;   try {-    YieldTermStructure *ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),+    ts = qlPiecewiseYieldCurveAux1(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),         qlDateVector(dates, datesLen), hasquant::SimpleZeroYield, hasquant::Linear, /*approximator=*/0, /*approximatorArg=*/0, /*bootstrap=*/1, accuracy,         std::vector<double>(weights, weights + weightsLen), defaultBootstrapOpts());     if (extrapolate) ts->enableExtrapolation();     return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure *>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYieldTermStructure *>(e, er);}}  QlYieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrap3(unsigned settl, Calendar *cal, unsigned rateLen, QlRateHelper **ratehelpers, DayCounter *dayCount, unsigned quoteLen,   QlQuote **quotes, unsigned datesLen, int *dates, unsigned additionalRateLen, QlRateHelper **additionalRatehelpers, unsigned additionalDatesLen, int *additionalDates,   double accuracy, int extrapolate, char **e) {+  YieldTermStructure *ts = 0;   try {-    YieldTermStructure *ts = qlPiecewiseYieldCurveGlobalBootstrapFullAux(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),+    ts = qlPiecewiseYieldCurveGlobalBootstrapFullAux(settl, *arg(cal), qlVector(ratehelpers, rateLen), *arg(dayCount), qlHandleVector(quotes, quoteLen),         qlDateVector(dates, datesLen), qlVector(additionalRatehelpers, additionalRateLen), qlDateVector(additionalDates, additionalDatesLen), accuracy);     if (extrapolate) ts->enableExtrapolation();     return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure *>(e, er);}}+  } catch (std::exception& er) {delete ts; return handleException<QlYieldTermStructure *>(e, er);}}  // MultiCurve builds a set of curves that form a genuine dependency cycle -- see the class's own // doc comment in multicurve.hpp for the 4-step protocol this wraps. It is bound as a standalone@@ -1196,8 +1710,10 @@   try {return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(new ImpliedTermStructure(*arg(x0), Date(referenceDate))))));   } catch (std::exception& er) {return handleException<QlYieldTermStructure*>(e, er);}} -QlYieldTermStructure* qlPiecewiseZeroSpreadedTermStructure(QlYieldTermStructure* x0, unsigned spreadsLen, QlQuote** spreads, unsigned datesLen, int* dates, int comp, int freq, char **e) {-  try {return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(new PiecewiseZeroSpreadedTermStructure(*arg(x0), qlHandleVector(spreads, spreadsLen), qlDateVector(dates, datesLen), (Compounding)comp, (Frequency)freq)))));+QlYieldTermStructure* qlPiecewiseZeroSpreadedTermStructure(QlYieldTermStructure* x0, unsigned spreadsLen, QlQuote** spreads, unsigned datesLen, int* dates, int comp, int freq, int interpolator, int approximator, int approximatorArg, char **e) {+  try {+    YieldTermStructure *ts = qlPiecewiseZeroSpreadedTermStructureAux(qlNullableHandle(arg(x0)), qlHandleVector(spreads, spreadsLen), qlDateVector(dates, datesLen), (Compounding)comp, (Frequency)freq, interpolator, approximator, approximatorArg);+    return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(ts))));   } catch (std::exception& er) {return handleException<QlYieldTermStructure*>(e, er);}} QlYieldTermStructure* qlQuantoTermStructure(QlYieldTermStructure* underlyingDividendTS, QlYieldTermStructure* riskFreeTS, QlYieldTermStructure* foreignRiskFreeTS, QlBlackVolTermStructure* underlyingBlackVolTS, double strike, QlBlackVolTermStructure* exchRateBlackVolTS, double exchRateATMlevel, double underlyingExchRateCorrelation, char **e) {   try {return ret(new QlYieldTermStructure(shared_ptr<YieldTermStructure>(alloc(new QuantoTermStructure(*arg(underlyingDividendTS), *arg(riskFreeTS), *arg(foreignRiskFreeTS), *arg(underlyingBlackVolTS), strike, *arg(exchRateBlackVolTS), exchRateATMlevel, underlyingExchRateCorrelation)))));@@ -1437,18 +1953,9 @@   } catch (std::exception& er) {return handleException<QlEquityIndex *>(e, er);}} void qlFreeEquityIndex(QlEquityIndex *o) {del(o);} QlIndex* qlEquityIndexAsIndex(QlEquityIndex *o) {return ret(new QlIndex(*arg(o)));}-Currency* qlEquityIndexCurrency(QlEquityIndex* o, char **e) {-  try {return alloc(new Currency((*arg(o))->currency()));-  } catch (std::exception& er) {return handleException<Currency*>(e, er);}}-QlYieldTermStructure* qlEquityIndexInterestRateCurve(QlEquityIndex* o, char **e) {-  try {return ret(new QlYieldTermStructure((*arg(o))->equityInterestRateCurve().currentLink()));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure*>(e, er);}}-QlYieldTermStructure* qlEquityIndexDividendCurve(QlEquityIndex* o, char **e) {-  try {return ret(new QlYieldTermStructure((*arg(o))->equityDividendCurve().currentLink()));-  } catch (std::exception& er) {return handleException<QlYieldTermStructure*>(e, er);}}-QlQuote* qlEquityIndexSpot(QlEquityIndex* o, char **e) {-  try {return ret(new QlQuote((*arg(o))->spot().currentLink()));-  } catch (std::exception& er) {return handleException<QlQuote*>(e, er);}}+// currency()/equityInterestRateCurve()/equityDividendCurve()/spot() are all plain,+// never-mutated echoes of the constructor's own arguments (equityindex.hpp's inline getters+// each just `return foo_;`) -- not bound, per CLAUDE.md's trivial-getter rule.  typedef ZeroInflationIndex *(*makeZeroInflationIndex)(); // must match the order of qlEnumObjects.h:ZeroInflationIndexType@@ -1537,5 +2044,245 @@ double qlYoYInflationIndexFixing(QlYoYInflationIndex* o, int fixingDate, char **e) {   try {return (*arg(o))->fixing(Date(fixingDate));   } catch (std::exception& er) {return handleException<double>(e, er);}}++/* YoYOptionletVolatilitySurface */++QlYoYOptionletVolatilitySurface *qlConstantYoYOptionletVolatility(QlQuote *v, unsigned settlementDays,+    Calendar *cal, int bdc, DayCounter *dc, int observationLagLen, int observationLagUnit, int frequency,+    int indexIsInterpolated, double minStrike, double maxStrike, int volType, double displacement, char **e) {+  try {return ret(new QlYoYOptionletVolatilitySurface(Handle<YoYOptionletVolatilitySurface>(+      shared_ptr<YoYOptionletVolatilitySurface>(alloc(new ConstantYoYOptionletVolatility(*arg(v), settlementDays, *arg(cal), (BusinessDayConvention)bdc,+        *arg(dc), Period(observationLagLen, (TimeUnit)observationLagUnit), (Frequency)frequency,+        (bool)indexIsInterpolated, minStrike, maxStrike, (VolatilityType)volType, displacement))))));+  } catch (std::exception& er) {return handleException<QlYoYOptionletVolatilitySurface*>(e, er);}}++void qlFreeYoYOptionletVolatilitySurface(QlYoYOptionletVolatilitySurface *p) {del(p);}++// Deliberate snapshot detach, same reasoning as qlOptionletVolatilityStructureAsVolatilityTermStructure.+QlVolatilityTermStructure *qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure(QlYoYOptionletVolatilitySurface *o) {+  return ret(new QlVolatilityTermStructure(handlePtr(arg(o))));}++// obsLagUnit < 0 is the "use my own observationLag" sentinel, matching the C++ default+// Period(-1, Days) -- same convention as qlOptionletStripper1's optionletFrequency.+double qlYoYOptionletVolatilitySurfaceVolatility(QlYoYOptionletVolatilitySurface *o, int maturityDate,+    double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e) {+  try {return handleRef(arg(o)).volatility(Date(maturityDate), strike,+      obsLagUnit < 0 ? Period(-1, Days) : Period(obsLagLen, (TimeUnit)obsLagUnit), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++double qlYoYOptionletVolatilitySurfaceTotalVariance(QlYoYOptionletVolatilitySurface *o, int exerciseDate,+    double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e) {+  try {return handleRef(arg(o)).totalVariance(Date(exerciseDate), strike,+      obsLagUnit < 0 ? Period(-1, Days) : Period(obsLagLen, (TimeUnit)obsLagUnit), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++/* YoY inflation cap/floor pricing engines */++QlPricingEngine *qlYoYInflationBlackCapFloorEngine(QlYoYInflationIndex *index, QlYoYOptionletVolatilitySurface *vol,+    QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlPricingEngine(alloc(new YoYInflationBlackCapFloorEngine(*arg(index), *arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}++QlPricingEngine *qlYoYInflationUnitDisplacedBlackCapFloorEngine(QlYoYInflationIndex *index,+    QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlPricingEngine(alloc(new YoYInflationUnitDisplacedBlackCapFloorEngine(*arg(index), *arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}++QlPricingEngine *qlYoYInflationBachelierCapFloorEngine(QlYoYInflationIndex *index, QlYoYOptionletVolatilitySurface *vol,+    QlYieldTermStructure *nominalTs, char **e) {+  try {return ret(new QlPricingEngine(alloc(new YoYInflationBachelierCapFloorEngine(*arg(index), *arg(vol), *arg(nominalTs)))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}++/* CPICapFloorTermPriceSurface */++void qlFreeCPICapFloorTermPriceSurface(QlCPICapFloorTermPriceSurface *o) {del(o);}+QlTermStructure *qlCPICapFloorTermPriceSurfaceAsTermStructure(QlCPICapFloorTermPriceSurface *o) {+  return ret(new QlTermStructure(*arg(o)));}++QlCPICapFloorTermPriceSurface *qlCPICapFloorTermPriceSurface(double nominal, double baseRate,+    int observationLagLen, int observationLagUnit, Calendar *cal, int bdc, DayCounter *dc,+    QlZeroInflationIndex *zii, int interpolationType, QlYieldTermStructure *yts,+    unsigned cStrikesLen, double *cStrikes, unsigned fStrikesLen, double *fStrikes,+    unsigned cfMaturitiesLen, int *cfMaturitiesNum, unsigned, int *cfMaturitiesUnit,+    unsigned cPriceRows, unsigned cPriceCols, double *cPriceData,+    unsigned fPriceRows, unsigned fPriceCols, double *fPriceData,+    int interpolator2D, char **e) {+  try {+    const Period observationLag(observationLagLen, (TimeUnit)observationLagUnit);+    const std::vector<Rate> cStrikesVec(cStrikes, cStrikes+cStrikesLen);+    const std::vector<Rate> fStrikesVec(fStrikes, fStrikes+fStrikesLen);+    const std::vector<Period> cfMaturitiesVec = qlPeriodVector(cfMaturitiesNum, cfMaturitiesUnit, cfMaturitiesLen);+    const Matrix cPriceMat = qlMatrix(cPriceData, cPriceRows, cPriceCols);+    const Matrix fPriceMat = qlMatrix(fPriceData, fPriceRows, fPriceCols);+    CPICapFloorTermPriceSurface *s;+    switch (interpolator2D) {+    case hasquant::Bilinear:+      s = makeCPICapFloorTermPriceSurface<QuantLib::Bilinear>(nominal, baseRate, observationLag, *arg(cal),+          (BusinessDayConvention)bdc, *arg(dc), *arg(zii), (CPI::InterpolationType)interpolationType, *arg(yts),+          cStrikesVec, fStrikesVec, cfMaturitiesVec, cPriceMat, fPriceMat);+      break;+    case hasquant::Bicubic:+      s = makeCPICapFloorTermPriceSurface<QuantLib::Bicubic>(nominal, baseRate, observationLag, *arg(cal),+          (BusinessDayConvention)bdc, *arg(dc), *arg(zii), (CPI::InterpolationType)interpolationType, *arg(yts),+          cStrikesVec, fStrikesVec, cfMaturitiesVec, cPriceMat, fPriceMat);+      break;+    default:+      QL_FAIL("Unsupported 2-D interpolation " << interpolator2D);+    }+    return ret(new QlCPICapFloorTermPriceSurface(alloc(s)));+  } catch (std::exception& er) {return handleException<QlCPICapFloorTermPriceSurface*>(e, er);}}++/* InterpolatingCPICapFloorEngine -- the only CPICapFloor engine in QL 1.43 */++QlPricingEngine *qlInterpolatingCPICapFloorEngine(QlCPICapFloorTermPriceSurface *surface, char **e) {+  try {return ret(new QlPricingEngine(alloc(new InterpolatingCPICapFloorEngine(Handle<CPICapFloorTermPriceSurface>(*arg(surface))))));+  } catch (std::exception& er) {return handleException<QlPricingEngine*>(e, er);}}++/* CPIVolatilitySurface -- no consumer (engine/pricer) in QL 1.43, see qlaux.h/Internal.Type's own+   note; this type stands alone as a queryable surface. */++QlCPIVolatilitySurface *qlConstantCPIVolatility(QlQuote *v, unsigned settlementDays, Calendar *cal,+    int bdc, DayCounter *dc, int observationLagLen, int observationLagUnit, int frequency,+    int indexIsInterpolated, char **e) {+  try {return ret(new QlCPIVolatilitySurface(Handle<CPIVolatilitySurface>(+      shared_ptr<CPIVolatilitySurface>(alloc(new ConstantCPIVolatility(*arg(v), settlementDays, *arg(cal), (BusinessDayConvention)bdc,+        *arg(dc), Period(observationLagLen, (TimeUnit)observationLagUnit), (Frequency)frequency,+        (bool)indexIsInterpolated))))));+  } catch (std::exception& er) {return handleException<QlCPIVolatilitySurface*>(e, er);}}++void qlFreeCPIVolatilitySurface(QlCPIVolatilitySurface *p) {del(p);}++// Deliberate snapshot detach, same reasoning as qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure.+QlVolatilityTermStructure *qlCPIVolatilitySurfaceAsVolatilityTermStructure(QlCPIVolatilitySurface *o) {+  return ret(new QlVolatilityTermStructure(handlePtr(arg(o))));}++double qlCPIVolatilitySurfaceVolatility(QlCPIVolatilitySurface *o, int maturityDate,+    double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e) {+  try {return handleRef(arg(o)).volatility(Date(maturityDate), strike,+      obsLagUnit < 0 ? Period(-1, Days) : Period(obsLagLen, (TimeUnit)obsLagUnit), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++double qlCPIVolatilitySurfaceTotalVariance(QlCPIVolatilitySurface *o, int exerciseDate,+    double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e) {+  try {return handleRef(arg(o)).totalVariance(Date(exerciseDate), strike,+      obsLagUnit < 0 ? Period(-1, Days) : Period(obsLagLen, (TimeUnit)obsLagUnit), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++/* YoYCapFloorTermPriceSurface */++void qlFreeYoYCapFloorTermPriceSurface(QlYoYCapFloorTermPriceSurface *o) {del(o);}+QlTermStructure *qlYoYCapFloorTermPriceSurfaceAsTermStructure(QlYoYCapFloorTermPriceSurface *o) {+  return ret(new QlTermStructure(*arg(o)));}++QlYoYCapFloorTermPriceSurface *qlYoYCapFloorTermPriceSurface(unsigned fixingDays,+    int yyLagLen, int yyLagUnit, QlYoYInflationIndex *yii, int interpolationType,+    QlYieldTermStructure *nominal, DayCounter *dc, Calendar *cal, int bdc,+    unsigned cStrikesLen, double *cStrikes, unsigned fStrikesLen, double *fStrikes,+    unsigned cfMaturitiesLen, int *cfMaturitiesNum, unsigned, int *cfMaturitiesUnit,+    unsigned cPriceRows, unsigned cPriceCols, double *cPriceData,+    unsigned fPriceRows, unsigned fPriceCols, double *fPriceData,+    int interpolator2D, int interpolator1D, int approximator, int approximatorArg, char **e) {+  try {+    const Period yyLag(yyLagLen, (TimeUnit)yyLagUnit);+    const shared_ptr<YoYInflationIndex>& yiiRef = *arg(yii);+    const Handle<YieldTermStructure>& nominalRef = *arg(nominal);+    const std::vector<Rate> cStrikesVec(cStrikes, cStrikes+cStrikesLen);+    const std::vector<Rate> fStrikesVec(fStrikes, fStrikes+fStrikesLen);+    const std::vector<Period> cfMaturitiesVec = qlPeriodVector(cfMaturitiesNum, cfMaturitiesUnit, cfMaturitiesLen);+    const Matrix cPriceMat = qlMatrix(cPriceData, cPriceRows, cPriceCols);+    const Matrix fPriceMat = qlMatrix(fPriceData, fPriceRows, fPriceCols);+    YoYCapFloorTermPriceSurface *s;+    switch (interpolator2D) {+    case hasquant::Bilinear:+      s = makeYoYCapFloorTermPriceSurface<QuantLib::Bilinear>(fixingDays, yyLag, yiiRef, (CPI::InterpolationType)interpolationType,+          nominalRef, *arg(dc), *arg(cal), (BusinessDayConvention)bdc, cStrikesVec, fStrikesVec, cfMaturitiesVec, cPriceMat, fPriceMat,+          interpolator1D, approximator, approximatorArg);+      break;+    case hasquant::Bicubic:+      s = makeYoYCapFloorTermPriceSurface<QuantLib::Bicubic>(fixingDays, yyLag, yiiRef, (CPI::InterpolationType)interpolationType,+          nominalRef, *arg(dc), *arg(cal), (BusinessDayConvention)bdc, cStrikesVec, fStrikesVec, cfMaturitiesVec, cPriceMat, fPriceMat,+          interpolator1D, approximator, approximatorArg);+      break;+    default:+      QL_FAIL("Unsupported 2-D interpolation " << interpolator2D);+    }+    return ret(new QlYoYCapFloorTermPriceSurface(alloc(s)));+  } catch (std::exception& er) {return handleException<QlYoYCapFloorTermPriceSurface*>(e, er);}}++int qlYoYCapFloorTermPriceSurfaceBaseDate(QlYoYCapFloorTermPriceSurface *o, char **e) {+  try {return qlNullableDate((*arg(o))->baseDate());+  } catch (std::exception& er) {return handleException<int>(e, er);}}++void qlYoYCapFloorTermPriceSurfaceAtmYoYSwapDateRates(QlYoYCapFloorTermPriceSurface *o,+    unsigned *dl, int **date, unsigned *rl, double **rate) {+  *date = 0; *rate = 0;+  const auto &dr = (*arg(o))->atmYoYSwapDateRates();+  *dl = dr.first.size(); *rl = dr.second.size();+  *date = qlAllocateInts(*dl); *rate = qlAllocateDoubles(*rl);+  for (unsigned i = 0; i < *dl; ++i) (*date)[i] = dr.first[i].serialNumber();+  for (unsigned i = 0; i < *rl; ++i) (*rate)[i] = dr.second[i];+}++double qlYoYCapFloorTermPriceSurfaceAtmYoYSwapRate(QlYoYCapFloorTermPriceSurface *o, int d,+    int extrapolate, char **e) {+  try {return (*arg(o))->atmYoYSwapRate(Date(d), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++double qlYoYCapFloorTermPriceSurfaceAtmYoYRate(QlYoYCapFloorTermPriceSurface *o, int d,+    int obsLagLen, int obsLagUnit, int extrapolate, char **e) {+  try {return (*arg(o))->atmYoYRate(Date(d),+      obsLagUnit < 0 ? Period(-1, Days) : Period(obsLagLen, (TimeUnit)obsLagUnit), (bool)extrapolate);+  } catch (std::exception& er) {return handleException<double>(e, er);}}++void qlYoYCapFloorTermPriceSurfaceStrikes(QlYoYCapFloorTermPriceSurface *o, unsigned *sl, double **strike) {+  *strike = 0;+  const std::vector<Rate> &ks = (*arg(o))->strikes();+  *sl = ks.size(); *strike = qlAllocateDoubles(*sl);+  for (unsigned i = 0; i < *sl; ++i) (*strike)[i] = ks[i];+}++/* KInterpolatedYoYOptionletVolatilitySurface */++QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceBlack(+    unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+    QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+    QlYieldTermStructure *nominalTs, double slope,+    int interpolator, int approximator, int approximatorArg, char **e) {+  try {+    shared_ptr<YoYInflationCapFloorEngine> engine(new YoYInflationBlackCapFloorEngine(+        *arg(index), qlNullYoYOptionletVolatilitySurfaceHandle(), *arg(nominalTs)));+    YoYOptionletVolatilitySurface *s = dispatchKInterpolatedYoYOptionletVolatilitySurface(+        settlementDays, *arg(cal), (BusinessDayConvention)bdc, *arg(dc), *arg(capFloorPrices), engine, slope,+        interpolator, approximator, approximatorArg);+    return ret(new QlYoYOptionletVolatilitySurface(Handle<YoYOptionletVolatilitySurface>(shared_ptr<YoYOptionletVolatilitySurface>(alloc(s)))));+  } catch (std::exception& er) {return handleException<QlYoYOptionletVolatilitySurface*>(e, er);}}++QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack(+    unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+    QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+    QlYieldTermStructure *nominalTs, double slope,+    int interpolator, int approximator, int approximatorArg, char **e) {+  try {+    shared_ptr<YoYInflationCapFloorEngine> engine(new YoYInflationUnitDisplacedBlackCapFloorEngine(+        *arg(index), qlNullYoYOptionletVolatilitySurfaceHandle(), *arg(nominalTs)));+    YoYOptionletVolatilitySurface *s = dispatchKInterpolatedYoYOptionletVolatilitySurface(+        settlementDays, *arg(cal), (BusinessDayConvention)bdc, *arg(dc), *arg(capFloorPrices), engine, slope,+        interpolator, approximator, approximatorArg);+    return ret(new QlYoYOptionletVolatilitySurface(Handle<YoYOptionletVolatilitySurface>(shared_ptr<YoYOptionletVolatilitySurface>(alloc(s)))));+  } catch (std::exception& er) {return handleException<QlYoYOptionletVolatilitySurface*>(e, er);}}++QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceBachelier(+    unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+    QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+    QlYieldTermStructure *nominalTs, double slope,+    int interpolator, int approximator, int approximatorArg, char **e) {+  try {+    shared_ptr<YoYInflationCapFloorEngine> engine(new YoYInflationBachelierCapFloorEngine(+        *arg(index), qlNullYoYOptionletVolatilitySurfaceHandle(), *arg(nominalTs)));+    YoYOptionletVolatilitySurface *s = dispatchKInterpolatedYoYOptionletVolatilitySurface(+        settlementDays, *arg(cal), (BusinessDayConvention)bdc, *arg(dc), *arg(capFloorPrices), engine, slope,+        interpolator, approximator, approximatorArg);+    return ret(new QlYoYOptionletVolatilitySurface(Handle<YoYOptionletVolatilitySurface>(shared_ptr<YoYOptionletVolatilitySurface>(alloc(s)))));+  } catch (std::exception& er) {return handleException<QlYoYOptionletVolatilitySurface*>(e, er);}} } /* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
cbits/qlTermStructure.h view
@@ -11,6 +11,49 @@   QlOptionletVolatilityStructure* qlOptionletStripper1(QlCapFloorTermVolSurface* surface, QlIborIndex* index, double switchStrikes, double accuracy, unsigned maxIter, QlYieldTermStructure* discount, int type, double displacement, int dontThrow, int optionletFrequencyLen, int optionletFrequencyUnit, char **e);   void qlFreeVolatilityTermStructure(QlVolatilityTermStructure *o);   QlTermStructure* qlVolatilityTermStructureAsTermStructure(QlVolatilityTermStructure *o);+  void qlFreeBlackAtmVolCurve(QlBlackAtmVolCurve *o);+  QlVolatilityTermStructure* qlBlackAtmVolCurveAsVolatilityTermStructure(QlBlackAtmVolCurve *o);+  void qlFreeBlackVolSurface(QlBlackVolSurface *o);+  QlBlackAtmVolCurve* qlBlackVolSurfaceAsBlackAtmVolCurve(QlBlackVolSurface *o);+  void qlFreeAbcdAtmVolCurve(QlAbcdAtmVolCurve *o);+  QlBlackAtmVolCurve* qlAbcdAtmVolCurveAsBlackAtmVolCurve(QlAbcdAtmVolCurve *o);+  void qlFreeSabrVolSurface(QlSabrVolSurface *o);+  QlBlackVolSurface* qlSabrVolSurfaceAsBlackVolSurface(QlSabrVolSurface *o);+  double qlBlackAtmVolCurveAtmVolForPeriod(QlBlackAtmVolCurve* o, int n, int u, int extrapolate, char **e);+  double qlBlackAtmVolCurveAtmVolForDate(QlBlackAtmVolCurve* o, int date, int extrapolate, char **e);+  double qlBlackAtmVolCurveAtmVolForTime(QlBlackAtmVolCurve* o, double t, int extrapolate, char **e);+  double qlBlackAtmVolCurveAtmVarianceForPeriod(QlBlackAtmVolCurve* o, int n, int u, int extrapolate, char **e);+  double qlBlackAtmVolCurveAtmVarianceForDate(QlBlackAtmVolCurve* o, int date, int extrapolate, char **e);+  double qlBlackAtmVolCurveAtmVarianceForTime(QlBlackAtmVolCurve* o, double t, int extrapolate, char **e);+  QlSmileSection* qlBlackVolSurfaceSmileSectionForPeriod(QlBlackVolSurface* o, int n, int u, int extrapolate, char **e);+  QlSmileSection* qlBlackVolSurfaceSmileSectionForDate(QlBlackVolSurface* o, int date, int extrapolate, char **e);+  QlSmileSection* qlBlackVolSurfaceSmileSectionForTime(QlBlackVolSurface* o, double t, int extrapolate, char **e);+  QlAbcdAtmVolCurve* qlAbcdAtmVolCurve(unsigned settlementDays, Calendar* calendar, unsigned, int *n, unsigned, int *u, unsigned volsLen, QlQuote** vols, unsigned flagsLen, int *flags, int bdc, DayCounter* dc, char **e);+  double qlAbcdAtmVolCurveA(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveB(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveC(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveD(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveRmsError(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveMaxError(QlAbcdAtmVolCurve* o, char **e);+  int qlAbcdAtmVolCurveEndCriteria(QlAbcdAtmVolCurve* o, char **e);+  double qlAbcdAtmVolCurveKAtTime(QlAbcdAtmVolCurve* o, double t, char **e);+  void qlAbcdAtmVolCurveK(QlAbcdAtmVolCurve* o, unsigned *count, double **ks, char **e);+  void qlAbcdAtmVolCurveOptionTenors(QlAbcdAtmVolCurve* o, unsigned *count, int **n, unsigned *count2, int **u, char **e);+  void qlAbcdAtmVolCurveOptionTenorsInInterpolation(QlAbcdAtmVolCurve* o, unsigned *count, int **n, unsigned *count2, int **u, char **e);+  void qlAbcdAtmVolCurveOptionDates(QlAbcdAtmVolCurve* o, unsigned *count, int **days, char **e);+  void qlAbcdAtmVolCurveOptionTimes(QlAbcdAtmVolCurve* o, unsigned *count, double **times, char **e);+  QlSabrVolSurface* qlSabrVolSurface(QlInterestRateIndex* index, QlBlackAtmVolCurve* atmCurve, unsigned tenorsLen, int *n, unsigned, int *u, unsigned spreadsLen, double *atmRateSpreads, unsigned volRows, unsigned volCols, QlQuote** volSpreads, char **e);+  QlBlackAtmVolCurve* qlSabrVolSurfaceAtmCurve(QlSabrVolSurface* o, char **e);+  void qlSabrVolSurfaceVolatilitySpreadsForPeriod(QlSabrVolSurface* o, int n, int u, unsigned *count, double **vols, char **e);+  void qlSabrVolSurfaceVolatilitySpreadsForDate(QlSabrVolSurface* o, int date, unsigned *count, double **vols, char **e);+  QlInterestRateIndex* qlSabrVolSurfaceIndex(QlSabrVolSurface* o, char **e);+  int qlSabrVolSurfaceOptionDateFromTenor(QlSabrVolSurface* o, int n, int u, char **e);+  QlOptionletStripper2* qlOptionletStripper2(QlCapFloorTermVolSurface* surface, QlIborIndex* index, double switchStrikes, double accuracy, unsigned maxIter, QlYieldTermStructure* discount, int type, double displacement, int dontThrow, int optionletFrequencyLen, int optionletFrequencyUnit, QlCapFloorTermVolCurve* atmCurve, char **e);+  void qlFreeOptionletStripper2(QlOptionletStripper2 *o);+  QlOptionletVolatilityStructure* qlOptionletStripper2AsOptionletVolatilityStructure(QlOptionletStripper2 *o, char **e);+  void qlOptionletStripper2AtmCapFloorStrikes(QlOptionletStripper2* o, unsigned *count, double **vs, char **e);+  void qlOptionletStripper2AtmCapFloorPrices(QlOptionletStripper2* o, unsigned *count, double **vs, char **e);+  void qlOptionletStripper2SpreadsVol(QlOptionletStripper2* o, unsigned *count, double **vs, char **e);   void qlFreeBlackVolTermStructure(QlBlackVolTermStructure *o);   QlVolatilityTermStructure* qlBlackVolTermStructureAsVolatilityTermStructure(QlBlackVolTermStructure *o);   QlRelinkableBlackVolTermStructure* qlRelinkableBlackVolTermStructure(QlBlackVolTermStructure *initial, char **e);@@ -71,15 +114,27 @@   double qlSwaptionVolatilityStructureVolatility4(QlSwaptionVolatilityStructure* o, int optionDate, double swapLength, double strike, int extrapolate, char **e);   double qlSwaptionVolatilityStructureVolatility5(QlSwaptionVolatilityStructure* o, double optionTime, double swapLength, double strike, int extrapolate, char **e);   double qlSwaptionVolatilityStructureVolatility(QlSwaptionVolatilityStructure* o, int, int, int, int, double strike, int extrapolate, char **e);-  QlVolatilityTermStructure* qlCapFloorTermVolCurve1(int settlementDate, Calendar* calendar, int bdc, unsigned, int*, unsigned, int*, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e);-  QlVolatilityTermStructure* qlCapFloorTermVolCurve(unsigned settlementDays, Calendar* calendar, int bdc, unsigned, int*, unsigned, int*, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e);-  QlVolatilityTermStructure* qlConstantCapFloorTermVolatility1(int referenceDate, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e);-  QlVolatilityTermStructure* qlConstantCapFloorTermVolatility(unsigned settlementDays, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e);+  QlCapFloorTermVolCurve* qlCapFloorTermVolCurve1(int settlementDate, Calendar* calendar, int bdc, unsigned, int*, unsigned, int*, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e);+  QlCapFloorTermVolCurve* qlCapFloorTermVolCurve(unsigned settlementDays, Calendar* calendar, int bdc, unsigned, int*, unsigned, int*, unsigned volsLen, QlQuote** vols, DayCounter* dc, char **e);+  QlCapFloorTermVolatilityStructure* qlConstantCapFloorTermVolatility1(int referenceDate, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e);+  QlCapFloorTermVolatilityStructure* qlConstantCapFloorTermVolatility(unsigned settlementDays, Calendar* cal, int bdc, QlQuote* volatility, DayCounter* dc, char **e);   QlSwaptionVolatilityStructure* qlSpreadedSwaptionVolatility(QlSwaptionVolatilityStructure* x0, QlQuote* spread, char **e);   QlOptionletVolatilityStructure* qlSpreadedOptionletVolatility(QlOptionletVolatilityStructure* x0, QlQuote* spread, char **e); +  void qlFreeCapFloorTermVolatilityStructure(QlCapFloorTermVolatilityStructure *o);+  QlVolatilityTermStructure* qlCapFloorTermVolatilityStructureAsVolatilityTermStructure(QlCapFloorTermVolatilityStructure *o);+  double qlCapFloorTermVolatilityStructureVolatilityForPeriod(QlCapFloorTermVolatilityStructure* o, int n, int u, double strike, int extrapolate, char **e);+  double qlCapFloorTermVolatilityStructureVolatilityForDate(QlCapFloorTermVolatilityStructure* o, int date, double strike, int extrapolate, char **e);+  double qlCapFloorTermVolatilityStructureVolatilityForTime(QlCapFloorTermVolatilityStructure* o, double t, double strike, int extrapolate, char **e);+  void qlFreeCapFloorTermVolCurve(QlCapFloorTermVolCurve *o);+  QlCapFloorTermVolatilityStructure* qlCapFloorTermVolCurveAsCapFloorTermVolatilityStructure(QlCapFloorTermVolCurve *o);+  void qlCapFloorTermVolCurveOptionDates(QlCapFloorTermVolCurve *o, unsigned *count, int **days);+  void qlCapFloorTermVolCurveOptionTimes(QlCapFloorTermVolCurve *o, unsigned *count, double **times);+   void qlFreeCapFloorTermVolSurface(QlCapFloorTermVolSurface *o);-  QlVolatilityTermStructure* qlCapFloorTermVolSurfaceAsVolatilityTermStructure(QlCapFloorTermVolSurface *o);+  QlCapFloorTermVolatilityStructure* qlCapFloorTermVolSurfaceAsCapFloorTermVolatilityStructure(QlCapFloorTermVolSurface *o);+  void qlCapFloorTermVolSurfaceOptionDates(QlCapFloorTermVolSurface *o, unsigned *count, int **days);+  void qlCapFloorTermVolSurfaceOptionTimes(QlCapFloorTermVolSurface *o, unsigned *count, double **times);   void qlFreeLocalVolTermStructure(QlLocalVolTermStructure *o);   QlVolatilityTermStructure* qlLocalVolTermStructureAsVolatilityTermStructure(QlLocalVolTermStructure *o);   double qlLocalVolTermStructureLocalVol(QlLocalVolTermStructure* o, int d, double underlyingLevel, int extrapolate, char **e);@@ -182,6 +237,51 @@   QlTermStructure* qlYoYInflationTermStructureAsTermStructure(QlYoYInflationTermStructure *o);   double qlYoYInflationTermStructureYoYRate(QlYoYInflationTermStructure* o, int d, int extrapolate, char **e); +  /* CommodityCurve -- a plain TermStructure leaf, per qlaux.h's QlCommodityCurve comment. */+  QlCommodityCurve* qlCommodityCurve(char *name, CommodityType *commodityType, Currency *currency,+                                     UnitOfMeasure *unitOfMeasure, Calendar *calendar,+                                     unsigned datesLen, int *dates, unsigned pricesLen, double *prices,+                                     DayCounter *dayCounter, char **e);+  void qlFreeCommodityCurve(QlCommodityCurve *o);+  QlTermStructure* qlCommodityCurveAsTermStructure(QlCommodityCurve *o);+  char *qlCommodityCurveName(QlCommodityCurve *o);+  CommodityType *qlCommodityCurveCommodityType(QlCommodityCurve *o, char **e);+  UnitOfMeasure *qlCommodityCurveUnitOfMeasure(QlCommodityCurve *o, char **e);+  Currency *qlCommodityCurveCurrency(QlCommodityCurve *o, char **e);+  void qlCommodityCurveDates(QlCommodityCurve *o, unsigned *count, int **days, char **e);+  void qlCommodityCurvePrices(QlCommodityCurve *o, unsigned *count, double **prices, char **e);+  int qlCommodityCurveEmpty(QlCommodityCurve *o);+  QlCommodityCurve *qlCommodityCurveBasisOfCurve(QlCommodityCurve *o);+  void qlCommodityCurveSetBasisOfCurve(QlCommodityCurve *o, QlCommodityCurve *basisOfCurve, char **e);+  /* Full price()/underlyingPriceDate() signature, threading a real ExchangeContracts map (as 5+     parallel arrays -- map key, code, expirationDate, underlyingStartDate, underlyingEndDate --+     per the "c2hs's & caps at 2" precedent already used for Quantity's 3 flat args) and a+     nearbyOffset through to upstream. nearbyOffset<=0 with an empty map reproduces the old+     flat-price call exactly, since exchangeContracts is never touched on that branch. */+  double qlCommodityCurvePrice(QlCommodityCurve *o, int date,+      unsigned ecLen1, int *ecKeys, unsigned ecLen2, char **ecCodes,+      unsigned ecLen3, int *ecExpirations, unsigned ecLen4, int *ecStarts,+      unsigned ecLen5, int *ecEnds, int nearbyOffset, char **e);+  double qlCommodityCurveBasisOfPrice(QlCommodityCurve *o, int date, char **e);+  int qlCommodityCurveUnderlyingPriceDate(QlCommodityCurve *o, int date,+      unsigned ecLen1, int *ecKeys, unsigned ecLen2, char **ecCodes,+      unsigned ecLen3, int *ecExpirations, unsigned ecLen4, int *ecStarts,+      unsigned ecLen5, int *ecEnds, int nearbyOffset, char **e);++  /* CommodityIndex -- an Index leaf, per qlaux.h's QlCommodityIndex comment. The+     ExchangeContracts/nearbyOffset constructor args are not exposed (see Stage 3's+     CommodityCurve::price binding note): a null exchangeContracts + nearbyOffset 0 are passed+     to upstream, which is exactly the branch forwardPrice's own price() call never varies on+     exchangeContracts for. */+  QlCommodityIndex* qlCommodityIndex(char *name, CommodityType *commodityType, Currency *currency,+                                     UnitOfMeasure *unitOfMeasure, Calendar *calendar,+                                     double lotQuantity, QlCommodityCurve *forwardCurve, char **e);+  void qlFreeCommodityIndex(QlCommodityIndex *o);+  QlIndex* qlCommodityIndexAsIndex(QlCommodityIndex *o);+  double qlCommodityIndexForwardPrice(QlCommodityIndex *o, int date, char **e);+  int qlCommodityIndexLastQuoteDate(QlCommodityIndex *o, char **e);+  int qlCommodityIndexEmpty(QlCommodityIndex *o);+   void qlFreeZeroCouponInflationSwapHelper(QlZeroCouponInflationSwapHelper *o);   QlZeroCouponInflationSwapHelper* qlZeroCouponInflationSwapHelper(QlQuote* quote, int, int, int maturity, Calendar* calendar, int paymentConvention, DayCounter* dayCounter, QlZeroInflationIndex* zii, int observationInterpolation, int pillar, int customPillarDate, char **e);   void qlFreeYearOnYearInflationSwapHelper(QlYearOnYearInflationSwapHelper *o);@@ -191,6 +291,8 @@    QlZeroInflationTermStructure* qlPiecewiseZeroInflationCurve(int referenceDate, int baseDate, int frequency, DayCounter* dayCounter, unsigned instrumentsLen, QlZeroCouponInflationSwapHelper** instruments, int interpolator, int approximator, int approximatorArg, char **e);   QlYoYInflationTermStructure* qlPiecewiseYoYInflationCurve(int referenceDate, int baseDate, double baseYoYRate, int frequency, DayCounter* dayCounter, unsigned instrumentsLen, QlYearOnYearInflationSwapHelper** instruments, int interpolator, int approximator, int approximatorArg, char **e);+  QlYoYInflationTermStructure* qlInterpolatedYoYInflationCurve(int referenceDate, unsigned datesLen, int *dates, double *rates, int frequency, DayCounter* dayCounter,+      int interpolator, int approximator, int approximatorArg, char **e);    QlRateHelper *qlDepositRateHelper(QlQuote *quote, int, int, unsigned fixDays, Calendar *calendar, int conv, int eom, DayCounter *dayCount, char **e);   QlBondHelper *qlFixedRateBondHelper(QlQuote *quote, unsigned settlDays, double face, Schedule *sched, unsigned cLen, double *coupons, DayCounter *dayCount, int conv, double redemption, int issue, char **e);@@ -313,7 +415,7 @@   void qlFreeTermStructure(QlTermStructure *o);   QlTermStructure* qlYieldTermStructureAsTermStructure(QlYieldTermStructure *o);   QlYieldTermStructure* qlImpliedTermStructure(QlYieldTermStructure* x0, int referenceDate, char **e);-  QlYieldTermStructure* qlPiecewiseZeroSpreadedTermStructure(QlYieldTermStructure* x0, unsigned spreadsLen, QlQuote** spreads, unsigned datesLen, int* dates, int comp, int freq, char **e);+  QlYieldTermStructure* qlPiecewiseZeroSpreadedTermStructure(QlYieldTermStructure* x0, unsigned spreadsLen, QlQuote** spreads, unsigned datesLen, int* dates, int comp, int freq, int interpolator, int approximator, int approximatorArg, char **e);   QlYieldTermStructure* qlQuantoTermStructure(QlYieldTermStructure* underlyingDividendTS, QlYieldTermStructure* riskFreeTS, QlYieldTermStructure* foreignRiskFreeTS, QlBlackVolTermStructure* underlyingBlackVolTS, double strike, QlBlackVolTermStructure* exchRateBlackVolTS, double exchRateATMlevel, double underlyingExchRateCorrelation, char **e);   QlYieldTermStructure* qlUltimateForwardTermStructure(QlYieldTermStructure* x0, QlQuote* lastLiquidForwardRate, QlQuote* ultimateForwardRate, int fspLen, int fspUnit, double alpha, int roundingDigits, int compounding, int frequency, char **e);   QlYieldTermStructure* qlInterpolatedSpreadDiscountCurve(QlYieldTermStructure* baseCurve, unsigned dfsLen, double *dfs, unsigned datesLen, int *dates, int interpolator, int approximator, int approximatorArg, char **e);@@ -372,10 +474,6 @@   QlEquityIndex *qlEquityIndex(char *name, Calendar *fixingCalendar, Currency *ccy, QlYieldTermStructure *interest, QlYieldTermStructure *dividend, QlQuote *spot, char **e);   void qlFreeEquityIndex(QlEquityIndex *o);   QlIndex* qlEquityIndexAsIndex(QlEquityIndex *o);-  Currency* qlEquityIndexCurrency(QlEquityIndex* o, char **e);-  QlYieldTermStructure* qlEquityIndexInterestRateCurve(QlEquityIndex* o, char **e);-  QlYieldTermStructure* qlEquityIndexDividendCurve(QlEquityIndex* o, char **e);-  QlQuote* qlEquityIndexSpot(QlEquityIndex* o, char **e);    QlZeroInflationIndex *qlCreateZeroInflationIndex(int index, char **e);   QlYoYInflationIndex *qlCreateYoYInflationIndex(int index, char **e);@@ -400,6 +498,98 @@    double qlZeroInflationIndexFixing(QlZeroInflationIndex* o, int fixingDate, char **e);   double qlYoYInflationIndexFixing(QlYoYInflationIndex* o, int fixingDate, char **e);++  /* YoYOptionletVolatilitySurface */+  QlYoYOptionletVolatilitySurface *qlConstantYoYOptionletVolatility(QlQuote *v, unsigned settlementDays,+      Calendar *cal, int bdc, DayCounter *dc, int observationLagLen, int observationLagUnit, int frequency,+      int indexIsInterpolated, double minStrike, double maxStrike, int volType, double displacement, char **e);+  void qlFreeYoYOptionletVolatilitySurface(QlYoYOptionletVolatilitySurface *p);+  QlVolatilityTermStructure *qlYoYOptionletVolatilitySurfaceAsVolatilityTermStructure(QlYoYOptionletVolatilitySurface *o);+  double qlYoYOptionletVolatilitySurfaceVolatility(QlYoYOptionletVolatilitySurface *o, int maturityDate,+      double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e);+  double qlYoYOptionletVolatilitySurfaceTotalVariance(QlYoYOptionletVolatilitySurface *o, int exerciseDate,+      double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e);++  /* YoY inflation cap/floor pricing engines -- all three share the same ctor shape+     (index, vol surface handle, nominal discount curve handle). */+  QlPricingEngine *qlYoYInflationBlackCapFloorEngine(QlYoYInflationIndex *index, QlYoYOptionletVolatilitySurface *vol,+      QlYieldTermStructure *nominalTs, char **e);+  QlPricingEngine *qlYoYInflationUnitDisplacedBlackCapFloorEngine(QlYoYInflationIndex *index,+      QlYoYOptionletVolatilitySurface *vol, QlYieldTermStructure *nominalTs, char **e);+  QlPricingEngine *qlYoYInflationBachelierCapFloorEngine(QlYoYInflationIndex *index, QlYoYOptionletVolatilitySurface *vol,+      QlYieldTermStructure *nominalTs, char **e);++  /* CPICapFloorTermPriceSurface */+  QlCPICapFloorTermPriceSurface *qlCPICapFloorTermPriceSurface(double nominal, double baseRate,+      int observationLagLen, int observationLagUnit, Calendar *cal, int bdc, DayCounter *dc,+      QlZeroInflationIndex *zii, int interpolationType, QlYieldTermStructure *yts,+      unsigned cStrikesLen, double *cStrikes, unsigned fStrikesLen, double *fStrikes,+      unsigned cfMaturitiesLen, int *cfMaturitiesNum, unsigned, int *cfMaturitiesUnit,+      unsigned cPriceRows, unsigned cPriceCols, double *cPriceData,+      unsigned fPriceRows, unsigned fPriceCols, double *fPriceData,+      int interpolator2D, char **e);+  void qlFreeCPICapFloorTermPriceSurface(QlCPICapFloorTermPriceSurface *o);+  QlTermStructure *qlCPICapFloorTermPriceSurfaceAsTermStructure(QlCPICapFloorTermPriceSurface *o);++  /* The only CPICapFloor pricing engine in QL 1.43: prices purely by interpolating a price+     surface, no stochastic-vol model (see plan Item 3's note on the CPI/YoY asymmetry). */+  QlPricingEngine *qlInterpolatingCPICapFloorEngine(QlCPICapFloorTermPriceSurface *surface, char **e);++  /* CPIVolatilitySurface -- no consumer (engine/pricer) in QL 1.43, see this type's own haddock+     in QuantLib.Internal.Type; stands alone as a queryable surface. */+  QlCPIVolatilitySurface *qlConstantCPIVolatility(QlQuote *v, unsigned settlementDays, Calendar *cal,+      int bdc, DayCounter *dc, int observationLagLen, int observationLagUnit, int frequency,+      int indexIsInterpolated, char **e);+  void qlFreeCPIVolatilitySurface(QlCPIVolatilitySurface *p);+  QlVolatilityTermStructure *qlCPIVolatilitySurfaceAsVolatilityTermStructure(QlCPIVolatilitySurface *o);+  double qlCPIVolatilitySurfaceVolatility(QlCPIVolatilitySurface *o, int maturityDate,+      double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e);+  double qlCPIVolatilitySurfaceTotalVariance(QlCPIVolatilitySurface *o, int exerciseDate,+      double strike, int obsLagLen, int obsLagUnit, int extrapolate, char **e);++  /* YoYCapFloorTermPriceSurface */+  QlYoYCapFloorTermPriceSurface *qlYoYCapFloorTermPriceSurface(unsigned fixingDays,+      int yyLagLen, int yyLagUnit, QlYoYInflationIndex *yii, int interpolationType,+      QlYieldTermStructure *nominal, DayCounter *dc, Calendar *cal, int bdc,+      unsigned cStrikesLen, double *cStrikes, unsigned fStrikesLen, double *fStrikes,+      unsigned cfMaturitiesLen, int *cfMaturitiesNum, unsigned, int *cfMaturitiesUnit,+      unsigned cPriceRows, unsigned cPriceCols, double *cPriceData,+      unsigned fPriceRows, unsigned fPriceCols, double *fPriceData,+      int interpolator2D, int interpolator1D, int approximator, int approximatorArg, char **e);+  void qlFreeYoYCapFloorTermPriceSurface(QlYoYCapFloorTermPriceSurface *o);+  QlTermStructure *qlYoYCapFloorTermPriceSurfaceAsTermStructure(QlYoYCapFloorTermPriceSurface *o);+  int qlYoYCapFloorTermPriceSurfaceBaseDate(QlYoYCapFloorTermPriceSurface *o, char **e);+  void qlYoYCapFloorTermPriceSurfaceAtmYoYSwapDateRates(QlYoYCapFloorTermPriceSurface *o,+      unsigned *dl, int **date, unsigned *rl, double **rate);+  double qlYoYCapFloorTermPriceSurfaceAtmYoYSwapRate(QlYoYCapFloorTermPriceSurface *o, int d,+      int extrapolate, char **e);+  double qlYoYCapFloorTermPriceSurfaceAtmYoYRate(QlYoYCapFloorTermPriceSurface *o, int d,+      int obsLagLen, int obsLagUnit, int extrapolate, char **e);+  void qlYoYCapFloorTermPriceSurfaceStrikes(QlYoYCapFloorTermPriceSurface *o, unsigned *sl, double **strike);++  /* KInterpolatedYoYOptionletVolatilitySurface<Linear> -- another concrete leaf constructor for+     YoYOptionletVolatilitySurface (Item 1), built by internally wiring up an+     InterpolatedYoYOptionletStripper<Linear> and one of the 3 YoYInflationCapFloorEngine+     descendants (constructed here with a null vol handle -- the stripper sets the real vol as+     it bootstraps each strike's curve, see interpolatedyoyoptionletstripper.hpp). Neither the+     stripper nor the per-strike PiecewiseYoYOptionletVolatilityCurve/YoYOptionletHelper it+     builds internally are ever exposed: nothing in upstream reaches them from outside+     YoYOptionletStripper::initialize, so there is nothing for a Haskell binding to return. */+  QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceBlack(+      unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+      QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+      QlYieldTermStructure *nominalTs, double slope,+      int interpolator, int approximator, int approximatorArg, char **e);+  QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack(+      unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+      QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+      QlYieldTermStructure *nominalTs, double slope,+      int interpolator, int approximator, int approximatorArg, char **e);+  QlYoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceBachelier(+      unsigned settlementDays, Calendar *cal, int bdc, DayCounter *dc,+      QlYoYCapFloorTermPriceSurface *capFloorPrices, QlYoYInflationIndex *index,+      QlYieldTermStructure *nominalTs, double slope,+      int interpolator, int approximator, int approximatorArg, char **e); #ifdef __cplusplus } #endif
cbits/qlTermStructureAux.cpp view
@@ -14,7 +14,6 @@ // spelling out its own `new PiecewiseYieldCurve<Trait, Interp>(...)` argument list -- which is // why adding a bootstrap argument prompted the factoring. Shape borrowed from QuantLib-SWIG's // make_bootstrap<Curve>() (SWIG/piecewiseyieldcurve.i).-namespace {  // Spelled CurveType::bootstrap_type, not IterativeBootstrap<CurveType>, for the same // [temp.inst] reason spelled out on the GlobalBootstrap branch further down -- see that@@ -85,8 +84,6 @@   } } -}- // Upstream QuantLib-SWIG's canned-functor GlobalBootstrap construction (SWIG/piecewiseyieldcurve.i // :186-282's AdditionalErrors/AdditionalDates), confirmed to compile against both clang and // g++-16 by an earlier standalone spike (see README's # TODO). AdditionalErrors is a fixed linear-@@ -95,7 +92,6 @@ // trait-independent (Traits::helper is BootstrapHelper<YieldTermStructure> == RateHelper for // every trait this file dispatches, per ratehelpers.hpp/bootstraptraits.hpp), so they live here // once rather than duplicated per trait x interpolator combination that ends up using them.-namespace {  class AdditionalErrors {   std::vector<shared_ptr<RateHelper> > additionalHelpers_;@@ -121,8 +117,6 @@   std::vector<Date> operator()() const { return additionalDates_; } }; -}- // PiecewiseYieldCurve<SimpleZeroYield, Linear, GlobalBootstrap> built via GlobalBootstrap's // functor-callback constructor, taking additionalHelpers/additionalDates and constructing // AdditionalErrors/AdditionalDates internally -- the same GlobalLinearSimpleZeroCurve combination@@ -437,6 +431,60 @@   } } +YieldTermStructure *qlPiecewiseZeroSpreadedTermStructureAux(+    const Handle<YieldTermStructure>& baseCurve,+    const std::vector<Handle<Quote> >& spreads,+    const std::vector<Date>& dates,+    Compounding comp, Frequency freq,+    int interpolator, int approximator, int approximatorArg) {+  switch (interpolator) {+  case hasquant::BackwardFlat:+    return new InterpolatedPiecewiseZeroSpreadedTermStructure<BackwardFlat>(baseCurve, spreads, dates, comp, freq);+  case hasquant::ForwardFlat:+    return new InterpolatedPiecewiseZeroSpreadedTermStructure<ForwardFlat>(baseCurve, spreads, dates, comp, freq);+  case hasquant::Linear:+    return new InterpolatedPiecewiseZeroSpreadedTermStructure<Linear>(baseCurve, spreads, dates, comp, freq);+  case hasquant::LogLinear:+    return new InterpolatedPiecewiseZeroSpreadedTermStructure<LogLinear>(baseCurve, spreads, dates, comp, freq);+  case hasquant::Cubic:+    switch (approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<Cubic>(baseCurve, spreads, dates, comp, freq,+          Cubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<Cubic>(baseCurve, spreads, dates, comp, freq,+          Cubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<Cubic>(baseCurve, spreads, dates, comp, freq,+          Cubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<Cubic>(baseCurve, spreads, dates, comp, freq,+          Cubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  case hasquant::LogCubic:+    switch(approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<LogCubic>(baseCurve, spreads, dates, comp, freq,+          LogCubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<LogCubic>(baseCurve, spreads, dates, comp, freq,+          LogCubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<LogCubic>(baseCurve, spreads, dates, comp, freq,+          LogCubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedPiecewiseZeroSpreadedTermStructure<LogCubic>(baseCurve, spreads, dates, comp, freq,+          LogCubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  default:+    QL_FAIL("Unsupported interpolation " << interpolator);+  }+}+ DefaultProbabilityTermStructure *qlInterpolatedDefaultDensityCurveAux(     const std::vector<Date>& dates,     const std::vector<double>& densities,@@ -941,6 +989,61 @@           LogCubic(CubicInterpolation::FritschButland));     case hasquant::Parabolic:       return new PiecewiseYoYInflationCurve<LogCubic>(referenceDate, baseDate, baseYoYRate, frequency, dayCounter, instruments, {}, 1.0e-12,+          LogCubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  default:+    QL_FAIL("Unsupported interpolation " << interpolator);+  }+}++YoYInflationTermStructure *qlInterpolatedYoYInflationCurveAux(+    const Date &referenceDate,+    const std::vector<Date> &dates,+    const std::vector<Rate> &rates,+    Frequency frequency,+    const DayCounter& dayCounter,+    int interpolator, int approximator, int approximatorArg) {+  switch (interpolator) {+  case hasquant::BackwardFlat:+    return new InterpolatedYoYInflationCurve<BackwardFlat>(referenceDate, dates, rates, frequency, dayCounter);+  case hasquant::ForwardFlat:+    return new InterpolatedYoYInflationCurve<ForwardFlat>(referenceDate, dates, rates, frequency, dayCounter);+  case hasquant::Linear:+    return new InterpolatedYoYInflationCurve<Linear>(referenceDate, dates, rates, frequency, dayCounter);+  case hasquant::LogLinear:+    return new InterpolatedYoYInflationCurve<LogLinear>(referenceDate, dates, rates, frequency, dayCounter);+  case hasquant::Cubic:+    switch (approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedYoYInflationCurve<Cubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          Cubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedYoYInflationCurve<Cubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          Cubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedYoYInflationCurve<Cubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          Cubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedYoYInflationCurve<Cubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          Cubic(CubicInterpolation::Parabolic, approximatorArg));+    default:+      QL_FAIL("Unsupported approximation " << approximator);+    }+  case hasquant::LogCubic:+    switch(approximator) {+    case hasquant::NaturalSpline:+      return new InterpolatedYoYInflationCurve<LogCubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          LogCubic(CubicInterpolation::Spline, approximatorArg, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0));+    case hasquant::Kruger:+      return new InterpolatedYoYInflationCurve<LogCubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          LogCubic(CubicInterpolation::Kruger));+    case hasquant::FritschButland:+      return new InterpolatedYoYInflationCurve<LogCubic>(referenceDate, dates, rates, frequency, dayCounter, {},+          LogCubic(CubicInterpolation::FritschButland));+    case hasquant::Parabolic:+      return new InterpolatedYoYInflationCurve<LogCubic>(referenceDate, dates, rates, frequency, dayCounter, {},           LogCubic(CubicInterpolation::Parabolic, approximatorArg));     default:       QL_FAIL("Unsupported approximation " << approximator);
cbits/qlTermStructureAux.h view
@@ -9,6 +9,7 @@ #include <ql/termstructures/credit/defaultprobabilityhelpers.hpp> #include <ql/termstructures/inflation/piecewisezeroinflationcurve.hpp> #include <ql/termstructures/inflation/piecewiseyoyinflationcurve.hpp>+#include <ql/termstructures/inflation/interpolatedyoyinflationcurve.hpp>  // Every IterativeBootstrap constructor parameter (ql/termstructures/iterativebootstrap.hpp), // as one flat POD so the piecewise-curve entry points don't grow nine more positional@@ -100,6 +101,13 @@   const std::vector<double>& dfs,   int interpolator, int approximator, int approximatorArg); +QuantLib::YieldTermStructure *qlPiecewiseZeroSpreadedTermStructureAux(+  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,+  const std::vector<QuantLib::Handle<QuantLib::Quote> >& spreads,+  const std::vector<QuantLib::Date>& dates,+  QuantLib::Compounding comp, QuantLib::Frequency freq,+  int interpolator, int approximator, int approximatorArg);+ // some credit stuff QuantLib::DefaultProbabilityTermStructure *qlInterpolatedDefaultDensityCurveAux(             const std::vector<QuantLib::Date>& dates,@@ -156,6 +164,14 @@     QuantLib::Frequency frequency,     const QuantLib::DayCounter& dayCounter,     const std::vector<QuantLib::ext::shared_ptr<QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure> > >& instruments,+    int interpolator, int approximator, int approximatorArg);++QuantLib::YoYInflationTermStructure *qlInterpolatedYoYInflationCurveAux(+    const QuantLib::Date &referenceDate,+    const std::vector<QuantLib::Date> &dates,+    const std::vector<QuantLib::Rate> &rates,+    QuantLib::Frequency frequency,+    const QuantLib::DayCounter& dayCounter,     int interpolator, int approximator, int approximatorArg);  /* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
cbits/qlTypesC2HS.h view
@@ -13,6 +13,10 @@ typedef struct EndCriteria EndCriteria; typedef struct TimeGrid TimeGrid; typedef struct Rounding Rounding;+typedef struct CommodityType CommodityType;+typedef struct UnitOfMeasure UnitOfMeasure;+typedef struct PaymentTerm PaymentTerm;+typedef struct UnitOfMeasureConversion UnitOfMeasureConversion; typedef struct FdmSchemeDesc FdmSchemeDesc; typedef struct BlackDeltaCalculator BlackDeltaCalculator; typedef struct CouponLeg CouponLeg;@@ -33,6 +37,10 @@ typedef struct QlBatesModel QlBatesModel; typedef struct QlBatesProcess QlBatesProcess; typedef struct QlBermudanExercise QlBermudanExercise;+typedef struct QlBlackAtmVolCurve QlBlackAtmVolCurve;+typedef struct QlAbcdAtmVolCurve QlAbcdAtmVolCurve;+typedef struct QlBlackVolSurface QlBlackVolSurface;+typedef struct QlSabrVolSurface QlSabrVolSurface; typedef struct QlBlackCalculator QlBlackCalculator; typedef struct QlBlackProcess QlBlackProcess; typedef struct QlBlackScholesCalculator QlBlackScholesCalculator;@@ -50,13 +58,27 @@ typedef struct QlCallableBond QlCallableBond; typedef struct QlCallableBondVolatilityStructure QlCallableBondVolatilityStructure; typedef struct QlCapFloor QlCapFloor;+typedef struct QlCapFloorTermVolatilityStructure QlCapFloorTermVolatilityStructure;+typedef struct QlCapFloorTermVolCurve QlCapFloorTermVolCurve; typedef struct QlCapFloorTermVolSurface QlCapFloorTermVolSurface;+typedef struct QlCommodityCurve QlCommodityCurve;+typedef struct QlCommodityIndex QlCommodityIndex;+typedef struct QlCommodity QlCommodity;+typedef struct QlEnergyCommodity QlEnergyCommodity;+typedef struct QlEnergyFuture QlEnergyFuture;+typedef struct QlEnergySwap QlEnergySwap;+typedef struct QlEnergyVanillaSwap QlEnergyVanillaSwap;+typedef struct QlEnergyBasisSwap QlEnergyBasisSwap;+typedef struct QlCommodityCashFlow QlCommodityCashFlow; typedef struct QlCdsOption QlCdsOption; typedef struct QlClaim QlClaim; typedef struct QlConvertibleBond QlConvertibleBond; typedef struct QlCPIBond QlCPIBond;+typedef struct QlCPICapFloor QlCPICapFloor;+typedef struct QlCPICapFloorTermPriceSurface QlCPICapFloorTermPriceSurface; typedef struct QlCPICashFlow QlCPICashFlow; typedef struct QlCPISwap QlCPISwap;+typedef struct QlCPIVolatilitySurface QlCPIVolatilitySurface; typedef struct QlCreditDefaultSwap QlCreditDefaultSwap; typedef struct QlDefaultProbabilityHelper QlDefaultProbabilityHelper; typedef struct QlDefaultProbabilityTermStructure QlDefaultProbabilityTermStructure;@@ -70,6 +92,7 @@ typedef struct QlEquityTotalReturnSwap QlEquityTotalReturnSwap; typedef struct QlEuropeanExercise QlEuropeanExercise; typedef struct QlExercise QlExercise;+typedef struct QlRebatedExercise QlRebatedExercise; typedef struct QlExtendedOrnsteinUhlenbeckProcess QlExtendedOrnsteinUhlenbeckProcess; typedef struct QlExtOUWithJumpsProcess QlExtOUWithJumpsProcess; typedef struct QlFdmQuantoHelper QlFdmQuantoHelper;@@ -110,11 +133,16 @@ typedef struct QlMerton76Process QlMerton76Process; typedef struct QlMultiAssetOption QlMultiAssetOption; typedef struct QlMultiCurve QlMultiCurve;+typedef struct QlNonstandardSwap QlNonstandardSwap;+typedef struct QlNonstandardSwaption QlNonstandardSwaption;+typedef struct QlFloatFloatSwap QlFloatFloatSwap;+typedef struct QlFloatFloatSwaption QlFloatFloatSwaption; typedef struct QlOISRateHelper QlOISRateHelper; typedef struct QlOneAssetOption QlOneAssetOption; typedef struct QlOneFactorAffineModel QlOneFactorAffineModel; typedef struct QlOption QlOption; typedef struct QlOptionletVolatilityStructure QlOptionletVolatilityStructure;+typedef struct QlOptionletStripper2 QlOptionletStripper2; typedef struct QlOvernightIndex QlOvernightIndex; typedef struct QlOvernightIndexedSwap QlOvernightIndexedSwap; typedef struct QlOvernightIndexedSwapIndex QlOvernightIndexedSwapIndex;@@ -138,14 +166,20 @@ typedef struct QlShortRateModel QlShortRateModel; typedef struct QlSimpleQuote QlSimpleQuote; typedef struct QlSmileSection QlSmileSection;+typedef struct QlSoftBarrierOption QlSoftBarrierOption; typedef struct QlStochasticProcess QlStochasticProcess; typedef struct QlStochasticProcess1D QlStochasticProcess1D; typedef struct QlStochasticProcessArray QlStochasticProcessArray; typedef struct QlStrikedTypePayoff QlStrikedTypePayoff; typedef struct QlSwap QlSwap;+typedef struct QlFixedVsFloatingSwap QlFixedVsFloatingSwap;+typedef struct QlConstNotionalCrossCurrencySwap QlConstNotionalCrossCurrencySwap;+typedef struct QlConstNotionalCrossCurrencyBasisSwap QlConstNotionalCrossCurrencyBasisSwap;+typedef struct QlConstNotionalCrossCurrencyFixedVsFloatingSwap QlConstNotionalCrossCurrencyFixedVsFloatingSwap; typedef struct QlSwapIndex QlSwapIndex; typedef struct QlSwapRateHelper QlSwapRateHelper; typedef struct QlSwaption QlSwaption;+typedef struct QlSwaptionHelper QlSwaptionHelper; typedef struct QlSwaptionVolatilityStructure QlSwaptionVolatilityStructure; typedef struct QlSwingExercise QlSwingExercise; typedef struct QlTermStructure QlTermStructure;@@ -159,8 +193,12 @@ typedef struct QlYearOnYearInflationSwap QlYearOnYearInflationSwap; typedef struct QlYearOnYearInflationSwapHelper QlYearOnYearInflationSwapHelper; typedef struct QlYieldTermStructure QlYieldTermStructure;+typedef struct QlYoYCapFloorTermPriceSurface QlYoYCapFloorTermPriceSurface;+typedef struct QlYoYInflationCapFloor QlYoYInflationCapFloor;+typedef struct QlYoYInflationCouponPricer QlYoYInflationCouponPricer; typedef struct QlYoYInflationIndex QlYoYInflationIndex; typedef struct QlYoYInflationTermStructure QlYoYInflationTermStructure;+typedef struct QlYoYOptionletVolatilitySurface QlYoYOptionletVolatilitySurface; typedef struct QlZeroCouponInflationSwap QlZeroCouponInflationSwap; typedef struct QlZeroCouponInflationSwapHelper QlZeroCouponInflationSwapHelper; typedef struct QlZeroCouponSwap QlZeroCouponSwap;
cbits/qlaux.h view
@@ -5,6 +5,9 @@ #include <boost/optional.hpp> #include <ql/math/matrix.hpp> #include <ql/instruments/varianceswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencyswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencybasisswap.hpp>+#include <ql/instruments/constnotionalcrosscurrencyfixedvsfloatingswap.hpp> // SabrSwaptionVolatilityCube is a typedef of a template instantiation // (XabrSwaptionVolatilityCube<SwaptionVolCubeSabrModel>), not an ordinary class -- it cannot be // forward-declared the way every other type below is, so its full header is pulled in here@@ -34,6 +37,7 @@   class Quote;   class Bond;   class FixedRateBond;+  class FixedVsFloatingSwap;   class FloatingRateBond;   class ZeroCouponBond;   class Forward;@@ -46,6 +50,19 @@   class BespokeCalendar;   class Schedule;   class Currency;+  class CommodityType;+  class UnitOfMeasure;+  class PaymentTerm;+  class UnitOfMeasureConversion;+  class CommodityCurve;+  class CommodityIndex;+  class Commodity;+  class EnergyCommodity;+  class EnergyFuture;+  class EnergySwap;+  class EnergyVanillaSwap;+  class EnergyBasisSwap;+  class CommodityCashFlow;   class Region;   class InterestRate;   class FixedRateBondHelper;@@ -61,6 +78,7 @@   class Index;   class FloatingRateCouponPricer;   class OptionletVolatilityStructure;+  class OptionletStripper2;   class Coupon;   class AffineModel;   class AmericanExercise;@@ -101,6 +119,8 @@   class BatesProcess;   class BermudanExercise;   class BjerksundStenslandApproximationEngine;+  class AbcdAtmVolCurve;+  class BlackAtmVolCurve;   class BlackCalculator;   class BlackDeltaCalculator;   class BlackCalibrationHelper;@@ -115,6 +135,7 @@   class BlackScholesProcess;   class BlackSwaptionEngine;   class BlackVarianceCurve;+  class BlackVolSurface;   class BlackVolTermStructure;   class BlackVolatilitySurfaceDelta;   class BondHelper;@@ -127,6 +148,8 @@   class CallableFixedRateBond;   class CallableZeroCouponBond;   class CapFloor;+  class CapFloorTermVolatilityStructure;+  class CapFloorTermVolCurve;   class CapFloorTermVolSurface;   class CapHelper;   class CashOrNothingPayoff;@@ -139,14 +162,18 @@   class ConvertibleFloatingRateBond;   class ConvertibleZeroCouponBond;   class CPIBond;+  class CPICapFloor;+  class CPICapFloorTermPriceSurface;   class CPICashFlow;   class CPISwap;+  class CPIVolatilitySurface;   class CreditDefaultSwap;   class CubicBSplinesFitting;   class DefaultProbabilityTermStructure;   class DeltaVolQuote;   class DiscountingFxForwardEngine;   class DiscountingSwapEngine;+  class DiscountingConstNotionalCrossCurrencySwapEngine;   class Dividend;   class EarlyExercise;   class EndCriteria;@@ -220,6 +247,10 @@   class MultiCurve;   class NelsonSiegelFitting;   class NoConstraint;+  class NonstandardSwap;+  class NonstandardSwaption;+  class FloatFloatSwap;+  class FloatFloatSwaption;   class OISRateHelper;   class OneAssetOption;   class OneFactorAffineModel;@@ -237,14 +268,17 @@   class QuantoForwardVanillaOption;   class QuantoTermStructure;   class QuantoVanillaOption;+  class RebatedExercise;   class ReplicatingVarianceSwapEngine;   class Rounding;   class SabrInterpolatedSmileSection;+  class SabrVolSurface;   class ShortRateModel;   class SimplePolynomialFitting;   class SimpleQuote;   class Simplex;   class SmileSection;+  class SoftBarrierOption;   class SoftCallability;   class SpreadCdsHelper;   class StochasticProcess;@@ -281,8 +315,12 @@   class VolatilityTermStructure;   class YearOnYearInflationSwap;   class YearOnYearInflationSwapHelper;+  class YoYCapFloorTermPriceSurface;+  class YoYInflationCapFloor;+  class YoYInflationCouponPricer;   class YoYInflationIndex;   class YoYInflationTermStructure;+  class YoYOptionletVolatilitySurface;   class ZeroCouponInflationSwap;   class ZeroCouponInflationSwapHelper;   class ZeroCouponSwap;@@ -298,6 +336,11 @@ using QuantLib::BusinessDayConvention; using QuantLib::Bond; using QuantLib::FixedRateBond;+using QuantLib::FixedVsFloatingSwap;+using QuantLib::ConstNotionalCrossCurrencySwap;+using QuantLib::ConstNotionalCrossCurrencyBasisSwap;+using QuantLib::ConstNotionalCrossCurrencyFixedVsFloatingSwap;+using QuantLib::DiscountingConstNotionalCrossCurrencySwapEngine; using QuantLib::FloatingRateBond; using QuantLib::ZeroCouponBond; using QuantLib::Forward;@@ -310,6 +353,19 @@ using QuantLib::BespokeCalendar; using QuantLib::Schedule; using QuantLib::Currency;+using QuantLib::CommodityType;+using QuantLib::UnitOfMeasure;+using QuantLib::PaymentTerm;+using QuantLib::UnitOfMeasureConversion;+using QuantLib::CommodityCurve;+using QuantLib::CommodityIndex;+using QuantLib::Commodity;+using QuantLib::EnergyCommodity;+using QuantLib::EnergyFuture;+using QuantLib::EnergySwap;+using QuantLib::EnergyVanillaSwap;+using QuantLib::EnergyBasisSwap;+using QuantLib::CommodityCashFlow; using QuantLib::Region; using QuantLib::InterestRate; using QuantLib::FixedRateBondHelper;@@ -325,6 +381,7 @@ using QuantLib::Index; using QuantLib::FloatingRateCouponPricer; using QuantLib::OptionletVolatilityStructure;+using QuantLib::OptionletStripper2; using QuantLib::Coupon; using QuantLib::AffineModel; using QuantLib::AmericanExercise;@@ -365,6 +422,8 @@ using QuantLib::BatesProcess; using QuantLib::BermudanExercise; using QuantLib::BjerksundStenslandApproximationEngine;+using QuantLib::AbcdAtmVolCurve;+using QuantLib::BlackAtmVolCurve; using QuantLib::BlackCalculator; using QuantLib::BlackDeltaCalculator; using QuantLib::BlackCalibrationHelper;@@ -379,6 +438,7 @@ using QuantLib::BlackScholesProcess; using QuantLib::BlackSwaptionEngine; using QuantLib::BlackVarianceCurve;+using QuantLib::BlackVolSurface; using QuantLib::BlackVolTermStructure; using QuantLib::BlackVolatilitySurfaceDelta; using QuantLib::BondHelper;@@ -391,6 +451,8 @@ using QuantLib::CallableFixedRateBond; using QuantLib::CallableZeroCouponBond; using QuantLib::CapFloor;+using QuantLib::CapFloorTermVolatilityStructure;+using QuantLib::CapFloorTermVolCurve; using QuantLib::CapFloorTermVolSurface; using QuantLib::CapHelper; using QuantLib::CashOrNothingPayoff;@@ -403,8 +465,11 @@ using QuantLib::ConvertibleFloatingRateBond; using QuantLib::ConvertibleZeroCouponBond; using QuantLib::CPIBond;+using QuantLib::CPICapFloor;+using QuantLib::CPICapFloorTermPriceSurface; using QuantLib::CPICashFlow; using QuantLib::CPISwap;+using QuantLib::CPIVolatilitySurface; using QuantLib::CreditDefaultSwap; using QuantLib::CubicBSplinesFitting; using QuantLib::DefaultProbabilityTermStructure;@@ -484,6 +549,10 @@ using QuantLib::MultiCurve; using QuantLib::NelsonSiegelFitting; using QuantLib::NoConstraint;+using QuantLib::NonstandardSwap;+using QuantLib::NonstandardSwaption;+using QuantLib::FloatFloatSwap;+using QuantLib::FloatFloatSwaption; using QuantLib::OISRateHelper; using QuantLib::OneAssetOption; using QuantLib::OneFactorAffineModel;@@ -502,14 +571,17 @@ using QuantLib::QuantoForwardVanillaOption; using QuantLib::QuantoTermStructure; using QuantLib::QuantoVanillaOption;+using QuantLib::RebatedExercise; using QuantLib::ReplicatingVarianceSwapEngine; using QuantLib::Rounding; using QuantLib::SabrInterpolatedSmileSection;+using QuantLib::SabrVolSurface; using QuantLib::ShortRateModel; using QuantLib::SimplePolynomialFitting; using QuantLib::SimpleQuote; using QuantLib::Simplex; using QuantLib::SmileSection;+using QuantLib::SoftBarrierOption; using QuantLib::SoftCallability; using QuantLib::SpreadCdsHelper; using QuantLib::StochasticProcess1D;@@ -549,8 +621,12 @@ using QuantLib::VolatilityTermStructure; using QuantLib::YearOnYearInflationSwap; using QuantLib::YearOnYearInflationSwapHelper;+using QuantLib::YoYCapFloorTermPriceSurface;+using QuantLib::YoYInflationCapFloor;+using QuantLib::YoYInflationCouponPricer; using QuantLib::YoYInflationIndex; using QuantLib::YoYInflationTermStructure;+using QuantLib::YoYOptionletVolatilitySurface; using QuantLib::ZeroCouponInflationSwap; using QuantLib::ZeroCouponInflationSwapHelper; using QuantLib::ZeroCouponSwap;@@ -613,6 +689,21 @@ typedef shared_ptr<BatesModel> QlBatesModel; typedef shared_ptr<BatesProcess> QlBatesProcess; typedef shared_ptr<BermudanExercise> QlBermudanExercise;+// BlackAtmVolCurve is the family root: upstream speaks Handle<BlackAtmVolCurve> itself+// (SabrVolSurface's ctor/atmCurve(), VolatilityCube), same reasoning as+// QlOptionletVolatilityStructure/QlSwaptionVolatilityStructure/QlBlackVolTermStructure above --+// Handle, not shared_ptr. AbcdAtmVolCurve/SabrVolSurface are dedicated leaves with their own+// calc/getters (per CLAUDE.md), so each gets its own shared_ptr-wrapped type, same as+// QlSabrSwaptionVolatilityCube/QlInterpolatedSwaptionVolatilityCube under the Handle-wrapped+// QlSwaptionVolatilityStructure root.+typedef Handle<BlackAtmVolCurve> QlBlackAtmVolCurve;+typedef shared_ptr<AbcdAtmVolCurve> QlAbcdAtmVolCurve;+// BlackVolSurface itself is never spoken of as Handle<BlackVolSurface> upstream (grep confirms),+// so it's a plain shared_ptr intermediate -- only used to route SabrVolSurface's Upcastable chain+// through its own smileSection getter, exactly like QlFixedVsFloatingSwap routes VanillaSwap's+// upcast chain up to QlSwap.+typedef shared_ptr<BlackVolSurface> QlBlackVolSurface;+typedef shared_ptr<SabrVolSurface> QlSabrVolSurface; typedef shared_ptr<BlackCalculator> QlBlackCalculator; typedef shared_ptr<BlackCalibrationHelper> QlBlackCalibrationHelper; typedef shared_ptr<BlackProcess> QlBlackProcess;@@ -631,13 +722,50 @@ typedef shared_ptr<CallableBond> QlCallableBond; typedef shared_ptr<CallableBondVolatilityStructure> QlCallableBondVolatilityStructure; typedef shared_ptr<CapFloor> QlCapFloor;+// Unlike QlOptionletVolatilityStructure/QlSwaptionVolatilityStructure/QlBlackVolTermStructure,+// upstream never speaks Handle<CapFloorTermVolatilityStructure> anywhere (grep confirms only+// Handle<CapFloorTermVolCurve>, in the still-unbound OptionletStripper2, and+// shared_ptr<CapFloorTermVolSurface>, in OptionletStripper1) -- shared_ptr, like+// QlVolatilityTermStructure/QlCapFloorTermVolSurface themselves.+typedef shared_ptr<CapFloorTermVolatilityStructure> QlCapFloorTermVolatilityStructure;+typedef shared_ptr<CapFloorTermVolCurve> QlCapFloorTermVolCurve; typedef shared_ptr<CapFloorTermVolSurface> QlCapFloorTermVolSurface;+// CommodityCurve is a plain TermStructure subclass, constructed and consumed directly by value+// (basisOfCurve_ is a shared_ptr<CommodityCurve>, never a Handle) -- shared_ptr-wrapped, same+// reasoning as QlTermStructure/QlCallableBondVolatilityStructure/QlDefaultProbabilityTermStructure.+typedef shared_ptr<CommodityCurve> QlCommodityCurve;+// CommodityIndex is likewise shared_ptr-wrapped: Index leaves in general are (QlIndex,+// QlEquityIndex above), and CommodityIndex's own forwardCurve_ member is the shared_ptr+// QlCommodityCurve above, never a Handle.+typedef shared_ptr<CommodityIndex> QlCommodityIndex;+// Commodity/EnergyCommodity are abstract-here (no bindable constructor -- Commodity is never+// constructed directly upstream, and EnergyCommodity::quantity() is pure virtual), reachable only+// as an upcast target once a Stage-6 leaf (EnergyFuture, EnergyVanillaSwap, EnergyBasisSwap) exists.+typedef shared_ptr<Commodity> QlCommodity;+typedef shared_ptr<EnergyCommodity> QlEnergyCommodity;+typedef shared_ptr<EnergyFuture> QlEnergyFuture;+// EnergySwap binds no constructor (its own performCalculations is never overridden, so calling it+// falls through to Instrument::performCalculations's QL_REQUIRE(engine_, ...) and throws) --+// reachable only as an upcast target from EnergyVanillaSwap/EnergyBasisSwap, exactly like+// FixedVsFloatingSwap/VanillaSwap.+typedef shared_ptr<EnergySwap> QlEnergySwap;+typedef shared_ptr<EnergyVanillaSwap> QlEnergyVanillaSwap;+typedef shared_ptr<EnergyBasisSwap> QlEnergyBasisSwap;+typedef shared_ptr<CommodityCashFlow> QlCommodityCashFlow; typedef shared_ptr<CdsOption> QlCdsOption; typedef shared_ptr<Claim> QlClaim; typedef shared_ptr<ConvertibleBond> QlConvertibleBond; typedef shared_ptr<CPIBond> QlCPIBond;+typedef shared_ptr<CPICapFloor> QlCPICapFloor;+// A plain TermStructure leaf like CommodityCurve/ZeroInflationTermStructure -- shared_ptr, not+// a Handle; wrapped into Handle<CPICapFloorTermPriceSurface> at the point of use+// (InterpolatingCPICapFloorEngine's ctor).+typedef shared_ptr<CPICapFloorTermPriceSurface> QlCPICapFloorTermPriceSurface; typedef shared_ptr<CPICashFlow> QlCPICashFlow; typedef shared_ptr<CPISwap> QlCPISwap;+// A VolatilityTermStructure family member like YoYOptionletVolatilitySurface -- Handle, not a+// plain shared_ptr.+typedef Handle<CPIVolatilitySurface> QlCPIVolatilitySurface; typedef shared_ptr<CreditDefaultSwap> QlCreditDefaultSwap; typedef shared_ptr<DefaultProbabilityTermStructure> QlDefaultProbabilityTermStructure; typedef shared_ptr<DeltaVolQuote> QlDeltaVolQuote;@@ -649,6 +777,7 @@ typedef shared_ptr<EquityTotalReturnSwap> QlEquityTotalReturnSwap; typedef shared_ptr<EuropeanExercise> QlEuropeanExercise; typedef shared_ptr<Exercise> QlExercise;+typedef shared_ptr<RebatedExercise> QlRebatedExercise; typedef shared_ptr<ExtOUWithJumpsProcess> QlExtOUWithJumpsProcess; typedef shared_ptr<ExtendedOrnsteinUhlenbeckProcess> QlExtendedOrnsteinUhlenbeckProcess; typedef shared_ptr<FdmQuantoHelper> QlFdmQuantoHelper;@@ -682,10 +811,18 @@ // shared pointer" -- bound as a standalone leaf type (own Finalizable instance, no Upcastable // parent: it isn't a TermStructure), same shape as e.g. QlSwapRateHelper. typedef shared_ptr<MultiCurve> QlMultiCurve;+typedef shared_ptr<NonstandardSwap> QlNonstandardSwap;+typedef shared_ptr<NonstandardSwaption> QlNonstandardSwaption;+typedef shared_ptr<FloatFloatSwap> QlFloatFloatSwap;+typedef shared_ptr<FloatFloatSwaption> QlFloatFloatSwaption; typedef shared_ptr<OISRateHelper> QlOISRateHelper; typedef shared_ptr<OneAssetOption> QlOneAssetOption; typedef shared_ptr<OneFactorAffineModel> QlOneFactorAffineModel; typedef shared_ptr<Option> QlOption;+// OptionletStripper1 is never exposed to Haskell (see qlOptionletStripper1 above), but+// OptionletStripper2 has its own diagnostic getters (atmCapFloorStrikes/atmCapFloorPrices/+// spreadsVol), so it gets its own shared_ptr-wrapped leaf, same as QlSabrInterpolatedSmileSection.+typedef shared_ptr<OptionletStripper2> QlOptionletStripper2; typedef shared_ptr<OvernightIndex> QlOvernightIndex; typedef shared_ptr<OvernightIndexedSwap> QlOvernightIndexedSwap; typedef shared_ptr<OvernightIndexedSwapIndex> QlOvernightIndexedSwapIndex;@@ -700,14 +837,20 @@ typedef shared_ptr<ShortRateModel> QlShortRateModel; typedef shared_ptr<SimpleQuote> QlSimpleQuote; typedef shared_ptr<SmileSection> QlSmileSection;+typedef shared_ptr<SoftBarrierOption> QlSoftBarrierOption; typedef shared_ptr<StochasticProcess1D> QlStochasticProcess1D; typedef shared_ptr<StochasticProcess> QlStochasticProcess; typedef shared_ptr<StochasticProcessArray> QlStochasticProcessArray; typedef shared_ptr<StrikedTypePayoff> QlStrikedTypePayoff; typedef shared_ptr<Swap> QlSwap;+typedef shared_ptr<FixedVsFloatingSwap> QlFixedVsFloatingSwap;+typedef shared_ptr<ConstNotionalCrossCurrencySwap> QlConstNotionalCrossCurrencySwap;+typedef shared_ptr<ConstNotionalCrossCurrencyBasisSwap> QlConstNotionalCrossCurrencyBasisSwap;+typedef shared_ptr<ConstNotionalCrossCurrencyFixedVsFloatingSwap> QlConstNotionalCrossCurrencyFixedVsFloatingSwap; typedef shared_ptr<SwapIndex> QlSwapIndex; typedef shared_ptr<SwapRateHelper> QlSwapRateHelper; typedef shared_ptr<Swaption> QlSwaption;+typedef shared_ptr<SwaptionHelper> QlSwaptionHelper; typedef shared_ptr<SabrSwaptionVolatilityCube> QlSabrSwaptionVolatilityCube; typedef shared_ptr<InterpolatedSwaptionVolatilityCube> QlInterpolatedSwaptionVolatilityCube; // A vol structure is a Handle, same reasoning as QlBlackVolTermStructure above.@@ -724,8 +867,15 @@ typedef shared_ptr<VolatilityTermStructure> QlVolatilityTermStructure; typedef shared_ptr<YearOnYearInflationSwap> QlYearOnYearInflationSwap; typedef shared_ptr<YearOnYearInflationSwapHelper> QlYearOnYearInflationSwapHelper;+// A plain TermStructure leaf like CPICapFloorTermPriceSurface -- shared_ptr, not a Handle.+typedef shared_ptr<YoYCapFloorTermPriceSurface> QlYoYCapFloorTermPriceSurface;+typedef shared_ptr<YoYInflationCapFloor> QlYoYInflationCapFloor;+// A standalone pricer type like FloatingRateCouponPricer -- shared_ptr, not a Handle.+typedef shared_ptr<YoYInflationCouponPricer> QlYoYInflationCouponPricer; typedef shared_ptr<YoYInflationIndex> QlYoYInflationIndex; typedef shared_ptr<YoYInflationTermStructure> QlYoYInflationTermStructure;+// A vol structure is a Handle, same reasoning as QlOptionletVolatilityStructure above.+typedef Handle<YoYOptionletVolatilitySurface> QlYoYOptionletVolatilitySurface; typedef shared_ptr<ZeroCouponInflationSwap> QlZeroCouponInflationSwap; typedef shared_ptr<ZeroCouponInflationSwapHelper> QlZeroCouponInflationSwapHelper; typedef shared_ptr<ZeroCouponSwap> QlZeroCouponSwap;@@ -805,11 +955,14 @@ template <> class ObjClassName<CallableFixedRateBond*> {public: static void output(std::ostream& os) {os << "CallableFixedRateBond";}}; template <> class ObjClassName<CallableZeroCouponBond*> {public: static void output(std::ostream& os) {os << "CallableZeroCouponBond";}}; template <> class ObjClassName<CapFloor*> {public: static void output(std::ostream& os) {os << "CapFloor";}};+template <> class ObjClassName<CapFloorTermVolatilityStructure*> {public: static void output(std::ostream& os) {os << "CapFloorTermVolatilityStructure";}};+template <> class ObjClassName<CapFloorTermVolCurve*> {public: static void output(std::ostream& os) {os << "CapFloorTermVolCurve";}}; template <> class ObjClassName<CapFloorTermVolSurface*> {public: static void output(std::ostream& os) {os << "CapFloorTermVolSurface";}}; template <> class ObjClassName<CapHelper*> {public: static void output(std::ostream& os) {os << "CapHelper";}}; template <> class ObjClassName<CashOrNothingPayoff*> {public: static void output(std::ostream& os) {os << "CashOrNothingPayoff";}}; template <> class ObjClassName<CdsOption*> {public: static void output(std::ostream& os) {os << "CdsOption";}}; template <> class ObjClassName<Claim*> {public: static void output(std::ostream& os) {os << "Claim";}};+template <> class ObjClassName<CommodityType*> {public: static void output(std::ostream& os) {os << "CommodityType";}}; template <> class ObjClassName<CompositeConstraint*> {public: static void output(std::ostream& os) {os << "CompositeConstraint";}}; template <> class ObjClassName<CompositeInstrument*> {public: static void output(std::ostream& os) {os << "CompositeInstrument";}}; template <> class ObjClassName<Constraint*> {public: static void output(std::ostream& os) {os << "Constraint";}};@@ -819,7 +972,10 @@ template <> class ObjClassName<ConvertibleZeroCouponBond*> {public: static void output(std::ostream& os) {os << "ConvertibleZeroCouponBond";}}; template <> class ObjClassName<CouponLeg*> {public: static void output(std::ostream& os) {os << "CouponLeg";}}; template <> class ObjClassName<CPIBond*> {public: static void output(std::ostream& os) {os << "CPIBond";}};+template <> class ObjClassName<CPICapFloor*> {public: static void output(std::ostream& os) {os << "CPICapFloor";}};+template <> class ObjClassName<CPICapFloorTermPriceSurface*> {public: static void output(std::ostream& os) {os << "CPICapFloorTermPriceSurface";}}; template <> class ObjClassName<CPISwap*> {public: static void output(std::ostream& os) {os << "CPISwap";}};+template <> class ObjClassName<CPIVolatilitySurface*> {public: static void output(std::ostream& os) {os << "CPIVolatilitySurface";}}; template <> class ObjClassName<CreditDefaultSwap*> {public: static void output(std::ostream& os) {os << "CreditDefaultSwap";}}; template <> class ObjClassName<CubicBSplinesFitting*> {public: static void output(std::ostream& os) {os << "CubicBSplinesFitting";}}; template <> class ObjClassName<Currency*> {public: static void output(std::ostream& os) {os << "Currency";}};@@ -830,6 +986,7 @@ template <> class ObjClassName<DiscountingBondEngine*> {public: static void output(std::ostream& os) {os << "DiscountingBondEngine";}}; template <> class ObjClassName<DiscountingFxForwardEngine*> {public: static void output(std::ostream& os) {os << "DiscountingFxForwardEngine";}}; template <> class ObjClassName<DiscountingSwapEngine*> {public: static void output(std::ostream& os) {os << "DiscountingSwapEngine";}};+template <> class ObjClassName<DiscountingConstNotionalCrossCurrencySwapEngine*> {public: static void output(std::ostream& os) {os << "DiscountingConstNotionalCrossCurrencySwapEngine";}}; template <> class ObjClassName<Dividend*> {public: static void output(std::ostream& os) {os << "Dividend";}}; template <> class ObjClassName<EarlyExercise*> {public: static void output(std::ostream& os) {os << "EarlyExercise";}}; template <> class ObjClassName<EndCriteria*> {public: static void output(std::ostream& os) {os << "EndCriteria";}};@@ -920,9 +1077,11 @@ template <> class ObjClassName<OptimizationMethod*> {public: static void output(std::ostream& os) {os << "OptimizationMethod";}}; template <> class ObjClassName<Option*> {public: static void output(std::ostream& os) {os << "Option";}}; template <> class ObjClassName<OptionletVolatilityStructure*> {public: static void output(std::ostream& os) {os << "OptionletVolatilityStructure";}};+template <> class ObjClassName<OptionletStripper2*> {public: static void output(std::ostream& os) {os << "OptionletStripper2";}}; template <> class ObjClassName<OvernightIndex*> {public: static void output(std::ostream& os) {os << "OvernightIndex";}}; template <> class ObjClassName<OvernightIndexedSwap*> {public: static void output(std::ostream& os) {os << "OvernightIndexedSwap";}}; template <> class ObjClassName<OvernightIndexedSwapIndex*> {public: static void output(std::ostream& os) {os << "OvernightIndexedSwapIndex";}};+template <> class ObjClassName<PaymentTerm*> {public: static void output(std::ostream& os) {os << "PaymentTerm";}}; template <> class ObjClassName<Payoff*> {public: static void output(std::ostream& os) {os << "Payoff";}}; template <> class ObjClassName<PercentageStrikePayoff*> {public: static void output(std::ostream& os) {os << "PercentageStrikePayoff";}}; template <> class ObjClassName<PiecewiseTimeDependentHestonModel*> {public: static void output(std::ostream& os) {os << "PiecewiseTimeDependentHestonModel";}};@@ -945,6 +1104,10 @@ template <> class ObjClassName<QlBatesModel*> {public: static void output(std::ostream& os) {os << "QlBatesModel";}}; template <> class ObjClassName<QlBatesProcess*> {public: static void output(std::ostream& os) {os << "QlBatesProcess";}}; template <> class ObjClassName<QlBermudanExercise*> {public: static void output(std::ostream& os) {os << "QlBermudanExercise";}};+template <> class ObjClassName<QlBlackAtmVolCurve*> {public: static void output(std::ostream& os) {os << "QlBlackAtmVolCurve";}};+template <> class ObjClassName<QlAbcdAtmVolCurve*> {public: static void output(std::ostream& os) {os << "QlAbcdAtmVolCurve";}};+template <> class ObjClassName<QlBlackVolSurface*> {public: static void output(std::ostream& os) {os << "QlBlackVolSurface";}};+template <> class ObjClassName<QlSabrVolSurface*> {public: static void output(std::ostream& os) {os << "QlSabrVolSurface";}}; template <> class ObjClassName<QlBlackCalculator*> {public: static void output(std::ostream& os) {os << "QlBlackCalculator";}}; template <> class ObjClassName<QlBlackCalibrationHelper*> {public: static void output(std::ostream& os) {os << "QlBlackCalibrationHelper";}}; template <> class ObjClassName<QlBlackProcess*> {public: static void output(std::ostream& os) {os << "QlBlackProcess";}};@@ -961,13 +1124,27 @@ template <> class ObjClassName<QlCallableBond*> {public: static void output(std::ostream& os) {os << "QlCallableBond";}}; template <> class ObjClassName<QlCallableBondVolatilityStructure*> {public: static void output(std::ostream& os) {os << "QlCallableBondVolatilityStructure";}}; template <> class ObjClassName<QlCapFloor*> {public: static void output(std::ostream& os) {os << "QlCapFloor";}};+template <> class ObjClassName<QlCapFloorTermVolatilityStructure*> {public: static void output(std::ostream& os) {os << "QlCapFloorTermVolatilityStructure";}};+template <> class ObjClassName<QlCapFloorTermVolCurve*> {public: static void output(std::ostream& os) {os << "QlCapFloorTermVolCurve";}}; template <> class ObjClassName<QlCapFloorTermVolSurface*> {public: static void output(std::ostream& os) {os << "QlCapFloorTermVolSurface";}};+template <> class ObjClassName<QlCommodityCurve*> {public: static void output(std::ostream& os) {os << "QlCommodityCurve";}};+template <> class ObjClassName<QlCommodityIndex*> {public: static void output(std::ostream& os) {os << "QlCommodityIndex";}};+template <> class ObjClassName<QlCommodity*> {public: static void output(std::ostream& os) {os << "QlCommodity";}};+template <> class ObjClassName<QlEnergyCommodity*> {public: static void output(std::ostream& os) {os << "QlEnergyCommodity";}};+template <> class ObjClassName<QlEnergyFuture*> {public: static void output(std::ostream& os) {os << "QlEnergyFuture";}};+template <> class ObjClassName<QlEnergySwap*> {public: static void output(std::ostream& os) {os << "QlEnergySwap";}};+template <> class ObjClassName<QlEnergyVanillaSwap*> {public: static void output(std::ostream& os) {os << "QlEnergyVanillaSwap";}};+template <> class ObjClassName<QlEnergyBasisSwap*> {public: static void output(std::ostream& os) {os << "QlEnergyBasisSwap";}};+template <> class ObjClassName<QlCommodityCashFlow*> {public: static void output(std::ostream& os) {os << "QlCommodityCashFlow";}}; template <> class ObjClassName<QlCdsOption*> {public: static void output(std::ostream& os) {os << "QlCdsOption";}}; template <> class ObjClassName<QlClaim*> {public: static void output(std::ostream& os) {os << "QlClaim";}}; template <> class ObjClassName<QlConvertibleBond*> {public: static void output(std::ostream& os) {os << "QlConvertibleBond";}}; template <> class ObjClassName<QlCPIBond*> {public: static void output(std::ostream& os) {os << "QlCPIBond";}};+template <> class ObjClassName<QlCPICapFloor*> {public: static void output(std::ostream& os) {os << "QlCPICapFloor";}};+template <> class ObjClassName<QlCPICapFloorTermPriceSurface*> {public: static void output(std::ostream& os) {os << "QlCPICapFloorTermPriceSurface";}}; template <> class ObjClassName<QlCPICashFlow*> {public: static void output(std::ostream& os) {os << "QlCPICashFlow";}}; template <> class ObjClassName<QlCPISwap*> {public: static void output(std::ostream& os) {os << "QlCPISwap";}};+template <> class ObjClassName<QlCPIVolatilitySurface*> {public: static void output(std::ostream& os) {os << "QlCPIVolatilitySurface";}}; template <> class ObjClassName<QlCreditDefaultSwap*> {public: static void output(std::ostream& os) {os << "QlCreditDefaultSwap";}}; template <> class ObjClassName<QlDefaultProbabilityTermStructure*> {public: static void output(std::ostream& os) {os << "QlDefaultProbabilityTermStructure";}}; template <> class ObjClassName<QlDeltaVolQuote*> {public: static void output(std::ostream& os) {os << "QlDeltaVolQuote";}};@@ -1016,11 +1193,16 @@ template <> class ObjClassName<QlMerton76Process*> {public: static void output(std::ostream& os) {os << "QlMerton76Process";}}; template <> class ObjClassName<QlMultiAssetOption*> {public: static void output(std::ostream& os) {os << "QlMultiAssetOption";}}; template <> class ObjClassName<QlMultiCurve*> {public: static void output(std::ostream& os) {os << "QlMultiCurve";}};+template <> class ObjClassName<QlNonstandardSwap*> {public: static void output(std::ostream& os) {os << "QlNonstandardSwap";}};+template <> class ObjClassName<QlNonstandardSwaption*> {public: static void output(std::ostream& os) {os << "QlNonstandardSwaption";}};+template <> class ObjClassName<QlFloatFloatSwap*> {public: static void output(std::ostream& os) {os << "QlFloatFloatSwap";}};+template <> class ObjClassName<QlFloatFloatSwaption*> {public: static void output(std::ostream& os) {os << "QlFloatFloatSwaption";}}; template <> class ObjClassName<QlOISRateHelper*> {public: static void output(std::ostream& os) {os << "QlOISRateHelper";}}; template <> class ObjClassName<QlOneAssetOption*> {public: static void output(std::ostream& os) {os << "QlOneAssetOption";}}; template <> class ObjClassName<QlOneFactorAffineModel*> {public: static void output(std::ostream& os) {os << "QlOneFactorAffineModel";}}; template <> class ObjClassName<QlOption*> {public: static void output(std::ostream& os) {os << "QlOption";}}; template <> class ObjClassName<QlOptionletVolatilityStructure*> {public: static void output(std::ostream& os) {os << "QlOptionletVolatilityStructure";}};+template <> class ObjClassName<QlOptionletStripper2*> {public: static void output(std::ostream& os) {os << "QlOptionletStripper2";}}; template <> class ObjClassName<QlOvernightIndex*> {public: static void output(std::ostream& os) {os << "QlOvernightIndex";}}; template <> class ObjClassName<QlOvernightIndexedSwap*> {public: static void output(std::ostream& os) {os << "QlOvernightIndexedSwap";}}; template <> class ObjClassName<QlOvernightIndexedSwapIndex*> {public: static void output(std::ostream& os) {os << "QlOvernightIndexedSwapIndex";}};@@ -1037,14 +1219,17 @@ template <> class ObjClassName<QlShortRateModel*> {public: static void output(std::ostream& os) {os << "QlShortRateModel";}}; template <> class ObjClassName<QlSimpleQuote*> {public: static void output(std::ostream& os) {os << "QlSimpleQuote";}}; template <> class ObjClassName<QlSmileSection*> {public: static void output(std::ostream& os) {os << "QlSmileSection";}};+template <> class ObjClassName<QlSoftBarrierOption*> {public: static void output(std::ostream& os) {os << "QlSoftBarrierOption";}}; template <> class ObjClassName<QlStochasticProcess*> {public: static void output(std::ostream& os) {os << "QlStochasticProcess";}}; template <> class ObjClassName<QlStochasticProcess1D*> {public: static void output(std::ostream& os) {os << "QlStochasticProcess1D";}}; template <> class ObjClassName<QlStochasticProcessArray*> {public: static void output(std::ostream& os) {os << "QlStochasticProcessArray";}}; template <> class ObjClassName<QlStrikedTypePayoff*> {public: static void output(std::ostream& os) {os << "QlStrikedTypePayoff";}}; template <> class ObjClassName<QlSwap*> {public: static void output(std::ostream& os) {os << "QlSwap";}};+template <> class ObjClassName<QlFixedVsFloatingSwap*> {public: static void output(std::ostream& os) {os << "QlFixedVsFloatingSwap";}}; template <> class ObjClassName<QlSwapIndex*> {public: static void output(std::ostream& os) {os << "QlSwapIndex";}}; template <> class ObjClassName<QlSwapRateHelper*> {public: static void output(std::ostream& os) {os << "QlSwapRateHelper";}}; template <> class ObjClassName<QlSwaption*> {public: static void output(std::ostream& os) {os << "QlSwaption";}};+template <> class ObjClassName<QlSwaptionHelper*> {public: static void output(std::ostream& os) {os << "QlSwaptionHelper";}}; template <> class ObjClassName<QlSwaptionVolatilityStructure*> {public: static void output(std::ostream& os) {os << "QlSwaptionVolatilityStructure";}}; template <> class ObjClassName<QlSabrSwaptionVolatilityCube*> {public: static void output(std::ostream& os) {os << "QlSabrSwaptionVolatilityCube";}}; template <> class ObjClassName<QlInterpolatedSwaptionVolatilityCube*> {public: static void output(std::ostream& os) {os << "QlInterpolatedSwaptionVolatilityCube";}};@@ -1060,8 +1245,12 @@ template <> class ObjClassName<QlYearOnYearInflationSwap*> {public: static void output(std::ostream& os) {os << "QlYearOnYearInflationSwap";}}; template <> class ObjClassName<QlYearOnYearInflationSwapHelper*> {public: static void output(std::ostream& os) {os << "QlYearOnYearInflationSwapHelper";}}; template <> class ObjClassName<QlYieldTermStructure*> {public: static void output(std::ostream& os) {os << "QlYieldTermStructure";}};+template <> class ObjClassName<QlYoYCapFloorTermPriceSurface*> {public: static void output(std::ostream& os) {os << "QlYoYCapFloorTermPriceSurface";}};+template <> class ObjClassName<QlYoYInflationCapFloor*> {public: static void output(std::ostream& os) {os << "QlYoYInflationCapFloor";}};+template <> class ObjClassName<QlYoYInflationCouponPricer*> {public: static void output(std::ostream& os) {os << "QlYoYInflationCouponPricer";}}; template <> class ObjClassName<QlYoYInflationIndex*> {public: static void output(std::ostream& os) {os << "QlYoYInflationIndex";}}; template <> class ObjClassName<QlYoYInflationTermStructure*> {public: static void output(std::ostream& os) {os << "QlYoYInflationTermStructure";}};+template <> class ObjClassName<QlYoYOptionletVolatilitySurface*> {public: static void output(std::ostream& os) {os << "QlYoYOptionletVolatilitySurface";}}; template <> class ObjClassName<QlZeroCouponInflationSwap*> {public: static void output(std::ostream& os) {os << "QlZeroCouponInflationSwap";}}; template <> class ObjClassName<QlZeroCouponSwap*> {public: static void output(std::ostream& os) {os << "QlZeroCouponSwap";}}; template <> class ObjClassName<QlZeroCouponInflationSwapHelper*> {public: static void output(std::ostream& os) {os << "QlZeroCouponInflationSwapHelper";}};@@ -1082,6 +1271,7 @@ template <> class ObjClassName<SimpleQuote*> {public: static void output(std::ostream& os) {os << "SimpleQuote";}}; template <> class ObjClassName<Simplex*> {public: static void output(std::ostream& os) {os << "Simplex";}}; template <> class ObjClassName<SmileSection*> {public: static void output(std::ostream& os) {os << "SmileSection";}};+template <> class ObjClassName<SoftBarrierOption*> {public: static void output(std::ostream& os) {os << "SoftBarrierOption";}}; template <> class ObjClassName<SoftCallability*> {public: static void output(std::ostream& os) {os << "SoftCallability";}}; template <> class ObjClassName<SpreadCdsHelper*> {public: static void output(std::ostream& os) {os << "SpreadCdsHelper";}}; template <> class ObjClassName<StochasticProcess*> {public: static void output(std::ostream& os) {os << "StochasticProcess";}};@@ -1093,6 +1283,9 @@ template <> class ObjClassName<SuperSharePayoff*> {public: static void output(std::ostream& os) {os << "SuperSharePayoff";}}; template <> class ObjClassName<SvenssonFitting*> {public: static void output(std::ostream& os) {os << "SvenssonFitting";}}; template <> class ObjClassName<Swap*> {public: static void output(std::ostream& os) {os << "Swap";}};+template <> class ObjClassName<ConstNotionalCrossCurrencySwap*> {public: static void output(std::ostream& os) {os << "ConstNotionalCrossCurrencySwap";}};+template <> class ObjClassName<ConstNotionalCrossCurrencyBasisSwap*> {public: static void output(std::ostream& os) {os << "ConstNotionalCrossCurrencyBasisSwap";}};+template <> class ObjClassName<ConstNotionalCrossCurrencyFixedVsFloatingSwap*> {public: static void output(std::ostream& os) {os << "ConstNotionalCrossCurrencyFixedVsFloatingSwap";}}; template <> class ObjClassName<SwapIndex*> {public: static void output(std::ostream& os) {os << "SwapIndex";}}; template <> class ObjClassName<SwapRateHelper*> {public: static void output(std::ostream& os) {os << "SwapRateHelper";}}; template <> class ObjClassName<Swaption*> {public: static void output(std::ostream& os) {os << "Swaption";}};@@ -1108,6 +1301,8 @@ template <> class ObjClassName<TreeVanillaSwapEngine*> {public: static void output(std::ostream& os) {os << "TreeVanillaSwapEngine";}}; template <> class ObjClassName<TypePayoff*> {public: static void output(std::ostream& os) {os << "TypePayoff";}}; template <> class ObjClassName<UpfrontCdsHelper*> {public: static void output(std::ostream& os) {os << "UpfrontCdsHelper";}};+template <> class ObjClassName<UnitOfMeasure*> {public: static void output(std::ostream& os) {os << "UnitOfMeasure";}};+template <> class ObjClassName<UnitOfMeasureConversion*> {public: static void output(std::ostream& os) {os << "UnitOfMeasureConversion";}}; template <> class ObjClassName<VanillaOption*> {public: static void output(std::ostream& os) {os << "VanillaOption";}}; template <> class ObjClassName<VanillaSwap*> {public: static void output(std::ostream& os) {os << "VanillaSwap";}}; template <> class ObjClassName<VarianceGammaEngine*> {public: static void output(std::ostream& os) {os << "VarianceGammaEngine";}};@@ -1118,8 +1313,12 @@ template <> class ObjClassName<YearOnYearInflationSwap*> {public: static void output(std::ostream& os) {os << "YearOnYearInflationSwap";}}; template <> class ObjClassName<YearOnYearInflationSwapHelper*> {public: static void output(std::ostream& os) {os << "YearOnYearInflationSwapHelper";}}; template <> class ObjClassName<YieldTermStructure*> {public: static void output(std::ostream& os) {os << "YieldTermStructure";}};+template <> class ObjClassName<YoYCapFloorTermPriceSurface*> {public: static void output(std::ostream& os) {os << "YoYCapFloorTermPriceSurface";}};+template <> class ObjClassName<YoYInflationCapFloor*> {public: static void output(std::ostream& os) {os << "YoYInflationCapFloor";}};+template <> class ObjClassName<YoYInflationCouponPricer*> {public: static void output(std::ostream& os) {os << "YoYInflationCouponPricer";}}; template <> class ObjClassName<YoYInflationIndex*> {public: static void output(std::ostream& os) {os << "YoYInflationIndex";}}; template <> class ObjClassName<YoYInflationTermStructure*> {public: static void output(std::ostream& os) {os << "YoYInflationTermStructure";}};+template <> class ObjClassName<YoYOptionletVolatilitySurface*> {public: static void output(std::ostream& os) {os << "YoYOptionletVolatilitySurface";}}; template <> class ObjClassName<ZeroCouponBond*> {public: static void output(std::ostream& os) {os << "ZeroCouponBond";}}; template <> class ObjClassName<ZeroCouponInflationSwap*> {public: static void output(std::ostream& os) {os << "ZeroCouponInflationSwap";}}; template <> class ObjClassName<ZeroCouponSwap*> {public: static void output(std::ostream& os) {os << "ZeroCouponSwap";}};
hasquant.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           hasquant-version:        0.5.0.2+version:        0.6.0.0 synopsis:       Bindings to QuantLib description:    Bindings to the QuantLib library. category:       Finance,FFI,Library@@ -19,6 +19,7 @@ build-type:     Simple tested-with:     GHC == 8.10.6+  , GHC == 9.8.4   , GHC == 9.10.3   , GHC == 9.12.4   , GHC == 9.14.1@@ -61,6 +62,7 @@       QuantLib.Type       QuantLib.Math       QuantLib.Currency+      QuantLib.Commodity       QuantLib.Time.Date       QuantLib.Time.Calendar       QuantLib.Time.Schedule@@ -76,22 +78,27 @@       QuantLib.TermStructure.Inflation       QuantLib.TermStructure.Credit       QuantLib.TermStructure.Volatility+      QuantLib.TermStructure.InflationVolatility+      QuantLib.TermStructure.Commodity       QuantLib.Index.InterestRate       QuantLib.Index.Inflation       QuantLib.Index.Equity+      QuantLib.Index.Commodity       QuantLib.Instrument.Bond       QuantLib.Instrument.CapFloor+      QuantLib.Instrument.InflationCapFloor       QuantLib.Instrument.Forward       QuantLib.Process       QuantLib.Instrument.Option       QuantLib.Model       QuantLib.Instrument.Credit       QuantLib.Instrument.Swap+      QuantLib.Instrument.Energy       QuantLib.PricingEngine       QuantLib.Syntax   other-modules:       QuantLib.Internal-      QuantLib.Internal.Enum+      QuantLib.Internal.Common       QuantLib.Internal.Syntax       QuantLib.Internal.CalendarEnum       QuantLib.Internal.Type@@ -129,14 +136,13 @@     extra-libraries:         QuantLib   if os(osx)-    cxx-options: -isystem/opt/homebrew/opt/quantlib/include -isystem/opt/homebrew/include-    include-dirs:-        /opt/homebrew/include+    cxx-options: -isystem/opt/homebrew/opt/quantlib/include -isystem/opt/homebrew/include -isystem/usr/local/opt/quantlib/include -isystem/usr/local/include   build-tool-depends: c2hs:c2hs >= 0.28.8 && < 0.29  executable hasquant_example   main-is: QuantLib/MainExample.hs   other-modules:+      QuantLib.Example.AsianOption       QuantLib.Example.BermudanSwaption       QuantLib.Example.Bond       QuantLib.Example.CallableBond@@ -146,8 +152,10 @@       QuantLib.Example.EquityOption       QuantLib.Example.EquityTotalReturnSwap       QuantLib.Example.FittedBondCurve+      QuantLib.Example.ForwardOption       QuantLib.Example.FRA       QuantLib.Example.FxForward+      QuantLib.Example.Gaussian1dModels       QuantLib.Example.InflationCurve       QuantLib.Example.InflationInstruments       QuantLib.Example.IsdaCds@@ -183,13 +191,21 @@   main-is: QuantLib/MainTest.hs   other-modules:       QuantLib.Spec.Calendars+      QuantLib.Spec.Commodity       QuantLib.Spec.CurrencyAndDayCounter       QuantLib.Spec.DatesAndSchedule       QuantLib.Spec.Examples       QuantLib.Spec.Helpers+      QuantLib.Spec.Index.Commodity+      QuantLib.Spec.Instrument.Energy+      QuantLib.Spec.Instrument.InflationCapFloor+      QuantLib.Spec.Instrument.Option       QuantLib.Spec.InterestRateAndCashFlow       QuantLib.Spec.Syntax       QuantLib.Spec.TermStructure+      QuantLib.Spec.TermStructure.Commodity+      QuantLib.Spec.TermStructure.InflationVolatility+      QuantLib.Example.AsianOption       QuantLib.Example.BermudanSwaption       QuantLib.Example.Bond       QuantLib.Example.CallableBond@@ -199,8 +215,10 @@       QuantLib.Example.EquityOption       QuantLib.Example.EquityTotalReturnSwap       QuantLib.Example.FittedBondCurve+      QuantLib.Example.ForwardOption       QuantLib.Example.FRA       QuantLib.Example.FxForward+      QuantLib.Example.Gaussian1dModels       QuantLib.Example.InflationCurve       QuantLib.Example.InflationInstruments       QuantLib.Example.IsdaCds
+ test/example/QuantLib/Example/AsianOption.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE TemplateHaskell #-}+module QuantLib.Example.AsianOption+  (+    Result(..)+  , run+  ) where+import Data.Time.Calendar++import QuantLib.Instrument+import QuantLib.InterestRate+import QuantLib.Instrument.Option+import QuantLib.Math+import QuantLib.Model()+import QuantLib.PricingEngine+import QuantLib.Process+import QuantLib.Quote+import QuantLib.Settings+import QuantLib.Time.Calendar+import QuantLib.Time.Date hiding(today)+import QuantLib.Time.Schedule+import QuantLib.TermStructure.Volatility+import QuantLib.TermStructure.Yield+import QuantLib.Syntax++-- | Discrete arithmetic average-price Asian put, reproducing the 26-fixing+-- case from QuantLib's own @asianoptions.cpp@ (@testMCDiscreteArithmeticAveragePrice@,+-- data from Levy 1997 as reproduced by Haug): spot 90, strike 87, dividend+-- yield 6%, risk-free rate 2.5%, 11\/12y to maturity, 13% vol, expected NPV+-- 1.7255070456. Cross-checks 'turnbullWakemanAsianEngine' and+-- 'fdBlackScholesAsianEngine' (this module's two new engines) against the+-- already-bound 'mcDiscreteArithmeticAPEngine' on the same instrument.+data Result = Result+  { twR :: Double+  , fdR :: Double+  , mcR :: Double+  }++run :: IO Result+run = do+  setEvaluationDate $ Just today+  dc <- dayCounter (Actual360 False)+  underQ <- simpleQuote 90+  divQ <- simpleQuote 0.06+  riskFreeQ <- simpleQuote 0.025+  ts <- flatForward today riskFreeQ dc Continuous Annual+  divTS <- flatForward today divQ dc Continuous Annual+  volQ <- simpleQuote 0.13+  volTS <- calendar TARGET >>= $(free2nd 'blackConstantVol) today volQ dc+  bsmProc <- blackScholesMertonProcess underQ divTS ts volTS EulerDiscretization False++  let payoff = PlainVanilla $ PlainVanillaPayoff Put strike+      exercise = European $ EuropeanExercise maturity+  option <- discreteAveragingAsianOption Arithmetic 0.0 0 fixingDates payoff exercise++  twEng <- turnbullWakemanAsianEngine bsmProc+  QuantLib.Instrument.setPricingEngine option twEng+  tw <- npv option++  fdEng <- fdBlackScholesAsianEngine bsmProc 100 100 100 Douglas+  QuantLib.Instrument.setPricingEngine option fdEng+  fd <- npv option++  mcEng <- mcDiscreteArithmeticAPEngine LowDiscrepancy bsmProc False False True (Just 2047) Nothing Nothing 0+  QuantLib.Instrument.setPricingEngine option mcEng+  mc <- npv option++  return Result { twR = tw, fdR = fd, mcR = mc }+  where+    today = 1 `january` 2020+    strike = 87+    fixings = 26 :: Int+    len = 11 / 12 :: Double+    dt = len / fromIntegral (fixings - 1)+    -- matches upstream's `timeToDays(t, 360) = lround(t * 360)`+    timeToDays t = round (t * 360 :: Double)+    fixingDates = [addDays (timeToDays (fromIntegral i * dt)) today | i <- [0 .. fixings - 1]]+    maturity = last fixingDates++-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et:
test/example/QuantLib/Example/BermudanSwaption.hs view
@@ -87,7 +87,8 @@   engine <- discountingSwapEngine ts Nothing Nothing Nothing   asSwap swp >>= asInstrument >>= (`setPricingEngine` engine)   fixedATMRate <- fairRate swp-  (swaptions, tms) <- mapAndUnzipM (createHelpers index6m ts) calibrationGrid+  (swaptionHelpers, tms) <- mapAndUnzipM (createHelpers index6m ts) calibrationGrid+  swaptions <- mapM Model.asBlackCalibrationHelper swaptionHelpers   grid <- timeGridFromList' (fromList (concat tms)) 30    (modelG2, g2v, g2p) <- calibrateShortRateModel
+ test/example/QuantLib/Example/ForwardOption.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE TemplateHaskell #-}+module QuantLib.Example.ForwardOption+  (+    Result(..)+  , run+  ) where++import Data.Time.Calendar++import QuantLib.Instrument+import QuantLib.InterestRate+import QuantLib.Instrument.Option+import QuantLib.Math+import QuantLib.PricingEngine+import QuantLib.Process+import QuantLib.Quote+import QuantLib.Settings+import QuantLib.Time.Calendar+import QuantLib.Time.Date hiding(today)+import QuantLib.Time.Schedule+import QuantLib.TermStructure.Volatility+import QuantLib.TermStructure.Yield+import QuantLib.Syntax++-- | Forward-starting (\"cliquet-style\") vanilla options, reproducing+-- QuantLib's own @forwardoption.cpp@ @testValues@ golden case (Haug,+-- \"Option pricing formulas\", p.37\/VBA code): moneyness 1.1, spot 60,+-- dividend yield 4%, risk-free rate 8%, reset in 0.25y, maturity in 1y,+-- 30% vol; expected NPV 4.4064 (call) \/ 8.2971 (put) under+-- 'forwardEuropeanEngine' (the @AnalyticEuropeanEngine@ instantiation of+-- @ForwardVanillaEngine\<Engine\>@). The other 5 forward-starting engines+-- added alongside it are exercised as self-consistency checks against this+-- reference: the finite-differences and Monte Carlo European forward+-- engines should reproduce the same (European-exercise) price; the two+-- American approximation engines, priced on an otherwise identical+-- American-exercise instrument, should be at least as valuable as the+-- European price (the right to exercise early is never a disadvantage);+-- and the Heston forward engine, with its process parameters chosen so+-- Heston degenerates to (near-)deterministic Black-Scholes volatility,+-- should reproduce the same price as the BS analytic engine.+data Result = Result+  { europeanCallR :: Double+  , europeanPutR :: Double+  , fdEuropeanR :: Double+  , mcEuropeanR :: Double+  , hestonEuropeanR :: Double+  , bawAmericanR :: Double+  , bjsAmericanR :: Double+  }++run :: IO Result+run = do+  setEvaluationDate $ Just today+  dc <- dayCounter (Actual360 False)+  spotQ <- simpleQuote spot+  qQ <- simpleQuote divYield+  rQ <- simpleQuote riskFreeRate+  qTS <- flatForward today qQ dc Continuous Annual+  rTS <- flatForward today rQ dc Continuous Annual+  volQ <- simpleQuote vol+  volTS <- calendar TARGET >>= $(free2nd 'blackConstantVol) today volQ dc+  bsmProc <- blackScholesMertonProcess spotQ qTS rTS volTS EulerDiscretization False++  let payoff t = PlainVanilla $ PlainVanillaPayoff t 0.0+      europeanExercise = European $ EuropeanExercise maturity+      americanExercise = American Nothing maturity False++  callOpt <- forwardVanillaOption moneyness resetDate (payoff Call) europeanExercise+  putOpt <- forwardVanillaOption moneyness resetDate (payoff Put) europeanExercise++  europeanEng <- forwardEuropeanEngine bsmProc+  QuantLib.Instrument.setPricingEngine callOpt europeanEng+  europeanCall <- npv callOpt+  QuantLib.Instrument.setPricingEngine putOpt europeanEng+  europeanPut <- npv putOpt++  fdEng <- forwardFdBlackScholesVanillaEngine bsmProc+  QuantLib.Instrument.setPricingEngine callOpt fdEng+  fdEuropean <- npv callOpt++  mcEng <- mcForwardEuropeanBSEngine LowDiscrepancy bsmProc (Just 1) Nothing False False (Just 32768) Nothing Nothing 0+  QuantLib.Instrument.setPricingEngine callOpt mcEng+  mcEuropean <- npv callOpt++  hestonProc <- hestonProcess rTS (Just qTS) spotQ (vol*vol) 1.0 (vol*vol) 0.3 0.0 QuadraticExponentialMartingale+  hestonEng <- analyticHestonForwardEuropeanEngine hestonProc 144+  QuantLib.Instrument.setPricingEngine callOpt hestonEng+  hestonEuropean <- npv callOpt++  americanOpt <- forwardVanillaOption moneyness resetDate (payoff Call) americanExercise+  bawEng <- forwardBaroneAdesiWhaleyEngine bsmProc+  QuantLib.Instrument.setPricingEngine americanOpt bawEng+  bawAmerican <- npv americanOpt++  bjsEng <- forwardBjerksundStenslandEngine bsmProc+  QuantLib.Instrument.setPricingEngine americanOpt bjsEng+  bjsAmerican <- npv americanOpt++  return Result+    { europeanCallR = europeanCall+    , europeanPutR = europeanPut+    , fdEuropeanR = fdEuropean+    , mcEuropeanR = mcEuropean+    , hestonEuropeanR = hestonEuropean+    , bawAmericanR = bawAmerican+    , bjsAmericanR = bjsAmerican+    }+  where+    today = 1 `january` 2020+    moneyness = 1.1+    spot = 60+    divYield = 0.04+    riskFreeRate = 0.08+    vol = 0.30+    -- matches upstream's `timeToDays(t, 360) = lround(t * 360)`+    timeToDays t = round (t * 360.0)+    resetDate = addDays (timeToDays (0.25 :: Double)) today+    maturity = addDays (timeToDays (1.0 :: Double)) today++-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et:
+ test/example/QuantLib/Example/Gaussian1dModels.hs view
@@ -0,0 +1,260 @@+{-# LANGUAGE TupleSections #-}+module QuantLib.Example.Gaussian1dModels+  (+    Result(..)+  , CalibrationCheck(..)+  , run+  ) where+import Control.Monad (forM, forM_, replicateM)+import Data.Maybe (mapMaybe)++import qualified QuantLib.CashFlow as CF+import qualified QuantLib.Index.InterestRate as IR+import QuantLib.InterestRate+import QuantLib.Instrument+import QuantLib.Instrument.Option (BermudanExercise(..))+import QuantLib.Instrument.Swap+import QuantLib.Math (EndCriteria(..), OptimizationMethod(..))+import QuantLib.Model hiding(setPricingEngine)+import qualified QuantLib.Model as Model+import QuantLib.PricingEngine+import QuantLib.Quote+import QuantLib.TermStructure.Volatility+import qualified QuantLib.TermStructure.Yield as TS+import QuantLib.Time.Calendar+import QuantLib.Time.Date+import QuantLib.Time.Schedule+import QuantLib.Settings++-- |Per-helper (modelValue, marketValue, impliedVolatility) after calibrating a basket --+-- what upstream's @printModelCalibration@ prints, and the strongest reachable calibration+-- check: 'calibrationBasket' returns generic 'BlackCalibrationHelper's (upstream erases to+-- the base inside @basketgeneratingengine.cpp@ before the vector is returned), so nominal\/+-- strike\/expiry on individual basket elements are not recoverable from hasquant -- see+-- CLAUDE.md's "A C++ return type erased by upstream itself" note.+data CalibrationCheck = CalibrationCheck+  { ccModelValue :: Double+  , ccMarketValue :: Double+  , ccImpliedVol :: Double+  } deriving Show++data Result = Result+  { basketNaiveLen :: Int             -- ^calibration basket size, Naive mode (bermudan swaption)+  , basketMsdgLen :: Int              -- ^..., MaturityStrikeByDeltaGamma mode+  , basketCalibration :: [CalibrationCheck] -- ^Naive basket, after calibrateVolatilitiesIterative+  , npvAtmGsr :: Double               -- ^bermudan swaption NPV, ATM-calibrated GSR+  , npvDealStrikeGsr :: Double        -- ^..., after recalibrating to the MaturityStrikeByDeltaGamma basket+  , amortizingBasketLen :: Int        -- ^MSDG basket size for the amortizing-nominal underlying+  , callRightBasketLen0 :: Int        -- ^MSDG basket size for the bond call right, oas=0+  , npvCallRight0 :: Double           -- ^bond call right NPV, oas=0+  , callRightBasketLen100 :: Int      -- ^..., oas=100bp+  , npvCallRight100 :: Double         -- ^bond call right NPV, oas=100bp+  , underlyingCmsSwapNpv :: Double    -- ^FloatFloatSwap underlying NPV (LinearTsrPricer/BlackIborCouponPricer)+  , cmsLegNpv :: Double+  , euriborLegNpv :: Double+  , floatBasketNaiveLen :: Int        -- ^Naive basket size for the CMS-vs-Euribor float swaption+  , npvFloatGsr :: Double             -- ^float swaption NPV under (Naive-basket-calibrated) GSR+  , underlyingValueGsr :: Double      -- ^float swaption's "underlyingValue" additional result, GSR+  , npvFloatMarkov :: Double          -- ^float swaption NPV under MarkovFunctional+  , underlyingValueMarkovPreCalib :: Double  -- ^"underlyingValue" before coterminal calibration+  , underlyingValueMarkovPostCalib :: Double -- ^"underlyingValue" after coterminal calibration+  } deriving Show++underlyingValueOf :: FloatFloatSwaption -> IO Double+underlyingValueOf i = do+  results <- additionalResults i+  case mapMaybe (\(k, v) -> if k == "underlyingValue" then Just v else Nothing) results of+    [RealVal v] -> return v+    _ -> error "underlyingValueOf: expected exactly one RealVal \"underlyingValue\" additional result"++calibrationCheck :: BlackCalibrationHelper -> IO CalibrationCheck+calibrationCheck h = do+  mv <- Model.modelValue h+  ccv <- Model.marketValue h+  vol <- Model.impliedVolatility h mv 1.0e-6 1000 0.0 2.0+  return CalibrationCheck { ccModelValue = mv, ccMarketValue = ccv, ccImpliedVol = vol }++lmMethod :: OptimizationMethod+lmMethod = LevenbergMarquardt 1.0e-8 1.0e-8 1.0e-8 False++lmEndCriteria :: EndCriteria+-- Only the max-iterations field is actually consulted by LevenbergMarquardt (per the+-- upstream example's own comment at ex/Gaussian1dModels.cpp:257-258).+lmEndCriteria = EndCriteria 1000 10 1.0e-8 1.0e-8 1.0e-8++run :: IO Result+run = do+  cal <- calendar TARGET+  setEvaluationDate (Just refDate)+  dc365 <- dayCounter Actual365FixedStandard+  thirty360bb <- dayCounter Thirty360BondBasis+  act360 <- dayCounter (Actual360 False)++  forward6mQuote <- simpleQuote forward6mLevel+  oisQuote <- simpleQuote oisLevel+  yts6m <- TS.flatForward refDate forward6mQuote dc365 Continuous Annual+  ytsOis <- TS.flatForward refDate oisQuote dc365 Continuous Annual+  euribor6m <- IR.iborIndex IR.Euribor6M (Just yts6m)++  volQuote <- simpleQuote volLevel+  swaptionVol <- constantSwaptionVolatility 0 cal ModifiedFollowing volQuote dc365 ShiftedLognormal 0.0++  effectiveDate <- advance cal refDate (2, Days) Following False+  maturity <- advance cal effectiveDate (10, Years) Following False+  fixedSchedule <- schedule (Just effectiveDate) maturity (1, Years) cal ModifiedFollowing ModifiedFollowing Forward False Nothing Nothing+  floatSchedule <- schedule (Just effectiveDate) maturity (6, Months) cal ModifiedFollowing ModifiedFollowing Forward False Nothing Nothing++  -- 1. A standard 10y bermudan payer swaption, struck at 4%, exercisable yearly.+  vanilla <- vanillaSwap Payer 1.0 fixedSchedule strike thirty360bb floatSchedule euribor6m 0.00 act360 Nothing Nothing+  underlying <- nonstandardSwapFromVanilla vanilla++  -- Exercise dates: fixedSchedule[1..9], each shifted back 2 business days -- upstream loops+  -- i = 1..9 over the *schedule*'s own dates, not the underlying's coupon accrual starts.+  fixedDates <- dates fixedSchedule+  exerciseDates <- forM (take 9 (drop 1 fixedDates)) $ \d -> advance cal d (-2, Days) Following False+  let ex = Bermudan (BermudanExercise exerciseDates False)+  swaption1 <- nonstandardSwaption underlying ex Physical PhysicalOTC++  -- One-factor GSR model with piecewise volatility adapted to the exercise dates.+  let stepDates = init exerciseDates+  gsrVolQuotes <- replicateM (length stepDates + 1) (simpleQuote 0.01)+  gsrReversionQuote <- simpleQuote reversion+  gsrModel <- gsr yts6m stepDates gsrVolQuotes gsrReversionQuote 60.0+  gsrGm <- gsrAsGaussian1dModel gsrModel++  swaptionEngine <- gaussian1dSwaptionEngine gsrGm 64 7.0 True False (Just ytsOis) None+  nonstandardSwaptionEngine <- gaussian1dNonstandardSwaptionEngine gsrGm 64 7.0 True False Nothing (Just ytsOis) None+  setPricingEngine swaption1 nonstandardSwaptionEngine++  swapBase <- IR.liborSwapIndex IR.EuriborSwapIsdaFixA (10, Years) (Just yts6m) (Just ytsOis)++  -- Naive calibration basket: ATM swaptions adapted to the exercise dates and maturity.+  basket1 <- calibrationBasket swaption1 swapBase swaptionVol CalibrationBasketNaive+  forM_ basket1 (`Model.setPricingEngine` swaptionEngine)+  calibrateVolatilitiesIterative gsrModel basket1 lmMethod lmEndCriteria Nothing []+  calib1 <- mapM calibrationCheck basket1+  npv1 <- npv swaption1++  -- MaturityStrikeByDeltaGamma basket: maturity/strike/nominal match the underlying's NPV,+  -- delta and gamma at each exercise date -- recalibrate and reprice.+  basket2 <- calibrationBasket swaption1 swapBase swaptionVol MaturityStrikeByDeltaGamma+  forM_ basket2 (`Model.setPricingEngine` swaptionEngine)+  calibrateVolatilitiesIterative gsrModel basket2 lmMethod lmEndCriteria Nothing []+  npv2 <- npv swaption1++  -- 2. Linear amortizing nominal schedule, same exercise dates.+  let n = length fixedDates - 1+      nominalFixed = [1.0 - fromIntegral i / fromIntegral n | i <- [0 .. n - 1]]+      nominalFloating = concatMap (\x -> [x, x]) nominalFixed -- 6m vs. 1y: two float periods per fixed one+      strikes = replicate n strike+  underlying2 <- nonstandardSwap Payer nominalFixed nominalFloating fixedSchedule strikes thirty360bb+    floatSchedule euribor6m 1.0 0.0 act360 False False Nothing+  swaption2 <- nonstandardSwaption underlying2 ex Physical PhysicalOTC+  setPricingEngine swaption2 nonstandardSwaptionEngine+  basket3 <- calibrationBasket swaption2 swapBase swaptionVol MaturityStrikeByDeltaGamma++  -- 3. Bond call right, modeled as a rebated-exercise swaption on a one-leg swap with+  -- notional reimbursement at maturity.+  let nominalFixed2 = replicate n 1.0+      nominalFloating2 = replicate (2 * n) 0.0 -- null the second leg+  underlying3 <- nonstandardSwap Receiver nominalFixed2 nominalFloating2 fixedSchedule strikes thirty360bb+    floatSchedule euribor6m 1.0 0.0 act360 False True Nothing -- final capital exchange+  let exercise2 = Rebated ex (-1.0) 2 cal Following+  swaption3 <- nonstandardSwaption underlying3 exercise2 Physical PhysicalOTC++  oasQuote <- simpleQuote 0.0+  nonstandardSwaptionEngine2 <- gaussian1dNonstandardSwaptionEngine gsrGm 64 7.0 True False (Just oasQuote) Nothing None -- discount on 6m, not OIS+  setPricingEngine swaption3 nonstandardSwaptionEngine2++  basket4 <- calibrationBasket swaption3 swapBase swaptionVol MaturityStrikeByDeltaGamma+  forM_ basket4 (`Model.setPricingEngine` swaptionEngine)+  calibrateVolatilitiesIterative gsrModel basket4 lmMethod lmEndCriteria Nothing []+  npv3 <- npv swaption3++  -- Add a 100bp credit spread and regenerate the basket.+  _ <- setValue oasQuote 0.01+  basket5 <- calibrationBasket swaption3 swapBase swaptionVol MaturityStrikeByDeltaGamma+  forM_ basket5 (`Model.setPricingEngine` swaptionEngine)+  calibrateVolatilitiesIterative gsrModel basket5 lmMethod lmEndCriteria Nothing []+  npv4 <- npv swaption3++  -- 4. CMS 10y vs Euribor 6m float-float swaption, exercisable yearly.+  underlying4 <- floatFloatSwap Payer 1.0 1.0 fixedSchedule swapBase thirty360bb floatSchedule euribor6m act360+    defaultFloatFloatSwapOpts{ffsSpread2 = 0.0010}+  swaption4 <- floatFloatSwaption underlying4 ex Physical PhysicalOTC+  floatSwaptionEngine <- gaussian1dFloatFloatSwaptionEngine gsrGm 64 7.0 True False Nothing (Just ytsOis) True None+  setPricingEngine swaption4 floatSwaptionEngine++  reversionQuote <- simpleQuote reversion+  cmsPricer <- CF.linearTsrPricer swaptionVol reversionQuote Nothing (CF.LinearTsrPricerSettings CF.LinearTsrRateBound Nothing)+  -- Only the CMS leg (leg 0) needs an explicit pricer -- a plain (uncapped/unfloored) Euribor+  -- leg computes its forecast fixing directly, with no pricer required (confirmed in the+  -- increment 2 smoke test).+  leg0 <- leg underlying4 0+  CF.setCouponPricer leg0 cmsPricer++  swapPricer <- discountingSwapEngine ytsOis Nothing Nothing Nothing+  setPricingEngine underlying4 swapPricer+  npv5 <- npv underlying4+  legNpv0 <- legNPV underlying4 0+  legNpv1 <- legNPV underlying4 1++  basket6 <- floatFloatSwaptionCalibrationBasket swaption4 swapBase swaptionVol CalibrationBasketNaive+  forM_ basket6 (`Model.setPricingEngine` swaptionEngine)+  calibrateVolatilitiesIterative gsrModel basket6 lmMethod lmEndCriteria Nothing []+  npv6 <- npv swaption4+  underlyingValGsr <- underlyingValueOf swaption4++  -- 5. The Markov-functional model: calibrates to the underlying's own smile directly+  -- (via its step-date/tenor/swapIndexBase construction), unlike GSR which only sees the+  -- coterminal calibration basket.+  let markovStepDates = exerciseDates+      markovSigmas = replicate (length markovStepDates + 1) 0.01+      cmsTenors = replicate (length markovStepDates) (10, Years) :: [(Word, TimeUnit)]+  markov <- markovFunctional yts6m reversion markovStepDates markovSigmas swaptionVol markovStepDates cmsTenors swapBase 16+  markovGm <- markovFunctionalAsGaussian1dModel markov++  swaptionEngineMarkov <- gaussian1dSwaptionEngine markovGm 8 5.0 True False (Just ytsOis) None+  floatEngineMarkov <- gaussian1dFloatFloatSwaptionEngine markovGm 16 7.0 True False Nothing (Just ytsOis) True None+  setPricingEngine swaption4 floatEngineMarkov+  npv7 <- npv swaption4+  underlyingValMarkovPre <- underlyingValueOf swaption4++  -- Calibrate the Markov model's own sigma function to the coterminal ATM swaptions basket+  -- (basket6, from above) -- this shouldn't move the underlying-smile match much, since that+  -- was already fixed by the model's construction.+  basket6ch <- mapM Model.asCalibrationHelper basket6+  forM_ basket6 (`Model.setPricingEngine` swaptionEngineMarkov)+  Model.calibrate markov (map (, 1.0) basket6ch) lmMethod lmEndCriteria Nothing []+  underlyingValMarkovPost <- underlyingValueOf swaption4++  return Result+    { basketNaiveLen = length basket1+    , basketMsdgLen = length basket2+    , basketCalibration = calib1+    , npvAtmGsr = npv1+    , npvDealStrikeGsr = npv2+    , amortizingBasketLen = length basket3+    , callRightBasketLen0 = length basket4+    , npvCallRight0 = npv3+    , callRightBasketLen100 = length basket5+    , npvCallRight100 = npv4+    , underlyingCmsSwapNpv = npv5+    , cmsLegNpv = legNpv0+    , euriborLegNpv = legNpv1+    , floatBasketNaiveLen = length basket6+    , npvFloatGsr = npv6+    , underlyingValueGsr = underlyingValGsr+    , npvFloatMarkov = npv7+    , underlyingValueMarkovPreCalib = underlyingValMarkovPre+    , underlyingValueMarkovPostCalib = underlyingValMarkovPost+    }+  where+    refDate = 30 `april` 2014+    forward6mLevel = 0.025+    oisLevel = 0.02+    volLevel = 0.20+    strike = 0.04+    reversion = 0.01++-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et:
test/example/QuantLib/Example/InflationInstruments.hs view
@@ -224,7 +224,7 @@   cpiLegNpv <- npv cpiLegBond    -- yoyInflationLeg exercised via the generic Leg-based 'swap'' constructor-  yoyL <- CF.yoyInflationLeg yoySchedule cal yidx1 obsLag CPILinear [nominal] dc Unadjusted [0] [1.0] [0.0]+  yoyL <- CF.yoyInflationLeg yoySchedule cal yidx1 obsLag CPILinear [nominal] dc Unadjusted [0] [1.0] [0.0] [] []   fixedIR <- interestRate flatRate dc Compounded Annual   fixedL <- CF.fixedRateLeg fixedSchedule [nominal] [fixedIR] Unadjusted dc cal   yoyLegSwap <- swap' [(fixedL, True), (yoyL, False)]
test/example/QuantLib/Example/ShortRateModels.hs view
@@ -17,7 +17,7 @@ import QuantLib.Instrument(npv, setPricingEngine) import QuantLib.Instrument.Swap hiding(startDate) import QuantLib.Math-import QuantLib.Model hiding (setPricingEngine, value)+import QuantLib.Model hiding(setPricingEngine, value) import qualified QuantLib.Model as Model import QuantLib.PricingEngine import QuantLib.Quote@@ -70,12 +70,13 @@   sw <- runSwaps   cirDF <- runExtendedCirDiscountFactor   vasicekDF <- runVasicekSmallMeanReversion+  fcb <- futuresConvexityChecks   pure Result     { cachedHullWhite = hw     , cachedHullWhiteFixedReversion = hwFixed     , cachedHullWhite2 = hw2     , swaps = sw-    , futuresConvexityBias = futuresConvexityChecks+    , futuresConvexityBias = fcb     , extendedCirDiscountFactor = cirDF     , vasicekDiscountFactorSmallMeanReversion = vasicekDF     }@@ -193,8 +194,8 @@     rates = [0.02, 0.04, 0.06]  -- |@testFuturesConvexityBias@: G. Kirikos, D. Novak, \"Convexity Conundrums\", Risk Magazine, March 1997.-futuresConvexityChecks :: [ConvexityCheck]-futuresConvexityChecks = map mkCheck convexityData+futuresConvexityChecks :: IO [ConvexityCheck]+futuresConvexityChecks = mapM mkCheck convexityData   where     futureQuote = 94.0     sigma = 0.015@@ -203,11 +204,13 @@     convexityData =       [ (5.25, 0.03, 0.0573037), (5.25, 1e-4, 0.0568627), (5.25, 0.0, 0.0568611)       , (5.001, 0.03, 0.0575736), (5.0, 0.03, 0.0575747) ]-    mkCheck (bigT, a, expected) = ConvexityCheck-      { convexityT = bigT, convexityA = a-      , expectedForward = expected-      , calculatedForward = futureImpliedRate - convexityBias futureQuote t bigT sigma a-      }+    mkCheck (bigT, a, expected) = do+      bias <- convexityBias futureQuote t bigT sigma a+      pure ConvexityCheck+        { convexityT = bigT, convexityA = a+        , expectedForward = expected+        , calculatedForward = futureImpliedRate - bias+        }  -- |@testExtendedCoxIngersollRossDiscountFactor@. runExtendedCirDiscountFactor :: IO DiscountCheck
+ test/hspec/QuantLib/Spec/Commodity.hs view
@@ -0,0 +1,196 @@+module QuantLib.Spec.Commodity (spec) where++import Test.Hspec++import Data.Time.Calendar(addDays)+import QuantLib.Time.Date+import QuantLib.Time.Calendar(calendar, adjust, CalendarConstructor(..), BusinessDayConvention(..))+import QuantLib.Currency(code)+import QuantLib.Commodity++spec :: Spec+spec = do+  describe "CommodityType" $ do+    it "round-trips code/name" $ do+      ho <- commodityType "HO" "Heating Oil"+      commodityTypeCode ho `shouldBe` "HO"+      commodityTypeName ho `shouldBe` "Heating Oil"+      commodityTypeEmpty ho `shouldBe` False++    it "equality is by code" $ do+      ho1 <- commodityType "HO" "Heating Oil"+      ho2 <- commodityType "HO" "Heating Oil (again)"+      wti <- commodityType "CL" "WTI Crude"+      ho1 `shouldBe` ho2+      ho1 `shouldNotBe` wti++    it "has a fixed null placeholder" $ do+      n1 <- nullCommodityType+      n2 <- nullCommodityType+      n1 `shouldBe` n2+      commodityTypeCode n1 `shouldBe` "<NULL>"++  describe "UnitOfMeasure" $ do+    it "round-trips name/code/type" $ do+      u <- unitOfMeasure "Barrels" "BBL" Volume+      unitOfMeasureName u `shouldBe` "Barrels"+      unitOfMeasureCode u `shouldBe` "BBL"+      unitOfMeasureType u `shouldBe` Volume+      unitOfMeasureEmpty u `shouldBe` False++    it "equality is by code" $ do+      u1 <- unitOfMeasure "Barrels" "BBL" Volume+      u2 <- unitOfMeasure "Barrels (again)" "BBL" Volume+      u1 `shouldBe` u2++    it "renames the Quantity tag to QuantityUnit to avoid clashing with the Quantity class" $ do+      u <- unitOfMeasure "Lots" "LOT" QuantityUnit+      unitOfMeasureType u `shouldBe` QuantityUnit++    it "has the petroleum and lot predefined units, each with the expected code" $ do+      lot <- lotUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      mt <- mtUnitOfMeasure+      mb <- mbUnitOfMeasure+      gal <- gallonUnitOfMeasure+      litre <- litreUnitOfMeasure+      kl <- kilolitreUnitOfMeasure+      tkl <- tokyoKilolitreUnitOfMeasure+      map unitOfMeasureCode [lot, bbl, mt, mb, gal, litre, kl, tkl]+        `shouldBe` ["Lot", "BBL", "MT", "MB", "GAL", "l", "kl", "KL_tk"]++  describe "PaymentTerm" $ do+    it "round-trips name/eventType/offsetDays/calendar" $ do+      cal <- calendar BrazilSettlement+      pt <- paymentTerm "Pricing end + 5 days" PricingDate 5 cal+      paymentTermName pt `shouldBe` "Pricing end + 5 days"+      paymentTermEventType pt `shouldBe` PricingDate+      paymentTermOffsetDays pt `shouldBe` 5+      paymentTermEmpty pt `shouldBe` False+      cal' <- paymentTermCalendar pt+      show cal' `shouldBe` show cal++    it "computes the payment date as the calendar-adjusted offset" $ do+      cal <- calendar BrazilSettlement+      pt <- paymentTerm "Trade + 2 days" TradeDate 2 cal+      let d = 3 `january` 2024+      expected <- adjust cal (addDays 2 d) Following+      paymentTermGetPaymentDate pt d `shouldReturn` expected++  describe "Quantity" $ do+    it "rounds the amount per the unit of measure's rounding convention, unit/type unchanged" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      let (ct, uom, amt) = roundedQuantity (ho, bbl, 1.006)+      amt `shouldBe` 1.0+      ct `shouldBe` ho+      uom `shouldBe` bbl++    it "considers equal-unit quantities with the same amount close" $ do+      nullCt <- nullCommodityType+      bbl <- barrelUnitOfMeasure+      close <- closeQuantity (nullCt, bbl, 1000) (nullCt, bbl, 1000) 42+      close `shouldBe` True++    it "throws comparing quantities in different units with no conversion setting configured" $ do+      nullCt <- nullCommodityType+      bbl <- barrelUnitOfMeasure+      gal <- gallonUnitOfMeasure+      closeQuantity (nullCt, bbl, 1) (nullCt, gal, 42) 42 `shouldThrow` anyException++  describe "UnitOfMeasureConversion" $ do+    it "round-trips source/target/commodityType/type/factor/code" $ do+      nullCt <- nullCommodityType+      mb <- mbUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      conv <- unitOfMeasureConversion nullCt mb bbl 1000+      src <- unitOfMeasureConversionSource conv+      tgt <- unitOfMeasureConversionTarget conv+      ct <- unitOfMeasureConversionCommodityType conv+      src `shouldBe` mb+      tgt `shouldBe` bbl+      ct `shouldBe` nullCt+      unitOfMeasureConversionType conv `shouldBe` UomDirect+      unitOfMeasureConversionFactor conv `shouldBe` 1000++    it "converts a quantity from source to target" $ do+      nullCt <- nullCommodityType+      mb <- mbUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      conv <- unitOfMeasureConversion nullCt mb bbl 1000+      (ct, uom, amt) <- convertQuantity conv (nullCt, mb, 1000)+      ct `shouldBe` nullCt+      uom `shouldBe` bbl+      amt `shouldBe` 1000000++    -- Ported from test-suite/commodityunitofmeasure.cpp's testDirect: a direct conversion built+    -- by hand must agree with the manager's pre-populated lookup for the same unit pair.+    it "agrees with the pre-populated manager lookup (ported testDirect, MB to BBL leg)" $ do+      nullCt <- nullCommodityType+      mb <- mbUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      direct <- unitOfMeasureConversion nullCt mb bbl 1000+      actual <- convertQuantity direct (nullCt, mb, 1000)+      looked <- lookupUomConversion nullCt bbl mb UomDirect+      calc <- convertQuantity looked (nullCt, mb, 1000)+      isClose <- closeQuantity calc actual 42+      isClose `shouldBe` True++    it "agrees with the pre-populated manager lookup (ported testDirect, BBL to Gallon leg)" $ do+      nullCt <- nullCommodityType+      bbl <- barrelUnitOfMeasure+      gal <- gallonUnitOfMeasure+      direct <- unitOfMeasureConversion nullCt bbl gal 42+      actual <- convertQuantity direct (nullCt, gal, 1000)+      looked <- lookupUomConversion nullCt bbl gal UomDirect+      calc <- convertQuantity looked (nullCt, gal, 1000)+      isClose <- closeQuantity calc actual 42+      isClose `shouldBe` True++    it "chains two conversions sharing a common unit" $ do+      nullCt <- nullCommodityType+      mb <- mbUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      gal <- gallonUnitOfMeasure+      mbToBbl <- unitOfMeasureConversion nullCt mb bbl 1000+      bblToGal <- unitOfMeasureConversion nullCt bbl gal 42+      chained <- chainUnitOfMeasureConversion mbToBbl bblToGal+      unitOfMeasureConversionType chained `shouldBe` UomDerived+      (_, uom, amt) <- convertQuantity chained (nullCt, mb, 1)+      uom `shouldBe` gal+      amt `shouldBe` 42000++  describe "UnitOfMeasureConversionManager" $ do+    it "resolves petroleum conversions via triangulation, pre-populated before any add" $ do+      nullCt <- nullCommodityType+      litre <- litreUnitOfMeasure+      gal <- gallonUnitOfMeasure+      conv <- lookupUomConversion nullCt litre gal UomDerived+      src <- unitOfMeasureConversionSource conv+      tgt <- unitOfMeasureConversionTarget conv+      [src, tgt] `shouldSatisfy` \l -> litre `elem` l && gal `elem` l++    it "add/clear round-trip: a direct conversion registered via addUomConversion is found by a\+       \ direct lookup, and clear discards it" $ do+      ho <- commodityType "HO" "Heating Oil"+      lot <- lotUnitOfMeasure+      bbl <- barrelUnitOfMeasure+      conv <- unitOfMeasureConversion ho lot bbl 500+      addUomConversion conv+      found <- lookupUomConversion ho lot bbl UomDirect+      unitOfMeasureConversionFactor found `shouldBe` 500+      clearUomConversions+      lookupUomConversion ho lot bbl UomDirect `shouldThrow` anyException++  describe "CommoditySettings" $ do+    it "defaults to USD and barrels, and round-trips a new setting" $ do+      origCcy <- commoditySettingsCurrency+      origUom <- commoditySettingsUnitOfMeasure+      code origCcy `shouldBe` "USD"+      unitOfMeasureCode origUom `shouldBe` "BBL"++      mt <- mtUnitOfMeasure+      setCommoditySettingsUnitOfMeasure mt+      commoditySettingsUnitOfMeasure `shouldReturn` mt+      setCommoditySettingsUnitOfMeasure origUom+      commoditySettingsUnitOfMeasure `shouldReturn` origUom
test/hspec/QuantLib/Spec/DatesAndSchedule.hs view
@@ -3,6 +3,7 @@  import Prelude hiding(until, head) +import Control.Exception(SomeException, evaluate, try) import Test.Hspec import Test.Hspec.QuickCheck(prop) import Test.QuickCheck.Monadic as Q(assert, monadicIO, run)@@ -121,8 +122,13 @@         \ds ->           monadicIO $ do             c <- run $ calendar RussiaSettlement-            s <- run $ fromDates (map validDay ds) c Unadjusted+            s <- run $ fromDates (map validDay ds) c Unadjusted Nothing Nothing Nothing Nothing             run $ dates s `shouldReturn` map validDay ds+      it "from dates with optional tenor/rule/conventions set" $ do+        cal <- calendar RussiaSettlement+        let ds = [20 `december` 2012, 21 `december` 2012, 21 `january` 2013]+        s <- fromDates ds cal Unadjusted (Just Following) (Just (1, Months)) (Just Forward) (Just False)+        dates s `shouldReturn` ds        it "daily" $         Settings.keepingSettings' $ do@@ -145,3 +151,45 @@           -- ql.Schedule(ql.Date(28, 3, 2013), ql.Date(30, 3, 2015), ql.Period(1, ql.Years), ql.TARGET(), ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Forward, True).dates()           (schedule (Just $ 28 `march` 2013) (30 `march` 2015) (1, Years) cal Unadjusted Unadjusted Forward True Nothing Nothing >>= dates)             `shouldReturn` [28 `march` 2013, 31 `march` 2014, 30 `march` 2015]++    -- regression tests for QuantLib.Settings.keepingSettings/keepingSettings' themselves: every+    -- other test in this suite trusts these brackets to restore the evaluation date, so their own+    -- restore behaviour -- including on an exception raised inside the bracketed action -- is+    -- worth pinning down directly rather than only assuming it from Control.Exception.bracket's+    -- documented semantics.+    describe "settings" $ do+      it "keepingSettings restores the evaluation date set inside it, on normal completion" $ do+        before' <- Settings.evaluationDate+        let inside = addDays 365 before'+        Settings.keepingSettings $ Settings.setEvaluationDate (Just inside)+        after' <- Settings.evaluationDate+        after' `shouldBe` before'++      it "keepingSettings' restores the evaluation date set inside it, on normal completion" $ do+        before' <- Settings.evaluationDate+        let inside = addDays 365 before'+        Settings.keepingSettings' $ Settings.setEvaluationDate (Just inside)+        after' <- Settings.evaluationDate+        after' `shouldBe` before'++      it "keepingSettings restores the evaluation date even when the bracketed action throws" $ do+        before' <- Settings.evaluationDate+        let inside = addDays 365 before'+        (result :: Either SomeException ()) <- try $ Settings.keepingSettings $ do+          Settings.setEvaluationDate (Just inside)+          _ <- evaluate (error "deliberate failure inside keepingSettings" :: ())+          return ()+        result `shouldSatisfy` either (const True) (const False)+        after' <- Settings.evaluationDate+        after' `shouldBe` before'++      it "keepingSettings' restores the evaluation date even when the bracketed action throws" $ do+        before' <- Settings.evaluationDate+        let inside = addDays 365 before'+        (result :: Either SomeException ()) <- try $ Settings.keepingSettings' $ do+          Settings.setEvaluationDate (Just inside)+          _ <- evaluate (error "deliberate failure inside keepingSettings'" :: ())+          return ()+        result `shouldSatisfy` either (const True) (const False)+        after' <- Settings.evaluationDate+        after' `shouldBe` before'
test/hspec/QuantLib/Spec/Examples.hs view
@@ -35,6 +35,9 @@ import qualified QuantLib.Example.TARF as TARFExample import qualified QuantLib.Example.FittedBondCurve as FittedBondCurveExample import qualified QuantLib.Example.ShortRateModels as ShortRateModelsExample+import qualified QuantLib.Example.Gaussian1dModels as Gaussian1dModelsExample+import qualified QuantLib.Example.AsianOption as AsianOptionExample+import qualified QuantLib.Example.ForwardOption as ForwardOptionExample  import QuantLib.Spec.Helpers(closePrec, listClose, listCloseRel, binomialsClose) @@ -95,7 +98,7 @@         c <- calendar UnitedKingdomSettlement         l <- CF.leg [(fromGregorian 2013 1 1, 1000)]         b <- B.bond' 2 c 1000 (Just (fromGregorian 2013 1 1)) (Just (fromGregorian 2012 1 1)) l-        B.maturityDate b `shouldBe` Just (fromGregorian 2013 1 1)+        B.maturityDate b `shouldReturn` Just (fromGregorian 2013 1 1)      describe "Amortizing bonds" $ do       it "AmortizingFixedRateBond reproduces upstream's sinking-fund pmt values" $ do@@ -536,3 +539,104 @@         all (> 0) (FittedBondCurveExample.numIterR rates2) `shouldBe` True         all (> 0) (FittedBondCurveExample.numIterR rates3) `shouldBe` True         all (> 0) (FittedBondCurveExample.numIterR rates4) `shouldBe` True++    describe "Gaussian1dModels example (LONG)" $+      it "check values" $ do+        -- calibrationBasket returns generic BlackCalibrationHelpers (upstream erases to the+        -- base inside basketgeneratingengine.cpp before the vector is returned), so nominal/+        -- strike/expiry per basket element aren't recoverable -- see CLAUDE.md's "A C+++        -- return type erased by upstream itself" note. Checked instead: basket size (Naive+        -- and MaturityStrikeByDeltaGamma both generate one helper per exercise date, 9 here),+        -- and -- the strongest reachable calibration-quality signal, what upstream's+        -- printModelCalibration actually displays -- that each calibrated helper's modelValue+        -- matches its marketValue and reprices to the 20% flat input vol.+        r <- Settings.keepingSettings' Gaussian1dModelsExample.run+        Gaussian1dModelsExample.basketNaiveLen r `shouldBe` 9+        Gaussian1dModelsExample.basketMsdgLen r `shouldBe` 9+        Gaussian1dModelsExample.amortizingBasketLen r `shouldBe` 9+        Gaussian1dModelsExample.callRightBasketLen0 r `shouldBe` 9+        Gaussian1dModelsExample.callRightBasketLen100 r `shouldBe` 9+        Gaussian1dModelsExample.floatBasketNaiveLen r `shouldBe` 9+        let calib = Gaussian1dModelsExample.basketCalibration r+        length calib `shouldBe` 9+        -- LM-calibrated, so 1e-6 relative (not absolute) per CLAUDE.md's CDS/G2 precedent.+        all (\c -> abs (Gaussian1dModelsExample.ccModelValue c - Gaussian1dModelsExample.ccMarketValue c)+                     < 1.0e-6 * max 1.0 (abs (Gaussian1dModelsExample.ccMarketValue c))) calib+          `shouldBe` True+        map Gaussian1dModelsExample.ccImpliedVol calib `shouldSatisfy` listClose id (replicate 9 0.20) 1.0e-3++        -- Recalibrating the model to the deal-strike (MaturityStrikeByDeltaGamma) basket+        -- moves the bermudan's price -- both values recorded from a run of this code (no+        -- upstream test-suite fixture for this exact scenario).+        Gaussian1dModelsExample.npvAtmGsr r `shouldSatisfy` closePrec 3.808059986124608e-3 1.0e-4+        Gaussian1dModelsExample.npvDealStrikeGsr r `shouldSatisfy` closePrec 7.627284474492891e-3 1.0e-4++        -- Bond call right (rebated-exercise swaption): widening the credit spread (oas+        -- 0bp -> 100bp) on the discounting side must reduce the call right's value.+        let npv0 = Gaussian1dModelsExample.npvCallRight0 r+            npv100 = Gaussian1dModelsExample.npvCallRight100 r+        npv0 `shouldSatisfy` closePrec 0.115409311734787 1.0e-4+        npv100 `shouldSatisfy` closePrec 4.497957039959159e-2 1.0e-4+        npv100 `shouldSatisfy` (< npv0)++        -- CMS-10Y-vs-Euribor-6M underlying swap (LinearTsrPricer-priced): NPV and its two+        -- leg NPVs must be internally consistent (leg0 - leg1, signed on a Payer swap).+        Gaussian1dModelsExample.underlyingCmsSwapNpv r `shouldSatisfy` closePrec 4.447180046586008e-3 1.0e-4+        let cmsLeg = Gaussian1dModelsExample.cmsLegNpv r+            euriborLeg = Gaussian1dModelsExample.euriborLegNpv r+        (cmsLeg + euriborLeg) `shouldSatisfy` closePrec (Gaussian1dModelsExample.underlyingCmsSwapNpv r) 1.0e-8++        -- Float-float (CMS vs Euribor) swaption under GSR: NPV and the "underlyingValue"+        -- additional result (the underlying swap's value in the GSR-implied smile).+        Gaussian1dModelsExample.npvFloatGsr r `shouldSatisfy` closePrec 4.291181496956639e-3 1.0e-4+        Gaussian1dModelsExample.underlyingValueGsr r `shouldSatisfy` closePrec 5.25035058083898e-3 1.0e-4++        -- Same swaption under MarkovFunctional: "not too far from the GSR price" (upstream's+        -- own prose, ex/Gaussian1dModels.cpp:585) -- a wide relative band, not exact digits.+        let npvGsr = Gaussian1dModelsExample.npvFloatGsr r+            npvMarkov = Gaussian1dModelsExample.npvFloatMarkov r+        npvMarkov `shouldSatisfy` closePrec 3.5487633569440007e-3 1.0e-4+        abs (npvMarkov - npvGsr) / npvGsr `shouldSatisfy` (< 0.5)++        -- Calibrating Markov's own sigma function to the coterminal ATM swaptions basket+        -- shouldn't move the underlying-smile match much -- "close to the previous value as+        -- expected" (ex/Gaussian1dModels.cpp:633-634).+        let preCalib = Gaussian1dModelsExample.underlyingValueMarkovPreCalib r+            postCalib = Gaussian1dModelsExample.underlyingValueMarkovPostCalib r+        preCalib `shouldSatisfy` closePrec 4.300762793278117e-3 1.0e-4+        postCalib `shouldSatisfy` closePrec 4.330369264462356e-3 1.0e-4+        abs (postCalib - preCalib) / abs preCalib `shouldSatisfy` (< 0.1)++    -- Discrete arithmetic average-price Asian put, reproducing the 26-fixing case from+    -- ~/Src/QuantLib/test-suite/asianoptions.cpp:testMCDiscreteArithmeticAveragePrice+    -- (data from Levy 1997 as reproduced by Haug): expected NPV 1.7255070456, upstream's+    -- own cross-engine tolerances are 2e-2 (MC/PDE) and 3e-2 (Turnbull-Wakeman analytic+    -- approximation) -- this exercises the two new Asian engines plus the already-bound+    -- mcDiscreteArithmeticAPEngine on the same instrument.+    describe "Asian option example" $+      it "check values" $ do+        r <- Settings.keepingSettings' AsianOptionExample.run+        AsianOptionExample.twR r `shouldSatisfy` closePrec 1.7255070456 3.0e-2+        AsianOptionExample.fdR r `shouldSatisfy` closePrec 1.7255070456 3.0e-2+        AsianOptionExample.mcR r `shouldSatisfy` closePrec 1.7255070456 2.0e-2++    -- Forward-starting vanilla options, reproducing+    -- ~/Src/QuantLib/test-suite/forwardoption.cpp:testValues (Haug, "Option pricing+    -- formulas", p.37/VBA code) under forwardEuropeanEngine, then cross-checking the+    -- other 5 new forward-starting engines against that reference (see+    -- QuantLib.Example.ForwardOption's haddock for the rationale of each check).+    describe "Forward option example" $+      it "check values" $ do+        r <- Settings.keepingSettings' ForwardOptionExample.run+        let call = ForwardOptionExample.europeanCallR r+        call `shouldSatisfy` closePrec 4.4064 1.0e-3+        ForwardOptionExample.europeanPutR r `shouldSatisfy` closePrec 8.2971 1.0e-3+        -- finite-differences and Monte Carlo should reproduce the same European price+        ForwardOptionExample.fdEuropeanR r `shouldSatisfy` closePrec call 1.0e-2+        ForwardOptionExample.mcEuropeanR r `shouldSatisfy` closePrec call 2.0e-2+        -- Heston (realistic, non-degenerate vol-of-vol) should stay in the same ballpark+        -- as the BS analytic price, not track it exactly+        ForwardOptionExample.hestonEuropeanR r `shouldSatisfy` closePrec call (0.1 * call)+        -- American exercise is never worth less than the otherwise-identical European option+        ForwardOptionExample.bawAmericanR r `shouldSatisfy` (>= call - 1.0e-6)+        ForwardOptionExample.bjsAmericanR r `shouldSatisfy` (>= call - 1.0e-6)
+ test/hspec/QuantLib/Spec/Index/Commodity.hs view
@@ -0,0 +1,48 @@+module QuantLib.Spec.Index.Commodity (spec) where++import Test.Hspec++import QuantLib.Time.Date+import QuantLib.Time.Calendar(calendar, CalendarConstructor(..))+import QuantLib.Time.Schedule(dayCounter, DayCounterConstructor(..))+import QuantLib.Index+import QuantLib.Index.Commodity+import QuantLib.Commodity+import QuantLib.TermStructure.Commodity++spec :: Spec+spec = do+  describe "CommodityIndex" $ do+    it "has no historical fixings and no forward price before any are added" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      idx <- commodityIndex "HO index" ho usd bbl cal 1000 Nothing+      commodityIndexEmpty idx `shouldBe` True++    it "forecasts a forward price from a forward curve" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let d0 = 1 `january` 2024+          d1 = 1 `february` 2024+      curve <- commodityCurve "HO curve" ho usd bbl cal [d0, d1] [70.0, 71.0] dc+      idx <- commodityIndex "HO index" ho usd bbl cal 1000 (Just curve)+      commodityIndexForwardPrice idx d0 `shouldReturn` 70.0++    it "stores and returns historical fixings via QuantLib.Index's generic addFixing/fixing" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      idx <- commodityIndex "HO index" ho usd bbl cal 1000 Nothing+      let d0 = 2 `january` 2024 -- a TARGET business day (Jan 1st is a holiday)+      addFixing idx d0 72.5 False+      commodityIndexEmpty idx `shouldBe` False+      commodityIndexLastQuoteDate idx `shouldReturn` d0+      fixing idx d0 False `shouldReturn` 72.5++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
+ test/hspec/QuantLib/Spec/Instrument/Energy.hs view
@@ -0,0 +1,152 @@+module QuantLib.Spec.Instrument.Energy (spec) where++import Test.Hspec+import Data.Time.Calendar(addDays)++import qualified QuantLib.Settings as Settings+import QuantLib.Time.Date+import QuantLib.Time.Calendar(calendar, CalendarConstructor(..))+import QuantLib.Time.Schedule(dayCounter, DayCounterConstructor(..), Frequency(..))+import QuantLib.InterestRate(Compounding(..))+import QuantLib.Quote(simpleQuote)+import QuantLib.TermStructure.Yield(YieldTermStructure, flatForward)+import QuantLib.Commodity+import QuantLib.TermStructure.Commodity(commodityCurve)+import QuantLib.Index.Commodity(CommodityIndex, commodityIndex)+import QuantLib.Index(addFixing)+import QuantLib.Instrument(npv)+import QuantLib.Instrument.Energy++-- |A flat, zero-rate discount curve -- with pay/receive/discount legs all pointing at the same+-- curve, a swap's paid and received legs discount identically, so a zero @uDelta@ (the legs'+-- undiscounted difference) implies a zero NPV regardless of the curve's own rate (see CLAUDE.md's+-- TARF-style martingale-check precedent). Rate 0 just keeps the by-hand arithmetic trivial.+flatZeroCurve :: Day -> IO YieldTermStructure+flatZeroCurve evalDate = do+  q <- simpleQuote 0.0+  dc <- dayCounter Actual365FixedStandard+  flatForward evalDate q dc Continuous Annual++-- |A flat @price@ 'CommodityIndex' over @ct@\/@bbl@: one historical fixing well before+-- @evalDate@ (so every date in the pricing window below falls after 'lastQuoteDate' and is priced+-- off the forward curve, per energyvanillaswap.cpp's own per-day branch) backed by a forward curve+-- quoting the same flat @price@ across the whole window -- so every quote used anywhere in a+-- test is exactly @price@, regardless of which date it's fetched for.+flatIndex :: CommodityType -> UnitOfMeasure -> Day -> Double -> IO CommodityIndex+flatIndex ct bbl evalDate price = do+  usd <- commoditySettingsCurrency+  cal <- calendar Null+  curve <- commodityCurve "flat curve" ct usd bbl cal [evalDate, addDays 400 evalDate] [price, price]+             =<< dayCounter Actual365FixedStandard+  idx <- commodityIndex "flat index" ct usd bbl cal 1 (Just curve)+  addFixing idx (addDays (-30) evalDate) price False+  pure idx++spec :: Spec+spec = do+  describe "EnergyFuture" $ do+    it "nets to zero when the trade price matches the index's flat quote" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        idx <- flatIndex ct bbl evalDate 100+        fut <- energyFuture 1 (ct, bbl, 1000) (100, usd, bbl) idx ct []+        npv fut `shouldReturn` 0++    it "control: a below-market trade price nets to a positive, formula-predicted NPV" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        idx <- flatIndex ct bbl evalDate 100+        -- buySell=1, quantity 1000, trade price 90 vs a 100 flat quote, lot quantity 1:+        -- delta = (quote - tradePrice) * quantity * lotQuantity^2 * buySell = (100-90)*1000*1*1+        fut <- energyFuture 1 (ct, bbl, 1000) (90, usd, bbl) idx ct []+        npv fut `shouldReturn` 10000++  describe "EnergyVanillaSwap" $ do+    it "nets to zero (before financing cost) when the fixed price matches the flat floating quote" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        cal <- calendar Null+        idx <- flatIndex ct bbl evalDate 100+        ts <- flatZeroCurve evalDate+        let pp = pricingPeriod (addDays 10 evalDate) (addDays 14 evalDate) (addDays 20 evalDate) (ct, bbl, 1000)+        swp <- energyVanillaSwap True cal (100, usd) bbl idx usd usd [pp] ct [] ts ts ts+        npv swp `shouldReturn` 0++    it "control: paying a below-market fixed price nets to a positive NPV" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        cal <- calendar Null+        idx <- flatIndex ct bbl evalDate 100+        ts <- flatZeroCurve evalDate+        let pp = pricingPeriod (addDays 10 evalDate) (addDays 14 evalDate) (addDays 20 evalDate) (ct, bbl, 1000)+        swp <- energyVanillaSwap True cal (90, usd) bbl idx usd usd [pp] ct [] ts ts ts+        n <- npv swp+        n `shouldSatisfy` (> 0)++  describe "EnergyBasisSwap" $ do+    it "nets to zero (before financing cost) with a zero basis and matching flat quotes" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        cal <- calendar Null+        idx <- flatIndex ct bbl evalDate 100+        ts <- flatZeroCurve evalDate+        let pp = pricingPeriod (addDays 10 evalDate) (addDays 14 evalDate) (addDays 20 evalDate) (ct, bbl, 1000)+        swp <- energyBasisSwap cal idx idx idx True usd usd [pp] (0, usd, bbl) ct [] ts ts ts+        npv swp `shouldReturn` 0++    it "control: a nonzero basis added to the pay leg nets to a negative NPV" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        ct <- commodityType "CL" "Crude Oil"+        bbl <- barrelUnitOfMeasure+        usd <- commoditySettingsCurrency+        cal <- calendar Null+        idx <- flatIndex ct bbl evalDate 100+        ts <- flatZeroCurve evalDate+        let pp = pricingPeriod (addDays 10 evalDate) (addDays 14 evalDate) (addDays 20 evalDate) (ct, bbl, 1000)+        swp <- energyBasisSwap cal idx idx idx True usd usd [pp] (5, usd, bbl) ct [] ts ts ts+        n <- npv swp+        n `shouldSatisfy` (< 0)++  describe "createPricingPeriods" $ do+    it "splits a date range into monthly PerMonth periods, per the paymentTerm's offset" $ do+      ct <- commodityType "CL" "Crude Oil"+      bbl <- barrelUnitOfMeasure+      cal <- calendar Null+      pt <- paymentTerm "5 days after pricing end" PricingDate 5 cal+      let startDate = 1 `january` 2024+          endDate = 1 `april` 2024+      pps@(st: _) <- createPricingPeriods startDate endDate (ct, bbl, 100) DeliveryMonthly PerMonth pt+      length pps `shouldBe` 3+      pricingPeriodStartDate st `shouldBe` startDate++    it "silently returns no periods for a DeliverySchedule createPricingPeriods doesn't implement" $ do+      ct <- commodityType "CL" "Crude Oil"+      bbl <- barrelUnitOfMeasure+      cal <- calendar Null+      pt <- paymentTerm "5 days after pricing end" PricingDate 5 cal+      pps <- createPricingPeriods (1 `january` 2024) (1 `april` 2024) (ct, bbl, 100) DeliveryQuarterly PerQuarter pt+      pps `shouldBe` []++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
+ test/hspec/QuantLib/Spec/Instrument/InflationCapFloor.hs view
@@ -0,0 +1,281 @@+module QuantLib.Spec.Instrument.InflationCapFloor (spec) where++import Control.Monad(forM_, forM)+import Data.Time.Calendar(toGregorian, fromGregorian)+import Test.Hspec++import qualified QuantLib.Settings as Settings+import QuantLib.CashFlow(Leg, yoyInflationLeg, blackYoYInflationCouponPricer, setYoYInflationCouponPricer)+import qualified QuantLib.CashFlow as CF+import QuantLib.Currency(currency, Ccy(GBP))+import QuantLib.Instrument.Option(OptionType(..))+import QuantLib.TermStructure.Inflation+import QuantLib.Index(addFixing)+import QuantLib.Index.Inflation+import qualified QuantLib.InterestRate as IR+import QuantLib.InterestRate(VolatilityType(..))+import QuantLib.Instrument(npv, setPricingEngine)+import QuantLib.Instrument.InflationCapFloor+import QuantLib.Math(Interpolation(..), Interpolation2D(..), Matrix(..))+import QuantLib.PricingEngine(PricingEngine, yoyInflationBlackCapFloorEngine, interpolatingCPICapFloorEngine)+import QuantLib.Quote(simpleQuote)+import QuantLib.TermStructure.InflationVolatility+import QuantLib.TermStructure.Yield(flatForward, PillarChoice(..))+import QuantLib.Time.Calendar+import QuantLib.Time.Date+import QuantLib.Time.Schedule++-- |A custom-named YoY index (rather than a shared named singleton like 'YYUKRPI') so this+-- module's made-up fixings and curve link can't collide with another test's fixings on the+-- same globally shared index-name fixing store -- QuantLib's fixing store is keyed by index+-- name, and hspec runs specs in random order, so any shared name is a latent cross-test+-- conflict.+customYoYIndex :: Maybe YoYInflationTermStructure -> IO YoYInflationIndex+customYoYIndex mts = do+  gbp <- currency GBP+  r <- region' "InflationCapFloor Test" "ICFT"+  yoyInflationIndex' "ICFT YoY" r False Monthly (1, Months) gbp mts++-- |Bootstraps a tiny YoY curve and returns an index linked to it. A YoY index's+-- 'needsForecast' (ql/indexes/inflationindex.cpp) is date-driven, not data-driven: any fixing+-- date beyond @evaluationDate - availabilityLag@ always forecasts through the index's own+-- linked 'YoYInflationTermStructure', regardless of whether a fixing has been manually added+-- for it -- so a future-dated cap/floor leg needs a real linked curve, not just extra+-- 'addFixing' calls (contrast 'QuantLib.Spec.Examples' CPI fixtures, which stay within the+-- historical window on purpose). Mirrors upstream's own CommonVars fixture+-- (test-suite/inflationcapfloor.cpp), minus the relinkable-handle indirection hasquant doesn't+-- expose for inflation curves: build the swap helpers off an unlinked index, bootstrap, then+-- construct a second, curve-linked index sharing the same family name (fixing history is keyed+-- by name, not object identity, so it's shared automatically).+linkedYoYIndex :: Day -> IO YoYInflationIndex+linkedYoYIndex tod = do+  cal <- calendar Null+  dc <- dayCounter Actual365FixedStandard+  yii0 <- customYoYIndex Nothing+  -- Fixings span [today-8y, today+1y] (not a hardcoded absolute range) so this test keeps+  -- working as the real wall-clock 'today' advances across future runs -- an absolute+  -- 2018-01..2026-01 window (this test's original form) silently falls out of range once+  -- 'today' itself passes 2026, since 'baseDate' below is derived from 'today'.+  fixingDates <- mapM (\n -> advance cal tod (n, Months) Unadjusted False) [-96 .. 12 :: Int]+  forM_ (zip [1 :: Double ..] fixingDates) $ \(i, d) -> addFixing yii0 d (0.03 + i * 0.0001) False+  nominalQ <- simpleQuote 0.02+  nominalCurve <- flatForward tod nominalQ dc IR.Continuous Annual+  maturity1 <- advance cal tod (2, Years) Unadjusted False+  maturity2 <- advance cal tod (5, Years) Unadjusted False+  q1 <- simpleQuote 0.03+  q2 <- simpleQuote 0.03+  h1 <- yearOnYearInflationSwapHelper q1 (3, Months) maturity1 cal Unadjusted dc yii0 CPIFlat nominalCurve LastRelevantDate Nothing+  h2 <- yearOnYearInflationSwapHelper q2 (3, Months) maturity2 cal Unadjusted dc yii0 CPIFlat nominalCurve LastRelevantDate Nothing+  baseDate <- advance cal tod (-2, Months) Unadjusted False+  yoyCurve <- piecewiseYoYInflationCurve tod baseDate 0.03 Monthly dc [h1, h2] Linear+  customYoYIndex (Just yoyCurve)++-- |A short YoY-inflation leg (3 annual coupons) on the given (curve-linked) index -- mirrors+-- the fixture in upstream's inflationcapfloor.cpp's CommonVars, trimmed to what a fast+-- structural-consistency check needs.+setupLeg :: YoYInflationIndex -> Day -> IO Leg+setupLeg yii tod = do+  cal <- calendar Null+  dc <- dayCounter Actual365FixedStandard+  endDate <- advance cal tod (3, Years) Unadjusted False+  sch <- schedule (Just tod) endDate (1, Years) cal Unadjusted Unadjusted Forward False Nothing Nothing+  yoyInflationLeg sch cal yii (3, Months) CPIFlat [1000000] dc Unadjusted [0] [1.0] [0.0] [] []++-- |Builds the Black engine (constant vol) all cap\/floor\/collar instruments in this module+-- share -- mirrors 'QuantLib.Spec.TermStructure`'s "Black cap/floor engine" setup, YoY-inflation+-- flavoured.+setupEngine :: YoYInflationIndex -> Day -> IO PricingEngine+setupEngine yii tod = do+  cal <- calendar Null+  dc <- dayCounter Actual365FixedStandard+  nominalQ <- simpleQuote 0.02+  nominalCurve <- flatForward tod nominalQ dc IR.Continuous Annual+  volQ <- simpleQuote 0.02+  vol <- constantYoYOptionletVolatility volQ 0 cal Unadjusted dc (3, Months) Annual False (-1.0) 100.0 ShiftedLognormal 0.0+  yoyInflationBlackCapFloorEngine yii vol nominalCurve++-- |A custom-named zero index, linked to a tiny bootstrapped 'ZeroInflationTermStructure' --+-- same fixing-store-isolation reasoning as 'customYoYIndex'. A link is required even though the+-- price surface only ever queries its own price grid: 'InterpolatedCPICapFloorTermPriceSurface's+-- @performCalculations@ computes each grid column's ATM level via the index's own+-- 'QuantLib.TermStructure.Inflation.ZeroInflationTermStructure' (put\/call parity, see this+-- type's own C++ haddock), which throws "ZITS missing from index" if unset -- mirrors upstream's+-- own CommonVars building 'PiecewiseZeroInflationCurve' before the price surface.+customZeroIndex :: Day -> IO ZeroInflationIndex+customZeroIndex tod = do+  gbp <- currency GBP+  r <- region' "InflationCapFloor CPI Test" "ICFCT"+  cal <- calendar Null+  dc <- dayCounter Actual365FixedStandard+  zii0 <- zeroInflationIndex' "ICFCT Zero" r False Monthly (1, Months) gbp Nothing+  -- Same today-relative fixing window as 'linkedYoYIndex', for the same reason.+  fixingDates <- mapM (\n -> advance cal tod (n, Months) Unadjusted False) [-96 .. 12 :: Int]+  forM_ (zip [1 :: Double ..] fixingDates) $ \(i, d) -> addFixing zii0 d (100.0 + i * 0.1) False+  maturity1 <- advance cal tod (2, Years) Unadjusted False+  -- 10y, not 5y: this curve must reach past the price surface's own widest grid maturity (7y,+  -- see the CPI cap/floor test below) since 'InterpolatedCPICapFloorTermPriceSurface's+  -- performCalculations computes each grid column's ATM level off this index's linked curve.+  maturity2 <- advance cal tod (10, Years) Unadjusted False+  q1 <- simpleQuote 0.03+  q2 <- simpleQuote 0.03+  h1 <- zeroCouponInflationSwapHelper q1 (2, Months) maturity1 cal Unadjusted dc zii0 CPIFlat LastRelevantDate Nothing+  h2 <- zeroCouponInflationSwapHelper q2 (2, Months) maturity2 cal Unadjusted dc zii0 CPIFlat LastRelevantDate Nothing+  baseDate <- advance cal tod (-2, Months) Unadjusted False+  zeroCurve <- piecewiseZeroInflationCurve tod baseDate Monthly dc [h1, h2] Linear+  zeroInflationIndex' "ICFCT Zero" r False Monthly (1, Months) gbp (Just zeroCurve)++spec :: Spec+spec = do+ describe "YoY inflation cap/floor" $ do+  it "cap - floor = collar, and the sum of optionlets equals the parent NPV" $ Settings.keepingSettings' $ do+    -- Anchored to the real wall-clock date (like 'QuantLib.Spec.Examples`'s SimpleChooserOption),+    -- not a hardcoded past date: every maturity derived below is then always in the future, so a+    -- later test in the suite changing the global evaluation date can never see this test's+    -- still-alive curve/swap objects as stale. (An earlier version of this test hardcoded+    -- "2 january 2024" and relied on 'performGC' alone to finalize those objects before the next+    -- test moved the clock forward -- but 'performGC' only schedules finalizers, it doesn't run+    -- them synchronously, so that was a race rather than a fix.)+    todayD <- today+    Settings.setEvaluationDate (Just todayD)+    yii <- linkedYoYIndex todayD+    leg <- setupLeg yii todayD+    engine <- setupEngine yii todayD++    let capRate = 0.035+        floorRate = 0.025+    capInst <- yoyInflationCap leg [capRate]+    floorInst <- yoyInflationFloor leg [floorRate]+    collarInst <- yoyInflationCollar leg [capRate] [floorRate]+    mapM_ (`setPricingEngine` engine) [capInst, floorInst, collarInst]++    capNPV <- npv capInst+    floorNPV <- npv floorInst+    collarNPV <- npv collarInst+    abs ((capNPV - floorNPV) - collarNPV) `shouldSatisfy` (< 1e-6)++    caplets <- forM [0 .. 2 :: Word] $ \n -> do+      o <- yoyInflationCapFloorOptionlet capInst n+      setPricingEngine o engine+      npv o+    abs (capNPV - sum caplets) `shouldSatisfy` (< 1e-6)++  it "a capped yoyInflationLeg's NPV decomposes as uncapped leg NPV minus the equivalent cap's NPV" $ Settings.keepingSettings' $ do+    -- Confirmed by reading inflationcoupon.cpp: InflationCoupon::rate() unconditionally requires+    -- a pricer (QL_REQUIRE(pricer_, "pricer not set")), capped or not -- yoyInflationLeg's own+    -- operator Leg() (yoyinflationcoupon.cpp) auto-attaches a default (non-vol) pricer only when+    -- caps and floors are BOTH empty; a non-empty cap here means 'setYoYInflationCouponPricer'+    -- must be called explicitly, and this test's NPV assertion below only succeeds if it actually+    -- ran (leaving it out reproduces "pricer not set", not a silently-wrong number) -- so this+    -- doubles as the setter's own regression check.+    todayD <- today+    Settings.setEvaluationDate (Just todayD)+    yii <- linkedYoYIndex todayD+    cal <- calendar Null+    dc <- dayCounter Actual365FixedStandard+    endDate <- advance cal todayD (3, Years) Unadjusted False+    sch <- schedule (Just todayD) endDate (1, Years) cal Unadjusted Unadjusted Forward False Nothing Nothing++    let capRate = 0.035+    cappedLeg <- yoyInflationLeg sch cal yii (3, Months) CPIFlat [1000000] dc Unadjusted [0] [1.0] [0.0] [capRate] []+    uncappedLeg <- yoyInflationLeg sch cal yii (3, Months) CPIFlat [1000000] dc Unadjusted [0] [1.0] [0.0] [] []++    nominalQ <- simpleQuote 0.02+    nominalCurve <- flatForward todayD nominalQ dc IR.Continuous Annual+    volQ <- simpleQuote 0.02+    vol <- constantYoYOptionletVolatility volQ 0 cal Unadjusted dc (3, Months) Annual False (-1.0) 100.0 ShiftedLognormal 0.0+    pricer <- blackYoYInflationCouponPricer vol nominalCurve+    setYoYInflationCouponPricer cappedLeg pricer++    cappedNPV <- CF.npv cappedLeg nominalCurve True Nothing Nothing+    uncappedNPV <- CF.npv uncappedLeg nominalCurve True Nothing Nothing++    capEngine <- yoyInflationBlackCapFloorEngine yii vol nominalCurve+    capInst <- yoyInflationCap uncappedLeg [capRate]+    setPricingEngine capInst capEngine+    capNPV <- npv capInst++    abs ((uncappedNPV - capNPV) - cappedNPV) `shouldSatisfy` (< 1e-6)++ describe "CPI cap/floor" $ do+  -- CPI cap/floor has no vol-driven engine in QL 1.43 -- InterpolatingCPICapFloorEngine prices+  -- purely by interpolating a market price surface (see cbits/qlInflationVol.cpp's+  -- qlInterpolatingCPICapFloorEngine and CPICapFloorTermPriceSurface's own haddock). At an+  -- exact grid node the interpolation is an identity, so this reproduces the input price+  -- exactly rather than just approximately -- mirrors upstream's own+  -- test-suite/inflationcpicapfloor.cpp::cpicapfloorpricer, whose fixture is built the same+  -- way: pick an evaluation date on the 1st of a month (so "the start of the inflation period+  -- containing the maturity", what CPI::Flat actually samples, coincides exactly with the+  -- maturity itself) and a maturity/strike that exactly match one price-surface grid node.+  -- baseCPI is a required constructor argument but never touched by this engine's calculate()+  -- (confirmed by reading cpicapfloorengines.cpp) so an arbitrary placeholder is fine.+  it "reproduces the exact grid price at a matching strike/maturity node" $ Settings.keepingSettings' $ do+    -- First-of-month, derived from the real wall-clock date rather than hardcoded, so+    -- CPI::Flat's period-start sampling (see the comment above) lands exactly on the raw date+    -- without pinning the test to a date that will eventually become stale/past.+    (y, m, _) <- toGregorian <$> today+    let today' = fromGregorian y m 1+    Settings.setEvaluationDate (Just today')+    cal <- calendar Null+    dc <- dayCounter Actual365FixedStandard+    nominalQ <- simpleQuote 0.02+    nominalCurve <- flatForward today' nominalQ dc IR.Continuous Annual+    zii <- customZeroIndex today'+    maturity5Y <- advance cal today' (5, Years) Unadjusted False++    let obsLag = (2, Months)+        cStrike = 0.04+        fStrike = 0.01+        cPriceGrid = 0.01279+        fPriceGrid = 0.006666+    -- A non-square (2 strikes x 3 maturities) slice of upstream's own cached cap/floor price+    -- grid (test-suite/inflationcpicapfloor.cpp's cPrice/fPrice tables, strikes 0.03/0.04 and+    -- 0.01/-0.01, maturities 3Y/5Y/7Y), row-major by strike then maturity -- deliberately+    -- non-square so a Matrix construction that silently transposed strikes/maturities (rather+    -- than throwing a dimension mismatch) would produce a detectably wrong value here; a square+    -- grid can't distinguish the two orientations. The assertions below check the (strike+    -- 0.04, maturity 5Y) and (strike 0.01, maturity 5Y) cells -- both off the [0][0] corner --+    -- rather than only the corner a transposed 2x2 grid would still get right by accident.+    surface <- cpiCapFloorTermPriceSurface 1.0 cStrike obsLag cal Unadjusted dc zii CPIFlat nominalCurve+      [0.03, cStrike] [-0.01, fStrike] [(3, Years), (5, Years), (7, Years)]+      (Matrix 2 3 [0.02276, 0.034532, 0.047795, 0.010027, cPriceGrid, 0.017019])+      (Matrix 2 3 [0.001562, 0.002145, 0.002445, 0.005361, fPriceGrid, 0.007704])+      Bilinear+    engine <- interpolatingCPICapFloorEngine surface++    capInst <- cpiCapFloor Call 1.0 today' 100.0 maturity5Y cal Unadjusted cal Unadjusted cStrike zii obsLag CPIFlat+    setPricingEngine capInst engine+    capNPV <- npv capInst+    abs (capNPV - cPriceGrid) `shouldSatisfy` (< 1e-9)++    floorInst <- cpiCapFloor Put 1.0 today' 100.0 maturity5Y cal Unadjusted cal Unadjusted fStrike zii obsLag CPIFlat+    setPricingEngine floorInst engine+    floorNPV <- npv floorInst+    abs (floorNPV - fPriceGrid) `shouldSatisfy` (< 1e-9)++  -- No upstream fixture covers a non-Bilinear Interpolation2D, so this is a+  -- construction/sanity check only, same reasoning as the yoyCapFloorTermPriceSurface+  -- spot-check in QuantLib.Spec.TermStructure.InflationVolatility.+  it "cpiCapFloorTermPriceSurface: Bicubic builds and reproduces the same grid price" $ Settings.keepingSettings' $ do+    (y, m, _) <- toGregorian <$> today+    let today' = fromGregorian y m 1+    Settings.setEvaluationDate (Just today')+    cal <- calendar Null+    dc <- dayCounter Actual365FixedStandard+    nominalQ <- simpleQuote 0.02+    nominalCurve <- flatForward today' nominalQ dc IR.Continuous Annual+    zii <- customZeroIndex today'+    maturity5Y <- advance cal today' (5, Years) Unadjusted False++    let obsLag = (2, Months)+        cStrike = 0.04+        cPriceGrid = 0.01279+    surface <- cpiCapFloorTermPriceSurface 1.0 cStrike obsLag cal Unadjusted dc zii CPIFlat nominalCurve+      [0.03, cStrike] [-0.01, 0.01] [(3, Years), (5, Years), (7, Years)]+      (Matrix 2 3 [0.02276, 0.034532, 0.047795, 0.010027, cPriceGrid, 0.017019])+      (Matrix 2 3 [0.001562, 0.002145, 0.002445, 0.005361, 0.006666, 0.007704])+      Bicubic+    engine <- interpolatingCPICapFloorEngine surface+    capInst <- cpiCapFloor Call 1.0 today' 100.0 maturity5Y cal Unadjusted cal Unadjusted cStrike zii obsLag CPIFlat+    setPricingEngine capInst engine+    capNPV <- npv capInst+    abs (capNPV - cPriceGrid) `shouldSatisfy` (< 1e-9)
+ test/hspec/QuantLib/Spec/Instrument/Option.hs view
@@ -0,0 +1,173 @@+-- | Golden-value tests for the exotic single-/multi-asset options bound+-- alongside their analytic engines: 'simpleChooserOption', 'softBarrierOption',+-- 'twoAssetCorrelationOption' reproduce cached NPVs from QuantLib's own+-- test-suite (chooseroption.cpp, softbarrieroption.cpp,+-- twoassetcorrelationoption.cpp). 'writerExtensibleOption' has no upstream+-- test-suite fixture, so it's checked instead against an independent+-- Monte Carlo simulation of its own payoff definition (see CLAUDE.md's+-- TARF-style self-consistency precedent) -- exact lognormal (GBM) path+-- simulation under the same flat-rate/flat-vol process, entirely+-- self-contained (no 'random' package dependency: a fixed-seed splitmix-style+-- LCG plus Box-Muller, both defined below).+module QuantLib.Spec.Instrument.Option (spec) where++import Prelude hiding(iterate, tail)+import Test.Hspec+import Data.Time.Calendar(addDays)+import Data.Bits(shiftR, xor)+import Data.Word(Word64)+import Data.List.NonEmpty(iterate, tail)++import qualified QuantLib.Settings as Settings+import QuantLib.Time.Date+import QuantLib.Time.Calendar(calendar, CalendarConstructor(..))+import QuantLib.Time.Schedule(dayCounter, DayCounterConstructor(..), Frequency(..))+import QuantLib.InterestRate(Compounding(..))+import QuantLib.Quote(simpleQuote)+import QuantLib.TermStructure.Yield(flatForward)+import QuantLib.TermStructure.Volatility(blackConstantVol)+import QuantLib.Process+import QuantLib.Instrument(npv, setPricingEngine, BarrierType(..))+import QuantLib.Instrument.Option hiding(theta)+import QuantLib.PricingEngine+import QuantLib.Spec.Helpers(closePrec)++-- |A flat Black-Scholes-Merton process: spot/dividend-yield/risk-free-rate/vol all constant.+flatProcess :: Day -> Double -> Double -> Double -> Double -> IO GeneralizedBlackScholesProcess+flatProcess evalDate spot q r vol = do+  dc <- dayCounter (Actual360 False)+  spotQ <- simpleQuote spot+  qTS <- simpleQuote q >>= \qQ -> flatForward evalDate qQ dc Continuous Annual+  rTS <- simpleQuote r >>= \rQ -> flatForward evalDate rQ dc Continuous Annual+  volQ <- simpleQuote vol+  cal <- calendar Null+  volTS <- blackConstantVol evalDate cal volQ dc+  blackScholesMertonProcess spotQ qTS rTS volTS EulerDiscretization False++europeanIn :: Word -> Day -> Exercise+europeanIn days evalDate = European (EuropeanExercise (addDays (fromIntegral days) evalDate))++-- |Fixed-seed splitmix-style LCG producing i.i.d. standard normal draws via+-- Box-Muller, entirely self-contained so the writer-extensible cross-check+-- below doesn't need the @random@ package as a new dependency.+lcgStream :: Word64 -> [Word64]+lcgStream = tail . iterate step+  where step x = let x1 = (x `xor` (x `shiftR` 12)) * 2545536902123478967+                     x2 = (x1 `xor` (x1 `shiftR` 25)) * 2545536902123478967+                 in x2 `xor` (x2 `shiftR` 33)++normals :: Word64 -> [Double]+normals seed = go (map toUnit (lcgStream seed))+  where+    m = (2 :: Double) ^ (53 :: Int)+    toUnit w = fromIntegral (w `mod` round m :: Word64) / m+    go (u1:u2:rest) =+      let r = sqrt (-2 * log (max u1 1e-12))+          theta = 2 * pi * u2+      in r * cos theta : r * sin theta : go rest+    go _ = []++-- |Monte Carlo NPV (antithetic variates) for a writer-extensible option:+-- simulate GBM to @t1@; if @payoff1@ is in the money there, the holder is+-- paid @payoff1 S1@ at @t1@, otherwise the same path continues to @t2@ and+-- the holder is paid @payoff2 S2@ at @t2@ -- exactly+-- writerextensibleoption.hpp's own definition, simulated independently of+-- the analytic engine under test.+writerExtensibleMcNpv :: Int -> Double -> Double -> Double -> Double+                       -> Double -> Double -> (Double -> Double) -> (Double -> Double)+                       -> Double+writerExtensibleMcNpv halfN s0 q r vol t1 t2 payoff1 payoff2 =+  (sum (map pathValue zs) + sum (map (pathValue . negatePair) zs)) / fromIntegral (2 * halfN)+  where+    zs = take halfN (pairs (normals 0xC0FFEE))+    pairs (a:b:rest) = (a, b) : pairs rest+    pairs _ = []+    negatePair (a, b) = (-a, -b)+    drift dt = (r - q - 0.5 * vol * vol) * dt+    diffuse s dt z = s * exp (drift dt + vol * sqrt dt * z)+    pathValue (z1, z2) =+      let s1 = diffuse s0 t1 z1+          s2 = diffuse s1 (t2 - t1) z2+          v1 = payoff1 s1+      in if v1 > 0 then exp (-r * t1) * v1 else exp (-r * t2) * payoff2 s2++spec :: Spec+spec = do+  describe "SimpleChooserOption" $+    -- cached reference from QuantLib test-suite/chooseroption.cpp::testAnalyticSimpleChooserEngine+    -- (Haug, "Complete Guide to Option Pricing Formulas", pp.39-40).+    it "reproduces Haug's simple chooser option value" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        process <- flatProcess evalDate 50.0 0.0 0.08 0.25+        eng <- analyticSimpleChooserEngine process+        opt <- simpleChooserOption (addDays 90 evalDate) 50.0 (europeanIn 180 evalDate)+        setPricingEngine opt eng+        v <- npv opt+        v `shouldSatisfy` closePrec 6.1071 3e-5++  describe "SoftBarrierOption" $ do+    -- cached reference from QuantLib test-suite/softbarrieroption.cpp::testSoftBarrierHaug+    -- (Haug 2nd ed., p.166; first DownOut/Call row). Pinned to the upstream test's own+    -- literal evaluation date (8 August 2025), not a dynamic 'today': AnalyticSoftBarrierEngine+    -- (a 2025 upstream addition) turns out to price differently for different evaluation dates+    -- even at identical time-to-maturity T -- confirmed independently against a standalone C+++    -- program linked against the same installed QuantLib 1.43 (evalDate 2020-01-01/2025-08-08/+    -- 2026-08-22 with T pinned to exactly 0.5y each gave 3.79624/3.80752/3.78492 respectively).+    -- This looks like a genuine date-arithmetic quirk in the new upstream engine, not a+    -- hasquant marshalling bug; matching the test-suite's own fixture date is the correct fix.+    it "reproduces Haug's soft barrier option value" $+      Settings.keepingSettings' $ do+        let evalDate = 8 `august` 2025+        Settings.setEvaluationDate (Just evalDate)+        process <- flatProcess evalDate 100.0 0.05 0.1 0.1+        eng <- analyticSoftBarrierEngine process+        opt <- softBarrierOption DownOut 95.0 95.0 (PlainVanilla (PlainVanillaPayoff Call 100.0)) (europeanIn 180 evalDate)+        setPricingEngine opt eng+        v <- npv opt+        v `shouldSatisfy` closePrec 3.8075 1e-4++    it "round-trips its own implied volatility" $+      Settings.keepingSettings' $ do+        let evalDate = 8 `august` 2025+        Settings.setEvaluationDate (Just evalDate)+        process <- flatProcess evalDate 100.0 0.05 0.1 0.1+        eng <- analyticSoftBarrierEngine process+        opt <- softBarrierOption DownOut 95.0 95.0 (PlainVanilla (PlainVanillaPayoff Call 100.0)) (europeanIn 180 evalDate)+        setPricingEngine opt eng+        price <- npv opt+        iv <- softBarrierOptionImpliedVolatility opt price process 1.0e-6 1000 1e-6 4.0+        iv `shouldSatisfy` closePrec 0.1 1e-4++  describe "TwoAssetCorrelationOption" $+    -- cached reference from QuantLib test-suite/twoassetcorrelationoption.cpp::testAnalyticEngine+    it "reproduces the upstream two-asset correlation option value" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        process1 <- flatProcess evalDate 52.0 0.0 0.1 0.2+        process2 <- flatProcess evalDate 65.0 0.0 0.1 0.3+        corr <- simpleQuote 0.75+        eng <- analyticTwoAssetCorrelationEngine process1 process2 corr+        opt <- twoAssetCorrelationOption Call 50.0 70.0 (europeanIn 180 evalDate)+        setPricingEngine opt eng+        v <- npv opt+        v `shouldSatisfy` closePrec 4.7073 1e-4++  describe "WriterExtensibleOption" $+    it "matches an independent Monte Carlo simulation of its own payoff definition" $+      Settings.keepingSettings' $ do+        evalDate <- today+        Settings.setEvaluationDate (Just evalDate)+        let s0 = 100.0; q = 0.0; r = 0.05; vol = 0.2+            t1 = 0.5; t2 = 1.0; x1 = 100.0; x2 = 110.0+        process <- flatProcess evalDate s0 q r vol+        eng <- analyticWriterExtensibleOptionEngine process+        opt <- writerExtensibleOption (PlainVanillaPayoff Call x1) (europeanIn 180 evalDate)+                                       (PlainVanillaPayoff Call x2) (europeanIn 360 evalDate)+        setPricingEngine opt eng+        analytic <- npv opt+        let mcNpv = writerExtensibleMcNpv 100000 s0 q r vol t1 t2+                      (\s -> max 0 (s - x1)) (\s -> max 0 (s - x2))+        mcNpv `shouldSatisfy` closePrec analytic (0.03 * analytic)
test/hspec/QuantLib/Spec/TermStructure.hs view
@@ -85,7 +85,7 @@              ts <- piecewiseYieldCurve settlement (deposits ++ swaps) actual360dc [] Discount LogLinear             return (cal, settlementDays, ts)-      it "referenceChange" $ do+      it "referenceChange" $ Settings.keepingSettings' $ do         let ds = [10, 30, 60, 120, 360, 720]         (_calendar, settlementDays, _ts) <- setup         flatRate <- Quote.simpleQuote 0.03@@ -141,6 +141,28 @@            (zero - (spreadedZero - val)) `shouldSatisfy` (<= 1.0e-10) +      -- Same spread value at two nodes bracketing the query date: with 'Linear' interpolation+      -- of the (piecewise-bootstrapped) spread, the spread at any date between them equals that+      -- common value, so this reduces to the same check as 'zeroSpreadedTermStructure' above.+      it "piecewise z-spreaded" $+        Settings.keepingSettings' $ do+          (_calendar, _settlementDays, ts) <- setup+          q <- Quote.simpleQuote 0.01+          val <- Quote.value q+          refDate <- asTermStructure ts >>= referenceDate+          let d1 = addGregorianYearsClip 10 refDate+          spreaded <- piecewiseZeroSpreadedTermStructure ts [(refDate, q), (d1, q)] IR.Continuous NoFrequency Linear+          actual360dc <- dayCounter (Actual360 False)+          let testDate = addGregorianYearsClip 5 refDate+          zero <- IR.rate <$> zeroRate' ts testDate actual360dc IR.Continuous NoFrequency False+          spreadedZero <- IR.rate <$> zeroRate' spreaded testDate actual360dc IR.Continuous NoFrequency False+          (zero - (spreadedZero - val)) `shouldSatisfy` (<= 1.0e-10)++          -- spot-check a second interpolation builds and queries without crashing+          spreadedCubic <- piecewiseZeroSpreadedTermStructure ts [(refDate, q), (d1, q)] IR.Continuous NoFrequency (Cubic Kruger)+          cubicZero <- IR.rate <$> zeroRate' spreadedCubic testDate actual360dc IR.Continuous NoFrequency False+          cubicZero `shouldSatisfy` (not . isNaN)+       -- Mirrors upstream's ultimateforwardtermstructure.cpp testZeroRateAtFirstSmoothingPoint:       -- below the first smoothing point (fsp) the UFR curve must exactly reproduce the base       -- curve's own zero rate, since extrapolation only kicks in past fsp.@@ -225,7 +247,7 @@           price <- Quote.simpleQuote 100.0           bond <- fixedRateBondHelper price 3 100.0 sch [0.04] thirty360dc Following 100.0 Nothing                     >>= bondHelperBond-          Bond.maturityDate bond `shouldBe` Just bondMaturity+          Bond.maturityDate bond `shouldReturn` Just bondMaturity      -- No upstream test-suite fixture exists for FxSwapRateHelper (unlike the other rate     -- helpers ported elsewhere in this file), so this is a self-consistency check instead of@@ -589,6 +611,142 @@            priceConst `shouldSatisfy` (> 1)           abs (priceStripped - priceConst) / abs priceConst `shouldSatisfy` (< 1.0e-5)++      -- CapFloorTermVolatilityStructure::volatility isn't declared on the generic+      -- VolatilityTermStructure, so this exercises the new family root directly across all three+      -- concrete subclasses (ConstantCapFloorTermVolatility, CapFloorTermVolCurve,+      -- CapFloorTermVolSurface), plus the calendar/day-counter-derived optionDates/optionTimes+      -- getters on the two LazyObject leaves.+      it "queries a flat cap/floor vol surface, curve and constant structure at their own grid" $+        Settings.keepingSettings' $ do+          Settings.setEvaluationDate (Just (11 `december` 2012))+          cal <- Calendar.calendar TARGET+          dc <- dayCounter Actual365FixedStandard+          let tenors = [(n, Years) | n <- [1 .. 10]]++          flatVolQ <- Quote.simpleQuote 0.18+          let volMatrix = either error id $ objectMatrix 10 3 (replicate 30 flatVolQ)+          capVolSurface <- Vol.capFloorTermVolSurface 0 cal Following tenors [0.02, 0.05, 0.08] volMatrix dc+          volFromSurface <- Vol.capFloorVolatilityForPeriod capVolSurface (5, Years) 0.05 False+          volFromSurface `shouldBe` 0.18+          surfaceDates <- Vol.capFloorTermVolSurfaceOptionDates capVolSurface+          surfaceTimes <- Vol.capFloorTermVolSurfaceOptionTimes capVolSurface+          length surfaceDates `shouldBe` 10+          length surfaceTimes `shouldBe` 10++          curveVolQ <- mapM (const (Quote.simpleQuote 0.18)) tenors+          capVolCurve <- Vol.capFloorTermVolCurve 0 cal Following (zipWith (\(n, u) q -> (n, u, q)) tenors curveVolQ) dc+          volFromCurve <- Vol.capFloorVolatilityForPeriod capVolCurve (5, Years) 0.05 False+          volFromCurve `shouldBe` 0.18+          curveDates <- Vol.capFloorTermVolCurveOptionDates capVolCurve+          curveTimes <- Vol.capFloorTermVolCurveOptionTimes capVolCurve+          length curveDates `shouldBe` 10+          length curveTimes `shouldBe` 10++          constVolQ <- Quote.simpleQuote 0.18+          constVol <- Vol.constantCapFloorTermVolatility 0 cal Following constVolQ dc+          volFromConst <- Vol.capFloorVolatilityForPeriod constVol (5, Years) 0.05 False+          volFromConst `shouldBe` 0.18++      -- OptionletStripper2 reconciles OptionletStripper1's forward-forward stripping against an+      -- ATM CapFloorTermVolCurve (upstream: optionletstripper.cpp's testFlatTermVolatilityStripping2).+      -- With flat term-vol inputs on both the surface and the ATM curve, stripping via either path+      -- must produce the same caplet vols, so pricing the same cap through each stripped+      -- structure's engine gives matching NPVs -- a real self-consistency check, not a hand-derived+      -- golden value.+      it "OptionletStripper2 reprices a cap the same as OptionletStripper1 on flat term vol inputs" $+        Settings.keepingSettings' $ do+          Settings.setEvaluationDate (Just (11 `december` 2012))+          (_, discountH, forecastH) <- setupSwap+          cal <- Calendar.calendar TARGET+          settle <- advance cal (11 `december` 2012) (2, Days) Following False+          floatDC <- dayCounter (Actual360 False)+          floatSch <- schedule (Just settle) (11 `december` 2017) (6, Months) cal+            ModifiedFollowing ModifiedFollowing Forward False Nothing Nothing+          idx <- iborIndex Euribor6M (Just forecastH)+          leg <- iborLeg floatSch idx [1000000] floatDC ModifiedFollowing [2] [1.0] [0.0] [] [] False False+          capfl <- cap leg [0.05]+          dc <- dayCounter Actual365FixedStandard+          let tenors = [(n, Years) | n <- [1 .. 10]]++          flatVolQ <- Quote.simpleQuote 0.18+          let volMatrix = either error id $ objectMatrix 10 3 (replicate 30 flatVolQ)+          capVolSurface <- Vol.capFloorTermVolSurface 0 cal Following tenors [0.02, 0.05, 0.08] volMatrix dc+          curveVolQs <- mapM (const (Quote.simpleQuote 0.18)) tenors+          capVolCurve <- Vol.capFloorTermVolCurve 0 cal Following (zipWith (\(n, u) q -> (n, u, q)) tenors curveVolQs) dc++          stripper1 <- Vol.optionletStripper1 capVolSurface idx Nothing 1.0e-6 100+            (Just discountH) IR.ShiftedLognormal 0 False Nothing+          stripper2 <- Vol.optionletStripper2 capVolSurface idx Nothing 1.0e-6 100+            (Just discountH) IR.ShiftedLognormal 0 False Nothing capVolCurve+          vol2 <- Vol.optionletStripper2AsOptionletVolatilityStructure stripper2++          eng1 <- blackCapFloorEngine' discountH stripper1+          setPricingEngine capfl eng1+          price1 <- npv capfl++          eng2 <- blackCapFloorEngine' discountH vol2+          setPricingEngine capfl eng2+          price2 <- npv capfl++          price1 `shouldSatisfy` (> 1)+          abs (price1 - price2) / abs price1 `shouldSatisfy` (< 1.0e-5)++          atmStrikes <- Vol.optionletStripper2AtmCapFloorStrikes stripper2+          atmPrices <- Vol.optionletStripper2AtmCapFloorPrices stripper2+          spreadsVol <- Vol.optionletStripper2SpreadsVol stripper2+          length atmStrikes `shouldBe` 10+          length atmPrices `shouldBe` 10+          length spreadsVol `shouldBe` 10++      -- AbcdAtmVolCurve fits an ABCD functional form to quoted ATM vols. No cached upstream+      -- fixture matches hasquant's binding shape (see the plan's Tests section), so this is a+      -- construction-plus-getters smoke test: with flat input quotes the fit should stay close to+      -- flat and converge with a small rms error.+      it "constructs an AbcdAtmVolCurve and queries its fit diagnostics" $+        Settings.keepingSettings' $ do+          Settings.setEvaluationDate (Just (11 `december` 2012))+          cal <- Calendar.calendar TARGET+          dc <- dayCounter Actual365FixedStandard+          let tenors = [(n, Years) | n <- [1 .. 10]]+          qs <- mapM (const (Quote.simpleQuote 0.18)) tenors+          curve <- Vol.abcdAtmVolCurve 0 cal tenors qs (replicate 10 True) Following dc+          rmsErr <- Vol.abcdAtmVolCurveRmsError curve+          rmsErr `shouldSatisfy` (< 0.05)+          ks <- Vol.abcdAtmVolCurveK curve+          length ks `shouldBe` 10+          returnedTenors <- Vol.abcdAtmVolCurveOptionTenors curve+          length returnedTenors `shouldBe` 10+          atmv <- Vol.atmVolForPeriod curve (5, Years) False+          atmv `shouldSatisfy` (\v -> v > 0.1 && v < 0.3)++      -- SabrVolSurface's own volatilitySpreads(Date) linearly interpolates the raw quoted+      -- vol-spread quotes across optionTenors -- at a date that lands exactly on a grid tenor,+      -- that interpolation is the identity, so with flat spread quotes the surface must echo the+      -- input value back exactly. Real self-consistency check, not a hand-derived value.+      it "constructs a SabrVolSurface anchored to an AbcdAtmVolCurve and echoes its vol spreads at a grid tenor" $+        Settings.keepingSettings' $ do+          Settings.setEvaluationDate (Just (11 `december` 2012))+          cal <- Calendar.calendar TARGET+          dc <- dayCounter Actual365FixedStandard+          (_, _, forecastH) <- setupSwap+          idx <- iborIndex Euribor6M (Just forecastH)+          let tenors = [(n, Years) | n <- [1 .. 5]]+          atmQs <- mapM (const (Quote.simpleQuote 0.18)) tenors+          atmCurve <- Vol.abcdAtmVolCurve 0 cal tenors atmQs (replicate 5 True) Following dc+          let spreads = [-0.01, 0, 0.01]+          spreadQs <- mapM (const (Quote.simpleQuote 0.02)) [1 .. (5 * 3 :: Int)]+          let volSpreads = either error id $ objectMatrix 5 3 spreadQs+          surf <- Vol.sabrVolSurface idx atmCurve tenors spreads volSpreads+          vs <- Vol.sabrVolSurfaceVolatilitySpreadsForPeriod surf (3, Years)+          length vs `shouldBe` 3+          vs `shouldSatisfy` all (\v -> abs (v - 0.02) < 1.0e-8)+          _ <- Vol.sabrVolSurfaceIndex surf+          d <- Vol.sabrVolSurfaceOptionDateFromTenor surf (3, Years)+          d `shouldSatisfy` (> 11 `december` 2012)+          curveBack <- Vol.sabrVolSurfaceAtmCurve surf+          v <- Vol.atmVolForPeriod curveBack (3, Years) False+          abs (v - 0.18) `shouldSatisfy` (< 1.0e-6)        -- Bachelier (normal-vol) engines use a different pricing formula from their Black       -- (lognormal-vol) siblings; this checks the new bindings are actually wired to that
+ test/hspec/QuantLib/Spec/TermStructure/Commodity.hs view
@@ -0,0 +1,142 @@+module QuantLib.Spec.TermStructure.Commodity (spec) where++import Control.Exception(evaluate)+import Data.Maybe(isNothing, isJust)++import Test.Hspec hiding(before)++import QuantLib.Time.Date+import QuantLib.Time.Calendar(calendar, CalendarConstructor(..))+import QuantLib.Time.Schedule(dayCounter, DayCounterConstructor(..))+import QuantLib.Commodity+import QuantLib.TermStructure.Commodity++spec :: Spec+spec = do+  describe "CommodityCurve" $ do+    it "round-trips name/commodityType/unitOfMeasure/currency/dates/prices, non-empty" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let dates = [1 `january` 2024, 1 `february` 2024, 1 `march` 2024]+          prices = [70.0, 71.5, 72.0]+      curve <- commodityCurve "HO curve" ho usd bbl cal dates prices dc+      commodityCurveName curve `shouldReturn` "HO curve"+      ct <- commodityCurveCommodityType curve+      ct `shouldBe` ho+      uom <- commodityCurveUnitOfMeasure curve+      uom `shouldBe` bbl+      ccy <- commodityCurveCurrency curve+      ccy `shouldBe` usd+      commodityCurveDates curve `shouldReturn` dates+      commodityCurvePrices curve `shouldReturn` prices+      commodityCurveEmpty curve `shouldBe` False++    it "has no basis curve until one is set, and finds it afterwards" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let dates = [1 `january` 2024, 1 `february` 2024]+      curve <- commodityCurve "HO curve" ho usd bbl cal dates [70.0, 71.0] dc+      basis <- commodityCurve "HO basis" ho usd bbl cal dates [1.0, 1.0] dc+      before <- commodityCurveBasisOfCurve curve+      isNothing before `shouldBe` True+      setCommodityCurveBasisOfCurve curve basis+      found <- commodityCurveBasisOfCurve curve+      isJust found `shouldBe` True++    it "prices at a node date via forward-flat interpolation, plus any chained basis price" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let d0 = 1 `january` 2024+          d1 = 1 `february` 2024+      curve <- commodityCurve "HO curve" ho usd bbl cal [d0, d1] [70.0, 71.0] dc+      p0 <- commodityCurvePrice curve d0+      p0 `shouldBe` 70.0+      basis <- commodityCurve "HO basis" ho usd bbl cal [d0, d1] [1.0, 1.0] dc+      setCommodityCurveBasisOfCurve curve basis+      p0' <- commodityCurvePrice curve d0+      p0' `shouldBe` 71.0+      basisPrice <- commodityCurveBasisOfPrice curve d0+      basisPrice `shouldBe` 1.0++    it "commodityCurvePriceNearby with no contracts and offset 0 reproduces the flat price exactly" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let d0 = 1 `january` 2024+          d1 = 1 `february` 2024+      curve <- commodityCurve "HO curve" ho usd bbl cal [d0, d1] [70.0, 71.0] dc+      flat <- commodityCurvePrice curve d0+      rolled <- commodityCurvePriceNearby curve d0 [] 0+      rolled `shouldBe` flat++    it "underlyingPriceDate rolls onto the nearbyOffset'th exchange contract at or after the query date" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      usd <- commoditySettingsCurrency+      cal <- calendar TARGET+      dc <- dayCounter Actual365FixedStandard+      let d0 = 1 `january` 2024+          d1 = 1 `february` 2024+      curve <- commodityCurve "HO curve" ho usd bbl cal [d0, d1] [70.0, 71.0] dc+      let jan1 = 1 `january` 2024+          feb1 = 1 `february` 2024+          mar1 = 1 `march` 2024+          us1 = 5 `january` 2024+          us2 = 5 `february` 2024+          us3 = 5 `march` 2024+          ecs = [ (jan1, ("HOF24", jan1, us1, 31 `january` 2024))+                , (feb1, ("HOG24", feb1, us2, 28 `february` 2024))+                , (mar1, ("HOH24", mar1, us3, 31 `march` 2024))+                ]+      commodityCurveUnderlyingPriceDate curve jan1 ecs 1 `shouldReturn` us1+      commodityCurveUnderlyingPriceDate curve jan1 ecs 2 `shouldReturn` us2+      commodityCurveUnderlyingPriceDate curve jan1 ecs 3 `shouldReturn` us3+      commodityCurveUnderlyingPriceDate curve jan1 ecs 4 `shouldThrow` anyException+      commodityCurveUnderlyingPriceDate curve jan1 ecs 0 `shouldThrow` anyException++  describe "DateInterval" $ do+    it "isDateBetween respects the includeFirst/includeLast flags" $ do+      let d0 = 1 `january` 2024+          d1 = 31 `january` 2024+          mid = 15 `january` 2024+          iv = (d0, d1)+      isDateBetween iv mid True True `shouldBe` True+      isDateBetween iv d0 True True `shouldBe` True+      isDateBetween iv d0 False True `shouldBe` False+      isDateBetween iv d1 True True `shouldBe` True+      isDateBetween iv d1 True False `shouldBe` False++    it "intersection overlaps two ranges, or Nothing if disjoint" $ do+      let iv1 = (1 `january` 2024, 31 `january` 2024)+          iv2 = (15 `january` 2024, 15 `february` 2024)+          iv3 = (1 `march` 2024, 31 `march` 2024)+      intersection iv1 iv2 `shouldBe` Just (15 `january` 2024, 31 `january` 2024)+      intersection iv1 iv3 `shouldBe` Nothing++  describe "PricingPeriod" $ do+    it "carries its dates/payment date/quantity, rejecting an end before the start" $ do+      ho <- commodityType "HO" "Heating Oil"+      bbl <- barrelUnitOfMeasure+      let s = 1 `january` 2024+          e = 31 `january` 2024+          p = 5 `february` 2024+          q = (ho, bbl, 1000)+          pp = pricingPeriod s e p q+      pricingPeriodStartDate pp `shouldBe` s+      pricingPeriodEndDate pp `shouldBe` e+      pricingPeriodPaymentDate pp `shouldBe` p+      pricingPeriodQuantity pp `shouldBe` q+      evaluate (pricingPeriod e s p q) `shouldThrow` anyErrorCall++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
+ test/hspec/QuantLib/Spec/TermStructure/InflationVolatility.hs view
@@ -0,0 +1,233 @@+module QuantLib.Spec.TermStructure.InflationVolatility (spec) where++import Control.Monad(forM_, zipWithM_)+import Data.Time.Calendar(addDays, addGregorianYearsClip)+import Test.Hspec++import qualified QuantLib.Settings as Settings+import QuantLib.Index.Inflation+import QuantLib.Math(Interpolation(..), Interpolation2D(..), Approximation(..), Matrix(..))+import QuantLib.TermStructure.Inflation+import QuantLib.TermStructure.InflationVolatility+import QuantLib.TermStructure.Yield(YieldTermStructure, interpolatedZeroCurve)+import QuantLib.Time.Calendar+import QuantLib.Time.Date+import QuantLib.Time.Schedule++-- |Builds an 'InterpolatedZeroCurve'-style nominal EUR curve from (time-from-eval, rate) pairs,+-- converting each time to a date the same way upstream's own fixture does (@eval ++-- Period(years,Years) + Period(days,Days)@, i.e. calendar-correct year steps plus a residual day+-- count -- NOT a plain 365-day multiple, which would quietly drift the resulting node dates+-- and hence the curve's node times under 'Actual365Fixed' by a day or two per node). Uses plain+-- 'Data.Time.Calendar' arithmetic on 'Day' directly rather than 'QuantLib.Time.Calendar.advance':+-- 'advance' steps a @Days@-unit period one *business day* at a time regardless of the given+-- 'BusinessDayConvention' (see @Calendar::advance@'s special-cased @unit == Days@ branch in+-- @ql/time/calendar.cpp@), which silently drifts a residual-day offset by however many holidays+-- and weekends it crosses -- badly enough, at these magnitudes, to reorder two nodes relative to+-- each other. Plain @Date + Period(Years) + Period(Days)@ (what upstream's own fixture computes)+-- has no such stepping, so plain 'Day' arithmetic is the faithful translation, not 'advance'.+nominalCurveFromTimes :: Calendar -> Day -> DayCounter -> [(Double, Double)] -> IO YieldTermStructure+nominalCurveFromTimes cal eval dc timesRates =+  interpolatedZeroCurve (map mkNode timesRates) dc cal [] (Cubic Kruger)+  where+    mkNode (t, r) =+      let ys = floor t :: Integer+          ds = floor ((t - fromIntegral ys) * 365) :: Integer+      in (addDays ds (addGregorianYearsClip ys eval), r)++-- |Upstream's own EUR nominal curve node data (test-suite/inflationvolatility.cpp's @setup()@),+-- unchanged: (time from eval, zero rate).+timesRatesEUR :: [(Double, Double)]+timesRatesEUR =+  [ (0.0109589, 0.0415600), (0.0684932, 0.0426840), (0.263014, 0.0470980), (0.317808, 0.0458506)+  , (0.567123, 0.0449550), (0.816438, 0.0439784), (1.06575, 0.0431887), (1.31507, 0.0426604)+  , (1.56438, 0.0422925), (2.0137, 0.0424591), (3.01918, 0.0421477), (4.01644, 0.0421853)+  , (5.01644, 0.0424016), (6.01644, 0.0426969), (7.01644, 0.0430804), (8.01644, 0.0435011)+  , (9.02192, 0.0439368), (10.0192, 0.0443825), (12.0192, 0.0452589), (15.0247, 0.0463389)+  , (20.0301, 0.0472636), (25.0356, 0.0473401), (30.0329, 0.0470629), (40.0384, 0.0461092)+  , (50.0466, 0.0450794) ]++-- |Upstream's YoY rates (times = years - 2 month lag; the first is the base rate), used to build+-- the linked 'YoYInflationTermStructure' directly via 'interpolatedYoYInflationCurve' -- these+-- are already-known market YoY levels, not swap quotes to bootstrap from.+yoyEURrates :: [Double]+yoyEURrates =+  [ 0.0237951+  , 0.0238749, 0.0240334, 0.0241934, 0.0243567, 0.0245323+  , 0.0247213, 0.0249348, 0.0251768, 0.0254337, 0.0257258+  , 0.0260217, 0.0263006, 0.0265538, 0.0267803, 0.0269378+  , 0.0270608, 0.0271363, 0.0272, 0.0272512, 0.0272927+  , 0.027317, 0.0273615, 0.0273811, 0.0274063, 0.0274307+  , 0.0274625, 0.027527, 0.0275952, 0.0276734, 0.027794 ]++-- |Upstream's cap/floor price-surface data (6 strikes x 7 maturities each for caps and floors).+cStrikesEU, fStrikesEU :: [Double]+cStrikesEU = [0.02, 0.025, 0.03, 0.035, 0.04, 0.05]+fStrikesEU = [-0.01, 0.00, 0.005, 0.01, 0.015, 0.02]++cfMaturitiesEU :: [(Word, TimeUnit)]+cfMaturitiesEU = [(3, Years), (5, Years), (7, Years), (10, Years), (15, Years), (20, Years), (30, Years)]++capPricesEU, floorPricesEU :: Matrix Double+capPricesEU = Matrix 6 7+  [ 116.225, 204.945, 296.285, 434.29, 654.47, 844.775, 1132.33+  , 34.305, 71.575, 114.1, 184.33, 307.595, 421.395, 602.35+  , 6.37, 19.085, 35.635, 66.42, 127.69, 189.685, 296.195+  , 1.325, 5.745, 12.585, 26.945, 58.95, 94.08, 158.985+  , 0.501, 2.37, 5.38, 13.065, 31.91, 53.95, 96.97+  , 0.501, 0.695, 1.47, 4.415, 12.86, 23.75, 46.7 ]+floorPricesEU = Matrix 6 7+  [ 0.501, 0.851, 2.44, 6.645, 16.23, 26.85, 46.365+  , 0.501, 2.236, 5.555, 13.075, 28.46, 44.525, 73.08+  , 1.025, 3.935, 9.095, 19.64, 39.93, 60.375, 96.02+  , 2.465, 7.885, 16.155, 31.6, 59.34, 86.21, 132.045+  , 6.9, 17.92, 32.085, 56.08, 95.95, 132.85, 194.18+  , 23.52, 47.625, 74.085, 114.355, 175.72, 229.565, 316.285 ]++-- |Vol slices at the surface's base date plus 1\/3 years, across the 11-strike union of+-- 'cStrikesEU'\/'fStrikesEU'. NOT upstream's own cached @volATyear1@\/@volATyear3@ (those are+-- @{0.0129, 0.0094, ...}@\/@{0.0080, 0.0058, ...}@) -- those values are stale against the+-- QuantLib 1.43 actually installed here, off by several times this test's tolerance. Confirmed+-- via an independent, minimal C++ program (bypassing hasquant's Haskell layer entirely) built+-- straight from @setup()@\/@setupPriceSurface()@\/@testYoYPriceSurfaceToVol@'s own C++ verbatim,+-- linked against the same installed @libQuantLib@: it reproduces exactly these values, not+-- upstream's cached ones, ruling out a hasquant-side bug and pointing at behavior that changed+-- upstream since this fixture was written (2009) without the cached numbers being refreshed --+-- consistent with both 'KInterpolatedYoYOptionletVolatilitySurface' and+-- 'InterpolatedYoYOptionletStripper' carrying an explicit upstream doc comment of their own,+-- @\\bug Tests currently fail@.+volATyear1, volATyear3 :: [Double]+volATyear1 = [0.0135064, 0.0098650, 0.0087791, 0.0077453, 0.0067549, 0.0060420, 0.0043860, 0.0048649, 0.0056425, 0.0067729, 0.0103381]+volATyear3 = [0.0085961, 0.0062788, 0.0055840, 0.0049221, 0.0042875, 0.0038286, 0.0027751, 0.0030795, 0.0035763, 0.0042978, 0.0065660]++-- |Cached YoY swap curve / ATM YoY rates from upstream's own @testYoYPriceSurfaceToATM@, at+-- 'cfMaturitiesEU'.+atmYoYSwapRates, atmYoYRates :: [Double]+atmYoYSwapRates = [0.024586, 0.0247575, 0.0249396, 0.0252596, 0.0258498, 0.0262883, 0.0267915]+atmYoYRates = [0.0247659, 0.0251437, 0.0255945, 0.0265015, 0.0280457, 0.0285534, 0.0295884]++setup :: IO (Day, Calendar, DayCounter, YieldTermStructure, YoYInflationIndex, YoYCapFloorTermPriceSurface)+setup = do+  let eval = 23 `november` 2007+  Settings.setEvaluationDate (Just eval)+  cal <- calendar TARGET+  dc <- dayCounter Actual365FixedStandard+  nominalEUR <- nominalCurveFromTimes cal eval dc timesRatesEUR++  -- the base date is based on the last published index fixing, and cap maturities are based+  -- on the observation lag -- both computed the same today-relative way upstream's setup() does+  baseDate <- advance cal eval (-1, Months) Unadjusted False+  capStartDate <- advance cal eval (-2, Months) ModifiedFollowing False+  yoyDates <- (baseDate :) <$> mapM (\n -> advance cal capStartDate (n, Years) ModifiedFollowing False) [1 .. length yoyEURrates - 1]+  yoyEU <- interpolatedYoYInflationCurve eval (zip yoyDates yoyEURrates) Monthly dc Linear++  zii <- zeroInflationIndex EUHICP+  yoyIndexEU <- yoyInflationIndexFromZero zii (Just yoyEU)++  let fixingDays = 0+      yyLag = (3, Months)+  priceSurfEU <- yoyCapFloorTermPriceSurface fixingDays yyLag yoyIndexEU CPILinear nominalEUR dc cal ModifiedFollowing+                   cStrikesEU fStrikesEU cfMaturitiesEU capPricesEU floorPricesEU Bicubic (Cubic Kruger)++  return (eval, cal, dc, nominalEUR, yoyIndexEU, priceSurfEU)++spec :: Spec+spec = describe "YoY optionlet stripper (KInterpolatedYoYOptionletVolatilitySurface)" $ do+  it "interpolatedYoYInflationCurve: a non-Linear interpolation builds and differs between nodes" $ Settings.keepingSettings' $ do+    let eval = 23 `november` 2007+    Settings.setEvaluationDate (Just eval)+    cal <- calendar TARGET+    dc <- dayCounter Actual365FixedStandard+    baseDate <- advance cal eval (-1, Months) Unadjusted False+    capStartDate <- advance cal eval (-2, Months) ModifiedFollowing False+    yoyDates <- (baseDate :) <$> mapM (\n -> advance cal capStartDate (n, Years) ModifiedFollowing False) [1 .. length yoyEURrates - 1]+    let mid = addDays 180 (yoyDates !! 1)+    yoyLinear <- interpolatedYoYInflationCurve eval (zip yoyDates yoyEURrates) Monthly dc Linear+    yoyCubic <- interpolatedYoYInflationCurve eval (zip yoyDates yoyEURrates) Monthly dc (Cubic Kruger)+    rLinear <- yoyRate yoyLinear mid True+    rCubic <- yoyRate yoyCubic mid True+    -- both interpolators agree at the nodes themselves; a mid-node query is where a genuinely+    -- different interpolation should (and does) diverge from Linear+    abs (rLinear - rCubic) `shouldSatisfy` (> 1e-8)++  it "matches an independent C++ reprise of upstream's testYoYPriceSurfaceToVol fixture" $ Settings.keepingSettings' $ do+    (_, cal, dc, nominalEUR, yoyIndexEU, priceSurfEU) <- setup++    yoySurf <- kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack 0 cal ModifiedFollowing dc+                 priceSurfEU yoyIndexEU nominalEUR (-0.5) Linear++    strikes <- yoyCapFloorStrikes priceSurfEU+    baseDate <- yoyCapFloorBaseDate priceSurfEU+    d1 <- advance cal baseDate (1, Years) Unadjusted False+    d3 <- advance cal baseDate (3, Years) Unadjusted False++    let eps = 1e-6 :: Double+    zipWithM_ (\k v -> do+        vol <- yoyOptionletVolatility yoySurf d1 k Nothing True+        abs (vol - v) `shouldSatisfy` (< eps)+      ) strikes volATyear1+    zipWithM_ (\k v -> do+        vol <- yoyOptionletVolatility yoySurf d3 k Nothing True+        abs (vol - v) `shouldSatisfy` (< eps)+      ) strikes volATyear3++  it "recovers upstream's cached ATM YoY swap/inflation curve (testYoYPriceSurfaceToATM)" $ Settings.keepingSettings' $ do+    (_, _, _, _, _, priceSurfEU) <- setup++    dateRates <- yoyCapFloorAtmYoYSwapDateRates priceSurfEU+    let eps = 2e-5 :: Double+    zipWithM_ (\(d, r) expected -> do+        abs (r - expected) `shouldSatisfy` (< eps)+        r2 <- yoyCapFloorAtmYoYSwapRate priceSurfEU d True+        abs (r2 - expected) `shouldSatisfy` (< eps)+      ) dateRates atmYoYSwapRates++    forM_ (zip (map fst dateRates) atmYoYRates) $ \(d, expected) -> do+      a <- yoyCapFloorAtmYoYRate priceSurfEU d Nothing True+      abs (a - expected) `shouldSatisfy` (< eps)++  -- No second upstream fixture covers a non-(Bicubic, Cubic) combination, so this is a+  -- construction/sanity check only, same reasoning as the interpolatedYoYInflationCurve+  -- spot-check above.+  it "yoyCapFloorTermPriceSurface: a different (Interpolation2D, Interpolation) pair builds and queries" $ Settings.keepingSettings' $ do+    let eval = 23 `november` 2007+    Settings.setEvaluationDate (Just eval)+    cal <- calendar TARGET+    dc <- dayCounter Actual365FixedStandard+    nominalEUR <- nominalCurveFromTimes cal eval dc timesRatesEUR+    baseDate <- advance cal eval (-1, Months) Unadjusted False+    capStartDate <- advance cal eval (-2, Months) ModifiedFollowing False+    yoyDates <- (baseDate :) <$> mapM (\n -> advance cal capStartDate (n, Years) ModifiedFollowing False) [1 .. length yoyEURrates - 1]+    yoyEU <- interpolatedYoYInflationCurve eval (zip yoyDates yoyEURrates) Monthly dc Linear+    zii <- zeroInflationIndex EUHICP+    yoyIndexEU <- yoyInflationIndexFromZero zii (Just yoyEU)++    priceSurf <- yoyCapFloorTermPriceSurface 0 (3, Months) yoyIndexEU CPILinear nominalEUR dc cal ModifiedFollowing+                   cStrikesEU fStrikesEU cfMaturitiesEU capPricesEU floorPricesEU Bilinear Linear+    ((rate1st, _):_) <- yoyCapFloorAtmYoYSwapDateRates priceSurf+    rate <- yoyCapFloorAtmYoYSwapRate priceSurf rate1st True+    rate `shouldSatisfy` (not . isNaN)++  -- No second upstream fixture covers a non-Linear interpolation here, so this is a+  -- construction/sanity check only, same reasoning as the spot-checks above. LogCubic is+  -- deliberately not exercised: it can't back this template at all (see the comment on the+  -- LogCubic case in qlInflationVol.cpp's dispatchKInterpolatedYoYOptionletVolatilitySurface).+  -- Cubic/LogLinear are also skipped here: this fixture's sparse (3-maturity) per-strike vol+  -- bootstrap (PiecewiseYoYOptionletVolatilityCurve, one per strike, see initialize() in+  -- interpolatedyoyoptionletstripper.hpp) fails to converge under Cubic's default-constructed+  -- Kruger derivative estimate with so few points ("root not bracketed") -- a real numerical+  -- fragility of the bootstrap with this data, not a hasquant bug. BackwardFlat has no derivative+  -- estimation so it bootstraps fine and still exercises a genuinely different interpolator.+  it "kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack: a non-Linear interpolation builds and queries" $ Settings.keepingSettings' $ do+    (_, cal, dc, nominalEUR, yoyIndexEU, priceSurfEU) <- setup++    yoySurf <- kInterpolatedYoYOptionletVolatilitySurfaceUnitDisplacedBlack 0 cal ModifiedFollowing dc+                 priceSurfEU yoyIndexEU nominalEUR (-0.5) BackwardFlat++    (strike1st: _) <- yoyCapFloorStrikes priceSurfEU+    baseDate <- yoyCapFloorBaseDate priceSurfEU+    d1 <- advance cal baseDate (1, Years) Unadjusted False+    vol <- yoyOptionletVolatility yoySurf d1 strike1st Nothing True+    vol `shouldSatisfy` (not . isNaN)++-- vim: set ff=unix ts=8 sts=2 sw=2 et:
test/main/QuantLib/MainTest.hs view
@@ -9,8 +9,15 @@ import qualified QuantLib.Spec.DatesAndSchedule as DatesAndSchedule import qualified QuantLib.Spec.Calendars as Calendars import qualified QuantLib.Spec.CurrencyAndDayCounter as CurrencyAndDayCounter+import qualified QuantLib.Spec.Commodity as Commodity import qualified QuantLib.Spec.InterestRateAndCashFlow as InterestRateAndCashFlow import qualified QuantLib.Spec.TermStructure as TermStructure+import qualified QuantLib.Spec.TermStructure.Commodity as TermStructureCommodity+import qualified QuantLib.Spec.TermStructure.InflationVolatility as TermStructureInflationVolatility+import qualified QuantLib.Spec.Index.Commodity as IndexCommodity+import qualified QuantLib.Spec.Instrument.Energy as InstrumentEnergy+import qualified QuantLib.Spec.Instrument.InflationCapFloor as InstrumentInflationCapFloor+import qualified QuantLib.Spec.Instrument.Option as InstrumentOption import qualified QuantLib.Spec.Examples as Examples  main :: IO ()@@ -26,8 +33,15 @@     DatesAndSchedule.spec     Calendars.spec tod     CurrencyAndDayCounter.spec+    Commodity.spec     InterestRateAndCashFlow.spec tod     TermStructure.spec+    TermStructureCommodity.spec+    TermStructureInflationVolatility.spec+    IndexCommodity.spec+    InstrumentEnergy.spec+    InstrumentInflationCapFloor.spec+    InstrumentOption.spec     Examples.spec  -- vim: set ff=unix ts=8 sts=2 sw=2 et: