feat(signal_v2): rate_limit + 3 unit tests
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>
This commit is contained in:
34
signal_v2/tests/test_rate_limit.py
Normal file
34
signal_v2/tests/test_rate_limit.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user