Configuration¶
Classes that control how BasanosEngine and BasanosStream behave.
BasanosConfig¶
basanos.math.BasanosConfig
¶
Bases: BaseModel
Configuration for correlation-aware position optimization.
The required parameters (vola, corr, clip, shrink, aum)
must be supplied by the caller. The optional parameters carry
carefully chosen defaults whose rationale is described below.
Shrinkage methodology¶
shrink controls linear shrinkage of the EWMA correlation matrix toward
the identity:
where \(\\lambda\) = shrink and \(I_n\) is the identity.
Shrinkage regularises the matrix when assets are few relative to the
lookback (high concentration ratio \(n / T\)), reducing the impact of
extreme sample eigenvalues and improving the condition number of the matrix
passed to the linear solver.
When to prefer strong shrinkage (low shrink / high 1-shrink\ ):
- Fewer than ~30 assets with a
corrlookback shorter than 100 days. - High-volatility or crisis regimes where correlations spike and the sample matrix is less representative of the true structure.
- Portfolios where estimation noise is more costly than correlation bias
(e.g., when the signal-to-noise ratio of
muis low).
When to prefer light shrinkage (high shrink\ ):
- Many assets with a long lookback (low concentration ratio).
- The EWMA correlation structure carries genuine diversification information that you want the solver to exploit.
- Out-of-sample testing shows that position stability is not a concern.
Practical starting points (daily return data):
Here n = number of assets and T = cfg.corr (EWMA lookback).
+-----------------------+-------------------+--------------------------------+ | n (assets) / T (corr) | Suggested shrink | Notes | +=======================+===================+================================+ | n > 20, T < 40 | 0.3 - 0.5 | Near-singular matrix likely; | | | | strong regularisation needed. | +-----------------------+-------------------+--------------------------------+ | n ~ 10, T ~ 60 | 0.5 - 0.7 | Balanced regime. | +-----------------------+-------------------+--------------------------------+ | n < 10, T > 100 | 0.7 - 0.9 | Well-conditioned sample; | | | | light shrinkage for stability. | +-----------------------+-------------------+--------------------------------+
See shrink2id for the full theoretical
background and academic references (Ledoit & Wolf, 2004; Chen et al., 2010).
Default rationale¶
denom_tol = 1e-12
Positions are zeroed when the normalisation denominator
inv_a_norm(μ, Σ) falls at or below this threshold. The
value 1e-12 provides ample headroom above float64 machine
epsilon (~2.2e-16) while remaining negligible relative to any
economically meaningful signal magnitude.
position_scale = 1e6
The dimensionless risk position is multiplied by this factor
before being passed to Portfolio.
A value of 1e6 means positions are expressed in units of one
million of the base currency, a conventional denomination for
institutional-scale portfolios where AUM is measured in hundreds
of millions.
min_corr_denom = 1e-14
The EWMA correlation denominator sqrt(var_x * var_y) is
compared against this threshold; when at or below it the
correlation is set to NaN rather than dividing by a near-zero
value. The default 1e-14 is safely above float64 underflow
while remaining negligible for any realistic return series.
Advanced users may tighten this guard (larger value) when
working with very-low-variance synthetic data.
max_nan_fraction = 0.9
ExcessiveNullsError is raised
during construction when the null fraction in any asset price
column strictly exceeds this threshold. The default 0.9
permits up to 90 % missing prices (e.g., illiquid or recently
listed assets in a long history) while rejecting columns that
are almost entirely null and would contribute no useful
information. Callers who want a stricter gate can lower this
value; callers running on sparse data can raise it toward 1.0.
Sliding-window mode¶
When covariance_config is a SlidingWindowConfig, the EWMA
correlation estimator is replaced by a rolling-window factor model
(Section 4.4 of basanos.pdf). At each timestamp t the
\(W \\times n\) submatrix of the \(W\) most recent
volatility-adjusted returns is decomposed via truncated SVD to extract
\(k\) latent factors. The resulting correlation estimate is
where \(\\hat{D}_t\) enforces unit diagonal. The linear system
\(\\hat{C}_t^{(W,k)}\\mathbf{x}_t = \\boldsymbol{\\mu}_t\) is solved
via the Woodbury identity (solve)
at cost \(O(k^3 + kn)\) per step rather than \(O(n^3)\).
covariance_config
Pass a SlidingWindowConfig instance to enable this mode.
The required sub-parameters are:
``window``
Rolling window length $W \\geq 1$. Rule of thumb: $W
\\geq 2n$ keeps the sample covariance well-posed before truncation.
``n_factors``
Number of latent factors $k \\geq 1$. $k = 1$
recovers the single market-factor model; larger $k$ captures
finer correlation structure at the cost of higher estimation noise.
Examples:
>>> cfg = BasanosConfig(vola=32, corr=64, clip=3.0, shrink=0.5, aum=1e8)
>>> cfg.vola
32
>>> cfg.corr
64
>>> sw_cfg = BasanosConfig(
... vola=16, corr=32, clip=3.0, shrink=0.5, aum=1e6,
... covariance_config=SlidingWindowConfig(window=60, n_factors=3),
... )
>>> sw_cfg.covariance_mode
<CovarianceMode.sliding_window: 'sliding_window'>
Source code in src/basanos/math/_config.py
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | |
covariance_mode
property
¶
Covariance mode derived from covariance_config.
n_factors
property
¶
Number of latent factors, or None when not in sliding_window mode.
report
property
¶
Return a ConfigReport facade for this config.
Generates a self-contained HTML report summarising all configuration parameters, a shrinkage-guidance table, and a theory section on Ledoit-Wolf shrinkage.
To also include a lambda-sweep chart (Sharpe vs λ), use
config_report instead, which requires price and
signal data.
Returns:
| Type | Description |
|---|---|
ConfigReport
|
basanos.math._config_report.ConfigReport: Report facade with |
ConfigReport
|
|
Examples:
window
property
¶
Sliding window length, or None when not in sliding_window mode.
corr_greater_than_vola(v, info)
classmethod
¶
Optionally enforce corr ≥ vola for stability.
Pydantic v2 passes ValidationInfo; use info.data to access other fields.
Source code in src/basanos/math/_config.py
replace(*, vola=None, corr=None, clip=None, shrink=None, aum=None, denom_tol=None, position_scale=None, min_corr_denom=None, max_nan_fraction=None, covariance_config=None, cost_per_unit=None, max_turnover=_SENTINEL)
¶
Return a new BasanosConfig with selected fields replaced.
Unlike model_copy, this method uses explicit constructor kwarg
forwarding so that any new required field added to
BasanosConfig surfaces immediately as a type or lint error at
the call site, rather than silently failing at runtime.
All parameters default to None, meaning keep the existing value.
Pass a non-None value for every field you want to change.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vola
|
int | None
|
EWMA lookback for volatility normalisation. |
None
|
corr
|
int | None
|
EWMA lookback for correlation estimation. |
None
|
clip
|
float | None
|
Clipping threshold for volatility adjustment. |
None
|
shrink
|
float | None
|
Retention weight λ ∈ [0, 1] for linear shrinkage. |
None
|
aum
|
float | None
|
Assets under management for portfolio scaling. |
None
|
denom_tol
|
float | None
|
Minimum normalisation denominator. |
None
|
position_scale
|
float | None
|
Multiplicative scaling factor for cash positions. |
None
|
min_corr_denom
|
float | None
|
Guard threshold for the EWMA correlation denominator. |
None
|
max_nan_fraction
|
float | None
|
Maximum tolerated null fraction per price column. |
None
|
covariance_config
|
CovarianceConfig | None
|
Covariance estimation configuration. |
None
|
cost_per_unit
|
float | None
|
One-way trading cost per unit of position change. |
None
|
max_turnover
|
float | None
|
Optional turnover budget per period in cash-position
units. Pass |
_SENTINEL
|
Returns:
| Type | Description |
|---|---|
BasanosConfig
|
A new |
BasanosConfig
|
all other fields copied from |
Examples:
>>> cfg = BasanosConfig(vola=10, corr=20, clip=3.0, shrink=0.5, aum=1e6)
>>> cfg2 = cfg.replace(shrink=0.8)
>>> cfg2.shrink
0.8
>>> cfg2.vola == cfg.vola
True
>>> cfg3 = cfg.replace(cost_per_unit=0.001, max_turnover=1e5)
>>> cfg3.cost_per_unit
0.001
>>> cfg3.max_turnover
100000.0
Source code in src/basanos/math/_config.py
CovarianceMode¶
basanos.math.CovarianceMode
¶
Bases: StrEnum
Covariance estimation mode for the Basanos optimizer.
Attributes:
| Name | Type | Description |
|---|---|---|
ewma_shrink |
EWMA correlation matrix with linear shrinkage toward the
identity. Controlled by |
|
sliding_window |
Rolling-window factor model. A fixed block of the
\[
\\hat{C}_t^{(W,k)} = \\frac{1}{W}
\\mathbf{V}_{k,t}\\mathbf{\\Sigma}_{k,t}^2\\mathbf{V}_{k,t}^\\top
+ \\hat{D}_t
\]
where \(\\hat{D}_t\) is chosen to enforce unit diagonal.
The system is solved efficiently via the Woodbury identity
(Section 4.3 of basanos.pdf) at \(O(k^3 + kn)\) per step
rather than \(O(n^3)\).
Configured via |
Examples:
>>> CovarianceMode.ewma_shrink
<CovarianceMode.ewma_shrink: 'ewma_shrink'>
>>> CovarianceMode.sliding_window
<CovarianceMode.sliding_window: 'sliding_window'>
>>> CovarianceMode("sliding_window")
<CovarianceMode.sliding_window: 'sliding_window'>
Source code in src/basanos/math/_config.py
EwmaShrinkConfig¶
basanos.math.EwmaShrinkConfig
¶
Bases: BaseModel
Covariance configuration for the ewma_shrink mode.
This is the default covariance mode. No additional parameters are required
beyond those already present on BasanosConfig (shrink, corr).
.. note::
This class is intentionally minimal. The only field is the
covariance_mode discriminator, which is required to make Pydantic's
discriminated-union dispatch work correctly (see CovarianceConfig).
Before adding new EWMA-specific fields here, consider whether the field
name clashes with existing BasanosConfig top-level fields and
whether it would constitute a breaking change to the public API.
Examples:
Source code in src/basanos/math/_config.py
SlidingWindowConfig¶
basanos.math.SlidingWindowConfig
¶
Bases: BaseModel
Covariance configuration for the sliding_window mode.
Requires both window (rolling window length) and n_factors (number
of latent factors for the truncated SVD factor model).
Effective component count — at each streaming step the number of SVD components actually used is
where \(k\) = n_factors, \(W\) = window,
\(n_{\text{valid}}\) is the number of assets with finite prices at that
step, and \(k_{\text{max}}\) = max_components (or \(+\infty\)
when unset). This ensures the truncated SVD remains well-posed even when
assets temporarily drop out of the universe. Setting max_components
explicitly caps computational cost in large universes without changing the
desired factor count used in batch mode.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window
|
Rolling window length \(W \\geq 1\). Rule of thumb: \(W \\geq 2n\) keeps the sample covariance well-posed before truncation. |
required | |
n_factors
|
Number of latent factors \(k \\geq 1\). \(k = 1\) recovers the single market-factor model; larger \(k\) captures finer correlation structure at the cost of higher estimation noise. |
required | |
max_components
|
Optional hard cap on the number of SVD components used
per streaming step. When set, the effective component count is
\(\\min(k_{\\text{eff}},\\, \\texttt{max\\_components})\).
Useful for large universes where only a few factors dominate and
you want to limit SVD cost below |
required |
Examples:
>>> cfg = SlidingWindowConfig(window=60, n_factors=3)
>>> cfg.covariance_mode
<CovarianceMode.sliding_window: 'sliding_window'>
>>> cfg.window
60
>>> cfg.n_factors
3
>>> cfg.max_components is None
True
>>> cfg2 = SlidingWindowConfig(window=60, n_factors=10, max_components=3)
>>> cfg2.max_components
3
Source code in src/basanos/math/_config.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
CovarianceConfig¶
basanos.math.CovarianceConfig = Annotated[EwmaShrinkConfig | SlidingWindowConfig, Field(discriminator='covariance_mode')]
module-attribute
¶
Discriminated union of covariance-mode configurations.
Pydantic selects the correct sub-config based on the covariance_mode
discriminator field:
EwmaShrinkConfigwhencovariance_mode="ewma_shrink"SlidingWindowConfigwhencovariance_mode="sliding_window"