A multi-factor analysis tool that suggests long-term stock & ETF buy recommendations from US, European, and Asian markets, computed live from public market data.
- π Multi-factor scoring β composite 0-100 score per asset
- π¦ Stocks & ETFs β auto-detected and scored with dedicated models
- π US, European & Asian markets β S&P 500, DAX, CAC 40, FTSE 100, Nikkei 225, Hang Seng, NSE, and more
- π± Currency filter β narrow by native currency (
USD,EUR,JPY, β¦) - β‘ Concurrent fetching β analyzes ~300 tickers in seconds
- π Rich CLI output β price, 1M/1Y change, score breakdown and rationale
- π§Ύ Self-contained HTML export β interactive report with filters and sortable columns
- π§ͺ Pure scoring functions β testable without network
- π§ Interactive advisor β market pulse, portfolio review, and tailored buy recommendations via the
advisorsubcommand - π€ AI-powered advisor β chat with an intelligent investment advisor that analyzes markets, reviews portfolios, and recommends buys β powered by OpenCode agents
pip install investdaytipgit clone https://github.com/dfdezdom/investdaytip.git
cd investdaytip
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"pip install investdaytip
investdaytipThat's it. You'll see the top 5 buys scored across 300+ stocks & ETFs.
investdaytip # Top 5 from full universe (US + EU + Asia, stocks + ETFs)
investdaytip -n 10 # Top 10
investdaytip -a stocks # Only stocks
investdaytip -a etfs # Only ETFs
investdaytip -r us # Only US
investdaytip -r eu # Only Europe
investdaytip -r asia # Only Asia
investdaytip -r us eu # US + Europe
investdaytip -r eu -a stocks # Only European stocks
investdaytip -r asia -a etfs # Only Asian ETFs
investdaytip -c USD # Only USD-denominated assets
investdaytip -c EUR # Only EUR-denominated assets
investdaytip -c USD EUR # USD + EUR assets
investdaytip -c JPY # Only JPY-denominated assets
investdaytip -r eu -c USD # EU region + USD post-filter
investdaytip -r us eu -c USD EUR # US + EU, USD + EUR assets
investdaytip -t AAPL MSFT VOO # Custom ticker list
investdaytip --tickers-file tickers.txt # Custom ticker file (lines, spaces, commas)
investdaytip --tickers-file tickers-files-examples/semiconductors_relevant_tickers.txt
investdaytip --export-html report.html # Export report with interactive filters
investdaytip --export-html # Uses investDayTip-aaaammdd-hhmm.html
# or investDayTip-<tag>-aaaammdd-hhmm.html
# when --tickers-file is set
investdaytip --workers 20 # More parallelism
investdaytip --min-market-cap 1B # Raise min market cap to $1B
investdaytip --min-market-cap 0 # Disable market-cap filter
investdaytip --no-cache # Bypass SQLite cache, fetch fresh data
investdaytip --cache-clear # Purge all cached data before running
investdaytip --help
./preview.sh # Serve generated HTML files on localhost:8000| Flag | Description | Default |
|---|---|---|
-n, --top N |
Number of recommendations | 5 |
-t, --tickers ... |
Custom ticker list (overrides universe) | curated universe |
--tickers-file PATH |
Text file with custom tickers (merged with --tickers if both are used) |
disabled |
-a, --asset-class {all,stocks,etfs} |
Asset class filter | all |
-r, --region {all,us,eu,asia} nargs="+" |
Region filter(s) β e.g. -r us eu |
all |
-c, --currency {all,USD,EUR,GBP,β¦} nargs="+" |
Currency filter(s); narrows universe to matching regions when no -r is given |
all |
--export-html [PATH] |
Export recommendations to self-contained HTML (investDayTip-aaaammdd-hhmm.html if omitted) |
disabled |
--min-market-cap VALUE |
Minimum market cap (1B, 500M, 0 to disable) |
2B |
--no-cache |
Skip SQLite cache, fetch all data live from Yahoo Finance | disabled |
--cache-clear |
Purge the SQLite cache before running | disabled |
--workers N |
Parallel fetch threads | 10 |
-h, --help |
Show the CLI help message and exit | n/a |
Interactive market analysis, portfolio review, and buy recommendations:
investdaytip advisor # Interactive mode (asks for risk, region, etc.)
investdaytip advisor --risk moderate # Non-interactive with risk preset
investdaytip advisor --risk aggressive -r us -a stocks # US stocks, aggressive, non-interactive
investdaytip advisor --risk moderate --portfolio portfolios/portfolio.txt # Custom portfolioSee investdaytip advisor --help for all options.
π€ Chat with an AI investment advisor that checks VIX, reviews portfolios, and recommends buys β see
.opencode/agents/advisor.md.
No memorizing flags. From the project root:
@advisor what's the market pulse?
Generate an interactive report that works offline (single file with inline CSS/JS):
investdaytip -n 25 -a all -r all --export-html investdaytip-report.htmlThe generated report includes filters for:
- Text search (ticker/name/sector)
- Asset class (
stock/etf) - Region (
us/eu/asia) - Minimum score
- Minimum 1M return (%)
- Minimum 1Y return (%)
It also includes:
- Click-to-sort columns (ascending/descending)
- Full-width responsive layout (uses available browser width)
- Pre-rendered rows + client-side interactivity (works even if JS is restricted)
- Direct platform links in table columns:
Ticker(Google Finance),T(TradingView),Y(Yahoo Finance)
Direct platform links (Ticker β Google Finance, T β TradingView, Y β Yahoo Finance) use exchange suffix mapping. See _normalize_exchange_hint() and _exchange_mapping() in src/investdaytip/html_export.py for the full list of ~20 supported exchanges.
from investdaytip import get_recommendations
# Get top 5 Asian stocks
picks = get_recommendations(top_n=5, region="asia", asset_class="stocks")
for s in picks:
print(f"{s.data.ticker} ({s.asset_type}) β score={s.total:.1f}")
print(f" Price: {s.data.current_price} {s.data.currency}")
print(f" 1M: {s.data.return_1m:.2%} 1Y: {s.data.return_12m:.2%}")
print(f" Why: {'; '.join(s.rationale[:3])}")
# Or mix regions and asset classes
picks = get_recommendations(top_n=10, region="all") # US + EU + Asia stocks & ETFsEach recommendation includes:
| Column | Meaning |
|---|---|
| Type | STOCK or ETF |
| Ticker / Name / Sector | Identification |
| Ticker link | Opens Google Finance in a new tab |
| T / Y | Opens TradingView / Yahoo Finance in a new tab |
| Price | Current price in native currency |
| P/E | Trailing price-to-earnings ratio (stocks; - when unavailable) |
| 1M Ξ | % change vs ~22 trading days ago |
| 1Y Ξ | % change vs ~252 trading days ago |
| Score | Composite 0-100 weighted score |
| Breakdown | Four sub-scores (shown in a compact single line) |
| Why | Top 3 rationale notes |
Each metric is normalized to 0-100 via piecewise-linear functions over empirically reasonable ranges. Missing data contributes a neutral 50 so a ticker isn't penalized for lacking a metric.
| Pillar | Weight | Metrics |
|---|---|---|
| Quality | 35% | ROE, profit margin, earnings & revenue growth |
| Value | 25% | trailing P/E, P/B, PEG |
| Health | 20% | Debt/Equity, current ratio, free cash flow |
| Trend | 20% | price vs SMA200, 12-month return, SMA200 slope |
| Pillar | Weight | Metrics |
|---|---|---|
| Returns | 40% | 3y avg, 5y avg, 12m return |
| RiskAdj | 25% | Sharpe proxy (r12 - rf) / Ο, annualized volatility |
| Size | 15% | AUM (log scale) |
| Cost/Yield | 20% | expense ratio (lower=better), dividend yield |
When no -t is given, InvestDayTip uses curated universes:
- US stocks β 58 large-caps across all S&P sectors (
src/investdaytip/universe.py) - US ETFs β 41 broad-market, factor, sector and bond ETFs (
etf_universe.py) - EU stocks β 65 large-caps from DAX, CAC, FTSE 100, IBEX, AEX, SMI, FTSE MIB, Nordics (
eu_universe.py) - EU UCITS ETFs β 38 broad, sector and bond UCITS ETFs (
eu_etf_universe.py) - Asia stocks β 76 large-caps from Japan, Hong Kong, Singapore, India, South Korea, Taiwan, and Australia (
asia_universe.py) - Asia ETFs β 20 broad-market, country-specific, and sector ETFs with significant Asian exposure (
asia_etf_universe.py)
Tickers use Yahoo Finance suffixes:
- US: no suffix (AAPL, MSFT)
- EU:
.DEXetra Β·.PAParis Β·.ASAmsterdam Β·.LLondon Β·.MCMadrid Β·.MIMilan Β·.SWSwiss - Asia:
.TTokyo Β·.HKHong Kong Β·.SISingapore Β·.NSNSE India Β·.KSKorea Β·.TWTaiwan Β·.AXAustralia
The repository includes ready-to-use ticker sets in tickers-files-examples/ for thematic analyses:
artificial_intelligence_relevant_tickers.txtbiotech_relevant_tickers.txtenergy_relevant_tickers.txteu_etfs_relevant_tickers.txtfinancial_relevant_tickers.txthealth_relevant_tickers.txtpharma_relevant_tickers.txtquantum_computing_relevant_tickers.txtsemiconductors_relevant_tickers.txtspace_relevant_tickers.txtspanish_relevant_tickers.txttechnology_relevant_tickers.txt
Example:
investdaytip -n 15 --tickers-file tickers-files-examples/artificial_intelligence_relevant_tickers.txt --export-htmlAfter export, preview the generated file in a browser by running:
./preview.shThen open the generated report from:
http://localhost:8000/<generated-file-name>.html
All market data is fetched live from Yahoo Finance via the yfinance library. Fundamentals come from Ticker.info, prices and trend metrics from Ticker.history(period="2y").
InvestDayTip includes an SQLite cache (~/.investdaytip/cache.db) created automatically on first fetch:
| Data | TTL |
|---|---|
| Prices & history | 5 minutes |
| Fundamentals (info dict) | 1 day |
The cache uses per-thread SQLite connections with a write lock to support concurrent fetches safely. Use --no-cache to bypass the cache for a single run, or --cache-clear to purge all entries. Caching is automatically disabled when running tests.
preview.sh # Local static server for generated HTML reports
src/investdaytip/
βββ __init__.py # Public API: get_recommendations
βββ main.py # CLI entry point + rich table rendering
βββ advisor.py # Interactive advisor: market pulse, portfolio review, buy recs
βββ html_export.py # Self-contained HTML report exporter
βββ recommender.py # Concurrent orchestration
βββ cache.py # SQLite caching layer (per-thread connections, WAL mode)
βββ data_source.py # yfinance wrapper + dataclasses (StockData / EtfData)
βββ scoring.py # Pure scoring functions (score_stock, score_etf)
βββ universe.py # US stock universe
βββ etf_universe.py # US ETF universe
βββ eu_universe.py # EU stock universe
βββ eu_etf_universe.py # EU UCITS ETF universe
βββ asia_universe.py # Asia stock universe
βββ asia_etf_universe.py # Asia ETF universe
portfolios/ # Portfolio ticker files
advisor_recommendations/ # Advisor-generated HTML reports (git-ignored)
tests/
βββ test_main.py # CLI helper tests
βββ test_html_export.py # HTML export tests
βββ test_scoring.py # Stock scoring tests
βββ test_etf_scoring.py # ETF scoring tests
tickers-files-examples/
βββ semiconductors_relevant_tickers.txt
βββ artificial_intelligence_relevant_tickers.txt
βββ quantum_computing_relevant_tickers.txt
βββ energy_relevant_tickers.txt
βββ space_relevant_tickers.txt
βββ technology_relevant_tickers.txt
βββ spanish_relevant_tickers.txt
βββ pharma_relevant_tickers.txt
βββ biotech_relevant_tickers.txt
βββ health_relevant_tickers.txt
βββ financial_relevant_tickers.txt
- No currency normalization β prices, market caps and AUM stay in native currency
- Currency filter (
-c) compares against yfinance's reported currency field; tickers with a missing/unknown currency are always kept (a missing field shouldn't silently drop a candidate) min_market_capfilter (--min-market-cap) is applied against raw native-currency figures; when active, tickers with a missing market cap are excluded- Some European tickers change Yahoo symbols over time; if a ticker is delisted in Yahoo it's silently skipped
- ETF expense ratios are sometimes missing in
yfinanceβ the scorer falls back to a slightly optimistic default (60) in that case - Long-term, fundamental-driven model: not suitable for short-term/day trading signals
pip install -e ".[dev]" # pytest, ruff, mypy
pytest -q # run the suite
ruff check src tests # lint
mypy # type-checkThe scoring engine is purely functional and tested without network calls; an
autouse guard in tests/conftest.py fails fast if a test reaches yfinance
unmocked.
Contributions are welcome! See CONTRIBUTING.md.
This is not financial advice. InvestDayTip is an educational tool that applies a deterministic scoring model to publicly available data. Always do your own research and consult a licensed advisor before making investment decisions.