mirror of
https://github.com/webclinic017/drift.git
synced 2026-08-22 23:38:08 +00:00
feat(Labeling): purge overlapping events, sort dataframe at loading time (#226)
* feat(Labeling): purge overlapping events, sort dataframe at loading time * fix(Linter): ran * refactor(Labeling): moved purge_overlapping_events one abstraction level higher * fix(Data): renamed class * fix(Data): corrected parameter name * fix(Config): parameters * fix(Data): fixed path * fix(Data): uncommented required code * feat(EventFilters): use vol based CUSUM * fix(Config): only retrain every 2000 samples * fix(Config): filter out even more events * fix(Inference): added remove_overlapping_events * refactor(Types): simplified type hierarchy
This commit is contained in:
@@ -7,12 +7,13 @@ from numba.typed import List
|
||||
|
||||
|
||||
class CUSUMVolatilityEventFilter(EventFilter):
|
||||
def __init__(self, vol_period: int):
|
||||
def __init__(self, vol_period: int, multiplier: float):
|
||||
self.vol_period = vol_period
|
||||
self.multiplier = multiplier
|
||||
|
||||
def get_event_start_times(self, returns: ReturnSeries) -> pd.DatetimeIndex:
|
||||
|
||||
rolling_vol = returns.rolling(self.vol_period).std().mean()
|
||||
rolling_vol = returns.rolling(self.vol_period).std() * self.multiplier
|
||||
|
||||
filtered_indices = []
|
||||
pos_threshold = 0
|
||||
|
||||
@@ -3,6 +3,6 @@ from .event_filters.cusum import CUSUMVolatilityEventFilter, CUSUMFixedEventFilt
|
||||
|
||||
eventfilters_map = dict(
|
||||
none=NoEventFilter(),
|
||||
cusum_vol=CUSUMVolatilityEventFilter(vol_period=20),
|
||||
cusum_fixed=CUSUMFixedEventFilter(threshold=70),
|
||||
cusum_vol=CUSUMVolatilityEventFilter(vol_period=100, multiplier=3.5),
|
||||
cusum_fixed=CUSUMFixedEventFilter(threshold=20),
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from data_loader.types import ReturnSeries, ForwardReturnSeries
|
||||
from data_loader.types import ReturnSeries
|
||||
from ..types import EventLabeller, EventsDataFrame
|
||||
import pandas as pd
|
||||
from .utils import create_forward_returns
|
||||
@@ -13,7 +13,7 @@ class FixedTimeHorionThreeClassBalancedEventLabeller(EventLabeller):
|
||||
|
||||
def label_events(
|
||||
self, event_start_times: pd.DatetimeIndex, returns: ReturnSeries
|
||||
) -> tuple[EventsDataFrame, ForwardReturnSeries]:
|
||||
) -> EventsDataFrame:
|
||||
|
||||
forward_returns = create_forward_returns(returns, self.time_horizon)
|
||||
cutoff_point = returns.index[-self.time_horizon]
|
||||
@@ -43,15 +43,12 @@ class FixedTimeHorionThreeClassBalancedEventLabeller(EventLabeller):
|
||||
return 1
|
||||
|
||||
labels = event_candidates.map(map_class_threeway)
|
||||
|
||||
return (
|
||||
pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(days=self.time_horizon),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
),
|
||||
forward_returns[event_start_times],
|
||||
events = pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(minutes=self.time_horizon * 5),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
)
|
||||
return events
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from ..types import EventLabeller, EventsDataFrame, ReturnSeries, ForwardReturnSeries
|
||||
from ..types import EventLabeller, EventsDataFrame, ReturnSeries
|
||||
import pandas as pd
|
||||
from .utils import create_forward_returns
|
||||
|
||||
@@ -12,7 +12,7 @@ class FixedTimeHorionThreeClassImbalancedEventLabeller(EventLabeller):
|
||||
|
||||
def label_events(
|
||||
self, event_start_times: pd.DatetimeIndex, returns: ReturnSeries
|
||||
) -> tuple[EventsDataFrame, ForwardReturnSeries]:
|
||||
) -> EventsDataFrame:
|
||||
|
||||
forward_returns = create_forward_returns(returns, self.time_horizon)
|
||||
cutoff_point = returns.index[-self.time_horizon]
|
||||
@@ -42,15 +42,12 @@ class FixedTimeHorionThreeClassImbalancedEventLabeller(EventLabeller):
|
||||
return 1
|
||||
|
||||
labels = event_candidates.map(map_class_threeway)
|
||||
|
||||
return (
|
||||
pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(days=self.time_horizon),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
),
|
||||
forward_returns[event_start_times],
|
||||
events = pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(minutes=self.time_horizon * 5),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
)
|
||||
return events
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from ..types import EventLabeller, EventsDataFrame, ReturnSeries, ForwardReturnSeries
|
||||
from ..types import EventLabeller, EventsDataFrame, ReturnSeries
|
||||
import pandas as pd
|
||||
from .utils import create_forward_returns
|
||||
|
||||
@@ -12,7 +12,7 @@ class FixedTimeHorionTwoClassEventLabeller(EventLabeller):
|
||||
|
||||
def label_events(
|
||||
self, event_start_times: pd.DatetimeIndex, returns: ReturnSeries
|
||||
) -> tuple[EventsDataFrame, ForwardReturnSeries]:
|
||||
) -> EventsDataFrame:
|
||||
|
||||
forward_returns = create_forward_returns(returns, self.time_horizon)
|
||||
cutoff_point = returns.index[-self.time_horizon]
|
||||
@@ -23,15 +23,12 @@ class FixedTimeHorionTwoClassEventLabeller(EventLabeller):
|
||||
return -1 if x <= 0.0 else 1
|
||||
|
||||
labels = event_candidates.map(get_class_binary)
|
||||
|
||||
return (
|
||||
pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(days=self.time_horizon),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
),
|
||||
forward_returns[event_start_times],
|
||||
events = pd.DataFrame(
|
||||
{
|
||||
"start": event_start_times,
|
||||
"end": event_start_times + pd.Timedelta(minutes=self.time_horizon * 5),
|
||||
"label": labels,
|
||||
"returns": forward_returns[event_start_times],
|
||||
}
|
||||
)
|
||||
return events
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pandas as pd
|
||||
from data_loader.types import ForwardReturnSeries
|
||||
from labeling.types import EventsDataFrame
|
||||
|
||||
|
||||
def create_forward_returns(series: pd.Series, period: int) -> ForwardReturnSeries:
|
||||
@@ -8,3 +9,16 @@ def create_forward_returns(series: pd.Series, period: int) -> ForwardReturnSerie
|
||||
|
||||
forward_returns = series.rolling(window=indexer).sum()
|
||||
return forward_returns
|
||||
|
||||
|
||||
def purge_overlapping_events(events: EventsDataFrame) -> EventsDataFrame:
|
||||
events = events.copy()
|
||||
indicies_to_remove = []
|
||||
last_event_end = events.iloc[0]["start"]
|
||||
for index, row in events.iterrows():
|
||||
if row["start"] < last_event_end:
|
||||
indicies_to_remove.append(index)
|
||||
else:
|
||||
last_event_end = row["end"]
|
||||
events.drop(indicies_to_remove, inplace=True)
|
||||
return events
|
||||
|
||||
+10
-1
@@ -1,5 +1,6 @@
|
||||
from .types import EventFilter, EventLabeller, EventsDataFrame
|
||||
from data_loader.types import ForwardReturnSeries, XDataFrame, ReturnSeries, ySeries
|
||||
from .labellers.utils import purge_overlapping_events
|
||||
|
||||
|
||||
def label_data(
|
||||
@@ -7,6 +8,7 @@ def label_data(
|
||||
event_labeller: EventLabeller,
|
||||
X: XDataFrame,
|
||||
returns: ReturnSeries,
|
||||
remove_overlapping_events: bool,
|
||||
) -> tuple[EventsDataFrame, XDataFrame, ySeries, ForwardReturnSeries]:
|
||||
|
||||
event_start_times = event_filter.get_event_start_times(returns)
|
||||
@@ -16,7 +18,14 @@ def label_data(
|
||||
"% of timestamps",
|
||||
)
|
||||
|
||||
events, forward_returns = event_labeller.label_events(event_start_times, returns)
|
||||
events = event_labeller.label_events(event_start_times, returns)
|
||||
if remove_overlapping_events:
|
||||
events = purge_overlapping_events(events)
|
||||
print(
|
||||
"| Purged ",
|
||||
(1 - (len(events) / len(event_start_times))) * 100,
|
||||
"% of overlapping events",
|
||||
)
|
||||
|
||||
X = X.filter(items=events.index, axis=0)
|
||||
y = events["label"]
|
||||
|
||||
+1
-1
@@ -25,5 +25,5 @@ class EventLabeller(ABC):
|
||||
@abstractmethod
|
||||
def label_events(
|
||||
self, event_start_times: pd.DatetimeIndex, returns: ReturnSeries
|
||||
) -> tuple[EventsDataFrame, ForwardReturnSeries]:
|
||||
) -> EventsDataFrame:
|
||||
raise NotImplementedError
|
||||
|
||||
Reference in New Issue
Block a user