I have some data like:
import pandas as pd
import datetime as dt
import plotly.graph_objects as go
# Example data
returns = pd.DataFrame({'time': [dt.date(2020,1,1), dt.date(2020,1,2), dt.date(2020,1,3), dt.date(2020,1,4), dt.date(2020,1,5), dt.date(2020,1,6)],
'longs': [0, 1,2,3,4,3],
'shorts': [0, -1,-2,-3,-4,-4]})
and a chart like:
fig = go.Figure()
fig.add_trace(
go.Scatter(x=list(returns.time),
y=list(returns.longs),
name="Longs",
line=dict(color="#0c56cc")))
fig.add_trace(
go.Scatter(x=list(returns.time),
y=list(returns.shorts),
name="Shorts",
line=dict(color="#850411", dash="dash")))
fig.show()
When I zoom in on a particular section however I would like for the data to be renormlised using the first date in the xrange. So zooming in on the period after Jan 5 here would give me something like:
This seems to be possible using something like fig.layout.on_change
as discussed here. My attempt at doing it is below but it does not appear to change the figure at all.
def renormalise_returns(returns, renorm_date):
long_data = returns.melt(id_vars = ['time'])
long_data.sort_values(by = 'time', inplace=True)
cum_at_start = long_data[long_data['time'] >= renorm_date].groupby(['variable']).first().reset_index().rename(columns = {'value': 'old_value'}).drop(columns = ['time'])
long_data2 = pd.merge(long_data, cum_at_start, how = 'left', on = ['variable'])
long_data2['value'] = long_data2['value'] - long_data2['old_value']
long_data2.drop(columns = ['old_value'], inplace=True)
finn = long_data2.pivot(index = ['time'], columns = ['variable'], values = 'value').reset_index()
return finn
fig = go.FigureWidget([go.Scatter(x=returns['time'], y=returns['longs'], name='Longs', line=dict(color="#0c56cc")),
go.Scatter(x=returns['time'], y=returns['shorts'], name="Shorts", line=dict(color="#850411", dash="dash"))])
def zoom(xrange):
xrange_zoom_min, xrange_zoom_max = fig.layout.xaxis.range[0], fig.layout.xaxis.range[1]
df2 = renormalise_returns(returns, xrange_zoom_min)
fig = go.FigureWidget([go.Scatter(x=df2['time'], y=df2['longs']), go.Scatter(x=df2['time'], y=df2['shorts'])])
fig.layout.on_change(zoom, 'xaxis.range')
fig.show()