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

Beneish M-Score

Install and import#

bash
npm install fintech-algorithms
ts
import { beneishMScore } from "fintech-algorithms/fundamental-analysis-and-valuation/quality-and-distress/beneish-m-score";

Signature#

beneishMScore(data)

Builds the eight Beneish indices from a current and prior-year accounting pair and combines them into the M-Score with the 1999 eight-variable coefficients, reporting whether the score clears the screening cutoff.

Parameters#

NameTypeNotes
data{ sales: number; prior_sales: number; receivables: number; prior_receivables: number; cost_of_goods_sold: number; prior_cost_of_goods_sold: number; current_assets: number; prior_current_assets: number; net_ppe: number; prior_net_ppe: number; securities: number; prior_securities: number; total_assets: number; prior_total_assets: number; depreciation: number; prior_depreciation: number; sga_expense: number; prior_sga_expense: number; current_liabilities: number; prior_current_liabilities: number; long_term_debt: number; prior_long_term_debt: number; income_from_continuing_operations: number; operating_cash_flow: number }A flat record holding each line item for the current year and its prior-year twin. sales, prior_sales, receivables and prior_receivables drive DSRI; cost_of_goods_sold and its prior drive GMI; current_assets, net_ppe, securities, total_assets and their priors drive AQI; depreciation and prior_depreciation with net PPE drive DEPI; sga_expense and its prior drive SGAI; current_liabilities, long_term_debt and their priors drive LVGI; and income_from_continuing_operations less operating_cash_flow over total_assets gives TATA.

Returns#

{ state: string; method: string; indices: { dsri: number; gmi: number; aqi: number; sgi: number; depi: number; sgai: number; lvgi: number; tata: number }; contributions: { intercept: number; dsri: number; gmi: number; aqi: number; sgi: number; depi: number; sgai: number; tata: number; lvgi: number }; m_score: number; screen: string; cutoff: number }

indices holds the eight raw indices and contributions holds each one after its coefficient, together with the -4.84 intercept. The weights applied are 0.92 DSRI, 0.528 GMI, 0.404 AQI, 0.892 SGI, 0.115 DEPI, -0.172 SGAI, 4.679 TATA and -0.327 LVGI. m_score is their sum, cutoff is -1.78 and screen is above-screening-cutoff when the score exceeds it and below-screening-cutoff otherwise. method is beneish-1999-eight-variable and state is calculated.

Errors#

  • When data is not a plain object — throws TypeError
  • When any field read is missing or not a finite number — throws TypeError
  • When sales, prior_sales, total_assets or prior_total_assets is zero or negative — throws RangeError
  • When receivables or prior_receivables is negative — throws RangeError
  • When the current or prior gross margin computes to zero — throws RangeError
  • When the prior asset-quality denominator is zero — throws RangeError
  • When a depreciation rate denominator, or a DSRI, SGAI or LVGI denominator, is zero — throws RangeError

Complexity: time O(1), space O(1).

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
{
  "sales": 1200,
  "prior_sales": 1000,
  "receivables": 180,
  "prior_receivables": 100,
  "cost_of_goods_sold": 720,
  "prior_cost_of_goods_sold": 650,
  "current_assets": 500,
  "prior_current_assets": 430,
  "net_ppe": 400,
  "prior_net_ppe": 390,
  "securities": 10,
  "prior_securities": 10,
  "total_assets": 1000,
  "prior_total_assets": 900
}

Showing 14 of 24 fields.

Call#

beneishMScore(data)

Returns#

object with 7 fields: state, method, indices, contributions, m_score, screen, cutoff

{
  "state": "calculated",
  "method": "beneish-1999-eight-variable",
  "indices": {
    "dsri": 1.4999999999999998,
    "gmi": 0.8749999999999999,
    "aqi": 1.1571428571428575,
    "sgi": 1.2,
    "depi": 0.947565543071161,
    "sgai": 0.9895833333333333,
    "lvgi": 0.9519230769230771,
    "tata": 0.035
  },
  "contributions": {
    "intercept": -4.84,
    "dsri": 1.38,
    "gmi": 0.46199999999999997,
    "aqi": 0.46748571428571445,
    "sgi": 1.0704,
    "depi": 0.10897003745318352,
    "sgai": -0.1702083333333333,
    "tata": 0.16376500000000002,
    "lvgi": -0.3112788461538462
  },
  "m_score": -1.6688664277482819,
  "screen": "above-screening-cutoff",
  "cutoff": -1.78
}

Other exports#

This module also exports calculate, altmanZScore, piotroskiFScore, sloanAccrualMeasure, ohlsonOScore, zmijewskiXScore, springateSScore, tafflerZScore, fulmerHScore, groverGScore, dechowFScoreForMisstatementRisk, dechowDichevAccrualQuality, modifiedJonesDiscretionaryAccrualModel. 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#

Beneish M-Score — evidence clock
Beneish M-Score — model anatomy
Beneish M-Score — system map
Beneish M-Score — threshold and interpretation
Beneish M-Score — 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 Quality and Distress family#