Sentify is a Flask web app for analyzing stock-related news sentiment and turning it into an actionable recommendation. It pulls Yahoo Finance news, scores article sentiment with a transformer model, and combines those signals into a Buy, Hold, or Sell recommendation with a confidence score.
- Search by company name or ticker symbol.
- Autocomplete suggestions for both company names and tickers.
- Adjustable news lookback window from the dashboard.
- Recommendation tuning controls for recency and article-length weighting.
- Cached Yahoo news lists, article bodies, and sentiment results.
- Offline and stale-cache fallback support when live requests or model loading fail.
- Cache cleanup on startup and a dashboard action to clear cached data.
- TradingView chart embed alongside the news and recommendation summary.
Before you begin, make sure you have the following installed:
- Python (version 3.11 or higher)
- uv (recommended)
- or pip
-
Clone the repository:
git clone https://github.com/LifeAdventurer/sentify.git cd sentify -
Install dependencies:
uv sync
-
Activate the virtual environment:
source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
-
Clone the repository:
git clone https://github.com/LifeAdventurer/sentify.git cd sentify -
Create and activate a virtual environment:
python -m venv venv source venv/bin/activate # On Windows use `venv\Scripts\activate`
-
Install dependencies:
pip install -r requirements.txt
To serve the Flask app locally, run:
uv run python src/main.pyThen open http://127.0.0.1:5000.
Configuration can be provided through environment variables, a repository-root
.env file, or src/config/config.py. You can start from .env.example.
- Enter a company name or ticker symbol.
- Pick a suggestion from the autocomplete dropdown or submit directly.
- Adjust the
News Lookbackslider to control the article time window. - Open
Tune Signalsto change recommendation weighting for the current request. - Use
Clear Cacheif you want to remove cached news, article bodies, and sentiment results.
Sentify supports two weighting dimensions when producing the final recommendation:
Recency: newer articles can count more than older ones.Content length: longer articles can carry more weight than very short ones.
The dashboard modal lets you adjust these values per request without changing cached article sentiment.
By default, Sentify tries live Yahoo requests and live model loading.
- If Yahoo requests fail, Sentify falls back to cached news lists and article bodies when available.
- If model loading fails, Sentify falls back to cached sentiment results when available.
- In offline mode, Sentify reuses cached news, article bodies, and sentiment results even when they are stale.
- Expired cache entries are cleaned up on startup based on the configured retention windows.
Optional model overrides:
export SENTIFY_MODEL_PATH="/path/to/local/model"
export SENTIFY_MODEL_ID="marcev/financebert"
export SENTIFY_MODEL_REVISION="<pinned-revision>"
export SENTIFY_DEBUG=false
export SENTIFY_MODEL_LOCAL_FILES_ONLY=true
export SENTIFY_OFFLINE_MODE=false
export SENTIFY_CACHE_DIR="/path/to/cache"
export SENTIFY_NEWS_LIST_CACHE_TTL_SECONDS=900
export SENTIFY_NEWS_ARTICLE_CACHE_TTL_SECONDS=5184000
export SENTIFY_SENTIMENT_CACHE_TTL_SECONDS=5184000
export SENTIFY_NEWS_LIST_CACHE_RETENTION_SECONDS=5184000
export SENTIFY_NEWS_ARTICLE_CACHE_RETENTION_SECONDS=5184000
export SENTIFY_SENTIMENT_CACHE_RETENTION_SECONDS=5184000
export SENTIFY_RECENCY_WEIGHT_HALF_LIFE_HOURS=168
export SENTIFY_RECENCY_WEIGHT_FLOOR=0.2
export SENTIFY_CONTENT_LENGTH_WEIGHT_TARGET_WORDS=400
export SENTIFY_CONTENT_LENGTH_WEIGHT_MIN=0.75
export SENTIFY_CONTENT_LENGTH_WEIGHT_MAX=1.25Offline mode:
- Set
SENTIFY_OFFLINE_MODE=trueto disable Yahoo network requests and force local-only model loading. - You can put
SENTIFY_OFFLINE_MODE=truein.envinstead of prefixing the run command. - In offline mode, Sentify reuses cached news lists, article bodies, and sentiment results even if they are stale.
- To analyze uncached articles offline, provide a local model with
SENTIFY_MODEL_PATHor make sure the Hugging Face model is already cached locally.
The main defaults live in src/config/config.py. Key parameters include:
TOP_COMPANIES_COUNT = 10000
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
UTC_DIFFERENCE = 8
MAX_NEWS_LOOKBACK_DAYS = 60
CPU_COUNT = 2TOP_COMPANIES_COUNT: The number of top companies ranked by market cap to search.TIMESTAMP_FORMAT: The format for timestamps used in the application, especially for the news API.UTC_DIFFERENCE: The difference in hours between local time and UTC.MAX_NEWS_LOOKBACK_DAYS: The max number of days to look back when fetching news articles.CPU_COUNT: The number of CPUs to be used for multiprocessing.SENTIFY_MODEL_PATH: Local model directory override. If set, it takes precedence over the remote model id.SENTIFY_MODEL_ID: Hugging Face model id to use when no local path override is set.SENTIFY_MODEL_REVISION: Optional pinned revision for reproducible Hugging Face loads.SENTIFY_DEBUG: Enables Flask debug mode when set totrue,1,yes, oron. Defaults tofalseso local and production runs stay non-debug unless you opt in.SENTIFY_MODEL_LOCAL_FILES_ONLY: Forces local-only loading when set totrue,1,yes, oron.SENTIFY_OFFLINE_MODE: Disables Yahoo network fetches, reuses cached data even when stale, and forces local-only model loading. Defaults tofalse.SENTIFY_CACHE_DIR: Directory for cached Yahoo news responses. Defaults to.cache/sentifyin the repository root.SENTIFY_NEWS_LIST_CACHE_TTL_SECONDS: How long ticker news query results stay fresh. Defaults to 900 seconds.SENTIFY_NEWS_ARTICLE_CACHE_TTL_SECONDS: How long article body fetches stay fresh. Defaults toMAX_NEWS_LOOKBACK_DAYS * 86400seconds.SENTIFY_SENTIMENT_CACHE_TTL_SECONDS: How long article sentiment results stay fresh. Defaults toMAX_NEWS_LOOKBACK_DAYS * 86400seconds.SENTIFY_NEWS_LIST_CACHE_RETENTION_SECONDS: How long news-list cache files stay on disk for stale fallback. Defaults to at leastMAX_NEWS_LOOKBACK_DAYS * 86400seconds and never below the freshness TTL.SENTIFY_NEWS_ARTICLE_CACHE_RETENTION_SECONDS: How long cached article bodies stay on disk for stale fallback. Defaults to at leastMAX_NEWS_LOOKBACK_DAYS * 86400seconds and never below the freshness TTL.SENTIFY_SENTIMENT_CACHE_RETENTION_SECONDS: How long cached sentiment results stay on disk for stale fallback. Defaults to at leastMAX_NEWS_LOOKBACK_DAYS * 86400seconds and never below the freshness TTL.SENTIFY_RECENCY_WEIGHT_HALF_LIFE_HOURS: Half-life for recency weighting in the recommendation score. More recent news gets more weight on a smooth exponential curve. Defaults to168hours (7 days).SENTIFY_RECENCY_WEIGHT_FLOOR: Minimum weight applied to older news so it still contributes to the recommendation. Defaults to0.2.SENTIFY_CONTENT_LENGTH_WEIGHT_TARGET_WORDS: Word-count threshold where the content-length weight reaches its configured maximum. Defaults to400.SENTIFY_CONTENT_LENGTH_WEIGHT_MIN: Minimum weight applied to very short articles. Defaults to0.75.SENTIFY_CONTENT_LENGTH_WEIGHT_MAX: Maximum weight applied to articles at or above the target word count. Defaults to1.25.
Run the test suite with:
python3 -m unittest discover -s testsThis project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
