Ctrl K
ComunidadGuías…

docs/diagrams/scoring-engine.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Scoring Engine

```mermaid
flowchart TB
    subgraph Input[Scoring Input]
        DOMAIN["domain, sld, tld<br/>renewalCost (optional)"]
    end

    subgraph Signals[4 Signal Computation]
        direction TB
        IS[Intrinsic Signal<br/>length, pronounceability<br/>hyphens/numbers penalty<br/>TLD bonus]
        CS[Commercial Signal<br/>keyword volume × CPC<br/>via KeywordProvider]
        MS[Market Signal<br/>comparable NameBio sales<br/>via CompsProvider]
        ES[Expiry Signal<br/>domain age, backlinks<br/>Wayback history]
    end

    subgraph Weighting[Dynamic Weight Resolution]
        AVAIL[SignalAvailability<br/>which signals have data?]
        WEIGHTS["resolveEffectiveWeights()<br/>redistribute weights<br/>from missing → available signals"]
        THOLDS["computeEffectiveThresholds()<br/>adjust recommend/confidence<br/>gates based on coverage"]
    end

    subgraph Core[Score Computation]
        WSUM["weightedScore =<br/>Σ(signal_score × effective_weight)"]
        CONF["confidence =<br/>f(coverage, intrinsic_quality)"]
        EV["expectedValue =<br/>weightedScore × baseMarketValue ×<br/>(1 + medianSalePrice / baseMV × 0.5)"]
        BUYMAX["suggestedBuyMax =<br/>min(EV × buyMaxRatio - holdingCost,<br/>absoluteCap)"]
        LISTPRICE["suggestedListPrice =<br/>expectedValue × listPriceMultiplier"]
    end

    subgraph Verdict[Buy / Pass Decision]
        RECOMMEND["recommended =<br/>confidence ≥ confidenceThreshold<br/>AND weightedScore ≥ recommendThreshold"]
    end

    subgraph Output[ScoreResult]
        OR["expected_value, confidence<br/>suggested_buy_max, suggested_list_price<br/>bidRange: {conservative, aggressive}<br/>breakdown: {intrinsic, commercial, market, expiry}<br/>effectiveWeights, signalStatus"]
    end

    Input --> IS
    Input --> CS
    Input --> MS
    Input --> ES

    IS --> AVAIL
    CS --> AVAIL
    MS --> AVAIL
    ES --> AVAIL

    AVAIL --> WEIGHTS
    AVAIL --> THOLDS

    IS --> WSUM
    CS --> WSUM
    MS --> WSUM
    ES --> WSUM

    WEIGHTS --> WSUM
    THOLDS --> RECOMMEND
    IS --> CONF
    AVAIL --> CONF

    WSUM --> EV
    EV --> BUYMAX
    EV --> LISTPRICE
    EV --> RECOMMEND
    CONF --> RECOMMEND
    CONF --> BUYMAX

    BUYMAX --> OR
    LISTPRICE --> OR
    EV --> OR
    CONF --> OR
    WSUM --> OR
    RECOMMEND --> OR

    style Input fill:#1a1a2e,stroke:#16213e,color:#eee
    style Signals fill:#16213e,stroke:#0f3460,color:#eee
    style Weighting fill:#0f3460,stroke:#533483,color:#eee
    style Core fill:#16213e,stroke:#533483,color:#eee
    style Verdict fill:#2d1b69,stroke:#533483,color:#eee
    style Output fill:#1a1a2e,stroke:#16213e,color:#eee
```

## Signal Details

| Signal | Computation | Data Source | Conservative Tuning |
|--------|-------------|-------------|-------------------|
| **Intrinsic** | Domain length score + pronounceability + hyphen/numbers penalty + TLD bonus | Local heuristics | TLD bonus multiplies (0.4-1.0); hyphen and digit penalties floor the score |
| **Commercial** | Search volume × CPC (normalised) | `KeywordProvider` | Falls back to 0 (no boost) if provider unavailable |
| **Market** | Comparable sales median + recency-weighted average | `CompsProvider` | Falls back to 0; strong signal when available but capped |
| **Expiry** | Age decile + backlinks log-scaled + Wayback age | Closeout CSV import | Only fires for expired/closeout domains |

## Weight Redistribution

When one or more signals lack data, their weight is redistributed proportionally
among the available signals. The intrinsic signal always retains at least its
base weight (no redistribution below the intrinsic floor). This ensures the
engine never produces a score from zero data.

## Confidence Formula

```
coverage = intrinsic_weight +
           (commercial_available ? commercial_weight : 0) +
           (market_available ? market_weight : 0) +
           (expiry_available ? expiry_weight : 0)

signal_confidence = (coverage - intrinsic_min) / (1 - intrinsic_min)
                    × (confidence_cap - confidence_base)
                    × (1 - intrinsic_quality_influence)

quality_boost = intrinsic_score × intrinsic_quality_influence
                × (confidence_cap - confidence_base)

confidence = min(confidence_cap, confidence_base + signal_confidence + quality_boost)
```