Spread trade targets across distance bands
MKC showed 5 targets all far/Aggressive: target selection was top-5 by quality (0.35*R:R + ...), and R:R grows with distance, so far levels crowded out every nearby one. generate_targets now selects for spread: always include the nearest level, plus the best-quality representative from each distance band (Conservative <=2.9 ATR, Moderate <=4.6 ATR, Aggressive beyond), then fill remaining slots by quality. Restores a Conservative/Moderate/ Aggressive mix with the nearest target always present. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,32 @@ def test_generate_targets_respects_direction_and_order():
|
||||
assert distances == sorted(distances)
|
||||
|
||||
|
||||
def test_generate_targets_spreads_across_distance_bands():
|
||||
"""Near levels must not be crowded out by far high-R:R ones — expect a mix
|
||||
of distance bands, including the nearest, not just the 5 farthest."""
|
||||
# entry 100, atr 2 → ATR multiples: 5→2.5, 8→4.0, 14→7.0, 24→12, 34→17, 44→22
|
||||
sr_levels = [
|
||||
_SRLevelStub(id=1, price_level=105.0, type="resistance", strength=60), # 2.5 ATR (conservative)
|
||||
_SRLevelStub(id=2, price_level=108.0, type="resistance", strength=55), # 4.0 ATR (moderate)
|
||||
_SRLevelStub(id=3, price_level=114.0, type="resistance", strength=90), # 7.0 ATR (aggressive, strong)
|
||||
_SRLevelStub(id=4, price_level=124.0, type="resistance", strength=95), # 12 ATR (aggressive, strong)
|
||||
_SRLevelStub(id=5, price_level=134.0, type="resistance", strength=92), # 17 ATR (aggressive, strong)
|
||||
_SRLevelStub(id=6, price_level=144.0, type="resistance", strength=88), # 22 ATR (aggressive, strong)
|
||||
]
|
||||
|
||||
targets = target_generator.generate_targets(
|
||||
direction="long", entry_price=100.0, stop_loss=96.0,
|
||||
sr_levels=sr_levels, atr_value=2.0, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
multiples = [t["distance_atr_multiple"] for t in targets]
|
||||
# The nearest (conservative) and a moderate target survive despite the
|
||||
# strong far levels that would dominate a pure top-5-by-quality pick.
|
||||
assert any(m <= 2.9 for m in multiples), "expected a conservative (near) target"
|
||||
assert any(2.9 < m <= 4.6 for m in multiples), "expected a moderate target"
|
||||
assert any(m > 4.6 for m in multiples), "expected an aggressive (far) target"
|
||||
|
||||
|
||||
def test_probability_decreases_with_distance():
|
||||
"""A far target must be far less likely than a near one — no 90% at +39%."""
|
||||
config = {
|
||||
|
||||
Reference in New Issue
Block a user