@@ -883,13 +883,19 @@ void ParSensitivityAnalysis::computeParInstrumentSensitivities(const boost::shar
883883
884884 // process par helpers
885885
886+ std::set<RiskFactorKey::KeyType> survivalAndRateCurveTypes = {
887+ RiskFactorKey::KeyType::SurvivalProbability, RiskFactorKey::KeyType::DiscountCurve,
888+ RiskFactorKey::KeyType::YieldCurve, RiskFactorKey::KeyType::IndexCurve};
889+
886890 for (auto const & p : parHelpers_) {
887891
888892 // skip if par helper has no sensi to zero risk factor (except the special treatment below kicks in)
889893
890894 if (p.second ->isCalculated () &&
891- (p.first .keytype != RiskFactorKey::KeyType::SurvivalProbability || p.first != desc[i].key1 ()))
895+ (survivalAndRateCurveTypes.find (p.first .keytype ) == survivalAndRateCurveTypes.end () ||
896+ p.first != desc[i].key1 ())) {
892897 continue ;
898+ }
893899
894900 // compute fair and base quotes
895901
@@ -901,14 +907,14 @@ void ParSensitivityAnalysis::computeParInstrumentSensitivities(const boost::shar
901907
902908 // special treatments for certain risk factors
903909
904- // for curves with survival probabilities going to zero quickly we might see a sensitivity
905- // that is close to zero, which we sanitise here in order to prevent the Jacobi matrix
910+ // for curves with survival probabilities / discount factors going to zero quickly we might see a
911+ // sensitivity that is close to zero, which we sanitise here in order to prevent the Jacobi matrix
906912 // getting ill-conditioned or even singular
907913
908- if (p.first .keytype == RiskFactorKey::KeyType::SurvivalProbability && p. first == desc[i]. key1 () &&
909- std::abs (tmp) < 0.01 ) {
910- WLOG (" Setting Diagonal Default Curve Sensi " << p.first << " w.r.t. " << desc[i].key1 ()
911- << " to 0.01 (got " << tmp << " )" );
914+ if (survivalAndRateCurveTypes. find ( p.first .keytype ) != survivalAndRateCurveTypes. end () &&
915+ p. first == desc[i]. key1 () && std::abs (tmp) < 0.01 ) {
916+ WLOG (" Setting Diagonal Sensi " << p.first << " w.r.t. " << desc[i].key1 () << " to 0.01 (got " << tmp
917+ << " )" );
912918 tmp = 0.01 ;
913919 }
914920
@@ -1006,16 +1012,35 @@ void ParSensitivityAnalysis::computeParInstrumentSensitivities(const boost::shar
10061012 std::inserter (parKeysZero, parKeysZero.begin ()));
10071013 std::set_difference (rawKeysCheck.begin (), rawKeysCheck.end (), rawKeysNonZero.begin (), rawKeysNonZero.end (),
10081014 std::inserter (rawKeysZero, rawKeysZero.begin ()));
1009- for (auto const & k : parKeysZero) {
1010- WLOG (" Found par instrument which has no sensitivity to any of the risk factors: \" " << k << " \" " );
1011- }
1012- for (auto const & k : rawKeysZero) {
1013- WLOG (" Found risk factor w.r.t. which no par instrument has a sensitivity: \" " << k << " \" " );
1015+ std::set<RiskFactorKey> problematicKeys;
1016+ problematicKeys.insert (parKeysZero.begin (), parKeysZero.end ());
1017+ problematicKeys.insert (rawKeysZero.begin (), rawKeysZero.end ());
1018+ for (auto const & k : problematicKeys) {
1019+ std::string type;
1020+ if (parKeysZero.find (k) != parKeysZero.end ())
1021+ type = " par instrument is insensitive to all zero risk factors" ;
1022+ else if (rawKeysZero.find (k) != rawKeysZero.end ())
1023+ type = " zero risk factor that does not affect an par instrument" ;
1024+ else
1025+ type = " unknown" ;
1026+ Real parHelperValue = Null<Real>();
1027+ if (auto tmp = parHelpers_.find (k); tmp != parHelpers_.end ())
1028+ parHelperValue = impliedQuote (tmp->second );
1029+ else if (auto tmp = parCaps_.find (k); tmp != parCaps_.end ())
1030+ parHelperValue = tmp->second ->NPV ();
1031+ else if (auto tmp = parYoYCaps_.find (k); tmp != parYoYCaps_.end ())
1032+ parHelperValue = tmp->second ->NPV ();
1033+ Real zeroFactorValue = Null<Real>();
1034+ if (simMarket->baseScenarioAbsolute ()->has (k))
1035+ zeroFactorValue = simMarket->baseScenarioAbsolute ()->get (k);
1036+ WLOG (" zero/par relation problem for key '"
1037+ << k << " ', type " + type + " , par value = "
1038+ << (parHelperValue == Null<Real>() ? " na" : std::to_string (parHelperValue))
1039+ << " , zero value = " << (zeroFactorValue == Null<Real>() ? " na" : std::to_string (zeroFactorValue)));
10141040 }
10151041
10161042 LOG (" Computing par rate and flat vol sensitivities done" );
1017-
1018- } // namespace sensitivity
1043+ } // compute par instrument sensis
10191044
10201045void ParSensitivityAnalysis::alignPillars () {
10211046 LOG (" Align simulation market pillars to actual latest relevant dates of par instruments" );
0 commit comments