mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-07 21:11:50 +08:00
update
This commit is contained in:
@@ -157,7 +157,7 @@ class Expression(abc.ABC):
|
||||
|
||||
@abc.abstractmethod
|
||||
def _load_internal(self, instrument, start_index, end_index, freq):
|
||||
pass
|
||||
raise NotImplementedError("This function must be implemented in your newly defined feature")
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_longest_back_rolling(self):
|
||||
|
||||
@@ -117,17 +117,7 @@ class CalendarProvider(abc.ABC):
|
||||
if flag in H["c"]:
|
||||
_calendar, _calendar_index = H["c"][flag]
|
||||
else:
|
||||
_calendar = np.array(self._load_calendar(freq, future))
|
||||
_calendar_index = {x: i for i, x in enumerate(_calendar)} # for fast search
|
||||
H["c"][flag] = _calendar, _calendar_index
|
||||
return _calendar, _calendar_index
|
||||
|
||||
def get_calendar_day(self, freq="day", future=False):
|
||||
flag = f"{freq}_future_{future}_day"
|
||||
if flag in H["c"]:
|
||||
_calendar, _calendar_index = H["c"][flag]
|
||||
else:
|
||||
_calendar = np.array(list(map(lambda x: x.date(), self._load_calendar(freq, future))))
|
||||
_calendar = np.array(self.load_calendar(freq, future))
|
||||
_calendar_index = {x: i for i, x in enumerate(_calendar)} # for fast search
|
||||
H["c"][flag] = _calendar, _calendar_index
|
||||
return _calendar, _calendar_index
|
||||
@@ -514,7 +504,7 @@ class LocalCalendarProvider(CalendarProvider):
|
||||
"""Calendar file uri."""
|
||||
return os.path.join(C.get_data_path(), "calendars", "{}.txt")
|
||||
|
||||
def _load_calendar(self, freq, future):
|
||||
def load_calendar(self, freq, future):
|
||||
"""Load original calendar timestamp from file.
|
||||
|
||||
Parameters
|
||||
@@ -679,12 +669,11 @@ class LocalExpressionProvider(ExpressionProvider):
|
||||
# 1) The stock data is currently float. If there is other types of data, this part needs to be re-implemented.
|
||||
# 2) The the precision should be configurable
|
||||
try:
|
||||
if series.dtype == np.float64:
|
||||
series = series.astype(np.float32)
|
||||
elif series.dtype == np.bool:
|
||||
series = series.astype(np.int8)
|
||||
series = series.astype(np.float32)
|
||||
except ValueError:
|
||||
pass
|
||||
except TypeError:
|
||||
pass
|
||||
if not series.empty:
|
||||
series = series.loc[start_index:end_index]
|
||||
return series
|
||||
|
||||
@@ -88,15 +88,8 @@ class DatasetH(Dataset):
|
||||
super().__init__(handler, segments)
|
||||
|
||||
def init(self, **kwargs):
|
||||
|
||||
logger = get_module_logger("DatasetH")
|
||||
handler_init_kwargs = {}
|
||||
for arg_key, arg_value in kwargs.items():
|
||||
if arg_key in getfullargspec(self.handler.init).args:
|
||||
handler_init_kwargs[arg_key] = arg_value
|
||||
else:
|
||||
logger.info(f"init arguments[{arg_key}] is ignored.")
|
||||
self.handler.init(**handler_init_kwargs)
|
||||
"""Initialize the DatasetH, Only parameters belonging to handler.init will be passed in"""
|
||||
self.handler.init(**kwargs)
|
||||
|
||||
def setup_data(self, handler: Union[dict, DataHandler], segments: list):
|
||||
"""
|
||||
|
||||
@@ -428,13 +428,11 @@ class DataHandlerLP(DataHandler):
|
||||
# TODO: Be able to cache handler data. Save the memory for data processing
|
||||
|
||||
def _get_df_by_key(self, data_key: str = DK_I) -> pd.DataFrame:
|
||||
try:
|
||||
df = getattr(self, {self.DK_R: "_data", self.DK_I: "_infer", self.DK_L: "_learn"}[data_key])
|
||||
except AttributeError:
|
||||
print("please set drop_raw = False if you want to use raw data")
|
||||
raise
|
||||
except:
|
||||
raise
|
||||
if data_key == self.DK_R and self.drop_raw:
|
||||
raise AttributeError(
|
||||
"DataHandlerLP has not attribute _data, please set drop_raw = False if you want to use raw data"
|
||||
)
|
||||
df = getattr(self, {self.DK_R: "_data", self.DK_I: "_infer", self.DK_L: "_learn"}[data_key])
|
||||
return df
|
||||
|
||||
def fetch(
|
||||
|
||||
138
qlib/data/ops.py
138
qlib/data/ops.py
@@ -6,6 +6,7 @@ from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import abc
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
@@ -22,8 +23,6 @@ except ImportError:
|
||||
"#### Do not import qlib package in the repository directory in case of importing qlib from . without compiling #####"
|
||||
)
|
||||
raise
|
||||
except:
|
||||
raise
|
||||
|
||||
|
||||
np.seterr(invalid="ignore")
|
||||
@@ -34,12 +33,39 @@ np.seterr(invalid="ignore")
|
||||
class ElemOperator(ExpressionOps):
|
||||
"""Element-wise Operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
feature : Expression
|
||||
feature instance
|
||||
|
||||
Returns
|
||||
----------
|
||||
Expression
|
||||
feature operation output
|
||||
"""
|
||||
|
||||
def __init__(self, feature):
|
||||
self.feature = feature
|
||||
|
||||
def __str__(self):
|
||||
return "{}({})".format(type(self).__name__, self.feature)
|
||||
|
||||
def get_longest_back_rolling(self):
|
||||
return self.feature.get_longest_back_rolling()
|
||||
|
||||
def get_extended_window_size(self):
|
||||
return self.feature.get_extended_window_size()
|
||||
|
||||
|
||||
class NpElemOperator(ElemOperator):
|
||||
"""Numpy Element-wise Operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
feature : Expression
|
||||
feature instance
|
||||
func : str
|
||||
feature operation method
|
||||
numpy feature operation method
|
||||
|
||||
Returns
|
||||
----------
|
||||
@@ -50,22 +76,14 @@ class ElemOperator(ExpressionOps):
|
||||
def __init__(self, feature, func):
|
||||
self.feature = feature
|
||||
self.func = func
|
||||
|
||||
def __str__(self):
|
||||
return "{}({})".format(type(self).__name__, self.feature)
|
||||
super(NpElemOperator, self).__init__(feature)
|
||||
|
||||
def _load_internal(self, instrument, start_index, end_index, freq):
|
||||
series = self.feature.load(instrument, start_index, end_index, freq)
|
||||
return getattr(np, self.func)(series)
|
||||
|
||||
def get_longest_back_rolling(self):
|
||||
return self.feature.get_longest_back_rolling()
|
||||
|
||||
def get_extended_window_size(self):
|
||||
return self.feature.get_extended_window_size()
|
||||
|
||||
|
||||
class Abs(ElemOperator):
|
||||
class Abs(NpElemOperator):
|
||||
"""Feature Absolute Value
|
||||
|
||||
Parameters
|
||||
@@ -83,7 +101,7 @@ class Abs(ElemOperator):
|
||||
super(Abs, self).__init__(feature, "abs")
|
||||
|
||||
|
||||
class Sign(ElemOperator):
|
||||
class Sign(NpElemOperator):
|
||||
"""Feature Sign
|
||||
|
||||
Parameters
|
||||
@@ -110,7 +128,7 @@ class Sign(ElemOperator):
|
||||
return getattr(np, self.func)(series)
|
||||
|
||||
|
||||
class Log(ElemOperator):
|
||||
class Log(NpElemOperator):
|
||||
"""Feature Log
|
||||
|
||||
Parameters
|
||||
@@ -128,7 +146,7 @@ class Log(ElemOperator):
|
||||
super(Log, self).__init__(feature, "log")
|
||||
|
||||
|
||||
class Power(ElemOperator):
|
||||
class Power(NpElemOperator):
|
||||
"""Feature Power
|
||||
|
||||
Parameters
|
||||
@@ -154,7 +172,7 @@ class Power(ElemOperator):
|
||||
return getattr(np, self.func)(series, self.exponent)
|
||||
|
||||
|
||||
class Mask(ElemOperator):
|
||||
class Mask(NpElemOperator):
|
||||
"""Feature Mask
|
||||
|
||||
Parameters
|
||||
@@ -181,7 +199,7 @@ class Mask(ElemOperator):
|
||||
return self.feature.load(self.instrument, start_index, end_index, freq)
|
||||
|
||||
|
||||
class Not(ElemOperator):
|
||||
class Not(NpElemOperator):
|
||||
"""Not Operator
|
||||
|
||||
Parameters
|
||||
@@ -220,28 +238,13 @@ class PairOperator(ExpressionOps):
|
||||
two features' operation output
|
||||
"""
|
||||
|
||||
def __init__(self, feature_left, feature_right, func):
|
||||
def __init__(self, feature_left, feature_right):
|
||||
self.feature_left = feature_left
|
||||
self.feature_right = feature_right
|
||||
self.func = func
|
||||
|
||||
def __str__(self):
|
||||
return "{}({},{})".format(type(self).__name__, self.feature_left, self.feature_right)
|
||||
|
||||
def _load_internal(self, instrument, start_index, end_index, freq):
|
||||
assert any(
|
||||
[isinstance(self.feature_left, Expression), self.feature_right, Expression]
|
||||
), "at least one of two inputs is Expression instance"
|
||||
if isinstance(self.feature_left, Expression):
|
||||
series_left = self.feature_left.load(instrument, start_index, end_index, freq)
|
||||
else:
|
||||
series_left = self.feature_left # numeric value
|
||||
if isinstance(self.feature_right, Expression):
|
||||
series_right = self.feature_right.load(instrument, start_index, end_index, freq)
|
||||
else:
|
||||
series_right = self.feature_right
|
||||
return getattr(np, self.func)(series_left, series_right)
|
||||
|
||||
def get_longest_back_rolling(self):
|
||||
if isinstance(self.feature_left, Expression):
|
||||
left_br = self.feature_left.get_longest_back_rolling()
|
||||
@@ -267,7 +270,46 @@ class PairOperator(ExpressionOps):
|
||||
return max(ll, rl), max(lr, rr)
|
||||
|
||||
|
||||
class Add(PairOperator):
|
||||
class NpPairOperator(PairOperator):
|
||||
"""Numpy Pair-wise operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
feature_left : Expression
|
||||
feature instance or numeric value
|
||||
feature_right : Expression
|
||||
feature instance or numeric value
|
||||
func : str
|
||||
operator function
|
||||
|
||||
Returns
|
||||
----------
|
||||
Feature:
|
||||
two features' operation output
|
||||
"""
|
||||
|
||||
def __init__(self, feature_left, feature_right, func):
|
||||
self.feature_left = feature_left
|
||||
self.feature_right = feature_right
|
||||
self.func = func
|
||||
super(NpPairOperator, self).__init__(feature_left, feature_right)
|
||||
|
||||
def _load_internal(self, instrument, start_index, end_index, freq):
|
||||
assert any(
|
||||
[isinstance(self.feature_left, Expression), self.feature_right, Expression]
|
||||
), "at least one of two inputs is Expression instance"
|
||||
if isinstance(self.feature_left, Expression):
|
||||
series_left = self.feature_left.load(instrument, start_index, end_index, freq)
|
||||
else:
|
||||
series_left = self.feature_left # numeric value
|
||||
if isinstance(self.feature_right, Expression):
|
||||
series_right = self.feature_right.load(instrument, start_index, end_index, freq)
|
||||
else:
|
||||
series_right = self.feature_right
|
||||
return getattr(np, self.func)(series_left, series_right)
|
||||
|
||||
|
||||
class Add(NpPairOperator):
|
||||
"""Add Operator
|
||||
|
||||
Parameters
|
||||
@@ -287,7 +329,7 @@ class Add(PairOperator):
|
||||
super(Add, self).__init__(feature_left, feature_right, "add")
|
||||
|
||||
|
||||
class Sub(PairOperator):
|
||||
class Sub(NpPairOperator):
|
||||
"""Subtract Operator
|
||||
|
||||
Parameters
|
||||
@@ -307,7 +349,7 @@ class Sub(PairOperator):
|
||||
super(Sub, self).__init__(feature_left, feature_right, "subtract")
|
||||
|
||||
|
||||
class Mul(PairOperator):
|
||||
class Mul(NpPairOperator):
|
||||
"""Multiply Operator
|
||||
|
||||
Parameters
|
||||
@@ -327,7 +369,7 @@ class Mul(PairOperator):
|
||||
super(Mul, self).__init__(feature_left, feature_right, "multiply")
|
||||
|
||||
|
||||
class Div(PairOperator):
|
||||
class Div(NpPairOperator):
|
||||
"""Division Operator
|
||||
|
||||
Parameters
|
||||
@@ -347,7 +389,7 @@ class Div(PairOperator):
|
||||
super(Div, self).__init__(feature_left, feature_right, "divide")
|
||||
|
||||
|
||||
class Greater(PairOperator):
|
||||
class Greater(NpPairOperator):
|
||||
"""Greater Operator
|
||||
|
||||
Parameters
|
||||
@@ -367,7 +409,7 @@ class Greater(PairOperator):
|
||||
super(Greater, self).__init__(feature_left, feature_right, "maximum")
|
||||
|
||||
|
||||
class Less(PairOperator):
|
||||
class Less(NpPairOperator):
|
||||
"""Less Operator
|
||||
|
||||
Parameters
|
||||
@@ -387,7 +429,7 @@ class Less(PairOperator):
|
||||
super(Less, self).__init__(feature_left, feature_right, "minimum")
|
||||
|
||||
|
||||
class Gt(PairOperator):
|
||||
class Gt(NpPairOperator):
|
||||
"""Greater Than Operator
|
||||
|
||||
Parameters
|
||||
@@ -407,7 +449,7 @@ class Gt(PairOperator):
|
||||
super(Gt, self).__init__(feature_left, feature_right, "greater")
|
||||
|
||||
|
||||
class Ge(PairOperator):
|
||||
class Ge(NpPairOperator):
|
||||
"""Greater Equal Than Operator
|
||||
|
||||
Parameters
|
||||
@@ -427,7 +469,7 @@ class Ge(PairOperator):
|
||||
super(Ge, self).__init__(feature_left, feature_right, "greater_equal")
|
||||
|
||||
|
||||
class Lt(PairOperator):
|
||||
class Lt(NpPairOperator):
|
||||
"""Less Than Operator
|
||||
|
||||
Parameters
|
||||
@@ -447,7 +489,7 @@ class Lt(PairOperator):
|
||||
super(Lt, self).__init__(feature_left, feature_right, "less")
|
||||
|
||||
|
||||
class Le(PairOperator):
|
||||
class Le(NpPairOperator):
|
||||
"""Less Equal Than Operator
|
||||
|
||||
Parameters
|
||||
@@ -467,7 +509,7 @@ class Le(PairOperator):
|
||||
super(Le, self).__init__(feature_left, feature_right, "less_equal")
|
||||
|
||||
|
||||
class Eq(PairOperator):
|
||||
class Eq(NpPairOperator):
|
||||
"""Equal Operator
|
||||
|
||||
Parameters
|
||||
@@ -487,7 +529,7 @@ class Eq(PairOperator):
|
||||
super(Eq, self).__init__(feature_left, feature_right, "equal")
|
||||
|
||||
|
||||
class Ne(PairOperator):
|
||||
class Ne(NpPairOperator):
|
||||
"""Not Equal Operator
|
||||
|
||||
Parameters
|
||||
@@ -507,7 +549,7 @@ class Ne(PairOperator):
|
||||
super(Ne, self).__init__(feature_left, feature_right, "not_equal")
|
||||
|
||||
|
||||
class And(PairOperator):
|
||||
class And(NpPairOperator):
|
||||
"""And Operator
|
||||
|
||||
Parameters
|
||||
@@ -527,7 +569,7 @@ class And(PairOperator):
|
||||
super(And, self).__init__(feature_left, feature_right, "bitwise_and")
|
||||
|
||||
|
||||
class Or(PairOperator):
|
||||
class Or(NpPairOperator):
|
||||
"""Or Operator
|
||||
|
||||
Parameters
|
||||
|
||||
Reference in New Issue
Block a user