Real-time and Historical Analyst Ratings API

·

6 min read

I code small internal products and provide consultancy for finance platforms. The Analyst Ratings API I have been using recently (which is by Finnworlds) is a 3-endpoint analyst rating and consensus data source with the REST structure. The API responds in JSON with other formats available upon request. I know this as I asked them if we could get CSV and they said this could be possible. This is a useful API to fetch and implement stock price rating and estimation data as reported by analysts and financial experts. The coverage is for all sectors and industries you can use to program solutions for all actors.


Taking a Look at The Analyst Ratings API Endpoints

You can fetch ratings and consensus data via the company ratings API under 3 endpoints that focus on different aspects. You might find consensus ratings data (which is endpoint 3) useful in particular as you can fetch stock price estimation data with it for technical analysis.

Basically, the first (company ratings data) endpoint allows fetching data based on company, the second (analyst ratings data) based on individual analysts or ratings of all analysts in an analyst firm and the third (consensus ratings data) a consensus of all analyst ratings with price targets for upcoming quarters.

  1. Company Ratings Data

api.finnworlds.com/api/v1/companyratings?ke..

{
    "status": {
        "code": 200,
        "message": "OK",
        "details": ""
    },
    "result": {
        "basics": {
            "company_name": "Apple Inc",
            "ticker": "AAPL"
        },
        "output": {
            "analyst_consensus": {
                "consensus_conclusion": "",
                "stock_price": "179.23",
                "analyst_average": "205.20",
                "analyst_highest": "240.00",
                "analyst_lowest": "150.00",
                "analysts_number": "28",
                "buy": "21",
                "hold": "7",
                "sell": "",
                "consensus_date": "2023-11-07"
            },
            "analysts": [
                {
                    "analyst_name": "samik chatterjee",
                    "analyst_firm": "J.P. Morgan",
                    "analyst_role": "analyst",
                    "rating": {
                        "date_rating": "2023-11-06",
                        "target_date": "2024-11-06",
                        "price_target": "225.0",
                        "rated": "Buy",
                        "conclusion": "rated"
                    }
                },
                {
                    "analyst_name": "brian white",
                    "analyst_firm": "Monness",
                    "analyst_role": "analyst",
                    "rating": {
                        "date_rating": "2023-11-03",
                        "target_date": "2024-11-03",
                        "price_target": "189.0",
                        "rated": "Buy",
                        "conclusion": "maintained"
                    }
                },
                {
                    "analyst_name": "aaron rakers",
                    "analyst_firm": "Wells Fargo",
                    "analyst_role": "analyst",
                    "rating": {
                        "date_rating": "2023-11-02",
                        "target_date": "2024-11-02",
                        "price_target": "225.0",
                        "rated": "Buy",
                        "conclusion": "maintained"
                    }
                },
....
                    }
                }
            ]
        }
    }
}

Now let’s calculate the average price target from the analysts' ratings:

function calculateAveragePriceTarget(analystsRatings) {
  if (!analystsRatings || analystsRatings.length === 0) {
    return 0;
  }

  const sumPriceTarget = analystsRatings.reduce((acc, analyst) => {
    return acc + parseFloat(analyst.rating.price_target);
  }, 0);

  return (sumPriceTarget / analystsRatings.length).toFixed(2); // rounding to 2 decimal places
}

// Example usage within the getAnalystRatings function, after data is retrieved:
const averagePriceTarget = calculateAveragePriceTarget(response.data.result.output.analysts);
console.log(`The average price target from analysts is: $${averagePriceTarget}`);

  1. Analyst Ratings Data

api.finnworlds.com/api/v1/analystratings?ke..

{
    "status": {
        "code": 200,
        "message": "OK",
        "details": ""
    },
    "result": {
        "basics": {
            "firm": "Wedbush"
        },
        "output": [
            {
                "analyst_name": "seth basham",
                "analyst_firm": "Wedbush",
                "analyst_role": "Analyst",
                "ratings": [
                    [
                        {
                            "ticker": "FND",
                            "company_name": "Floor & Decor Holdings",
                            "rating": {
                                "date_rating": "2023-11-03",
                                "target_date": "2024-11-03",
                                "price_target": "85.0",
                                "rated": "Buy",
                                "conclusion": "maintained"
                            },
                            "analyst_consensus": {
                                "consensus_conclusion": "",
                                "stock_price": "77.83",
                                "analyst_average": "92.00",
                                "analyst_highest": "115.00",
                                "analyst_lowest": "71.00",
                                "analysts_number": "11",
                                "buy": "5",
                                "hold": "6",
                                "sell": "",
                                "consensus_date": "2023-11-07"
                            }
                        },
                        {
                            "ticker": "ETSY",
                            "company_name": "Etsy Inc",
                            "rating": {
                                "date_rating": "2023-11-02",
                                "target_date": "2024-11-02",
                                "price_target": "60.0",
                                "rated": "Hold",
                                "conclusion": "maintained"
                            },
                            "analyst_consensus": {
                                "consensus_conclusion": "",
                                "stock_price": "63.08",
                                "analyst_average": "82.95",
                                "analyst_highest": "157.00",
                                "analyst_lowest": "50.00",
                                "analysts_number": "22",
                                "buy": "12",
                                "hold": "8",
                                "sell": "2",
                                "consensus_date": "2023-11-07"
                            }
                        },
                        {
                            "ticker": "TSCO",
                            "company_name": "Tractor Supply Company",
                            "rating": {
                                "date_rating": "2023-10-27",
                                "target_date": "2024-10-27",
                                "price_target": "200.0",
                                "rated": "Hold",
                                "conclusion": "maintained"
                            },
                            "analyst_consensus": {
                                "consensus_conclusion": "",
                                "stock_price": "199.25",
                                "analyst_average": "219.81",
                                "analyst_highest": "265.00",
                                "analyst_lowest": "192.00",
                                "analysts_number": "21",
                                "buy": "12",
                                "hold": "9",
                                "sell": "",
                                "consensus_date": "2023-11-07"
                            }
                        },
……
                           }
                        }
                    ]
                ]
            }
        ]
    }
}

Now example Code Snippet to fetch analyst ratings data via GET:

const axios = require('axios');

const API_KEY = 'your_api_key_here'; // Replace with your API key
const ANALYST_FIRM = 'wedbush';
const ENDPOINT = `https://api.finnworlds.com/api/v1/analystratings?key=${API_KEY}&analyst_firm=${ANALYST_FIRM}`;

axios.get(ENDPOINT)
  .then(response => {
    // The data is available in response.data
    console.log('Status:', response.data.status);
    console.log('Result:', response.data.result);
  })
  .catch(error => {
    // Handle any errors here
    console.error('Error fetching analyst ratings:', error);
  });

TIP: If you're using ES6 or above, or TypeScript, you can also use async/await for cleaner syntax:

const axios = require('axios');

const fetchAnalystRatings = async () => {
  const API_KEY = 'your_api_key_here'; // Replace with your API key
  const ANALYST_FIRM = 'wedbush';
  const ENDPOINT = `https://api.finnworlds.com/api/v1/analystratings?key=${API_KEY}&analyst_firm=${ANALYST_FIRM}`;

  try {
    const response = await axios.get(ENDPOINT);
    console.log('Status:', response.data.status);
    console.log('Result:', response.data.result);
  } catch (error) {
    console.error('Error fetching analyst ratings:', error);
  }
};

fetchAnalystRatings();

  1. Analyst Consensus Ratings Data

api.finnworlds.com/api/v1/consensusratings?..

{
    "status": {
        "code": 200,
        "message": "OK",
        "details": ""
    },
    "result": {
        "basics": {
            "company_name": "Microsoft",
            "ticker": "MSFT"
        },
        "output": {
            "analyst_consensus": {
                "consensus_conclusion": "",
                "stock_price": "356.53",
                "analyst_average": "408.97",
                "analyst_highest": "450.00",
                "analyst_lowest": "375.00",
                "analysts_number": "29",
                "buy": "29",
                "hold": "0",
                "sell": "0",
                "consensus_date": "2023-11-07"
            },
            "earnings_estimate": {
                "previous_quarter": {
                    "analysts_number": "34",
                    "average_estimate": "2.5",
                    "low_estimate": "2.41",
                    "high_estimate": "2.58",
                    "last_year_eps": "2.35",
                    "date": "quarter3_23"
                },
                "current_quarter": {
                    "analysts_number": "34",
                    "average_estimate": "2.5",
                    "low_estimate": "2.36",
                    "high_estimate": "2.71",
                    "last_year_eps": "2.32",
                    "date": "quarter4_23"
                },
                "next_quarter": "",
                "next_year": {
                    "analysts_number": "45",
                    "average_estimate": "10.35",
                    "low_estimate": "10",
                    "high_estimate": "11.09",
                    "last_year_eps": "9.81",
                    "year": "2024"
                }
            },
            "earnings_history": {
                "3_month_ago": "",
                "6_month_ago": {
                    "estimated_eps": "2.55",
                    "real_eps": "2.69",
                    "difference_points": "0.14",
                    "difference_perc": "5.50%",
                    "date": "quarter2_23"
                },
                "9_month_ago": {
                    "estimated_eps": "2.23",
                    "real_eps": "2.45",
                    "difference_points": "0.22",
                    "difference_perc": "9.90%",
                    "date": "quarter1_23"
                },
                "12_month_ago": {
                    "estimated_eps": "2.29",
                    "real_eps": "2.32",
                    "difference_points": "0.03",
                    "difference_perc": "1.30%",
                    "date": "quarter4_22"
                }
            },
            "revenue_estimate": {
                "previous_quarter": {
                    "analysts_number": "33",
                    "average_estimate": "51.4B",
                    "low_estimate": "50.8B",
                    "high_estimate": "52.2B",
                    "sales_last_year": "49.61B",
                    "growth_perc": "3.60%",
                    "date": "quarter3_23"
                },
                "current_quarter": {
                    "analysts_number": "33",
                    "average_estimate": "55.08B",
                    "low_estimate": "53.92B",
                    "high_estimate": "56.4B",
                    "sales_last_year": null,
                    "growth_perc": null,
                    "date": "quarter4_23"
                },
                "next_quarter": "",
                "next_year": {
                    "analysts_number": "49",
                    "average_estimate": "222B",
                    "low_estimate": "217.42B",
                    "high_estimate": "227.86B",
                    "sales_last_year": "211.91B",
                    "growth_perc": "4.80%",
                    "year": "2024"
                }
            }
        }
    }
}

First, we request analyst consensus ratings API using GET by running npm install axios. This script defines an async function getAnalystConsensus which uses axios.get to make a GET request to the API.

const axios = require('axios');

// Replace 'YOUR_API_KEY' with your actual API key
const apiKey = 'YOUR_API_KEY';
const ticker = 'MSFT';
const url = `https://api.finnworlds.com/api/v1/consensusratings?key=${apiKey}&ticker=${ticker}`;

async function getAnalystConsensus() {
  try {
    const response = await axios.get(url);
    const data = response.data;

    // Handling the status and result separately
    if (data.status && data.status.code === 200) {
      console.log('Successfully retrieved analyst consensus ratings:', data.result);
    } else {
      console.error('API returned an error:', data.status);
    }
  } catch (error) {
    console.error('Error while fetching the data:', error);
  }
}

getAnalystConsensus();

Another example snippet to filters data to just consensus details within the Consensus Ratings API output:

function extractConsensusDetails(data) {
  if (data && data.result && data.result.output && data.result.output.analyst_consensus) {
    return data.result.output.analyst_consensus;
  }
  return null;
}

// ... Inside the try block of the getAnalystConsensus function, after you get the response:
const consensusDetails = extractConsensusDetails(data);
if (consensusDetails) {
  console.log('Analyst Consensus Details:', consensusDetails);
}

TIP!

Historical analyst ratings data: In case you need historical data to analyse performance based on past ratings, this is also available even though I haven’t featured this on this post since I don’t need it for my current project. The API has date parameters to fetch past analyst ratings data you can feed to your machine learning projects. You should refer to their documentation for details.


Analyst Ratings API Summary

Wow that was a long post. Basically, you can implement analyst ratings data to get:

  • Target and rating dates, price targets, analyst name and firm details

  • Analyst buy/sell hold recommendations

  • Highest, lowest, average analyst price stock estimations with total analyst numbers

  • Last year sales and growth percentage estimations

  • Analyst consensus price targets for upcoming quarters

This is not a paid partnership by Finnworlds, so all I can refer to is their website if you want your own personal API key to try things out. My personal opinion is that this data is worth implementing with the codes that I worked pretty hard on. Check them out here.