df and sr accessor enhancements
This commit is contained in:
46
README.md
46
README.md
@ -1,25 +1,49 @@
|
||||
Fork of the original [lightweight-charts](louisnw01/lightweight-charts-python) with enhancements and supporting vectorbtpro workflow
|
||||
* legends cookie matching line colors
|
||||
* automatic colors picks if not provided
|
||||
* support for left and mid price scales
|
||||
* legend color matching each line color
|
||||
* automatic color assignment if not provided
|
||||
* support for multiple scales (right, left, middle1, middle2, histogram)
|
||||
* accepts df,pd.series or vectorbtpro indicator object (including unpacking multi outputs)
|
||||
* new markers_set method allowing to set pd.series or dataframe as markers input
|
||||
* supports simple df/sr accessors `close.lw.plot()` for quick visualization of single panel chart
|
||||
* supports `ch = chart([pane1, pane2], sync=True, title="Title", size="m")` to quickly display chart with N panes (`Panels`). Also supports syncing the Panels `sync=True` or using xloc.
|
||||
* for quick display supports simple df/sr accessors `close.lw.plot()` for quick visualization of single panel chart
|
||||
* df accessor unpacks dataframe columns and display them accordingly (ohlcv as ohlcv, vwap on the right, rsi on the left scale etc.)
|
||||
* multipanes support `ch = chart([pane1, pane2], sync=True, title="Title", size="m")` to quickly display chart with N panes (`Panels`). Also supports syncing the Panels `sync=True` or using xloc.
|
||||
|
||||
|
||||
<img width="1005" alt="image" src="https://github.com/drew2323/lightweight-charts-python/assets/28433232/856c32aa-e0ff-4de0-b4a2-befc34adb571">
|
||||
|
||||
It should be installed directly from this repository.
|
||||
## Instalation
|
||||
Directly from the repository
|
||||
|
||||
```pip install git+https://github.com/drew2323/lightweight-charts-python.git```
|
||||
|
||||
## Examples
|
||||
|
||||
```python
|
||||
from lightweight_charts import chart, Panel
|
||||
from lightweight_charts import chart, Panel, PlotSRAccessor, PlotDFAccessor
|
||||
|
||||
#one liner, displays close series as line on single Panel
|
||||
close.lw.plot()
|
||||
|
||||
close_sr.lw.plot()
|
||||
```
|
||||

|
||||
```python
|
||||
close_sr.lw.plot(size="m") #on medium panesize
|
||||
close_se.lw.plot(histogram=(trade_series, "trades")) #number of trades as histogram is displayed on top of that
|
||||
```
|
||||

|
||||
```python
|
||||
#one liner to display OHLCV
|
||||
ohlcv_df.lw.plot() #if dataframe contains other columns they are displayed too - based on standard settings (rsi-on the left, vwap - right etc.)
|
||||
```
|
||||

|
||||
```python
|
||||
ohlcv_df.lw.plot(left=[(angle_series, "angle_momentum")]) #Another line is displayed on top of OHLCV on left scale
|
||||
```
|
||||

|
||||
```python
|
||||
ohlcv_complex_df.lw.plot() #df containing ohlcv and other columns
|
||||
```
|
||||

|
||||
```python
|
||||
#quick few liner, displays close series with label "close" on right pricescale and rsi on left price scale, all on single Panel
|
||||
pane1 = Panel(
|
||||
right=[(close, "close")],
|
||||
@ -53,7 +77,7 @@ pane2 = Panel(
|
||||
)
|
||||
|
||||
#display both Panels, sync them and pick size, use xloc
|
||||
ch = chart([pane1, pane2], sync=True, title="Title", size="l", xloc=slice("1-1-2024","1-2-2024")
|
||||
ch = chart([pane1, pane2], sync=True, title="Title", size="l", xloc=slice("1-1-2024","1-2-2024"))
|
||||
|
||||
```
|
||||
|
||||
@ -88,7 +112,7 @@ ch = chart([pane1], title="Chart with EntryShort/ExitShort (yellow) and EntryLon
|
||||
|
||||
<div align="center">
|
||||
|
||||
# lightweight-charts-python
|
||||
# lightweight-charts-python - forked from
|
||||
|
||||
[](https://pypi.org/project/lightweight-charts/)
|
||||
[](https://python.org "Go to Python homepage")
|
||||
|
||||
BIN
image-1.png
Normal file
BIN
image-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
image-2.png
Normal file
BIN
image-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
image-3.png
Normal file
BIN
image-3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
image-4.png
Normal file
BIN
image-4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
image-5.png
Normal file
BIN
image-5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
@ -2,4 +2,4 @@ from .abstract import AbstractChart, Window
|
||||
from .chart import Chart
|
||||
from .widgets import JupyterChart
|
||||
from .polygon import PolygonChart
|
||||
from .helpers import chart, Panel, PlotAccessor
|
||||
from .helpers import chart, Panel, PlotSRAccessor, PlotDFAccessor
|
||||
@ -4,15 +4,54 @@ from .util import (
|
||||
)
|
||||
import pandas as pd
|
||||
|
||||
def append_or_extend(target_list, value):
|
||||
if isinstance(value, list):
|
||||
target_list.extend(value) # Extend if it's a list
|
||||
else:
|
||||
target_list.append(value) # Append if it's a single value
|
||||
|
||||
def extend_kwargs(ohlcv, right, left, middle1, middle2, histogram, kwargs):
|
||||
"""
|
||||
Mutate lists based on kwargs for accessor.
|
||||
Used when user added additional series to kwargs when using accessor.
|
||||
"""
|
||||
if 'ohlcv' in kwargs:
|
||||
ohlcv = kwargs['ohlcv'] #ohlcv is only a tuple
|
||||
if 'left' in kwargs:
|
||||
append_or_extend(left, kwargs['left'])
|
||||
if 'right' in kwargs:
|
||||
append_or_extend(right, kwargs['right'])
|
||||
if 'histogram' in kwargs:
|
||||
append_or_extend(histogram, kwargs['histogram'])
|
||||
if 'middle1' in kwargs:
|
||||
append_or_extend(middle1, kwargs['middle1'])
|
||||
if 'middle2' in kwargs:
|
||||
append_or_extend(middle1, kwargs['middle2'])
|
||||
|
||||
return ohlcv #as tuple is immutable
|
||||
|
||||
# Register the custom accessor
|
||||
@pd.api.extensions.register_series_accessor("lw")
|
||||
class PlotAccessor:
|
||||
class PlotSRAccessor:
|
||||
"""
|
||||
Custom plot accessor for pandas series.
|
||||
Custom plot accessor for pandas series. Quickly displays series values as line on the single pane.
|
||||
|
||||
Also additional priceseries can be added on top of them. They can be added
|
||||
for each scale in the correct format - either as tuple(OHLCV) or as list of tuple (others)
|
||||
|
||||
# input parameter / expected format:
|
||||
# ohlcv=(), #(series, entries, exits, other_markers)
|
||||
# histogram=[], # [(series, name, "rgba(53, 94, 59, 0.6)", opacity)]
|
||||
# right=[],
|
||||
# left=[], #[(series, name, entries, exits, other_markers)]
|
||||
# middle1=[],
|
||||
# middle2=[],
|
||||
|
||||
|
||||
Usage: s
|
||||
series.lw.plot()
|
||||
series.lw.plot(size="m")
|
||||
series.lw.plot() #plot series as line
|
||||
series.lw.plot(size="m") #on medium panesize
|
||||
series.lw.plot(histogram=(trade_series, "trades")) #plot histogram with trades on top of that
|
||||
"""
|
||||
def __init__(self, pandas_obj):
|
||||
self._obj = pandas_obj
|
||||
@ -20,11 +59,123 @@ class PlotAccessor:
|
||||
def plot(self, **kwargs):
|
||||
if "size" not in kwargs:
|
||||
kwargs["size"] = "xs"
|
||||
|
||||
ohlcv = ()
|
||||
right = []
|
||||
left = []
|
||||
middle1 = []
|
||||
middle2 = []
|
||||
histogram = []
|
||||
|
||||
#if there are additional series in kwargs add them too
|
||||
#ohlcv is returned as it is tuple thus immutable
|
||||
ohlcv = extend_kwargs(ohlcv, right, left, middle1, middle2, histogram, kwargs)
|
||||
|
||||
right.append((self._obj,"line"))
|
||||
|
||||
pane1 = Panel(
|
||||
right=[(self._obj, "line")],
|
||||
)
|
||||
ohlcv=ohlcv,
|
||||
histogram=histogram,
|
||||
right=right,
|
||||
left=left,
|
||||
middle1=middle1,
|
||||
middle2=middle2
|
||||
)
|
||||
|
||||
ch = chart([pane1], **kwargs)
|
||||
|
||||
@pd.api.extensions.register_dataframe_accessor("lw")
|
||||
class PlotDFAccessor:
|
||||
"""
|
||||
Custom plot accessor for dataframe. Quickly displays all columns on the single pane.
|
||||
|
||||
Series type is automatically extracted for each column based on following setting:
|
||||
scale / columns
|
||||
ohlcv = ['close', 'volume', 'open', 'high', 'low']
|
||||
right = ['vwap']
|
||||
left = ['rsi']
|
||||
middle1 = []
|
||||
middle2 = []
|
||||
histogram = ['buyvolume', 'sellvolume', 'trades']
|
||||
|
||||
Also additional priceseries can be added on top of them as parameters. They can be added
|
||||
for each scale in the correct format - either as tuple(OHLCV) or as list of tuple (others)
|
||||
|
||||
# input parameter / expected format:
|
||||
# ohlcv=(), #(series, entries, exits, other_markers)
|
||||
# histogram=[], # [(series, name, "rgba(53, 94, 59, 0.6)", opacity)]
|
||||
# right=[],
|
||||
# left=[], #[(series, name, entries, exits, other_markers)]
|
||||
# middle1=[],
|
||||
# middle2=[],
|
||||
|
||||
|
||||
Usage:
|
||||
ohlcv_df.lw.plot()
|
||||
ohlcv_df.lw.plot(size="m")
|
||||
ohlcv_df.lw.plot(right=(rsi_series, "rsi"))
|
||||
ohlcv_df.lw.plot(right=[(rsi_series, "rsi"), (angle_series, "angle")])
|
||||
basic_data.data[SYMBOL].lw.plot(histogram=(basic_data.data[SYMBOL].close, "close"), size="m")
|
||||
"""
|
||||
def __init__(self, pandas_obj):
|
||||
self._obj = pandas_obj
|
||||
|
||||
def plot(self, **kwargs):
|
||||
if "size" not in kwargs:
|
||||
kwargs["size"] = "xs"
|
||||
|
||||
#default settings for each pricescale
|
||||
ohlcv_cols = ['close', 'volume', 'open', 'high', 'low']
|
||||
right_cols = ['vwap']
|
||||
left_cols = ['rsi']
|
||||
middle1_cols = []
|
||||
middle2_cols = []
|
||||
histogram_cols = ['buyvolume', 'sellvolume', 'trades']
|
||||
|
||||
ohlcv = ()
|
||||
right = []
|
||||
left = []
|
||||
middle1 = []
|
||||
middle2 = []
|
||||
histogram = []
|
||||
|
||||
for col in self._obj.columns:
|
||||
if col in right_cols:
|
||||
right.append((self._obj[col],col,))
|
||||
if col in histogram_cols:
|
||||
histogram.append((self._obj[col],col,))
|
||||
if col in left_cols:
|
||||
left.append((self._obj[col],col,))
|
||||
if col in middle1_cols:
|
||||
middle1_cols.append((self._obj[col],col,))
|
||||
if col in middle2_cols:
|
||||
middle2_cols.append((self._obj[col],col,))
|
||||
|
||||
ohlcv = (self._obj[ohlcv_cols],)
|
||||
|
||||
#if there are additional series in kwargs add them too
|
||||
ohlcv = extend_kwargs(ohlcv, right, left, middle1, middle2, histogram, kwargs)
|
||||
|
||||
pane1 = Panel(
|
||||
ohlcv=ohlcv,
|
||||
histogram=histogram,
|
||||
right=right,
|
||||
left=left,
|
||||
middle1=middle1,
|
||||
middle2=middle2
|
||||
)
|
||||
|
||||
ch = chart([pane1], **kwargs)
|
||||
|
||||
# pane1 = Panel(
|
||||
# ohlcv=(), #(series, entries, exits, other_markers)
|
||||
# histogram=[], # [(series, name, "rgba(53, 94, 59, 0.6)", opacity)]
|
||||
# right=[],
|
||||
# left=[], #[(series, name, entries, exits, other_markers)]
|
||||
# middle1=[],
|
||||
# middle2=[],
|
||||
# )
|
||||
|
||||
class Panel:
|
||||
"""
|
||||
A class to represent a panel in a chart.
|
||||
@ -118,7 +269,7 @@ class Panel:
|
||||
self.precision = precision
|
||||
|
||||
|
||||
def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session: str="9:30:00, 09:30:05", precision=None):
|
||||
def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session: str="9:30:00, 09:30:05", precision=None, **kwargs):
|
||||
"""
|
||||
Function to fast render a chart with multiple panes. This function manipulates graphical
|
||||
output or interfaces with an external framework to display charts with synchronized
|
||||
|
||||
Reference in New Issue
Block a user