67 lines
2.7 KiB
Python
67 lines
2.7 KiB
Python
import os
|
|
import unittest
|
|
|
|
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://user:pass@localhost:5432/ai_ict_test")
|
|
|
|
from src.services.targets import (
|
|
TARGET_PLAN_STATUS_INCOMPLETE,
|
|
TARGET_PLAN_STATUS_READY,
|
|
TargetSelectionService,
|
|
has_complete_structural_target_plan,
|
|
)
|
|
|
|
|
|
class TargetSelectionServiceTests(unittest.TestCase):
|
|
def test_selects_internal_tp1_and_external_tp2_with_traceable_sources(self) -> None:
|
|
plan = TargetSelectionService().select_targets(
|
|
side="buy",
|
|
entry_low=100.0,
|
|
entry_high=100.2,
|
|
trading_plan={"allowed_sessions": ["LONDON"], "invalidations": [{"code": "range_low_lost"}]},
|
|
range_row={"id": 10, "low": 99.0, "high": 103.0, "equilibrium": 101.0},
|
|
liquidity_pools=[
|
|
{"id": 21, "side": "buy_side", "price_low": 100.9, "price_high": 101.1, "status": "untouched"},
|
|
{"id": 22, "side": "buy_side", "price_low": 103.8, "price_high": 104.0, "status": "untouched"},
|
|
],
|
|
sessions=[{"id": 31, "session_code": "LONDON", "high": 102.0, "low": 99.2, "midpoint": 100.6}],
|
|
candles=[
|
|
{"high": 101.0, "low": 100.0, "close": 100.5},
|
|
{"high": 102.0, "low": 100.5, "close": 101.2},
|
|
{"high": 102.8, "low": 101.0, "close": 102.2},
|
|
],
|
|
)
|
|
|
|
payload = plan.to_dict()
|
|
|
|
self.assertEqual(payload["status"], TARGET_PLAN_STATUS_READY)
|
|
self.assertEqual(payload["tp1"]["objective_layer"], "IRL")
|
|
self.assertEqual(payload["tp2"]["objective_layer"], "ERL")
|
|
self.assertEqual(payload["tp1"]["source"]["table"], "market_sessions")
|
|
self.assertEqual(payload["tp2"]["source"]["table"], "dealing_ranges")
|
|
self.assertTrue(has_complete_structural_target_plan(payload))
|
|
self.assertEqual(
|
|
[rule["code"] for rule in payload["management_rules"]],
|
|
["tp1_partial", "move_stop", "invalidate_on_reclaim", "expire_by_session"],
|
|
)
|
|
|
|
def test_reports_missing_structural_targets_when_no_irl_or_erl_exists(self) -> None:
|
|
plan = TargetSelectionService().select_targets(
|
|
side="buy",
|
|
entry_low=100.0,
|
|
entry_high=100.2,
|
|
range_row=None,
|
|
liquidity_pools=[],
|
|
sessions=[],
|
|
candles=[],
|
|
)
|
|
|
|
payload = plan.to_dict()
|
|
|
|
self.assertEqual(payload["status"], TARGET_PLAN_STATUS_INCOMPLETE)
|
|
self.assertEqual(payload["missing_targets"], ["missing_tp1_internal_target", "missing_tp2_external_target"])
|
|
self.assertFalse(has_complete_structural_target_plan(payload))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|