summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/alembic/versions/002_news_sentiment_tables.py8
-rw-r--r--shared/src/shared/db.py10
-rw-r--r--shared/src/shared/notifier.py3
-rw-r--r--shared/src/shared/sentiment.py6
-rw-r--r--shared/tests/test_db_news.py2
-rw-r--r--shared/tests/test_sentiment_aggregator.py12
-rw-r--r--shared/tests/test_sentiment_models.py1
7 files changed, 23 insertions, 19 deletions
diff --git a/shared/alembic/versions/002_news_sentiment_tables.py b/shared/alembic/versions/002_news_sentiment_tables.py
index b57f1d6..402ff87 100644
--- a/shared/alembic/versions/002_news_sentiment_tables.py
+++ b/shared/alembic/versions/002_news_sentiment_tables.py
@@ -29,7 +29,9 @@ def upgrade() -> None:
sa.Column("sentiment", sa.Float, nullable=False),
sa.Column("category", sa.Text, nullable=False),
sa.Column("raw_data", sa.Text),
- sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
+ sa.Column(
+ "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()
+ ),
)
op.create_index("idx_news_items_published", "news_items", ["published_at"])
op.create_index("idx_news_items_source", "news_items", ["source"])
@@ -68,7 +70,9 @@ def upgrade() -> None:
sa.Column("reason", sa.Text, nullable=False),
sa.Column("key_news", sa.Text),
sa.Column("sentiment_snapshot", sa.Text),
- sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
+ sa.Column(
+ "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()
+ ),
)
op.create_index("idx_stock_selections_date", "stock_selections", ["trade_date"])
diff --git a/shared/src/shared/db.py b/shared/src/shared/db.py
index 55f93b4..9cc8686 100644
--- a/shared/src/shared/db.py
+++ b/shared/src/shared/db.py
@@ -299,11 +299,7 @@ class Database:
async def get_top_symbol_scores(self, limit: int = 20) -> list[dict]:
"""Retrieve top symbol scores ordered by composite descending."""
- stmt = (
- select(SymbolScoreRow)
- .order_by(SymbolScoreRow.composite.desc())
- .limit(limit)
- )
+ stmt = select(SymbolScoreRow).order_by(SymbolScoreRow.composite.desc()).limit(limit)
async with self._session_factory() as session:
try:
result = await session.execute(stmt)
@@ -431,7 +427,9 @@ class Database:
"conviction": r.conviction,
"reason": r.reason,
"key_news": json.loads(r.key_news) if r.key_news else [],
- "sentiment_snapshot": json.loads(r.sentiment_snapshot) if r.sentiment_snapshot else {},
+ "sentiment_snapshot": json.loads(r.sentiment_snapshot)
+ if r.sentiment_snapshot
+ else {},
"created_at": r.created_at,
}
for r in rows
diff --git a/shared/src/shared/notifier.py b/shared/src/shared/notifier.py
index 9630a18..3d7b6cf 100644
--- a/shared/src/shared/notifier.py
+++ b/shared/src/shared/notifier.py
@@ -137,8 +137,7 @@ class TelegramNotifier:
for i, s in enumerate(selections, 1):
emoji = side_emoji.get(s.side.value, "⚪")
lines.append(
- f"{i}. <b>{s.symbol}</b> {emoji} {s.side.value} "
- f"(conviction: {s.conviction:.0%})"
+ f"{i}. <b>{s.symbol}</b> {emoji} {s.side.value} (conviction: {s.conviction:.0%})"
)
lines.append(f" {s.reason}")
if s.key_news:
diff --git a/shared/src/shared/sentiment.py b/shared/src/shared/sentiment.py
index a20227e..449eb76 100644
--- a/shared/src/shared/sentiment.py
+++ b/shared/src/shared/sentiment.py
@@ -2,7 +2,7 @@
import logging
from dataclasses import dataclass, field
-from datetime import datetime, timedelta, timezone
+from datetime import datetime, timezone
from shared.sentiment_models import SymbolScore
@@ -82,9 +82,7 @@ class SentimentAggregator:
+ filing_score * self.WEIGHTS["filing"]
)
- def aggregate(
- self, news_items: list[dict], now: datetime
- ) -> dict[str, SymbolScore]:
+ def aggregate(self, news_items: list[dict], now: datetime) -> dict[str, SymbolScore]:
"""Aggregate news items into per-symbol scores.
Each dict needs: symbols, sentiment, category, published_at.
diff --git a/shared/tests/test_db_news.py b/shared/tests/test_db_news.py
index f13cf1e..a2c9140 100644
--- a/shared/tests/test_db_news.py
+++ b/shared/tests/test_db_news.py
@@ -1,7 +1,5 @@
"""Tests for database news/sentiment methods. Uses in-memory SQLite."""
-import json
-import uuid
import pytest
from datetime import datetime, date, timezone
diff --git a/shared/tests/test_sentiment_aggregator.py b/shared/tests/test_sentiment_aggregator.py
index f9277e7..a99c711 100644
--- a/shared/tests/test_sentiment_aggregator.py
+++ b/shared/tests/test_sentiment_aggregator.py
@@ -1,4 +1,5 @@
"""Tests for sentiment aggregator."""
+
import pytest
from datetime import datetime, timezone, timedelta
from shared.sentiment import SentimentAggregator
@@ -35,7 +36,9 @@ def test_freshness_decay_old():
def test_compute_composite():
a = SentimentAggregator()
- composite = a._compute_composite(news_score=0.5, social_score=0.3, policy_score=0.8, filing_score=0.2)
+ composite = a._compute_composite(
+ news_score=0.5, social_score=0.3, policy_score=0.8, filing_score=0.2
+ )
expected = 0.5 * 0.3 + 0.3 * 0.2 + 0.8 * 0.3 + 0.2 * 0.2
assert abs(composite - expected) < 0.001
@@ -44,7 +47,12 @@ def test_aggregate_news_by_symbol(aggregator):
now = datetime.now(timezone.utc)
news_items = [
{"symbols": ["AAPL"], "sentiment": 0.8, "category": "earnings", "published_at": now},
- {"symbols": ["AAPL"], "sentiment": 0.3, "category": "macro", "published_at": now - timedelta(hours=2)},
+ {
+ "symbols": ["AAPL"],
+ "sentiment": 0.3,
+ "category": "macro",
+ "published_at": now - timedelta(hours=2),
+ },
{"symbols": ["MSFT"], "sentiment": -0.5, "category": "policy", "published_at": now},
]
scores = aggregator.aggregate(news_items, now)
diff --git a/shared/tests/test_sentiment_models.py b/shared/tests/test_sentiment_models.py
index 74f1acd..25fc371 100644
--- a/shared/tests/test_sentiment_models.py
+++ b/shared/tests/test_sentiment_models.py
@@ -1,6 +1,5 @@
"""Tests for news and sentiment models."""
-import pytest
from datetime import datetime, timezone
from shared.models import NewsCategory, NewsItem, OrderSide