"""Opportunity historical evaluation tests.""" from __future__ import annotations import json import tempfile import unittest from pathlib import Path from coinhunter.services import opportunity_evaluation_service def _rows(start_ms: int, closes: list[float]) -> list[list[float]]: rows = [] for index, close in enumerate(closes): open_time = start_ms + index * 3_600_000 volume = 1_000 + index * 10 rows.append( [ float(open_time), close * 0.99, close * 1.02, close * 0.98, close, float(volume), float(open_time + 3_599_999), close * volume, ] ) return rows class OpportunityEvaluationServiceTestCase(unittest.TestCase): def test_evaluate_opportunity_dataset_scores_historical_samples(self): start_ms = 1_767_225_600_000 dataset = { "metadata": { "plan": { "intervals": ["1h"], "simulation_start": "2026-01-01T04:00:00Z", "simulation_end": "2026-01-01T07:00:00Z", "simulate_days": 1, } }, "klines": { "GOODUSDT": {"1h": _rows(start_ms, [100, 101, 102, 103, 104, 106, 108, 109, 110])}, "BADUSDT": {"1h": _rows(start_ms, [100, 99, 98, 97, 96, 95, 94, 93, 92])}, }, } config = { "market": {"default_quote": "USDT"}, "opportunity": { "entry_threshold": 1.5, "watch_threshold": 0.6, "evaluation_horizon_hours": 2.0, "evaluation_take_profit_pct": 1.0, "evaluation_stop_loss_pct": 2.0, "evaluation_setup_target_pct": 0.5, "evaluation_lookback": 4, "top_n": 2, }, } with tempfile.TemporaryDirectory() as tmp_dir: dataset_path = Path(tmp_dir) / "opportunity-dataset.json" dataset_path.write_text(json.dumps(dataset), encoding="utf-8") payload = opportunity_evaluation_service.evaluate_opportunity_dataset( config, dataset_path=str(dataset_path), horizon_hours=2.0, take_profit=0.01, stop_loss=0.02, setup_target=0.005, lookback=4, top_n=2, max_examples=3, ) self.assertEqual(payload["summary"]["symbols"], ["BADUSDT", "GOODUSDT"]) self.assertEqual(payload["summary"]["interval"], "1h") self.assertGreater(payload["summary"]["count"], 0) self.assertIn("by_action", payload) self.assertIn("trade_simulation", payload) self.assertEqual(payload["rules"]["research_mode"], "disabled: dataset has no point-in-time research snapshots") self.assertLessEqual(len(payload["examples"]), 3) if __name__ == "__main__": unittest.main()