QPS Financial Contracts API - Structured Products error message: Invalid Correlation Data.

Harry.Nan
Harry.Nan LSEG
edited December 2024 in Refinitiv Data Platform

Hello team,

I keep getting the following error message while pricing structured products using QPS financial contracts API:

'Cannot price Structured Products. Invalid correlation data.'

It seems that when there are more than one Equity underliers the error would be triggered. I have priced similar products with single equity underlier with no issues.

Request body below.

{
"fields": [
"MarketValueInDealCcy",
"ErrorMessage"
],
"universe": [
{
"instrumentDefinition": {
"instrumentTag": "63873HEZ3",
"dealCcy": "USD",
"inputs": [
{
"type": "string",
"name": "CUSIP",
"value": "63873HEZ3"
},
{
"type": "string",
"name": "Issuer",
"value": "MS"
},
{
"type": "string",
"name": "Callable",
"value": "True"
},
{
"type": "string",
"name": "PrincipalAtRisk",
"value": "True"
},
{
"type": "string",
"name": "RangeAccrualType",
"value": "A"
},
{
"type": "string",
"name": "SOFR",
"value": "False"
},
{
"type": "string",
"name": "NumOfAssets",
"value": "2"
},
{
"type": "date",
"name": "TradeDate",
"value": "28/03/2016"
},
{
"type": "date",
"name": "ValuationDate",
"value": "26/03/2036"
},
{
"type": "date",
"name": "MaturityDate",
"value": "31/03/2036"
},
{
"type": "date",
"name": "StartDate",
"value": "31/03/2016"
},
{
"type": "date",
"name": "EndDate",
"value": "31/03/2036"
},
{
"type": "date",
"name": "RangeStart",
"value": "31/03/2020"
},
{
"type": "date",
"name": "RangeStart_2",
"value": "31/03/2026"
},
{
"type": "date",
"name": "CallStart",
"value": "31/03/2017"
},
{
"type": "date",
"name": "CallEnd",
"value": "31/03/2036"
},
{
"type": "string",
"name": "CMS_Long",
"value": "30Y"
},
{
"type": "string",
"name": "CMS_Short",
"value": "2Y"
},
{
"type": "string",
"name": "CpnB",
"value": "0.65"
},
{
"type": "string",
"name": "Trigger",
"value": "0.5"
},
{
"type": "string",
"name": "FixedCpn",
"value": "0.09"
},
{
"type": "string",
"name": "Cap",
"value": "0.1"
},
{
"type": "string",
"name": "Notional",
"value": "100"
},
{
"type": "string",
"name": "PayFreq",
"value": "M"
},
{
"type": "string",
"name": "CallFreq",
"value": "Q"
},
{
"type": "string",
"name": "CallGap",
"value": "-5B"
},
{
"type": "string",
"name": "ResetGap",
"value": "-2B"
},
{
"type": "string",
"name": "PayGap",
"value": "0B"
},
{
"type": "string",
"name": "DateRule",
"value": "ModifiedFollowing"
},
{
"type": "string",
"name": "Calendar",
"value": "NYSE"
},
{
"type": "string",
"name": "DayCount",
"value": "Act/Act"
},
{
"type": "string",
"name": "A_1",
"value": "SP500"
},
{
"type": "string",
"name": "A_2",
"value": "RUT"
},
{
"type": "string",
"name": "Initial_1",
"value": "2037.05"
},
{
"type": "string",
"name": "Initial_2",
"value": "1093.6"
},
{
"type": "string",
"name": "ResetArrear",
"value": "False"
},
{
"type": "string",
"name": "Leverage_Steps",
"value": "2"
},
{
"type": "string",
"name": "Leverage",
"value": "8.0"
},
{
"type": "string",
"name": "Leverage_2",
"value": "10.0"
},
{
"type": "string",
"name": "Spread",
"value": "0.0"
}
],
"payoffDescription": [
[
"Schedule type",
"Schedule description",
"Spot_1",
"Spot_2",
"WorstPerform",
"CMS_Spread",
"nday",
"Actday",
"Cpn",
"Redemption",
"Price"
],
[
"AtDate",
"TradeDate",
"Initial_1",
"Initial_2",
"",
"",
"$n=0",
"$act=0",
"",
"",
""
],
[
"AllTheTime",
"FromTo(RangeStart,MaturityDate,1b)",
"EqSpot(A_1)",
"EqSpot(A_2)",
"MIN(Spot_1[t]/Spot_1[1],Spot_2[t]/Spot_2[1])",
"",
"$n=$n+IF(WorstPerform[t]>=CpnB,1,0)",
"$act=$act+1",
"",
"",
""
],
[
"OnSchedule",
"DateTable(StartDate,RangeStart,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=ResetGap,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
"",
"",
"",
"",
"",
"",
"FixedCpn*InterestTerm()",
"",
"Receive Notional*Cpn[t]"
],
[
"OnSchedule",
"DateTable(StartDate,EndDate,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=ResetGap,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
"",
"",
"",
"Max(0,SwapRate(USD,EventDate(),CMS_Long)-SwapRate(USD,EventDate(),CMS_Short)+Spread)",
"",
"",
"",
"",
""
],
[
"OnSchedule",
"DateTable(RangeStart,RangeStart_2,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=0B,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
"",
"",
"",
"",
"",
"",
"$n/$act*Min(Cap,Leverage*IF(\"ResetArrear\"==\"False\",CMS_Spread[LastDate(-1)],CMS_Spread[LastDate]))*InterestTerm()",
"",
"Receive Notional*Cpn[t];$n=0;$act=0"
],
[
"OnSchedule",
"DateTable(RangeStart_2,EndDate,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=0B,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
"",
"",
"",
"",
"",
"",
"$n/$act*Min(Cap,Leverage_2*IF(\"ResetArrear\"==\"False\",CMS_Spread[LastDate(-1)],CMS_Spread[LastDate]))*InterestTerm()",
"",
"Receive Notional*Cpn[t];$n=0;$act=0"
],
[
"OnSchedule",
"DateTable(CallStart,CallEnd,CallFreq,DayCount,PayGap:=PayGap,ResetGap:=CallGap,Arrear:=False,DateRule:=DateRule,Calendar:=Calendar)",
"",
"",
"",
"",
"",
"",
"",
"",
"CallableBy(Them,Notional)"
],
[
"AtDate",
"ValuationDate",
"EqSpot(A_1)",
"EqSpot(A_2)",
"MIN(Spot_1[t]/Spot_1[1],Spot_2[t]/Spot_2[1])",
"",
"",
"",
"",
"IF(WorstPerform[t]>=Trigger,1,WorstPerform[t])",
"Receive(MaturityDate,Notional*Redemption[t])"
]
]
},
"pricingParameters": {
"models": [
{
"underlyingCode": "USD",
"underlyingName": "USD",
"underlyingCurrency": "USD",
"assetClass": "InterestRate",
"modelName": "HullWhite1Factor",
"modelParameters": {
"volatilityTermStructure": [
{
"value": 1.0,
"unit": "Percent"
}
],
"meanReversionTermStructure": [
{
"value": 1.0,
"unit": "Percent"
}
],
"volatilityModel": "NormalVolatility"
}
},
{
"underlyingCode": ".RUT",
"underlyingName": "RUT",
"underlyingCurrency": "USD",
"assetClass": "Equity",
"modelName": "Dupire"
},
{
"underlyingCode": ".SPX",
"underlyingName": "SP500",
"underlyingCurrency": "USD",
"assetClass": "Equity",
"modelName": "Dupire"
}
],
"numericalMethod": {
"allTheTimePointsPerYear": 260,
"method": "AmericanMonteCarlo",
"additionalPoints": 12,
"simulationCount": 1000
},
"fundingSpreadInBp": 0,
"forceDecreasingDiscountFactor": false,
"includeCashFlowsAtValuationDate": false,
"correlationReferenceCoefficientPercent": -100,
"correlationMultiplier": 1,
"numeraireType": "Cash",
"useBasisSwap": false,
"valuationDate": "2022-09-01"
},
"instrumentType": "StructuredProduct"
}
]

}

Answers

  • Hi @Harry.Nan

    I had simillar issues in the past, and wrote this article as a result:

    Troubleshooting IPA & RD Python Library: https://developers.lseg.com/en/article-catalog/article/troubleshooting-ipa-and-the-data-library-api-in-python


    The way I found the culprit in my body was through trial and error. I would suggest the same here. I wrote about just this at the end of the article:



     

    I recently came uppon a second error returned from IPA, ''ErrorMessage" `Unable to calculate the Implied Volatility` and "ErrorCode" `QPS-Pricer.4011`.

    I went through the technique above, and found the folowing test call totry out on the API Playground:

     

    {

      "universe": [

        {

          "instrumentType": "Option",

          "instrumentDefinition": {

            "buySell": "Buy",

            "callPut": "Call",

            "underlyingType": "Eti",

            "instrumentCode": "STXE45500N4.EX",

            "strike": 4550

          },

          "pricingParameters": {

            "pricingModelType": "BlackScholes",

            "underlyingTimeStamp": "Default",

            "volatilityType": "Implied",

            "marketValueInDealCcy": 4534.61,

            "reportCcy": "EUR",

            "riskFreeRatePercent": 3.938,

            "underlyingPrice": 4534.61,

            "valuationDate": "2023-12-18T11:10:00Z"

          }

        }

      ],

      "fields": [

        "ErrorMessage",

        "ErrorCode",

        "MarketValueInDealCcy",

        "RiskFreeRatePercent",

        "UnderlyingPrice",

        "Volatility",

        "DeltaPercent",

        "GammaPercent",

        "RhoPercent",

        "ThetaPercent",

        "VegaPercent"

      ]

    }

     What I then did, on the Playground, was remove one (and only one) argument. I found out, through this trial and error proccess that the the culprit was "marketValueInDealCcy".

    apitroubleshoot.PNG

     

    Removing this argument showed that this option was trading at a much lower rate, making Greeks imposible to calculate.

    Please do let me know if you did not find the culprit argument in the body after going through the above.

  • Hi Jonathan, thank you for your reply. I've tried everything I could. Is there a way to get a more detailed error message/log so I can figure out what failed during the pricing process?

    The following request with almost the same structure works, only difference being that it only has one equity index underliers rather than two in the original one I posted. I am struggling to understand what triggers the specific 'Invalid Correlation Data' error.

    {
    "fields": [
    "MarketValueInDealCcy",
    "ErrorMessage"
    ],
    "universe": [
    {
    "instrumentDefinition": {
    "instrumentTag": "1730T02P3",
    "dealCcy": "USD",
    "inputs": [
    {
    "type": "string",
    "name": "CUSIP",
    "value": "1730T02P3"
    },
    {
    "type": "string",
    "name": "Issuer",
    "value": "C"
    },
    {
    "type": "string",
    "name": "Callable",
    "value": "True"
    },
    {
    "type": "string",
    "name": "PrincipalAtRisk",
    "value": "False"
    },
    {
    "type": "string",
    "name": "RangeAccrualType",
    "value": "A"
    },
    {
    "type": "string",
    "name": "SOFR",
    "value": "False"
    },
    {
    "type": "string",
    "name": "NumOfAssets",
    "value": "1"
    },
    {
    "type": "date",
    "name": "TradeDate",
    "value": "28/10/2014"
    },
    {
    "type": "date",
    "name": "ValuationDate",
    "value": "31/10/2034"
    },
    {
    "type": "date",
    "name": "MaturityDate",
    "value": "31/10/2034"
    },
    {
    "type": "date",
    "name": "StartDate",
    "value": "31/10/2014"
    },
    {
    "type": "date",
    "name": "EndDate",
    "value": "31/10/2034"
    },
    {
    "type": "date",
    "name": "RangeStart",
    "value": "31/10/2015"
    },
    {
    "type": "date",
    "name": "CallStart",
    "value": "31/10/2015"
    },
    {
    "type": "date",
    "name": "CallEnd",
    "value": "31/10/2034"
    },
    {
    "type": "string",
    "name": "CMS_Long",
    "value": "30Y"
    },
    {
    "type": "string",
    "name": "CMS_Short",
    "value": "2Y"
    },
    {
    "type": "string",
    "name": "CpnB",
    "value": "0.7"
    },
    {
    "type": "string",
    "name": "FixedCpn",
    "value": "0.09"
    },
    {
    "type": "string",
    "name": "Cap",
    "value": "0.1"
    },
    {
    "type": "string",
    "name": "Notional",
    "value": "100"
    },
    {
    "type": "string",
    "name": "PayFreq",
    "value": "Q"
    },
    {
    "type": "string",
    "name": "CallFreq",
    "value": "Q"
    },
    {
    "type": "string",
    "name": "CallGap",
    "value": "-5B"
    },
    {
    "type": "string",
    "name": "ResetGap",
    "value": "-2B"
    },
    {
    "type": "string",
    "name": "PayGap",
    "value": "0B"
    },
    {
    "type": "string",
    "name": "DateRule",
    "value": "ModifiedFollowing"
    },
    {
    "type": "string",
    "name": "Calendar",
    "value": "NYSE"
    },
    {
    "type": "string",
    "name": "DayCount",
    "value": "30/360"
    },
    {
    "type": "string",
    "name": "A_1",
    "value": "SP500"
    },
    {
    "type": "string",
    "name": "Initial_1",
    "value": "1985.05"
    },
    {
    "type": "string",
    "name": "ResetArrear",
    "value": "False"
    },
    {
    "type": "string",
    "name": "Leverage_Steps",
    "value": "1"
    },
    {
    "type": "string",
    "name": "Leverage",
    "value": "4.0"
    },
    {
    "type": "string",
    "name": "Spread",
    "value": "0.0"
    }
    ],
    "payoffDescription": [
    [
    "Schedule type",
    "Schedule description",
    "Spot_1",
    "WorstPerform",
    "CMS_Spread",
    "nday",
    "Actday",
    "Cpn",
    "Redemption",
    "Price"
    ],
    [
    "AtDate",
    "TradeDate",
    "Initial_1",
    "",
    "",
    "$n=0",
    "$act=0",
    "",
    "",
    ""
    ],
    [
    "AllTheTime",
    "FromTo(RangeStart,MaturityDate,1b)",
    "EqSpot(A_1)",
    "Spot_1[t]/Spot_1[1]",
    "",
    "$n=$n+IF(WorstPerform[t]>=CpnB,1,0)",
    "$act=$act+1",
    "",
    "",
    ""
    ],
    [
    "OnSchedule",
    "DateTable(StartDate,RangeStart,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=ResetGap,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
    "",
    "",
    "",
    "",
    "",
    "FixedCpn*InterestTerm()",
    "",
    "Receive Notional*Cpn[t]"
    ],
    [
    "OnSchedule",
    "DateTable(StartDate,EndDate,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=ResetGap,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
    "",
    "",
    "Max(0,SwapRate(USD,EventDate(),CMS_Long)-SwapRate(USD,EventDate(),CMS_Short)+Spread)",
    "",
    "",
    "",
    "",
    ""
    ],
    [
    "OnSchedule",
    "DateTable(RangeStart,EndDate,PayFreq,DayCount,PayGap:=PayGap,ResetGap:=0B,Arrear:=Yes,DateRule:=DateRule,Calendar:=Calendar)",
    "",
    "",
    "",
    "",
    "",
    "$n/$act*Min(Cap,Leverage*IF(\"ResetArrear\"==\"False\",CMS_Spread[LastDate(-1)],CMS_Spread[LastDate]))*InterestTerm()",
    "",
    "Receive Notional*Cpn[t];$n=0;$act=0"
    ],
    [
    "OnSchedule",
    "DateTable(CallStart,CallEnd,CallFreq,DayCount,PayGap:=PayGap,ResetGap:=CallGap,Arrear:=False,DateRule:=DateRule,Calendar:=Calendar)",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "CallableBy(Them,Notional)"
    ],
    [
    "AtDate",
    "ValuationDate",
    "EqSpot(A_1)",
    "Spot_1[t]/Spot_1[1]",
    "",
    "",
    "",
    "",
    "1",
    "Receive(MaturityDate,Notional*Redemption[t])"
    ]
    ]
    },
    "pricingParameters": {
    "models": [
    {
    "underlyingCode": "USD",
    "underlyingName": "USD",
    "underlyingCurrency": "USD",
    "assetClass": "InterestRate",
    "modelName": "HullWhite1Factor",
    "modelParameters": {
    "volatilityTermStructure": [
    {
    "value": 1.0,
    "unit": "Percent"
    }
    ],
    "meanReversionTermStructure": [
    {
    "value": 1.0,
    "unit": "Percent"
    }
    ],
    "volatilityModel": "NormalVolatility"
    }
    },
    {
    "underlyingCode": ".SPX",
    "underlyingName": "SP500",
    "underlyingCurrency": "USD",
    "assetClass": "Equity",
    "modelName": "Dupire"
    }
    ],
    "numericalMethod": {
    "allTheTimePointsPerYear": 260,
    "method": "AmericanMonteCarlo",
    "additionalPoints": 12,
    "simulationCount": 1000
    },
    "fundingSpreadInBp": 0,
    "forceDecreasingDiscountFactor": false,
    "includeCashFlowsAtValuationDate": false,
    "correlationReferenceCoefficientPercent": -100,
    "correlationMultiplier": 0.995,
    "numeraireType": "Cash",
    "useBasisSwap": false,
    "valuationDate": "2022-09-01"
    },
    "instrumentType": "StructuredProduct"
    }
    ]
    }
  • Hi @Harry.Nan

    Thank you for your reply. I have let the internal IPA team know of this and kept you in the email exchange on this matter. They are investigating the issue and will get back as soon as there is news.