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

Piotroski F-Score

Install and import#

bash
npm install fintech-algorithms
ts
import { piotroskiFScore } from "fintech-algorithms/fundamental-analysis-and-valuation/quality-and-distress/piotroski-f-score";

Signature#

piotroskiFScore(data)

Scores the nine binary Piotroski signals covering profitability, leverage and liquidity, and operating efficiency across the current and prior year, and sums them into an F-Score from 0 to 9.

Parameters#

NameTypeNotes
data{ net_income: number; prior_net_income: number; operating_cash_flow: number; beginning_total_assets: number; prior_beginning_total_assets: number; long_term_debt: number; prior_long_term_debt: number; current_assets: number; current_liabilities: number; prior_current_assets: number; prior_current_liabilities: number; equity_issued: number; gross_profit: number; prior_gross_profit: number; sales: number; prior_sales: number }Current and prior-year accounting values in one flat record. The function reads beginning_total_assets and prior_beginning_total_assets as the ROA and turnover denominators, net_income, prior_net_income and operating_cash_flow for the profitability signals, long_term_debt, prior_long_term_debt, current_assets, current_liabilities, prior_current_assets, prior_current_liabilities and equity_issued for the leverage and liquidity signals, and gross_profit, prior_gross_profit, sales and prior_sales for the efficiency signals.

Returns#

{ state: string; method: string; signals: { positive_roa: number; positive_cfo: number; improving_roa: number; cash_exceeds_income: number; lower_leverage: number; higher_current_ratio: number; no_equity_issue: number; higher_gross_margin: number; higher_asset_turnover: number }; f_score: number; band: string; signal_count: number }

signals carries each of the nine tests as 0 or 1 and f_score is their sum. band is weak-signals at 2 or below, strong-signals at 8 or above and mixed-signals between. signal_count is always 9, method is piotroski-2000-nine-signal 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 any of beginning_total_assets, prior_beginning_total_assets, current_assets, current_liabilities, prior_current_assets, prior_current_liabilities, sales or prior_sales is zero or negative — throws RangeError
  • When equity_issued is negative — 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
{
  "net_income": 80,
  "prior_net_income": 50,
  "operating_cash_flow": 110,
  "beginning_total_assets": 900,
  "prior_beginning_total_assets": 850,
  "long_term_debt": 260,
  "prior_long_term_debt": 300,
  "current_assets": 500,
  "current_liabilities": 250,
  "prior_current_assets": 430,
  "prior_current_liabilities": 250,
  "equity_issued": 0,
  "gross_profit": 480,
  "prior_gross_profit": 390
}

Showing 14 of 16 fields.

Call#

piotroskiFScore(data)

Returns#

object with 6 fields: state, method, signals, f_score, band, signal_count

{
  "state": "calculated",
  "method": "piotroski-2000-nine-signal",
  "signals": {
    "positive_roa": 1,
    "positive_cfo": 1,
    "improving_roa": 1,
    "cash_exceeds_income": 1,
    "lower_leverage": 1,
    "higher_current_ratio": 1,
    "no_equity_issue": 1,
    "higher_gross_margin": 1,
    "higher_asset_turnover": 1
  },
  "f_score": 9,
  "band": "strong-signals",
  "signal_count": 9
}

Other exports#

This module also exports calculate, altmanZScore, beneishMScore, 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#

Piotroski F-Score — evidence clock
Piotroski F-Score — model anatomy
Piotroski F-Score — system map
Piotroski F-Score — threshold and interpretation
Piotroski F-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#