mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-13 15:56:57 +08:00
Add a example to collecting all the decisions
This commit is contained in:
@@ -9,11 +9,11 @@ from .account import Account
|
||||
if TYPE_CHECKING:
|
||||
from ..strategy.base import BaseStrategy
|
||||
from .executor import BaseExecutor
|
||||
from .order import BaseTradeDecision
|
||||
from .position import Position
|
||||
from .exchange import Exchange
|
||||
from .backtest import backtest_loop
|
||||
from .backtest import collect_data_loop
|
||||
from .order import Order
|
||||
from .utils import CommonInfrastructure, LevelInfrastructure, TradeCalendarManager
|
||||
from ..utils import init_instance_by_config
|
||||
from ..log import get_module_logger
|
||||
@@ -228,10 +228,13 @@ def backtest(
|
||||
|
||||
Returns
|
||||
-------
|
||||
report_dict: Report
|
||||
report: Report
|
||||
it records the trading report information
|
||||
indicator_dict: Indicator
|
||||
It is organized in a dict format
|
||||
indicator: Indicator
|
||||
it computes the trading indicator
|
||||
It is organized in a dict format
|
||||
|
||||
"""
|
||||
trade_strategy, trade_executor = get_strategy_executor(
|
||||
start_time,
|
||||
@@ -243,9 +246,9 @@ def backtest(
|
||||
exchange_kwargs,
|
||||
pos_type=pos_type,
|
||||
)
|
||||
report_dict, indicator_dict = backtest_loop(start_time, end_time, trade_strategy, trade_executor)
|
||||
report, indicator = backtest_loop(start_time, end_time, trade_strategy, trade_executor)
|
||||
|
||||
return report_dict, indicator_dict
|
||||
return report, indicator
|
||||
|
||||
|
||||
def collect_data(
|
||||
@@ -257,6 +260,7 @@ def collect_data(
|
||||
account=1e9,
|
||||
exchange_kwargs={},
|
||||
pos_type: str = "Position",
|
||||
return_value: dict = None,
|
||||
):
|
||||
"""initialize the strategy and executor, then collect the trade decision data for rl training
|
||||
|
||||
@@ -277,4 +281,41 @@ def collect_data(
|
||||
exchange_kwargs,
|
||||
pos_type=pos_type,
|
||||
)
|
||||
yield from collect_data_loop(start_time, end_time, trade_strategy, trade_executor)
|
||||
yield from collect_data_loop(start_time, end_time, trade_strategy, trade_executor, return_value=return_value)
|
||||
|
||||
|
||||
def format_decisions(
|
||||
decisions: List[BaseTradeDecision],
|
||||
) -> Tuple[str, List[Tuple[BaseTradeDecision, Union[Tuple, None]]]]:
|
||||
"""
|
||||
format the decisions collected by `qlib.backtest.collect_data`
|
||||
The decisions will be organized into a tree-like structure.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
decisions : List[BaseTradeDecision]
|
||||
decisions collected by `qlib.backtest.collect_data`
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tuple[str, List[Tuple[BaseTradeDecision, Union[Tuple, None]]]]:
|
||||
|
||||
reformat the list of decisions into a more user-friendly format
|
||||
<decisions> := Tuple[<freq>, List[Tuple[<decision>, <sub decisions>]]]
|
||||
- <sub decisions> := `<decisions> in lower level` | None
|
||||
- <freq> := "day" | "30min" | "1min" | ...
|
||||
- <decision> := <instance of BaseTradeDecision>
|
||||
"""
|
||||
if len(decisions) == 0:
|
||||
return None
|
||||
|
||||
cur_freq = decisions[0].strategy.trade_calendar.get_freq()
|
||||
|
||||
res = (cur_freq, [])
|
||||
last_dec_idx = 0
|
||||
for i, dec in enumerate(decisions[1:], 1):
|
||||
if dec.strategy.trade_calendar.get_freq() == cur_freq:
|
||||
res[1].append((decisions[last_dec_idx], format_decisions(decisions[last_dec_idx + 1 : i])))
|
||||
last_dec_idx = i
|
||||
res[1].append((decisions[last_dec_idx], format_decisions(decisions[last_dec_idx + 1 :])))
|
||||
return res
|
||||
|
||||
@@ -171,7 +171,7 @@ class BaseSingleMetric:
|
||||
|
||||
@property
|
||||
def empty(self) -> bool:
|
||||
"""If metric is empyt, return True."""
|
||||
"""If metric is empty, return True."""
|
||||
|
||||
raise NotImplementedError(f"Please implement the `empty` method")
|
||||
|
||||
@@ -357,17 +357,17 @@ class PandasSingleMetric:
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, (int, float)):
|
||||
return PandasSingleMetric(self.metric < other)
|
||||
return PandasSingleMetric(self.metric > other)
|
||||
elif isinstance(other, PandasSingleMetric):
|
||||
return PandasSingleMetric(self.metric < other.metric)
|
||||
return PandasSingleMetric(self.metric > other.metric)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, (int, float)):
|
||||
return PandasSingleMetric(self.metric > other)
|
||||
return PandasSingleMetric(self.metric < other)
|
||||
elif isinstance(other, PandasSingleMetric):
|
||||
return PandasSingleMetric(self.metric > other.metric)
|
||||
return PandasSingleMetric(self.metric < other.metric)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
@@ -8,17 +8,72 @@ class TestAutoData(unittest.TestCase):
|
||||
|
||||
_setup_kwargs = {}
|
||||
provider_uri = "~/.qlib/qlib_data/cn_data_simple" # target_dir
|
||||
provider_uri_1day = "~/.qlib/qlib_data/cn_data" # target_dir
|
||||
provider_uri_1min = "~/.qlib/qlib_data/cn_data_1min"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
def setUpClass(cls, enable_1d_type="simple", enable_1min=False) -> None:
|
||||
# use default data
|
||||
|
||||
if enable_1d_type == "simple":
|
||||
provider_uri_day = cls.provider_uri
|
||||
name_day = "qlib_data_simple"
|
||||
elif enable_1d_type == "full":
|
||||
provider_uri_day = cls.provider_uri_1day
|
||||
name_day = "qlib_data"
|
||||
else:
|
||||
raise NotImplementedError(f"This type of input is not supported")
|
||||
|
||||
GetData().qlib_data(
|
||||
name="qlib_data_simple",
|
||||
name=name_day,
|
||||
region=REG_CN,
|
||||
interval="1d",
|
||||
target_dir=cls.provider_uri,
|
||||
target_dir=provider_uri_day,
|
||||
delete_old=False,
|
||||
exists_skip=True,
|
||||
)
|
||||
init(provider_uri=cls.provider_uri, region=REG_CN, **cls._setup_kwargs)
|
||||
|
||||
if enable_1min:
|
||||
GetData().qlib_data(
|
||||
name="qlib_data",
|
||||
region=REG_CN,
|
||||
interval="1min",
|
||||
target_dir=cls.provider_uri_1min,
|
||||
delete_old=False,
|
||||
exists_skip=True,
|
||||
)
|
||||
|
||||
provider_uri_map = {"1min": cls.provider_uri_1min, "day": provider_uri_day}
|
||||
|
||||
client_config = {
|
||||
"calendar_provider": {
|
||||
"class": "LocalCalendarProvider",
|
||||
"module_path": "qlib.data.data",
|
||||
"kwargs": {
|
||||
"backend": {
|
||||
"class": "FileCalendarStorage",
|
||||
"module_path": "qlib.data.storage.file_storage",
|
||||
"kwargs": {"provider_uri_map": provider_uri_map},
|
||||
}
|
||||
},
|
||||
},
|
||||
"feature_provider": {
|
||||
"class": "LocalFeatureProvider",
|
||||
"module_path": "qlib.data.data",
|
||||
"kwargs": {
|
||||
"backend": {
|
||||
"class": "FileFeatureStorage",
|
||||
"module_path": "qlib.data.storage.file_storage",
|
||||
"kwargs": {"provider_uri_map": provider_uri_map},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
init(
|
||||
provider_uri=cls.provider_uri,
|
||||
region=REG_CN,
|
||||
expression_cache=None,
|
||||
dataset_cache=None,
|
||||
**client_config,
|
||||
**cls._setup_kwargs,
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ from qlib.utils import exists_qlib_data
|
||||
|
||||
|
||||
class GetData:
|
||||
DATASET_VERSION = "v1"
|
||||
DATASET_VERSION = "v2"
|
||||
REMOTE_URL = "http://fintech.msra.cn/stock_data/downloads"
|
||||
QLIB_DATA_NAME = "{dataset_name}_{region}_{interval}_{qlib_version}.zip"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user