Skip to main content

Plotting stock charts (OHLC) with matplotlib and mplfinance

When analyzing stock market data, simple line charts only tell part of the story. In this tutorial, you’ll learn how to create candlestick charts that reveal much more about price action, giving you a clearer picture of what’s happening in the market.

This tutorial builds on our previous lessons about downloading market data with yfinance and rethinking yfinance’s default MultiIndex DataFrames.

Today, we’re taking things to the next level by learning how to create candlestick charts, one of fundamental tools in any traders toolbox.

Whether you’re tracking market trends, analyzing support and resistance levels, or just trying to make sense of price volatility, visual representation is your most powerful ally. And when it comes to stock market visualization, nothing beats the information density of a good candlestick chart.


This tutorial is part 3 in my series on getting started with fintech and market analysis with Python:

  1. How to download market data with yfinance and Python
  2. Rethinking yfinance’s default MultiIndex format
  3. How to plot candlestick charts with Python and mplfinance (this tutorial)
  4. How to compute Simple Moving Averages (SMAs) for trading with Python and Pandas
  5. Finding consecutive integer groups in arrays with Python and NumPy
  6. Computing slope of series with Pandas and SciPy
  7. Market stage detection with Python and Pandas
  8. Implementing TradingView’s Stochastic RSI indicator in Python
  9. Introduction to position sizing
  10. Risk/Reward analysis and position sizing with Python

Configuring your development environment #

Before diving in, let’s set up our Python environment with the necessary packages:

$ pip install numpy pandas yfinance matplotlib mplfinance seaborn

Here’s what each package does:

  • numpy — The foundational package for numerical computing in Python
  • pandas — Gives us powerful DataFrame objects for manipulating and analyzing market data
  • yfinance — Allows us to download historical market data from the Yahoo Finance API
  • matplotlib — The workhorse plotting library that gives us control over visualizations
  • mplfinance — A specialized matplotlib extension for financial plots, including candlestick charts
  • seaborn — Adds aesthetic improvements to matplotlib visualizations

With our development environment configured, we can move to learning how to create stock charts with Python.

Downloading market data #

Let’s start by importing our required Python packages:

# import the necessary packages
from datetime import timedelta
from datetime import datetime
import matplotlib.pyplot as plt
import mplfinance as mpf
import seaborn as sns
import yfinance as yf

These imports give us everything we need to download, manipulate, and visualize stock data:

  • datetime and timedelta — For managing date ranges for our data requests
  • matplotlib.pyplot — For creating basic plots
  • mplfinance — For financial-specific chart types like candlesticks
  • seaborn — For enhanced visual styling
  • yfinance — For downloading the actual market data

Now let’s set up our date range and ticker:

# set the start and end dates for our market data request to be TTM
end_date = datetime(year=2025, month=3, day=1)
start_date = end_date - timedelta(days=365)

# set the name of the ticker we want to download market data for
ticker = "AAPL"

We’re looking at the “trailing twelve months” (TTM) of data for Apple (AAPL), going back one year from March 1, 2025.

This time range gives us a solid dataset to work with, capturing both short-term fluctuations and longer-term trends.

With our parameters defined, let’s download market data for our ticker:

# download market data
df = yf.download(
    tickers=ticker,
    start=start_date,
    end=end_date,
    interval="1d",
    group_by="ticker",
    auto_adjust=True,
    progress=False
)

As well as transforms the data into our preferred MultiIndex structure (as covered in our previous tutorial):

# restructure the default multi-index dataframe to our preferred format
df = df.stack(level="Ticker", future_stack=True)
df.index.names = ["Date", "Symbol"]
df = df[["Open", "High", "Low", "Close", "Volume"]]
df = df.swaplevel(0, 1)
df = df.sort_index()
df

The output DataFrame should look like the following:

PriceOpenHighLowCloseVolume
SymbolDate
AAPL2024-03-01178.706190179.681580176.546390178.81567473488000
2024-03-04175.322137176.068613172.973228174.27708481510100
2024-03-05169.957503171.231486168.822861169.32051195132400
2024-03-06170.256065170.435227167.887245168.32518068587700
2024-03-07168.355054169.927630167.698167168.20576571765100
..................
2025-02-24244.929993248.860001244.419998247.10000651326400
2025-02-25248.000000250.000000244.910004247.03999348013300
2025-02-26244.330002244.979996239.130005240.36000144433600
2025-02-27239.410004242.460007237.059998237.30000341153600
2025-02-28236.949997242.089996230.199997241.83999656833400

The resulting DataFrame contains our OHLCV (Open, High, Low, Close, Volume) data, properly structured and ready for visualization.

Plotting closing prices with matplotlib #

Let’s start with something simple — a basic line plot of closing prices:

# initialize an empty figure
plt.figure(figsize=(10, 6))
plt.grid(alpha=0.5)

# plot the closing prices
plt.plot(
    df.xs(ticker).index,
    df.xs(ticker)["Close"],
    color="blue",
    linewidth=1.5
)

# set the plot title and axis labels
plt.title(f"{ticker} Closing Price [TTM]")
plt.xlabel("Date")
plt.ylabel("Price ($)")

# finish constructing the plot
plt.xticks(rotation=45)
plt.tight_layout()

# show the plot
plt.show()

The resulting plot should look like:

APPL closing prices

Let’s break down what this code does:

  1. We create a new figure with a specific size and add a subtle background grid
  2. We plot the closing price against dates using df.xs(ticker) to extract just the AAPL data from our MultiIndex DataFrame
  3. We customize the appearance with a title, axis labels, and date labels
  4. Finally, we call tight_layout() to ensure everything fits nicely, and show() to display the chart

The resulting plot gives us a clean visualization of AAPL’s price movement over the past year, showing the upward trend with some volatility along the way.

Plotting candlestick chart of OHLC data #

Anatomy of a candlestick #

While line charts are nice for tracking overall trends, they only show one dimension of price data (the closing price). But the stock market is much more complex than that!

Each trading day contains four critical price points:

  • Open — The price at which the stock started trading that day
  • High — The highest price reached during the day
  • Low — The lowest price reached during the day
  • Close — The final price when the market closed

Candlestick charts display all four of these values in a compact, informative visualization:

  • The body of the candle shows the range between open and close
  • The wicks (or shadows) show the full range from high to low
  • The color indicates whether the stock closed higher (green/white) or lower (red/black) than it opened

The following image provides a nice visualization of both a bullish and bearish candle:

Anatomy of a candlestick
Anatomy of a candlestick. (image source)

Take the time now to study the image for a few moments to ensure you understand it.

Using mplfinance to a candlestick chart #

Let’s create our first candlestick chart using mplfinance:

# plot the open, high, low, and close candlestick data
mpf.plot(
    df.xs(ticker),
    type="candle",
    style="yahoo",
    figsize=(14, 7),
    title=f"{ticker} - Basic Candlestick Chart"
)

Which results in the following plot:

AAPL simple candlestick chart

This code is amazingly simple compared to what it accomplishes!

To create the above plot, we’re using mpf.plot() and passing in:

  • Our cross-section of AAPL data from the DataFrame
  • type="candle" to specify we want a candlestick chart
  • style="yahoo" for a Yahoo Finance-like appearance
  • Our figure size and title

The beauty of mplfinance is that it automatically detects the OHLC columns in our DataFrame and creates the appropriate visualization.

Overall, this leads to a much richer view of AAPL’s price action:

  • Green candles show days when the stock price increased
  • Red candles indicate days with price decreases
  • Long wicks reveal volatile days with large price swings
  • We can easily spot days with gaps between the previous close and current open

This visualization gives us a much deeper understanding of market behavior than a simple line chart.

Adding volume to the candlestick chart with mplfinance #

Volume is another crucial piece of market information—it tells us how many shares changed hands, indicating the level of participation and conviction behind price moves.

Let’s enhance our chart by adding volume data:

# include volume in the candlestick chart
mpf.plot(
    df.xs(ticker),
    type="candle",
    style="yahoo",
    figsize=(14, 7),
    volume=True,
    title=f"{ticker} - Candlestick Chart w/ Volume"
)

Note the bottom third of the chart and now an additional axis of data is now included:

AAPL candlestick chart with volume

Adding volume is as simple as setting volume=True in our mpf.plot() call. As long as our DataFrame contains a Volume column (which it does), mplfinance will automatically create a volume subplot below the price chart.

This combined visualization now shows us:

  • Price action through candlesticks in the upper panel
  • Trading volume in the lower panel, color-coded to match price direction
  • Red volume bars for down days
  • Green volume bars for up days

This lets us identify important patterns like high-volume breakouts or low-volume pullbacks—critical information for making trading decisions.

Plotting only recent OHLCV data #

Often, we want to focus on more recent price action rather than looking at the entire data range. Let’s create a zoomed-in view of the most recent trading days:

# grab only the latest 30 days of trading data
df_latest = df.head(30)

And from there we can plot this subset:

# plot the latest data, thereby creating a "zoomed in" version of the plot
mpf.plot(
    df_latest.xs(ticker),
    type="candle",
    style="yahoo",
    figsize=(14, 7),
    volume=True,
    title=f"{ticker} - Last 30 Days"
)

AAPL past 30 days

The resulting chart shows only the most recent month of trading — mplfinance automatically adjusts the scaling based on the data provided, giving us a more detailed view of recent price action.

This zoomed-in view makes it easier to analyze short-term patterns and make more immediate trading decisions.

Exercises #

Before we wrap up, try these exercises to reinforce what you’ve just learned:

  1. Cross-ticker comparison: Plot a candlestick chart for a different stock (e.g., MSFT, AMZN, or TSLA) and compare its price action with AAPL. What differences do you notice in volatility, trend direction, and volume patterns?

  2. Custom styling exploration: Create a custom color scheme for your candlestick chart by exploring the style parameter options in mpf.plot(). Try creating a dark mode theme for your charts or customize the colors to match your personal preferences.

  3. Moving average visualization: Add a 20-day Simple Moving Average to your candlestick chart (hint: look up the mav parameter in mpf.plot()). Does the price tend to respect this moving average as support or resistance? Try adding multiple moving averages with different periods.

  4. High-resolution export: Export your chart as a high-resolution image file using savefig(). This is particularly useful when creating reports or sharing analysis with others who don’t have Python installed.

Remember, the best way to master these visualization techniques is through hands-on practice—try implementing each example yourself to develop a deeper understanding of how candlestick charts can enhance your market analysis workflows.

Final thoughts #

Visualization is one of the most powerful tools in a trader or analyst’s arsenal. What we’ve covered today—transforming raw OHLCV data into informative candlestick charts—is the foundation for more advanced technical analysis.

With just a few lines of Python code, we’ve created stock charts that reveal price trends, volatility, and market participation. These visualizations help us spot patterns that might be invisible in raw data or simpler line charts.

The mplfinance library makes this process remarkably easy, handling all the complexity of translating OHLC data into meaningful visual representations. And the best part? This is just the beginning of what’s possible.

In the next tutorial, we’ll build on these visualization skills by learning how to compute and plot Simple Moving Averages (SMAs)—one of the most fundamental technical indicators used by traders worldwide.

👉 Click here to download the source code to this tutorial