Skip to content

Repository files navigation

Stock Assistant

AI-powered market analysis that delivers pre-market reports and trade ideas every trading day — via Telegram, web dashboard, CLI, or GitHub Actions.


Table of Contents


What It Does

  • Fetches live prices (indices, commodities, crypto) via yfinance
  • Pulls recent financial headlines from NewsAPI
  • Feeds both into an LLM (Gemini, Claude, GPT-4o, Llama) to generate analysis and trade ideas
  • Screens your watchlist for setups using configurable strategies
  • Delivers to your Telegram, a web dashboard, a CLI, or GitHub Actions artifacts

Current Architecture Status

  • The project now has a canonical deterministic pipeline: signals -> candidate merge -> signal synthesis -> portfolio decisions -> execution proposal
  • Canonical portfolio state is stored separately from messaging preferences:
    • preferences live in SQLite in core/preferences.py
    • portfolio profile / snapshot live in SQLite in core/portfolio_store.py
  • The pipeline is available through:
    • POST /api/pipeline/run
    • POST /api/proposals/build
    • GET /api/proposals/latest
    • structured report generation
    • watchlist push / Telegram watchlist summaries
    • Telegram /report and /ideas
  • Presentation is increasingly renderer-driven:
    • canonical markdown renderers now live in app/renderers/proposal_renderer.py
    • report markdown, market stock ideas, strategy reports, and Telegram proposal text now reuse those renderers
  • Legacy compatibility paths still exist, but are now explicitly marked:
    • build_screen_response() / format_screen_response() remain for older score-first consumers
    • build_personalized_report() remains as a compatibility wrapper, but now delegates to canonical pipeline helpers
    • build_structured_watchlist_report() remains as a migration fallback for symbols that do not yet map cleanly into canonical proposal output
  • Remaining work is focused on:
    • AI reliability for structured outputs
    • continuing to retire legacy score-only presentation helpers
    • expanding regression coverage

Start Here

Choose a run option first.

  • If you want the easiest setup, use Option A: GitHub Actions. You can configure notifications and report settings entirely in the GitHub web UI.
  • If you want a browser dashboard or interactive bot, use Option B/C and then do Environment Setup.
  • If you want terminal or cron usage, use Option D and then do Environment Setup.

Option A — GitHub Actions (default, no local setup)

Recommended for most users. Fork the repo, add your API keys in the GitHub UI, and get a daily Telegram report every trading day at 8:30 AM New York time — no terminal, no server, no code changes needed.

Step 1 — Fork the repository

Click Fork at the top of this page to create your own copy.

Step 2 — Add API keys as Secrets

In your forked repo: Settings → Secrets and variables → Actions → Secrets → New repository secret

Add these secrets:

Secret name Where to get it Required?
GEMINI_API_KEY aistudio.google.com — free One LLM key required
ANTHROPIC_API_KEY console.anthropic.com (or)
OPENAI_API_KEY platform.openai.com (or)
GROQ_API_KEY console.groq.com — free (or)
NEWS_API_KEY newsapi.org/register — free Yes
TELEGRAM_BOT_TOKEN Message @BotFather on Telegram → /newbot For Telegram delivery
TELEGRAM_CHAT_ID Message @userinfobot on Telegram to find yours For Telegram delivery

Step 3 — Set your watchlist and preferences (optional)

In your forked repo: Settings → Secrets and variables → Actions → Variables → New repository variable

Variable name Example value Description
WATCHLIST AAPL,NVDA,^GSPC,GC=F Tickers to track (default: ^GSPC,^IXIC,BTC-USD,GC=F,CL=F)
STRATEGIES breakout,pullback Screening strategies (default: breakout)
REPORT_LANGUAGE zh en or zh (default: en)
LLM_MODEL gemini/gemini-2.0-flash Override the LLM model. If omitted, the model is auto-selected from whichever API key is set (Gemini → gemini/gemini-2.0-flash, Anthropic → claude-haiku-4-5-20251001, OpenAI → gpt-4o-mini, Groq → groq/llama-3.3-70b-versatile).
LLM_REQUEST_DELAY_S 4 Seconds to wait between LLM calls. Set to 4 when using a free-tier provider (Gemini, Groq) to stay within the ~15 RPM limit. Default: 0 (no delay).

Step 4 — Enable the workflow

Go to the Actions tab of your fork. If prompted, click "I understand my workflows, enable them".

Step 5 — Run it once manually

Run the workflow once from GitHub to confirm your secrets and settings are correct.

Go to Actions → Stock Report → Run workflow. You can override any settings for that one run:

Input Description
watchlist Comma-separated tickers, e.g. AAPL,NVDA,^GSPC
strategies e.g. breakout,pullback,commodity_macro
language en or zh
sections watchlist / watchlist,market / watchlist,market,commodity
send_telegram true to send to Telegram, false to skip (default: false)

Step 6 — Automatic runs continue from your saved settings

After that first manual run, the workflow (.github/workflows/stock-report.yml) will keep running automatically based on the repo settings:

  • Every trading day (Mon–Fri) at 8:30 AM New York time
  • Uses your repository secrets and variables by default
  • Saves the report as a downloadable artifact in the Actions run
  • Sends the report to Telegram only if TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID are set and send_telegram is true

What the workflow does

  1. Checks out your repo
  2. Installs Python 3.11 + dependencies
  3. Runs the report script with all env vars injected
  4. Writes the report to the GitHub Actions Job Summary (visible on the run page)
  5. Uploads .md + .json report files as a downloadable artifact (kept 30 days)
  6. Sends the report to your Telegram chat (optional — skipped if tokens are not set)

Change the schedule

Edit .github/workflows/stock-report.yml in the GitHub web editor (click the pencil icon). Change the cron line:

schedule:
  - cron: "30 13 * * 1-5"   # Mon–Fri 8:30 AM ET (13:30 UTC)
  # - cron: "0 14 * * 1"    # Weekly — every Monday 9:00 AM ET
  # - cron: "0 13 * * 1-5"  # Mon–Fri 8:00 AM ET

Note on daylight saving time: GitHub Actions cron runs in UTC. 13:30 UTC = 8:30 AM EST (Nov–Mar) and 9:30 AM EDT (Mar–Nov). The report always arrives before or at the opening bell either way.


Option B — Web Dashboard & API Server

A local server with a browser UI and full REST API. Also activates scheduled Telegram pushes and the interactive Telegram bot.

Requires: Local setup first.

cd stock-assistant
python3 -m venv venv
source venv/bin/activate        # macOS / Linux
# venv\Scripts\activate         # Windows
pip install -r requirements.txt
python main.py
URL Description
http://localhost:8000 Web dashboard
http://localhost:8000/docs Interactive API explorer (Swagger UI)

The server also starts:

  • APScheduler — runs per-user scheduled Telegram pushes
  • Telegram bot — starts polling if TELEGRAM_BOT_TOKEN is set

Option C — Telegram Bot (interactive)

A conversational bot you can message any time to get on-demand reports and manage your watchlist.

Requires: The web server running (Option B). The bot starts automatically.

Setup:

  1. Message @BotFather/newbot → copy the token into TELEGRAM_BOT_TOKEN in .env
  2. Message @userinfobot on Telegram to get your chat ID → set TELEGRAM_CHAT_ID
  3. Start the server: python main.py
  4. Find your bot on Telegram and send /start

How scheduled pushes work:

Set up your schedule with a few commands:

/schedule daily          → every day at your push time
/schedule twice          → twice a day (push time + 8 h)
/schedule weekly         → every Monday at your push time
/pushtime 08:30          → set push time (24h)
/timezone America/New_York

Each scheduled push sends messages in order:

  1. Watchlist summary — trade ideas from your tickers (always included)
  2. US market overview — indices, gold, oil, Bitcoin (add with /sections watchlist,market)
  3. Commodity screen — top commodity setups (add with /sections watchlist,market,commodity)

See all bot commands in the Telegram Bot Commands section.


Option D — CLI / Cron

Generate a report from the terminal — no server required. Useful for scheduled tasks or quick spot-checks.

Requires: Local setup first.

cd stock-assistant

Minimal — print report to stdout:

python scripts/run_report.py

Custom watchlist and Telegram notification:

python scripts/run_report.py \
  --watchlist "AAPL,NVDA,^GSPC,GC=F" \
  --strategies "breakout,pullback" \
  --language en \
  --sections "watchlist,market" \
  --send-telegram

All flags (each has a matching env var as fallback):

Flag Env var Default Description
--watchlist WATCHLIST ^GSPC,^IXIC,BTC-USD Comma-separated tickers
--strategies STRATEGIES breakout Comma-separated strategy IDs
--language REPORT_LANGUAGE en en or zh
--sections REPORT_SECTIONS watchlist,market watchlist, market, commodity
--schedule weekly LLM prompt context label
--send-telegram SEND_TELEGRAM=true off Send to Telegram
--chat-id TELEGRAM_CHAT_ID Override Telegram chat ID

Reports are saved to reports/github-actions/<report_id>.md and .json.

macOS / Linux cron example (every weekday at 8:30 AM local time):

30 8 * * 1-5 cd /path/to/stock-assistant && venv/bin/python scripts/run_report.py --send-telegram

Environment Setup (local only)

Required for Options B, C, and D.

1. Create the virtual environment

cd stock-assistant

python3 -m venv venv
source venv/bin/activate        # macOS / Linux
# venv\Scripts\activate         # Windows

pip install -r requirements.txt

2. Configure API keys

cp .env.example .env

Edit .env:

# LLM_MODEL is optional — if omitted, the model is auto-selected from whichever key is set below.
# GEMINI_API_KEY=your_key_here          # → gemini/gemini-2.0-flash (free tier)
# ANTHROPIC_API_KEY=your_key_here       # → claude-haiku-4-5-20251001
# OPENAI_API_KEY=your_key_here          # → gpt-4o-mini
# GROQ_API_KEY=your_key_here            # → groq/llama-3.3-70b-versatile (free tier)

# To override the auto-selected model:
# LLM_MODEL=gemini/gemini-2.0-flash

# Free-tier rate limit guard (set to 4 for Gemini/Groq free tiers — ~15 RPM limit)
# LLM_REQUEST_DELAY_S=4

# News headlines
NEWS_API_KEY=your_key_here

# Telegram — optional. Remove or leave blank to skip Telegram delivery.
# TELEGRAM_BOT_TOKEN=your_bot_token
# TELEGRAM_CHAT_ID=your_chat_id

3. Smoke-test the core modules

python -m core.market_data    # prints a live market price snapshot
python -m core.news           # prints recent headlines
python -m core.ai_analysis    # prints an LLM-generated summary

API Reference

All endpoints available on the running local server.

Method Path Description
GET / Web dashboard
GET /api/market Raw market snapshot (no LLM)
GET /api/summary AI-generated global market summary
GET /api/analyze/{ticker} AI analysis for one ticker. Optional: ?strategy=emotion_cycle
GET /api/strategies List strategies. Optional: ?capability=analysis|screen|backtest
GET /api/strategies/{id} Full strategy config + documentation
GET /api/screen Legacy-compatible screener view. Params: strategy, asset_type, top_n, tickers
GET /api/candidates/latest Recommended canonical replacement for saved-profile/watchlist candidate views
GET /api/profile/{profile_id} Get the canonical portfolio user profile
PUT /api/profile/{profile_id} Update the canonical portfolio user profile
GET /api/portfolio/{profile_id} Get the canonical portfolio snapshot
PUT /api/portfolio/{profile_id} Update the canonical portfolio snapshot
POST /api/signals/run Run the v2 signal pipeline and return merged candidates
POST /api/pipeline/run Canonical deterministic pipeline output
POST /api/proposals/build Canonical proposal output for a request payload
GET /api/proposals/latest Canonical proposal output from saved profile preferences
GET /api/backtest Daily backtest. Params: ticker, strategy, start_date, end_date, cost params
GET /api/report/{profile_id} Generate + save a full report for a profile
GET /api/reports/{profile_id} List saved reports
GET /api/reports/{profile_id}/{report_id} Load a saved report
GET /api/reports/{profile_id}/{report_id}/download Download as ?format=md or ?format=json
GET /api/preferences/{profile_id} Get profile preferences
PUT /api/preferences/{profile_id} Update profile preferences

Interactive docs: http://localhost:8000/docs

/api/screen note:

  • This endpoint is kept for backward compatibility with older score-first consumers.
  • It is no longer the recommended entry point for new product work.
  • Prefer /api/candidates/latest as the first replacement for watchlist/profile-driven UI.
  • Prefer /api/pipeline/run when the client needs a custom ticker universe and full pipeline output.
  • Prefer /api/proposals/build or /api/proposals/latest when only proposal output is needed.

Telegram Bot Commands

On-demand

Command Description
/start Welcome message and command reference
/report Full AI dashboard for your watchlist
/fullreport Full saved markdown report for your watchlist
/summary Global market overview (indices, commodities, crypto)
/analyze TICKER Deep-dive on one ticker, e.g. /analyze AAPL
/ideas [strategy] [asset_type] [top_n] Ranked trade ideas, e.g. /ideas commodity_macro commodity 5

Watchlist management

Command Description
/watch TICKER Add a ticker, e.g. /watch NVDA
/unwatch TICKER Remove a ticker
/watchlist Show watchlist and all current settings

Scheduled push settings

Command Description
/schedule daily|twice|weekly|off Push frequency
/timezone ZONE IANA timezone, e.g. /timezone America/New_York
/pushtime HH:MM Push time in 24h local time, e.g. /pushtime 08:30
/sections watchlist,market,commodity Which sections are included in scheduled pushes
/strategy breakout,pullback Default strategies used for screening
/pushmode simple|full Scheduled push detail level
/reportmode summary|ideas|summary+ideas What watchlist reports contain
/language en|zh Report language
/risk conservative|moderate|aggressive Portfolio risk profile used by the canonical proposal flow
/maxpos N Max single-position limit, e.g. 5 for 5%
/horizon swing|day|longterm Preferred holding horizon

Strategies

ID Asset types Capabilities Description
breakout stock analysis, screen, backtest Price breaks above recent range with volume
pullback stock analysis, screen, backtest Buy the dip in an uptrend
commodity_macro commodity analysis, screen, backtest Trend + macro filter for commodities
trend_following stock, commodity analysis, screen, backtest Multi-timeframe trend alignment
mean_reversion stock, commodity analysis, screen, backtest Oversold bounce in a range
donchian_breakout stock, commodity analysis, screen, backtest Donchian channel breakout
emotion_cycle stock, commodity analysis only Sentiment and fear/greed positioning

Strategy definitions live in strategies/ — each has a .yaml (metadata) and .md (LLM prompt documentation). You can add your own by following the same format.


Switching LLM Providers

LLM_MODEL is optional. If you omit it, the model is auto-selected from whichever API key is present in the environment:

API key set Auto-selected model
GEMINI_API_KEY gemini/gemini-2.0-flash (free tier)
ANTHROPIC_API_KEY claude-haiku-4-5-20251001
OPENAI_API_KEY gpt-4o-mini
GROQ_API_KEY groq/llama-3.3-70b-versatile (free tier)

To override, set LLM_MODEL explicitly:

LLM_MODEL=gemini/gemini-2.0-flash              # Google Gemini (free)
LLM_MODEL=anthropic/claude-sonnet-4-6           # Anthropic Claude
LLM_MODEL=gpt-4o                                # OpenAI GPT-4o
LLM_MODEL=groq/llama-3.3-70b-versatile          # Groq Llama (free, fast)

All routing is handled by LiteLLM — no code changes needed.

Free-tier rate limits: Gemini and Groq free tiers allow ~15 RPM. Each report generation makes 3–5 LLM calls. Set LLM_REQUEST_DELAY_S=4 in .env to add a 4-second gap between calls and avoid hitting the limit.


Project Structure

stock-assistant/
├── main.py                       # FastAPI app + APScheduler + Telegram bot startup
├── requirements.txt
├── .env.example
├── scripts/
│   ├── run_report.py             # Standalone CLI — used by GitHub Actions and cron
│   └── validate_v2_pipeline.py   # Validation helper for the v2 canonical pipeline
├── app/
│   ├── renderers/
│   │   └── proposal_renderer.py  # Canonical markdown renderers for proposals/reports
│   └── services/
│       ├── research_service.py   # Market summaries, analysis, and legacy-compatible APIs
│       ├── report_service.py     # Report composition, persistence, push messages
│       ├── signal_service.py     # Strategy signal execution
│       ├── candidate_merge_service.py   # Multi-strategy candidate aggregation
│       ├── signal_synthesis.py   # Per-candidate synthesis layer
│       ├── portfolio_engine.py   # Portfolio-aware decision engine
│       ├── execution_planner.py  # Proposal/execution plan generation
│       └── proposal_service.py   # Canonical proposal and latest-candidate helpers
├── core/
│   ├── market_data.py            # yfinance price fetching
│   ├── news.py                   # NewsAPI with 1-hour cache
│   ├── ai_analysis.py            # LiteLLM prompt building + LLM calls
│   ├── strategy_registry.py      # Loads YAML + MD strategy definitions
│   ├── scheduler.py              # APScheduler per-user push jobs
│   ├── preferences.py            # Per-user preference store (SQLite + legacy JSON migration)
│   └── portfolio_store.py        # Canonical portfolio profile/snapshot store (SQLite)
├── domain/schemas/               # Pydantic schemas for signals, proposals, reports, portfolio
├── strategies/                   # Strategy definitions (YAML + Markdown)
├── backtesting/engine.py         # Deterministic daily backtest engine
├── channels/telegram/bot.py      # Telegram command handlers
├── data/preferences.db           # Persisted user preferences
├── data/portfolio.db             # Persisted portfolio profiles and snapshots
├── reports/<profile_id>/         # Saved reports (auto-created)
├── tests/                        # Regression coverage for the v2 pipeline and API/bot surfaces
└── web/index.html                # Dashboard frontend

.github/
└── workflows/
    └── stock-report.yml          # GitHub Actions: scheduled + manual delivery

API Keys

Service URL Notes
Google Gemini aistudio.google.com Free, instant
Anthropic Claude console.anthropic.com Pay-as-you-go
OpenAI platform.openai.com Pay-as-you-go
Groq console.groq.com Free tier, fast
NewsAPI newsapi.org/register Free, 100 req/day
Telegram Bot Message @BotFather on Telegram Free, instant

Disclaimer

All AI-generated analysis is for informational purposes only. This is not financial advice. Always do your own research before making any investment decisions.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages