Skip to content

Commit

Permalink
...
Browse files Browse the repository at this point in the history
  • Loading branch information
furechan committed Dec 17, 2024
1 parent 991a802 commit 93ced2d
Show file tree
Hide file tree
Showing 9 changed files with 675 additions and 9 deletions.
33 changes: 33 additions & 0 deletions docs/indicator-info.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Indicator info meta-data


## Model

Info attributes are stored as dictionary items in the `info` attribute of an indicator when available, or else as regular attributes of the indicator.

Most metadata attributes are treated as read-only except for `default_pane` which can be modifed by some primitives/modifiers ...



## Retrieve metadata with `get_info`

```python
from mplchart.utils import get_info

default_pane = get_info(indicator, 'default_pane')
```

## Known attributes

```python
same_scale: bool # wether the output uses same scale as input
defaul_pane: str # wich pane to use for a new scale
overbought: float # overbought level
oversold: float # oversold level
yticks: tuple # force major ticks
```

## Design Questions

- Should we split main attributes like `same_scale`, `default_pane` from the other optional read-only attibutes ?
- Should we have a `force_pane` uopdatable attribute to override `default_pane` read-only attribute. Main logic is in the `Chart.get_axes` method.
181 changes: 181 additions & 0 deletions examples/matplotlib-backend.ipynb

Large diffs are not rendered by default.

321 changes: 321 additions & 0 deletions examples/mplchart-interact.ipynb

Large diffs are not rendered by default.

File renamed without changes.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
]

[dependency-groups]
dev = ["numpy<2.0.0", "yfinance", "pytest", "nbmake", "ipykernel", "ta-lib", "ruff"]
dev = ["numpy<2.0.0", "yfinance", "ta-lib", "pytest", "nbmake", "ipykernel", "jinja2", "ipywidgets", "ruff"]


[tool.hatch.build]
Expand Down
6 changes: 3 additions & 3 deletions src/mplchart/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from .wrappers import get_wrapper
from .colors import closest_color
from .utils import series_xy, same_scale
from .utils import series_xy, same_scale, get_info
from .layout import make_twinx, StandardLayout
from .mapper import RawDateMapper, DateIndexMapper

Expand Down Expand Up @@ -297,7 +297,7 @@ def get_target(self, indicator):
if indicator is None:
return "same"

default_pane = getattr(indicator, "default_pane", None)
default_pane = get_info(indicator, "default_pane", None)
if default_pane is not None:
return default_pane

Expand Down Expand Up @@ -433,7 +433,7 @@ def plot_indicator(self, data, indicator):
indicator = wrapper

# Select axes according to indicator properties (default_pane, same_scale)
# target = self.default_pane(indicator)
# target = self.get_target(indicator)
# ax = self.get_axes(target)
ax = None

Expand Down
15 changes: 14 additions & 1 deletion src/mplchart/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,27 @@
TALIB_SAME_SCALE = "Output scale same as input"



def get_info(indicator, name: str, default=None):
"""get indicator info"""

if hasattr(indicator, "info"): # talib
info = indicator.info
else:
info = vars(indicator)

return info.get(name, default)



def same_scale(indicator):
"""Whether indicator uses the same scale as inputs"""

if hasattr(indicator, "function_flags"): # talib
flags = indicator.function_flags or ()
return TALIB_SAME_SCALE in flags

return getattr(indicator, "same_scale", False)
return get_info(indicator, "same_scale", False)


def get_name(indicator):
Expand Down
8 changes: 4 additions & 4 deletions src/mplchart/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from functools import singledispatch

from .model import Wrapper
from .utils import get_name, get_label
from .utils import get_name, get_label, get_info


@singledispatch
Expand Down Expand Up @@ -107,12 +107,12 @@ def plot_result(self, data, chart, ax=None):
)
counter += 1

yticks = getattr(self.indicator, "yticks", ())
yticks = get_info(self.indicator, "yticks", ())
if yticks:
ax.set_yticks(yticks)
ax.grid(axis="y", which="major", linestyle="-", linewidth=2)

oversold = getattr(self.indicator, "oversold", None)
oversold = get_info(self.indicator, "oversold", None)
if oversold is not None:
color = chart.get_color("oversold", ax, self.indicator, fallback="fill")
with np.errstate(invalid="ignore"):
Expand All @@ -126,7 +126,7 @@ def plot_result(self, data, chart, ax=None):
alpha=0.5,
)

overbought = getattr(self.indicator, "overbought", None)
overbought = get_info(self.indicator, "overbought", None)
if overbought is not None:
color = chart.get_color("overbought", ax, self.indicator, fallback="fill")
with np.errstate(invalid="ignore"):
Expand Down
118 changes: 118 additions & 0 deletions uv.lock

Large diffs are not rendered by default.

0 comments on commit 93ced2d

Please sign in to comment.