fintech-algorithms
Using a coding agent? Give it the skill: npx skills add IslamBaraka90/Fintech-Algorithms-Library What it does →

Fundamental Metric Direction and Peer Normalization

Install and import#

bash
npm install fintech-algorithms
ts
import { fundamentalMetricDirectionAndPeerNormalization } from "fintech-algorithms/fundamental-analysis-and-valuation/integrated-equity-scoring/fundamental-metric-direction-and-peer-normalization";

Signature#

fundamentalMetricDirectionAndPeerNormalization(data)

Turns each metric's target value into a midrank empirical percentile against its peer values, flips that percentile where lower is better, and averages the resulting scores across metrics.

Parameters#

NameTypeNotes
data{ min_peers: number; metrics: Array<{ name: string; target: number; peers: number[]; higher_is_better: boolean }> }The normalisation request. min_peers is truncated to an integer and is the number of finite peers each metric must supply. Each metric needs a text name, a finite target, a peers list whose non-finite entries are dropped, and a boolean higher_is_better that decides whether the percentile is kept or subtracted from 100.

Returns#

{ state: string; method: string; metrics: Array<{ name: string; target: number; peer_count: number; percentile: number; higher_is_better: boolean; normalized_score: number }>; aggregate_score: number; metric_count: number; invariant: string }

One row per input metric carrying peer_count, the percentile formed as peers strictly below the target plus half the ties, over the peer count and times 100, and the direction-adjusted normalized_score. aggregate_score is the unweighted mean of those scores and metric_count their number.

Errors#

  • When metrics is not a nonempty list, or a metric lacks a text name or a peers list — throws TypeError
  • When a metric target is not a finite number, or higher_is_better is not a boolean — throws TypeError
  • When min_peers is not positive — throws RangeError
  • When a metric supplies fewer finite peer values than min_peers — throws RangeError

Complexity: time O(m * p), space O(m + p).

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#

data
{
  "min_peers": 3,
  "metrics": [
    {
      "name": "roic",
      "target": 0.12,
      "peers": [0.08, 0.1, 0.14, 0.16],
      "higher_is_better": true
    },
    {
      "name": "net_debt_to_ebitda",
      "target": 1.5,
      "peers": [0.8, 1.2, 2, 3],
      "higher_is_better": false
    },
    {
      "name": "fcf_margin",
      "target": 0.1,
      "peers": [0.04, 0.08, 0.12, 0.16],
      "higher_is_better": true
    }
  ]
}

Call#

fundamentalMetricDirectionAndPeerNormalization(data)

Returns#

object with 6 fields: state, method, metrics, aggregate_score, metric_count, invariant

{
  "state": "calculated",
  "method": "midrank-empirical-percentile-with-direction",
  "metrics": [
    {
      "name": "roic",
      "target": 0.12,
      "peer_count": 4,
      "percentile": 50,
      "higher_is_better": true,
      "normalized_score": 50
    },
    {
      "name": "net_debt_to_ebitda",
      "target": 1.5,
      "peer_count": 4,
      "percentile": 50,
      "higher_is_better": false,
      "normalized_score": 50
    },
    {
      "name": "fcf_margin",
      "target": 0.1,
      "peer_count": 4,
      "percentile": 50,
      "higher_is_better": true,
      "normalized_score": 50
    }
  ],
  "aggregate_score": 50,
  "metric_count": 3,
  "invariant": "higher-is-better reverses the percentile only; peer values are not z-scored"
}

Other exports#

This module also exports calculate, pointInTimeStockScoringInputAssembly, stockScoringPeerCohortResolver, modelApplicabilityAndVariantRouter, accountingFinancialHealthComposite, earningsQualityComposite, dividendSafetyScore, balanceSheetResilienceScore, distressModelEnsemble, crossModelConflictAndDoubleCountingResolver, overallExplainableStockScore, scoreConfidenceMissingDataPenaltyAndAbstention, marketWideStockScreeningAndRanking, stockScoreHistoryMigrationAndChangeAttribution. 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#

Fundamental Metric Direction and Peer Normalization — evidence clock
Fundamental Metric Direction and Peer Normalization — model anatomy
Fundamental Metric Direction and Peer Normalization — system map
Fundamental Metric Direction and Peer Normalization — threshold and interpretation
Fundamental Metric Direction and Peer Normalization — variant boundaries

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.

Read the article →

References#

The rest of the Integrated Equity Scoring family#