streamlit-lightweight-charts-ntf
This streamlit component wraps lightweight-charts
using the ntf fork.
This fork augments the lightweight-charts with an effective and aligned multipane experience.
The ntf fork is frozen on an old version (v3.8.0), there are no further developments, and no further updates - it is an AS IT IS scenario
. Although it seems very stable and very useful for financial and trading Data Science. It has an extra option pane
that:
- Aligns panes - by width
- synchronises panes mouse moves
- synchronises the hair-cross cursor between charts
Documentation
A nice example from DeKay on how to use:
How to install:
python -m pip install streamlit-lightweight-charts-ntf
How to use:
from streamlit_lightweight_charts_ntf import renderLightweightCharts
renderLightweightCharts(charts: <List of Dicts> , key: <str>)
API
-
charts:
<List of Dicts>
-
key:
<str>
when creating multiple charts in one page
pane
The extra option: In the example below you will notice the option pane
that is used to group charts
It return values from an onClick() event
<List of Dicts>
-
-
time
(x axis)
-
-
-
prices
(y axis)
-
-
-
-
title
(title set in options)
-
-
-
-
-
type
(e.g. Candlestick)
-
-
-
-
-
values
(depending on chart type)
-
-
import streamlit as st
from streamlit_lightweight_charts_ntf import renderLightweightCharts
import json
import numpy as np
import yfinance as yf
import pandas as pd
import pandas_ta as ta
COLOR_BULL = 'rgba(38,166,154,0.9)' # #26a69a
COLOR_BEAR = 'rgba(239,83,80,0.9)' # #ef5350
def dataToJSON(df, column, slice=0, color=None):
data = df[['time', column, 'color']].copy()
data = data.rename(columns={column: "value"})
if(color == None):
data.drop('color', axis=1)
elif(color != 'default'):
data['color'] = color
if(slice > 0):
data = data.iloc[slice:,:]
return json.loads(data.to_json(orient = "records"))
# Request historic pricing data via finance.yahoo.com API
df = yf.Ticker('AAPL').history(period='9mo')[['Open', 'High', 'Low', 'Close', 'Volume']]
# Some data wrangling to match required format
df = df.reset_index()
df.columns = ['time','open','high','low','close','volume'] # rename columns
df['time'] = df['time'].dt.strftime('%Y-%m-%d') # Date to string
# indicators
df.ta.macd(close='close', fast=6, slow=12, signal=5, append=True) # calculate macd
df.ta.ema(close='close', length=14, offset=None, append=True) # EMA fast
df.ta.sma(close='close', length=60, offset=None, append=True) # SMA slow
df.ta.rsi(close='close', length=14, offset=None, append=True) # RSI - momentum oscillator
df['VOL_BID'] = -df['volume'].sample(frac=1).values # shuffle and negate volume values
# export to JSON format
df['color'] = np.where( df['open'] > df['close'], COLOR_BEAR, COLOR_BULL) # bull or bear
candles = json.loads(df.to_json(orient = "records"))
sma_slow = dataToJSON(df,"SMA_60", 60, 'blue')
ema_fast = dataToJSON(df, "EMA_14", 14, 'orange')
vol_ASK = dataToJSON(df,'volume', 0, COLOR_BULL)
vol_BID = dataToJSON(df,'VOL_BID', 0, COLOR_BEAR)
rsi = dataToJSON(df,'RSI_14', 14, 'purple')
macd_fast = dataToJSON(df, "MACDh_6_12_5", 0, 'orange')
macd_slow = dataToJSON(df, "MACDs_6_12_5", 0, 'blue')
df['color'] = np.where( df['MACD_6_12_5'] > 0, COLOR_BULL, COLOR_BEAR) # MACD histogram color
macd_hist = dataToJSON(df, "MACD_6_12_5")
chartMultipaneOptions = [
{
"width": 600,
"height": 600,
"layout": {
"background": {
"type": "solid",
"color": 'white'
},
"textColor": "black"
},
"grid": {
"vertLines": {
"color": "rgba(197, 203, 206, 0.5)"
},
"horzLines": {
"color": "rgba(197, 203, 206, 0.5)"
}
},
"priceScale": {
"borderColor": "rgba(197, 203, 206, 0.8)"
},
"timeScale": {
"borderColor": "rgba(197, 203, 206, 0.8)",
"barSpacing": 10,
"minBarSpacing": 8
}
}
]
seriesMultipaneChart = [
{
"type": 'Candlestick',
"title": 'Main chart',
"data": candles,
"options": {
"upColor": COLOR_BULL,
"downColor": COLOR_BEAR,
"borderVisible": False,
"wickUpColor": COLOR_BULL,
"wickDownColor": COLOR_BEAR,
"pane": 0
}
},
{
"type": 'Line',
"title": 'SMA slow',
"data": sma_slow,
"options": {
"color": 'blue',
"lineWidth": 2,
"pane": 0
}
},
{
"type": 'Line',
"title": 'EMA fast',
"data": ema_fast,
"options": {
"color": 'green',
"lineWidth": 2,
"pane": 0
}
},
{
"type": 'Histogram',
"title": 'volume ASK',
"data": vol_ASK,
"options": {
"priceFormat": {
"type": 'volume',
},
"pane": 1
}
},
{
"type": 'Histogram',
"title": 'volume BID',
"data": vol_BID,
"options": {
"priceFormat": {
"type": 'volume',
},
"pane": 1
}
},
{
"type": 'Line',
"title": 'RSI',
"data": rsi,
"options": {
"lineWidth": 2,
"pane": 2
}
},
{
"type": 'Line',
"title": 'MACD fast',
"data": macd_fast,
"options": {
"lineWidth": 2,
"pane": 3
}
},
{
"type": 'Line',
"title": 'MACD slow',
"data": macd_slow,
"options": {
"lineWidth": 2,
"pane": 3
}
},
{
"type": 'Histogram',
"title": 'MACD histogram',
"data": macd_hist,
"options": {
"lineWidth": 1,
"pane": 3
}
}
]
st.subheader("Multipane Chart with Pandas")
click_events = renderLightweightCharts([
{
"chart": chartMultipaneOptions[0],
"series": seriesMultipaneChart
}
], 'multipane')
print('onClick event', click_events)