Skip to content

Analyst Ratings Dataset

Access Wall Street analyst ratings, price targets, and recommendation changes. Track consensus ratings and target price movements for systematic trading strategies.

The Analyst Ratings dataset provides:

  • Current Rating: Buy, hold, or sell recommendation
  • Price Target: Analyst’s target price (with historical changes)
  • Analyst Info: Firm name and rating action
  • Rating Changes: Upgrades, downgrades, and reiterations
  • Historical Data: Track rating changes over time
Coverage Details
Markets S&P 500, NASDAQ, NYSE
Sources Major investment banks and research firms
Update Frequency Daily
Historical Data 3+ years
Rating Meaning Signal
Strong Buy Highest conviction recommendation Bullish
Buy / Outperform Expect stock to beat market Bullish
Hold / Neutral Expect market performance Neutral
Underperform Expect stock to lag market Bearish
Sell Recommend selling Bearish

Note: The targetPrice field is a string (e.g., "$275").

from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
df = fb.analyst_ratings.ticker("AAPL", as_dataframe=True)
print(df)

For complete code examples in Python, JavaScript, C++, Rust, and cURL, see the API Reference.

Scan for recent rating changes:

from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
def scan_rating_changes(tickers):
"""Find stocks with recent upgrades or downgrades"""
upgrades = []
downgrades = []
for symbol in tickers:
try:
df = fb.analyst_ratings.ticker(symbol, as_dataframe=True)
for _, row in df.head(5).iterrows(): # Last 5 ratings
if row["action"] == "Upgrade":
upgrades.append({
"symbol": symbol,
"institution": row["institution"],
"rating": row["rating"],
"targetPrice": row["targetPrice"],
"date": row.name
})
elif row["action"] == "Downgrade":
downgrades.append({
"symbol": symbol,
"institution": row["institution"],
"rating": row["rating"],
"targetPrice": row["targetPrice"],
"date": row.name
})
except Exception:
continue
return {"upgrades": upgrades, "downgrades": downgrades}
tickers = ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA", "META", "TSLA"]
changes = scan_rating_changes(tickers)
print("Recent Upgrades:")
for u in changes["upgrades"]:
print(f" {u['symbol']}: {u['institution']} -> {u['rating']} ({u['targetPrice']})")
print("\nRecent Downgrades:")
for d in changes["downgrades"]:
print(f" {d['symbol']}: {d['institution']} -> {d['rating']} ({d['targetPrice']})")

Calculate upside potential to consensus target:

import re
from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
def parse_target_price(target_str):
"""Parse target price string like '$275' and return numeric value"""
if not target_str:
return None
# Match price patterns like $190, $205.50, etc.
prices = re.findall(r'\$?([\d,]+\.?\d*)', str(target_str).replace(',', ''))
if prices:
# Return the last price (new target) or only price
return float(prices[-1])
return None
def calculate_upside(symbol, current_price):
"""Calculate upside to analyst target"""
df = fb.analyst_ratings.ticker(symbol, as_dataframe=True)
if df.empty:
return None
# Parse target prices from string format
targets = []
for target_str in df["targetPrice"]:
target = parse_target_price(target_str)
if target:
targets.append(target)
if not targets:
return None
avg_target = sum(targets) / len(targets)
upside = ((avg_target - current_price) / current_price) * 100
return {
"symbol": symbol,
"current_price": current_price,
"avg_target_price": round(avg_target, 2),
"upside_percent": round(upside, 2),
"num_analysts": len(targets)
}
# Example usage (you'd get current price from market data)
result = calculate_upside("AAPL", 185.00)
if result:
print(f"{result['symbol']}: {result['upside_percent']}% upside to ${result['avg_target_price']}")

Track how analyst sentiment is changing over time:

from finbrain import FinBrainClient
fb = FinBrainClient(api_key="YOUR_API_KEY")
def analyze_rating_trend(symbol):
"""Analyze if analyst sentiment is improving or deteriorating"""
df = fb.analyst_ratings.ticker(symbol, as_dataframe=True)
rating_scores = {
"Sell": 1, "Underperform": 2, "Hold": 3, "Neutral": 3,
"Buy": 4, "Outperform": 4, "Overweight": 4, "Strong Buy": 5
}
df["score"] = df["rating"].map(rating_scores).fillna(3)
if len(df) < 2:
return "insufficient_data"
recent_avg = df["score"].head(5).mean()
older_avg = df["score"].iloc[5:10].mean() if len(df) > 5 else recent_avg
if recent_avg > older_avg + 0.3:
return "improving"
elif recent_avg < older_avg - 0.3:
return "deteriorating"
else:
return "stable"
trend = analyze_rating_trend("AAPL")
print(f"Analyst sentiment: {trend}")