Finalize GTL and retire S/R research harness
This commit is contained in:
@@ -6,14 +6,12 @@ from app.services.sr_service import (
|
||||
MAX_LEVELS,
|
||||
_bar_respect_weight,
|
||||
_cap_levels,
|
||||
_legacy_range_grid_nodes,
|
||||
_legacy_volume_profile_nodes,
|
||||
_gate_target_range_centers,
|
||||
_merge_levels,
|
||||
_round_number_candidates,
|
||||
_strength_from_respects,
|
||||
detect_gate_target_ladder,
|
||||
detect_sr_levels,
|
||||
detect_sr_levels_legacy,
|
||||
)
|
||||
|
||||
|
||||
@@ -237,134 +235,26 @@ class TestDetectSrLevels:
|
||||
pinned = sum(1 for lvl in levels if lvl["strength"] == 100)
|
||||
assert pinned < len(levels)
|
||||
|
||||
def test_legacy_control_retains_old_uncapped_grid(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
levels = detect_sr_levels_legacy(highs, lows, closes, volumes)
|
||||
assert levels
|
||||
assert all(level["sources"] for level in levels)
|
||||
# The research control intentionally keeps the deployed detector's much
|
||||
# denser output instead of borrowing the rewrite's presentation cap.
|
||||
def test_gate_target_range_centers_cover_the_observed_range(self):
|
||||
highs, lows, closes, _ = _make_series(n=500)
|
||||
centers = _gate_target_range_centers(highs, lows, closes)
|
||||
|
||||
assert len(centers) == 20
|
||||
assert centers == sorted(centers)
|
||||
assert min(lows) < centers[0] < centers[-1] < max(highs)
|
||||
|
||||
def test_gate_target_ladder_is_dense_transient_price_traffic(self):
|
||||
highs, lows, closes, _ = _make_series(n=500)
|
||||
levels = detect_gate_target_ladder(highs, lows, closes)
|
||||
|
||||
assert len(levels) > MAX_LEVELS
|
||||
assert any("range_grid" in level["sources"] for level in levels)
|
||||
assert all("volume_profile" not in level["sources"] for level in levels)
|
||||
assert all(0 <= level["strength"] <= 100 for level in levels)
|
||||
assert all(level["rejection_count"] >= 0 for level in levels)
|
||||
|
||||
def test_legacy_geometry_neutral_changes_only_strength(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
control = detect_sr_levels_legacy(highs, lows, closes, volumes)
|
||||
neutral = detect_sr_levels_legacy(
|
||||
highs, lows, closes, volumes, neutral_strength=True
|
||||
def test_gate_target_ladder_is_deterministic(self):
|
||||
highs, lows, closes, _ = _make_series(n=500)
|
||||
assert detect_gate_target_ladder(highs, lows, closes) == (
|
||||
detect_gate_target_ladder(list(highs), list(lows), list(closes))
|
||||
)
|
||||
assert [level["price_level"] for level in neutral] == [
|
||||
level["price_level"] for level in sorted(
|
||||
control, key=lambda row: row["price_level"]
|
||||
)
|
||||
]
|
||||
assert all(level["strength"] == 50 for level in neutral)
|
||||
|
||||
def test_legacy_source_ablation_isolates_candidates(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
pivots = detect_sr_levels_legacy(
|
||||
highs, lows, closes, volumes, include_volume_profile=False
|
||||
)
|
||||
traffic = detect_sr_levels_legacy(
|
||||
highs, lows, closes, volumes, include_pivots=False
|
||||
)
|
||||
assert pivots and traffic
|
||||
assert all(level["sources"] == ["pivot_point"] for level in pivots)
|
||||
assert all(level["sources"] == ["volume_profile"] for level in traffic)
|
||||
|
||||
def test_legacy_profile_union_matches_explicit_range_grid(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
deployed = _legacy_volume_profile_nodes(highs, lows, closes, volumes)
|
||||
explicit = _legacy_range_grid_nodes(highs, lows, closes)
|
||||
assert sorted(deployed) == explicit
|
||||
assert len(explicit) == 20
|
||||
|
||||
def test_explicit_target_ladder_preserves_full_legacy_mechanics(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
deployed = detect_sr_levels_legacy(highs, lows, closes, volumes)
|
||||
explicit = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
volumes,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
|
||||
def mechanics(level):
|
||||
return {
|
||||
key: value
|
||||
for key, value in level.items()
|
||||
if key not in {"detection_method", "sources"}
|
||||
}
|
||||
|
||||
assert [mechanics(level) for level in explicit] == [
|
||||
mechanics(level) for level in deployed
|
||||
]
|
||||
assert any("range_grid" in level["sources"] for level in explicit)
|
||||
assert all("volume_profile" not in level["sources"] for level in explicit)
|
||||
|
||||
def test_gate_target_ladder_is_the_explicit_volume_free_detector(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
expected = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
volumes,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
|
||||
assert detect_gate_target_ladder(highs, lows, closes) == expected
|
||||
|
||||
def test_explicit_range_grid_is_volume_independent(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
shifted_volumes = [volume * (i + 1) for i, volume in enumerate(volumes)]
|
||||
baseline = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
volumes,
|
||||
include_pivots=False,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
shifted = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
shifted_volumes,
|
||||
include_pivots=False,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
assert shifted == baseline
|
||||
|
||||
def test_explicit_range_grid_neutral_changes_only_strength(self):
|
||||
highs, lows, closes, volumes = _make_series(n=500)
|
||||
touch = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
volumes,
|
||||
include_pivots=False,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
neutral = detect_sr_levels_legacy(
|
||||
highs,
|
||||
lows,
|
||||
closes,
|
||||
volumes,
|
||||
include_pivots=False,
|
||||
neutral_strength=True,
|
||||
explicit_range_grid=True,
|
||||
)
|
||||
touch_by_price = {level["price_level"]: level for level in touch}
|
||||
neutral_by_price = {level["price_level"]: level for level in neutral}
|
||||
assert neutral_by_price.keys() == touch_by_price.keys()
|
||||
for price, neutral_level in neutral_by_price.items():
|
||||
assert neutral_level["strength"] == 50
|
||||
assert {
|
||||
key: value
|
||||
for key, value in neutral_level.items()
|
||||
if key != "strength"
|
||||
} == {
|
||||
key: value
|
||||
for key, value in touch_by_price[price].items()
|
||||
if key != "strength"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user