summaryrefslogtreecommitdiff
path: root/shared/tests/test_sentiment_models.py
blob: e00ffa6f7a7074223f8287fbbeba0c390dfa1ce4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"""Tests for news and sentiment models."""

from datetime import UTC, datetime

from shared.models import NewsCategory, NewsItem, OrderSide
from shared.sentiment_models import Candidate, MarketSentiment, SelectedStock, SymbolScore


def test_news_item_defaults():
    item = NewsItem(
        source="finnhub",
        headline="Test headline",
        published_at=datetime(2026, 4, 2, tzinfo=UTC),
        sentiment=0.5,
        category=NewsCategory.MACRO,
    )
    assert item.id
    assert item.symbols == []
    assert item.summary is None
    assert item.raw_data == {}
    assert item.created_at is not None


def test_news_item_with_symbols():
    item = NewsItem(
        source="rss",
        headline="AAPL earnings beat",
        published_at=datetime(2026, 4, 2, tzinfo=UTC),
        sentiment=0.8,
        category=NewsCategory.EARNINGS,
        symbols=["AAPL"],
    )
    assert item.symbols == ["AAPL"]
    assert item.category == NewsCategory.EARNINGS


def test_news_category_values():
    assert NewsCategory.POLICY == "policy"
    assert NewsCategory.EARNINGS == "earnings"
    assert NewsCategory.MACRO == "macro"
    assert NewsCategory.SOCIAL == "social"
    assert NewsCategory.FILING == "filing"
    assert NewsCategory.FED == "fed"


def test_symbol_score():
    score = SymbolScore(
        symbol="AAPL",
        news_score=0.5,
        news_count=10,
        social_score=0.3,
        policy_score=0.0,
        filing_score=0.2,
        composite=0.3,
        updated_at=datetime(2026, 4, 2, tzinfo=UTC),
    )
    assert score.symbol == "AAPL"
    assert score.composite == 0.3


def test_market_sentiment():
    ms = MarketSentiment(
        fear_greed=25,
        fear_greed_label="Extreme Fear",
        vix=32.5,
        fed_stance="hawkish",
        market_regime="risk_off",
        updated_at=datetime(2026, 4, 2, tzinfo=UTC),
    )
    assert ms.market_regime == "risk_off"
    assert ms.vix == 32.5


def test_market_sentiment_no_vix():
    ms = MarketSentiment(
        fear_greed=50,
        fear_greed_label="Neutral",
        fed_stance="neutral",
        market_regime="neutral",
        updated_at=datetime(2026, 4, 2, tzinfo=UTC),
    )
    assert ms.vix is None


def test_selected_stock():
    ss = SelectedStock(
        symbol="NVDA",
        side=OrderSide.BUY,
        conviction=0.85,
        reason="CHIPS Act expansion",
        key_news=["Trump signs CHIPS Act expansion"],
    )
    assert ss.conviction == 0.85
    assert len(ss.key_news) == 1


def test_candidate():
    c = Candidate(
        symbol="TSLA",
        source="sentiment",
        direction=OrderSide.BUY,
        score=0.75,
        reason="High social buzz",
    )
    assert c.direction == OrderSide.BUY

    c2 = Candidate(
        symbol="XOM",
        source="llm",
        score=0.6,
        reason="Oil price surge",
    )
    assert c2.direction is None