EMA lines not with the rest of the graph

89 Views Asked by At

When you load up the code, it's supposed to plot the Candlestick chart and the 4 EMA lines over each other, but they are separated. I'm currently testing the code on Tesla stocks for the example I am showing here.

enter image description here

Code:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd

# Dates to get stock data
start_date = "2010-07-01"
end_date = "2023-06-17"

# Fetch Tesla stock data
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg(
    {"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}
).dropna()

# Get the latest closing price
latest_price = tesla_weekly_data['Close'][-1]

# Create additional plot
close_price = tesla_weekly_data['Close']
apd = mpf.make_addplot(close_price, color='cyan', width=2)

# Calculate the EMA with different lengths
ema_lengths = [8, 13, 21, 55]
ema_colors = ['blue', 'green', 'yellow', 'red']
ema_lines = []
for length, color in zip(ema_lengths, ema_colors):
    ema_line = tesla_weekly_data['Close'].ewm(span=length, adjust=False).mean()
    ema_lines.append(ema_line)

# Plot the candlestick chart with EMA lines
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=apd,
                     style='yahoo',
                     title='Tesla Stock Prices',
                     ylabel='Price',
                     xlabel='Date',
                     volume=True,
                     ylabel_lower='Volume',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True)

# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# Set y-axis label for price and volume
axes[0].set_ylabel('Price', rotation=0, labelpad=20)
axes[1].set_ylabel('Volume', rotation=0, labelpad=20)

# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["Price Up", "Price Down", "Closing Price"]
axes[0].legend(handles=handles, labels=labels)

# Add a box to display the current price
latest_price_text = f"Current Price: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment='top', bbox=box_props)

# Add EMA lines
for ema_line, color in zip(ema_lines, ema_colors):
    axes[0].plot(ema_line, color=color)

# Display the chart
plt.show()

Why are the EMA lines separated from the rest of the plot when they should be aligned?

1

There are 1 best solutions below

0
r-beginners On

I don't know much about it, but it seems to me that each time line is treated differently based on the events that are taking place. By combining the additional graphs into the mpl side of the process, it can be displayed correctly. I don't know if the warning is displayed in your environment, but I have added the settings from the error message, as it was displayed when the number of data was large.

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd

# Dates to get stock data
start_date = "2010-07-01"
end_date = "2023-06-17"

# Fetch Tesla stock data
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg(
    {"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}
).dropna()

# Get the latest closing price
latest_price = tesla_weekly_data['Close'][-1]

# Calculate the EMA with different lengths
ema_lengths = [8, 13, 21, 55]
ema_colors = ['blue', 'green', 'yellow', 'red']
ema_lines = []
for length, color in zip(ema_lengths, ema_colors):
    ema_line = tesla_weekly_data['Close'].ewm(span=length, adjust=False).mean()
    ema_lines.append(ema_line)

# Create additional plot
apds = []
close_price = tesla_weekly_data['Close']
apds.append(mpf.make_addplot(close_price, color='cyan', width=2))

# Add EMA lines
for ema_line, color in zip(ema_lines, ema_colors):
    apds.append(mpf.make_addplot(ema_line, color=color))

# Plot the candlestick chart with EMA lines
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=apds, # update
                     style='yahoo',
                     title='Tesla Stock Prices',
                     ylabel='Price',
                     #xlabel='Date',
                     volume=True,
                     ylabel_lower='Volume',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True,
                     warn_too_much_data=2800, # update: 677 records x 4 lines
                    )

# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# Set y-axis label for price and volume
axes[0].set_ylabel('Price', rotation=0, labelpad=20)
axes[1].set_ylabel('Volume', rotation=0, labelpad=20)

# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["Price Up", "Price Down", "Closing Price"]
axes[0].legend(handles=handles, labels=labels)

# Add a box to display the current price
latest_price_text = f"Current Price: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment='top', bbox=box_props)

# Display the chart
plt.show()

enter image description here