From 136b7694a37198cb139a48c0f1cf060cab36057b Mon Sep 17 00:00:00 2001 From: "Linlang Lv (iSoftStone Information)" Date: Fri, 17 Apr 2026 12:08:47 +0800 Subject: [PATCH 1/4] fix: use baostock to fetch trading calendar instead of Eastmoney API --- scripts/data_collector/utils.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/scripts/data_collector/utils.py b/scripts/data_collector/utils.py index 2b75916989b..5353dfaba14 100644 --- a/scripts/data_collector/utils.py +++ b/scripts/data_collector/utils.py @@ -20,6 +20,7 @@ from functools import partial from concurrent.futures import ProcessPoolExecutor from bs4 import BeautifulSoup +import baostock as bs from qlib.utils.pickle_utils import restricted_pickle_load @@ -68,9 +69,16 @@ def get_calendar_list(bench_code="CSI300") -> List[pd.Timestamp]: logger.info(f"get calendar list: {bench_code}......") - def _get_calendar(url): - _value_list = requests.get(url, timeout=None).json()["data"]["klines"] - return sorted(map(lambda x: pd.Timestamp(x.split(",")[0]), _value_list)) + def _get_calendar(end_date): + bs.login() + rs = bs.query_trade_dates(start_date="2005-01-01", end_date=end_date) + data_list = [] + while (rs.error_code == '0') & rs.next(): + data_list.append(rs.get_row_data()) + bs.logout() + df = pd.DataFrame(data_list, columns=rs.fields) + trade_days = df[df['is_trading_day'] == '1']['calendar_date'] + return sorted(map(lambda x: pd.Timestamp(x), trade_days.to_list())) calendar = _CALENDAR_MAP.get(bench_code, None) if calendar is None: @@ -90,7 +98,8 @@ def _get_calendar(url): filtered_dates = dates[(dates >= "2000-01-04") & (dates <= pd.Timestamp.today().normalize())] calendar = filtered_dates.tolist() else: - calendar = _get_calendar(CALENDAR_BENCH_URL_MAP[bench_code]) + end_date = time.strftime("%Y-%m-%d", time.localtime()) + calendar = _get_calendar(end_date=end_date) _CALENDAR_MAP[bench_code] = calendar logger.info(f"end of get calendar list: {bench_code}.") return calendar From a8827ec839ec3400f6bb1fac2711f13ed3fb26a6 Mon Sep 17 00:00:00 2001 From: "Linlang Lv (iSoftStone Information)" Date: Fri, 17 Apr 2026 12:13:38 +0800 Subject: [PATCH 2/4] fix: lint error --- scripts/data_collector/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/data_collector/utils.py b/scripts/data_collector/utils.py index 5353dfaba14..e4c35d973af 100644 --- a/scripts/data_collector/utils.py +++ b/scripts/data_collector/utils.py @@ -73,11 +73,11 @@ def _get_calendar(end_date): bs.login() rs = bs.query_trade_dates(start_date="2005-01-01", end_date=end_date) data_list = [] - while (rs.error_code == '0') & rs.next(): + while (rs.error_code == "0") & rs.next(): data_list.append(rs.get_row_data()) bs.logout() df = pd.DataFrame(data_list, columns=rs.fields) - trade_days = df[df['is_trading_day'] == '1']['calendar_date'] + trade_days = df[df["is_trading_day"] == "1"]["calendar_date"] return sorted(map(lambda x: pd.Timestamp(x), trade_days.to_list())) calendar = _CALENDAR_MAP.get(bench_code, None) From a45ee54efc4b3c7d4c3a1e55a539d93690b1f405 Mon Sep 17 00:00:00 2001 From: "Linlang Lv (iSoftStone Information)" Date: Fri, 17 Apr 2026 12:19:49 +0800 Subject: [PATCH 3/4] fix: lint error --- scripts/data_collector/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/data_collector/utils.py b/scripts/data_collector/utils.py index e4c35d973af..b4e6708b1a6 100644 --- a/scripts/data_collector/utils.py +++ b/scripts/data_collector/utils.py @@ -78,7 +78,7 @@ def _get_calendar(end_date): bs.logout() df = pd.DataFrame(data_list, columns=rs.fields) trade_days = df[df["is_trading_day"] == "1"]["calendar_date"] - return sorted(map(lambda x: pd.Timestamp(x), trade_days.to_list())) + return sorted(map(pd.Timestamp, trade_days.to_list())) calendar = _CALENDAR_MAP.get(bench_code, None) if calendar is None: From ffe456d7afd9806695c1a06f80afa848c5818599 Mon Sep 17 00:00:00 2001 From: "Linlang Lv (iSoftStone Information)" Date: Fri, 17 Apr 2026 15:34:45 +0800 Subject: [PATCH 4/4] ci: enable concurrency to cancel in-progress runs for same workflow and ref --- .github/workflows/test_qlib_from_pip.yml | 4 ++++ .github/workflows/test_qlib_from_source.yml | 4 ++++ .github/workflows/test_qlib_from_source_slow.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/test_qlib_from_pip.yml b/.github/workflows/test_qlib_from_pip.yml index 4311e3239b8..6a3bfe674d7 100644 --- a/.github/workflows/test_qlib_from_pip.yml +++ b/.github/workflows/test_qlib_from_pip.yml @@ -1,5 +1,9 @@ name: Test qlib from pip +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + on: push: branches: [ main ] diff --git a/.github/workflows/test_qlib_from_source.yml b/.github/workflows/test_qlib_from_source.yml index edda1849f56..81f6926a81b 100644 --- a/.github/workflows/test_qlib_from_source.yml +++ b/.github/workflows/test_qlib_from_source.yml @@ -1,5 +1,9 @@ name: Test qlib from source +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + on: push: branches: [ main ] diff --git a/.github/workflows/test_qlib_from_source_slow.yml b/.github/workflows/test_qlib_from_source_slow.yml index 4d4f184c89f..79e2a1117e0 100644 --- a/.github/workflows/test_qlib_from_source_slow.yml +++ b/.github/workflows/test_qlib_from_source_slow.yml @@ -1,5 +1,9 @@ name: Test qlib from source slow +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + on: push: branches: [ main ]