mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-09 14:00:55 +08:00
Merge branch 'main' into dnn_drop
This commit is contained in:
@@ -17,8 +17,8 @@ class Dataset(Serializable):
|
||||
init is designed to finish following steps:
|
||||
|
||||
- setup data
|
||||
- The data related attributes' names should start with '_' so that it will not be saved on disk when serializing
|
||||
|
||||
- The data related attributes' names should start with '_' so that it will not be saved on disk when serializing.
|
||||
|
||||
- initialize the state of the dataset(info to prepare the data)
|
||||
- The name of essential state for preparing data should not start with '_' so that it could be serialized on disk when serializing.
|
||||
|
||||
@@ -29,17 +29,17 @@ class Dataset(Serializable):
|
||||
|
||||
def setup_data(self, *args, **kwargs):
|
||||
"""
|
||||
setup the data
|
||||
Setup the data.
|
||||
|
||||
We split the setup_data function for following situation:
|
||||
|
||||
- User have a Dataset object with learned status on disk
|
||||
- User have a Dataset object with learned status on disk.
|
||||
|
||||
- User load the Dataset object from the disk(Note the init function is skiped)
|
||||
- User load the Dataset object from the disk(Note the init function is skiped).
|
||||
|
||||
- User call `setup_data` to load new data
|
||||
- User call `setup_data` to load new data.
|
||||
|
||||
- User prepare data for model based on previous status
|
||||
- User prepare data for model based on previous status.
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -66,9 +66,10 @@ class DatasetH(Dataset):
|
||||
|
||||
User should try to put the data preprocessing functions into handler.
|
||||
Only following data processing functions should be placed in Dataset:
|
||||
|
||||
- The processing is related to specific model.
|
||||
|
||||
- The processing is related to data split
|
||||
- The processing is related to data split.
|
||||
"""
|
||||
|
||||
def __init__(self, handler: Union[dict, DataHandler], segments: list):
|
||||
@@ -76,15 +77,15 @@ class DatasetH(Dataset):
|
||||
Parameters
|
||||
----------
|
||||
handler : Union[dict, DataHandler]
|
||||
handler will be passed into setup_data
|
||||
handler will be passed into setup_data.
|
||||
segments : list
|
||||
handler will be passed into setup_data
|
||||
handler will be passed into setup_data.
|
||||
"""
|
||||
super().__init__(handler, segments)
|
||||
|
||||
def setup_data(self, handler: Union[dict, DataHandler], segments: list):
|
||||
"""
|
||||
setup the underlying data
|
||||
Setup the underlying data.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -94,12 +95,13 @@ class DatasetH(Dataset):
|
||||
- insntance of `DataHandler`
|
||||
|
||||
- config of `DataHandler`. Please refer to `DataHandler`
|
||||
|
||||
segments : list
|
||||
Describe the options to segment the data.
|
||||
Here are some examples:
|
||||
|
||||
.. code-block::
|
||||
|
||||
|
||||
1) 'segments': {
|
||||
'train': ("2008-01-01", "2014-12-31"),
|
||||
'valid': ("2017-01-01", "2020-08-01",),
|
||||
@@ -121,7 +123,7 @@ class DatasetH(Dataset):
|
||||
**kwargs,
|
||||
) -> Union[List[pd.DataFrame], pd.DataFrame]:
|
||||
"""
|
||||
prepare the data for learning and inference
|
||||
Prepare the data for learning and inference.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -132,11 +134,12 @@ class DatasetH(Dataset):
|
||||
- 'train'
|
||||
|
||||
- ['train', 'valid']
|
||||
|
||||
col_set : str
|
||||
The col_set will be passed to self._handler when fetching data
|
||||
data_key: str
|
||||
The col_set will be passed to self._handler when fetching data.
|
||||
data_key : str
|
||||
The data to fetch: DK_*
|
||||
Default is DK_I, which indicate fetching data for **inference**
|
||||
Default is DK_I, which indicate fetching data for **inference**.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
@@ -29,7 +29,7 @@ class DataHandler(Serializable):
|
||||
"""
|
||||
The steps to using a handler
|
||||
1. initialized data handler (call by `init`).
|
||||
2. use the data
|
||||
2. use the data.
|
||||
|
||||
|
||||
The data handler try to maintain a handler with 2 level.
|
||||
@@ -65,17 +65,17 @@ class DataHandler(Serializable):
|
||||
Parameters
|
||||
----------
|
||||
instruments :
|
||||
The stock list to retrive
|
||||
The stock list to retrive.
|
||||
start_time :
|
||||
start_time of the original data
|
||||
start_time of the original data.
|
||||
end_time :
|
||||
end_time of the original data
|
||||
end_time of the original data.
|
||||
data_loader : Tuple[dict, str, DataLoader]
|
||||
data loader to load the data
|
||||
data loader to load the data.
|
||||
init_data :
|
||||
intialize the original data in the constructor
|
||||
intialize the original data in the constructor.
|
||||
fetch_orig : bool
|
||||
Return the original data instead of copy if possible
|
||||
Return the original data instead of copy if possible.
|
||||
"""
|
||||
# Set logger
|
||||
self.logger = get_module_logger("DataHandler")
|
||||
@@ -219,9 +219,9 @@ class DataHandler(Serializable):
|
||||
get a iterator of sliced data with given periods
|
||||
|
||||
Args:
|
||||
periods (int): number of periods
|
||||
min_periods (int): minimum periods for sliced dataframe
|
||||
kwargs (dict): will be passed to `self.fetch`
|
||||
periods (int): number of periods.
|
||||
min_periods (int): minimum periods for sliced dataframe.
|
||||
kwargs (dict): will be passed to `self.fetch`.
|
||||
"""
|
||||
trading_dates = self._data.index.unique(level="datetime")
|
||||
if min_periods is None:
|
||||
@@ -243,10 +243,10 @@ class DataHandlerLP(DataHandler):
|
||||
|
||||
# process type
|
||||
PTYPE_I = "independent"
|
||||
# - self._infer will processed by infer_processors
|
||||
# - self._infer will be processed by infer_processors
|
||||
# - self._learn will be processed by learn_processors
|
||||
PTYPE_A = "append"
|
||||
# - self._infer will processed by infer_processors
|
||||
# - self._infer will be processed by infer_processors
|
||||
# - self._learn will be processed by infer_processors + learn_processors
|
||||
# - (e.g. self._infer processed by learn_processors )
|
||||
|
||||
@@ -265,30 +265,40 @@ class DataHandlerLP(DataHandler):
|
||||
Parameters
|
||||
----------
|
||||
infer_processors : list
|
||||
list of <description info> of processors to generate data for inference
|
||||
example of <description info>:
|
||||
1) classname & kwargs:
|
||||
{
|
||||
"class": "MinMaxNorm",
|
||||
"kwargs": {
|
||||
"fit_start_time": "20080101",
|
||||
"fit_end_time": "20121231"
|
||||
- list of <description info> of processors to generate data for inference
|
||||
|
||||
- example of <description info>:
|
||||
|
||||
.. code-block::
|
||||
|
||||
1) classname & kwargs:
|
||||
{
|
||||
"class": "MinMaxNorm",
|
||||
"kwargs": {
|
||||
"fit_start_time": "20080101",
|
||||
"fit_end_time": "20121231"
|
||||
}
|
||||
}
|
||||
}
|
||||
2) Only classname:
|
||||
"DropnaFeature"
|
||||
3) object instance of Processor
|
||||
2) Only classname:
|
||||
"DropnaFeature"
|
||||
3) object instance of Processor
|
||||
|
||||
learn_processors : list
|
||||
similar to infer_processors, but for generating data for learning models
|
||||
|
||||
process_type: str
|
||||
PTYPE_I = 'independent'
|
||||
|
||||
- self._infer will processed by infer_processors
|
||||
|
||||
- self._learn will be processed by learn_processors
|
||||
|
||||
PTYPE_A = 'append'
|
||||
|
||||
- self._infer will processed by infer_processors
|
||||
|
||||
- self._learn will be processed by infer_processors + learn_processors
|
||||
|
||||
- (e.g. self._infer processed by learn_processors )
|
||||
"""
|
||||
|
||||
@@ -377,7 +387,7 @@ class DataHandlerLP(DataHandler):
|
||||
Parameters
|
||||
----------
|
||||
init_type : str
|
||||
The type `IT_*` listed above
|
||||
The type `IT_*` listed above.
|
||||
enable_cache : bool
|
||||
default value is false:
|
||||
|
||||
@@ -419,13 +429,13 @@ class DataHandlerLP(DataHandler):
|
||||
Parameters
|
||||
----------
|
||||
selector : Union[pd.Timestamp, slice, str]
|
||||
describe how to select data by index
|
||||
describe how to select data by index.
|
||||
level : Union[str, int]
|
||||
which index level to select the data
|
||||
which index level to select the data.
|
||||
col_set : str
|
||||
select a set of meaningful columns.(e.g. features, columns)
|
||||
data_key: str
|
||||
The data to fetch: DK_*
|
||||
select a set of meaningful columns.(e.g. features, columns).
|
||||
data_key : str
|
||||
the data to fetch: DK_*.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -443,9 +453,9 @@ class DataHandlerLP(DataHandler):
|
||||
Parameters
|
||||
----------
|
||||
col_set : str
|
||||
select a set of meaningful columns.(e.g. features, columns)
|
||||
data_key: str
|
||||
The data to fetch: DK_*
|
||||
select a set of meaningful columns.(e.g. features, columns).
|
||||
data_key : str
|
||||
the data to fetch: DK_*.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
@@ -21,27 +21,11 @@ class DataLoader(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def load(self, instruments, start_time=None, end_time=None) -> pd.DataFrame:
|
||||
"""
|
||||
load the data as pd.DataFrame
|
||||
load the data as pd.DataFrame.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
self : [TODO:type]
|
||||
[TODO:description]
|
||||
instruments : [TODO:type]
|
||||
[TODO:description]
|
||||
start_time : [TODO:type]
|
||||
[TODO:description]
|
||||
end_time : [TODO:type]
|
||||
[TODO:description]
|
||||
Example of the data (The multi-index of the columns is optional.):
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame:
|
||||
data load from the under layer source
|
||||
|
||||
Example of the data (The multi-index of the columns is optional.):
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: python
|
||||
|
||||
feature label
|
||||
$close $volume Ref($close, 1) Mean($close, 3) $high-$low LABEL0
|
||||
@@ -49,6 +33,21 @@ class DataLoader(abc.ABC):
|
||||
2010-01-04 SH600000 81.807068 17145150.0 83.737389 83.016739 2.741058 0.0032
|
||||
SH600004 13.313329 11800983.0 13.313329 13.317701 0.183632 0.0042
|
||||
SH600005 37.796539 12231662.0 38.258602 37.919757 0.970325 0.0289
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instruments : str or dict
|
||||
it can either be the market name or the config file of instruments generated by InstrumentProvider.
|
||||
start_time : str
|
||||
start of the time range.
|
||||
end_time : str
|
||||
end of the time range.
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame:
|
||||
data load from the under layer source
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -67,7 +66,7 @@ class DLWParser(DataLoader):
|
||||
config : Tuple[list, tuple, dict]
|
||||
Config will be used to describe the fields and column names
|
||||
|
||||
.. code-block:: YAML
|
||||
.. code-block::
|
||||
|
||||
<config> := {
|
||||
"group_name1": <fields_info1>
|
||||
@@ -102,16 +101,16 @@ class DLWParser(DataLoader):
|
||||
Parameters
|
||||
----------
|
||||
instruments :
|
||||
the instruments
|
||||
the instruments.
|
||||
exprs : list
|
||||
The expressions to describe the content of the data
|
||||
the expressions to describe the content of the data.
|
||||
names : list
|
||||
The name of the data
|
||||
the name of the data.
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame:
|
||||
the queried dataframe
|
||||
the queried dataframe.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ def get_group_columns(df: pd.DataFrame, group: str):
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
with multi of columns
|
||||
with multi of columns.
|
||||
group : str
|
||||
the name of the feature group, i.e. the first level value of the group index.
|
||||
"""
|
||||
@@ -56,7 +56,7 @@ class Processor(Serializable):
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
The raw_df of handler or result from previous processor
|
||||
The raw_df of handler or result from previous processor.
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -68,7 +68,7 @@ class Processor(Serializable):
|
||||
Returns
|
||||
-------
|
||||
bool:
|
||||
if it is usable for infenrece
|
||||
if it is usable for infenrece.
|
||||
"""
|
||||
return True
|
||||
|
||||
@@ -176,7 +176,9 @@ class MinMaxNorm(Processor):
|
||||
return df
|
||||
|
||||
|
||||
class ZscoreNorm(Processor):
|
||||
class ZScoreNorm(Processor):
|
||||
"""ZScore Normalization"""
|
||||
|
||||
def __init__(self, fit_start_time, fit_end_time, fields_group=None):
|
||||
self.fit_start_time = fit_start_time
|
||||
self.fit_end_time = fit_end_time
|
||||
@@ -203,6 +205,42 @@ class ZscoreNorm(Processor):
|
||||
return df
|
||||
|
||||
|
||||
class RobustZScoreNorm(Processor):
|
||||
"""Robust ZScore Normalization
|
||||
|
||||
Use robust statistics for Z-Score normalization:
|
||||
mean(x) = median(x)
|
||||
std(x) = MAD(x) * 1.4826
|
||||
|
||||
Reference:
|
||||
https://en.wikipedia.org/wiki/Median_absolute_deviation.
|
||||
"""
|
||||
|
||||
def __init__(self, fit_start_time, fit_end_time, fields_group=None, clip_outlier=True):
|
||||
self.fit_start_time = fit_start_time
|
||||
self.fit_end_time = fit_end_time
|
||||
self.fields_group = fields_group
|
||||
self.clip_outlier = clip_outlier
|
||||
|
||||
def fit(self, df):
|
||||
df = fetch_df_by_index(df, slice(self.fit_start_time, self.fit_end_time), level="datetime")
|
||||
self.cols = get_group_columns(df, self.fields_group)
|
||||
X = df[self.cols].values
|
||||
self.mean_train = np.nanmedian(X, axis=0)
|
||||
self.std_train = np.nanmedian(np.abs(X - self.mean_train), axis=0)
|
||||
self.std_train += EPS
|
||||
self.std_train *= 1.4826
|
||||
|
||||
def __call__(self, df):
|
||||
X = df[self.cols]
|
||||
X -= self.mean_train
|
||||
X /= self.std_train
|
||||
df[self.cols] = X
|
||||
if self.clip_outlier:
|
||||
df.clip(-3, 3, inplace=True)
|
||||
return df
|
||||
|
||||
|
||||
class CSZScoreNorm(Processor):
|
||||
"""Cross Sectional ZScore Normalization"""
|
||||
|
||||
|
||||
@@ -51,6 +51,9 @@ def fetch_df_by_index(
|
||||
-------
|
||||
Data of the given index.
|
||||
"""
|
||||
# level = None -> use selector directly
|
||||
if level == None:
|
||||
return df.loc(axis=0)[selector]
|
||||
# Try to get the right index
|
||||
idx_slc = (selector, slice(None, None))
|
||||
if get_level_index(df, level) == 1:
|
||||
|
||||
Reference in New Issue
Block a user