Skip to content

how to plot horizontal line in a streaming intraday chart #552

Description

@pannet1

the streaming part and the buy button clicking all works great. however when clicking the console says
`Error adding horizontal line: must plot this primitive in prior time-range

import finplot as fplt
import numpy as np
import pandas as pd
import time
from PyQt6.QtWidgets import (
    QApplication,
    QVBoxLayout,
    QPushButton,
    QGridLayout,
    QGraphicsView,
    QComboBox,
)
from PyQt6.QtCore import QThread
import random


# Mock broker API (replace with your actual API calls)
def place_buy_order():
    order_id = f"BUY-{random.randint(1000, 9999)}"
    print(f"Placing buy order: {order_id}")
    time.sleep(0.1)
    print(f"Buy order {order_id} placed.")


class BrokerThread(QThread):
    def __init__(self, order_function):
        super().__init__()
        self.order_function = order_function

    def run(self):
        self.order_function()


def gen_dumb_price(symbol="DUMB"):
    random.seed(hash(symbol))
    v = np.random.normal(size=(1000, 4))
    df = pd.DataFrame(v, columns="low open close high".split())
    df = df.rolling(10).mean()
    ma = df["low"].rolling(20).mean().diff()
    for col in df.columns:
        df[col] *= ma * 100
    df.values.sort(axis=1)
    df = (df.T + np.sin(df.index / 87) * 3 + np.cos(df.index / 201) * 5).T + 20
    flip = df["open"].shift(-1) <= df["open"]
    df.loc[flip, "open"], df.loc[flip, "close"] = df["close"].copy(), df["open"].copy()
    df["volume"] = df["high"] - df["low"]
    # epoch time
    df.index = np.linspace(1608332400 - 60 * 1000, 1608332400, 1000)
    return df["open close high low volume".split()].dropna()


def update_chart(ax, df, current_index):
    if current_index >= len(df):
        return current_index
    df_subset = df.iloc[: current_index + 1]
    fplt.candlestick_ochl(df_subset, ax=ax)
    fplt.refresh()
    return current_index + 1


current_symbol = "DUMB"
df = gen_dumb_price(current_symbol)
ax = fplt.create_plot("Live Candlestick Chart", init_zoom_periods=100, maximize=False)

current_index = 1
update_interval = 0.5
last_update_time = time.time()
horizontal_line = None


def update_loop():
    global current_index, last_update_time
    now = time.time()
    if now - last_update_time >= update_interval:
        current_index = update_chart(ax, df, current_index)
        last_update_time = now


app = QApplication([])
win = QGraphicsView()
win.setWindowTitle("Trading Chart with Buy Button and Symbol Selection")
layout = QGridLayout()
win.setLayout(layout)
win.resize(800, 600)

controls_layout = QVBoxLayout()
buy_button = QPushButton("Buy")
controls_layout.addWidget(buy_button)

symbol_dropdown = QComboBox()
symbol_dropdown.addItems(["DUMB", "AAPL", "GOOG", "MSFT", "TSLA"])
controls_layout.addWidget(symbol_dropdown)

layout.addLayout(controls_layout, 0, 1, 1, 1)

win.axs = [ax]
layout.addWidget(ax.vb.win, 0, 0, 1, 1)

active_threads = []


def on_buy_click():
    global horizontal_line
    broker_thread = BrokerThread(place_buy_order)
    active_threads.append(broker_thread)
    broker_thread.finished.connect(lambda: active_threads.remove(broker_thread))
    broker_thread.start()

    # Add horizontal line
    if current_index > 2 and len(df) > 1:  # Ensure enough data
        y_value = df["high"].iloc[current_index - 2]
        now = time.time()  # Use Unix timestamp
        latest_time = df.index[-1]  # df.index is already unix timestamp.

        try:
            if horizontal_line is None:
                horizontal_line = fplt.add_line(
                    (now, y_value),
                    (latest_time, y_value),
                    color="#0000FF",
                    style="-",
                    width=1,
                    interactive=False,
                )
            else:
                horizontal_line.setPos((now, y_value), (latest_time, y_value))
            fplt.refresh()

        except Exception as e:
            print(f"Error adding horizontal line: {e}")


def on_symbol_change(symbol):
    global df, current_index, current_symbol, horizontal_line
    current_symbol = symbol
    df = gen_dumb_price(symbol)
    current_index = 1
    ax.reset()
    if horizontal_line is not None:
        ax.remove_line(horizontal_line)
        horizontal_line = None
    update_chart(ax, df, current_index)


buy_button.clicked.connect(on_buy_click)
symbol_dropdown.currentTextChanged.connect(on_symbol_change)

fplt.show(qt_exec=False)
win.show()
fplt.timer_callback(update_loop, 0.1)
app.exec()

```

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions