import { ScoringRules } from '../config/ScoringConfig.js'; import { MarketRegime } from '../market/MarketRegime.js'; import { SCORE_MODE } from '../config/constants.js'; import type { AssetType, MarketContext } from '../types.js'; interface RuleSet { gates: Record; weights: Record; thresholds: Record; } export const RuleMerger = { getRulesForAsset( type: AssetType, metrics: { sector?: string }, marketContext: Partial = {}, mode: string = SCORE_MODE.FUNDAMENTAL, ): RuleSet { const base = ScoringRules[type as keyof typeof ScoringRules]; if (!base) throw new Error(`No rules configured for asset type: ${type}`); // Deep clone to avoid mutating the source config const rules: RuleSet & { SECTOR_OVERRIDE?: unknown } = JSON.parse(JSON.stringify(base)); if (type === 'STOCK' && metrics.sector) { const stockBase = ScoringRules.STOCK; const override = stockBase.SECTOR_OVERRIDE?.[ metrics.sector.toUpperCase() as keyof typeof stockBase.SECTOR_OVERRIDE ]; if (override) { rules.gates = { ...rules.gates, ...override.gates }; rules.weights = { ...rules.weights, ...override.weights }; rules.thresholds = { ...rules.thresholds, ...override.thresholds }; } } delete rules.SECTOR_OVERRIDE; if (mode === SCORE_MODE.INFLATED) { const { gates, thresholds } = new MarketRegime( marketContext as MarketContext, ).getInflatedOverrides(type, metrics.sector); rules.gates = { ...rules.gates, ...gates }; rules.thresholds = { ...rules.thresholds, ...thresholds }; } return rules; }, };