import type { Sector } from './constants.js'; // ── Credit rating scale (S&P convention) ───────────────────────────────── // Bond.ts converts letter ratings to these numbers; BondScorer uses them for gate checks. // Investment grade = BBB (7) and above. export const CREDIT_RATING_SCALE: Record = { AAA: 10, AA: 9, A: 8, BBB: 7, BB: 6, B: 5, CCC: 4, CC: 3, C: 2, D: 1, }; // ── Scoring rule shape ──────────────────────────────────────────────────── interface GateSet extends Record {} interface WeightSet extends Record {} interface ThresholdSet extends Record {} interface RuleBlock { gates: GateSet; weights: WeightSet; thresholds: ThresholdSet; } interface StockRules extends RuleBlock { SECTOR_OVERRIDE: Partial>>; } interface ScoringRulesShape { STOCK: StockRules; ETF: RuleBlock; BOND: RuleBlock; } // ───────────────────────────────────────────────────────────────────────────── // Fundamental baseline — Graham / value-investing style. // MarketRegime.ts overrides the valuation gates for INFLATED-mode analysis. // Sector overrides are structural — they apply in both modes. // ───────────────────────────────────────────────────────────────────────────── export const ScoringRules: ScoringRulesShape = { STOCK: { gates: { maxDebtToEquity: 1.5, // Graham ceiling; most distress starts above 2x minQuickRatio: 0.8, // below 0.8 signals real liquidity stress in non-tech maxPERatio: 15, // Graham's actual rule: never pay more than 15x trailing earnings maxPegGate: 1.0, // PEG > 1.0 means you're paying full price for growth (Lynch standard) }, weights: { margin: 2, // net profit margin opMargin: 2, // operating margin (pricing power) roe: 3, // return on equity — Buffett's primary quality metric peg: 2, // valuation relative to growth revenue: 2, // revenue growth fcf: 3, // FCF is the most manipulation-resistant quality signal }, thresholds: { marginHigh: 15, // 15% net margin is genuinely excellent across most sectors marginMed: 8, // 8% is the realistic mid-tier for industrials/retail opMarginHigh: 20, opMarginMed: 10, roeHigh: 15, // sustainable 15% ROE is Buffett-quality; 20% is rare/fleeting roeMed: 10, // 10% is the cost-of-equity floor for most businesses pegHigh: 0.75, // PEG < 0.75 is genuinely cheap relative to growth pegMed: 1.0, revHigh: 10, // 10% organic revenue growth is strong for mature cos revMed: 5, fcfHigh: 5, fcfMed: 2, }, SECTOR_OVERRIDE: { TECHNOLOGY: { gates: { maxDebtToEquity: 2.0, minQuickRatio: 0.8, maxPERatio: 35, maxPegGate: 1.5 }, weights: { margin: 1, opMargin: 3, roe: 3, peg: 3, revenue: 4, fcf: 3 }, thresholds: { marginHigh: 25, opMarginHigh: 25, roeHigh: 20, pegHigh: 1.0, revHigh: 20 }, }, REIT: { gates: { maxDebtToEquity: 6.0, minQuickRatio: 0.1, maxPERatio: 9999, maxPegGate: 9999 }, weights: { margin: 0, opMargin: 0, roe: 0, peg: 0, revenue: 0, fcf: 0, yield: 5, pFFO: 3 }, thresholds: { minYield: 4.5, maxPFFO: 20 }, }, FINANCIAL: { gates: { maxDebtToEquity: 9999, minQuickRatio: 0.1, maxPERatio: 9999, maxPegGate: 9999, maxPriceToBook: 1.5, }, weights: { margin: 0, opMargin: 0, peg: 0, roe: 5, revenue: 1, fcf: 1, priceToBook: 3 }, thresholds: { roeHigh: 15, roeMed: 12, revHigh: 10, revMed: 5 }, }, ENERGY: { gates: { maxDebtToEquity: 1.5, minQuickRatio: 0.6, maxPERatio: 15, maxPegGate: 1.5 }, weights: { margin: 0, opMargin: 3, roe: 2, peg: 1, revenue: 2, fcf: 4, yield: 3 }, thresholds: { opMarginHigh: 20, opMarginMed: 10, roeHigh: 15, roeMed: 8, fcfHigh: 8, fcfMed: 4, }, }, HEALTHCARE: { gates: { maxDebtToEquity: 1.5, minQuickRatio: 1.0, maxPERatio: 25, maxPegGate: 1.5 }, weights: { margin: 1, opMargin: 2, roe: 2, peg: 2, revenue: 4, fcf: 3 }, thresholds: { marginHigh: 20, marginMed: 10, roeHigh: 20, roeMed: 12, revHigh: 15, revMed: 8, fcfHigh: 8, fcfMed: 3, }, }, COMMUNICATION: { gates: { maxDebtToEquity: 2.0, minQuickRatio: 0.8, maxPERatio: 25, maxPegGate: 1.5 }, weights: { margin: 2, opMargin: 3, roe: 2, peg: 2, revenue: 3, fcf: 4 }, thresholds: { marginHigh: 25, marginMed: 12, opMarginHigh: 30, opMarginMed: 15, roeHigh: 20, roeMed: 12, pegHigh: 1.0, pegMed: 1.5, revHigh: 15, revMed: 5, fcfHigh: 8, fcfMed: 3, }, }, CONSUMER_STAPLES: { gates: { maxDebtToEquity: 1.5, minQuickRatio: 0.5, maxPERatio: 22, maxPegGate: 2.0 }, weights: { margin: 3, opMargin: 3, roe: 3, peg: 1, revenue: 1, fcf: 3 }, thresholds: { marginHigh: 12, marginMed: 7, opMarginHigh: 18, opMarginMed: 10, roeHigh: 20, roeMed: 12, pegHigh: 1.5, pegMed: 2.0, revHigh: 5, revMed: 2, fcfHigh: 5, fcfMed: 2, }, }, CONSUMER_DISCRETIONARY: { gates: { maxDebtToEquity: 2.0, minQuickRatio: 0.5, maxPERatio: 25, maxPegGate: 1.5 }, weights: { margin: 2, opMargin: 2, roe: 2, peg: 2, revenue: 4, fcf: 3 }, thresholds: { marginHigh: 10, marginMed: 5, opMarginHigh: 15, opMarginMed: 8, roeHigh: 20, roeMed: 12, pegHigh: 1.0, pegMed: 1.5, revHigh: 12, revMed: 5, fcfHigh: 5, fcfMed: 2, }, }, }, }, ETF: { gates: { maxExpenseRatio: 0.2 }, weights: { yield: 2, lowCost: 4, fiveYearReturn: 2 }, thresholds: { minYield: 1.5, maxExpense: 0.05, minVolume: 1_000_000, minFiveYearReturn: 8.0, }, }, BOND: { gates: { minCreditRating: 7 }, // BBB = investment-grade floor weights: { yieldSpread: 3, duration: 2 }, thresholds: { minSpread: 1.5, maxDuration: 7 }, }, };