Home > front end >  How to plot a linear model on an existing time series line plot
How to plot a linear model on an existing time series line plot

Time:09-17

I have a question about the value of the slope in degrees which I have calculated below:

import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np

df = yf.download('aapl', '2015-01-01', '2021-01-01')
df.rename(columns = {'Adj Close' : 'Adj_close'}, inplace= True)

x1 = pd.Timestamp('2019-01-02')
x2 = df.index[-1]
y1 = df[df.index == x1].Adj_close[0]
y2 = df[df.index == x2].Adj_close[0]

slope = (y2 - y1)/ (x2 - x1).days
angle = round(np.rad2deg(np.arctan2(y2 - y1, (x2 - x1).days)), 1)

fig, ax1 = plt.subplots(figsize= (15, 6))
ax1.grid(True, linestyle= ':')
ax1.set_zorder(1)
ax1.set_frame_on(False)
ax1.plot(df.index, df.Adj_close, c= 'k', lw= 0.8)
ax1.plot([x1, x2], [y1, y2], c= 'k')


ax1.set_xlim(df.index[0], df.index[-1])
plt.show()

It returns the value of the angle of the slope as 7.3 degrees. Which doesnt look true looking at the chart: enter image description here

It looks close to 45 degrees. What is wrong here?

Here is the line for which I need to calculate the angle: enter image description here

CodePudding user response:

  • The implementation in the OP is not the correct way to determine, or plot a linear model. As such, the question about determining the angle to plot the line is bypassed, and a more rigorous approach to plotting the regression line is shown.

  • A regression line can be added by converting the datetime dates to ordinal. The model can be calculated with sklearn, or added to the plot with seaborn.regplot, as show below.

  • Plot the full data with enter image description here

    Calculate the Linear Model

    • Use enter image description here

      Angle of the Slope

      • This is an artifact of the aspect of the axes, which is not equal for x and y. When the aspect is equal, see that the slope is 7.0 deg.
      x = x2 - x1
      y = y2[0][0] - y1[0][0]
      slope = y / x
      
      print(round(slope, 7) == round(model.coef_[0][0], 7))
      [out]:
      True
      
      angle = round(np.rad2deg(np.arctan2(y, x)), 1)
      print(angle)
      [out]:
      7.0
      
      # given the existing plot
      ax1 = df.plot(y='Adj Close', c='k', figsize=(15, 6), grid=True, legend=False,
                    title='Adjusted Close with Regression Line from 2019-01-02')
      ax1.plot([x1, x2], [y1[0][0], y2[0][0]], label='Linear Model', c='magenta')
      
      # make the aspect equal
      ax1.set_aspect('equal', adjustable='box')
      

      enter image description here

  • Related