1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-22 03:37:34 +08:00

Compare commits

..

19 Commits

Author SHA1 Message Date
Linlang Lv (iSoftStone Information)
3ebcddf8be fix ci 2024-04-25 16:02:24 +08:00
Linlang Lv (iSoftStone Information)
f98370c878 fix ci 2024-04-25 15:51:07 +08:00
Linlang Lv (iSoftStone Information)
414fcb309e fix ci 2024-04-25 15:23:31 +08:00
Linlang Lv (iSoftStone Information)
4b613effef fix ci 2024-04-25 15:20:15 +08:00
Linlang Lv (iSoftStone Information)
a862c9a74c fix ci 2024-04-25 15:19:05 +08:00
Linlang Lv (iSoftStone Information)
9db3b06842 fix ci 2024-04-25 15:01:40 +08:00
Linlang Lv (iSoftStone Information)
8815b9f05a fix ci 2024-04-25 14:54:35 +08:00
Linlang Lv (iSoftStone Information)
0d9853e6d9 fix ci 2024-04-25 14:51:21 +08:00
Linlang Lv (iSoftStone Information)
62909afa54 remove upload test 2024-04-24 16:51:31 +08:00
Linlang Lv (iSoftStone Information)
bfc1869a7d add upload test 2024-04-19 16:13:28 +08:00
Linlang Lv (iSoftStone Information)
cf74248ac2 add upload test 2024-04-19 15:57:50 +08:00
Linlang Lv (iSoftStone Information)
304171264b add upload test 2024-04-19 15:38:12 +08:00
Linlang Lv (iSoftStone Information)
95aec64de1 add upload test 2024-04-19 14:30:23 +08:00
Linlang Lv (iSoftStone Information)
bcbb3ac680 add upload test 2024-04-18 17:53:11 +08:00
Linlang Lv (iSoftStone Information)
af1546ee1b add upload test 2024-04-18 17:20:43 +08:00
Linlang Lv (iSoftStone Information)
a054eb0ed3 add upload test 2024-04-18 17:10:54 +08:00
Linlang Lv (iSoftStone Information)
a0d80c00a7 add upload test 2024-04-18 17:02:53 +08:00
Linlang Lv (iSoftStone Information)
0aa6c55bef set up publish 2024-04-17 15:43:26 +08:00
Young
7217c6e748 Update version 2024-04-14 00:09:30 +08:00
17 changed files with 46 additions and 152 deletions

View File

@@ -58,6 +58,8 @@ jobs:
deploy_with_manylinux: deploy_with_manylinux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
id-token: write
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Build wheel on Linux - name: Build wheel on Linux

View File

@@ -6,14 +6,8 @@ on:
branches: branches:
- main - main
permissions:
contents: read
jobs: jobs:
update_release_draft: update_release_draft:
permissions:
contents: write
pull-requests: read
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# Drafts your next Release notes as Pull Requests are merged into "master" # Drafts your next Release notes as Pull Requests are merged into "master"

View File

@@ -13,9 +13,6 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
# Since macos-latest changed from 12.7.4 to 14.4.1,
# the minimum python version that matches a 14.4.1 version of macos is 3.10,
# so we limit the macos version to macos-12.
os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12] os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12]
# not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129 # not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129
python-version: [3.7, 3.8] python-version: [3.7, 3.8]

View File

@@ -14,9 +14,6 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
# Since macos-latest changed from 12.7.4 to 14.4.1,
# the minimum python version that matches a 14.4.1 version of macos is 3.10,
# so we limit the macos version to macos-12.
os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12] os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12]
# not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129 # not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129
python-version: [3.7, 3.8] python-version: [3.7, 3.8]

View File

@@ -14,9 +14,6 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
# Since macos-latest changed from 12.7.4 to 14.4.1,
# the minimum python version that matches a 14.4.1 version of macos is 3.10,
# so we limit the macos version to macos-12.
os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12] os: [windows-latest, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12]
# not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129 # not supporting 3.6 due to annotations is not supported https://stackoverflow.com/a/52890129
python-version: [3.7, 3.8] python-version: [3.7, 3.8]

View File

@@ -5,12 +5,6 @@
# Required # Required
version: 2 version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.7"
# Build documentation in the docs/ directory with Sphinx # Build documentation in the docs/ directory with Sphinx
sphinx: sphinx:
configuration: docs/conf.py configuration: docs/conf.py
@@ -20,6 +14,7 @@ formats: all
# Optionally set the version of Python and requirements required to build your docs # Optionally set the version of Python and requirements required to build your docs
python: python:
version: 3.7
install: install:
- requirements: docs/requirements.txt - requirements: docs/requirements.txt
- method: pip - method: pip

View File

@@ -175,20 +175,6 @@ Also, users can install the latest dev version ``Qlib`` by the source code accor
**Tips for Mac**: If you are using Mac with M1, you might encounter issues in building the wheel for LightGBM, which is due to missing dependencies from OpenMP. To solve the problem, install openmp first with ``brew install libomp`` and then run ``pip install .`` to build it successfully. **Tips for Mac**: If you are using Mac with M1, you might encounter issues in building the wheel for LightGBM, which is due to missing dependencies from OpenMP. To solve the problem, install openmp first with ``brew install libomp`` and then run ``pip install .`` to build it successfully.
## Data Preparation ## Data Preparation
❗ Due to more restrict data security policy. The offical dataset is disabled temporarily. You can try [this data source](https://github.com/chenditc/investment_data/releases) contributed by the community.
Here is an example to download the data updated on 20220720.
```bash
wget https://github.com/chenditc/investment_data/releases/download/20220720/qlib_bin.tar.gz
mkdir -p ~/.qlib/qlib_data/cn_data
tar -zxvf qlib_bin.tar.gz -C ~/.qlib/qlib_data/cn_data --strip-components=2
rm -f qlib_bin.tar.gz
```
The official dataset below will resume in short future.
----
Load and prepare data by running the following code: Load and prepare data by running the following code:
### Get with module ### Get with module

View File

@@ -5,4 +5,3 @@ scipy
scikit-learn scikit-learn
pandas pandas
tianshou tianshou
sphinx_rtd_theme

View File

@@ -16,7 +16,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 coverage gdown pip install pytest coverage
pip install arctic # NOTE: pip may fail to resolve the right package dependency !!! Please make sure the dependency are satisfied. pip install arctic # NOTE: pip may fail to resolve the right package dependency !!! Please make sure the dependency are satisfied.
``` ```
@@ -27,8 +27,7 @@ pip install arctic # NOTE: pip may fail to resolve the right package dependency
2. Please follow following steps to download example data 2. Please follow following steps to download example data
```bash ```bash
cd examples/orderbook_data/ cd examples/orderbook_data/
gdown https://drive.google.com/uc?id=15nZF7tFT_eKVZAcMFL1qPS4jGyJflH7e # Proxies may be necessary here. python ../../scripts/get_data.py download_data --target_dir . --file_name highfreq_orderbook_example_data.zip
python ../../scripts/get_data.py _unzip --file_path highfreq_orderbook_example_data.zip --target_dir .
``` ```
3. Please import the example data to your mongo db 3. Please import the example data to your mongo db

View File

@@ -2,7 +2,7 @@
# Licensed under the MIT License. # Licensed under the MIT License.
from pathlib import Path from pathlib import Path
__version__ = "0.9.5" __version__ = "0.9.4"
__version__bak = __version__ # This version is backup for QlibConfig.reset_qlib_version __version__bak = __version__ # This version is backup for QlibConfig.reset_qlib_version
import os import os
from typing import Union from typing import Union

View File

@@ -536,6 +536,7 @@ class DatasetProvider(abc.ABC):
""" """
if len(fields) == 0: if len(fields) == 0:
raise ValueError("fields cannot be empty") raise ValueError("fields cannot be empty")
fields = fields.copy()
column_names = [str(f) for f in fields] column_names = [str(f) for f in fields]
return column_names return column_names

View File

@@ -12,11 +12,15 @@ import datetime
from tqdm import tqdm from tqdm import tqdm
from pathlib import Path from pathlib import Path
from loguru import logger from loguru import logger
from cryptography.fernet import Fernet
from qlib.utils import exists_qlib_data from qlib.utils import exists_qlib_data
class GetData: class GetData:
REMOTE_URL = "https://github.com/SunsetWolf/qlib_dataset/releases/download" REMOTE_URL = "https://qlibpublic.blob.core.windows.net/data/default/stock_data"
# "?" is not included in the token.
TOKEN = b"gAAAAABkmDhojHc0VSCDdNK1MqmRzNLeDFXe5hy8obHpa6SDQh4de6nW5gtzuD-fa6O_WZb0yyqYOL7ndOfJX_751W3xN5YB4-n-P22jK-t6ucoZqhT70KPD0Lf0_P328QPJVZ1gDnjIdjhi2YLOcP4BFTHLNYO0mvzszR8TKm9iT5AKRvuysWnpi8bbYwGU9zAcJK3x9EPL43hOGtxliFHcPNGMBoJW4g_ercdhi0-Qgv5_JLsV-29_MV-_AhuaYvJuN2dEywBy"
KEY = "EYcA8cgorA8X9OhyMwVfuFxn_1W3jGk6jCbs3L2oPoA="
def __init__(self, delete_zip_file=False): def __init__(self, delete_zip_file=False):
""" """
@@ -29,45 +33,9 @@ class GetData:
self.delete_zip_file = delete_zip_file self.delete_zip_file = delete_zip_file
def merge_remote_url(self, file_name: str): def merge_remote_url(self, file_name: str):
""" fernet = Fernet(self.KEY)
Generate download links. token = fernet.decrypt(self.TOKEN).decode()
return f"{self.REMOTE_URL}/{file_name}?{token}"
Parameters
----------
file_name: str
The name of the file to be downloaded.
The file name can be accompanied by a version number, (e.g.: v2/qlib_data_simple_cn_1d_latest.zip),
if no version number is attached, it will be downloaded from v0 by default.
"""
return f"{self.REMOTE_URL}/{file_name}" if "/" in file_name else f"{self.REMOTE_URL}/v0/{file_name}"
def download(self, url: str, target_path: [Path, str]):
"""
Download a file from the specified url.
Parameters
----------
url: str
The url of the data.
target_path: str
The location where the data is saved, including the file name.
"""
file_name = str(target_path).rsplit("/", maxsplit=1)[-1]
resp = requests.get(url, stream=True, timeout=60)
resp.raise_for_status()
if resp.status_code != 200:
raise requests.exceptions.HTTPError()
chunk_size = 1024
logger.warning(
f"The data for the example is collected from Yahoo Finance. Please be aware that the quality of the data might not be perfect. (You can refer to the original data source: https://finance.yahoo.com/lookup.)"
)
logger.info(f"{os.path.basename(file_name)} downloading......")
with tqdm(total=int(resp.headers.get("Content-Length", 0))) as p_bar:
with target_path.open("wb") as fp:
for chunk in resp.iter_content(chunk_size=chunk_size):
fp.write(chunk)
p_bar.update(chunk_size)
def download_data(self, file_name: str, target_dir: [Path, str], delete_old: bool = True): def download_data(self, file_name: str, target_dir: [Path, str], delete_old: bool = True):
""" """
@@ -102,7 +70,21 @@ class GetData:
target_path = target_dir.joinpath(_target_file_name) target_path = target_dir.joinpath(_target_file_name)
url = self.merge_remote_url(file_name) url = self.merge_remote_url(file_name)
self.download(url=url, target_path=target_path) resp = requests.get(url, stream=True, timeout=60)
resp.raise_for_status()
if resp.status_code != 200:
raise requests.exceptions.HTTPError()
chunk_size = 1024
logger.warning(
f"The data for the example is collected from Yahoo Finance. Please be aware that the quality of the data might not be perfect. (You can refer to the original data source: https://finance.yahoo.com/lookup.)"
)
logger.info(f"{os.path.basename(file_name)} downloading......")
with tqdm(total=int(resp.headers.get("Content-Length", 0))) as p_bar:
with target_path.open("wb") as fp:
for chunk in resp.iter_content(chunk_size=chunk_size):
fp.write(chunk)
p_bar.update(chunk_size)
self._unzip(target_path, target_dir, delete_old) self._unzip(target_path, target_dir, delete_old)
if self.delete_zip_file: if self.delete_zip_file:
@@ -117,9 +99,7 @@ class GetData:
return status return status
@staticmethod @staticmethod
def _unzip(file_path: [Path, str], target_dir: [Path, str], delete_old: bool = True): def _unzip(file_path: Path, target_dir: Path, delete_old: bool = True):
file_path = Path(file_path)
target_dir = Path(target_dir)
if delete_old: if delete_old:
logger.warning( logger.warning(
f"will delete the old qlib data directory(features, instruments, calendars, features_cache, dataset_cache): {target_dir}" f"will delete the old qlib data directory(features, instruments, calendars, features_cache, dataset_cache): {target_dir}"

View File

@@ -25,12 +25,7 @@ import pandas as pd
from pathlib import Path from pathlib import Path
from typing import List, Union, Optional, Callable from typing import List, Union, Optional, Callable
from packaging import version from packaging import version
from .file import ( from .file import get_or_create_path, save_multiple_parts_file, unpack_archive_with_buffer, get_tmp_file_with_buffer
get_or_create_path,
save_multiple_parts_file,
unpack_archive_with_buffer,
get_tmp_file_with_buffer,
)
from ..config import C from ..config import C
from ..log import get_module_logger, set_log_with_config from ..log import get_module_logger, set_log_with_config
@@ -42,12 +37,7 @@ is_deprecated_lexsorted_pandas = version.parse(pd.__version__) > version.parse("
#################### Server #################### #################### Server ####################
def get_redis_connection(): def get_redis_connection():
"""get redis connection instance.""" """get redis connection instance."""
return redis.StrictRedis( return redis.StrictRedis(host=C.redis_host, port=C.redis_port, db=C.redis_task_db, password=C.redis_password)
host=C.redis_host,
port=C.redis_port,
db=C.redis_task_db,
password=C.redis_password,
)
#################### Data #################### #################### Data ####################
@@ -106,14 +96,7 @@ def get_period_offset(first_year, period, quarterly):
return offset return offset
def read_period_data( def read_period_data(index_path, data_path, period, cur_date_int: int, quarterly, last_period_index: int = None):
index_path,
data_path,
period,
cur_date_int: int,
quarterly,
last_period_index: int = None,
):
""" """
At `cur_date`(e.g. 20190102), read the information at `period`(e.g. 201803). At `cur_date`(e.g. 20190102), read the information at `period`(e.g. 201803).
Only the updating info before cur_date or at cur_date will be used. Only the updating info before cur_date or at cur_date will be used.
@@ -290,10 +273,7 @@ def parse_field(field):
# \uff09 -> ) # \uff09 -> )
chinese_punctuation_regex = r"\u3001\uff1a\uff08\uff09" chinese_punctuation_regex = r"\u3001\uff1a\uff08\uff09"
for pattern, new in [ for pattern, new in [
( (rf"\$\$([\w{chinese_punctuation_regex}]+)", r'PFeature("\1")'), # $$ must be before $
rf"\$\$([\w{chinese_punctuation_regex}]+)",
r'PFeature("\1")',
), # $$ must be before $
(rf"\$([\w{chinese_punctuation_regex}]+)", r'Feature("\1")'), (rf"\$([\w{chinese_punctuation_regex}]+)", r'Feature("\1")'),
(r"(\w+\s*)\(", r"Operators.\1("), (r"(\w+\s*)\(", r"Operators.\1("),
]: # Features # Operators ]: # Features # Operators
@@ -403,14 +383,7 @@ def get_date_range(trading_date, left_shift=0, right_shift=0, future=False):
return calendar return calendar
def get_date_by_shift( def get_date_by_shift(trading_date, shift, future=False, clip_shift=True, freq="day", align: Optional[str] = None):
trading_date,
shift,
future=False,
clip_shift=True,
freq="day",
align: Optional[str] = None,
):
"""get trading date with shift bias will cur_date """get trading date with shift bias will cur_date
e.g. : shift == 1, return next trading date e.g. : shift == 1, return next trading date
shift == -1, return previous trading date shift == -1, return previous trading date
@@ -596,38 +569,7 @@ def exists_qlib_data(qlib_dir):
# check instruments # check instruments
code_names = set(map(lambda x: fname_to_code(x.name.lower()), features_dir.iterdir())) code_names = set(map(lambda x: fname_to_code(x.name.lower()), features_dir.iterdir()))
_instrument = instruments_dir.joinpath("all.txt") _instrument = instruments_dir.joinpath("all.txt")
# Removed two possible ticker names "NA" and "NULL" from the default na_values list for column 0 miss_code = set(pd.read_csv(_instrument, sep="\t", header=None).loc[:, 0].apply(str.lower)) - set(code_names)
miss_code = set(
pd.read_csv(
_instrument,
sep="\t",
header=None,
keep_default_na=False,
na_values={
0: [
" ",
"#N/A",
"#N/A N/A",
"#NA",
"-1.#IND",
"-1.#QNAN",
"-NaN",
"-nan",
"1.#IND",
"1.#QNAN",
"<NA>",
"N/A",
"NaN",
"None",
"n/a",
"nan",
"null ",
]
},
)
.loc[:, 0]
.apply(str.lower)
) - set(code_names)
if miss_code and any(map(lambda x: "sht" not in x, miss_code)): if miss_code and any(map(lambda x: "sht" not in x, miss_code)):
return False return False

View File

@@ -396,7 +396,14 @@ class CSI500Index(CSIIndex):
today = pd.Timestamp.now() today = pd.Timestamp.now()
date_range = pd.DataFrame(pd.date_range(start="2007-01-15", end=today, freq="7D"))[0].dt.date date_range = pd.DataFrame(pd.date_range(start="2007-01-15", end=today, freq="7D"))[0].dt.date
ret_list = [] ret_list = []
col = ["date", "symbol", "code_name"]
for date in tqdm(date_range, desc="Download CSI500"): for date in tqdm(date_range, desc="Download CSI500"):
rs = bs.query_zz500_stocks(date=str(date))
zz500_stocks = []
while (rs.error_code == "0") & rs.next():
zz500_stocks.append(rs.get_row_data())
result = pd.DataFrame(zz500_stocks, columns=col)
result["symbol"] = result["symbol"].apply(lambda x: x.replace(".", "").upper())
result = self.get_data_from_baostock(date) result = self.get_data_from_baostock(date)
ret_list.append(result[["date", "symbol"]]) ret_list.append(result[["date", "symbol"]])
bs.logout() bs.logout()

View File

@@ -5,5 +5,3 @@ pandas
lxml lxml
loguru loguru
tqdm tqdm
yahooquery
openpyxl

View File

@@ -3,7 +3,7 @@
""" """
TODO: TODO:
- A more well-designed PIT database is required. - A more well-designed PIT database is required.
- separated insert, delete, update, query operations are required. - seperated insert, delete, update, query operations are required.
""" """
import shutil import shutil