# Experiment: Wider Hidden Layer (50→32→16→1)

**Status:** Concluded (2026-06-20) — no promotions, bb50 baseline holds  
**Branch:** `feature/approach-b-4h-probe`

---

## Motivation

After exhaustive search with the current `50→16→8→1` architecture, all available levers have been tested:

| Lever | Tried | Result |
|---|---|---|
| More seeds (bb50) | 12 per TF | Ceiling confirmed |
| feat55 (+5 new inputs) | 24 seeds per TF | Zero promotions |
| lean50 (replaced 2 dead slots) | 6 seeds per TF | Zero promotions |
| Wide threshold sweep (±600, 500k samples) | All 5 TFs | Zero new promotions |

The 16-unit first hidden layer produces a weight matrix W1 of shape `[16 × 50]` = 800 parameters. The hypothesis is that this is too narrow to express complex combinations of 50 input features — the model can represent at most 16 independent linear projections of the input before the nonlinearity, which may not be enough to disentangle the macro/on-chain/momentum signals that overlap in the current feature set.

## Proposed Change

Replace the hidden layer shape from `16→8` to `32→16`:

| | Current (bb50) | Proposed (wide32) |
|---|---|---|
| Architecture | `50→16→8→1` | `50→32→16→1` |
| W1 parameters | 16×50 = 800 | 32×50 = 1,600 |
| W2 parameters | 8×16 = 128 | 16×32 = 512 |
| W3 parameters | 1×8 = 8 | 1×16 = 16 |
| Total params | ~940 | ~2,130 |

Parameter count doubles. For the IS window size (~1,700 bars on 4H, ~4,000 on 1D) this is still well within safe territory for a tanh MLP — no regularization change expected to be necessary, but L2 should be monitored.

## Training Plan

- Tag: `wide32`
- Seeds: 101–606 (6 seeds), then extend if promising
- Objectives: `robust` + `mean_min` (same as all previous runs)
- All 5 BTC TFs: 4H, 6H, 8H, 12H, 1D
- Command:
  ```bash
  python3 tools/run_mlp_train.py \
    --assets COINBASE_BTCUSD \
    --tfs 4H 6H 8H 12H 1D \
    --seed-start 101 --seeds 6 \
    --hidden 32 16 \
    --tag wide32 \
    --sweep --promote \
    --notify
  ```

## Pine Changes Required (if wide32 wins)

This is a Phase 2 upgrade and requires careful execution — do NOT start until `mlp_status.py` shows all 5 TFs consistent on `50→32→16→1`.

Static section changes in `strategy_mlp_scores.pine`:

```pine
// W1: [32 × 50] = 1600 values  (was 800 for [16×50])
var float[] _w1 = array.new_float(1600, 0.0)
// b1: [32]  (was 16)
var float[] _b1 = array.new_float(32, 0.0)
// W2: [16 × 32] = 512 values  (was 128 for [8×16])
var float[] _w2 = array.new_float(512, 0.0)
// b2: [16]  (was 8)
var float[] _b2 = array.new_float(16, 0.0)
// W3: [1 × 16] = 16 values  (was 8 for [1×8])
var float[] _w3 = array.new_float(16, 0.0)
// b3: scalar (unchanged)

// Layer 1: 50 → 32  (was 50 → 16)
for _i = 0 to 31   // (was 15)
    ...
    for _j = 0 to 49
        _s1 += array.get(_w1, _i * 50 + _j) * array.get(_x, _j)

// Layer 2: 32 → 16  (was 16 → 8)
for _i = 0 to 15   // (was 7)
    ...
    for _j = 0 to 31  // (was 15)
        _s2 += array.get(_w2, _i * 32 + _j) * array.get(_h1, _j)

// Layer 3: 16 → 1  (was 8 → 1)
for _j = 0 to 15   // (was 7)
    _s3 += array.get(_w3, _j) * array.get(_h2, _j)
```

The `generate_pine_mlp_presets.py` codegen also needs to write 1600+512+16 weights instead of 800+128+8 — check whether it reads arch from the artifact dynamically or has hardcoded sizes.

## Results

6 seeds (101–606) trained across all 5 BTC TFs. Three sweeps run: initial (200k samples), wide-range deep sweep (500k, ±600/±750), focused narrow sweep (500k, entry ±100, exit 40–150 on the single promising 12H candidate). Zero promotions.

| TF | bb50 Calmar | Wide32 best IS Calmar | Δ | Wide32 composite | bb50 composite | OOS | Conclusion |
|---|---|---|---|---|---|---|---|
| 4H | 0.229 | 0.236 | +3% | 1.021 | ~1.6 | 0 trades | No improvement |
| 6H | 0.547 | 0.468 | −14% | 2.597 | 6.048 | — | Worse |
| 8H | 0.727 | 0.847 | +16% IS | 4.891 | 7.057 | 0 trades (down mkt) | See note |
| 12H | 0.869 | 0.493 (confirmed) | −43% | 2.769 | 8.250 | 7 trades, negative | Worse |
| 1D | 2.750 | 1.553 | −44% | 2.483 | 10.641 | — | Worse |

**Pine is unchanged.** No winner CSV was overwritten; `generate_pine_mlp_presets.py` was not run. The active strategy still uses bb50 artifacts on all 5 TFs.

### 8H note — genuine IS gain, neutral OOS

Wide32 8H (seed202) achieved real IS Calmar improvement (+16%) and produced 0 OOS trades during a confirmed sideways/down market period — which for a long-only strategy is neutral, not a failure. The composite shortfall (~4.9 vs bb50's ~7.1) is driven by fewer IS trades (81 vs 105), meaning the model is more selective but not demonstrably more correct in the OOS window we have.

The experiment was concluded rather than extended to 12 seeds on 8H because:
1. All other 4 TFs failed even with the OOS reframe
2. The 12H 8.814 composite (initially promising) was not reproducible under a focused sweep
3. Running 6 more 8H seeds to chase a composite gate is fishing, not systematic validation

The wide32 8H result is the closest thing to a partial win in this experiment and could be revisited if new features are added that give the model more to work with at sub-daily resolution.

## Conclusion

The `50→32→16→1` architecture is not a better architecture for the current feature set. Wider W1 (1,600 vs 800 params) produces more expressive IS representations on some TFs but does not generalize:

- Where IS Calmar improved (8H: +16%), the model learned a more selective signal that sat out the OOS down market rather than trading.
- Where it did take OOS trades (12H: 7 trades), it lost money.
- On 3 of 5 TFs (6H, 12H, 1D) the wider arch was outright worse even IS.

**The architecture class (shallow MLP on pre-normalised features) has reached its ceiling for the current feature set.** The primary lever remaining is a fundamentally different model class or new features with orthogonal predictive power at sub-daily resolution.

Candidates for future exploration (not started):
- **Gradient-boosted trees** (XGBoost/LightGBM): no gradient vanishing, handles mixed signal quality well, interpretable feature importance
- **Attention/transformer encoder**: can learn which features matter per-bar context
- **Recurrent (LSTM/GRU)**: captures sequential state that the MLP's single-bar view misses
- **New features**: order-flow data, funding rates, on-chain at hourly resolution (none currently in the feature set)

## Success Criteria (original)

A wide32 model promotes on any TF with Calmar > the current bb50 baseline. The key baselines:

| TF | bb50 Calmar |
|---|---|
| 4H | 0.229 |
| 6H | 0.547 |
| 8H | 0.727 |
| 12H | 0.869 |
| 1D | 2.750 |

Criteria not met after 6 seeds and three sweep rounds.

## Context

- The current feature set has two recently repaired dead slots: `qqq_spy_roc_sign` and `fear_greed_norm` were hardcoded to `0.0` and replaced with `sopr_norm` and `cvd_norm` (2026-06-20). The lean50 tag reflects models trained with the corrected feature set; these did not beat bb50 baselines.
- The `--wide` flag on `run_mlp_deep_sweep.py` extends threshold ranges to ±600/±750 for future use.
- The supplemental Pine file `strategy_mlp_feature_export.pine` provides a training-only export of 5 additional on-chain signals; these are not yet wired into the production strategy pending proof of benefit.

---

## Priority 2 Re-evaluation (2026-06-20)

Re-ran the full 5-TF deep sweep and a focused 8H sweep with all 6 wide32 seeds under the corrected OOS evaluation framework (0-trade OOS → 0.0, not -10.0).

**Results — unchanged:**
- bb50 wins all 5 TFs by composite; no promotions
- Wide32 8H best: Calmar 0.863, Composite 3.817, P&L/DD 176.7, Fragile_0.05=1, OOS=0 trades/0.0 (92% Bear)
- bb50 8H: Calmar 0.727, Composite 7.057, P&L/DD 434.7, OOS=2 trades/-0.635 Sortino

**Notable:** with corrected OOS, wide32 8H (OOS Sortino 0.0) now ranks better than bb50 (OOS Sortino -0.635) on the OOS axis — but the P&L/DD gate (176.7 < 434.7) and Fragile_0.05 gate remain the binding constraints. Conclusion stands.

**Side finding:** `mvrv_regime` column is inconsistent across TF data files due to Pine export discretization (only 2 discrete mvrv_zscore_value levels: 0.5, 1.0). 8H/12H/1D show 92-99% Bear for OOS period, while 4H/6H show 14-33% Bull — likely a Pine request.security sampling artifact, not a real market divergence.
