packages feed

hasquant-0.7.0.0: QuantLib/Index.chs

module QuantLib.Index
  (
    -- * Types
    GenIndex
  , Index
  , HistoricalIndexAnalysis

    -- * Constructors
  , asIndex
  , historicalIndexAnalysis

    -- * Mutators
  , addFixing
  , addFixings
  , clearFixings
  , clearAllFixingHistories

    -- * Inspectors
    -- ** Index fixings
  , fixingCalendar
  , fixing
  , hasHistoricalFixing
  , isValidFixingDate
  , fixingHistory
  , fixingHistoryNames
    -- ** Historical return analysis
  , skipped
  , mean
  , standardDeviation
  , skewness
  , kurtosis
  , minimumReturn
  , maximumReturn
  , semiVariance
  , semiDeviation
  , downsideVariance
  , downsideDeviation
  , percentile
  , gaussianPercentile
  , valueAtRisk
  , potentialUpside
  , gaussianPotentialUpside
  , regret
  , shortfall
  , gaussianShortfall
  , averageShortfall
  , gaussianAverageShortfall
  , gaussianValueAtRisk
  , expectedShortfall
  , gaussianExpectedShortfall
  , covariance
  , correlation
  ) where
import QuantLib.Internal
import QuantLib.Internal.Common
import QuantLib.Internal.Type

#include "qlTypesC2HS.h"
#include "qlEnumC2HS.h"
#include "qlEnumObjects.h"

#include "ql.h"

{#pointer *Calendar foreign -> CCalendar nocode#}
{#pointer *QlIndex as Index foreign -> CIndex' nocode#}

-- |stores the historical fixing at the given date; the date must be the actual calendar date of the fixing, not a settlement date
{#fun qlIndexAddFixing as addFixing{withIndex*`GenIndex idx',withDay*`Day',`Double' -- ^fixing
  ,`Bool' -- ^forceOverwrite
  ,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |returns the calendar defining valid fixing dates
{#fun qlIndexFixingCalendar as fixingCalendar{withIndex*`GenIndex idx',preErrorCheck-`String'errorCheck*-}->`Calendar'peekCalendar*#}

-- |returns the fixing at the given date, forecasting it if not available and /forecastTodaysFixing/ is true
{#fun qlIndexFixing as fixing{withIndex*`GenIndex idx',withDay*`Day',`Bool' -- ^forecastTodaysFixing
  ,preErrorCheck-`String'errorCheck*-}->`Double'#}

-- |whether a historical fixing has been stored for the given date
{#fun qlIndexHasHistoricalFixing as hasHistoricalFixing{withIndex*`GenIndex idx',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Bool'#}

-- |whether the given date is a valid fixing date for this index
{#fun qlIndexIsValidFixingDate as isValidFixingDate{withIndex*`GenIndex idx',withDay*`Day',preErrorCheck-`String'errorCheck*-}->`Bool'#}

-- |Stores historical fixings as @(date, value)@ pairs; the date is the actual fixing date.
addFixings :: GenIndex idx -> [(Day, Double)] -> Bool -> IO ()
addFixings idx fixings forceOverwrite = qlIndexAddFixings idx dates values forceOverwrite
  where (dates, values) = unzip fixings
{#fun qlIndexAddFixings{withIndex*`GenIndex idx',withDayArray*`[Day]'&,withDoubleArrayRaw*`[Double]',`Bool' -- ^forceOverwrite
  ,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |clears all stored historical fixings for this index
{#fun qlIndexClearFixings as clearFixings{withIndex*`GenIndex idx',preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Returns every stored native fixing for this index, in ascending date order.  This is a
-- snapshot copied out of QuantLib's process-global fixing store; it has no forecasting behavior.
fixingHistory :: GenIndex idx -> IO [(Day, Double)]
fixingHistory i = do
  (ds, vs) <- qlIndexFixingHistory i
  return $ zip ds vs
{#fun qlIndexFixingHistory{withIndex*`GenIndex idx'
  ,preArray-`[Day]'&peekDayArray*,preArray-`[Double]'&peekDoubleArray*
  ,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Returns the names with an entry in QuantLib's process-global fixing store.  Names are
-- case-insensitive in that store and can be shared by separate index instances.
{#fun qlIndexManagerHistories as fixingHistoryNames{preArray-`[String]'&peekCStringArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Clears every native fixing history in QuantLib's process-global store, for all index names.
-- This affects other index instances and is intended for explicit session or test cleanup.
{#fun qlIndexManagerClearHistories as clearAllFixingHistories{preErrorCheck-`String'errorCheck*-}->`()'#}

{#pointer *QlHistoricalIndexAnalysis as HistoricalIndexAnalysis foreign -> CHistoricalIndexAnalysis nocode#}

-- |Computes 'SequenceStatistics' (mean\/standard deviation\/skewness\/kurtosis\/min\/max\/semi-
-- and downside-variance and -deviation\/percentiles\/value-at-risk\/expected shortfall,
-- empirical and gaussian-assumption\/covariance\/correlation) over historical fixings of the
-- given indexes, sampled every @step@ between @startDate@ and @endDate@. A date/index pair whose
-- fixing is unavailable is recorded in 'skipped' rather than failing the whole analysis.
-- 'SequenceStatistics' is only the accumulator filled internally by this constructor, so its
-- risk-statistics surface is exposed directly through these accessors.
{#fun qlHistoricalIndexAnalysis as historicalIndexAnalysis{withDay*`Day' -- ^startDate
  ,withDay*`Day' -- ^endDate
  ,fromEnumQuantity`(Int,TimeUnit)'& -- ^step
  ,withIndexArray*`[Index]'&
  ,preErrorCheck-`String'errorCheck*-}->`HistoricalIndexAnalysis'peekHistoricalIndexAnalysis*#}

-- |Skipped fixing dates paired with the reason no complete fixing vector was available.
skipped :: HistoricalIndexAnalysis -> IO [(Day, String)]
skipped analysis = do
  dates <- qlHistoricalIndexAnalysisSkippedDates analysis
  messages <- qlHistoricalIndexAnalysisSkippedMessages analysis
  pure (zip dates messages)
{#fun qlHistoricalIndexAnalysisSkippedDates as qlHistoricalIndexAnalysisSkippedDates{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Day]'&peekDayArray*,preErrorCheck-`String'errorCheck*-}->`()'#}
{#fun qlHistoricalIndexAnalysisSkippedDatesErrorMessage as qlHistoricalIndexAnalysisSkippedMessages{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[String]'&peekCStringArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index mean of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisMean as mean{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index standard deviation of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisStandardDeviation as standardDeviation{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index skewness of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisSkewness as skewness{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index (excess) kurtosis of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisKurtosis as kurtosis{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index minimum of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisMin as minimumReturn{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index maximum of the historical relative returns actually sampled.
{#fun qlHistoricalIndexAnalysisMax as maximumReturn{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index variance of the historical relative returns falling below the mean.
{#fun qlHistoricalIndexAnalysisSemiVariance as semiVariance{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index square root of 'semiVariance'.
{#fun qlHistoricalIndexAnalysisSemiDeviation as semiDeviation{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index variance of the historical relative returns falling below zero.
{#fun qlHistoricalIndexAnalysisDownsideVariance as downsideVariance{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index square root of 'downsideVariance'.
{#fun qlHistoricalIndexAnalysisDownsideDeviation as downsideDeviation{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis',preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical @y@-th percentile of the historical relative returns actually sampled;
-- @y@ must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisPercentile as percentile{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^y
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index @y@-th percentile assuming the historical relative returns are gaussian; @y@ must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisGaussianPercentile as gaussianPercentile{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^y
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical value-at-risk at the given @centile@, which must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisValueAtRisk as valueAtRisk{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index value-at-risk at the given @centile@ assuming the historical relative returns are gaussian; @centile@ must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisGaussianValueAtRisk as gaussianValueAtRisk{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical expected shortfall at the given @centile@, which must lie in @[0.9, 1.0)@.
-- Throws if no sampled return falls below the value-at-risk threshold.
{#fun qlHistoricalIndexAnalysisExpectedShortfall as expectedShortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index expected shortfall at the given @centile@ assuming the historical relative returns
-- are gaussian; @centile@ must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisGaussianExpectedShortfall as gaussianExpectedShortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical potential upside at the given @centile@, which must lie in @[0.9, 1.0)@ --
-- the upside counterpart of 'valueAtRisk'.
{#fun qlHistoricalIndexAnalysisPotentialUpside as potentialUpside{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index potential upside at the given @centile@ assuming the historical relative returns
-- are gaussian; @centile@ must lie in @[0.9, 1.0)@.
{#fun qlHistoricalIndexAnalysisGaussianPotentialUpside as gaussianPotentialUpside{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^centile
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index regret at the given @target@: expected loss below target, conditional on being below it.
{#fun qlHistoricalIndexAnalysisRegret as regret{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^target
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical probability of falling below @target@.
{#fun qlHistoricalIndexAnalysisShortfall as shortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^target
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index probability of falling below @target@ assuming the historical relative returns are gaussian.
{#fun qlHistoricalIndexAnalysisGaussianShortfall as gaussianShortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^target
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index empirical average shortfall (expected loss below @target@, unconditional) at the given @target@.
{#fun qlHistoricalIndexAnalysisAverageShortfall as averageShortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^target
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Per-index average shortfall at the given @target@ assuming the historical relative returns are gaussian.
{#fun qlHistoricalIndexAnalysisGaussianAverageShortfall as gaussianAverageShortfall{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,`Double' -- ^target
  ,preArray-`[Double]'&peekDoubleArray*,preErrorCheck-`String'errorCheck*-}->`()'#}

toMatrixDouble :: (Word, Word, [Double]) -> Matrix Double
toMatrixDouble (r, c, d) = Matrix r c d

-- |Covariance matrix of the historical relative returns across indexes.
covariance :: HistoricalIndexAnalysis -> IO (Matrix Double)
covariance hra = toMatrixDouble <$> qlHistoricalIndexAnalysisCovariance hra
{#fun qlHistoricalIndexAnalysisCovariance{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,prePtr-`Word'peekWord*,prePtr-`Word'peekWord*,preArray-`[Double]'&peekDoubleArray*
  ,preErrorCheck-`String'errorCheck*-}->`()'#}

-- |Correlation matrix of the historical relative returns across indexes.
correlation :: HistoricalIndexAnalysis -> IO (Matrix Double)
correlation hra = toMatrixDouble <$> qlHistoricalIndexAnalysisCorrelation hra
{#fun qlHistoricalIndexAnalysisCorrelation{withHistoricalIndexAnalysis*`HistoricalIndexAnalysis'
  ,prePtr-`Word'peekWord*,prePtr-`Word'peekWord*,preArray-`[Double]'&peekDoubleArray*
  ,preErrorCheck-`String'errorCheck*-}->`()'#}

-- vim: set ff=unix ts=8 sts=2 sw=2 et: