lightweight-charts-python icon indicating copy to clipboard operation
lightweight-charts-python copied to clipboard

subscribeClick

Open sbgmicromax opened this issue 1 year ago • 1 comments

Description

Need to get the value and time of the series from the point of click, for further calculation purpose in the strategy

Code example

No response

Method of implementation

No response

sbgmicromax avatar Apr 29 '24 22:04 sbgmicromax

Hey, this has been posted previously somewhere around here and I used it since then.

def subscribe_click(chart, *, callback):
    js = (
        'function clickHandler(param) {'
        'if (!param.point) {'
        'return;'
        '}'
        f'const time = {chart.id}.chart.timeScale().coordinateToTime(param.point.x);'
        f'const price = {chart.id}.series.coordinateToPrice(param.point.y);'
        'const data = JSON.stringify({time: time, price: price});'
        'window.callbackFunction(`on_click_~_${data}`);'
        '}'
        f'{chart.id}.chart.subscribeClick(clickHandler);'
    )

    def decorated_callback(data):
        data = json.loads(data)
        data = {
            'timestamp': pd.to_datetime(data['time'], unit='s'),
            'price': data['price'],
        }
        return callback(data, chart, chart.candle_data)

    chart.win.handlers['on_click'] = decorated_callback
    chart.win.run_script(js)

def on_chart_click(data, chart, candle_data): print(data['timestamp'])

subscribe_click(chart, callback=on_chart_click)

emma-uw avatar May 01 '24 12:05 emma-uw

hey @emma-uw any idea on how to exit that callback state ? once i trigger the function using a topbar switcher state, the click feed keep giving information on clicks, even if i change that switcher's state

isshin1 avatar Jun 02 '24 15:06 isshin1

@Iss-in Hey. Hard to tell what you meant without looking into the implementation. But there is a new built-in function in version 2.0. Maybe it will work better for you?

def on_chart_click(chart, timestamp, price):
    print(chart, timestamp, price)
        
chart.events.click += on_chart_click

emma-uw avatar Jun 02 '24 15:06 emma-uw

@emma-uw can you please explain how this works , with some working example if possible?

simply using that code , and clicking on graph doesnt do anything

isshin1 avatar Jun 02 '24 16:06 isshin1

actually scratch that, here is my implementation for a replay of graph

chart.topbar.switcher('click', ('c1', 'c2'), default='c1',
                    func=on_click)
                    

def on_chart_click(chart, timestamp, price):
    print(chart, timestamp, price)
    dt_object = datetime.fromtimestamp(timestamp, tz=timezone.utc)
    dt_string = dt_object.strftime('%Y-%m-%d %H:%M:%S')

    print("Datetime string:", dt_string)
    ind = df[df['date'] == dt_string].index.tolist()[0]
    print(f"index to start replay is {ind} with timestamp {timestamp}")
    for i in range(ind,len(df.index)):
        df2 = df.head(i)
        time.sleep(2)
        chart.set(df2)
        state = chart.topbar['click'].value

        if state == 'c1':
            break
        print(state)

def on_click(chart):
    state = chart.topbar['click'].value
    if state == 'c2':
        print(f"start click")
        chart.events.click += on_chart_click

if i select state c2, and then click on graph, replay happens, but when change state back to c1, it doesnt stop is there a way to accomplish this

isshin1 avatar Jun 02 '24 16:06 isshin1

@Iss-in That's because replay is running synchronously, so until your loop isn't done - any other execution is blocked. You will need your replay function to run separately. Something like this.

from datetime import datetime, timezone
from lightweight_charts import Chart

import pandas as pd
import asyncio

async def start_replay(replay_data):
    for i in range(replay_data.index[0], replay_data.index[-1]):
        df2 = df.head(i)
        await asyncio.sleep(2)
        chart.set(df2)
        state = chart.topbar['click'].value

        if state == 'c1':
            break
        print(state)


def on_chart_click(chart, timestamp, price):
    state = chart.topbar['click'].value
    if state == 'c2':
        print(chart, timestamp, price)
        dt_object = datetime.fromtimestamp(timestamp, tz=timezone.utc)
        dt_string = dt_object.strftime('%Y-%m-%d %H:%M:%S')
        candle_data = chart.candle_data

        print("Datetime string:", dt_string)
        replay_data = candle_data[candle_data['time'] > timestamp]
        print(f"index to start replay is {replay_data.index[0]} with timestamp {timestamp}")

        asyncio.create_task(start_replay(replay_data))


def on_click(chart):
    state = chart.topbar['click'].value
    print(state)


if __name__ == '__main__':
    chart = Chart()

    chart.topbar.switcher('click', ('c1', 'c2'), default='c1', func=on_click)
    chart.events.click += on_chart_click

    df = pd.read_csv('ohlcv.csv')
    chart.set(df)

    chart.show(block=True)

emma-uw avatar Jun 02 '24 17:06 emma-uw

thanks a lot, this helped :)

isshin1 avatar Jun 02 '24 18:06 isshin1