Search code examples
pythonslideripywidgetsbqplot

Using multiple sliders to create dynamic chart in bqplt/jupyter


I am trying to plot a dynamic portfolio performance that changes as the weights of the portfolio change

Assume a portfolio has 2 components with a 50% weighting each. I want to show a chart of the portfolio with sliders representing the weights of the components. I then want to be able to slide the values of the weights around and have the portfolio chart dynamically update.

I have done this for a portfolio that consists of one weight but cant figure out how to amend for more than 1 weight - maybe I need a different approach.

Example below substitutes a random df with 1 column in place of my portfolio df - process should be the same.

In terms of this example if the df had 2 columns - how can I get it working with 2 sliders controlling each weight ?


from bqplot import DateScale, LinearScale, Axis, Figure, Lines

from ipywidgets import FloatSlider, VBox

import pandas as pd

import numpy as np

slider = FloatSlider(value=1, min = 0, max = 1, step = .01, description = 'Weight A')

df = pd.DataFrame(np.random.randint(0,100,size=(100, 1)), columns=list('A'))

x_sc = LinearScale()

y_sc = LinearScale()

ax_x = Axis(label='Date', scale=x_sc, grid_lines='solid')

ax_y = Axis(label='Price', scale=y_sc, orientation='vertical', grid_lines='solid')

line = Lines(y=df['A'],x=df.index , scales={'x': x_sc, 'y': y_sc}, colors = ['#FF0000'])

line2 = Lines(y=df['A'],x=df.index , scales={'x': x_sc, 'y': y_sc})

fig = Figure(axes=[ax_x, ax_y], marks=[line, line2], title='Price Chart')

def new_chart(value):

new_y = df[['A']]*slider.value

line.y = new_y

slider.observe(new_chart,'value')

VBox([fig,slider])


Solution

  • Not sure if I have understood you. Do you mean this?

    from bqplot import DateScale, LinearScale, Axis, Figure, Lines
    
    from ipywidgets import FloatSlider, VBox
    
    import pandas as pd
    
    import numpy as np
    
    slider = FloatSlider(value=1, min = 0, max = 1, step = .01, description = 'Weight A')
    sliderB = FloatSlider(value=1, min = 0, max = 1, step = .01, description = 'Weight B')
    
    df = pd.DataFrame(np.random.randint(0,100,size=(100, 1)), columns=list('A'))
    df['B'] = np.random.randint(0,100,size=(100, 1))
    
    x_sc = LinearScale()
    
    y_sc = LinearScale()
    
    ax_x = Axis(label='Date', scale=x_sc, grid_lines='solid')
    
    ax_y = Axis(label='Price', scale=y_sc, orientation='vertical', grid_lines='solid')
    
    line = Lines(y=df['A']+df['B'],x=df.index , scales={'x': x_sc, 'y': y_sc}, colors = ['#FF0000'])
    
    line2 = Lines(y=df['A']+df['B'],x=df.index , scales={'x': x_sc, 'y': y_sc})
    
    fig = Figure(axes=[ax_x, ax_y], marks=[line, line2, ], title='Price Chart')
    
    def new_chart(change):
        line.y = df['A']*slider.value + df['B']*sliderB.value
    
    slider.observe(new_chart,'value')
    
    sliderB.observe(new_chart,'value')
    
    VBox([fig,slider,sliderB])