Closed WheatMaThink closed 9 months ago
app.py
import dash from dash import html, Output, Input, State, ClientsideFunction, dcc import dash_tvlwc candlestick_data = [ {'close': 97.56, 'high': 101.29, 'low': 95.07, 'open': 100, 'time': '2021-01-01'}, {'close': 96.06, 'high': 99.06, 'low': 95.17, 'open': 97.56, 'time': '2021-01-02'}, {'close': 92.06, 'high': 98.39, 'low': 90.72, 'open': 96.06, 'time': '2021-01-03'}, {'close': 95.74, 'high': 97.87, 'low': 89.75, 'open': 92.06, 'time': '2021-01-04'}, {'close': 92.44, 'high': 97.5, 'low': 88.56, 'open': 95.74, 'time': '2021-01-05'}, {'close': 89.31, 'high': 93.1, 'low': 85.20, 'open': 92.44, 'time': '2021-01-06'}, {'close': 85.10, 'high': 93.08, 'low': 82.23, 'open': 89.31, 'time': '2021-01-07'}, {'close': 81.87, 'high': 88.34, 'low': 77.97, 'open': 85.10, 'time': '2021-01-08'}, {'close': 79.55, 'high': 82.44, 'low': 76.08, 'open': 81.87, 'time': '2021-01-09'}, {'close': 82.74, 'high': 84.01, 'low': 78, 'open': 79.55, 'time': '2021-01-10'} ] line_data = [ {'time': '2021-01-01', 'value': 100.35}, {'time': '2021-01-02', 'value': 97.09}, {'time': '2021-01-03', 'value': 95.74}, {'time': '2021-01-04', 'value': 98.72}, {'time': '2021-01-05', 'value': 100.3}, {'time': '2021-01-06', 'value': 95.8}, {'time': '2021-01-07', 'value': 91.22}, {'time': '2021-01-08', 'value': 94.26}, {'time': '2021-01-09', 'value': 94.9}, {'time': '2021-01-10', 'value': 94.85} ] main_panel = [ dcc.Store(id='tw_operations_store', data={'data_name': {'0': "A", '1': "B"}}), # data_name in seriesPrices 0,1 数据名称,和数据顺序对应 html.Div(style={'position': 'relative', 'width': '100%', 'height': '100%'}, children=[ html.Div(children=[ dash_tvlwc.Tvlwc( id='tv-chart-1', seriesData=[candlestick_data, line_data], seriesTypes=['candlestick', 'line'], width='100%', ), ], style={'width': '100%', 'height': '100%', 'left': 0, 'top': 0}), html.Div(id='chart-info', children=[ # https://tradingview.github.io/lightweight-charts/tutorials/how_to/tooltips html.Span(id='chart-tooltips', style={'width': '120px', 'height': '100%', 'position': 'absolute', 'padding': '8px', 'fontSize': '12px', 'textAlign': 'left', 'zIndex': 999, 'top': '12px', 'left': '12px', 'pointerEvents': 'none', 'boxSizing': 'border-box', 'boxShadow': 'rgba(117, 134, 150, 0.45) 0px 2px 5px 0px', 'background': 'rgba(255, 255, 255, 0.25)', 'borderRadius': '4px 4px 0px 0px', 'borderTopColor': 'rgb(239, 83, 80)', 'borderRightColor': 'rgb(239, 83, 80)', 'borderLeftColor': 'rgb(239, 83, 80)', 'borderBottom': 'none', 'color': '#20262E', 'WebkitFontSmoothing': 'antialiased', 'fontFamily': '-apple-system, BlinkMacSystemFont, "Trebuchet MS", Roboto, Ubuntu, sans-serif', } ), ], style={'left': 0, 'top': 0, 'zIndex': 10}) ]), ] app = dash.Dash(__name__, suppress_callback_exceptions=True, ) app.layout = html.Div(className='container', children=[ html.Div(className='main-container', children=[ html.Div(children=main_panel), ]), ]) app.clientside_callback( ClientsideFunction(namespace="lightweight_chart", function_name="lightweight_chart_tooltips"), [Output("chart-tooltips", "children")], Input("tv-chart-1", "crosshair"), Input("chart-tooltips", "id"), prevent_initial_call=True ) if __name__ == '__main__': app.run_server()
javascript file
function toStrWithTwoDecimals(num) { if (num === undefined) { return "" } else return num.toFixed(2); } function iterateDictValueWithKey(obj) { let str = ""; for (const key in obj) { const value = obj[key]; if (typeof value === "object") { for (const entry of Object.entries(value)) { str += `${entry[0]}:${entry[1]}<br>`; } str += '<br>' } else { str += `${toStrWithTwoDecimals(value)}<br>`; } } return str; } // Define a relatively long callback function in a stand-alone js script window.dash_clientside = Object.assign({}, window.dash_clientside, { lightweight_chart: { lightweight_chart_tooltips: function (param, trigger_id) { let toolTip = document.getElementById(trigger_id) if (param.point === undefined || !param.time || param.point.x < 0) { toolTip.style.display = 'none'; } else { const date_str = param.time.year.toString() + "-" + param.time.month.toString().padStart(2, "0") + "-" + param.time.day.toString().padStart(2, "0"); const price_str = iterateDictValueWithKey(param.seriesPrices) toolTip.style.display = 'block'; toolTip.innerHTML = `<div style="color: ${'rgba( 239, 83, 80, 1)'}">⬤ ABC Inc.</div> <div style="font-size: 18px;color: ${'black'}"> ${date_str} </div> <div style="width:100%;font-size: 12px; margin: 1px; color: ${'black'}"> ${price_str} </div>`; let left = param.point.x; // relative to timeScale left -= 60; toolTip.style.left = left + 'px'; toolTip.style.top = 0 + 'px'; } return window.dash_clientside.no_update; } } });
app.py
javascript file