mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-17 17:34:35 +08:00
Remove arctic from Qlib core to Contrib (#865)
* Remove arctic from Qlib core to Contrib * fix empty df bug
This commit is contained in:
@@ -17,6 +17,7 @@ Current version of script with default value tries to connect localhost **via de
|
|||||||
Run following command to install necessary libraries
|
Run following command to install necessary libraries
|
||||||
```
|
```
|
||||||
pip install pytest
|
pip install pytest
|
||||||
|
pip install arctic # NOTE: pip may fail to resolve the right package dependency !!! Please make sure the dependency are satisfied.
|
||||||
```
|
```
|
||||||
|
|
||||||
# Importing example data
|
# Importing example data
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ class TestClass(unittest.TestCase):
|
|||||||
mem_cache_type="sizeof",
|
mem_cache_type="sizeof",
|
||||||
kernels=1,
|
kernels=1,
|
||||||
expression_provider={"class": "LocalExpressionProvider", "kwargs": {"time2idx": False}},
|
expression_provider={"class": "LocalExpressionProvider", "kwargs": {"time2idx": False}},
|
||||||
feature_provider={"class": "ArcticFeatureProvider", "kwargs": {"uri": "127.0.0.1"}},
|
feature_provider={
|
||||||
|
"class": "ArcticFeatureProvider",
|
||||||
|
"module_path": "qlib.contrib.data.data",
|
||||||
|
"kwargs": {"uri": "127.0.0.1"},
|
||||||
|
},
|
||||||
dataset_provider={
|
dataset_provider={
|
||||||
"class": "LocalDatasetProvider",
|
"class": "LocalDatasetProvider",
|
||||||
"kwargs": {
|
"kwargs": {
|
||||||
|
|||||||
55
qlib/contrib/data/data.py
Normal file
55
qlib/contrib/data/data.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# Licensed under the MIT License.
|
||||||
|
|
||||||
|
# We remove arctic from core framework of Qlib to contrib due to
|
||||||
|
# - Arctic has very strict limitation on pandas and numpy version
|
||||||
|
# - https://github.com/man-group/arctic/pull/908
|
||||||
|
# - pip fail to computing the right version number!!!!
|
||||||
|
# - Maybe we can solve this problem by poetry
|
||||||
|
|
||||||
|
# FIXME: So if you want to use arctic-based provider, please install arctic manually
|
||||||
|
# `pip install arctic` may not be enough.
|
||||||
|
from arctic import Arctic
|
||||||
|
import pandas as pd
|
||||||
|
import pymongo
|
||||||
|
|
||||||
|
from qlib.data.data import FeatureProvider
|
||||||
|
|
||||||
|
|
||||||
|
class ArcticFeatureProvider(FeatureProvider):
|
||||||
|
def __init__(
|
||||||
|
self, uri="127.0.0.1", retry_time=0, market_transaction_time_list=[("09:15", "11:30"), ("13:00", "15:00")]
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
self.uri = uri
|
||||||
|
# TODO:
|
||||||
|
# retry connecting if error occurs
|
||||||
|
# does it real matters?
|
||||||
|
self.retry_time = retry_time
|
||||||
|
# NOTE: this is especially important for TResample operator
|
||||||
|
self.market_transaction_time_list = market_transaction_time_list
|
||||||
|
|
||||||
|
def feature(self, instrument, field, start_index, end_index, freq):
|
||||||
|
field = str(field)[1:]
|
||||||
|
with pymongo.MongoClient(self.uri) as client:
|
||||||
|
# TODO: this will result in frequently connecting the server and performance issue
|
||||||
|
arctic = Arctic(client)
|
||||||
|
|
||||||
|
if freq not in arctic.list_libraries():
|
||||||
|
raise ValueError("lib {} not in arctic".format(freq))
|
||||||
|
|
||||||
|
if instrument not in arctic[freq].list_symbols():
|
||||||
|
# instruments does not exist
|
||||||
|
return pd.Series()
|
||||||
|
else:
|
||||||
|
df = arctic[freq].read(instrument, columns=[field], chunk_range=(start_index, end_index))
|
||||||
|
s = df[field]
|
||||||
|
|
||||||
|
if not s.empty:
|
||||||
|
s = pd.concat(
|
||||||
|
[
|
||||||
|
s.between_time(time_tuple[0], time_tuple[1])
|
||||||
|
for time_tuple in self.market_transaction_time_list
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return s
|
||||||
@@ -15,7 +15,6 @@ from .data import (
|
|||||||
LocalCalendarProvider,
|
LocalCalendarProvider,
|
||||||
LocalInstrumentProvider,
|
LocalInstrumentProvider,
|
||||||
LocalFeatureProvider,
|
LocalFeatureProvider,
|
||||||
ArcticFeatureProvider,
|
|
||||||
LocalExpressionProvider,
|
LocalExpressionProvider,
|
||||||
LocalDatasetProvider,
|
LocalDatasetProvider,
|
||||||
ClientCalendarProvider,
|
ClientCalendarProvider,
|
||||||
|
|||||||
@@ -17,11 +17,9 @@ import pandas as pd
|
|||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from typing import Iterable, Union
|
from typing import Iterable, Union
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
from arctic import Arctic
|
|
||||||
|
|
||||||
# For supporting multiprocessing in outer code, joblib is used
|
# For supporting multiprocessing in outer code, joblib is used
|
||||||
from joblib import delayed
|
from joblib import delayed
|
||||||
import pymongo
|
|
||||||
|
|
||||||
from .cache import H
|
from .cache import H
|
||||||
from ..config import C
|
from ..config import C
|
||||||
@@ -582,7 +580,7 @@ class DatasetProvider(abc.ABC):
|
|||||||
data.index = _calendar[data.index.values.astype(int)]
|
data.index = _calendar[data.index.values.astype(int)]
|
||||||
data.index.names = ["datetime"]
|
data.index.names = ["datetime"]
|
||||||
|
|
||||||
if spans is not None:
|
if not data.empty and spans is not None:
|
||||||
mask = np.zeros(len(data), dtype=bool)
|
mask = np.zeros(len(data), dtype=bool)
|
||||||
for begin, end in spans:
|
for begin, end in spans:
|
||||||
mask |= (data.index >= begin) & (data.index <= end)
|
mask |= (data.index >= begin) & (data.index <= end)
|
||||||
@@ -702,45 +700,6 @@ class LocalFeatureProvider(FeatureProvider, ProviderBackendMixin):
|
|||||||
return self.backend_obj(instrument=instrument, field=field, freq=freq)[start_index : end_index + 1]
|
return self.backend_obj(instrument=instrument, field=field, freq=freq)[start_index : end_index + 1]
|
||||||
|
|
||||||
|
|
||||||
class ArcticFeatureProvider(FeatureProvider):
|
|
||||||
def __init__(
|
|
||||||
self, uri="127.0.0.1", retry_time=0, market_transaction_time_list=[("09:15", "11:30"), ("13:00", "15:00")]
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.uri = uri
|
|
||||||
# TODO:
|
|
||||||
# retry connecting if error occurs
|
|
||||||
# does it real matters?
|
|
||||||
self.retry_time = retry_time
|
|
||||||
# NOTE: this is especially important for TResample operator
|
|
||||||
self.market_transaction_time_list = market_transaction_time_list
|
|
||||||
|
|
||||||
def feature(self, instrument, field, start_index, end_index, freq):
|
|
||||||
field = str(field)[1:]
|
|
||||||
with pymongo.MongoClient(self.uri) as client:
|
|
||||||
# TODO: this will result in frequently connecting the server and performance issue
|
|
||||||
arctic = Arctic(client)
|
|
||||||
|
|
||||||
if freq not in arctic.list_libraries():
|
|
||||||
raise ValueError("lib {} not in arctic".format(freq))
|
|
||||||
|
|
||||||
if instrument not in arctic[freq].list_symbols():
|
|
||||||
# instruments does not exist
|
|
||||||
return pd.Series()
|
|
||||||
else:
|
|
||||||
df = arctic[freq].read(instrument, columns=[field], chunk_range=(start_index, end_index))
|
|
||||||
s = df[field]
|
|
||||||
|
|
||||||
if not s.empty:
|
|
||||||
s = pd.concat(
|
|
||||||
[
|
|
||||||
s.between_time(time_tuple[0], time_tuple[1])
|
|
||||||
for time_tuple in self.market_transaction_time_list
|
|
||||||
]
|
|
||||||
)
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
class LocalExpressionProvider(ExpressionProvider):
|
class LocalExpressionProvider(ExpressionProvider):
|
||||||
"""Local expression data provider class
|
"""Local expression data provider class
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user