Interactive Stock Chart, step by step animation with a slider. Matplolib & Jupyter

Viewed 198

In this post: Interactive Stock Chart, step by step animation with keyboard arrows, with Matplolib, I wrote a code, in which the user Zephyr brilliantly fixed, that interactively simulate a stock using keyboard arrows.
It turned out that I found a way of doing the same thing in Jupyter, using the module ipywidgets. The code works, but unfortunately the same chart is plotted twice. I have no idea why this is happening. Can someone help? I just want to show one plot (notice that the second plot does not move as I use the slider).
Here is the code:

%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.read_csv('all_stocks_5yr.csv')
df_apple = df[df['Name'] == 'AAPL'].copy()
df_apple['date'] = pd.to_datetime(df_apple['date'])
df_apple.reset_index(inplace = True)

bars_to_display = 60
step = widgets.IntSlider(value=0, min=0, max=len(df_apple)-bars_to_display)

val_array = []
for idx, val in df_apple.iterrows():
    val_array.append(val)
    
x = np.arange(0, len(df_apple))

fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)

def f(step):
    
    ax.cla()
    ax2.cla()
    
    for i in range(step, bars_to_display + step):
        
        color = '#2CA453'
        if val_array[i]['open'] > val_array[i]['close']: color = '#F04730'
        ax.plot([x[i], x[i]], [val_array[i]['low'], val_array[i]['high']], color = color)
        ax.plot([x[i], x[i] - 0.1], [val_array[i]['open'], val_array[i]['open']], color = color)
        ax.plot([x[i], x[i] + 0.1], [val_array[i]['close'], val_array[i]['close']], color = color)
        ax2.bar(x[i], val_array[i]['volume'], color = 'lightgrey')
        
    display(fig)
    

display(step)
out = widgets.interactive_output(f, {'step': step})
display(out)

enter image description here

1 Answers

The line:

fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)

draws the first figure. Just add plt.close() after that.

Complete Code

from IPython.display import display
from ipywidgets import interactive, widgets
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline

df = pd.read_csv('all_stocks_5yr.csv')
df_apple = df[df['Name'] == 'AAPL'].copy()
df_apple['date'] = pd.to_datetime(df_apple['date'])
df_apple.reset_index(inplace = True)

bars_to_display = 60
step = widgets.IntSlider(value = 0, min = 0, max = len(df_apple) - bars_to_display)

val_array = []
for idx, val in df_apple.iterrows():
    val_array.append(val)

x = np.arange(0, len(df_apple))

fig, (ax, ax2) = plt.subplots(2, figsize = (12, 8), gridspec_kw = {'height_ratios': [4, 1]}, sharex = True)
plt.close()


def f(step):
    ax.cla()
    ax2.cla()

    for i in range(step, bars_to_display + step):

        color = '#2CA453'
        if val_array[i]['open'] > val_array[i]['close']: color = '#F04730'
        ax.plot([x[i], x[i]], [val_array[i]['low'], val_array[i]['high']], color = color)
        ax.plot([x[i], x[i] - 0.1], [val_array[i]['open'], val_array[i]['open']], color = color)
        ax.plot([x[i], x[i] + 0.1], [val_array[i]['close'], val_array[i]['close']], color = color)
        ax2.bar(x[i], val_array[i]['volume'], color = 'lightgrey')

    display(fig)


display(step)
out = widgets.interactive_output(f, {'step': step})
display(out)

enter image description here

Related