Source code for tradeexecutor.analysis.regime
"""Market regime analysis helpers."""
import enum
from dataclasses import dataclass
from typing import Iterable
import pandas as pd
[docs]class Regime(enum.Enum):
"""Possible market regimes.
The content of signal for :py:func:`visualise_market_regime_filter`
"""
#: We are in a bull market (trends up)
bull = 1
#: We are in a bear market (trends down)
bear = -1
#: We are in a sideways market (no trends)
crab = 0
[docs]@dataclass(frozen=True, slots=True)
class RegimeRegion:
"""One regime colouring region for the charts."""
start: pd.Timestamp
end: pd.Timestamp
regime: Regime
[docs]def get_regime_signal_regions(signal: pd.Series) -> Iterable[RegimeRegion]:
"""Get regions of the regime signal.
Split the signal to continous blocks for coloring.
:return:
Iterable of market regimes for colouring
"""
# https://stackoverflow.com/a/69222703/315168
edges = signal.diff(periods=1)
# edge_mask = edges.loc[edges != 0]
current_signal = Regime(signal.iloc[0])
current_start = edges.index[0]
regime_change_timestamps = edges.index[edges != 0]
if len(regime_change_timestamps) > 0:
# Skip the start region
for idx in regime_change_timestamps[1:]:
yield RegimeRegion(
current_start,
idx,
current_signal
)
current_start = idx
current_signal = Regime(signal[idx])
# The closing region
yield RegimeRegion(
current_start,
signal.index[-1],
current_signal,
)