support for markers list
This commit is contained in:
@ -14,78 +14,12 @@ from .topbar import TopBar
|
|||||||
from .util import (
|
from .util import (
|
||||||
BulkRunScript, Pane, Events, IDGen, as_enum, jbool, js_json, TIME, NUM, FLOAT,
|
BulkRunScript, Pane, Events, IDGen, as_enum, jbool, js_json, TIME, NUM, FLOAT,
|
||||||
LINE_STYLE, MARKER_POSITION, MARKER_SHAPE, CROSSHAIR_MODE, MARKER_TYPE,
|
LINE_STYLE, MARKER_POSITION, MARKER_SHAPE, CROSSHAIR_MODE, MARKER_TYPE,
|
||||||
PRICE_SCALE_MODE, marker_position, marker_shape, js_data, is_vbt_indicator, apply_opacity
|
PRICE_SCALE_MODE, marker_position, marker_shape, js_data, is_vbt_indicator, apply_opacity, get_next_color
|
||||||
)
|
)
|
||||||
|
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
INDEX = os.path.join(current_dir, 'js', 'index.html')
|
INDEX = os.path.join(current_dir, 'js', 'index.html')
|
||||||
|
|
||||||
# # Predefined colors that stand out well on dark backgrounds
|
|
||||||
# COLORS = [
|
|
||||||
# 'rgba(255, 0, 0, 0.6)', # Red
|
|
||||||
# 'rgba(0, 255, 0, 0.6)', # Green
|
|
||||||
# 'rgba(0, 0, 255, 0.6)', # Blue
|
|
||||||
# 'rgba(255, 255, 0, 0.6)', # Yellow
|
|
||||||
# 'rgba(255, 165, 0, 0.6)', # Orange
|
|
||||||
# 'rgba(75, 0, 130, 0.6)', # Indigo
|
|
||||||
# 'rgba(238, 130, 238, 0.6)', # Violet
|
|
||||||
# 'rgba(0, 255, 255, 0.6)', # Cyan
|
|
||||||
# 'rgba(255, 192, 203, 0.6)', # Pink
|
|
||||||
# 'rgba(0, 128, 128, 0.6)', # Teal
|
|
||||||
# 'rgba(128, 0, 128, 0.6)', # Purple
|
|
||||||
# 'rgba(255, 215, 0, 0.6)', # Gold
|
|
||||||
# 'rgba(173, 255, 47, 0.6)', # Green Yellow
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# def get_next_color():
|
|
||||||
# return random.choice(COLORS)
|
|
||||||
|
|
||||||
# Predefined pool of colors
|
|
||||||
COLORS = [
|
|
||||||
"#63AA57", "#8F8AB0", "#E24AEE", "#D06AA6", "#7891BA", "#A39A34", "#8A94A2", "#61BB2F",
|
|
||||||
"#FD569D", "#1EB6E1", "#379AC9", "#FD6F2E", "#8C9858", "#39A4A3", "#6D97F4", "#1ECB01", "#FA5B16", "#A6891C",
|
|
||||||
"#48CF10", "#D27B26", "#D56B55", "#FE3AB8", "#E35C51", "#EC4FE6", "#E250A3", "#BA618E", "#1BC074", "#C57784",
|
|
||||||
"#888BC5", "#4FA452", "#80885C", "#B97272", "#33BF98", "#B7961D", "#A07284", "#02E54E", "#AF7F35", "#F852EF",
|
|
||||||
"#6D955B", "#E0676E", "#F73DEC", "#CE53FD", "#9773D3", "#649E81", "#D062CE", "#AB73E7", "#A4729C", "#E76A07",
|
|
||||||
"#E85CCB", "#A16FB1", "#4BB859", "#B25EE2", "#8580CE", "#A275EF", "#AC9245", "#4D988D", "#B672C9", "#4CA96E",
|
|
||||||
"#C9873E", "#5BB147", "#10C783", "#D7647D", "#CB893A", "#A586BA", "#28C0A2", "#61A755", "#0EB7C5", "#2DADBC",
|
|
||||||
"#17BB71", "#2BC733", "#2BB890", "#F04EF8", "#699580", "#A88809", "#EB3FF6", "#A75ED3", "#859171", "#BB6285",
|
|
||||||
"#81A147", "#AD7CD2", "#65B630", "#C9616C", "#BD5EFA", "#7A9F30", "#2AB6AB", "#FC496A", "#687FC7", "#DB40E7",
|
|
||||||
"#07BCE9", "#509F63", "#EC4FDD", "#A079BE", "#C17297", "#E447C2", "#E95AD9", "#9FA01E", "#7E86CF", "#21E316",
|
|
||||||
"#1CABF9", "#17C24F", "#9C9254", "#C97994", "#4BA9DA", "#0DD595", "#13BEA8", "#C2855D", "#DF6C13", "#60B370",
|
|
||||||
"#0FC3F6", "#C1830E", "#3AC917", "#0EBBB0", "#CC50B4", "#B768EC", "#D47F49", "#B47BC5", "#38ADBD", "#05DC53",
|
|
||||||
"#44CD4E", "#838E65", "#49D70F", "#2DADBE", "#2CB0C9", "#DA703E", "#06B5CA", "#7BAF3E", "#918E79", "#2AA5E5",
|
|
||||||
"#C37F5E", "#07B8C9", "#4CBA27", "#E752C6", "#7F93B2", "#4798CD", "#45AA4C", "#4DB666", "#7683A7", "#758685",
|
|
||||||
"#4B9FAD", "#9280FD", "#6682DD", "#42ACBE", "#C1609F", "#D850DB", "#649A62", "#54CC22", "#AD81C1", "#BF7A43",
|
|
||||||
"#0FCEA5", "#D06DAF", "#87799B", "#4DA94E", "#2FD654", "#07D587", "#21CF0C", "#03CF34", "#42C771", "#D563CD",
|
|
||||||
"#6D9E9A", "#C76C59", "#68B368", "#11BCE5", "#0DCFB3", "#9266D8", "#BF67F6", "#88A04E", "#73BE17", "#67B437",
|
|
||||||
"#8586E4", "#9F8749", "#479CA5", "#CC777E", "#4FAF46", "#9D9836", "#918DAF", "#D167B8", "#6F9DA5", "#2BB167",
|
|
||||||
"#16B8BC", "#B4861F", "#A08487", "#67B357", "#5CAA5C", "#20CA49", "#D18813", "#15D63F", "#C8618F", "#887E92",
|
|
||||||
"#21C457", "#4EA8CE", "#53BE49", "#5A86D5", "#BD7E4E", "#27B0A1", "#33CF42", "#709083", "#38A8DE", "#4CA762",
|
|
||||||
"#1EA4FF", "#DE3EE4", "#70A860", "#39A3C8", "#6BBB39", "#F053F4", "#8C7FB5", "#969F21", "#B19841", "#E57148",
|
|
||||||
"#C25DA7", "#6DA979", "#B27D73", "#7F9786", "#41AC99", "#C58848", "#948F9E", "#6BB620", "#81AB3B", "#09DE44",
|
|
||||||
"#43A9D2", "#41B0D7", "#20ACAA", "#649FCB", "#CD8345", "#A88669", "#3EA5E7", "#F36A19", "#E06B48", "#8388BD",
|
|
||||||
"#EC6153", "#639082", "#52CA32", "#878BAA", "#02BCDB", "#828FD9", "#3DC07F", "#29D46A", "#9C7CC1", "#EB7713",
|
|
||||||
"#F95F6A", "#E25F4C", "#589994", "#D45AB7", "#DE66AB", "#B8715F", "#E850F4", "#FB6420", "#C2832C", "#6383C5",
|
|
||||||
"#D57A58", "#EF652C", "#02D71A", "#ED664D", "#60A526"
|
|
||||||
]
|
|
||||||
|
|
||||||
# Iterator to keep track of the current color index
|
|
||||||
color_index = 0
|
|
||||||
|
|
||||||
def get_next_color():
|
|
||||||
global color_index
|
|
||||||
# Get the next color from the list
|
|
||||||
color = COLORS[color_index]
|
|
||||||
# Convert the color from HEX to RGBA format
|
|
||||||
color_index = (color_index + 1) % len(COLORS)
|
|
||||||
return hex_to_rgba(color)
|
|
||||||
|
|
||||||
def hex_to_rgba(hex_color, alpha=0.5):
|
|
||||||
hex_color = hex_color.lstrip('#')
|
|
||||||
r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16)
|
|
||||||
return f'rgba({r}, {g}, {b}, {alpha})'
|
|
||||||
|
|
||||||
class Window:
|
class Window:
|
||||||
_id_gen = IDGen()
|
_id_gen = IDGen()
|
||||||
handlers = {}
|
handlers = {}
|
||||||
@ -336,7 +270,7 @@ class SeriesCommon(Pane):
|
|||||||
col_name: Optional[str] = None,
|
col_name: Optional[str] = None,
|
||||||
position: MARKER_POSITION = 'below',
|
position: MARKER_POSITION = 'below',
|
||||||
shape: MARKER_SHAPE = 'arrow_up',
|
shape: MARKER_SHAPE = 'arrow_up',
|
||||||
color: str = '#2196F3', text: str = ''):
|
color: str = None, text: str = ''):
|
||||||
"""
|
"""
|
||||||
Adds multiple markers from pd series or Dataframe
|
Adds multiple markers from pd series or Dataframe
|
||||||
:param markers: A pandas Series or Dataframe with DateTimeIndex and boolean values.
|
:param markers: A pandas Series or Dataframe with DateTimeIndex and boolean values.
|
||||||
@ -356,11 +290,11 @@ class SeriesCommon(Pane):
|
|||||||
case "entries":
|
case "entries":
|
||||||
position = "below"
|
position = "below"
|
||||||
shape = "arrow_up"
|
shape = "arrow_up"
|
||||||
color = "blue"
|
color = "blue" if color is None else color
|
||||||
case "exits":
|
case "exits":
|
||||||
position = "above"
|
position = "above"
|
||||||
shape = "arrow_down"
|
shape = "arrow_down"
|
||||||
color = "red"
|
color = "red" if color is None else color
|
||||||
|
|
||||||
if isinstance(markers, pd.Series):
|
if isinstance(markers, pd.Series):
|
||||||
markers = markers.to_frame(name="markers")
|
markers = markers.to_frame(name="markers")
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from .widgets import JupyterChart
|
from .widgets import JupyterChart
|
||||||
from .util import (
|
from .util import (
|
||||||
is_vbt_indicator
|
is_vbt_indicator, get_next_color
|
||||||
)
|
)
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
@ -32,7 +32,8 @@ class Panel:
|
|||||||
Attributes
|
Attributes
|
||||||
----------
|
----------
|
||||||
* ohlcv : tuple optional\n
|
* ohlcv : tuple optional\n
|
||||||
(series, entries, exits, other_markers)
|
(series, entries, exits, other_markers).\n
|
||||||
|
entries, exits and other_markers can be sr/df or lists of sr/df or list of tuples (if you want to specify color)
|
||||||
* histogram : list of tuples, optional.\n
|
* histogram : list of tuples, optional.\n
|
||||||
[(series, name, color, opacity)]
|
[(series, name, color, opacity)]
|
||||||
* title : str, optional
|
* title : str, optional
|
||||||
@ -83,6 +84,26 @@ class Panel:
|
|||||||
)
|
)
|
||||||
|
|
||||||
ch = chart([pane1, pane2], sync=True, title="neco", size="m", xloc=slice("2024-02-12 09:30","2024-02-12 16:00"))
|
ch = chart([pane1, pane2], sync=True, title="neco", size="m", xloc=slice("2024-02-12 09:30","2024-02-12 16:00"))
|
||||||
|
|
||||||
|
#Markers examples
|
||||||
|
|
||||||
|
#assume i want to display simple entries or exits on series or ohlcv
|
||||||
|
#based on tuple positions it determines entries or exits (and set colors and shape accordingly)
|
||||||
|
pane1 = Panel(
|
||||||
|
ohlcv=(ohlcv_df, clean_long_entries, clean_short_entries)
|
||||||
|
)
|
||||||
|
ch = chart([pane1], title="Chart with Entry/Exit Markers", session=None, size="s")
|
||||||
|
|
||||||
|
#if you want to display more entries or exits, use tuples with their colors
|
||||||
|
# Create Panel with OHLC data and entry signals
|
||||||
|
pane1 = Panel(
|
||||||
|
ohlcv=(data.ohlcv.get(),
|
||||||
|
[(clean_long_entries, "yellow"), (clean_short_entries, "pink")], #list of entries tuples with color
|
||||||
|
[(clean_long_exits, "yellow"), (clean_short_exits, "pink")]), #list of exits tuples with color
|
||||||
|
)
|
||||||
|
|
||||||
|
# # Create the chart with the panel
|
||||||
|
ch = chart([pane1], title="Chart with EntryShort/ExitShort (yellow) and EntryLong/ExitLong markers (pink)", sync=True, session=None, size="s")
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
def __init__(self, ohlcv=None, right=None, left=None, middle1=None, middle2=None, histogram=None, title=None, xloc=None, precision=None):
|
def __init__(self, ohlcv=None, right=None, left=None, middle1=None, middle2=None, histogram=None, title=None, xloc=None, precision=None):
|
||||||
@ -97,7 +118,7 @@ class Panel:
|
|||||||
self.precision = precision
|
self.precision = precision
|
||||||
|
|
||||||
|
|
||||||
def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session: str="9:30", precision=None):
|
def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session: str="9:30:00", precision=None):
|
||||||
"""
|
"""
|
||||||
Function to fast render a chart with multiple panes. This function manipulates graphical
|
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
|
output or interfaces with an external framework to display charts with synchronized
|
||||||
@ -177,13 +198,14 @@ def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session
|
|||||||
return dfsr.vbt.xloc[xloc].obj
|
return dfsr.vbt.xloc[xloc].obj
|
||||||
|
|
||||||
size_to_dimensions = {
|
size_to_dimensions = {
|
||||||
'xs': (600, 300),
|
'xs': (600, 200),
|
||||||
's': (800, 400),
|
's': (800, 400),
|
||||||
'm': (1000, 600),
|
'm': (1000, 600),
|
||||||
'l': (1300, 800)}
|
'l': (1300, 800)}
|
||||||
width, height = size_to_dimensions.get(size, (1000, 600))
|
width, height = size_to_dimensions.get(size, (1000, 600))
|
||||||
height_ratio = 1 / len(panes)
|
height_ratio = 1 / len(panes)
|
||||||
main_title_set = False
|
main_title_set = False
|
||||||
|
output_series = None
|
||||||
for index, pane in enumerate(panes):
|
for index, pane in enumerate(panes):
|
||||||
subchartX = None
|
subchartX = None
|
||||||
if index == 0:
|
if index == 0:
|
||||||
@ -195,15 +217,30 @@ def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session
|
|||||||
|
|
||||||
xloc = pane.xloc if pane.xloc is not None else xloc
|
xloc = pane.xloc if pane.xloc is not None else xloc
|
||||||
|
|
||||||
if pane.ohlcv is not None:
|
def display_markers(active_chart: JupyterChart, markers, type= None, xloc=None):
|
||||||
|
color = None
|
||||||
|
if isinstance(markers, list):
|
||||||
|
for markerset in markers:
|
||||||
|
if isinstance(markerset, tuple):
|
||||||
|
markerset,color = markerset
|
||||||
|
active_chart.markers_set(markers=xloc_me(markerset, xloc), type=type, color=color if color is not None else None)
|
||||||
|
else:
|
||||||
|
if isinstance(markers, tuple):
|
||||||
|
markers,color = markers
|
||||||
|
active_chart.markers_set(markers=xloc_me(markers, xloc), type=type, color=color if color is not None else None)
|
||||||
|
|
||||||
|
|
||||||
|
if pane.ohlcv != ():
|
||||||
series, entries, exits, markers = (pane.ohlcv + (None,) * 4)[:4]
|
series, entries, exits, markers = (pane.ohlcv + (None,) * 4)[:4]
|
||||||
|
if series is None:
|
||||||
|
raise ValueError("OHLCV series cannot be None. Omit the OHLCV tuple.")
|
||||||
active_chart.set(xloc_me(series, xloc))
|
active_chart.set(xloc_me(series, xloc))
|
||||||
if entries is not None:
|
if entries is not None:
|
||||||
active_chart.markers_set(xloc_me(entries, xloc), "entries")
|
display_markers(active_chart=active_chart, markers=entries, type="entries", xloc=xloc)
|
||||||
if exits is not None:
|
if exits is not None:
|
||||||
active_chart.markers_set(xloc_me(exits, xloc), "exits")
|
display_markers(active_chart=active_chart, markers=exits, type="exits", xloc=xloc)
|
||||||
if markers is not None:
|
if markers is not None:
|
||||||
active_chart.markers_set(xloc_me(markers, xloc))
|
display_markers(chart=active_chart, markers=markers, xloc=xloc)
|
||||||
|
|
||||||
for tup in pane.histogram:
|
for tup in pane.histogram:
|
||||||
series, name, color, opacity, _ = (tup + (None, None, None, None, None))[:5]
|
series, name, color, opacity, _ = (tup + (None, None, None, None, None))[:5]
|
||||||
@ -235,7 +272,8 @@ def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session
|
|||||||
if is_vbt_indicator(series):
|
if is_vbt_indicator(series):
|
||||||
series = series.xloc[xloc] if xloc is not None else series
|
series = series.xloc[xloc] if xloc is not None else series
|
||||||
for output in series.output_names:
|
for output in series.output_names:
|
||||||
output_series = getattr(series, output)
|
output_series = getattr(series, output)
|
||||||
|
output = name + ':' + output if name is not None else output
|
||||||
tmp = active_chart.create_line(name=output, priceScaleId=att_name)#, color="blue")
|
tmp = active_chart.create_line(name=output, priceScaleId=att_name)#, color="blue")
|
||||||
tmp.set(output_series)
|
tmp.set(output_series)
|
||||||
else:
|
else:
|
||||||
@ -249,16 +287,17 @@ def chart(panes: list[Panel], sync=False, title='', size="m", xloc=None, session
|
|||||||
tmp.precision(pane.precision if pane.precision is not None else precision)
|
tmp.precision(pane.precision if pane.precision is not None else precision)
|
||||||
|
|
||||||
if entries is not None:
|
if entries is not None:
|
||||||
tmp.markers_set(xloc_me(entries, xloc), "entries")
|
display_markers(active_chart=tmp, markers=entries, type="entries", xloc=xloc)
|
||||||
if exits is not None:
|
if exits is not None:
|
||||||
tmp.markers_set(xloc_me(exits, xloc), "exits")
|
display_markers(active_chart=tmp, markers=exits, type="exits", xloc=xloc)
|
||||||
if markers is not None:
|
if markers is not None:
|
||||||
tmp.markers_set(xloc_me(markers, xloc))
|
display_markers(active_chart=tmp, markers=markers, xloc=xloc)
|
||||||
|
|
||||||
active_chart.legend(True)
|
active_chart.legend(True)
|
||||||
active_chart.fit()
|
active_chart.fit()
|
||||||
if session is not None and session:
|
if session is not None and session:
|
||||||
active_chart.vertical_span(start_time=xloc_me(series, xloc).vbt.xloc[session].obj.index.to_list(), color="rgba(252, 255, 187, 0.42)")
|
last_used_series = output_series if is_vbt_indicator(series) else series #pokud byl posledni series vbt, pak pouzijeme jeho outputy
|
||||||
|
active_chart.vertical_span(start_time=xloc_me(last_used_series, xloc).vbt.xloc[session].obj.index.to_list(), color="rgba(252, 255, 187, 0.42)")
|
||||||
|
|
||||||
if not main_title_set:
|
if not main_title_set:
|
||||||
chartX.topbar.textbox("title",title)
|
chartX.topbar.textbox("title",title)
|
||||||
|
|||||||
@ -8,6 +8,72 @@ import pandas as pd
|
|||||||
import re
|
import re
|
||||||
from matplotlib.colors import to_rgba
|
from matplotlib.colors import to_rgba
|
||||||
|
|
||||||
|
# # Predefined colors that stand out well on dark backgrounds
|
||||||
|
# COLORS = [
|
||||||
|
# 'rgba(255, 0, 0, 0.6)', # Red
|
||||||
|
# 'rgba(0, 255, 0, 0.6)', # Green
|
||||||
|
# 'rgba(0, 0, 255, 0.6)', # Blue
|
||||||
|
# 'rgba(255, 255, 0, 0.6)', # Yellow
|
||||||
|
# 'rgba(255, 165, 0, 0.6)', # Orange
|
||||||
|
# 'rgba(75, 0, 130, 0.6)', # Indigo
|
||||||
|
# 'rgba(238, 130, 238, 0.6)', # Violet
|
||||||
|
# 'rgba(0, 255, 255, 0.6)', # Cyan
|
||||||
|
# 'rgba(255, 192, 203, 0.6)', # Pink
|
||||||
|
# 'rgba(0, 128, 128, 0.6)', # Teal
|
||||||
|
# 'rgba(128, 0, 128, 0.6)', # Purple
|
||||||
|
# 'rgba(255, 215, 0, 0.6)', # Gold
|
||||||
|
# 'rgba(173, 255, 47, 0.6)', # Green Yellow
|
||||||
|
# ]
|
||||||
|
|
||||||
|
# def get_next_color():
|
||||||
|
# return random.choice(COLORS)
|
||||||
|
|
||||||
|
# Predefined pool of colors
|
||||||
|
COLORS = [
|
||||||
|
"#63AA57", "#8F8AB0", "#E24AEE", "#D06AA6", "#7891BA", "#A39A34", "#8A94A2", "#61BB2F",
|
||||||
|
"#FD569D", "#1EB6E1", "#379AC9", "#FD6F2E", "#8C9858", "#39A4A3", "#6D97F4", "#1ECB01", "#FA5B16", "#A6891C",
|
||||||
|
"#48CF10", "#D27B26", "#D56B55", "#FE3AB8", "#E35C51", "#EC4FE6", "#E250A3", "#BA618E", "#1BC074", "#C57784",
|
||||||
|
"#888BC5", "#4FA452", "#80885C", "#B97272", "#33BF98", "#B7961D", "#A07284", "#02E54E", "#AF7F35", "#F852EF",
|
||||||
|
"#6D955B", "#E0676E", "#F73DEC", "#CE53FD", "#9773D3", "#649E81", "#D062CE", "#AB73E7", "#A4729C", "#E76A07",
|
||||||
|
"#E85CCB", "#A16FB1", "#4BB859", "#B25EE2", "#8580CE", "#A275EF", "#AC9245", "#4D988D", "#B672C9", "#4CA96E",
|
||||||
|
"#C9873E", "#5BB147", "#10C783", "#D7647D", "#CB893A", "#A586BA", "#28C0A2", "#61A755", "#0EB7C5", "#2DADBC",
|
||||||
|
"#17BB71", "#2BC733", "#2BB890", "#F04EF8", "#699580", "#A88809", "#EB3FF6", "#A75ED3", "#859171", "#BB6285",
|
||||||
|
"#81A147", "#AD7CD2", "#65B630", "#C9616C", "#BD5EFA", "#7A9F30", "#2AB6AB", "#FC496A", "#687FC7", "#DB40E7",
|
||||||
|
"#07BCE9", "#509F63", "#EC4FDD", "#A079BE", "#C17297", "#E447C2", "#E95AD9", "#9FA01E", "#7E86CF", "#21E316",
|
||||||
|
"#1CABF9", "#17C24F", "#9C9254", "#C97994", "#4BA9DA", "#0DD595", "#13BEA8", "#C2855D", "#DF6C13", "#60B370",
|
||||||
|
"#0FC3F6", "#C1830E", "#3AC917", "#0EBBB0", "#CC50B4", "#B768EC", "#D47F49", "#B47BC5", "#38ADBD", "#05DC53",
|
||||||
|
"#44CD4E", "#838E65", "#49D70F", "#2DADBE", "#2CB0C9", "#DA703E", "#06B5CA", "#7BAF3E", "#918E79", "#2AA5E5",
|
||||||
|
"#C37F5E", "#07B8C9", "#4CBA27", "#E752C6", "#7F93B2", "#4798CD", "#45AA4C", "#4DB666", "#7683A7", "#758685",
|
||||||
|
"#4B9FAD", "#9280FD", "#6682DD", "#42ACBE", "#C1609F", "#D850DB", "#649A62", "#54CC22", "#AD81C1", "#BF7A43",
|
||||||
|
"#0FCEA5", "#D06DAF", "#87799B", "#4DA94E", "#2FD654", "#07D587", "#21CF0C", "#03CF34", "#42C771", "#D563CD",
|
||||||
|
"#6D9E9A", "#C76C59", "#68B368", "#11BCE5", "#0DCFB3", "#9266D8", "#BF67F6", "#88A04E", "#73BE17", "#67B437",
|
||||||
|
"#8586E4", "#9F8749", "#479CA5", "#CC777E", "#4FAF46", "#9D9836", "#918DAF", "#D167B8", "#6F9DA5", "#2BB167",
|
||||||
|
"#16B8BC", "#B4861F", "#A08487", "#67B357", "#5CAA5C", "#20CA49", "#D18813", "#15D63F", "#C8618F", "#887E92",
|
||||||
|
"#21C457", "#4EA8CE", "#53BE49", "#5A86D5", "#BD7E4E", "#27B0A1", "#33CF42", "#709083", "#38A8DE", "#4CA762",
|
||||||
|
"#1EA4FF", "#DE3EE4", "#70A860", "#39A3C8", "#6BBB39", "#F053F4", "#8C7FB5", "#969F21", "#B19841", "#E57148",
|
||||||
|
"#C25DA7", "#6DA979", "#B27D73", "#7F9786", "#41AC99", "#C58848", "#948F9E", "#6BB620", "#81AB3B", "#09DE44",
|
||||||
|
"#43A9D2", "#41B0D7", "#20ACAA", "#649FCB", "#CD8345", "#A88669", "#3EA5E7", "#F36A19", "#E06B48", "#8388BD",
|
||||||
|
"#EC6153", "#639082", "#52CA32", "#878BAA", "#02BCDB", "#828FD9", "#3DC07F", "#29D46A", "#9C7CC1", "#EB7713",
|
||||||
|
"#F95F6A", "#E25F4C", "#589994", "#D45AB7", "#DE66AB", "#B8715F", "#E850F4", "#FB6420", "#C2832C", "#6383C5",
|
||||||
|
"#D57A58", "#EF652C", "#02D71A", "#ED664D", "#60A526"
|
||||||
|
]
|
||||||
|
|
||||||
|
# Iterator to keep track of the current color index
|
||||||
|
color_index = 0
|
||||||
|
|
||||||
|
def get_next_color():
|
||||||
|
global color_index
|
||||||
|
# Get the next color from the list
|
||||||
|
color = COLORS[color_index]
|
||||||
|
# Convert the color from HEX to RGBA format
|
||||||
|
color_index = (color_index + 1) % len(COLORS)
|
||||||
|
return hex_to_rgba(color)
|
||||||
|
|
||||||
|
def hex_to_rgba(hex_color, alpha=0.5):
|
||||||
|
hex_color = hex_color.lstrip('#')
|
||||||
|
r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16)
|
||||||
|
return f'rgba({r}, {g}, {b}, {alpha})'
|
||||||
|
|
||||||
def apply_opacity(color, opacity):
|
def apply_opacity(color, opacity):
|
||||||
"""
|
"""
|
||||||
Converts any color format (named, hex, RGB, or RGBA) to RGBA format and applies a specified opacity.
|
Converts any color format (named, hex, RGB, or RGBA) to RGBA format and applies a specified opacity.
|
||||||
|
|||||||
2
setup.py
2
setup.py
@ -5,7 +5,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='lightweight_charts',
|
name='lightweight_charts',
|
||||||
version='2.1.3',
|
version='2.1.4',
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
python_requires='>=3.8',
|
python_requires='>=3.8',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
|||||||
Reference in New Issue
Block a user