DEV Community

Abhijeet Giri
Abhijeet Giri

Posted on

I built an AI stock & crypto research bot for Telegram — here's how

I've been trading stocks and crypto on the side for a while, and I got tired of opening 5 different tabs just to research a ticker before making a move. So I built AI Research Pro — a Telegram bot that brings real-time prices, AI analysis, news, and alerts into one place.

Here's what it does and how I built it.

What it does

  • /price AAPL — real-time price, change %, volume, market cap
  • /analyze TSLA — Groq-powered AI gives a buy/hold/sell summary with key metrics
  • /news BTC — latest headlines for any stock or crypto
  • /movers — top gainers and losers across stocks and crypto right now
  • /alert NVDA 900 — price alert that notifies you when hit
  • /watchlist — track your portfolio of tickers
  • /briefing — daily AI-generated market summary delivered to you

Try it here: https://t.me/AIResearchProbot

Tech stack

  • python-telegram-bot (v21.6 with job-queue) for the bot framework
  • yfinance for stock data (prices, fundamentals, news)
  • CoinGecko API for crypto prices
  • Groq API (llama-3.1-8b-instant) for the AI analysis — it's blazing fast and free-tier friendly
  • SQLite for user data, watchlists, and alerts
  • Railway for hosting (auto-restarts on failure)

The trickiest bug I fixed

yfinance changed their news item structure in v0.2.40. Old code accessed item["title"] directly. New structure nests everything under item["content"]["title"]. This silently broke /news — it returned 0 results with no error.

Fix: a helper that detects both formats:

def _parse_news_item(item: dict) -> tuple[str, str, str, str]:
    if "content" in item:
        c = item["content"]
        title = c.get("title", "")
        publisher = c.get("provider", {}).get("displayName", "")
        link = (c.get("canonicalUrl") or c.get("clickThroughUrl") or {}).get("url", "")
        pub_date = c.get("pubDate", "")
        try:
            dt_str = datetime.fromisoformat(pub_date.replace("Z", "+00:00")).strftime("%b %d, %H:%M")
        except Exception:
            dt_str = ""
    else:
        title = item.get("title", "")
        publisher = item.get("publisher", "")
        link = item.get("link", "")
        ts = item.get("providerPublishTime", 0)
        dt_str = datetime.fromtimestamp(ts).strftime("%b %d, %H:%M") if ts else ""
    return title, publisher, link, dt_str
Enter fullscreen mode Exit fullscreen mode

AI analysis prompt engineering

The AI gets a structured context block with price, P/E, EPS, 52-week range, volume, and recent news headlines. The prompt asks for: current sentiment, key strengths/risks, and a brief buy/hold/sell take. Keeping the context tight keeps Groq's latency under 2 seconds.

What's next

  • Options flow data
  • Portfolio tracking with P&L
  • Premium tier with more analysis depth

If you're into markets or building bots, give it a try: https://t.me/AIResearchProbot

Happy to answer questions about the tech or share more code snippets below.

Top comments (0)