Turnover-Constrained Optimization
Install and import#
npm install fintech-algorithmsimport { solveTurnoverConstrainedMarkowitz } from "fintech-algorithms/portfolio-construction/practical-constraints/turnover-constrained-optimization";Signature#
solveTurnoverConstrainedMarkowitz(mu, covariance, lambdaRisk, w0, tau, options)Parameters#
| Name | Type | Notes |
|---|---|---|
mu | finite real vector, length `N` | decimal simple return for the declared period; asset order is canonical |
covariance | finite `N×N` matrix | squared-return units; symmetric PSD within scale-aware tolerance |
lambdaRisk | finite real scalar | nonnegative objective coefficient |
w0 | finite real vector, length `N` | nonnegative current normalized holdings; sum must already be one within 1e-12; no silent normalization |
tau | finite real scalar | nonnegative one-way turnover cap in normalized portfolio units |
options | TurnoverSolverOptions | optional |
Worked example#
executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.
Input#
[0.1, 0.04][
[0.04, 0],
[0, 0.01]
]1[0.6, 0.4]0.1Call#
solveTurnoverConstrainedMarkowitz(mu, covariance, lambdaRisk, w0, tau, options)Returns#
object with 10 fields: status, weights, objective, directTurnover, inputCurrentSum, simplexResidual, minWeight, iterations, …
{
"status": "optimal",
"weights": [0.7, 0.3],
"objective": 0.06149999999999999,
"directTurnover": 0.1,
"inputCurrentSum": 1,
"simplexResidual": 0,
"minWeight": 0.3,
"iterations": 2,
"frankWolfeGap": 1.8873791418627663e-18,
"certificate": {
"kind": "projected-gradient-kkt-plus-frank-wolfe-gap",
"stationarityResidual": 1.1102230246251566e-17,
"frankWolfeGap": 1.8873791418627663e-18,
"objectiveGapUpperBound": 1.8873791418627663e-18,
"normalizedStationarityResidual": 1.1102230246251565e-16,
"normalizedFrankWolfeGap": 1.8873791418627663e-17,
"normalizedObjectiveGapUpperBound": 1.8873791418627663e-17,
"objectiveScale": 0.1,
"stationarityTolerance": 1e-8,
"toleranceUnits": "normalized by objectiveScale; original-unit gap is retained above",
"lipschitzUpperBound": 0.08,
"stepDenominator": 0.1,
"stepSize": 10,
"turnoverRadius": 0.2
}
}Diagrams#
How it works#
This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.
References#
- transaction chapter
- multi-period chapter
- Multi-period trading with transaction costs
- Portfolio Analysis with Turnover Constraints
- `Portfolio.setTurnover` method
- portfolio constraints chapter
- Google discovery ledger
- Evidence classification
- Limitations