Add `marginal_gate_active` to paper_book — reuses book_allocator's `_marginal_prune` to bench has-history sleeves only when removing them raises trailing book Sharpe, keeping anticorrelated hedges. Cold sleeves and <2-has-history cases pass through unchanged. TDD (4 unit tests green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
27 lines
1.3 KiB
Python
27 lines
1.3 KiB
Python
from fxhnt.application.paper_book import marginal_gate_active
|
|
|
|
def _series(vals, start=1):
|
|
return {start + i: v for i, v in enumerate(vals)}
|
|
|
|
def test_benches_dead_non_diversifying_sleeve():
|
|
good = _series([0.02, 0.01, 0.03, 0.00] * 15) # positive-mean, real Sharpe
|
|
dead = _series([-0.02, -0.01, -0.03, 0.00] * 15) # negative-mean, drags the book
|
|
kept = marginal_gate_active({"good": good, "dead": dead}, ["good", "dead"])
|
|
assert "good" in kept and "dead" not in kept
|
|
|
|
def test_keeps_both_diversifying_sleeves():
|
|
a = _series([0.03, 0.01] * 30) # both positive-mean, anti-phase -> diversify
|
|
b = _series([0.01, 0.03] * 30)
|
|
kept = marginal_gate_active({"a": a, "b": b}, ["a", "b"])
|
|
assert set(kept) == {"a", "b"}
|
|
|
|
def test_cold_sleeve_passes_through_and_no_pruning_under_two_history():
|
|
good = _series([0.02, 0.01] * 30)
|
|
kept = marginal_gate_active({"good": good, "new": {1: 0.01}}, ["good", "new"]) # only 1 has-history
|
|
assert kept == ["good", "new"] # <2 has-history -> unchanged, order preserved
|
|
|
|
def test_never_empty_and_preserves_input_order():
|
|
a = _series([0.02, 0.01] * 30); b = _series([0.015, 0.02] * 30)
|
|
kept = marginal_gate_active({"a": a, "b": b}, ["a", "b"])
|
|
assert kept and kept == [s for s in ["a", "b"] if s in kept]
|