Skip to content

Commit

Permalink
Fix fill_between
Browse files Browse the repository at this point in the history
Circumventing a bug in pyqtgraph. More info in comment.
  • Loading branch information
highfestiva committed Oct 30, 2023
1 parent dc547ff commit 3d57357
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
22 changes: 18 additions & 4 deletions finplot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,7 @@ def __init__(self, win, init_steps=300, yscale=YScale('linear', 1), v_zoom_scale
self.master_viewbox = None
self.rois = []
self.win._isMouseLeftDrag = False
self.zoom_listeners = set()
self.reset()

def reset(self):
Expand Down Expand Up @@ -1099,6 +1100,7 @@ def set_range(self, x0, y0, x1, y1):
_y0 = self.yscale.invxform(y0, verify=True)
_y1 = self.yscale.invxform(y1, verify=True)
self.setRange(QtCore.QRectF(pg.Point(x0, _y0), pg.Point(x1, _y1)), padding=0)
self.zoom_changed()
return True

def remove_last_roi(self):
Expand Down Expand Up @@ -1135,6 +1137,10 @@ def set_draw_line_color(self, color):
def suggestPadding(self, axis):
return 0

def zoom_changed(self):
for zl in self.zoom_listeners:
zl(self)



class FinPlotItem(pg.GraphicsObject):
Expand Down Expand Up @@ -1682,8 +1688,6 @@ def plot(x, y=None, color=None, width=1, ax=None, style=None, legend=None, zooms
if style is None or any(ch in style for ch in '-_.'):
connect_dots = 'finite' # same as matplotlib; use datasrc.standalone=True if you want to keep separate intervals on a plot
item = ax.plot(x, y, pen=_makepen(color=used_color, style=style, width=width), name=legend, connect=connect_dots)
item.setClipToView(True)
item.setDownsampling(auto=True, method='subsample')
item.setZValue(5)
else:
symbol = {'v':'t', '^':'t1', '>':'t2', '<':'t3'}.get(style, style) # translate some similar styles
Expand Down Expand Up @@ -1754,6 +1758,13 @@ def fill_between(plot0, plot1, color=None):
item.ax = plot0.ax
item.setZValue(-40)
item.ax.addItem(item)
# Ugly bug fix for PyQtGraph bug where downsampled/clipped plots are used in conjunction
# with fill between. The reason is that the curves of the downsampled plots are only
# calculated when shown, but not when added to the axis. We fix by saying the plot is
# changed every time the zoom is changed - including initial load.
def update_fill(vb):
plot0.sigPlotChanged.emit(plot0)
plot0.ax.vb.zoom_listeners.add(update_fill)
return item


Expand Down Expand Up @@ -2072,6 +2083,8 @@ def _add_timestamp_plot(master, prev_ax, viewbox, index, yscale):
axw = pg.PlotWidget(viewBox=viewbox, axisItems=axes, name='plot-%i'%index, enableMenu=False)
ax = axw.plotItem
ax.ax_widget = axw
ax.setClipToView(True)
ax.setDownsampling(auto=True, mode='subsample')
ax.hideAxis('left')
if y_label_width:
ax.axes['right']['item'].setWidth(y_label_width) # this is to put all graphs on equal footing when texts vary from 0.4 to 2000000
Expand Down Expand Up @@ -2658,14 +2671,15 @@ def _get_color(ax, style, wanted_color):
return wanted_color
index = wanted_color if type(wanted_color) == int else None
is_line = lambda style: style is None or any(ch in style for ch in '-_.')
get_handed_color = lambda item: item.opts.get('handed_color')
this_line = is_line(style)
if this_line:
colors = soft_colors
else:
colors = hard_colors
if index is None:
avoid = set(i.opts['handed_color'] for i in ax.items if isinstance(i,pg.PlotDataItem) and i.opts['handed_color'] is not None and this_line==is_line(i.opts['symbol']))
index = len([i for i in ax.items if isinstance(i,pg.PlotDataItem) and i.opts['handed_color'] is None and this_line==is_line(i.opts['symbol'])])
avoid = set(i.opts['handed_color'] for i in ax.items if isinstance(i,pg.PlotDataItem) and get_handed_color(i) is not None and this_line==is_line(i.opts['symbol']))
index = len([i for i in ax.items if isinstance(i,pg.PlotDataItem) and get_handed_color(i) is None and this_line==is_line(i.opts['symbol'])])
while index in avoid:
index += 1
return colors[index%len(colors)]
Expand Down
3 changes: 1 addition & 2 deletions finplot/examples/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def local2timestamp(s):
return int(dateutil.parser.parse(s).timestamp())


def download_price_history(symbol='XBTUSD', start_time='2020-01-10', end_time='2020-05-07', interval_mins=60):
def download_price_history(symbol='XBTUSD', start_time='2023-01-01', end_time='2023-10-29', interval_mins=60):
start_time = local2timestamp(start_time)
end_time = local2timestamp(end_time)
data = defaultdict(list)
Expand Down Expand Up @@ -59,7 +59,6 @@ def plot_heikin_ashi(df, ax):
for i,hc in zip(df.index, df['h_close']):
df.loc[i, 'h_open'] = ho
ho = (ho + hc) / 2
print(df['h_open'])
df['h_high'] = df[['high','h_open','h_close']].max(axis=1)
df['h_low'] = df[['low','h_open','h_close']].min(axis=1)
df[['h_open','h_close','h_high','h_low']].plot(ax=ax, kind='candle')
Expand Down

0 comments on commit 3d57357

Please sign in to comment.