Visualize company sentiment (#422)

Updates the tab and widget "Stimmung"
This commit is contained in:
KM-R
2023-11-22 22:32:38 +01:00
committed by GitHub
parent 65c41bb20c
commit 4e83c83374
9 changed files with 777 additions and 53 deletions

View File

@ -10,6 +10,7 @@ from sqlalchemy.orm import Session, sessionmaker
from aki_prj23_transparenzregister.config.config_template import SQLiteConnectionString
from aki_prj23_transparenzregister.models.company import CapitalTypeEnum
from aki_prj23_transparenzregister.utils import data_transfer
from aki_prj23_transparenzregister.utils.enum_types import SentimentLabel
from aki_prj23_transparenzregister.utils.sql import entities
from aki_prj23_transparenzregister.utils.sql.connector import (
get_engine,
@ -189,3 +190,277 @@ def full_db(empty_db: Session, finance_statements: list[dict[str, Any]]) -> Sess
empty_db.commit()
# print(pd.read_sql_table("company", empty_db.bind).to_string())
return empty_db
@pytest.fixture()
def news_db(full_db: Session) -> Session:
news_example = entities.News(
title="AI Revolution in Tech",
timestamp=datetime.datetime(2023, 11, 1, 15, 30),
text="The latest advancements in AI are transforming the tech industry.",
source_url="http://example-news.com/ai-revolution",
source_domain="example-news.com",
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
overall_sentiment_certainty=0.95,
number_of_companies=2,
sum_of_times_named=5,
)
full_db.add(news_example)
full_db.commit()
# Print to see the object representation
# Example instances of Sentiment for different company IDs
sentiment_examples = [
entities.Sentiment(
company_id=1,
article_id=news_example.id, # This should be the actual ID after insertion into the database
times_named=3,
specific_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
specific_sentiment_score=0.5,
),
entities.Sentiment(
company_id=2,
article_id=news_example.id, # This should be the actual ID after insertion into the database
times_named=2,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.2,
),
entities.Sentiment(
company_id=3,
article_id=news_example.id, # This should be the actual ID after insertion into the database
times_named=1,
specific_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
specific_sentiment_score=0.8,
),
]
full_db.add_all(sentiment_examples)
add_news_examples = [
entities.News(
title="Breakthrough in Renewable Energy",
timestamp=datetime.datetime(2023, 11, 1, 15, 30),
text="Innovative solar panels are expected to revolutionize the energy sector.",
source_url="http://example-news.com/renewable-breakthrough",
source_domain="eco-news.com",
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
overall_sentiment_certainty=0.9,
number_of_companies=1,
sum_of_times_named=3,
),
entities.News(
title="Global Economic Outlook",
timestamp=datetime.datetime(2023, 11, 2, 10, 0),
text="Economists predict a challenging year ahead for global markets.",
source_url="http://example-news.com/economic-outlook",
source_domain="finance-world.com",
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
overall_sentiment_certainty=0.95,
number_of_companies=3,
sum_of_times_named=7,
),
entities.News(
title="Tech Giants Merge",
timestamp=datetime.datetime(2023, 11, 3, 12, 45),
text="Two leading tech companies have announced a merger, sparking industry-wide discussions.",
source_url="http://example-news.com/tech-merger",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
overall_sentiment_certainty=0.91,
number_of_companies=2,
sum_of_times_named=10,
),
entities.News(
title="Deutsche Bank announces huge job loss plan",
timestamp=datetime.datetime(2023, 11, 5, 12, 45),
text="Deutsche Bank has announced plans for major job losses and will also scale down massively its operations worldwide, as part of a major shake-up of.",
source_url="http://example-news.com/deutsche-bank",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
overall_sentiment_certainty=0.9,
number_of_companies=1,
sum_of_times_named=8,
),
entities.News(
title="Germany approves reforms to help its tech industry compete with Silicon Valley",
timestamp=datetime.datetime(2023, 11, 6, 9, 45),
text="Germany on Friday approved a litany of changes to its rules for stock-based compensation at tech startups, listing of companies and taxation.",
source_url="http://example-news.com/german-tech-industry",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
overall_sentiment_certainty=0.97,
number_of_companies=3,
sum_of_times_named=5,
),
entities.News(
title="German housebuilding is collapsing ",
timestamp=datetime.datetime(2023, 11, 8, 12, 30),
text="German housebuilding is on the brink of collapse as construction projects are being canceled and orders are slowing.",
source_url="http://example-news.com/german-housing",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
overall_sentiment_certainty=0.96,
number_of_companies=3,
sum_of_times_named=2,
),
entities.News(
title="The Berlin start-ups tearing up capitalism and putting workers first",
timestamp=datetime.datetime(2023, 11, 10, 12, 45),
text="Berlin is one of Europe's hottest start-up hubs. But companies setting up there are doing things differently and it starts with where the power lies.",
source_url="http://example-news.com/tech-merger",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
overall_sentiment_certainty=0.91,
number_of_companies=2,
sum_of_times_named=10,
),
entities.News(
title="Air traffic across Germany disrupted due to mass walkouts",
timestamp=datetime.datetime(2023, 11, 3, 12, 45),
text="Security workers are staging a full-day walkout at airports across Germany over pay disputes.",
source_url="http://example-news.com/tech-merger",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
overall_sentiment_certainty=0.95,
number_of_companies=3,
sum_of_times_named=17,
),
entities.News(
title="Car makers face fraud claims",
timestamp=datetime.datetime(2023, 11, 12, 12, 45),
text="The German economy grew 0.6 percent in Q1, quarter on quarter, helped by strong exports, booming construction and higher household and state spending.",
source_url="http://example-news.com/tech-merger",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
overall_sentiment_certainty=0.9,
number_of_companies=2,
sum_of_times_named=10,
),
entities.News(
title="Inflation rises, unemployment falls",
timestamp=datetime.datetime(2023, 11, 15, 12, 45),
text="German inflation rose in February, reaching its highest level in four-and-a-half years, while unemployment fell more than expected.",
source_url="http://example-news.com/inflation",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
overall_sentiment_certainty=0.98,
number_of_companies=2,
sum_of_times_named=10,
),
entities.News(
title="Exports struggle on slow factory output",
timestamp=datetime.datetime(2023, 11, 16, 12, 45),
text="Exports rebounded by less than expected in October, according to latest official figures.",
source_url="http://example-news.com/exports",
source_domain="tech-news.com",
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
overall_sentiment_certainty=0.98,
number_of_companies=3,
sum_of_times_named=4,
),
]
full_db.add_all(add_news_examples)
full_db.commit()
# Additional examples for the Sentiment entity
sentiment_more_examples = [
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
2
].id, # Placeholder ID, replace with actual after insertion
times_named=1,
specific_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
specific_sentiment_score=0.5,
),
entities.Sentiment(
company_id=3,
article_id=add_news_examples[
1
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
1
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
3
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
4
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
5
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
6
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
7
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
8
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
9
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
entities.Sentiment(
company_id=1,
article_id=add_news_examples[
10
].id, # Placeholder ID, replace with actual after insertion
times_named=4,
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
specific_sentiment_score=0.3,
),
]
full_db.add_all(sentiment_more_examples)
full_db.commit()
return full_db

View File

@ -4,6 +4,7 @@ import pandas as pd
from sqlalchemy.orm import Session
from aki_prj23_transparenzregister.ui import data_elements
from aki_prj23_transparenzregister.utils.enum_types import SentimentLabel
def test_import() -> None:
@ -86,3 +87,27 @@ def test_get_finance_data(full_db: Session) -> None:
}
)
pd.testing.assert_frame_equal(finance_df, test_data)
def test_get_news_of_one_company0(news_db: Session) -> None:
"""Tests what happens if no sentiment can be found."""
selected_company_id = 100
assert data_elements.get_news_of_one_company(selected_company_id, news_db).empty
def test_get_news_of_one_company1(news_db: Session) -> None:
"""Tests if the sentiments can be collected for a company specified."""
selected_company_id = 2
sentiment_df = data_elements.get_news_of_one_company(selected_company_id, news_db)
assert sentiment_df is not None
assert sentiment_df.to_dict(orient="records") == [
{
"overall_sentiment_certainty": 0.95,
"overall_sentiment_label": SentimentLabel.POSITIVE,
"source_domain": "example-news.com",
"source_url": "http://example-news.com/ai-revolution",
"times_named": 2,
"timestamp": pd.Timestamp("2023-11-01 15:30:00"),
"title": "AI Revolution in Tech",
},
]

View File

@ -0,0 +1,32 @@
"""Tests for sentiment ui elements."""
from sqlalchemy.orm import Session
from aki_prj23_transparenzregister.ui import data_elements, sentiment_elements
def test_sentiment_layout(news_db: Session) -> None:
"""Checks if the sentiment tab layout of the company page can be created."""
selected_company_id = 1
sentiment_elements.sentiment_layout(selected_company_id, news_db)
def test_sentiment_trend_figure(news_db: Session) -> None:
"""Checks if the sentiment trend graph can be created."""
n = 10
company_id = 1
articles = data_elements.get_news_of_one_company(company_id, news_db)
articles["overall_sentiment_label"] = articles["overall_sentiment_label"].apply(
lambda _: _.value
)
articles = articles.sort_values(by=["timestamp"], ascending=True)
articles["rolling_mean"] = articles["overall_sentiment_label"].rolling(n).mean()
sentiment_elements.sentiment_trend_figure(articles, n)
def test_sentiment_gauge_figure() -> None:
"""Checks if the sentiment gauge graph can be created."""
sentiment_score = 0.2
sentiment_elements.sentiment_gauge_figure(sentiment_score)