# Cross-Cutting Synthesis: Hardcoded Values Resolution Strategy

**Task:** Task 9: Cross-Cutting Synthesis and Resolution Strategy  
**Generated:** 2026-03-12  
**Source:** Aggregate audit of tasks 1-8 (Python Constants, CLI/Tools, ClickHouse, Config, Scripts, Backfill/Population, Rust Crates, Symbol Registry)

---

## Executive Summary

This document synthesizes findings from 8 audit tasks identifying hardcoded values that should be sourced from the Symbol Registry (symbols.toml). The audits identified **significant duplication** of threshold defaults and symbol lists across Python, Rust, and shell scripts.

**Key Finding:** The codebase has 250 hardcoded in **40+ locations** across multiple languages, creating maintenance burden and inconsistency risk.

---

## 1. Findings Matrix

### 1.1 Threshold Defaults (decimal basis points)

| Location | Hardcoded Value | Current Source | Should Be |
|----------|-----------------|----------------|-----------|
| `constants.py:DEFAULT_THRESHOLD` | 250 | Local constant | `get_thresholds_for_symbol()[0]` |
| `constants.py:THRESHOLD_PRESETS["medium"]` | 250 | Local dict | Registry or env override |
| `constants.py:THRESHOLD_PRESETS["wide"]` | 500 | Local dict | Registry or env override |
| `constants.py:THRESHOLD_PRESETS["macro"]` | 1000 | Local dict | Registry or env override |
| `config/algorithm.py:default_threshold_decimal_bps` | 250 | Pydantic default | Registry fallback |
| `tools/chart/src/main.rs:59` | 250 | clap default | Env var or registry |
| `clickhouse/cache.py:650` (example) | 250 | Docstring example | N/A (documentation) |
| Rust tests (20+ files) | 250 | Test data | Test fixtures from registry |
| Python scripts (15+ files) | 250 | CLI default | Env var or registry |

### 1.2 Symbol Lists

| Location | Hardcoded Value | Current Source | Should Be |
|----------|-----------------|----------------|-----------|
| `constants.py:TIER1_SYMBOLS` | 17 symbols | Local tuple | `filter_by_tier(1)` |
| Docstrings (various) | BTCUSDT | Example data | Dynamic from registry |

### 1.3 Minimum Thresholds

| Location | Hardcoded Value | Current Source | Should Be |
|----------|-----------------|----------------|-----------|
| `config/population.py:23` | `OPENDEVIATIONBAR_CRYPTO_MIN_THRESHOLD` | Env var (1000) | Per-symbol from registry |
| `constants.py` | No enforcement | N/A | Registry `min_threshold` field |

---

## 2. Registry Capabilities Analysis

### 2.1 Currently Exposed Functions

The symbol registry already provides:

```python
# Available in symbol_registry.py
get_thresholds_for_symbol(symbol: str) -> tuple[int, ...]
get_symbol_entries() -> MappingProxyType[str, SymbolEntry]
get_registered_symbols(tier: int | None = None, ...) -> list[str]
filter_pairs_by_registry(symbols: list[str], ...) -> list[str]
get_effective_start_date(symbol: str) -> str | None
```

### 2.2 SymbolEntry Fields Available

```python
@dataclass
class SymbolEntry:
    symbol: str
    enabled: bool
    asset_class: str      # "crypto", "forex", "equities"
    exchange: str         # "binance", "exness"
    market: str           # "spot", "futures-um", "futures-cm"
    listing_date: date
    effective_start: date | None
    tier: int | None      # 1 = highest liquidity
    min_threshold: int | None  # Per-symbol minimum
    thresholds: tuple[int, ...]  # Explicit thresholds to process
```

### 2.3 Missing Helper Functions

Based on audit findings, these helper functions are **missing** from the registry:

| Function | Purpose | Priority |
|----------|---------|----------|
| `get_default_thresholds()` | Return [250, 500, 750, 1000] as fallback | HIGH |
| `get_tier1_symbols()` | Return all tier=1 symbols | HIGH |
| `get_default_threshold()` | Return 250 as universal default | HIGH |
| `get_min_threshold_for_symbol(symbol)` | Return per-symbol min_threshold with fallback | HIGH |

---

## 3. Implementation Phases

### Phase 1: Quick Wins (Can be done immediately)

1. **Add missing registry helper functions**
   - `get_default_thresholds()` - returns [250, 500, 750, 1000]
   - `get_tier1_symbols()` - returns tier=1 symbols
   - `get_default_threshold()` - returns 250

2. **Update constants.py to delegate**
   ```python
   # New approach
   from opendeviationbar.symbol_registry import get_default_threshold, get_tier1_symbols
   
   DEFAULT_THRESHOLD = get_default_threshold()  # 250
   TIER1_SYMBOLS = get_tier1_symbols()
   ```

3. **Wire config/algorithm.py**
   ```python
   from opendeviationbar.symbol_registry import get_default_threshold
   default_threshold_decimal_bps: int = get_default_threshold()
   ```

### Phase 2: CLI/Tool Integration

1. **Update tools/chart/src/main.rs**
   - Accept threshold via environment variable `OPENDEVIATIONBAR_DEFAULT_THRESHOLD`
   - Default to 250 if not set

2. **Add .mise.toml defaults**
   ```toml
   [env]
   OPENDEVIATIONBAR_DEFAULT_THRESHOLD = "250"
   ```

### Phase 3: Script Migration

1. **Audit all scripts with hardcoded thresholds**
2. **Add env var support to each script**
3. **Document migration in scripts/README.md**

### Phase 4: Test Fixtures

1. **Create test fixtures from registry**
2. **Update Rust test constants**
3. **Eliminate magic numbers in test assertions**

---

## 4. Migration Strategy by Category

### 4.1 Threshold Defaults

**Pattern:** Replace hardcoded `250` with `get_default_threshold()`

```python
# Before
def process_trades(trades, threshold=250):
    ...

# After
from opendeviationbar.symbol_registry import get_default_threshold

def process_trades(trades, threshold=None):
    threshold = threshold or get_default_threshold()
    ...
```

### 4.2 Symbol Lists

**Pattern:** Replace hardcoded tuples with registry queries

```python
# Before
TIER1_SYMBOLS = ("BTC", "ETH", "SOL", ...)

# After
from opendeviationbar.symbol_registry import get_registered_symbols
TIER1_SYMBOLS = get_registered_symbols(tier=1)
```

### 4.3 Per-Symbol Thresholds

**Pattern:** Use registry as source of truth

```python
# Before
if symbol == "BTCUSDT":
    thresholds = [250, 500, 750, 1000]

# After
from opendeviationbar.symbol_registry import get_thresholds_for_symbol
thresholds = get_thresholds_for_symbol(symbol)
```

---

## 5. Recommended Sub-Tasks

Based on this synthesis, the following sub-tasks are recommended:

1. **Add registry helper functions** - Create `get_default_threshold()`, `get_tier1_symbols()`, `get_default_thresholds()`
2. **Update constants.py** - Delegate to registry
3. **Update config/algorithm.py** - Use registry fallback
4. **Update tools/chart** - Add env var support
5. **Audit scripts** - Document all hardcoded values
6. **Create test fixtures** - Centralize test data from registry

---

## 6. Dependencies & Wiring

### Can Be Wired Immediately

- `constants.py:DEFAULT_THRESHOLD` → `symbol_registry.get_default_threshold()`
- `constants.py:TIER1_SYMBOLS` → `symbol_registry.get_registered_symbols(tier=1)`
- `config/algorithm.py` → `symbol_registry.get_default_threshold()`

### Needs Registry Enhancement

- Per-symbol min_threshold enforcement (requires `get_min_threshold_for_symbol()`)
- Asset-class specific defaults (requires `get_default_thresholds_by_asset_class()`)

---

## 7. Summary

| Category | Hardcoded Locations | Ready for Wiring | Needs Work |
|----------|---------------------|------------------|------------|
| Threshold defaults | 40+ | 35 | 5 |
| Symbol lists | 2 | 1 | 1 |
| Min thresholds | 3 | 0 | 3 |
| **Total** | **45+** | **36** | **9** |

**Recommendation:** Implement Phase 1 quick wins immediately (3 helper functions + 2 file updates), then proceed to Phase 2-4 incrementally.

---

*Generated by Task 9: Cross-Cutting Synthesis*
