question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to make the cursors independent of each other in embedded plots?

See original GitHub issue

Hi, I have modified the code from example-embed.py as the following:

#!/usr/bin/env python3

import finplot as fplt
from functools import lru_cache
from PyQt5.QtWidgets import QGraphicsView, QComboBox, QLabel
from PyQt5.QtGui import QApplication, QGridLayout
from threading import Thread
import yfinance as yf


app = QApplication([])
win = QGraphicsView()
win.setWindowTitle('TradingView wannabe #2')
layout = QGridLayout()
win.setLayout(layout)
win.resize(900, 600)

combo1 = QComboBox()
combo1.setEditable(True)
[combo1.addItem(i) for i in 'AMRK FB GFN REVG TSLA TWTR WMT CT=F GC=F ^FTSE ^N225 EURUSD=X ETH-USD'.split()]
layout.addWidget(combo1, 0, 0, 1, 1)
info1 = QLabel()
layout.addWidget(info1, 0, 1, 1, 1)

combo2 = QComboBox()
combo2.setEditable(True)
[combo2.addItem(i) for i in 'AMRK FB GFN REVG TSLA TWTR WMT CT=F GC=F ^FTSE ^N225 EURUSD=X ETH-USD'.split()]
layout.addWidget(combo2, 0, 2, 1, 1)
info2 = QLabel()
layout.addWidget(info2, 0, 3, 1, 1)

ax1, ax2 = fplt.create_plot_widget(win, init_zoom_periods=100, rows=2)
win.axs = [ax1, ax2] # finplot requres this property
layout.addWidget(ax1.ax_widget, 1, 0, 1, 2)
layout.addWidget(ax2.ax_widget, 1, 2, 1, 2)


@lru_cache(maxsize=15)
def download1(symbol):
    return yf.download(symbol, '2020-01-01')

@lru_cache(maxsize=15)
def download2(symbol):
    return yf.download(symbol, '2020-06-01')

@lru_cache(maxsize=100)
def get_name(symbol):
    return yf.Ticker(symbol).info['shortName']

plots1 = []
def update1(txt):
    df = download1(txt)
    if len(df) < 20: # symbol does not exist
        return
    info1.setText('Loading symbol name...')
    price = df['Open Close High Low'.split()]
    ma20 = df.Close.rolling(20).mean()
    ma50 = df.Close.rolling(50).mean()
    volume = df['Open Close Volume'.split()]
    if not plots1:
        plots1.append(fplt.candlestick_ochl(price, ax=ax1))
        plots1.append(fplt.plot(ma20, legend='MA-20', ax=ax1))
        plots1.append(fplt.plot(ma50, legend='MA-50', ax=ax1))
        plots1.append(fplt.volume_ocv(volume, ax=ax1.overlay()))
    else:
        plots1[0].update_data(price)
        plots1[1].update_data(ma20)
        plots1[2].update_data(ma50)
        plots1[3].update_data(volume)
    Thread(target=lambda: info1.setText(get_name(txt))).start() # slow, so use thread

plots2 = []
def update2(txt):
    df = download2(txt)
    if len(df) < 20: # symbol does not exist
        return
    info2.setText('Loading symbol name...')
    price = df['Open Close High Low'.split()]
    ma20 = df.Close.rolling(20).mean()
    ma50 = df.Close.rolling(50).mean()
    volume = df['Open Close Volume'.split()]
    if not plots2:
        plots2.append(fplt.candlestick_ochl(price, ax=ax2))
        plots2.append(fplt.plot(ma20, legend='MA-20', ax=ax2))
        plots2.append(fplt.plot(ma50, legend='MA-50', ax=ax2))
        plots2.append(fplt.volume_ocv(volume, ax=ax2.overlay()))
    else:
        plots2[0].update_data(price)
        plots2[1].update_data(ma20)
        plots2[2].update_data(ma50)
        plots2[3].update_data(volume)
    Thread(target=lambda: info2.setText(get_name(txt))).start() # slow, so use thread
    

combo1.currentTextChanged.connect(update1)
update1(combo1.currentText())

combo2.currentTextChanged.connect(update2)
update2(combo2.currentText())


fplt.show(qt_exec=False) # prepares plots when they're all setup
win.show()
app.exec_()

The idea is to see if possible to have 2 independent plots embedded in a single QApplication. It works mostly, but I’ve noticed a few things:

  1. The cursors are in sync across the 2 plots, and it would be great if only the “active” one moves while the “inactive” does not
  2. The cursors have the same date value (x-axis). It seems that is the common denominator driving the behavior
  3. The 2nd plot (right-hand side) has the volume missing, although the code snippets are exactly the same for both plots
  4. The 2nd plot has different background color, and it doesn’t seem to change even if I specify a different color upfront
  5. Zooming is also in sync across the 2 plots. I purposely have different date ranges for the 2 plots to show the effect of the same scale being applied. Would be great if zooming can be made independent too.

Thanks in advance for your advice!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
highfestivacommented, Oct 9, 2020

Ah, missed what question you were asking about, sorry! Fixed in https://github.com/highfestiva/finplot/commit/b9a52cc096491a0f633e281f90981fd8498a3e2e – the overlay was ending up behind the viewbox of the odd one (with odd color set).

2reactions
highfestivacommented, Oct 9, 2020

See https://github.com/highfestiva/finplot/issues/25

Every other row uses odd row color to easily distinguish them.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to fix cursor at one particular value X? - NI Community
You can right click on the cursor panel and choose various settings on the attributes. You could also remove the point, but I...
Read more >
Annotated Cursor — Matplotlib 3.6.2 documentation
Hover your cursor to y=4. There are two x values producing this y value: -2 and 2. The function is only unique, but...
Read more >
Matplotlib plot zooming with scroll wheel - Stack Overflow
This should work. It re-centers the graph on the location of the pointer when you scroll. import matplotlib.pyplot as plt def ...
Read more >
II-12 Graphs - WaveMetrics, Inc.
If you want to plot the data values of the Y waves versus the data values of another wave, select the other wave...
Read more >
Mouse Programming in C/C++ - GeeksforGeeks
Reset mouse and get status. ... Returns AX = FFFFh , if mouse support is available, otherwise, returns Ax = 0. ... Show...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found