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
CoverageDetails
MarketsS&P 500, NASDAQ, NYSE
SourcesMajor investment banks and research firms
Update FrequencyDaily
Historical Data3+ years
RatingMeaningSignal
Strong BuyHighest conviction recommendationBullish
Buy / OutperformExpect stock to beat marketBullish
Hold / NeutralExpect market performanceNeutral
UnderperformExpect stock to lag marketBearish
SellRecommend sellingBearish

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