Module curveengine.parsing.checks
Expand source code
import re
from functools import partial
from .enums import *
'''
Example of a basic structure of the curve request:
{
"refDate": "2020-01-01",
"curves": [
{
"curveName": "PiecewiseCurveExample",
"curveConfig": {
"curveType": "Piecewise",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"rateHelpers": [
{
"helperConfig": {
...
},
"marketConfig": {
...
},
}
]
},
"curveIndex":{
...
}
},
{
"curveName": "DiscountCurveExample",
"curveConfig": {
"curveType": "Discount",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"nodes": [
{
"date": "2020-01-01",
"discount": 0.01
},
{
"date": "2020-02-01",
"discount": 0.02
}
]
},
"curveIndex":{
...
}
}
]
}
'''
class ConfigurationError(Exception):
'''
Exception raised when the request is invalid
'''
def __init__(self, message):
self.message = message
class RateIndexError(ConfigurationError):
'''
Exception raised when the index is invalid
'''
def __init__(self, message):
self.message = message
class RateHelperConfigurationError(ConfigurationError):
'''
Exception raised when the rate helper is invalid
'''
def __init__(self, message):
self.message = message
class MarketConfigurationError(ConfigurationError):
'''
Exception raised when the market configuration is invalid
'''
def __init__(self, message):
self.message = message
## Check available enums and possible instances#
def checkDate(value) -> None:
'''
Check if the date is valid
Parameters
----------
value: str
The date
Returns
-------
None
Raises
------
ValueError
If the date is invalid
'''
if not re.match(r'^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,6})?(Z|[+-]\d{2}:\d{2})?)?$', value):
raise ValueError(f'{value} is not a valid date or it does not follow the ISO format.')
def checkIsInEnum(value: str, enum: list) -> None:
'''
Check if the value is in the enum
Parameters
----------
value: str
The value to check
enum: list
The enum
Returns
-------
None
Raises
------
ValueError
If the value is not in the enum
'''
if value not in enum:
raise ValueError(f'{value} is not in {enum}')
def checkDayCounter(value) -> None:
'''
Check if the day counter is valid
Parameters
----------
value: str
The day counter. It must match the DayCounter enum.
Returns
-------
None
Raises
------
ValueError
If the day counter is invalid
Also see
--------
checkIsInEnum
DayCounter
'''
checkIsInEnum(value, DayCounter.__members__)
def checkFrequency(value) -> None:
'''
Check if the frequency is valid
Parameters
----------
value: str
The frequency, matching the Frequency enum.
Returns
-------
None
Raises
------
ValueError
If the frequency is invalid
Also see
--------
checkIsInEnum
Frequency
'''
checkIsInEnum(value, Frequency.__members__)
def checkCompounding(value) -> None:
'''
Check if the compounding is valid
Parameters
----------
value: str
The compounding, matching the Compounding enum.
Returns
-------
None
Raises
------
ValueError
If the compounding is invalid
Also see
--------
checkIsInEnum
Compounding
'''
checkIsInEnum(value, Compounding.__members__)
def checkConvention(value) -> None:
'''
Check if the convention is valid
Parameters
----------
value: str
The convention, matching the Convention enum.
Returns
-------
None
Raises
------
ValueError
If the convention is invalid
Also see
--------
checkIsInEnum
Convention
'''
checkIsInEnum(value, Convention.__members__)
def checkCalendar(value) -> None:
'''
Check if the calendar is valid
Parameters
----------
value: str
The calendar, matching the Calendar enum.
Returns
-------
None
Raises
------
ValueError
If the calendar is invalid
Also see
--------
checkIsInEnum
Calendar
'''
checkIsInEnum(value, Calendar.__members__)
def checkCurrency(value) -> None:
'''
Check if the currency is valid
Parameters
----------
value: str
The currency, matching the Currency enum.
Returns
-------
None
Raises
------
ValueError
If the currency is invalid
Also see
--------
checkIsInEnum
Currency
'''
checkIsInEnum(value, Currency.__members__)
def checkDateGenerationRule(value) -> None:
'''
Check if the date generation rule is valid
Parameters
----------
value: str
The date generation rule, matching the DateGenerationRule enum.
Returns
-------
None
Raises
------
ValueError
If the date generation rule is invalid
Also see
--------
checkIsInEnum
DateGenerationRule
'''
checkIsInEnum(value, DateGenerationRule.__members__)
def checkTenor(tenor: str) -> None:
'''
Check if the tenor is valid
Parameters
----------
tenor: str
The tenor, it can be a number followed by D, W, M or Y
Returns
-------
None
Raises
------
ConfigurationError
If the tenor is invalid
'''
regex = r'^(\d+[DWMY])+$'
if not re.match(regex, tenor):
raise ValueError(f'The tenor {tenor} is invalid')
def checkDictStructure(input: dict, reference: dict) -> None:
for key in reference.keys():
if key not in input.keys():
raise KeyError(
f'The required key "{key}" is missing.')
for key in input.keys():
if key in reference.keys():
reference[key](input[key])
def checkInstance(value: any, type: type) -> None:
'''
Check if the value is an instance of the type
Parameters
----------
value: any
The value to check
type: type
The type to check
Returns
-------
None
Raises
------
ValueError
If the value is not an instance of the type
'''
if not isinstance(value, type):
raise ValueError(f'The value {value} is not an instance of {type}.')
## Rate helpers checks ##
def checkOISRateHelper(data: dict) -> None:
'''
Check if the OIS rate helper is valid
Parameters
----------
data: dict
The OIS rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The OIS rate helper should have the following example structure:
```
"helperConfig": {
"tenor": "1W",
"dayCounter": "Actual360",
"calendar": "NullCalendar",
"convention": "Following",
"endOfMonth": True,
"frequency": "Annual",
"settlementDays": 2,
"paymentLag": 2,
"telescopicValueDates": True,
"index": "SOFR",
"fixedLegFrequency": "Semiannual",
"fwdStart": "0D",
"discountCurve": "SOFR"
}
```
'''
reference = {
"tenor": checkTenor,
"dayCounter": checkDayCounter,
"calendar": checkCalendar,
"convention": checkConvention,
"endOfMonth": partial(checkInstance, type=bool),
"frequency": checkFrequency,
"settlementDays": partial(checkInstance, type=int),
"paymentLag": partial(checkInstance, type=int),
"telescopicValueDates": partial(checkInstance, type=bool),
"index": partial(checkInstance, type=str),
"fixedLegFrequency": checkFrequency,
"fwdStart": checkTenor,
"discountCurve": partial(checkInstance, type=str)
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError('Invalid OIS rate helper') from exc
def checkDepositRateHelper(data: dict) -> None:
'''
Check if the deposit rate helper is valid
Parameters
----------
data: dict
The deposit rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The deposit rate helper should have the following example structure:
```
"helperConfig": {
"dayCounter": "Actual360",
"tenor": "1D",
"calendar": "NullCalendar",
"settlementDays": 0,
"endOfMonth": False,
"convention": "Unadjusted"
}
```
'''
reference = {
"dayCounter": checkDayCounter,
"tenor": checkTenor,
"calendar": checkCalendar,
"settlementDays": partial(checkInstance, type=int),
"endOfMonth": partial(checkInstance, type=bool),
"convention": checkConvention
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid deposit rate helper') from exc
def checkSwapRateHelper(data: dict) -> None:
'''
Check if the swap rate helper is valid
Parameters
----------
data: dict
The swap rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The swap rate helper should have the following example structure:
```
"helperConfig": {
"tenor": "2Y",
"dayCounter": "Thirty360",
"calendar": "NullCalendar",
"frequency": "Semiannual",
"settlementDays": 2,
"discountCurve": "SOFR",
"index": "LIBOR3M",
"endOfMonth": False,
"convention": "Unadjusted",
"fixedLegFrequency": "Semiannual",
"fwdStart": "0D"
}
```
'''
reference = {
"tenor": checkTenor,
"dayCounter": checkDayCounter,
"calendar": checkCalendar,
"frequency": checkFrequency,
"settlementDays": partial(checkInstance, type=int),
"discountCurve": partial(checkInstance, type=str),
"index": partial(checkInstance, type=str),
"endOfMonth": partial(checkInstance, type=bool),
"convention": checkConvention,
"fixedLegFrequency": checkFrequency,
"fwdStart": checkTenor
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError('Invalid swap rate helper') from exc
def checkFixedRateBondRateHelper(data: dict) -> None:
'''
Check if the bond rate helper is valid
Parameters
----------
data: dict
The bond rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The bond rate helper should have the following example structure:
```
"helperConfig": {
"calendar": "NullCalendar",
"convention": "Following",
"settlementDays": 2,
"couponDayCounter": "Actual360",
"couponRate": 0.05,
"frequency": "Annual",
"startDate": "2020-01-01",
"endDate": "2022-01-01",
"tenor": "2Y" # needed if start date and end date are not provided
}
```
'''
reference = {
"calendar": checkCalendar,
"convention": checkConvention,
"settlementDays": partial(checkInstance, type=int),
"couponDayCounter": checkDayCounter,
"couponRate": partial(checkInstance, type=float),
"frequency": checkFrequency,
}
# check if the start date and end date are provided
if "startDate" in data or "endDate" in data:
reference["startDate"] = checkDate
reference["endDate"] = checkDate
else:
reference["tenor"] = checkTenor
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError('Invalid bond rate helper') from exc
def checkFxSwapRateHelper(data: dict) -> None:
'''
Check if the FX swap rate helper is valid
Parameters
----------
data: dict
The FX swap rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The FX swap rate helper should have the following example structure:
```
"helperConfig": {
"calendar": "NullCalendar",
"fixingDays": 0,
"endOfMonth": False,
"baseCurrencyAsCollateral": False,
"convention": "Following",
"discountCurve": "CLP_COLLUSD",
"endDate": "2023-04-09",
"tenor": "1Y", # need if no end date is provided
"settlementDays": 0
}
```
'''
reference = {
"calendar": checkCalendar,
"fixingDays": partial(checkInstance, type=int),
"endOfMonth": partial(checkInstance, type=bool),
"baseCurrencyAsCollateral": partial(checkInstance, type=bool),
"convention": checkConvention,
"discountCurve": partial(checkInstance, type=str),
"settlementDays": partial(checkInstance, type=int)
}
# check if the end date is provided
if "endDate" in data:
reference["endDate"] = checkDate
else:
reference["tenor"] = checkTenor
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid FX swap rate helper') from exc
def checkCrossCcyFixFloatSwapRateHelper(data: dict) -> None:
'''
Check if the cross currency rate helper is valid
Parameters
----------
data: dict
The cross currency rate helper
Returns
-------
None
no return, raise RateHelperConfigurationError if the request is invalid
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The cross currency rate helper should have the following example structure:
```
"helperConfig": {
"tenor": "2Y",
"dayCounter": "Actual360",
"calendar": "NullCalendar",
"convention": "ModifiedFollowing",
"endOfMonth": False,
"settlementDays": 2,
"discountCurve": "CLP_COLLUSD",
"index": "ICP",
"fixedLegCurrency": "CLF",
"fwdStart": "0D",
"fixedLegFrequency": "Semiannual"
}
```
'''
reference = {
"tenor": checkTenor,
"dayCounter": checkDayCounter,
"calendar": checkCalendar,
"convention": checkConvention,
"endOfMonth": partial(checkInstance, type=bool),
"settlementDays": partial(checkInstance, type=int),
"discountCurve": partial(checkInstance, type=str),
"index": partial(checkInstance, type=str),
"fixedLegCurrency": partial(checkInstance, type=str),
"fwdStart": checkTenor,
"fixedLegFrequency": checkFrequency
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid cross currency rate helper') from exc
def checkTenorBasisSwapRateHelper(data: dict) -> None:
'''
Check if the tenor basis rate helper is valid
Parameters
----------
data: dict
The tenor basis rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The tenor basis rate helper should have the following example structure:
```
"helperConfig": {
"tenor": "3M",
"longIndex": "LIBOR3M",
"shortIndex": "LIBOR1M",
"discountCurve": "SOFR",
"spreadOnShort": True
}
```
'''
reference = {
"tenor": checkTenor,
"longIndex": partial(checkInstance, type=str),
"shortIndex": partial(checkInstance, type=str),
"discountCurve": partial(checkInstance, type=str),
"spreadOnShort": partial(checkInstance, type=bool)
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid tenor basis rate helper') from exc
def checkCrossCcyBasisSwapRateHelper(data: dict) -> None:
'''
Check if the cross currency basis rate helper is valid
Parameters
----------
data: dict
The cross currency basis rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The cross currency basis rate helper should have the following example structure:
```
"helperConfig": {
"tenor": "3M",
"calendar": "NullCalendar",
"settlementDays": 2,
"endOfMonth": False,
"convention": "ModifiedFollowing",
"flatIndex": "LIBOR3M",
"spreadIndex": "LIBOR1M",
"flatDiscountCurve": "SOFR",
"spreadDiscountCurve": "CLP_COLLUSD",
"flatIsDomestic": True
}
```
'''
reference = {
"tenor": checkTenor,
"calendar": checkCalendar,
"settlementDays": partial(checkInstance, type=int),
"endOfMonth": partial(checkInstance, type=bool),
"convention": checkConvention,
"flatIndex": partial(checkInstance, type=str),
"spreadIndex": partial(checkInstance, type=str),
"flatDiscountCurve": partial(checkInstance, type=str),
"spreadDiscountCurve": partial(checkInstance, type=str),
"flatIsDomestic": partial(checkInstance, type=bool)
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid cross currency basis rate helper') from exc
def checkMarketConfig(data: dict, helperType: HelperType) -> None:
'''
Check if the market config is valid
Parameters
----------
data: dict
The market config
Returns
-------
None
Raises
------
ConfigurationError
If the market config is invalid
Details
-------
The market config should have the following example structure:
```
"marketConfig": {
"rate": {
"ticker" : "CLP_CU",
"value" : 0.01
},
"spread": {
"ticker" : "CLP_CU",
"value" : 0.01
},
"fxSpot": {
"ticker" : "CLP_CU",
"value" : 0.01
},
"fxPoints": {
"ticker" : "CLP_CU",
"value" : 0.01
}
}
```
Where each field has at least a value. The ticker is optional.
Each field is dependent on the helper type. The following table shows the required fields for each helper type:
|Helper type | Required fields |
|----------------------- | ---------------------------------|
|Deposit | rate |
|Swap | rate, spread |
|FxSwap | fxSpot, fxPoints |
|Xccy | rate, spread, fxSpot |
|TenorBasis | spread |
|XccyBasis | spread, fxSpot |
|OIS | spread |
|Bond | rate |
'''
def checkPrice(data: dict) -> None:
if not isinstance(data, dict):
raise ConfigurationError(
'Invalid price, should be a dictionary')
if 'value' not in data:
raise ConfigurationError(
'Invalid price, missing value')
if not isinstance(data['value'], float) and not isinstance(data['value'], int):
raise ConfigurationError(
'Invalid price, value should be a float or int')
if 'ticker' in data and not isinstance(data['ticker'], str):
raise ConfigurationError(
'Invalid price, ticker should be a string')
reference = {}
if helperType == HelperType.Deposit:
reference = {
"rate": checkPrice
}
elif helperType == HelperType.Swap:
reference = {
"rate": checkPrice,
"spread": checkPrice
}
elif helperType == HelperType.FxSwap:
reference = {
"fxSpot": checkPrice,
"fxPoints": checkPrice
}
elif helperType == HelperType.Xccy:
reference = {
"rate": checkPrice,
"spread": checkPrice,
"fxSpot": checkPrice,
}
elif helperType == HelperType.TenorBasis:
reference = {
"spread": checkPrice
}
elif helperType == HelperType.XccyBasis:
reference = {
"spread": checkPrice,
"fxSpot": checkPrice
}
elif helperType == HelperType.OIS:
reference = {
"spread": checkPrice
}
elif helperType == HelperType.Bond:
reference = {
"rate": checkPrice
}
else:
raise ConfigurationError('Invalid helper type')
try:
checkDictStructure(data, reference)
except Exception as exc:
raise ConfigurationError(
'Invalid market config') from exc
def checkRateHelper(data: dict, pos: int) -> None:
'''
Check if the rate helper is valid
Parameters
----------
data: dict
The rate helper
Returns
-------
None
Raises
------
RateHelperConfigurationError
If the rate helper is invalid
Details
-------
The rate helper should have the following example structure:
```
"rateHelper": {
"helperType": "OIS",
"helperConfig": {
...
},
"marketConfig": {
...
}
}
```
'''
reference = {
"helperType": partial(checkIsInEnum, enum=[r.value for r in HelperType]),
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise ConfigurationError(
'Invalid rate helper configuration or helper type at pos {}'.format(pos)) from exc
helperType = HelperType[data['helperType']]
reference["marketConfig"] = partial(
checkMarketConfig, helperType=helperType)
if helperType == HelperType.Deposit:
reference["helperConfig"] = checkDepositRateHelper
elif helperType == HelperType.Swap:
reference["helperConfig"] = checkSwapRateHelper
elif helperType == HelperType.FxSwap:
reference["helperConfig"] = checkFxSwapRateHelper
elif helperType == HelperType.Xccy:
reference["helperConfig"] = checkCrossCcyFixFloatSwapRateHelper
elif helperType == HelperType.TenorBasis:
reference["helperConfig"] = checkTenorBasisSwapRateHelper
elif helperType == HelperType.XccyBasis:
reference["helperConfig"] = checkCrossCcyBasisSwapRateHelper
elif helperType == HelperType.OIS:
reference["helperConfig"] = checkOISRateHelper
elif helperType == HelperType.Bond:
reference["helperConfig"] = checkFixedRateBondRateHelper
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateHelperConfigurationError(
'Invalid rate helper {} configuration at pos {}'.format(helperType, pos)) from exc
## Index checks ##
def checkIndex(data: dict) -> None:
'''
Check if the index is valid
Parameters
----------
data: dict
The index
Returns
-------
None
Raises
------
RateIndexError
If the index is invalid
Details
-------
The index should have the following example structure:
```
"curveIndex": {
"indexType": "IborIndex",
"tenor": "6M",
"dayCounter": "Actual360",
"currency": "CLP",
"fixingDays": 0,
"calendar": "NullCalendar",
"endOfMonth": False,
"convention": "Unadjusted"
}
```
'''
reference = {
"indexType": partial(checkIsInEnum, enum=IndexType.__members__),
"tenor": checkTenor,
"dayCounter": checkDayCounter,
"currency": checkCurrency,
"fixingDays": partial(checkInstance, type=int),
"calendar": checkCalendar,
"endOfMonth": partial(checkInstance, type=bool),
"convention": checkConvention
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise RateIndexError('Invalid index configuration') from exc
## Curve checks ##
def checkPiecewiseCurve(data: dict) -> None:
'''
Check if the piecewise curve is valid
Parameters
----------
data: dict
The piecewise curve
Returns
-------
None
Raises
------
InvalidCurve
If the curve is invalid
Details
-------
The piecewise curve should have the following example structure:
```
"example": {
"curveType": "Piecewise",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"rateHelpers": [
...
]
}
```
'''
def checkRateHelperList(l: list) -> None:
checkInstance(l, type=list)
if len(l) == 0:
raise ConfigurationError(
'Invalid piecewise curve configuration, rateHelpers should not be empty')
for pos, helper in enumerate(l):
checkRateHelper(helper, pos)
reference = {
"curveType": partial(checkIsInEnum, enum=[r.value for r in CurveType]),
"dayCounter": checkDayCounter,
"enableExtrapolation": partial(checkInstance, type=bool),
"rateHelpers": checkRateHelperList
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise ConfigurationError(
'Invalid piecewise curve configuration') from exc
def checkDiscountCurve(data: dict) -> None:
'''
Check if the discount curve is valid
Parameters
----------
data: dict
The discount curve
Returns
-------
None
Raises
------
InvalidCurve
If the curve is invalid
Details
-------
The discount curve should have the following example structure:
```
"example": {
"curveType": "Discount",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"nodes": [
{
"date": "2020-01-01",
"value": 0.99
}
]
}
```
'''
def checkNodeList(l: list) -> None:
ref = {
"date": checkDate,
"value": partial(checkInstance, type=float)
}
checkInstance(l, type=list)
if len(l) == 0:
raise ConfigurationError(
'Invalid discount curve configuration, discountFactors should not be empty')
for node in l:
checkDictStructure(node, ref)
reference = {
"curveType": partial(checkIsInEnum, enum=[r.value for r in CurveType]),
"dayCounter": checkDayCounter,
"enableExtrapolation": partial(checkInstance, type=bool),
"nodes": checkNodeList
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise ConfigurationError(
'Invalid discount curve configuration') from exc
def checkCurve(data: dict, pos: int) -> None:
'''
Check if the curve is valid
Parameters
----------
data: dict
The curve
Returns
-------
None
Raises
------
ConfigurationError
If the curve is invalid
Details
-------
The curve should have the following example structure:
```
"curve": {
"curveName": "CLP",
"curveConfig": {
"curveType": "Piecewise",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"rateHelpers": [] # if curveType is Piecewise, otherwise nodes
},
"curveIndex": {}
}
```
'''
def checkBaseCurve(dict: dict) -> None:
if "curveType" not in dict:
raise ConfigurationError(
'Invalid curve configuration, curveType should be defined')
if dict["curveType"] == CurveType.Piecewise.value:
checkPiecewiseCurve(dict)
elif dict["curveType"] == CurveType.Discount.value:
checkDiscountCurve(dict)
else:
raise ConfigurationError(
'Invalid curve configuration, curveType should be Piecewise or Discount')
reference = {
"curveName": partial(checkInstance, type=str),
"curveConfig": checkBaseCurve,
"curveIndex": checkIndex
}
try:
checkDictStructure(data, reference)
except ConfigurationError as exc:
raise ConfigurationError(
'Invalid curve configuration for {} curve'.format(data['curveName'])) from exc
except Exception as exc:
raise ConfigurationError('Invalid curve configuration at pos {}'.format(pos)) from exc
def checkConfiguration(data: dict) -> None:
'''
Check if the configuration is valid
Parameters
----------
data: dict
The configuration
Returns
-------
None
Raises
------
ConfigurationError
If the configuration is invalid
Details
-------
The configuration should have the following example structure:
```
"configuration": {
"refDate": "2020-01-01",
"curves": [
{
"curveName": "CLP",
"curveConfig": {
"curveType": "Piecewise",
"dayCounter": "Actual360",
"enableExtrapolation": True,
"rateHelpers": [
...
]
},
"curveIndex": {
...
}
}
]
}
}
```
'''
def checkCurveList(l: list) -> None:
checkInstance(l, type=list)
if len(l) == 0:
raise ConfigurationError(
'Invalid configuration, curves should not be empty')
for pos, curve in enumerate(l):
checkCurve(curve, pos)
reference = {
"refDate": checkDate,
"curves": checkCurveList
}
try:
checkDictStructure(data, reference)
except Exception as exc:
raise ConfigurationError('Invalid configuration') from exc
Functions
def checkCalendar(value) ‑> None
-
Check if the calendar is valid
Parameters
value
:str
- The calendar, matching the Calendar enum.
Returns
None
Raises
ValueError
- If the calendar is invalid
Also See
checkIsInEnum Calendar
Expand source code
def checkCalendar(value) -> None: ''' Check if the calendar is valid Parameters ---------- value: str The calendar, matching the Calendar enum. Returns ------- None Raises ------ ValueError If the calendar is invalid Also see -------- checkIsInEnum Calendar ''' checkIsInEnum(value, Calendar.__members__)
def checkCompounding(value) ‑> None
-
Check if the compounding is valid
Parameters
value
:str
- The compounding, matching the Compounding enum.
Returns
None
Raises
ValueError
- If the compounding is invalid
Also See
checkIsInEnum Compounding
Expand source code
def checkCompounding(value) -> None: ''' Check if the compounding is valid Parameters ---------- value: str The compounding, matching the Compounding enum. Returns ------- None Raises ------ ValueError If the compounding is invalid Also see -------- checkIsInEnum Compounding ''' checkIsInEnum(value, Compounding.__members__)
def checkConfiguration(data: dict) ‑> None
-
Check if the configuration is valid
Parameters
data
:dict
- The configuration
Returns
None
Raises
ConfigurationError
- If the configuration is invalid
Details
The configuration should have the following example structure:
"configuration": { "refDate": "2020-01-01", "curves": [ { "curveName": "CLP", "curveConfig": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [ ... ] }, "curveIndex": { ... } } ] } }
Expand source code
def checkConfiguration(data: dict) -> None: ''' Check if the configuration is valid Parameters ---------- data: dict The configuration Returns ------- None Raises ------ ConfigurationError If the configuration is invalid Details ------- The configuration should have the following example structure: ``` "configuration": { "refDate": "2020-01-01", "curves": [ { "curveName": "CLP", "curveConfig": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [ ... ] }, "curveIndex": { ... } } ] } } ``` ''' def checkCurveList(l: list) -> None: checkInstance(l, type=list) if len(l) == 0: raise ConfigurationError( 'Invalid configuration, curves should not be empty') for pos, curve in enumerate(l): checkCurve(curve, pos) reference = { "refDate": checkDate, "curves": checkCurveList } try: checkDictStructure(data, reference) except Exception as exc: raise ConfigurationError('Invalid configuration') from exc
def checkConvention(value) ‑> None
-
Check if the convention is valid
Parameters
value
:str
- The convention, matching the Convention enum.
Returns
None
Raises
ValueError
- If the convention is invalid
Also See
checkIsInEnum Convention
Expand source code
def checkConvention(value) -> None: ''' Check if the convention is valid Parameters ---------- value: str The convention, matching the Convention enum. Returns ------- None Raises ------ ValueError If the convention is invalid Also see -------- checkIsInEnum Convention ''' checkIsInEnum(value, Convention.__members__)
def checkCrossCcyBasisSwapRateHelper(data: dict) ‑> None
-
Check if the cross currency basis rate helper is valid
Parameters
data
:dict
- The cross currency basis rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The cross currency basis rate helper should have the following example structure:
"helperConfig": { "tenor": "3M", "calendar": "NullCalendar", "settlementDays": 2, "endOfMonth": False, "convention": "ModifiedFollowing", "flatIndex": "LIBOR3M", "spreadIndex": "LIBOR1M", "flatDiscountCurve": "SOFR", "spreadDiscountCurve": "CLP_COLLUSD", "flatIsDomestic": True }
Expand source code
def checkCrossCcyBasisSwapRateHelper(data: dict) -> None: ''' Check if the cross currency basis rate helper is valid Parameters ---------- data: dict The cross currency basis rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The cross currency basis rate helper should have the following example structure: ``` "helperConfig": { "tenor": "3M", "calendar": "NullCalendar", "settlementDays": 2, "endOfMonth": False, "convention": "ModifiedFollowing", "flatIndex": "LIBOR3M", "spreadIndex": "LIBOR1M", "flatDiscountCurve": "SOFR", "spreadDiscountCurve": "CLP_COLLUSD", "flatIsDomestic": True } ``` ''' reference = { "tenor": checkTenor, "calendar": checkCalendar, "settlementDays": partial(checkInstance, type=int), "endOfMonth": partial(checkInstance, type=bool), "convention": checkConvention, "flatIndex": partial(checkInstance, type=str), "spreadIndex": partial(checkInstance, type=str), "flatDiscountCurve": partial(checkInstance, type=str), "spreadDiscountCurve": partial(checkInstance, type=str), "flatIsDomestic": partial(checkInstance, type=bool) } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid cross currency basis rate helper') from exc
def checkCrossCcyFixFloatSwapRateHelper(data: dict) ‑> None
-
Check if the cross currency rate helper is valid
Parameters
data
:dict
- The cross currency rate helper
Returns
None
- no return, raise RateHelperConfigurationError if the request is invalid
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The cross currency rate helper should have the following example structure:
"helperConfig": { "tenor": "2Y", "dayCounter": "Actual360", "calendar": "NullCalendar", "convention": "ModifiedFollowing", "endOfMonth": False, "settlementDays": 2, "discountCurve": "CLP_COLLUSD", "index": "ICP", "fixedLegCurrency": "CLF", "fwdStart": "0D", "fixedLegFrequency": "Semiannual" }
Expand source code
def checkCrossCcyFixFloatSwapRateHelper(data: dict) -> None: ''' Check if the cross currency rate helper is valid Parameters ---------- data: dict The cross currency rate helper Returns ------- None no return, raise RateHelperConfigurationError if the request is invalid Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The cross currency rate helper should have the following example structure: ``` "helperConfig": { "tenor": "2Y", "dayCounter": "Actual360", "calendar": "NullCalendar", "convention": "ModifiedFollowing", "endOfMonth": False, "settlementDays": 2, "discountCurve": "CLP_COLLUSD", "index": "ICP", "fixedLegCurrency": "CLF", "fwdStart": "0D", "fixedLegFrequency": "Semiannual" } ``` ''' reference = { "tenor": checkTenor, "dayCounter": checkDayCounter, "calendar": checkCalendar, "convention": checkConvention, "endOfMonth": partial(checkInstance, type=bool), "settlementDays": partial(checkInstance, type=int), "discountCurve": partial(checkInstance, type=str), "index": partial(checkInstance, type=str), "fixedLegCurrency": partial(checkInstance, type=str), "fwdStart": checkTenor, "fixedLegFrequency": checkFrequency } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid cross currency rate helper') from exc
def checkCurrency(value) ‑> None
-
Check if the currency is valid
Parameters
value
:str
- The currency, matching the Currency enum.
Returns
None
Raises
ValueError
- If the currency is invalid
Also See
checkIsInEnum Currency
Expand source code
def checkCurrency(value) -> None: ''' Check if the currency is valid Parameters ---------- value: str The currency, matching the Currency enum. Returns ------- None Raises ------ ValueError If the currency is invalid Also see -------- checkIsInEnum Currency ''' checkIsInEnum(value, Currency.__members__)
def checkCurve(data: dict, pos: int) ‑> None
-
Check if the curve is valid
Parameters
data
:dict
- The curve
Returns
None
Raises
ConfigurationError
- If the curve is invalid
Details
The curve should have the following example structure:
"curve": { "curveName": "CLP", "curveConfig": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [] # if curveType is Piecewise, otherwise nodes }, "curveIndex": {} }
Expand source code
def checkCurve(data: dict, pos: int) -> None: ''' Check if the curve is valid Parameters ---------- data: dict The curve Returns ------- None Raises ------ ConfigurationError If the curve is invalid Details ------- The curve should have the following example structure: ``` "curve": { "curveName": "CLP", "curveConfig": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [] # if curveType is Piecewise, otherwise nodes }, "curveIndex": {} } ``` ''' def checkBaseCurve(dict: dict) -> None: if "curveType" not in dict: raise ConfigurationError( 'Invalid curve configuration, curveType should be defined') if dict["curveType"] == CurveType.Piecewise.value: checkPiecewiseCurve(dict) elif dict["curveType"] == CurveType.Discount.value: checkDiscountCurve(dict) else: raise ConfigurationError( 'Invalid curve configuration, curveType should be Piecewise or Discount') reference = { "curveName": partial(checkInstance, type=str), "curveConfig": checkBaseCurve, "curveIndex": checkIndex } try: checkDictStructure(data, reference) except ConfigurationError as exc: raise ConfigurationError( 'Invalid curve configuration for {} curve'.format(data['curveName'])) from exc except Exception as exc: raise ConfigurationError('Invalid curve configuration at pos {}'.format(pos)) from exc
def checkDate(value) ‑> None
-
Check if the date is valid
Parameters
value
:str
- The date
Returns
None
Raises
ValueError
- If the date is invalid
Expand source code
def checkDate(value) -> None: ''' Check if the date is valid Parameters ---------- value: str The date Returns ------- None Raises ------ ValueError If the date is invalid ''' if not re.match(r'^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,6})?(Z|[+-]\d{2}:\d{2})?)?$', value): raise ValueError(f'{value} is not a valid date or it does not follow the ISO format.')
def checkDateGenerationRule(value) ‑> None
-
Check if the date generation rule is valid
Parameters
value
:str
- The date generation rule, matching the DateGenerationRule enum.
Returns
None
Raises
ValueError
- If the date generation rule is invalid
Also See
checkIsInEnum DateGenerationRule
Expand source code
def checkDateGenerationRule(value) -> None: ''' Check if the date generation rule is valid Parameters ---------- value: str The date generation rule, matching the DateGenerationRule enum. Returns ------- None Raises ------ ValueError If the date generation rule is invalid Also see -------- checkIsInEnum DateGenerationRule ''' checkIsInEnum(value, DateGenerationRule.__members__)
def checkDayCounter(value) ‑> None
-
Check if the day counter is valid
Parameters
value
:str
- The day counter. It must match the DayCounter enum.
Returns
None
Raises
ValueError
- If the day counter is invalid
Also See
checkIsInEnum DayCounter
Expand source code
def checkDayCounter(value) -> None: ''' Check if the day counter is valid Parameters ---------- value: str The day counter. It must match the DayCounter enum. Returns ------- None Raises ------ ValueError If the day counter is invalid Also see -------- checkIsInEnum DayCounter ''' checkIsInEnum(value, DayCounter.__members__)
def checkDepositRateHelper(data: dict) ‑> None
-
Check if the deposit rate helper is valid
Parameters
data
:dict
- The deposit rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The deposit rate helper should have the following example structure:
"helperConfig": { "dayCounter": "Actual360", "tenor": "1D", "calendar": "NullCalendar", "settlementDays": 0, "endOfMonth": False, "convention": "Unadjusted" }
Expand source code
def checkDepositRateHelper(data: dict) -> None: ''' Check if the deposit rate helper is valid Parameters ---------- data: dict The deposit rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The deposit rate helper should have the following example structure: ``` "helperConfig": { "dayCounter": "Actual360", "tenor": "1D", "calendar": "NullCalendar", "settlementDays": 0, "endOfMonth": False, "convention": "Unadjusted" } ``` ''' reference = { "dayCounter": checkDayCounter, "tenor": checkTenor, "calendar": checkCalendar, "settlementDays": partial(checkInstance, type=int), "endOfMonth": partial(checkInstance, type=bool), "convention": checkConvention } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid deposit rate helper') from exc
def checkDictStructure(input: dict, reference: dict) ‑> None
-
Expand source code
def checkDictStructure(input: dict, reference: dict) -> None: for key in reference.keys(): if key not in input.keys(): raise KeyError( f'The required key "{key}" is missing.') for key in input.keys(): if key in reference.keys(): reference[key](input[key])
def checkDiscountCurve(data: dict) ‑> None
-
Check if the discount curve is valid
Parameters
data
:dict
- The discount curve
Returns
None
Raises
InvalidCurve
- If the curve is invalid
Details
The discount curve should have the following example structure:
"example": { "curveType": "Discount", "dayCounter": "Actual360", "enableExtrapolation": True, "nodes": [ { "date": "2020-01-01", "value": 0.99 } ] }
Expand source code
def checkDiscountCurve(data: dict) -> None: ''' Check if the discount curve is valid Parameters ---------- data: dict The discount curve Returns ------- None Raises ------ InvalidCurve If the curve is invalid Details ------- The discount curve should have the following example structure: ``` "example": { "curveType": "Discount", "dayCounter": "Actual360", "enableExtrapolation": True, "nodes": [ { "date": "2020-01-01", "value": 0.99 } ] } ``` ''' def checkNodeList(l: list) -> None: ref = { "date": checkDate, "value": partial(checkInstance, type=float) } checkInstance(l, type=list) if len(l) == 0: raise ConfigurationError( 'Invalid discount curve configuration, discountFactors should not be empty') for node in l: checkDictStructure(node, ref) reference = { "curveType": partial(checkIsInEnum, enum=[r.value for r in CurveType]), "dayCounter": checkDayCounter, "enableExtrapolation": partial(checkInstance, type=bool), "nodes": checkNodeList } try: checkDictStructure(data, reference) except Exception as exc: raise ConfigurationError( 'Invalid discount curve configuration') from exc
def checkFixedRateBondRateHelper(data: dict) ‑> None
-
Check if the bond rate helper is valid
Parameters
data
:dict
- The bond rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The bond rate helper should have the following example structure:
"helperConfig": { "calendar": "NullCalendar", "convention": "Following", "settlementDays": 2, "couponDayCounter": "Actual360", "couponRate": 0.05, "frequency": "Annual", "startDate": "2020-01-01", "endDate": "2022-01-01", "tenor": "2Y" # needed if start date and end date are not provided }
Expand source code
def checkFixedRateBondRateHelper(data: dict) -> None: ''' Check if the bond rate helper is valid Parameters ---------- data: dict The bond rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The bond rate helper should have the following example structure: ``` "helperConfig": { "calendar": "NullCalendar", "convention": "Following", "settlementDays": 2, "couponDayCounter": "Actual360", "couponRate": 0.05, "frequency": "Annual", "startDate": "2020-01-01", "endDate": "2022-01-01", "tenor": "2Y" # needed if start date and end date are not provided } ``` ''' reference = { "calendar": checkCalendar, "convention": checkConvention, "settlementDays": partial(checkInstance, type=int), "couponDayCounter": checkDayCounter, "couponRate": partial(checkInstance, type=float), "frequency": checkFrequency, } # check if the start date and end date are provided if "startDate" in data or "endDate" in data: reference["startDate"] = checkDate reference["endDate"] = checkDate else: reference["tenor"] = checkTenor try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError('Invalid bond rate helper') from exc
def checkFrequency(value) ‑> None
-
Check if the frequency is valid
Parameters
value
:str
- The frequency, matching the Frequency enum.
Returns
None
Raises
ValueError
- If the frequency is invalid
Also See
checkIsInEnum Frequency
Expand source code
def checkFrequency(value) -> None: ''' Check if the frequency is valid Parameters ---------- value: str The frequency, matching the Frequency enum. Returns ------- None Raises ------ ValueError If the frequency is invalid Also see -------- checkIsInEnum Frequency ''' checkIsInEnum(value, Frequency.__members__)
def checkFxSwapRateHelper(data: dict) ‑> None
-
Check if the FX swap rate helper is valid
Parameters
data
:dict
- The FX swap rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The FX swap rate helper should have the following example structure:
"helperConfig": { "calendar": "NullCalendar", "fixingDays": 0, "endOfMonth": False, "baseCurrencyAsCollateral": False, "convention": "Following", "discountCurve": "CLP_COLLUSD", "endDate": "2023-04-09", "tenor": "1Y", # need if no end date is provided "settlementDays": 0 }
Expand source code
def checkFxSwapRateHelper(data: dict) -> None: ''' Check if the FX swap rate helper is valid Parameters ---------- data: dict The FX swap rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The FX swap rate helper should have the following example structure: ``` "helperConfig": { "calendar": "NullCalendar", "fixingDays": 0, "endOfMonth": False, "baseCurrencyAsCollateral": False, "convention": "Following", "discountCurve": "CLP_COLLUSD", "endDate": "2023-04-09", "tenor": "1Y", # need if no end date is provided "settlementDays": 0 } ``` ''' reference = { "calendar": checkCalendar, "fixingDays": partial(checkInstance, type=int), "endOfMonth": partial(checkInstance, type=bool), "baseCurrencyAsCollateral": partial(checkInstance, type=bool), "convention": checkConvention, "discountCurve": partial(checkInstance, type=str), "settlementDays": partial(checkInstance, type=int) } # check if the end date is provided if "endDate" in data: reference["endDate"] = checkDate else: reference["tenor"] = checkTenor try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid FX swap rate helper') from exc
def checkIndex(data: dict) ‑> None
-
Check if the index is valid
Parameters
data
:dict
- The index
Returns
None
Raises
RateIndexError
- If the index is invalid
Details
The index should have the following example structure:
"curveIndex": { "indexType": "IborIndex", "tenor": "6M", "dayCounter": "Actual360", "currency": "CLP", "fixingDays": 0, "calendar": "NullCalendar", "endOfMonth": False, "convention": "Unadjusted" }
Expand source code
def checkIndex(data: dict) -> None: ''' Check if the index is valid Parameters ---------- data: dict The index Returns ------- None Raises ------ RateIndexError If the index is invalid Details ------- The index should have the following example structure: ``` "curveIndex": { "indexType": "IborIndex", "tenor": "6M", "dayCounter": "Actual360", "currency": "CLP", "fixingDays": 0, "calendar": "NullCalendar", "endOfMonth": False, "convention": "Unadjusted" } ``` ''' reference = { "indexType": partial(checkIsInEnum, enum=IndexType.__members__), "tenor": checkTenor, "dayCounter": checkDayCounter, "currency": checkCurrency, "fixingDays": partial(checkInstance, type=int), "calendar": checkCalendar, "endOfMonth": partial(checkInstance, type=bool), "convention": checkConvention } try: checkDictStructure(data, reference) except Exception as exc: raise RateIndexError('Invalid index configuration') from exc
def checkInstance(value:
, type: type) ‑> None -
Check if the value is an instance of the type
Parameters
value
:any
- The value to check
type
:type
- The type to check
Returns
None
Raises
ValueError
- If the value is not an instance of the type
Expand source code
def checkInstance(value: any, type: type) -> None: ''' Check if the value is an instance of the type Parameters ---------- value: any The value to check type: type The type to check Returns ------- None Raises ------ ValueError If the value is not an instance of the type ''' if not isinstance(value, type): raise ValueError(f'The value {value} is not an instance of {type}.')
def checkIsInEnum(value: str, enum: list) ‑> None
-
Check if the value is in the enum
Parameters
value
:str
- The value to check
enum
:list
- The enum
Returns
None
Raises
ValueError
- If the value is not in the enum
Expand source code
def checkIsInEnum(value: str, enum: list) -> None: ''' Check if the value is in the enum Parameters ---------- value: str The value to check enum: list The enum Returns ------- None Raises ------ ValueError If the value is not in the enum ''' if value not in enum: raise ValueError(f'{value} is not in {enum}')
def checkMarketConfig(data: dict, helperType: HelperType) ‑> None
-
Check if the market config is valid
Parameters
data
:dict
- The market config
Returns
None
Raises
ConfigurationError
- If the market config is invalid
Details
The market config should have the following example structure:
"marketConfig": { "rate": { "ticker" : "CLP_CU", "value" : 0.01 }, "spread": { "ticker" : "CLP_CU", "value" : 0.01 }, "fxSpot": { "ticker" : "CLP_CU", "value" : 0.01 }, "fxPoints": { "ticker" : "CLP_CU", "value" : 0.01 } }
Where each field has at least a value. The ticker is optional.
Each field is dependent on the helper type. The following table shows the required fields for each helper type:Helper type Required fields Deposit rate Swap rate, spread FxSwap fxSpot, fxPoints Xccy rate, spread, fxSpot TenorBasis spread XccyBasis spread, fxSpot OIS spread Bond rate Expand source code
def checkMarketConfig(data: dict, helperType: HelperType) -> None: ''' Check if the market config is valid Parameters ---------- data: dict The market config Returns ------- None Raises ------ ConfigurationError If the market config is invalid Details ------- The market config should have the following example structure: ``` "marketConfig": { "rate": { "ticker" : "CLP_CU", "value" : 0.01 }, "spread": { "ticker" : "CLP_CU", "value" : 0.01 }, "fxSpot": { "ticker" : "CLP_CU", "value" : 0.01 }, "fxPoints": { "ticker" : "CLP_CU", "value" : 0.01 } } ``` Where each field has at least a value. The ticker is optional. Each field is dependent on the helper type. The following table shows the required fields for each helper type: |Helper type | Required fields | |----------------------- | ---------------------------------| |Deposit | rate | |Swap | rate, spread | |FxSwap | fxSpot, fxPoints | |Xccy | rate, spread, fxSpot | |TenorBasis | spread | |XccyBasis | spread, fxSpot | |OIS | spread | |Bond | rate | ''' def checkPrice(data: dict) -> None: if not isinstance(data, dict): raise ConfigurationError( 'Invalid price, should be a dictionary') if 'value' not in data: raise ConfigurationError( 'Invalid price, missing value') if not isinstance(data['value'], float) and not isinstance(data['value'], int): raise ConfigurationError( 'Invalid price, value should be a float or int') if 'ticker' in data and not isinstance(data['ticker'], str): raise ConfigurationError( 'Invalid price, ticker should be a string') reference = {} if helperType == HelperType.Deposit: reference = { "rate": checkPrice } elif helperType == HelperType.Swap: reference = { "rate": checkPrice, "spread": checkPrice } elif helperType == HelperType.FxSwap: reference = { "fxSpot": checkPrice, "fxPoints": checkPrice } elif helperType == HelperType.Xccy: reference = { "rate": checkPrice, "spread": checkPrice, "fxSpot": checkPrice, } elif helperType == HelperType.TenorBasis: reference = { "spread": checkPrice } elif helperType == HelperType.XccyBasis: reference = { "spread": checkPrice, "fxSpot": checkPrice } elif helperType == HelperType.OIS: reference = { "spread": checkPrice } elif helperType == HelperType.Bond: reference = { "rate": checkPrice } else: raise ConfigurationError('Invalid helper type') try: checkDictStructure(data, reference) except Exception as exc: raise ConfigurationError( 'Invalid market config') from exc
def checkOISRateHelper(data: dict) ‑> None
-
Check if the OIS rate helper is valid
Parameters
data
:dict
- The OIS rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The OIS rate helper should have the following example structure:
"helperConfig": { "tenor": "1W", "dayCounter": "Actual360", "calendar": "NullCalendar", "convention": "Following", "endOfMonth": True, "frequency": "Annual", "settlementDays": 2, "paymentLag": 2, "telescopicValueDates": True, "index": "SOFR", "fixedLegFrequency": "Semiannual", "fwdStart": "0D", "discountCurve": "SOFR" }
Expand source code
def checkOISRateHelper(data: dict) -> None: ''' Check if the OIS rate helper is valid Parameters ---------- data: dict The OIS rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The OIS rate helper should have the following example structure: ``` "helperConfig": { "tenor": "1W", "dayCounter": "Actual360", "calendar": "NullCalendar", "convention": "Following", "endOfMonth": True, "frequency": "Annual", "settlementDays": 2, "paymentLag": 2, "telescopicValueDates": True, "index": "SOFR", "fixedLegFrequency": "Semiannual", "fwdStart": "0D", "discountCurve": "SOFR" } ``` ''' reference = { "tenor": checkTenor, "dayCounter": checkDayCounter, "calendar": checkCalendar, "convention": checkConvention, "endOfMonth": partial(checkInstance, type=bool), "frequency": checkFrequency, "settlementDays": partial(checkInstance, type=int), "paymentLag": partial(checkInstance, type=int), "telescopicValueDates": partial(checkInstance, type=bool), "index": partial(checkInstance, type=str), "fixedLegFrequency": checkFrequency, "fwdStart": checkTenor, "discountCurve": partial(checkInstance, type=str) } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError('Invalid OIS rate helper') from exc
def checkPiecewiseCurve(data: dict) ‑> None
-
Check if the piecewise curve is valid
Parameters
data
:dict
- The piecewise curve
Returns
None
Raises
InvalidCurve
- If the curve is invalid
Details
The piecewise curve should have the following example structure:
"example": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [ ... ] }
Expand source code
def checkPiecewiseCurve(data: dict) -> None: ''' Check if the piecewise curve is valid Parameters ---------- data: dict The piecewise curve Returns ------- None Raises ------ InvalidCurve If the curve is invalid Details ------- The piecewise curve should have the following example structure: ``` "example": { "curveType": "Piecewise", "dayCounter": "Actual360", "enableExtrapolation": True, "rateHelpers": [ ... ] } ``` ''' def checkRateHelperList(l: list) -> None: checkInstance(l, type=list) if len(l) == 0: raise ConfigurationError( 'Invalid piecewise curve configuration, rateHelpers should not be empty') for pos, helper in enumerate(l): checkRateHelper(helper, pos) reference = { "curveType": partial(checkIsInEnum, enum=[r.value for r in CurveType]), "dayCounter": checkDayCounter, "enableExtrapolation": partial(checkInstance, type=bool), "rateHelpers": checkRateHelperList } try: checkDictStructure(data, reference) except Exception as exc: raise ConfigurationError( 'Invalid piecewise curve configuration') from exc
def checkRateHelper(data: dict, pos: int) ‑> None
-
Check if the rate helper is valid
Parameters
data
:dict
- The rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The rate helper should have the following example structure:
"rateHelper": { "helperType": "OIS", "helperConfig": { ... }, "marketConfig": { ... } }
Expand source code
def checkRateHelper(data: dict, pos: int) -> None: ''' Check if the rate helper is valid Parameters ---------- data: dict The rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The rate helper should have the following example structure: ``` "rateHelper": { "helperType": "OIS", "helperConfig": { ... }, "marketConfig": { ... } } ``` ''' reference = { "helperType": partial(checkIsInEnum, enum=[r.value for r in HelperType]), } try: checkDictStructure(data, reference) except Exception as exc: raise ConfigurationError( 'Invalid rate helper configuration or helper type at pos {}'.format(pos)) from exc helperType = HelperType[data['helperType']] reference["marketConfig"] = partial( checkMarketConfig, helperType=helperType) if helperType == HelperType.Deposit: reference["helperConfig"] = checkDepositRateHelper elif helperType == HelperType.Swap: reference["helperConfig"] = checkSwapRateHelper elif helperType == HelperType.FxSwap: reference["helperConfig"] = checkFxSwapRateHelper elif helperType == HelperType.Xccy: reference["helperConfig"] = checkCrossCcyFixFloatSwapRateHelper elif helperType == HelperType.TenorBasis: reference["helperConfig"] = checkTenorBasisSwapRateHelper elif helperType == HelperType.XccyBasis: reference["helperConfig"] = checkCrossCcyBasisSwapRateHelper elif helperType == HelperType.OIS: reference["helperConfig"] = checkOISRateHelper elif helperType == HelperType.Bond: reference["helperConfig"] = checkFixedRateBondRateHelper try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid rate helper {} configuration at pos {}'.format(helperType, pos)) from exc
def checkSwapRateHelper(data: dict) ‑> None
-
Check if the swap rate helper is valid
Parameters
data
:dict
- The swap rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The swap rate helper should have the following example structure:
"helperConfig": { "tenor": "2Y", "dayCounter": "Thirty360", "calendar": "NullCalendar", "frequency": "Semiannual", "settlementDays": 2, "discountCurve": "SOFR", "index": "LIBOR3M", "endOfMonth": False, "convention": "Unadjusted", "fixedLegFrequency": "Semiannual", "fwdStart": "0D" }
Expand source code
def checkSwapRateHelper(data: dict) -> None: ''' Check if the swap rate helper is valid Parameters ---------- data: dict The swap rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The swap rate helper should have the following example structure: ``` "helperConfig": { "tenor": "2Y", "dayCounter": "Thirty360", "calendar": "NullCalendar", "frequency": "Semiannual", "settlementDays": 2, "discountCurve": "SOFR", "index": "LIBOR3M", "endOfMonth": False, "convention": "Unadjusted", "fixedLegFrequency": "Semiannual", "fwdStart": "0D" } ``` ''' reference = { "tenor": checkTenor, "dayCounter": checkDayCounter, "calendar": checkCalendar, "frequency": checkFrequency, "settlementDays": partial(checkInstance, type=int), "discountCurve": partial(checkInstance, type=str), "index": partial(checkInstance, type=str), "endOfMonth": partial(checkInstance, type=bool), "convention": checkConvention, "fixedLegFrequency": checkFrequency, "fwdStart": checkTenor } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError('Invalid swap rate helper') from exc
def checkTenor(tenor: str) ‑> None
-
Check if the tenor is valid
Parameters
tenor
:str
- The tenor, it can be a number followed by D, W, M or Y
Returns
None
Raises
ConfigurationError
- If the tenor is invalid
Expand source code
def checkTenor(tenor: str) -> None: ''' Check if the tenor is valid Parameters ---------- tenor: str The tenor, it can be a number followed by D, W, M or Y Returns ------- None Raises ------ ConfigurationError If the tenor is invalid ''' regex = r'^(\d+[DWMY])+$' if not re.match(regex, tenor): raise ValueError(f'The tenor {tenor} is invalid')
def checkTenorBasisSwapRateHelper(data: dict) ‑> None
-
Check if the tenor basis rate helper is valid
Parameters
data
:dict
- The tenor basis rate helper
Returns
None
Raises
RateHelperConfigurationError
- If the rate helper is invalid
Details
The tenor basis rate helper should have the following example structure:
"helperConfig": { "tenor": "3M", "longIndex": "LIBOR3M", "shortIndex": "LIBOR1M", "discountCurve": "SOFR", "spreadOnShort": True }
Expand source code
def checkTenorBasisSwapRateHelper(data: dict) -> None: ''' Check if the tenor basis rate helper is valid Parameters ---------- data: dict The tenor basis rate helper Returns ------- None Raises ------ RateHelperConfigurationError If the rate helper is invalid Details ------- The tenor basis rate helper should have the following example structure: ``` "helperConfig": { "tenor": "3M", "longIndex": "LIBOR3M", "shortIndex": "LIBOR1M", "discountCurve": "SOFR", "spreadOnShort": True } ``` ''' reference = { "tenor": checkTenor, "longIndex": partial(checkInstance, type=str), "shortIndex": partial(checkInstance, type=str), "discountCurve": partial(checkInstance, type=str), "spreadOnShort": partial(checkInstance, type=bool) } try: checkDictStructure(data, reference) except Exception as exc: raise RateHelperConfigurationError( 'Invalid tenor basis rate helper') from exc
Classes
class ConfigurationError (message)
-
Exception raised when the request is invalid
Expand source code
class ConfigurationError(Exception): ''' Exception raised when the request is invalid ''' def __init__(self, message): self.message = message
Ancestors
- builtins.Exception
- builtins.BaseException
Subclasses
class MarketConfigurationError (message)
-
Exception raised when the market configuration is invalid
Expand source code
class MarketConfigurationError(ConfigurationError): ''' Exception raised when the market configuration is invalid ''' def __init__(self, message): self.message = message
Ancestors
- ConfigurationError
- builtins.Exception
- builtins.BaseException
class RateHelperConfigurationError (message)
-
Exception raised when the rate helper is invalid
Expand source code
class RateHelperConfigurationError(ConfigurationError): ''' Exception raised when the rate helper is invalid ''' def __init__(self, message): self.message = message
Ancestors
- ConfigurationError
- builtins.Exception
- builtins.BaseException
class RateIndexError (message)
-
Exception raised when the index is invalid
Expand source code
class RateIndexError(ConfigurationError): ''' Exception raised when the index is invalid ''' def __init__(self, message): self.message = message
Ancestors
- ConfigurationError
- builtins.Exception
- builtins.BaseException