I am trying to create a candlestick chart using finplot and embedding it in a gui using pyqt6. I have multiple csv files in a folder with the following columns: dt, open, high, low, close, and volume. Each csv file is named with the stock symbol(for e.g. TESLA.csv). I have added a functionality to my code where you can easily navigate through the files using a forward and back button. Anyways, here's my code:
import finplot as fplt
from functools import lru_cache
from PyQt6.QtWidgets import QApplication, QGridLayout, QGraphicsView, QComboBox, QLabel, QPushButton, QHBoxLayout, QWidget
from threading import Thread
import pandas as pd
import os
app = QApplication([])
win = QGraphicsView()
win.setWindowTitle('TradingView wannabe')
layout = QGridLayout()
win.setLayout(layout)
win.resize(800, 600)
data_folder = r"C:\Users\PC\Desktop\trade\pse\main\indv_stocks" # Replace this with the actual path to your data folder
# Get the list of filenames (symbols) without the ".csv" extension in the folder
csv_files = [file[:-4] for file in os.listdir(data_folder) if file.endswith('.csv')]
# Create a widget to contain the combo box and navigation buttons horizontally
widget = QWidget()
widget_layout = QHBoxLayout()
widget.setLayout(widget_layout)
combo = QComboBox()
combo.setEditable(True)
combo.setFixedWidth(150) # Set a fixed width for the combo box
[combo.addItem(i) for i in csv_files] # Use the list of filenames as items in the combo box
widget_layout.addWidget(combo)
info = QLabel()
widget_layout.addWidget(info)
# Create forward and backward navigation buttons
button_forward = QPushButton("➡")
button_backward = QPushButton("⬅")
button_forward.setFixedSize(30, 30) # Set a fixed size for the buttons
button_backward.setFixedSize(30, 30)
widget_layout.addWidget(button_backward)
widget_layout.addWidget(button_forward)
# Add the widget containing the combo box and buttons to the layout
layout.addWidget(widget, 0, 0, 1, 2)
ax = fplt.create_plot(init_zoom_periods=100)
win.axs = [ax] # finplot requires this property
axo = ax.overlay()
layout.addWidget(ax.vb.win, 1, 0, 1, 2)
@lru_cache(maxsize=15)
def download(symbol):
file_path = os.path.join(data_folder, f"{symbol}.csv")
if not os.path.exists(file_path):
return None
return pd.read_csv(file_path, index_col=0, parse_dates=True)
@lru_cache(maxsize=100)
def get_name(symbol):
return symbol # If you don't have a CSV with symbol names, you can return the symbol itself.
current_index = 0
def update(txt):
global current_index
df = download(txt)
if df is None or len(df) < 20: # Symbol does not exist or has insufficient data
return
info.setText('Loading symbol name...')
price = df['open close high low'.split()]
ema20 = df.close.ewm(span = 20, adjust = False).mean()
ema50 = df.close.ewm(span = 50, adjust = False).mean()
ema200 = df.close.ewm(span = 200, adjust = False).mean()
volume = df['open close volume'.split()]
ax.reset() # remove previous plots
axo.reset() # remove previous plots
fplt.candlestick_ochl(price)
fplt.plot(ema20, legend='EMA20')
fplt.plot(ema50, legend='EMA50')
fplt.plot(ema200, legend='EMA200')
fplt.volume_ocv(volume, ax=axo)
fplt.refresh() # refresh autoscaling when all plots complete
Thread(target=lambda: info.setText(get_name(txt))).start() # slow, so use thread
# Update the current index when the combo box selection changes
global csv_files
current_index = csv_files.index(txt)
# Connect the currentTextChanged signal of the combo box to the update function
combo.currentTextChanged.connect(update)
# Function to handle the button clicks for navigation
def navigate_forward():
global current_index
if current_index < len(csv_files) - 1:
current_index += 1
combo.setCurrentIndex(current_index)
def navigate_backward():
global current_index
if current_index > 0:
current_index -= 1
combo.setCurrentIndex(current_index)
# Connect the button clicks to the navigation functions
button_forward.clicked.connect(navigate_forward)
button_backward.clicked.connect(navigate_backward)
update(combo.currentText())
fplt.show(qt_exec=False) # prepares plots when they're all setup
win.show()
app.exec()
This works but what I also want to achieve is to display in a legend the value of the open, high, low, close, volume in the top of the chart (beside the combobox) when the mouse hovers over a date. Not allowed to post image yet to show what i want but if you go to tradingview.com you’ll see an example like this: O 12.50 H 15 L 11 C 13 V 1,000,000
I was able to do it but without embedding it in a gui. Tried chatgpt too but all the answers that it spewed produced errors