1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-15 08:46:56 +08:00

fix ops & EMA support alpha

This commit is contained in:
Dong Zhou
2020-10-30 11:02:32 +08:00
committed by you-n-g
parent da9d1c8ac6
commit 72b5d9abfa
2 changed files with 21 additions and 8 deletions

View File

@@ -117,7 +117,7 @@ cdef class Rsquare(Expanding):
self.na_count += 1 self.na_count += 1
else: else:
self.x_sum += size self.x_sum += size
self.x2_sum += size self.x2_sum += size * size
self.y_sum += val self.y_sum += val
self.y2_sum += val * val self.y2_sum += val * val
self.xy_sum += size * val self.xy_sum += size * val

View File

@@ -8,6 +8,8 @@ from __future__ import print_function
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from scipy.stats import percentileofscore
from .base import Expression, ExpressionOps from .base import Expression, ExpressionOps
from ..log import get_module_logger from ..log import get_module_logger
@@ -687,6 +689,8 @@ class Rolling(ExpressionOps):
# isnull = series.isnull() # NOTE: isnull = NaN, inf is not null # isnull = series.isnull() # NOTE: isnull = NaN, inf is not null
if self.N == 0: if self.N == 0:
series = getattr(series.expanding(min_periods=1), self.func)() series = getattr(series.expanding(min_periods=1), self.func)()
elif 0 < self.N < 1:
series = series.ewm(alpha=self.N, min_periods=1).mean()
else: else:
series = getattr(series.rolling(self.N, min_periods=1), self.func)() series = getattr(series.rolling(self.N, min_periods=1), self.func)()
# series.iloc[:self.N-1] = np.nan # series.iloc[:self.N-1] = np.nan
@@ -696,6 +700,8 @@ class Rolling(ExpressionOps):
def get_longest_back_rolling(self): def get_longest_back_rolling(self):
if self.N == 0: if self.N == 0:
return np.inf return np.inf
if 0 < self.N < 1:
return int(np.log(1e-6) / np.log(1 - self.N)) # (1 - N)**window == 1e-6
return self.feature.get_longest_back_rolling() + self.N - 1 return self.feature.get_longest_back_rolling() + self.N - 1
def get_extended_window_size(self): def get_extended_window_size(self):
@@ -704,6 +710,11 @@ class Rolling(ExpressionOps):
# remove such support for N == 0? # remove such support for N == 0?
get_module_logger(self.__class__.__name__).warning("The Rolling(ATTR, 0) will not be accurately calculated") get_module_logger(self.__class__.__name__).warning("The Rolling(ATTR, 0) will not be accurately calculated")
return self.feature.get_extended_window_size() return self.feature.get_extended_window_size()
elif 0 < self.N < 1:
lft_etd, rght_etd = self.feature.get_extended_window_size()
size = int(np.log(1e-6) / np.log(1 - self.N))
lft_etd = max(lft_etd + size - 1, lft_etd)
return lft_etd, rght_etd
else: else:
lft_etd, rght_etd = self.feature.get_extended_window_size() lft_etd, rght_etd = self.feature.get_extended_window_size()
lft_etd = max(lft_etd + self.N - 1, lft_etd) lft_etd = max(lft_etd + self.N - 1, lft_etd)
@@ -1087,7 +1098,7 @@ class Rank(Rolling):
x1 = x[~np.isnan(x)] x1 = x[~np.isnan(x)]
if x1.shape[0] == 0: if x1.shape[0] == 0:
return np.nan return np.nan
return (x1.argsort()[-1] + 1) / len(x1) return percentileofscore(x1, x1[-1]) / len(x1)
if self.N == 0: if self.N == 0:
series = series.expanding(min_periods=1).apply(rank, raw=True) series = series.expanding(min_periods=1).apply(rank, raw=True)
@@ -1273,7 +1284,7 @@ class EMA(Rolling):
---------- ----------
feature : Expression feature : Expression
feature instance feature instance
N : int N : int, float
rolling window size rolling window size
Returns Returns
@@ -1296,6 +1307,8 @@ class EMA(Rolling):
if self.N == 0: if self.N == 0:
series = series.expanding(min_periods=1).apply(exp_weighted_mean, raw=True) series = series.expanding(min_periods=1).apply(exp_weighted_mean, raw=True)
elif 0 < self.N < 1:
series = series.ewm(alpha=self.N, min_periods=1).mean()
else: else:
series = series.ewm(span=self.N, min_periods=1).mean() series = series.ewm(span=self.N, min_periods=1).mean()
return series return series