The governed definitions this build depends on. Read them first if a term is unfamiliar.
- PrimaryFactor Diffusion IndexFactor Diffusion Index summarizes how broadly a declared condition is spreading across eligible factor groups.
- PrerequisiteDiffusion IndexDiffusion Index summarizes the balance of increases, unchanged observations, and decreases across a population.
- PrerequisiteFactorFactor is a defined variable used to represent a systematic characteristic, exposure, or source of return variation.
- PrerequisiteFactor GroupFactor Group is a declared collection or bucket of securities, portfolios, or signals associated with a factor definition.
- PrerequisiteMarket BreadthMarket breadth describes how widely a market movement is shared across its eligible securities.
- ImportantFactor BreadthFactor Breadth describes how broadly a condition is shared across factor-defined securities, portfolios, or groups.
- ImportantFactor ExposureFactor Exposure is a quantified relationship between an asset, portfolio, or group and a defined factor.
The operational question
Market breadth is not one idea. A headline move can be driven by a few constituents, a weight vector can be concentrated before any return occurs, and a signal can spread across sectors or factor sleeves without those components being independent. Factor Diffusion Index owns one precise question: how broadly is a declared signal improving across a fixed set of factor sleeves?
Several factor sleeves can improve together because they share holdings. This diagnostic counts participation while keeping that overlap limitation visible. That is a diagnostic and governance outcome, not a forecast, recommendation, legal classification, or promise of diversification.
Intuition before notation
Treat each factor sleeve as one component of a breadth panel; the output describes cross-factor participation, not a provider factor index. Sector diffusion spans industry groups; factor diffusion spans systematic strategy sleeves whose holdings may overlap heavily.
The family map prevents a category error. Contribution combines beginning weight and realized return. HHI and effective N inspect the weight vector before returns. Diffusion scores direction across a fixed component panel. Choosing the wrong branch may produce valid arithmetic that answers the wrong question.
Freeze the series identity
The selected formula is:
Apply the declared signal, horizon, direction convention, and tolerance to each factor sleeve, then average 1/0.5/0 scores. Factor identities, construction methods, return basis, currency, horizon, availability time, and tolerance are part of the series identity. The relevant primary source establishes the underlying convention; the exact diagnostic, translated universe, and parameters remain package choices where stated.
The snapshot needs unique identifiers, finite values, complete coverage, and one point-in-time methodology. as_of is not enough in production: retain observation, availability, and knowledge times plus source owner, revision, and finality. A later corrected roster or classification must not overwrite what was knowable at the earlier cutoff.
Required input
| Field | Type | Unit and rule |
|---|---|---|
as_of | ISO date | common observation cutoff; retain availability and knowledge time separately |
component_id | string | unique fixed factor sleeve with a declared provider/methodology identity |
signal_change | finite number | decimal change for one synchronized sleeve signal, horizon, direction convention, return basis, and currency |
ready | boolean | false means cross-factor coverage is incomplete |
tolerance | nonnegative number | decimal deadband; exact +/- tolerance is unchanged |
Output and refusal behavior
Return value from 0 to 100 and class counts. The score describes equal-sleeve directional participation only; it is not a provider factor index, diversification ratio, or independence statistic.
The reference API deliberately matches sector-diffusion arithmetic while enforcing factor-sleeve identity in the data contract. The lab changes tolerance and scenarios without pretending the votes are independent.
Read the mathematics, not only the score
The 1/0.5/0 transform is identical to sector diffusion, but the component identity is a fixed factor-sleeve methodology. Exact tolerance equality is unchanged, and every sleeve receives one vote regardless of assets or holdings overlap.
0 <= D_factor <= 100and class counts sum to the fixed sleeve count.- Exact
+toleranceand-toleranceobservations are unchanged. - Replacing a provider methodology, factor definition, currency, horizon, or signal creates a new series.
- A high score does not imply independent exposures: Value, Quality, Momentum, and other sleeves may own many of the same securities.
The output must travel with its series identity and diagnostic trace. A bare number strips away the universe, methodology, horizon, tolerance, and evidence status needed to interpret it.
Work the synthetic example
The following is labelled synthetic and all arithmetic is author-derived:
| Component | Signal change | Class | Score |
|---|---|---|---|
| Value | 1.400% | improving | 1 |
| Momentum | 1.100% | improving | 1 |
| Quality | 0.700% | improving | 1 |
| Low Size | 0.300% | improving | 1 |
| Low Volatility | 0.000% | unchanged | 0.5 |
| High Yield | -0.200% | unchanged | 0.5 |
| Growth | -0.600% | deteriorating | 0 |
| Profitability | -0.900% | deteriorating | 0 |
The exact expected result is:
{
"status": "resolved",
"value": 62.5,
"improving": 4,
"unchanged": 2,
"deteriorating": 2,
"total": 8
}
The visual keeps the distribution beside the aggregate. That matters because two identical aggregate values can conceal different component states. The values are synthetic teaching inputs; the displayed result is author-derived arithmetic.
Compare nearby methods
| Variant | Component universe or vote | Best use | Main limitation |
|---|---|---|---|
| Equal-sleeve diffusion (selected) | one vote per fixed factor sleeve | audit breadth across declared strategies | overlapping holdings mean votes are not independent |
| Asset-weighted factor diffusion | weight sleeves by assets or allocation | describe a specific portfolio | allocation changes alter the series |
| Constituent-level factor breadth | classify securities within one factor | inspect internal participation | answers a different within-sleeve question |
| Continuous factor average | average raw sleeve signals | retain magnitude | can be dominated by one sleeve and is not diffusion |
The comparison is part of the contract. A different numerator, denominator, component universe, weighting rule, tolerance, or signal horizon is not a cosmetic option—it defines a different series.
Implementation walkthrough
The reference algorithm validates before aggregating:
validate a fixed set of provider/methodology-identified factor sleeves
validate synchronized signal, return basis, currency, horizon, and tolerance
classify each sleeve with strict tolerance boundaries
assign scores 1, 0.5, or 0 and average equal votes
return value, class counts, and sleeve-level trace
Validate provider and methodology identity before arithmetic, preserve sleeve-level classes, and route independence questions to covariance rather than the diffusion score.
Python and TypeScript consume the same JSON fixture and return the same resolved fields. Invalid or incomplete input raises rather than being repaired. The playground deliberately translates its failure fixture into a visible withheld state because its job is to teach the refusal boundary.
Guided lab
Open the guided playground. Start from the informative canonical state, switch to Comparison, then Failure / boundary. Use Back and Step to inspect how each component enters the result. Change the tolerance and compare broad factor participation, a split panel, and an incomplete sleeve set. Reset restores the exact canonical state, and reduced-motion Play advances one deterministic observation without starting a timer.
The calculation flow shows why point-in-time validation precedes aggregation.
Put the diagnostic into an operating workflow
Use the panel to ask whether a declared signal is improving across the same strategy sleeves. Pair it with holdings-overlap or covariance analysis before making any statement about diversification.
A robust dashboard retains the input snapshot, formula version, parameters, component trace, and refusal reason. It should make methodology or taxonomy changes visible as breaks in series identity rather than quietly splicing them into history.
Edge cases and misuse boundaries
Do not imply independence among factors, mix provider constructions, or call a high reading a forecast of aggregate market return. Missing components are neither zero nor unchanged. A different roster, taxonomy, factor provider, share-class policy, currency, return basis, horizon, or tolerance defines a different series.
Main takeaway: Cross-factor participation is useful, but equal votes across overlapping sleeves are not independent bets.
Passing implementation tests proves that the code matches the selected definition. It does not prove association with future returns, usefulness after costs, causation, or suitability for an investment decision.
Evidence and historical boundary
The source records in REFERENCES.md establish only the claims mapped to them. They do not establish the synthetic numbers or silently define this package's translated universe and parameters.
A named historical case is deferred until fixed licensed factor-sleeve methodologies, complete same-basis signals, availability timestamps, holdings-overlap evidence, revisions, and redistribution permission. Deferral is a publication boundary, not a missing-data invitation: the public tutorial uses a transparent synthetic case rather than an irreproducible observed value.
Summary and handoff
You can now calculate D_{\mathrm{factor}}=100\frac{N_+ + 0.5N_0}{N}, identify the series-defining choices, interpret its edge regimes, preserve the audit trace, and reject incomplete snapshots. Continue with Covariance.
Primary sources and exact limitations are recorded in REFERENCES.md.
Rendered from the canonical Mermaid sources linked by this article.
Calculation Flow — Factor Diffusion Index
Purpose: validate series identity before producing the diagnostic.
Takeaway: Missing evidence is a state, never a zero contribution or neutral component.
ReferencesPrimary sources and evidence notesExpand the source trail, evidence role, and limitations behind the engineering choices.
Expand the source trail, evidence role, and limitations behind the engineering choices.
Claim-to-source map
| Material claim | Evidence | Classification |
|---|---|---|
| Diffusion can score increase/unchanged/decrease as 1/0.5/0 | TCB-DIFF | sourced transform |
| Named factor sleeves are rules-based provider objects | MSCI-FACTORS | sourced provider scope |
| Equal sleeve votes and the 0.2% tolerance | definition contract | package application and parameter choice |
| Canonical values | datasets/canonical-fixture.json | synthetic input and author-derived calculation |
Every external source ID mapped above is expanded below. Provider or institutional conventions are not presented as universal laws; package translations and parameters remain labelled as implementation choices.
TCB-DIFF — How to Compute Diffusion Indexes
- Organization or authors: The Conference Board
- Source type: Institutional technical methodology
- Publication or effective date: 2012 technical-note convention
- Version: Web methodology accessed 2026-07-26
- URL or DOI: https://www.conference-board.org/data/bci/index.cfm?id=2180
- Accessed: 2026-07-26
- Jurisdiction: Global methodology unless the limitation states otherwise
- Supports: Diffusion scoring of 1 for increase, 0.5 for unchanged, 0 for decrease, divided by component count and multiplied by 100.
- Limitations: The source applies the convention to business-cycle components; sector and factor application here is an explicit package choice.
MSCI-FACTORS — MSCI Factor Indexes
- Organization or authors: MSCI
- Source type: Official index-provider overview
- Publication or effective date: Current page accessed 2026-07-26
- Version: Current web overview
- URL or DOI: https://www.msci.com/indexes/factor-indexes/msci-factor-indexes
- Accessed: 2026-07-26
- Jurisdiction: Global methodology unless the limitation states otherwise
- Supports: Factor indexes are rules-based and may represent Value, Low Size, Low Volatility, High Yield, Quality, Momentum, and Growth.
- Limitations: Does not define a Factor Diffusion Index; the cross-factor diffusion transform is package-selected and must not be attributed to MSCI.
Full dependency-light reference implementations in both supported languages.
type Row = Record<string, unknown>;
const numberValue = (value: unknown, name: string): number => {
if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${name} must be a finite number`);
return value;
};
const validateRows = (rows: Row[], weighted: boolean): void => {
if (!rows.length) throw new Error("rows must not be empty");
const seen = new Set<string>();
for (const row of rows) {
const key = row[weighted ? "security_id" : "component_id"];
if (typeof key !== "string" || !key || seen.has(key)) throw new Error("component identifiers must be nonempty and unique");
seen.add(key);
if (row.ready === false) throw new Error("incomplete_component");
}
};
export function calculate(rows: Row[], tolerance = 0.002) {
validateRows(rows, false); tolerance=numberValue(tolerance,"tolerance");
if (tolerance < 0) throw new Error("tolerance must be nonnegative");
const changes=rows.map(row=>numberValue(row.signal_change,"signal_change"));
const improving=changes.filter(x=>x>tolerance).length, deteriorating=changes.filter(x=>x < -tolerance).length, unchanged=rows.length-improving-deteriorating;
return {status:"resolved", value:100*(improving+0.5*unchanged)/rows.length, improving, unchanged, deteriorating, total:rows.length};
}
The embedded lab now expands to its full document height, keeping the article as the only scroll surface.