# DSF Adaptive Scoring SDK

An **enterprise-grade adaptive credit scoring system** that replaces static risk models and hard-coded rules with a configurable, intelligent decision engine.

---

## 🚀 Why DSF Scoring?

Traditional risk models are static — they're trained once and quickly become outdated, failing to adapt to new market conditions or applicant behaviors.  
The DSF Scoring SDK transforms your credit logic into a **configurable, self-adjusting scoring engine** that evolves based on real-world data and context.

---

## 🧠 Core Concepts

Instead of rigid, static rules (e.g., "DTI must be < 0.4"), DSF lets you define risk policies as weighted **features**.  
The system then evaluates how well each applicant matches an *ideal profile*, producing a dynamic **credit score**.

This shifts your scoring logic from hard-coded rules to a **living configuration** that's easy to maintain and evolve.

---

## ⚙️ Installation

```bash
pip install dsf-scoring-sdk
```

⚠️ **Requires SDK ≥ 1.0.11** (o la versión que incluya override_threshold)

---

## 🧩 Quick Start

### Community Edition (Free)

```python
from dsf_scoring_sdk import CreditScoreClient, LicenseError

config = {
    "monthly_income": {"type": "similarity", "default": 3000, "weight": 1.8, "criticality": 2.0},
    "debt_to_income": {"type": "similarity", "default": 0.3, "weight": 2.5, "criticality": 3.0}
}

applicant = {"monthly_income": 2800, "debt_to_income": 0.42}

try:
    with CreditScoreClient(api_key="dsf_api_prod_XXXXX", tier="community") as client:
        result = client.evaluate(applicant, config)
        print(f"Decision: {result['decision']}")
        print(f"Score: {result['score']:.4f}")
        print(f"Threshold: {result['threshold']}")
except LicenseError as e:
    print(f"License Error: {e}")
```

### Professional Edition (Batch Processing + Metrics + Traces)

```python
from dsf_scoring_sdk import CreditScoreClient

client = CreditScoreClient(
    api_key="dsf_api_prod_XXXXX",
    tier="professional",
    license_key="PRO-2026-12-31-XXXXX-0001"
)

applicants = [
    {"monthly_income": 5000, "debt_to_income": 0.25},
    {"monthly_income": 2100, "debt_to_income": 0.55},
    {"monthly_income": 3100, "debt_to_income": 0.31}
]

results = client.evaluate_batch(applicants, config, enable_trace=True)

print(f"Adaptive Threshold: {results['threshold']:.4f}")
print(f"Batch Decisions: {results['decisions']}")
print(f"Traces: {results['explanation_traces']}")

client.close()
```

### Enterprise Edition (Adaptive Weighting + Advanced Metrics)

```python
from dsf_scoring_sdk import CreditScoreClient

client = CreditScoreClient(
    api_key="dsf_api_prod_XXXXX",
    tier="enterprise",
    license_key="ENT-2026-12-31-XXXXX-0001"
)

result = client.evaluate(applicant, config)
metrics = result.get('metrics', {})

print(f"Evaluations: {metrics['evaluations']}")
print(f"Avg Score: {metrics['avg_score']}")
print(f"Adaptive Weights: {metrics['adaptive_weights']}")
```

---

## 🔍 Explainability Traces

**Available for Professional and Enterprise tiers.**

```python
results = client.evaluate_batch(applicants, config, enable_trace=True)
traces = results["explanation_traces"]
```

**Trace example:**

```python
"0": [
  {"feature": "credit_score", "contribution_pct": 26.22, "similarity": 0.6892},
  {"feature": "debt_to_income", "contribution_pct": 28.30, "similarity": 0.6376},
  {"feature": "employment_months", "contribution_pct": 23.20, "similarity": 1.0000}
]
```

---

## 📊 Tier Comparison

|       Feature          | Community | Professional |   Enterprise |
|------------------------|-----------|--------------|--------------|
| Direct Value Input     |    ✅     |      ✅      |    ✅        |
| Max Batch Size         |     1     |     100      |    500       |
| Max Payload            |   512 KB  |     1 MB     |    2 MB      |
| Model Metrics          |    ❌     |      ✅      |    ✅        |
| Adaptive Threshold     |    ❌     |      ✅      |    ✅        |
| Override Threshold     |    ❌     |      ✅      |    ✅        |
| Explainability Traces  |    ❌     |      ✅      |    ✅        |
| Adaptive Weighting     |    ❌     |      ❌      |    ✅        |
| Adaptive Penalty       |    ❌     |      ✅      |    ✅        |
| Storage                |  memory   |    redis     |    redis     |
| Support                | Community |    Email     | Priority SLA |

---

## 🧬 Enterprise & Professional Features

### 📌 Overriding the Threshold (New)

**Available for Professional and Enterprise tiers.**

Manually set the decision threshold for a specific call, overriding the self-adjusting threshold stored in Redis. This is ideal for specific campaigns, A/B testing, or applying different risk policies to different portfolios.

```python
# The adaptive threshold might be 0.65, but you can force 0.72
results = client.evaluate_batch(
    applicants,
    config,
    override_threshold=0.72
)
```

### Adaptive Feature Weighting (Enterprise Only)

Backend algorithm automatically adjusts feature weights based on data magnitude, blending expert-defined weights with learned weights using an `adjustment_factor` (default 0.3). Prevents model drift and improves resilience to changing market conditions.

### Adaptive Penalty Configuration

Control data quality tolerance with adaptive penalties:

```python
client.evaluate_batch(
    applicants,
    config,
    penalty_config={
        'base': 0.02,           # Base penalty (2%)
        'adaptive': True,       # Enable adaptive mode
        'severity_weight': 0.05 # Penalty per missing critical field
    }
)
```

**How it works:**
- `base`: Fixed penalty applied to all scores
- `adaptive`: When `True`, increases penalty for missing critical fields (criticality > 2.5)
- `severity_weight`: Additional penalty per missing critical field

**Example:** If 3 critical fields are missing: `penalty = 0.02 + (3 × 0.05) = 0.17` (17%)

---

## ⚖️ Default Similarity vs. Optimization

The engine uses an advanced symmetric similarity formula `1 - |v-r| / max(|v|, |r|)` by default.

**Scope:** This is the best **generic and universal** solution for most numerical data, ensuring traceability and scalability.

**Optimization Limit:** For variables with extremely atypical data distributions, or when absolute statistical precision is required, a generic formula may not be sufficient.

### 📌 Best Practice (Getting Optimal Results)

If you want to apply custom similarity or statistical risk calculations (e.g., a *Machine Learning* model with complex curves), bypass the default formula and **use Direct Value Mode**:

1. Calculate the final score (0-1) using your own model/logic
2. Inject the result into the API using `"type": "direct_value"`

This way, you combine the **maximum precision** of your proprietary logic with the **maximum transparency** of our audit engine.

**Example:**

```python
# Your custom ML model
fraud_score = my_fraud_model.predict_proba(features)[0][1]  # 0.0-1.0

# Inject directly
config = {
    "fraud_risk": {
        "type": "direct_value",  # ✅ Bypass similarity calculation
        "weight": 3.0,
        "criticality": 4.0
    }
}

applicant = {"fraud_risk": fraud_score}
```

---

## 🧱 Scoring Feature Examples

### Traditional (Bureau Data)
`credit_score`, `debt_to_income`, `previous_defaults`, `loan_to_value`, `months_since_last_delinquency`

### Alternative (Thin-File)
`monthly_income`, `employment_months`, `education_level`, `rent_to_income_ratio`, `utility_payment_history`

### Hybrid (Model Outputs)
`internal_risk_score`, `fraud_model_score`, `ml_default_probability`

---

## 🤖 Hybrid Model Integration

Integrate machine learning models or third-party risk systems directly into your scoring pipeline.

### FICO + ML Model Example

```python
# 1. Load your internal model
risk_model = load_my_internal_model('risk_v2.pkl')

# 2. Define hybrid configuration
hybrid_config = {
    "fico_score": {
        "type": "similarity",
        "default": 720,
        "weight": 2.0,
        "criticality": 2.0
    },
    "employment_months": {
        "type": "similarity",
        "default": 36,
        "weight": 1.5,
        "criticality": 1.0
    },
    "ml_risk_score": {
        "type": "direct_value",  # ML output goes directly
        "weight": 2.5,
        "criticality": 3.0
    }
}

# 3. Evaluate with hybrid inputs
def evaluate_hybrid_applicant(user_data):
    ml_score = risk_model.predict_proba(user_data)[0][1]
    
    applicant_context = {
        "fico_score": user_data.get('fico'),
        "employment_months": user_data.get('employment_months'),
        "ml_risk_score": ml_score
    }
    
    with CreditScoreClient(api_key="...", tier="professional", license_key="...") as client:
        return client.evaluate(applicant_context, hybrid_config, enable_trace=True)
```

**Benefits:**
- **Configurable Weighting:** Balance ML models, FICO, and alternative data
- **Transparent Decisions:** Every score is auditable with contribution percentages
- **No Retraining:** Adjust model influence dynamically without retraining

---

## 💼 Licensing

Professional and Enterprise tiers enable:
- Adaptive thresholds
- Batch processing
- Real-time metrics
- Explainability traces
- Adaptive feature weighting (Enterprise only)

**Licensing Contact:**  
📧 contacto@dsfuptech.cloud

- **Professional License:** `PRO-YYYY-MM-DD-XXXXX-NNNN`
- **Enterprise License:** `ENT-YYYY-MM-DD-XXXXX-NNNN`

---

## 🧩 Example Use Cases

### Thin-File Lending (No Credit History)

```python
config = {
    "monthly_income": {"type": "similarity", "default": 3500, "weight": 2.0, "criticality": 2.0},
    "employment_months": {"type": "similarity", "default": 24, "weight": 1.5, "criticality": 1.5},
    "rent_to_income_ratio": {"type": "similarity", "default": 0.3, "weight": 2.0, "criticality": 2.5},
    "utility_payments_on_time": {"type": "similarity", "default": 1.0, "weight": 1.0, "criticality": 3.0}
}
```

### Traditional Lending + ML Enhancement

```python
config = {
    "credit_score": {"type": "similarity", "default": 700, "weight": 2.5, "criticality": 3.0},
    "debt_to_income": {"type": "similarity", "default": 0.35, "weight": 2.0, "criticality": 2.0},
    "ml_default_risk": {"type": "direct_value", "weight": 2.0, "criticality": 2.5}
}
```

---

## 📊 Model Metrics (Pro & Enterprise)

```python
{
  "evaluations": 100,
  "avg_score": 0.6814,
  "threshold": 0.6729,
  "tier": "professional",
  "storage": "redis"
}
```

### Enterprise Additional Metrics

```python
{
  "min_score": 0.5234,
  "max_score": 0.8901,
  "adaptive_weights": True,
  "adjustment_factor": 0.3
}
```

---

## 🧾 API Reference

### CreditScoreClient

```python
CreditScoreClient(
    api_key: str,
    license_key: Optional[str] = None,
    tier: str = "community",
    base_url: Optional[str] = None,
    timeout: int = 30
)
```

### Methods

- **`evaluate(applicant, config, enable_trace=False, override_threshold=None)`** - Evaluate a single applicant
- **`evaluate_batch(applicants, config, enable_trace=False, override_threshold=None)`** - Evaluate multiple applicants (Pro/Enterprise)
- **`close()`** - Close the HTTP session

Supports `with CreditScoreClient(...) as client:` context usage.

### Config Structure

```python
config = {
    "feature_name": {
        "type": "similarity" | "direct_value",  # ✅ New in 1.0.9
        "default": <ideal_value>,  # Required for similarity type
        "weight": <float, 1.0–5.0>,
        "criticality": <float, 1.0–5.0>
    }
}
```

---

## 🧮 Migration from Static Rules

### Before (Blackbox ML)

```python
# Opaque model
risk_score = ml_model.predict(features)
# ❌ Can't explain why
```

### After (Explainable + Hybrid)

```python
config = {
    "ml_model_output": {"type": "direct_value", "weight": 2.0, "criticality": 2.5},
    "credit_score": {"type": "similarity", "default": 720, "weight": 2.0, "criticality": 2.0}
}

result = client.evaluate(applicant, config, enable_trace=True)
# ✅ Full audit trail: "ML contributed 42%, FICO contributed 38%"
```

---

## 📞 Support

**Issues:** contacto@dsfuptech.cloud  
**Professional/Enterprise Support:** contacto@dsfuptech.cloud

---

## License

Community Edition is free for evaluation and low-volume use. Professional and Enterprise tiers are subject to commercial licensing terms.

© 2025 DSF UpTech. Created by Jaime Alexander Jimenez.  
Powered by Adaptive Formula technology.
