Create an AI Watchlist Assistant That Explains Why a Stock Is Trending



This content originally appeared on Level Up Coding – Medium and was authored by Pranjal Saxena

Turn your static watchlist into a smart assistant using FMP’s Quote and News APIs with Groq AI

Photo by Nataliya Vaitkevich

Every investor has a watchlist. You open your trading app, see your favorite tickers lined up, and watch the numbers move. Apple is up 2%, Tesla is down 3%, NVIDIA is flashing green. But here’s the problem: those numbers don’t tell you why.

Is Apple up because of a new product launch? Did Tesla drop after weak delivery numbers? Is NVIDIA trending on record chip sales? Without context, a watchlist is just a blinking dashboard of prices, leaving you guessing at the real story.

That’s what we’re going to fix. In this article, we’ll build an AI Watchlist Assistant. It won’t just show you stock prices — it will tell you why a stock is trending. We’ll use FMP’s APIs to fetch live prices and the latest headlines, and then let a Groq-powered AI explain the movement in plain English.

By the end, you’ll have a smart watchlist that connects price action with context. Instead of staring at numbers, you’ll see the reasons behind them.

To explain why a stock is trending, we need two things:

  1. The numbers — how much the stock moved.
  2. The story — what events or news might explain that move.

FMP provides both through its APIs.

Stock Prices: Quote API

The Quote API gives us real-time prices and percentage changes. For example, to get Apple’s quote:

https://financialmodelingprep.com/api/v3/quote/AAPL?apikey=YOUR_KEY

Trimmed JSON response:

[
{
"symbol": "AAPL",
"price": 228.29,
"changesPercentage": 2.15,
"dayHigh": 229.47,
"dayLow": 224.80,
"volume": 45238100
}
]

From here, we’ll focus on price and changesPercentage.

Stock News: News API

The Stock News API gives us the latest headlines for each ticker. For Apple:

https://financialmodelingprep.com/api/v3/stock_news?tickers=AAPL&limit=5&apikey=YOUR_KEY

Trimmed JSON response:

[
{
"symbol": "AAPL",
"publishedDate": "2025-09-12 14:30:00",
"title": "Apple reports record iPhone 16 sales in first week",
"site": "Reuters",
"url": "https://www.reuters.com/..."
},
{
"symbol": "AAPL",
"publishedDate": "2025-09-11 09:00:00",
"title": "Apple unveils AI-powered camera features",
"site": "Bloomberg",
"url": "https://www.bloomberg.com/..."
}
]

Here, title and publishedDate give us the context behind the move.

With just these two APIs, we have everything we need: numbers + context. Next, we’ll use them to build the watchlist backbone.

Building the Watchlist Backbone

A watchlist is nothing more than a list of tickers you care about. To make it useful, we’ll pull both the latest quotes and recent news for each ticker, then store everything in a structured format.

Let’s start with a simple watchlist:

watchlist = ["AAPL", "TSLA", "NVDA"]

Step 1 — Fetch quotes for all tickers

import requests
import pandas as pd

API = "https://financialmodelingprep.com/api/v3"
KEY = "YOUR_API_KEY"

def get_quotes(tickers):
url = f"{API}/quote/{','.join(tickers)}?apikey={KEY}"
return requests.get(url).json()

quotes = get_quotes(watchlist)
pd.DataFrame(quotes)[["symbol","price","changesPercentage"]]

Output:

  symbol   price  changesPercentage
0 AAPL 228.29 2.15
1 TSLA 271.52 -3.20
2 NVDA 134.74 4.85

Step 2 — Fetch news for each ticker

def get_news(ticker, limit=3):
url = f"{API}/stock_news?tickers={ticker}&limit={limit}&apikey={KEY}"
return requests.get(url).json()

# Example: latest Apple headlines
news = get_news("AAPL")
pd.DataFrame(news)[["publishedDate","title"]]

Output:

  publishedDate                        title
0 2025-09-12 Apple reports record iPhone 16 sales
1 2025-09-11 Apple unveils AI-powered camera features
2 2025-09-10 Analysts raise price target on Apple

Step 3 — Combine quotes + news

We can now bring it all together by pairing each stock’s price change with its latest headlines.

watchlist_data = []

for ticker in watchlist:
q = next(item for item in quotes if item["symbol"] == ticker)
n = get_news(ticker, limit=2)
watchlist_data.append({
"symbol": ticker,
"price": q["price"],
"change_pct": q["changesPercentage"],
"headlines": [x["title"] for x in n]
})

pd.DataFrame(watchlist_data)

Output:

  symbol   price  change_pct                                  headlines
0 AAPL 228.29 2.15 [Apple reports record iPhone 16 sales, Apple unveils AI-powered camera features]
1 TSLA 271.52 -3.20 [Tesla misses delivery estimates, Tesla faces regulatory scrutiny in Europe]
2 NVDA 134.74 4.85 [NVIDIA posts record GPU sales, NVIDIA announces AI partnerships]

Now we have a living watchlist: not just prices, but also the context that explains what’s happening.

Adding AI Context: Why Is This Stock Moving?

Prices tell you what moved. Headlines tell you what happened. Your AI explains why it matters — in one clear line.

We’ll use a free Groq LLM to read each ticker’s price move and 1–3 latest headlines, then produce a short, human-readable reason.

Step 1 — A tiny prompt that works

We’ll keep the prompt simple and ask the model to return structured JSON so it’s easy to render.

import requests, json

GROQ_API_KEY = "YOUR_GROQ_KEY"
GROQ_URL = "https://api.groq.com/openai/v1/chat/completions"
MODEL = "llama-3.1-8b-instruct"

def explain_trend(symbol, price, change_pct, headlines):
system = "You turn price moves + headlines into a concise explanation. Respond as JSON."
user = {
"symbol": symbol,
"price": price,
"change_pct": change_pct,
"headlines": headlines
}
payload = {
"model": MODEL,
"messages": [
{"role":"system","content":system},
{"role":"user","content":json.dumps(user)}
],
"temperature": 0,
"response_format": {"type":"json_object"}
}
headers = {"Authorization": f"Bearer {GROQ_API_KEY}"}
r = requests.post(GROQ_URL, headers=headers, json=payload, timeout=30)
content = r.json()["choices"][0]["message"]["content"]
return json.loads(content)

Step 2 — Run explanations for the whole watchlist

We’ll reuse watchlist_data from Section 3.

def explain_watchlist(rows):
out = []
for row in rows:
resp = explain_trend(
symbol=row["symbol"],
price=row["price"],
change_pct=row["change_pct"],
headlines=row["headlines"]
)
# Expected keys: reason (str), drivers (list[str]), confidence (0-1)
out.append({
"symbol": row["symbol"],
"price": row["price"],
"change_pct": row["change_pct"],
"reason": resp.get("reason",""),
"drivers": ", ".join(resp.get("drivers", [])),
"confidence": resp.get("confidence", None)
})
return out

explanations = explain_watchlist(watchlist_data)
import pandas as pd
pd.DataFrame(explanations)[["symbol","change_pct","reason","drivers","confidence"]]

Output:

  symbol  change_pct                              reason                                 drivers                    confidence
0 AAPL 2.15 Up after strong iPhone 16 sales data. record sales, analyst upgrades 0.83
1 TSLA -3.20 Down on delivery miss and EU scrutiny. delivery miss, regulatory headlines 0.72
2 NVDA 4.85 Higher on record GPU demand and AI deals. record sales, AI partnerships 0.86

That’s it — your watchlist now explains itself in one glance.

Tip: Keep explanations tight (≤ 25 words). If you want more detail, add a second field like summary_long, but show the short reason by default to stay scannable.

AI Watchlist Assistant in Action

Below is a compact, script that:

  1. defines your watchlist,
  2. pulls quotes + news from FMP,
  3. calls Groq to explain the move, and
  4. prints a clean table you can export.
Replace YOUR_FMP_KEY and YOUR_GROQ_KEY before running.
# --- Setup
import requests, json, pandas as pd

FMP_API = "https://financialmodelingprep.com/api/v3"
FMP_KEY = "YOUR_FMP_KEY"

GROQ_API_KEY = "YOUR_GROQ_KEY"
GROQ_URL = "https://api.groq.com/openai/v1/chat/completions"
MODEL = "llama-3.1-8b-instruct"

watchlist = ["AAPL", "TSLA", "NVDA"] # edit as you like

# --- Data helpers
def get_quotes(tickers):
url = f"{FMP_API}/quote/{','.join(tickers)}?apikey={FMP_KEY}"
return requests.get(url, timeout=30).json()

def get_news(ticker, limit=3):
url = f"{FMP_API}/stock_news?tickers={ticker}&limit={limit}&apikey={FMP_KEY}"
return requests.get(url, timeout=30).json()

# --- Build watchlist backbone (prices + headlines)
quotes = {q["symbol"]: q for q in get_quotes(watchlist)}
rows = []
for t in watchlist:
q = quotes.get(t, {})
news = get_news(t, limit=2)
rows.append({
"symbol": t,
"price": q.get("price"),
"change_pct": q.get("changesPercentage"),
"headlines": [n.get("title") for n in news if n.get("title")]
})

# --- Groq explainer
def explain_trend(symbol, price, change_pct, headlines):
system = "You turn price moves + headlines into a concise explanation. Respond as JSON with keys: reason(str, <=25 words), drivers(list[str]), confidence(float 0-1)."
user = {"symbol": symbol, "price": price, "change_pct": change_pct, "headlines": headlines}
payload = {
"model": MODEL,
"messages": [
{"role": "system", "content": system},
{"role": "user", "content": json.dumps(user)}
],
"temperature": 0,
"response_format": {"type":"json_object"}
}
headers = {"Authorization": f"Bearer {GROQ_API_KEY}"}
r = requests.post(GROQ_URL, headers=headers, json=payload, timeout=30)
content = r.json()["choices"][0]["message"]["content"]
try:
return json.loads(content)
except Exception:
return {"reason": "Context insufficient.", "drivers": [], "confidence": 0.0}

# --- Generate explanations
out = []
for r in rows:
resp = explain_trend(r["symbol"], r["price"], r["change_pct"], r["headlines"])
out.append({
"symbol": r["symbol"],
"price": r["price"],
"change_%": r["change_pct"],
"reason": resp.get("reason", ""),
"drivers": ", ".join(resp.get("drivers", [])),
"confidence": resp.get("confidence", None)
})

df = pd.DataFrame(out, columns=["symbol","price","change_%","reason","drivers","confidence"])
print(df.to_string(index=False))

# Optional: save for reporting
# df.to_csv("ai_watchlist_explanations.csv", index=False)

What you get: a neat table like

symbol  price  change_%                               reason                              drivers  confidence
AAPL 228.3 2.15 Up on strong iPhone sales, analyst lifts. record sales, analyst upgrade 0.82
TSLA 271.5 -3.20 Down after delivery miss, EU scrutiny. delivery miss, regulatory headlines 0.73
NVDA 134.7 4.85 Higher on record GPU demand and AI deals. record demand, AI partnerships 0.86

Now your watchlist doesn’t just show moves — it explains them in one line.

Conclusion

We just built an AI Watchlist Assistant that doesn’t stop at prices — it explains the why behind stock moves. Using FMP’s Quote and News APIs, we pulled real-time numbers and headlines, then added a Groq-powered layer to turn them into plain-English insights. The result is a watchlist that saves you time and adds context to every move.

You can extend it further with volume signals, gainers/losers, or even alerts. Try it with your own tickers — with FMP as the data backbone, your watchlist becomes an intelligent assistant, not just a price board.


Create an AI Watchlist Assistant That Explains Why a Stock Is Trending was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding – Medium and was authored by Pranjal Saxena