FMP
Nov 24, 2025
In today's world, quick and dependable information is vital across almost all sectors. This importance is particularly evident in trading, where the stakes are high and the margin between a profitable trade and a loss can be very narrow.
The FMP Stock Quote API offers a powerful solution for accessing detailed stock price information in a single request. It caters to both retail investors who have experience with APIs and investment firms aiming to keep track of their portfolio valuations. Additionally, users can set up notifications to alert them about market openings or major fluctuations in stock prices, enhancing their ability to respond to market changes effectively.
To call the specific endpoint, you will need
|
import requests symbol = 'AAPL' apikey = 'YOUR FMP API KEY' url = 'https://financialmodelingprep.com/stable/quote' params = {'apikey': apikey, 'symbol':symbol} r = requests.get(url, params=params) data = r.json() data |
By calling this url (https://financialmodelingprep.com/stable/quote), you will get a list of one dictionary with the following data:
|
[ { "symbol": "AAPL", "name": "Apple Inc.", "price": 268.47, "changePercentage": -0.48189, "change": -1.3, "volume": 45140079, "dayLow": 266.82, "dayHigh": 272.29, "yearHigh": 277.32, "yearLow": 169.21, "marketCap": 3967020108000, "priceAvg50": 252.2522, "priceAvg200": 224.3975, "exchange": "NASDAQ", "open": 269.795, "previousClose": 269.77, "timestamp": 1762549202 } ] |
As you will see, the response is a list that includes a dictionary with various datapoints. Let's see what each datapoint represents:
|
Field |
Description |
|
symbol |
Ticker symbol identifying the stock or security uniquely. |
|
name |
Full name of the company or financial instrument. |
|
price |
Current trading price of the stock in the market. |
|
changePercentage |
Percent change in stock price compared to previous close. |
|
change |
Absolute change in price since the last trading session. |
|
volume |
Total number of shares traded during the current session. |
|
dayLow |
Lowest price reached by the stock during today's trading day. |
|
dayHigh |
Highest price reached by the stock during today's trading day. |
|
yearHigh |
Highest price the stock has traded at in last year. |
|
yearLow |
Lowest price the stock has traded at in last year. |
|
marketCap |
Total market value of the company's outstanding shares. |
|
priceAvg50 |
Average stock price over the past 50 trading days. |
|
priceAvg200 |
Average stock price over the past 200 trading days. |
|
exchange |
Stock exchange where the security is listed and traded. |
|
open |
Opening price of the stock at the start of trading day. |
|
previousClose |
Final trading price at market close from previous day. |
|
timestamp |
Unix timestamp indicating the time of the quoted data. |
Let's explore what additional interesting data we can derive from these data points using their code snippet.
One key insight from pricing data is identifying the stock's momentum: whether it's trending up or down. The following method shows a common approach: comparing a slow and a fast moving average. These averages are efficiently precomputed with this API, with the slow being 200 days and the fast being 50 days.
|
d = data[0] price = d.get('price') priceAvg50 = d.get('priceAvg50') priceAvg200 = d.get('priceAvg200')
if priceAvg50 > priceAvg200: trend_signal = "Uptrend (bullish momentum)" elif priceAvg50 < priceAvg200: trend_signal = "Downtrend (bearish momentum)" else: trend_signal = "Neutral/transition"
if price > priceAvg50 and priceAvg50 > priceAvg200: trend_signal = "Strong uptrend continuation" elif price < priceAvg50 and priceAvg50 < priceAvg200: trend_signal = "Strong downtrend continuation"
result = { "symbol": data[0].get("symbol") if data and isinstance(data, list) and data else None, "price": price if 'price' in locals() else None, "priceAvg50": priceAvg50 if 'priceAvg50' in locals() else None, "priceAvg200": priceAvg200 if 'priceAvg200' in locals() else None, "trend": trend_signal } print(result) |
Running the above code will produce an output based on the symbol and day. In the following example, you'll see that Apple stock is in a strong upward trend, as the price is above both moving averages, with the fast MA (50) above the slow MA (200):

Another important aspect we can extract from this endpoint is the potential support or resistance levels. If the price is close to the yearHigh, the stock might be nearing resistance levels. If it's close to the yearLow, it could indicate support. The only variable we need to define is what "near" means. For this, we'll set a threshold of 3% as an example. See the code below:
|
year_high = d.get('yearHigh') year_low = d.get('yearLow') threshold_percentage = 0.03 resistance_threshold = year_high * (1 - threshold_percentage) support_threshold = year_low * (1 + threshold_percentage) if resistance_threshold <= price <= year_high: sr_signal = f"Price is approaching resistance near yearly high {year_high:.2f}" elif year_low <= price <= support_threshold: sr_signal = f"Price is approaching support near yearly low {year_low:.2f}" else: sr_signal = "Price is not near significant resistance or support levels based on yearly range" print (f'Price is {price:.2f}') print (f'Yearly high is {year_high:.2f}') print(sr_signal) |
With Apple stock in a strong upward trend, the identified resistance level makes sense. As the price nears the yearly high, the script indicates there could be some resistance around that point.

The opening gap percentage is calculated by the difference between yesterday's closing price and today's opening. This indicates that there might be some news that affected this gap overnight. Usually, those are surprises with earnings reports, news from rumours about mergers and acquisitions of the stock itself, to natural disasters and election results. Again, we should define what a significant gap will be for us. In our code example below, we set it as 3%.
|
open_price = d.get('open') previous_close = d.get('previousClose') threshold_percentage = 0.03
if open_price is None or previous_close is None or previous_close == 0: gap_signal = "Insufficient data to assess opening gap" else: price_diff = open_price - previous_close price_diff_pct = price_diff / previous_close if price_diff_pct >= threshold_percentage: gap_signal = f"Gap up detected: Open price {open_price:.2f} is higher than previous close {previous_close:.2f}" elif price_diff_pct <= -threshold_percentage: gap_signal = f"Gap down detected: Open price {open_price:.2f} is lower than previous close {previous_close:.2f}" else: gap_signal = "No significant gap detected at open compared to previous close"
print(f'Open price is {open_price:.2f}') print(f'Previous close is {previous_close:.2f}') print(gap_signal) |
In this case, the stock opened quite close to the previous day's close, so the script will inform us that there was no significant gap there.

By comparing the daily high and low, we can identify the intraday volatility, measuring price swing intensity and market activity. We can set a threshold so that if the day's high and low prices fall within this range, the script indicates that the day is not volatile. If they exceed the threshold, it will notify us about the volatility and the position of the current price. We will set this volatility threshold at 1%.
|
day_high = d.get('dayHigh') day_low = d.get('dayLow') print(f'Day high is {day_high:.2f}') print(f'Day low is {day_low:.2f}') closeness_threshold_pct = 0.01 if day_high is None or day_low is None or price is None: intraday_signal = "Insufficient data to assess intraday position" else: volatility_range = day_high - day_low # Check if the day's range is very tight relative to current price if price and price != 0 and volatility_range / price <= closeness_threshold_pct: intraday_signal = ( f"Very tight intraday range: High-Low = {volatility_range:.2f} " f"({(volatility_range / price) * 100:.2f}% of price)." ) elif volatility_range == 0: intraday_signal = "No intraday volatility detected as day high equals day low." else: position_in_range = (price - day_low) / volatility_range if position_in_range > 0.8: intraday_signal = f"Price {price:.2f} is near the intraday high {day_high:.2f}, indicating bullish strength." elif position_in_range < 0.2: intraday_signal = f"Price {price:.2f} is near the intraday low {day_low:.2f}, indicating bearish pressure." else: intraday_signal = f"Price {price:.2f} is within the intraday range {day_low:.2f} - {day_high:.2f}, neutral zone." print(intraday_signal) |
The output of the script above will show a message similar to this, indicating that the price is near the intraday high, suggesting the stock is on a bullish trend.

If we set the threshold to 1.5%, we see the following. The script indicates no significant volatility because the difference between low and high is only 1.23%. This highlights how important it is to establish a threshold that aligns with your trading style.

Let's now visualise all these metrics together in a single plot. We will compare four stocks- Apple, Microsoft, Meta, and Google- and display their metrics side by side in four separate plots.
|
import pandas as pd import numpy as np import requests import matplotlib.pyplot as plt symbols = ['AAPL', 'MSFT', 'META', 'GOOG'] def fetch_quote(symbol): url = 'https://financialmodelingprep.com/stable/quote' params = {'apikey': apikey, 'symbol': symbol} r = requests.get(url, params=params) r.raise_for_status() data = r.json() return data[0] if isinstance(data, list) and data else {} def compute_metrics(d): price = d.get('price') priceAvg50 = d.get('priceAvg50') priceAvg200 = d.get('priceAvg200') open_price = d.get('open') previous_close = d.get('previousClose') day_high = d.get('dayHigh') day_low = d.get('dayLow') year_high = d.get('yearHigh') year_low = d.get('yearLow') # Momentum using moving averages if priceAvg50 is not None and priceAvg200 is not None: momentum = priceAvg50 - priceAvg200 else: momentum = np.nan # Gap percentage from open vs previous close if open_price is not None and previous_close not in (None, 0): gap = (open_price - previous_close) / previous_close else: gap = np.nan # Intraday volatility: normalized range if day_high is not None and day_low is not None and price not in (None, 0): volatility = (day_high - day_low) / price else: volatility = np.nan # Proximity to resistance (year high): smaller distance -> closer if year_high is not None and price is not None: resistance = (year_high - price) / year_high else: resistance = np.nan return { 'price': price, 'momentum': momentum, 'gap': gap, 'volatility': volatility, 'resistance': resistance } # Fetch and compute for all symbols records = [] for sym in symbols: d = fetch_quote(sym) m = compute_metrics(d) m['symbol'] = sym records.append(m) df_metrics = pd.DataFrame(records).set_index('symbol') # Plot 4 subplots: momentum, gap, volatility, resistance fig, axes = plt.subplots(2, 2, figsize=(12, 8), constrained_layout=True) ax1, ax2, ax3, ax4 = axes.ravel() # Momentum df_metrics['momentum'].plot(kind='bar', ax=ax1, color='steelblue', title='Momentum (50MA - 200MA)') ax1.axhline(0, color='gray', linewidth=0.8) # Gap (df_metrics['gap'] * 100).plot(kind='bar', ax=ax2, color='orange', title='Gap % (Open vs Prev Close)') ax2.axhline(0, color='gray', linewidth=0.8) ax2.set_ylabel('%') # Volatility (df_metrics['volatility'] * 100).plot(kind='bar', ax=ax3, color='seagreen', title='Intraday Volatility % (High-Low / Price)') ax3.set_ylabel('%') # Resistance proximity (df_metrics['resistance'] * 100).plot(kind='bar', ax=ax4, color='crimson', title='Proximity to Resistance % (Year High - Price) / Year High') ax4.set_ylabel('%') plt.show() |

You can see in the example above, on just one screen, that
Since FMP offers a wide range of endpoints, it's helpful to understand how its APIs function. This is an ideal chance to explore integrating this API with what we discussed earlier.
One approach is to start by dynamically fetching the entire universe of stocks through the FMP screener endpoint. This tool enables us to access all stock quotes for the:
And we will rank them based on how close they are to the year's high and low.
|
screener_url = f'https://financialmodelingprep.com/stable/company-screener' querystring = {"apikey":apikey, "marketCapMoreThan":100_000_000_000, "sector":"Technology", "country":"US", "exchange":"NASDAQ"} resp = requests.get(screener_url, querystring).json() df = pd.DataFrame(resp) tickers = df['symbol'].to_list() url = 'https://financialmodelingprep.com/stable/quote' results = [] # Ensure list_of_tickers exists; fallback to symbols if necessary # tickers = list_of_tickers if 'list_of_tickers' in locals() and list_of_tickers else [] for symbol in tickers: try: r = requests.get(url, params={"apikey": apikey, "symbol": symbol}) if r.status_code != 200: continue data = r.json() if not isinstance(data, list) or not data: continue q = data[0] price = q.get('price') yh = q.get('yearHigh') yl = q.get('yearLow') if price is None or yh in (None, 0) or yl in (None, 0): continue # Proximity percentages (smaller is closer) prox_high = (yh - price) / yh # 0 means at year high prox_low = (price - yl) / yl # 0 means at year low results.append({ "symbol": symbol, "price": price, "yearHigh": yh, "yearLow": yl, "prox_high": prox_high, "prox_low": prox_low }) except Exception: continue if not results: print("No valid quotes retrieved.") else: dfq = pd.DataFrame(results) # Closest to year high: smallest prox_high top_high = dfq.sort_values('prox_high').head(3).copy() # Closest to year low: smallest prox_low top_low = dfq.sort_values('prox_low').head(3).copy() print("Top 3 closest to Year High:") for _, row in top_high.iterrows(): pct = max(row['prox_high'], 0) * 100 print(f"{row['symbol']}: {pct:.2f}% below year high") print("\nTop 3 closest to Year Low:") for _, row in top_low.iterrows(): pct = max(row['prox_low'], 0) * 100 print(f"{row['symbol']}: {pct:.2f}% above year low") |

This output shows that the script highlights the three stocks nearest to the year's highest price and the three closest to the lowest. Currently, the Technology sector was mostly trending upward, which helps explain this trend.
The Stock Quote API is vital for financial data pipelines, offering fast access to detailed and reliable stock market data. Its comprehensive dataset allows developers and analysts to quickly retrieve key metrics like current prices, trading volume, and significant averages in a single request, supporting timely and informed decision-making.
This endpoint integrates seamlessly with other FMP APIs, such as screeners and company profiles, enabling users to easily retrieve, filter, and analyze stock universes. Together, they provide a powerful toolkit for building advanced market analysis and trading systems that respond to real-time data.
Explore the Stock Quote API today to elevate your applications with precise market insights. Integrating it will enhance your platform's capability to track stock movements and react quickly to market opportunities.
Introduction Apple (NASDAQ: AAPL) has been working to diversify its supply chain, reducing dependence on China due to...
MicroStrategy Incorporated (NASDAQ:MSTR) is a prominent business intelligence company known for its software solutions a...
Introduction In corporate finance, assessing how effectively a company utilizes its capital is crucial. Two key metri...