Skip to content

dfdezdom/investdaytip

Repository files navigation

InvestDayTip

InvestDayTip Logo

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.

License: MIT Python 3.10+ PyPI version CI GitHub stars Last commit


Features

  • πŸ“ˆ 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 advisor subcommand
  • πŸ€– AI-powered advisor β€” chat with an intelligent investment advisor that analyzes markets, reviews portfolios, and recommends buys β€” powered by OpenCode agents

Installation

From PyPI (recommended)

pip install investdaytip

From source (for development)

git 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]"

Quick start

pip install investdaytip
investdaytip

That's it. You'll see the top 5 buys scored across 300+ stocks & ETFs.

InvestDayTip CLI output


Usage

CLI

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

Options

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

Advisor subcommand

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 portfolio

See investdaytip advisor --help for all options.

OpenCode AI Agent

πŸ€– 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?

HTML export

Generate an interactive report that works offline (single file with inline CSS/JS):

investdaytip -n 25 -a all -r all --export-html investdaytip-report.html

The 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.

Programmatic API

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 & ETFs

Output

Each 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

Scoring Model

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.

Stocks (Graham/Buffett + Momentum)

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

ETFs

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

Universes

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: .DE Xetra Β· .PA Paris Β· .AS Amsterdam Β· .L London Β· .MC Madrid Β· .MI Milan Β· .SW Swiss
  • Asia: .T Tokyo Β· .HK Hong Kong Β· .SI Singapore Β· .NS NSE India Β· .KS Korea Β· .TW Taiwan Β· .AX Australia

Ticker File Examples

The repository includes ready-to-use ticker sets in tickers-files-examples/ for thematic analyses:

  • artificial_intelligence_relevant_tickers.txt
  • biotech_relevant_tickers.txt
  • energy_relevant_tickers.txt
  • eu_etfs_relevant_tickers.txt
  • financial_relevant_tickers.txt
  • health_relevant_tickers.txt
  • pharma_relevant_tickers.txt
  • quantum_computing_relevant_tickers.txt
  • semiconductors_relevant_tickers.txt
  • space_relevant_tickers.txt
  • spanish_relevant_tickers.txt
  • technology_relevant_tickers.txt

Example:

investdaytip -n 15 --tickers-file tickers-files-examples/artificial_intelligence_relevant_tickers.txt --export-html

After export, preview the generated file in a browser by running:

./preview.sh

Then open the generated report from:

http://localhost:8000/<generated-file-name>.html

Data Source

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").

Local Cache

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.


Project Structure

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

Limitations & Caveats

  • 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_cap filter (--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

Testing

pip install -e ".[dev]"   # pytest, ruff, mypy
pytest -q                 # run the suite
ruff check src tests      # lint
mypy                      # type-check

The 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.


Contributing

Contributions are welcome! See CONTRIBUTING.md.


Disclaimer

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.


License

MIT

About

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.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors

Languages