rmi-backend/tests/unit/test_whale_accumulation.py

159 lines
4.8 KiB
Python

"""
Tests for Whale Accumulation Pattern Detector
===============================================
"""
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from app.whale_accumulation import (
_classify_accumulation,
_compute_accumulation_score,
_generate_recommendation,
)
class TestAccumulationScore:
"""Test the core scoring algorithm."""
def test_zero_score(self):
"""No signals should give near-zero score."""
score = _compute_accumulation_score(
buy_volume_ratio=1.0,
holder_concentration=0.0,
tx_frequency=0.0,
wallet_age_days=365,
is_smart_money=False,
recent_large_buys=0,
)
assert 0 <= score <= 20 # low end
def test_heavy_accumulation(self):
"""All signals maxed should give high score."""
score = _compute_accumulation_score(
buy_volume_ratio=3.0,
holder_concentration=0.8,
tx_frequency=100.0,
wallet_age_days=1,
is_smart_money=True,
recent_large_buys=10,
)
assert score >= 70
def test_moderate_accumulation(self):
"""Mixed signals should give moderate score."""
score = _compute_accumulation_score(
buy_volume_ratio=1.8,
holder_concentration=0.3,
tx_frequency=15.0,
wallet_age_days=30,
is_smart_money=False,
recent_large_buys=2,
)
assert 20 <= score <= 70
def test_smart_money_bonus(self):
"""Smart money involvement should boost score."""
without_sm = _compute_accumulation_score(
buy_volume_ratio=1.0,
holder_concentration=0.3,
tx_frequency=5.0,
wallet_age_days=100,
is_smart_money=False,
recent_large_buys=0,
)
with_sm = _compute_accumulation_score(
buy_volume_ratio=1.0,
holder_concentration=0.3,
tx_frequency=5.0,
wallet_age_days=100,
is_smart_money=True,
recent_large_buys=0,
)
assert with_sm > without_sm
assert with_sm - without_sm == pytest.approx(20.0, abs=1.0)
def test_new_wallet_penalty(self):
"""Newer wallets should score higher (more suspicious)."""
old = _compute_accumulation_score(
buy_volume_ratio=1.0,
holder_concentration=0.3,
tx_frequency=10.0,
wallet_age_days=365,
is_smart_money=False,
recent_large_buys=0,
)
new = _compute_accumulation_score(
buy_volume_ratio=1.0,
holder_concentration=0.3,
tx_frequency=10.0,
wallet_age_days=1,
is_smart_money=False,
recent_large_buys=0,
)
assert new > old
def test_score_boundary(self):
"""Score should never exceed 100."""
score = _compute_accumulation_score(
buy_volume_ratio=999.0,
holder_concentration=1.0,
tx_frequency=999.0,
wallet_age_days=0,
is_smart_money=True,
recent_large_buys=999,
)
assert score <= 100.0
assert score >= 0.0
class TestClassification:
"""Test accumulation classification thresholds."""
def test_critical(self):
assert _classify_accumulation(85) == "critical"
assert _classify_accumulation(80) == "critical"
def test_high(self):
assert _classify_accumulation(70) == "high"
assert _classify_accumulation(60) == "high"
def test_moderate(self):
assert _classify_accumulation(50) == "moderate"
assert _classify_accumulation(40) == "moderate"
def test_low(self):
assert _classify_accumulation(30) == "low"
assert _classify_accumulation(20) == "low"
def test_none(self):
assert _classify_accumulation(10) == "none"
assert _classify_accumulation(0) == "none"
class TestRecommendation:
"""Test recommendation generation."""
def test_critical_recommendation(self):
rec = _generate_recommendation(85, "trader")
assert "CRITICAL" in rec
assert "ACCUMULATION" in rec
def test_high_recommendation(self):
rec = _generate_recommendation(65, "trader")
assert "HIGH" in rec
def test_none_recommendation(self):
rec = _generate_recommendation(5, "trader")
assert "No accumulation" in rec
def test_different_personas(self):
"""Different personas should get different messaging."""
trader_rec = _generate_recommendation(85, "trader")
generic_rec = _generate_recommendation(85, "investor")
assert trader_rec != generic_rec
assert "position" in trader_rec.lower()