- Added async methods to polygon.
- The `requests` library is no longer required, with `urllib` being used instead.
- Added the `get_bar_data` function, which returns a dataframe of aggregate data from polygon.
- Opened up the `subscribe` and `unsubscribe` functions

Enhancements:
- Tables will now scroll when the rows exceed table height.

Bugs:
- Fixed a bug preventing async functions being used with horizontal line event.
- Fixed a bug causing the legend to show duplicate lines if the line was created after the legend.
- Fixed a bug causing the line hide icon to persist within the legend after deletion (#75)
- Fixed a bug causing the search box to be unfocused when the chart is loaded.
This commit is contained in:
louisnw
2023-08-27 00:20:05 +01:00
parent 34ce3f7199
commit f72baf95ba
49 changed files with 43156 additions and 1895 deletions

View File

@ -0,0 +1,74 @@
# Events
## Hotkey Example
```python
from lightweight_charts import Chart
def place_buy_order(key):
print(f'Buy {key} shares.')
def place_sell_order(key):
print(f'Sell all shares, because I pressed {key}.')
if __name__ == '__main__':
chart = Chart()
chart.hotkey('shift', (1, 2, 3), place_buy_order)
chart.hotkey('shift', 'X', place_sell_order)
chart.show(block=True)
```
___
## Topbar Example
```python
import pandas as pd
from lightweight_charts import Chart
def get_bar_data(symbol, timeframe):
if symbol not in ('AAPL', 'GOOGL', 'TSLA'):
print(f'No data for "{symbol}"')
return pd.DataFrame()
return pd.read_csv(f'bar_data/{symbol}_{timeframe}.csv')
def on_search(chart, searched_string):
new_data = get_bar_data(searched_string, chart.topbar['timeframe'].value)
if new_data.empty:
return
chart.topbar['symbol'].set(searched_string)
chart.set(new_data)
def on_timeframe_selection(chart):
new_data = get_bar_data(chart.topbar['symbol'].value, chart.topbar['timeframe'].value)
if new_data.empty:
return
chart.set(new_data, True)
def on_horizontal_line_move(chart, line):
print(f'Horizontal line moved to: {line.price}')
if __name__ == '__main__':
chart = Chart(toolbox=True)
chart.legend(True)
chart.events.search += on_search
chart.topbar.textbox('symbol', 'TSLA')
chart.topbar.switcher('timeframe', ('1min', '5min', '30min'), default='5min',
func=on_timeframe_selection)
df = get_bar_data('TSLA', '5min')
chart.set(df)
chart.horizontal_line(200, func=on_horizontal_line_move)
chart.show(block=True)
```

View File

@ -0,0 +1,98 @@
# Alternative GUI's
## PyQt5 / PySide6
```python
import pandas as pd
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from lightweight_charts.widgets import QtChart
app = QApplication([])
window = QMainWindow()
layout = QVBoxLayout()
widget = QWidget()
widget.setLayout(layout)
window.resize(800, 500)
layout.setContentsMargins(0, 0, 0, 0)
chart = QtChart(widget)
df = pd.read_csv('ohlcv.csv')
chart.set(df)
layout.addWidget(chart.get_webview())
window.setCentralWidget(widget)
window.show()
app.exec_()
```
___
## WxPython
```python
import wx
import pandas as pd
from lightweight_charts.widgets import WxChart
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None)
self.SetSize(1000, 500)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(sizer)
chart = WxChart(panel)
df = pd.read_csv('ohlcv.csv')
chart.set(df)
sizer.Add(chart.get_webview(), 1, wx.EXPAND | wx.ALL)
sizer.Layout()
self.Show()
if __name__ == '__main__':
app = wx.App()
frame = MyFrame()
app.MainLoop()
```
___
## Jupyter
```python
import pandas as pd
from lightweight_charts import JupyterChart
chart = JupyterChart()
df = pd.read_csv('ohlcv.csv')
chart.set(df)
chart.load()
```
___
## Streamlit
```python
import pandas as pd
from lightweight_charts.widgets import StreamlitChart
chart = StreamlitChart(width=900, height=600)
df = pd.read_csv('ohlcv.csv')
chart.set(df)
chart.load()
```

View File

@ -0,0 +1,50 @@
# Subcharts
## Grid of 4
```python
import pandas as pd
from lightweight_charts import Chart
if __name__ == '__main__':
chart = Chart(inner_width=0.5, inner_height=0.5)
chart2 = chart.create_subchart(position='right', width=0.5, height=0.5)
chart3 = chart.create_subchart(position='left', width=0.5, height=0.5)
chart4 = chart.create_subchart(position='right', width=0.5, height=0.5)
chart.watermark('1')
chart2.watermark('2')
chart3.watermark('3')
chart4.watermark('4')
df = pd.read_csv('ohlcv.csv')
chart.set(df)
chart2.set(df)
chart3.set(df)
chart4.set(df)
chart.show(block=True)
```
___
## Synced Line Chart
```python
import pandas as pd
from lightweight_charts import Chart
if __name__ == '__main__':
chart = Chart(inner_width=1, inner_height=0.8)
chart.time_scale(visible=False)
chart2 = chart.create_subchart(width=1, height=0.2, sync=True)
line = chart2.create_line()
df = pd.read_csv('ohlcv.csv')
df2 = pd.read_csv('rsi.csv')
chart.set(df)
line.set(df2)
chart.show(block=True)
```

View File

@ -0,0 +1,38 @@
# Table
```python
import pandas as pd
from lightweight_charts import Chart
def on_row_click(row):
row['PL'] = round(row['PL']+1, 2)
row.background_color('PL', 'green' if row['PL'] > 0 else 'red')
table.footer[1] = row['Ticker']
if __name__ == '__main__':
chart = Chart(width=1000, inner_width=0.7, inner_height=1)
subchart = chart.create_subchart(width=0.3, height=0.5)
df = pd.read_csv('ohlcv.csv')
chart.set(df)
subchart.set(df)
table = chart.create_table(width=0.3, height=0.2,
headings=('Ticker', 'Quantity', 'Status', '%', 'PL'),
widths=(0.2, 0.1, 0.2, 0.2, 0.3),
alignments=('center', 'center', 'right', 'right', 'right'),
position='left', func=on_row_click)
table.format('PL', f{table.VALUE}')
table.format('%', f'{table.VALUE} %')
table.new_row('SPY', 3, 'Submitted', 0, 0)
table.new_row('AMD', 1, 'Filled', 25.5, 105.24)
table.new_row('NVDA', 2, 'Filled', -0.5, -8.24)
table.footer(2)
table.footer[0] = 'Selected:'
chart.show(block=True)
```

View File

@ -0,0 +1,73 @@
# Toolbox with persistent drawings
To get started, create a file called `drawings.json`, which should contain:
```
{}
```
___
```python
import pandas as pd
from lightweight_charts import Chart
def get_bar_data(symbol, timeframe):
if symbol not in ('AAPL', 'GOOGL', 'TSLA'):
print(f'No data for "{symbol}"')
return pd.DataFrame()
return pd.read_csv(f'bar_data/{symbol}_{timeframe}.csv')
def on_search(chart, searched_string):
new_data = get_bar_data(searched_string, chart.topbar['timeframe'].value)
if new_data.empty:
return
chart.topbar['symbol'].set(searched_string)
chart.set(new_data)
# Load the drawings saved under the symbol.
chart.toolbox.load_drawings(searched_string)
def on_timeframe_selection(chart):
new_data = get_bar_data(chart.topbar['symbol'].value, chart.topbar['timeframe'].value)
if new_data.empty:
return
# The symbol has not changed, so we want to re-render the drawings.
chart.set(new_data, render_drawings=True)
if __name__ == '__main__':
chart = Chart(toolbox=True)
chart.legend(True)
chart.events.search += on_search
chart.topbar.textbox('symbol', 'TSLA')
chart.topbar.switcher(
'timeframe',
('1min', '5min', '30min'),
default='5min',
func=on_timeframe_selection
)
df = get_bar_data('TSLA', '5min')
chart.set(df)
# Imports the drawings saved in the JSON file.
chart.toolbox.import_drawings('drawings.json')
# Loads the drawings under the default symbol.
chart.toolbox.load_drawings(chart.topbar['symbol'].value)
# Saves drawings based on the symbol.
chart.toolbox.save_drawings_under(chart.topbar['symbol'])
chart.show(block=True)
# Exports the drawings to the JSON file upon close.
chart.toolbox.export_drawings('drawings.json')
```

View File

@ -0,0 +1,48 @@
# YFinance
```python
import datetime as dt
import yfinance as yf
from lightweight_charts import Chart
def get_bar_data(symbol, timeframe):
if timeframe in ('1m', '5m', '30m'):
days = 7 if timeframe == '1m' else 60
start_date = dt.datetime.now()-dt.timedelta(days=days)
else:
start_date = None
chart.spinner(True)
data = yf.download(symbol, start_date, interval=timeframe)
chart.spinner(False)
if data.empty:
return False
chart.set(data)
return True
def on_search(chart, searched_string):
if get_bar_data(searched_string, chart.topbar['timeframe'].value):
chart.topbar['symbol'].set(searched_string)
def on_timeframe_selection(chart):
get_bar_data(chart.topbar['symbol'].value, chart.topbar['timeframe'].value)
if __name__ == '__main__':
chart = Chart(toolbox=True, debug=True)
chart.legend(True)
chart.events.search += on_search
chart.topbar.textbox('symbol', 'n/a')
chart.topbar.switcher(
'timeframe',
('1m', '5m', '30m', '1d', '1wk'),
default='5m',
func=on_timeframe_selection
)
chart.show(block=True)
```