pythonmatplotlibplotmplfinance

Plotted candlestick chart disappears after plotting additional data


I'm building a bot that analyzes my trades in the stock market. I have two axes, one plotting my trade orders, and one plotting the candlestick chart of the traded stock.

fig, (ax1, ax2) = plt.subplots(2)

# Plotting Trades
ax1.plot(...)

# Plotting Candlestick Chart
mpf.plot(stock.data, ax=ax2, type='candle')
ax2.set_title(f'Stock History of {stock.symbol}')
ax2.set_xlabel('Date')
ax2.set_ylabel('Price')

This works fine so far and plots the chart as envisioned. enter image description here

However, I'd now like to add markers to the chart for when I entered and exited trades. To start simple, I took all the orders and put all dates and prices in separate lists, so that I could specify the X as the dates and Y as the prices.

# Plotting Orders
dates, prices = [], []
for key, order in broker.orders.items():
    dates.append(order.date)
    prices.append(order.price)
ax2.plot(dates, prices, 'o')

But instead, now the chart was completely gone and all I could see was the markers.enter image description here

Even the dates are not showing up which is a bit confusing since I splitted up the dates in its own specific list so that the X-positions would still be correct.

Anyone who has an idea of what's going on here? Thanks beforehand.


Solution

  • It looks like mpf.plot(..., ax=ax2) and ax2.plot(...) override some important plot settings of each other. You should probably add your orders data with mplfinance.make_addplot() like this:

    import mplfinance as mpf
    import yfinance as yf
    import matplotlib.pyplot as plt
    import pandas as pd
    
    # market data
    df = yf.download("SPY", start="2024-02-13", end="2024-02-14", interval='1h')
    
    # some fake data
    d = {
        'dates': ['2024-02-13 09:30:00', '2024-02-13 10:30:00', '2024-02-13 11:30:00', '2024-02-13 12:30:00', '2024-02-13 13:30:00', '2024-02-13 14:30:00', '2024-02-13 15:30:00'],
        'prices': [493.5, 495.2, 495.8, 494.8, 492.0, 492.6, 493.0]
    }
    my_df = pd.DataFrame(data=d)
    
    # show everything on one plot
    fig, ax = plt.subplots()
    my_dict = mpf.make_addplot(my_df['prices'], type='scatter', ax=ax)
    mpf.plot(df,
             ax=ax,
             type="candle",
             addplot=my_dict
        )
    
    plt.show()
    

    The code produces the following image:

    enter image description here

    UPDATE

    If your orders data is available only for some of the stock market timestamps, then you could make a combined dataframe with a price column having NaN values in the rows, where orders data is "missing". In this way you would have two data frames of equal length, suitable to be shown on one plot with mpf.make_addplot() and mpf.plot():

    import mplfinance as mpf
    import yfinance as yf
    import matplotlib.pyplot as plt
    import pandas as pd
    
    # get market data
    df = yf.download("SPY", start="2024-02-13", end="2024-02-14", interval="1h")
    
    # make some fake data with the same time format as market data
    my_prices = [493.5, 495.2, 495.8]
    # these timestamps must be a subset of those from the market data
    my_timestamps = pd.date_range("2024-02-13 09:30:00", periods=len(my_prices), freq="H", tz="America/New_York")
    d = {
    # this column must be named the same way as the column with timestamps from the market data
        "Datetime": my_timestamps,
        "Prices": my_prices
    }
    my_df = pd.DataFrame(data=d)
    
    # merge data sets, resulting in a new column with prices, where prices for missing market dates are NaN
    combined_df = df.merge(my_df, how="outer", on="Datetime")
    
    # show everything on one plot
    fig, ax = plt.subplots()
    my_dict = mpf.make_addplot(combined_df["Prices"], type="scatter", color="red", ax=ax)
    mpf.plot(df,
             ax=ax,
             type="candle",
             addplot=my_dict
        )
    
    plt.show()
    

    Here is the result:

    enter image description here