SignalDedup: 24h-rolling duplicate signal blocker. SQLite WAL + busy_timeout=120000 standard fix (reference_sqlite_concurrency.md pattern). PK (ticker, action) with UPSERT. Phase 4 (signal generator) will call is_recent() before sending + record() after sending. 3 unit tests pass, total 17 signal_v2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
35 lines
1.1 KiB
Python
35 lines
1.1 KiB
Python
"""Tests for SignalDedup."""
|
|
from datetime import datetime, timedelta
|
|
from zoneinfo import ZoneInfo
|
|
|
|
from signal_v2.rate_limit import SignalDedup
|
|
|
|
KST = ZoneInfo("Asia/Seoul")
|
|
|
|
|
|
def test_is_recent_returns_false_for_new_ticker_action(tmp_dedup_db):
|
|
dedup = SignalDedup(tmp_dedup_db)
|
|
assert dedup.is_recent("005930", "buy") is False
|
|
|
|
|
|
def test_is_recent_returns_true_within_24h(tmp_dedup_db):
|
|
dedup = SignalDedup(tmp_dedup_db)
|
|
dedup.record("005930", "buy", confidence=0.82)
|
|
assert dedup.is_recent("005930", "buy") is True
|
|
|
|
|
|
def test_is_recent_returns_false_after_24h(tmp_dedup_db, monkeypatch):
|
|
dedup = SignalDedup(tmp_dedup_db)
|
|
# Record with a timestamp 25 hours ago
|
|
now = datetime.now(KST)
|
|
fake_now = now - timedelta(hours=25)
|
|
monkeypatch.setattr(
|
|
"signal_v2.rate_limit._now_iso", lambda: fake_now.isoformat()
|
|
)
|
|
dedup.record("005930", "buy", confidence=0.82)
|
|
# Reset to real now for is_recent check
|
|
monkeypatch.setattr(
|
|
"signal_v2.rate_limit._now_iso", lambda: now.isoformat()
|
|
)
|
|
assert dedup.is_recent("005930", "buy", within_hours=24) is False
|