# Weighted Signal Computation

```mermaid
flowchart TD
    DOC["Document Signal Input\n(published_at, source_credibility,\nnovelty_score, extraction_confidence,\nmarket_ctx)"]

    DOC --> GATE
    DOC --> REC
    DOC --> CRED
    DOC --> NOV
    DOC --> MKT

    subgraph GATE["Confidence Gate"]
        G1["extraction_confidence ≥ 0.2?"]
        G1 -->|"Yes"| G2["gate = 1.0"]
        G1 -->|"No"| G3["gate = 0.0\n(signal zeroed out)"]
    end

    subgraph REC["Recency Decay"]
        R1["w = 2^(−age_hours / half_life)"]
        R2["Half-lives per window:\nintraday: 2h\n1d: 12h\n7d: 72h\n30d: 240h\n90d: 720h"]
        R3["Floor: min_recency_weight = 0.01"]
        R1 --- R2
        R1 --- R3
    end

    subgraph CRED["Source Credibility"]
        C1["Clamp to [0.1, 1.0]"]
        C2["Apply exponent\n(default 1.0)"]
        C1 --> C2
    end

    subgraph NOV["Novelty Bonus"]
        N1["bonus = novelty_score × 0.25"]
        N2["Range: [0.0, 0.25]\n(up to 25% boost)"]
        N1 --- N2
    end

    subgraph MKT["Environmental Context Multiplier"]
        M1["Volatility boost\nlog₁₊(excess) × 0.15\ncapped at 0.30"]
        M2["Volume surge boost\nvolume_change > 50% → +0.15"]
        M3["multiplier = 1.0 + boost\n(always ≥ 1.0)"]
        M1 --> M3
        M2 --> M3
    end

    GATE --> FORMULA
    REC --> FORMULA
    CRED --> FORMULA
    NOV --> FORMULA
    MKT --> FORMULA

    FORMULA["combined = gate × recency × credibility\n× (1 + novelty_bonus)\n× market_context_multiplier"]

    FORMULA --> SW["SignalWeight\nservices/aggregation/scoring.py"]

    SW --> WS["WeightedSignal\n{ document_id, weight: SignalWeight,\nsentiment_value, impact_score }"]
```
