model_clo_insight.engines.solvers module

Module which contains the core optimization methods for the hypo pool generation

monitor_metric(riskscore_max, run_mode, shell_pool, wal, coef_sdr, risk_score_tbl, IDT_sp, WARF_sp, force_high, force_low)

Computes the 2 metrics used in the CDO Monitor computation

  • BDR: Break Even Default Rate

  • SDR: Scenario Default Rate (analagous to the DBRSM CLO Asset Model hurdle rate output)

Parameters
  • riskscore_max (float) – max DBRSM risk score of the pool

  • run_mode (str) – Expected portfolio default rate (EPDR) or WA Rating Factor (SP_WARF)

  • shell_pool (list[clo_internal_objects.Obligor]) – pool where obligor & industry percentages have been previously solved for a given Dscore

  • wal (float) – Target portfolio weighted average life

  • coef_sdr (list) – Scenario even default rate (SDR) coefficients for the transaction

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • IDT_sp (ndarray) – idealized default 2-D table; sourced from transaction documents

  • WARF_sp (ndarray) – WARF-equivalent 1-D table; sourced from transaction documents

  • force_high (tuple) – (rating_number, pct) for higher rtg prior to solving for risk score, force this on pool

  • force_low (tuple) – (rating_number, pct) for lower rtg prior to solving for risk score, force this on pool

Returns

Monitor SDR, SDR diagnostics dictionary

Return type

tuple

monitor_objective_function(riskscore_max, run_mode, target_sdr, shell_pool, wal, coef_sdr, risk_score_tbl, IDT_sp, WARF_sp, force_high, force_low)

Used as the objective funtion in the optimizers

Parameters
  • riskscore_max (float) – max DBRSM risk score of the pool; this is what gets iterated over when monitor_objective_function is hooked up to the optimizer

  • target_sdr (float) – target Monitor SDR metric that the optimizer attempts to reach by iterating over the

  • shell_pool (list[clo_internal_objects.Obligor]) – pool where obligor & industry percentages have been previously solved for a given Dscore

  • wal (float) – Target portfolio weighted average life

  • coef_sdr (list) – Scenario even default rate (SDR) coefficients for the transaction

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • IDT_sp (ndarray) – idealized default 2-D table; sourced from transaction documents

  • WARF_sp (ndarray) – WARF-equivalent 1-D table; sourced from transaction documents

  • force_high (tuple) – (rating_number, pct) for higher rtg prior to solving for risk score, force this on pool

  • force_low (tuple) – (rating_number, pct) for lower rtg prior to solving for risk score, force this on pool

Returns

difference between the actual dscore and the target, solver attempts to minimize this

Return type

float

monitor_pool(riskscore_max, shell_pool, wal, risk_score_tbl, IDT_sp, force_high, force_low, is_compute_pd=True)

Applies rating mixture to pool based on riskcore_max, then PD based on lookup tables. Need this to compute expected PD and PD dispersion metrics for the monitor calculation

Parameters
  • riskscore_max (float) – max DBRSM risk score of the pool

  • shell_pool (list[clo_internal_objects.Obligor]) – pool where obligor & industry percentages have been previously solved for a given Dscore

  • wal (float) – Target portfolio weighted average life

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • IDT_sp (ndarray) – idealized default 2-D table; sourced from transaction documents

  • force_high (tuple) – (rating_number, pct) for higher rtg prior to solving for risk score, force this on pool

  • force_low (tuple) – (rating_number, pct) for lower rtg prior to solving for risk score, force this on pool

  • is_compute_pd (bool) – if True, compute the PD for each obligor via IDT lookup

Returns

hypo pool w/ PD overlay

Return type

list

solve_dscore_ob_base(dscore_min, ob_base, ind_base, riskscore_max, ob_exceptions, ind_exceptions, ob_floor, ind_floor, risk_score_tbl, tables, force_high, force_low, is_simple_industry, n_simple_industry)

Solver for a pool based on dscore.

Solves for a pool dscore by forcing ob & ind conc limit exceptions, spinning down the base ob & ind exceptions until the dscore is in compliance. Should not be run directly, but from hypo_pool_master etc.

General Algorithm 1) Construct initial pool using build_pool and calculate dscore 2) If actual dscore > dscore limit, pool is compliant so no need to solve 3) Check lower bound ob base ob/ind max to ensure the solver can find a solution 4) Run numpy’s bisection algo by changing the base ob/ind max at a constant ratio (their initial ratio)

Parameters
  • dscore_min (float) – maximum diversity score limit for the pool

  • ob_base (float) – base max obligor concentration limitation

  • ind_base (float) – base max industry concentration limitation

  • riskscore_max (float) – max DBRSM risk score of the pool

  • ob_exceptions (list[objects.ConcLimitException]) – obligor concentration limitations

  • ind_exceptions (list[objects.ConcLimitException]) – industry concentration limitations

  • ob_floor (float) – lowest level that the base obligor concentration limitation is allowed to spin down to

  • ind_floor (float) – lowest level that the base industry concentration limitation is allowed to spin down to

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • tables (dict[str, np.ndarray]) – Lookup tables for Dscore and industry codes

  • force_high (tuple) – high rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • force_low (tuple) – low rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • is_simple_industry (bool) – if true, industry allocation is done on a repeating sequence. Hypo only iterates on obligor in this case.

  • n_simple_industry (int) – if is_simple_industry is True, this is the number of industries to repeat in sequence

Returns

results dictionary

Return type

dict

Results Dictionary Keys:

  • is_solve: True if solver found solution, False otherwise

  • dscore: diversity score calculated on the actual pool

  • ob_base: base obligor concentration limitation that the solver found

  • ind_base: base industry concentration limitation that the solver found

  • obligors: OrderedDict[objects.Obligor] pool of Obligors.

solve_dscore_ob_ex_partial(dscore_min, ob_base, ind_base, riskscore_max, ob_exceptions, ind_exceptions, ob_ex_partial, ob_floor, risk_score_tbl, tables, force_high, force_low, is_simple_industry, n_simple_industry)

Used when an obligor exception is removed in the outer layer algorithm. This solves for a fractional amount of that exception to be included back in the pool such the the target dscore is met

  • Iterates over the smallest obligor concentration limitation exception

Parameters
  • dscore_min (float) – target diversity score for the pool

  • ob_base (float) – base max obligor concentration limitation

  • ind_base (float) – base max industry concentration limitation

  • riskscore_max (float) – max DBRSM risk score of the pool

  • ob_exceptions (list[objects.ConcLimitException]) – obligor concentration limitations

  • ind_exceptions (list[objects.ConcLimitException]) – industry concentration limitations

  • ob_ex_partial (float) – the current smalled obligor concentration limitation exception; gets controlled by solver

  • ob_floor (float) – lowest level that the base obligor concentration limitation is allowed to spin down to

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • tables (dict[str, np.ndarray]) – Lookup tables for Dscore and industry codes

  • force_high (tuple) – high rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • force_low (tuple) – low rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • is_simple_industry (bool) – if true, industry allocation is done on a repeating sequence. Hypo only iterates on obligor in this case.

  • n_simple_industry (int) – if is_simple_industry is True, this is the number of industries to repeat in sequence

Returns

results dictionary

Return type

dict

solver_wrap_base_ob(ob_base, ind_mult, target_dscore, riskscore_max, ob_exceptions, ind_exceptions, ind_floor, risk_score_tbl, tables, force_high, force_low, is_simple_industry, n_simple_industry)

Objective function passed to the solver algorithm

  • Iterates over base obligor concentration limitation

  • Base industry concentration expressed as a multiple of base obligor

Parameters
  • ob_base (float) – base max obligor concentration limitation, this gets controlled by the solver

  • ind_mult (float) – multiplier to reduce the base max ind by a constant proportion to the base max ob

  • target_dscore (float) – target diversity score limit for the pool

  • riskscore_max (float) – max DBRSM risk score of the pool

  • ob_exceptions (list[objects.ConcLimitException]) – obligor concentration limitations

  • ind_exceptions (list[objects.ConcLimitException]) – industry concentration limitations

  • ind_floor (float) – minimum that the base industry pct can go; overrides the ind_mult * ob_max if that is too low

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • tables (dict[str, np.ndarray]) – Lookup tables for Dscore and industry codes

  • force_high (tuple) – high rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • force_low (tuple) – low rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • is_simple_industry (bool) – if true, industry allocation is done on a repeating sequence. Hypo only iterates on obligor in this case.

  • n_simple_industry (int) – if is_simple_industry is True, this is the number of industries to repeat in sequence

Returns

difference between the actual dscore and the target, solver attempts to minimize this

Return type

float

solver_wrap_ob_ex_partial(ob_ex_partial, ob_base, ind_base, target_dscore, riskscore_max, ob_exceptions, ind_exceptions, risk_score_tbl, tables, force_high, force_low, is_simple_industry, n_simple_industry)

Objective function passed to the solver algorithm

  • Iterates over smallest obligor concentration exception limitation percentage

Parameters
  • ob_ex_partial (float) – the current smallest obligor concentration limitation exception; gets controlled by solver

  • ob_base (float) – base max obligor concentration limitation,

  • ob_base – base max industry concentration limitation

  • target_dscore (float) – target diversity score limit for the pool

  • riskscore_max (float) – max DBRSM risk score of the pool

  • ob_exceptions (list[clo_internal_objects.ConcLimitException]) – obligor concentration limitations

  • ind_exceptions (list[clo_internal_objects.ConcLimitException]) – industry concentration limitations

  • risk_score_tbl (dict[int, float]) – lookup table for DBRSM Risk Score

  • tables (dict[str, np.ndarray]) – Lookup tables for Dscore and industry codes

  • force_high (tuple) – high rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • force_low (tuple) – low rating (rating integer, percentage) to lock prior to solving for belly ratings (ratings not in the front end or in the back end of the yield curve)

  • is_simple_industry (bool) – if true, industry allocation is done on a repeating sequence. Hypo only iterates on obligor in this case.

  • n_simple_industry (int) – if is_simple_industry is True, this is the number of industries to repeat in sequence

Returns

difference between the actual dscore and the target, solver attempts to minimize this

Return type

float