Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 1x 1x 18x 18x 18x 18x 18x 18x 18x 33x 33x 33x 33x 33x 31x 2x 33x 27x 6x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 33x 18x | /**
* JointConfidenceCalibrator — Bayesian fusion of detection + forecast signals.
*
* jointConfidence = α·grade + β·(1 - spread) + γ·hitRate + δ·driftPenalty
*/
import type { ICalibrator, DetectionResult, ForecastResult, DataPoint, CalibrationResult, CalibrationMode } from '../types.js'
import { HitRateTracker, clamp } from './forecast-guided.js'
export interface JointWeights { grade: number; spread: number; hitRate: number; drift: number }
export class JointConfidenceCalibrator implements ICalibrator {
readonly mode: CalibrationMode = 'joint'
private weights: JointWeights
private hitTracker = new HitRateTracker()
constructor(weights?: Partial<JointWeights>) {
this.weights = { grade: 0.4, spread: 0.3, hitRate: 0.2, drift: 0.1, ...weights }
}
calibrate(detection: DetectionResult, forecast: ForecastResult, currentPoint: DataPoint): CalibrationResult {
const predicted = forecast.predicted[0] ?? currentPoint.value
const q10 = forecast.q10[0] ?? predicted
const q90 = forecast.q90[0] ?? predicted
const spread = q90 - q10
const normalizedSpread = Math.abs(currentPoint.value) > 1e-10
? Math.min(spread / Math.abs(currentPoint.value), 1)
: 0
const residual = spread > 1e-10
? Math.abs(currentPoint.value - predicted) / (spread / 2)
: Math.abs(currentPoint.value - predicted)
const hitRate = this.hitTracker.getHitRate()
const driftPenalty = detection.driftDetected ? -1 : 0
const joint =
this.weights.grade * detection.grade +
this.weights.spread * (1 - normalizedSpread) +
this.weights.hitRate * hitRate +
this.weights.drift * driftPenalty
const jointConfidence = clamp(joint, 0, 1)
this.hitTracker.record(jointConfidence > 0.7, jointConfidence)
return {
mode: 'joint',
residual,
jointConfidence,
intervalBreached: residual > 1,
}
}
}
|