Sector-Specific Weight Calibration
Install and import#
npm install fintech-algorithmsimport { sectorSpecificWeightCalibration } from "fintech-algorithms/fundamental-analysis-and-valuation/sector-specific-equity-scoring/sector-specific-weight-calibration";Signature#
sectorSpecificWeightCalibration(data)Fits component weights by projected gradient descent on a logistic model of the labelled outcome, keeping the weights nonnegative and summing to 1 at every step and pulling them back toward the declared base weights with a ridge term. Splits the history in time and keeps the fitted weights only when they beat the base weights on the held-out Brier score.
Parameters#
| Name | Type | Notes |
|---|---|---|
data | RecordValue | A plain object. framework must be the string sector-weight-calibration-teaching-v1. component_names is an array of at least two unique nonempty strings; base_weights is an object keyed by exactly those names, nonnegative and summing to 1. feature_rows is an array of at least twelve rows, each a numeric array aligned to component_names with every score in [0, 100]; labels and observation_dates must match it in length, labels being 0 or 1 and dates being strictly increasing YYYY-MM-DD strings. train_end_index splits the rows in time. learning_rate, logit_slope and iterations must be positive, ridge_penalty nonnegative.min_rows: 12 · min_training_rows: 8 · min_validation_rows: 4 · max_iterations: 5000 |
Returns#
{ state: string; method: string; component_names: string[]; base_weights: Record<string, number>; candidate_weights: Record<string, number>; selected_weights: Record<string, number>; candidate_intercept: number; selected_intercept: number; base_train_brier: number; base_validation_brier: number; candidate_train_brier: number; candidate_validation_brier: number; selected_validation_brier: number; weight_shift_l1: number; train_rows: number; validation_rows: number; coverage_ratio: number; reason: string }
candidate_weights and candidate_intercept are the fitted values; selected_weights and selected_intercept are those same values when the candidate validation Brier score is at or below the base one, and otherwise the base weights with a zero intercept. The four Brier fields report train and validation loss for base and candidate, and selected_validation_brier repeats whichever was chosen. weight_shift_l1 is the summed absolute move from base to candidate, and train_rows and validation_rows record the split sizes. state is calibrated-improved or retain-base-weights. method is nonnegative-simplex-logloss-v1 and coverage_ratio is 1.
Errors#
- When data is not a plain object, or a feature value is not a finite number — throws TypeError
- When an observation date is not a YYYY-MM-DD string — throws TypeError
- When framework is not sector-weight-calibration-teaching-v1 — throws RangeError
- When component_names is not at least two unique nonempty strings — throws RangeError
- When feature_rows holds fewer than 12 observations, or labels or observation_dates do not match its length — throws RangeError
- When a feature row does not match component_names in length, or a score falls outside [0, 100] — throws RangeError
- When a label is not 0 or 1, or observation_dates is not strictly increasing — throws RangeError
- When train_end_index leaves fewer than 8 training or 4 validation rows — throws RangeError
- When base_weights does not match component_names, is negative, or does not sum to 1 within 1e-9 — throws RangeError
- When learning_rate, logit_slope or iterations is not positive, ridge_penalty is negative, or iterations exceeds 5000 — throws RangeError
Complexity: time O(i * n * k + i * k log k) for i iterations, n rows and k components,
space O(n * k).
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#
{
"framework": "sector-weight-calibration-teaching-v1",
"component_names": ["quality", "resilience", "cash_conversion"],
"base_weights": {
"quality": 0.4,
"resilience": 0.35,
"cash_conversion": 0.25
},
"feature_rows": [
[82, 65, 78],
[74, 60, 70],
[45, 72, 55]
],
"labels": [1, 1, 0, 1, 0, 1],
"observation_dates": [
"2024-01-01",
"2024-02-01",
"2024-03-01",
"2024-04-01",
"2024-05-01",
"2024-06-01"
],
"train_end_index": 12,
"learning_rate": 0.08,
"ridge_penalty": 0.2,
"logit_slope": 5,
"iterations": 600
}Call#
sectorSpecificWeightCalibration(data)Returns#
object with 18 fields: state, method, component_names, base_weights, candidate_weights, selected_weights, candidate_intercept, selected_intercept, …
{
"state": "retain-base-weights",
"method": "nonnegative-simplex-logloss-v1",
"component_names": ["quality", "resilience", "cash_conversion"],
"base_weights": {
"quality": 0.4,
"resilience": 0.35,
"cash_conversion": 0.25
},
"candidate_weights": {
"quality": 0.7551696860135335,
"resilience": 0,
"cash_conversion": 0.24483031398646643
},
"selected_weights": {
"quality": 0.4,
"resilience": 0.35,
"cash_conversion": 0.25
},
"candidate_intercept": -0.40266157235699845,
"selected_intercept": 0,
"base_train_brier": 0.14500903499442555,
"base_validation_brier": 0.10197248987791843,
"candidate_train_brier": 0.10051624085395794,
"candidate_validation_brier": 0.10310568321068389,
"selected_validation_brier": 0.10197248987791843,
"weight_shift_l1": 0.710339372027067
}Showing 14 of 18 fields.
Other exports#
This module also exports
calculate, bankFundamentalScore, insuranceFundamentalScore, reitFundamentalScore, utilityFundamentalScore, earlyStageLiquidityAndRunwayScore, cyclicalAndCommodityCycleNormalization, holdingCompanyLookThroughScore, unsupportedScopeAndCoverageDecision. Every module additionally exports run as an alias of its
primary function, and a meta object carrying its catalog id, domain, family,
shape and article URL.
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#
- Probability calibration — scikit-learn maintainers
- Forecasting: Principles and Practice — Time series cross-validation — Rob J Hyndman and George Athanasopoulos
- Evidence boundary