Skip to content

Commit

Permalink
...
Browse files Browse the repository at this point in the history
  • Loading branch information
furechan committed Dec 19, 2024
1 parent 82048eb commit 3bdd0e7
Show file tree
Hide file tree
Showing 14 changed files with 389 additions and 63 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


## 0.0.15
- Added `Stripes` primitive to plot vertical stripes depending on a flag value (experimental)
- Added `alpha` parameter to `Price`, `OHLC`, `Candlesticks`, `Volume`

## 0.0.14
Expand Down
File renamed without changes.
22 changes: 11 additions & 11 deletions examples/macd-indicator.ipynb

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions examples/ppo-indicator.ipynb

Large diffs are not rendered by default.

File renamed without changes.
144 changes: 144 additions & 0 deletions examples/stripes-example.ipynb

Large diffs are not rendered by default.

File renamed without changes.
139 changes: 139 additions & 0 deletions misc/slope-indicator.ipynb

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions src/mplchart/indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def __call__(self, prices):


class SLOPE(Indicator):
"""Slope (Linear regression with time)"""
"""Slope (Time linear regression)"""

def __init__(self, period: int = 20):
self.period = period
Expand All @@ -100,6 +100,17 @@ def __call__(self, prices):
return library.calc_slope(series, self.period)


class RVALUE(Indicator):
"""RValue (Time linear regression)"""

def __init__(self, period: int = 20):
self.period = period

def __call__(self, prices):
series = get_series(prices)
return library.calc_rvalue(series, self.period)


class RSI(Indicator):
"""Relative Strengh Index"""

Expand Down Expand Up @@ -180,7 +191,7 @@ def __call__(self, prices):


class STOCH(Indicator):
"""Stochastik Oscillator"""
"""Stochastic Oscillator"""

def __init__(self, period: int = 14, fastn: int = 3, slown: int = 3):
self.period = period
Expand Down
18 changes: 16 additions & 2 deletions src/mplchart/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def calc_bbands(prices, period: int = 20, nbdev: float = 2.0):


def calc_slope(series, period: int = 20):
"""calculates the slope (lnear regression) over a rolling window"""
"""calculates the slope (time linear regression) over a rolling window"""

xx = np.arange(period) - (period - 1) / 2.0

Expand All @@ -180,8 +180,22 @@ def func(xs):
return series.rolling(window=period).apply(func, raw=True)


def calc_rvalue(series, period: int = 20):
"""calculates the rvalue (time linear regression) over a rolling window"""

xx = np.arange(period) - (period - 1) / 2.0

def func(xs):
if np.any(np.isnan(xs)):
return np.nan

return np.corrcoef(xx, xs)[0, 1]

return series.rolling(window=period).apply(func, raw=True)


def calc_stoch(prices, period: int = 14, fastn: int = 3, slown: int = 3):
"""Stochastik Oscillator"""
"""Stochastic Oscillator"""

high = prices["high"].rolling(period).max()
low = prices["low"].rolling(period).min()
Expand Down
2 changes: 2 additions & 0 deletions src/mplchart/primitives/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from .ohlc import OHLC
from .candlesticks import Candlesticks
from .peaks import Peaks
from .stripes import Stripes
from .lineplot import LinePlot
from .areaplot import AreaPlot
from .barplot import BarPlot



33 changes: 0 additions & 33 deletions src/mplchart/primitives/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,3 @@ def plot_handler(self, prices, chart, ax=None):

ax.add_collection(lc)


class Stripes(Marker):
"""Stripes Primitive"""

COLOR = "green"
ALPHA = 0.1

def plot_handler(self, prices, chart, ax=None):
if ax is None:
ax = chart.root_axes()

data = self.process(prices)
data = chart.extract_df(data)
flag = data.flag

mask = flag.diff().fillna(0).ne(0)

color = self.COLOR
alpha = self.ALPHA

xv = data.index[mask]
sv = data.flag[mask]
x = s = px = None

for x, s in zip(xv, sv):
if s > 0 and px is None:
px = x
if s <= 0 and px is not None:
ax.axvspan(px, x, color=color, alpha=alpha)
px = None

if s <= 0 and px is not None:
ax.axvspan(px, x, color=color, alpha=alpha)
47 changes: 47 additions & 0 deletions src/mplchart/primitives/stripes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Marker primitives (experimental)"""

import numpy as np

from ..model import Primitive



class Stripes(Primitive):
"""Stripes Primitive"""

indicator = None

def __init__(self, expr: str = None, *, color: str = None, alpha: float = None):
self.expr = expr
self.color = color
self.alpha = alpha

def __ror__(self, indicator):
if not callable(indicator):
raise ValueError(f"{indicator!r} not callable!")

return self.clone(indicator=indicator)

def plot_handler(self, prices, chart, ax=None):
if ax is None:
ax = chart.root_axes()

result = chart.calc_result(prices, self.indicator)
result = chart.extract_df(result)

if not len(result):
return

if self.expr:
result = result.eval(self.expr)

flag = np.clip(np.sign(result), 0.0, 1.0).ffill()
csum = flag.diff().fillna(0).ne(0).cumsum()
aggs = flag[flag >0].index.to_series().groupby(csum).agg(['first', 'last'])

color = self.color
alpha = self.alpha

for x1, x2 in aggs.itertuples(index=False, name=None):
ax.axvspan(x1, x2, color=color, alpha=alpha)

1 change: 1 addition & 0 deletions src/mplchart/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def series_xy(data, item=None, *, dropna=False):


def series_data(data, item: str = None, *, default_item: str = None, strict: bool = False):
"""extract series data depending on data type and parameters"""
if isinstance(data, pd.DataFrame):
if item is not None:
return data[item]
Expand Down

0 comments on commit 3bdd0e7

Please sign in to comment.