Spaces:
Sleeping
Sleeping
| # Constraint Relaxation Cascade | |
| The Quantitative Portfolio Engine implements a robust 7-stage constraint relaxation cascade. This exists because strict convex optimization models (like CVXPY) frequently encounter feasibility limits (infeasible or optimal_inaccurate states) when processing dense covariance matrices with tight turnover, sector, and minimum weight constraints. | |
| When the primary formulation pushes solver limits or hits numerical precision walls, the engine sequentially relaxes constraints to find the nearest feasible mathematical solution, rather than failing abruptly. | |
| ## The 7-Stage Cascade | |
| ### Stage 1: Strict Formulation | |
| - **Objective:** Tries to solve the exact formulation provided by the user constraints. | |
| - **Constraints Active:** Minimum and maximum single asset weights, sector concentration limits, total turnover caps, and target Beta. | |
| ### Stage 2: Beta Range Expansion | |
| - **Relaxation:** The target market beta equality constraint is softened to an inequality range (e.g., Target Beta ± 0.1). | |
| - **Reason:** Perfect beta matching is often mathematically impossible when paired with tight turnover limits. | |
| ### Stage 3: Turnover Relaxation | |
| - **Relaxation:** The `max_turnover` constraint is completely disabled. | |
| - **Reason:** In highly volatile regimes, the expected returns might shift drastically. Preventing the solver from trading (turnover cap) makes it impossible to reach the efficient frontier, causing infeasibility. | |
| ### Stage 4: Sector Limit Expansion | |
| - **Relaxation:** The `sector_limit` constraint is disabled. | |
| - **Reason:** When correlations cluster heavily within a single sector (e.g., Tech during a rally), the optimizer wants to overweight that sector to achieve the target return/Sharpe. Removing this limit prevents artificial underperformance clipping. | |
| ### Stage 5: Zero Floor (No Shorts) | |
| - **Relaxation:** `single_asset_min` is strictly floored at `0.0`. Shorting is completely disabled. | |
| - **Reason:** Leverage and short-borrow cost parameters can create unstable quadratic objective spaces (non-PSD covariance interactions). Forcing a long-only constraint space guarantees a more stable OSQP projection. | |
| ### Stage 6: Unconstrained Max Weight | |
| - **Relaxation:** `single_asset_max` is pushed to `1.0` (100%). | |
| - **Reason:** At this point, the solver is struggling to find *any* combination of assets that satisfies the risk constraints. Allowing a 100% allocation into the safest asset (like CASH or TLT) gives the solver an "escape hatch". | |
| ### Stage 7: Cash Fallback | |
| - **Relaxation:** If all else fails, the engine abandons the Markowitz optimization entirely. | |
| - **Action:** It assigns 100% of the portfolio to the risk-free asset or cash proxy (e.g., `CASH`). | |
| - **Reason:** A mathematical failure in the convex space implies the risk regime is fundamentally broken or the input covariance matrix is irrecoverably singular. Protecting capital via a 100% cash allocation is the safest programmatic fallback. | |
| ## Solver Notes | |
| Even when passing feasibility checks, solvers like OSQP or ECOS may occasionally return `OPTIMAL_INACCURATE`. This is normal when dealing with near-collinear assets that leave tiny negative eigenvalues (e.g., `4e-7`). The cascade logs these occurrences and proceeds with the projected PSD matrix. | |