hasquant-0.6.0.0: QuantLib/TermStructure/Commodity.chs
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: