mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-12 15:26:54 +08:00
fix: strategies for enhancing crawlers
This commit is contained in:
@@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import copy
|
import copy
|
||||||
|
import datetime
|
||||||
import importlib
|
import importlib
|
||||||
import time
|
import time
|
||||||
import bisect
|
import bisect
|
||||||
import pickle
|
import pickle
|
||||||
|
import random
|
||||||
import requests
|
import requests
|
||||||
import functools
|
import functools
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -23,7 +25,7 @@ from bs4 import BeautifulSoup
|
|||||||
|
|
||||||
HS_SYMBOLS_URL = "http://app.finance.ifeng.com/hq/list.php?type=stock_a&class={s_type}"
|
HS_SYMBOLS_URL = "http://app.finance.ifeng.com/hq/list.php?type=stock_a&class={s_type}"
|
||||||
|
|
||||||
CALENDAR_URL_BASE = "http://push2his.eastmoney.com/api/qt/stock/kline/get?secid={market}.{bench_code}&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58&klt=101&fqt=0&beg=19900101&end=20991231"
|
CALENDAR_URL_BASE = "http://push2his.eastmoney.com/api/qt/stock/kline/get?secid={market}.{bench_code}&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58&klt=101&fqt=0&beg={start}&end={end}"
|
||||||
SZSE_CALENDAR_URL = "http://www.szse.cn/api/report/exchange/onepersistenthour/monthList?month={month}&random={random}"
|
SZSE_CALENDAR_URL = "http://www.szse.cn/api/report/exchange/onepersistenthour/monthList?month={month}&random={random}"
|
||||||
|
|
||||||
CALENDAR_BENCH_URL_MAP = {
|
CALENDAR_BENCH_URL_MAP = {
|
||||||
@@ -38,6 +40,24 @@ CALENDAR_BENCH_URL_MAP = {
|
|||||||
"BR_ALL": "^BVSP",
|
"BR_ALL": "^BVSP",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHROME_UA_POOL = [
|
||||||
|
# Windows
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/120.0.0.0 Safari/537.36",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/121.0.6167.85 Safari/537.36",
|
||||||
|
# macOS
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/121.0.0.0 Safari/537.36",
|
||||||
|
# Linux
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/120.0.0.0 Safari/537.36",
|
||||||
|
]
|
||||||
|
|
||||||
_BENCH_CALENDAR_LIST = None
|
_BENCH_CALENDAR_LIST = None
|
||||||
_ALL_CALENDAR_LIST = None
|
_ALL_CALENDAR_LIST = None
|
||||||
_HS_SYMBOLS = None
|
_HS_SYMBOLS = None
|
||||||
@@ -51,6 +71,16 @@ _CALENDAR_MAP = {}
|
|||||||
MINIMUM_SYMBOLS_NUM = 3900
|
MINIMUM_SYMBOLS_NUM = 3900
|
||||||
|
|
||||||
|
|
||||||
|
def build_headers():
|
||||||
|
return {
|
||||||
|
"User-Agent": random.choice(CHROME_UA_POOL),
|
||||||
|
"Accept": "application/json,text/plain,*/*",
|
||||||
|
"Accept-Language": "zh-CN,zh;q=0.9",
|
||||||
|
"Referer": "https://quote.eastmoney.com/",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_calendar_list(bench_code="CSI300") -> List[pd.Timestamp]:
|
def get_calendar_list(bench_code="CSI300") -> List[pd.Timestamp]:
|
||||||
"""get SH/SZ history calendar list
|
"""get SH/SZ history calendar list
|
||||||
|
|
||||||
@@ -67,16 +97,58 @@ def get_calendar_list(bench_code="CSI300") -> List[pd.Timestamp]:
|
|||||||
logger.info(f"get calendar list: {bench_code}......")
|
logger.info(f"get calendar list: {bench_code}......")
|
||||||
|
|
||||||
def _get_calendar(url):
|
def _get_calendar(url):
|
||||||
_value_list = requests.get(url, timeout=None).json()["data"]["klines"]
|
session = requests.Session()
|
||||||
return sorted(map(lambda x: pd.Timestamp(x.split(",")[0]), _value_list))
|
session.headers.update(build_headers())
|
||||||
|
current_datetime = datetime.datetime.now()
|
||||||
|
cur_year = current_datetime.year
|
||||||
|
res_list = []
|
||||||
|
for per_year in range(2000, cur_year + 1):
|
||||||
|
start = f"{per_year}0101"
|
||||||
|
end = f"{per_year}1231"
|
||||||
|
formatted_url = url.format(start=start, end=end)
|
||||||
|
try:
|
||||||
|
resp = session.get(formatted_url, timeout=10)
|
||||||
|
resp.raise_for_status()
|
||||||
|
payload = resp.json()
|
||||||
|
data = payload.get("data")
|
||||||
|
if not data or "klines" not in data:
|
||||||
|
continue
|
||||||
|
|
||||||
|
klines = data["klines"]
|
||||||
|
res_list.extend(pd.Timestamp(x.split(",")[0]) for x in klines)
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
time.sleep(random.uniform(0.5, 1.2))
|
||||||
|
|
||||||
|
return sorted(set(res_list))
|
||||||
|
|
||||||
|
# _value_list = requests.get(url, timeout=None).json()["data"]["klines"]
|
||||||
|
# return sorted(map(lambda x: pd.Timestamp(x.split(",")[0]), _value_list))
|
||||||
|
|
||||||
calendar = _CALENDAR_MAP.get(bench_code, None)
|
calendar = _CALENDAR_MAP.get(bench_code, None)
|
||||||
if calendar is None:
|
if calendar is None:
|
||||||
if bench_code.startswith("US_") or bench_code.startswith("IN_") or bench_code.startswith("BR_"):
|
if (
|
||||||
|
bench_code.startswith("US_")
|
||||||
|
or bench_code.startswith("IN_")
|
||||||
|
or bench_code.startswith("BR_")
|
||||||
|
):
|
||||||
print(Ticker(CALENDAR_BENCH_URL_MAP[bench_code]))
|
print(Ticker(CALENDAR_BENCH_URL_MAP[bench_code]))
|
||||||
print(Ticker(CALENDAR_BENCH_URL_MAP[bench_code]).history(interval="1d", period="max"))
|
print(
|
||||||
df = Ticker(CALENDAR_BENCH_URL_MAP[bench_code]).history(interval="1d", period="max")
|
Ticker(CALENDAR_BENCH_URL_MAP[bench_code]).history(
|
||||||
calendar = df.index.get_level_values(level="date").map(pd.Timestamp).unique().tolist()
|
interval="1d", period="max"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
df = Ticker(CALENDAR_BENCH_URL_MAP[bench_code]).history(
|
||||||
|
interval="1d", period="max"
|
||||||
|
)
|
||||||
|
calendar = (
|
||||||
|
df.index.get_level_values(level="date")
|
||||||
|
.map(pd.Timestamp)
|
||||||
|
.unique()
|
||||||
|
.tolist()
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if bench_code.upper() == "ALL":
|
if bench_code.upper() == "ALL":
|
||||||
import akshare as ak # pylint: disable=C0415
|
import akshare as ak # pylint: disable=C0415
|
||||||
@@ -85,7 +157,10 @@ def get_calendar_list(bench_code="CSI300") -> List[pd.Timestamp]:
|
|||||||
trade_date_list = trade_date_df["trade_date"].tolist()
|
trade_date_list = trade_date_df["trade_date"].tolist()
|
||||||
trade_date_list = [pd.Timestamp(d) for d in trade_date_list]
|
trade_date_list = [pd.Timestamp(d) for d in trade_date_list]
|
||||||
dates = pd.DatetimeIndex(trade_date_list)
|
dates = pd.DatetimeIndex(trade_date_list)
|
||||||
filtered_dates = dates[(dates >= "2000-01-04") & (dates <= pd.Timestamp.today().normalize())]
|
filtered_dates = dates[
|
||||||
|
(dates >= "2000-01-04")
|
||||||
|
& (dates <= pd.Timestamp.today().normalize())
|
||||||
|
]
|
||||||
calendar = filtered_dates.tolist()
|
calendar = filtered_dates.tolist()
|
||||||
else:
|
else:
|
||||||
calendar = _get_calendar(CALENDAR_BENCH_URL_MAP[bench_code])
|
calendar = _get_calendar(CALENDAR_BENCH_URL_MAP[bench_code])
|
||||||
@@ -150,7 +225,9 @@ def get_calendar_list_by_ratio(
|
|||||||
p_bar.update()
|
p_bar.update()
|
||||||
|
|
||||||
logger.info(f"count how many funds have founded in this day......")
|
logger.info(f"count how many funds have founded in this day......")
|
||||||
_dict_count_founding = {date: _number_all_funds for date in _dict_count_trade} # dict{date:count}
|
_dict_count_founding = {
|
||||||
|
date: _number_all_funds for date in _dict_count_trade
|
||||||
|
} # dict{date:count}
|
||||||
with tqdm(total=_number_all_funds) as p_bar:
|
with tqdm(total=_number_all_funds) as p_bar:
|
||||||
for oldest_date in all_oldest_list:
|
for oldest_date in all_oldest_list:
|
||||||
for date in _dict_count_founding.keys():
|
for date in _dict_count_founding.keys():
|
||||||
@@ -158,7 +235,9 @@ def get_calendar_list_by_ratio(
|
|||||||
_dict_count_founding[date] -= 1
|
_dict_count_founding[date] -= 1
|
||||||
|
|
||||||
calendar = [
|
calendar = [
|
||||||
date for date, count in _dict_count_trade.items() if count >= max(int(count * threshold), minimum_count)
|
date
|
||||||
|
for date, count in _dict_count_trade.items()
|
||||||
|
if count >= max(int(count * threshold), minimum_count)
|
||||||
]
|
]
|
||||||
|
|
||||||
return calendar
|
return calendar
|
||||||
@@ -210,14 +289,21 @@ def get_hs_stock_symbols() -> list:
|
|||||||
data = resp.json()
|
data = resp.json()
|
||||||
|
|
||||||
# Check if response contains valid data
|
# Check if response contains valid data
|
||||||
if not data or "data" not in data or not data["data"] or "diff" not in data["data"]:
|
if (
|
||||||
|
not data
|
||||||
|
or "data" not in data
|
||||||
|
or not data["data"]
|
||||||
|
or "diff" not in data["data"]
|
||||||
|
):
|
||||||
logger.warning(f"Invalid response structure on page {page}")
|
logger.warning(f"Invalid response structure on page {page}")
|
||||||
break
|
break
|
||||||
|
|
||||||
# fetch the current page data
|
# fetch the current page data
|
||||||
current_symbols = [_v["f12"] for _v in data["data"]["diff"]]
|
current_symbols = [_v["f12"] for _v in data["data"]["diff"]]
|
||||||
|
|
||||||
if not current_symbols: # It's the last page if there is no data in current page
|
if (
|
||||||
|
not current_symbols
|
||||||
|
): # It's the last page if there is no data in current page
|
||||||
logger.info(f"Last page reached: {page - 1}")
|
logger.info(f"Last page reached: {page - 1}")
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -238,7 +324,9 @@ def get_hs_stock_symbols() -> list:
|
|||||||
f"Request to {base_url} failed with status code {resp.status_code}"
|
f"Request to {base_url} failed with status code {resp.status_code}"
|
||||||
) from e
|
) from e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("An error occurred while extracting data from the response.")
|
logger.warning(
|
||||||
|
"An error occurred while extracting data from the response."
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if len(_symbols) < 3900:
|
if len(_symbols) < 3900:
|
||||||
@@ -246,7 +334,11 @@ def get_hs_stock_symbols() -> list:
|
|||||||
|
|
||||||
# Add suffix after the stock code to conform to yahooquery standard, otherwise the data will not be fetched.
|
# Add suffix after the stock code to conform to yahooquery standard, otherwise the data will not be fetched.
|
||||||
_symbols = [
|
_symbols = [
|
||||||
_symbol + ".ss" if _symbol.startswith("6") else _symbol + ".sz" if _symbol.startswith(("0", "3")) else None
|
(
|
||||||
|
_symbol + ".ss"
|
||||||
|
if _symbol.startswith("6")
|
||||||
|
else _symbol + ".sz" if _symbol.startswith(("0", "3")) else None
|
||||||
|
)
|
||||||
for _symbol in _symbols
|
for _symbol in _symbols
|
||||||
]
|
]
|
||||||
_symbols = [_symbol for _symbol in _symbols if _symbol is not None]
|
_symbols = [_symbol for _symbol in _symbols if _symbol is not None]
|
||||||
@@ -292,7 +384,10 @@ def get_us_stock_symbols(qlib_data_path: [str, Path] = None) -> list:
|
|||||||
raise ValueError("request error")
|
raise ValueError("request error")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_symbols = [_v["f12"].replace("_", "-P") for _v in resp.json()["data"]["diff"].values()]
|
_symbols = [
|
||||||
|
_v["f12"].replace("_", "-P")
|
||||||
|
for _v in resp.json()["data"]["diff"].values()
|
||||||
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"request error: {e}")
|
logger.warning(f"request error: {e}")
|
||||||
raise
|
raise
|
||||||
@@ -357,7 +452,14 @@ def get_us_stock_symbols(qlib_data_path: [str, Path] = None) -> list:
|
|||||||
s_ = s_.strip("*")
|
s_ = s_.strip("*")
|
||||||
return s_
|
return s_
|
||||||
|
|
||||||
_US_SYMBOLS = sorted(set(map(_format, filter(lambda x: len(x) < 8 and not x.endswith("WS"), _all_symbols))))
|
_US_SYMBOLS = sorted(
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
_format,
|
||||||
|
filter(lambda x: len(x) < 8 and not x.endswith("WS"), _all_symbols),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return _US_SYMBOLS
|
return _US_SYMBOLS
|
||||||
|
|
||||||
@@ -427,7 +529,9 @@ def get_br_stock_symbols(qlib_data_path: [str, Path] = None) -> list:
|
|||||||
|
|
||||||
children = tbody.findChildren("a", recursive=True)
|
children = tbody.findChildren("a", recursive=True)
|
||||||
for child in children:
|
for child in children:
|
||||||
_symbols.append(str(child).rsplit('"', maxsplit=1)[-1].split(">")[1].split("<")[0])
|
_symbols.append(
|
||||||
|
str(child).rsplit('"', maxsplit=1)[-1].split(">")[1].split("<")[0]
|
||||||
|
)
|
||||||
|
|
||||||
return _symbols
|
return _symbols
|
||||||
|
|
||||||
@@ -471,7 +575,10 @@ def get_en_fund_symbols(qlib_data_path: [str, Path] = None) -> list:
|
|||||||
raise ValueError("request error")
|
raise ValueError("request error")
|
||||||
try:
|
try:
|
||||||
_symbols = []
|
_symbols = []
|
||||||
for sub_data in re.findall(r"[\[](.*?)[\]]", resp.content.decode().split("= [")[-1].replace("];", "")):
|
for sub_data in re.findall(
|
||||||
|
r"[\[](.*?)[\]]",
|
||||||
|
resp.content.decode().split("= [")[-1].replace("];", ""),
|
||||||
|
):
|
||||||
data = sub_data.replace('"', "").replace("'", "")
|
data = sub_data.replace('"', "").replace("'", "")
|
||||||
# TODO: do we need other information, like fund_name from ['000001', 'HXCZHH', '华夏成长混合', '混合型', 'HUAXIACHENGZHANGHUNHE']
|
# TODO: do we need other information, like fund_name from ['000001', 'HXCZHH', '华夏成长混合', '混合型', 'HUAXIACHENGZHANGHUNHE']
|
||||||
_symbols.append(data.split(",")[0])
|
_symbols.append(data.split(",")[0])
|
||||||
@@ -552,7 +659,9 @@ def deco_retry(retry: int = 5, retry_sleep: int = 3):
|
|||||||
return deco_func(retry) if callable(retry) else deco_func
|
return deco_func(retry) if callable(retry) else deco_func
|
||||||
|
|
||||||
|
|
||||||
def get_trading_date_by_shift(trading_list: list, trading_date: pd.Timestamp, shift: int = 1):
|
def get_trading_date_by_shift(
|
||||||
|
trading_list: list, trading_date: pd.Timestamp, shift: int = 1
|
||||||
|
):
|
||||||
"""get trading date by shift
|
"""get trading date by shift
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -650,17 +759,28 @@ def get_instruments(
|
|||||||
$ python collector.py --index_name CSI300 --qlib_dir ~/.qlib/qlib_data/cn_data --method save_new_companies
|
$ python collector.py --index_name CSI300 --qlib_dir ~/.qlib/qlib_data/cn_data --method save_new_companies
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_cur_module = importlib.import_module("data_collector.{}.collector".format(market_index))
|
_cur_module = importlib.import_module(
|
||||||
|
"data_collector.{}.collector".format(market_index)
|
||||||
|
)
|
||||||
obj = getattr(_cur_module, f"{index_name.upper()}Index")(
|
obj = getattr(_cur_module, f"{index_name.upper()}Index")(
|
||||||
qlib_dir=qlib_dir, index_name=index_name, freq=freq, request_retry=request_retry, retry_sleep=retry_sleep
|
qlib_dir=qlib_dir,
|
||||||
|
index_name=index_name,
|
||||||
|
freq=freq,
|
||||||
|
request_retry=request_retry,
|
||||||
|
retry_sleep=retry_sleep,
|
||||||
)
|
)
|
||||||
getattr(obj, method)()
|
getattr(obj, method)()
|
||||||
|
|
||||||
|
|
||||||
def _get_all_1d_data(_date_field_name: str, _symbol_field_name: str, _1d_data_all: pd.DataFrame):
|
def _get_all_1d_data(
|
||||||
|
_date_field_name: str, _symbol_field_name: str, _1d_data_all: pd.DataFrame
|
||||||
|
):
|
||||||
df = copy.deepcopy(_1d_data_all)
|
df = copy.deepcopy(_1d_data_all)
|
||||||
df.reset_index(inplace=True)
|
df.reset_index(inplace=True)
|
||||||
df.rename(columns={"datetime": _date_field_name, "instrument": _symbol_field_name}, inplace=True)
|
df.rename(
|
||||||
|
columns={"datetime": _date_field_name, "instrument": _symbol_field_name},
|
||||||
|
inplace=True,
|
||||||
|
)
|
||||||
df.columns = list(map(lambda x: x[1:] if x.startswith("$") else x, df.columns))
|
df.columns = list(map(lambda x: x[1:] if x.startswith("$") else x, df.columns))
|
||||||
return df
|
return df
|
||||||
|
|
||||||
@@ -723,8 +843,12 @@ def calc_adjusted_price(
|
|||||||
df[_date_field_name] = pd.to_datetime(df[_date_field_name])
|
df[_date_field_name] = pd.to_datetime(df[_date_field_name])
|
||||||
# get 1d data from qlib
|
# get 1d data from qlib
|
||||||
_start = pd.Timestamp(df[_date_field_name].min()).strftime("%Y-%m-%d")
|
_start = pd.Timestamp(df[_date_field_name].min()).strftime("%Y-%m-%d")
|
||||||
_end = (pd.Timestamp(df[_date_field_name].max()) + pd.Timedelta(days=1)).strftime("%Y-%m-%d")
|
_end = (pd.Timestamp(df[_date_field_name].max()) + pd.Timedelta(days=1)).strftime(
|
||||||
data_1d: pd.DataFrame = get_1d_data(_date_field_name, _symbol_field_name, symbol, _start, _end, _1d_data_all)
|
"%Y-%m-%d"
|
||||||
|
)
|
||||||
|
data_1d: pd.DataFrame = get_1d_data(
|
||||||
|
_date_field_name, _symbol_field_name, symbol, _start, _end, _1d_data_all
|
||||||
|
)
|
||||||
data_1d = data_1d.copy()
|
data_1d = data_1d.copy()
|
||||||
if data_1d is None or data_1d.empty:
|
if data_1d is None or data_1d.empty:
|
||||||
df["factor"] = 1 / df.loc[df["close"].first_valid_index()]["close"]
|
df["factor"] = 1 / df.loc[df["close"].first_valid_index()]["close"]
|
||||||
@@ -744,27 +868,38 @@ def calc_adjusted_price(
|
|||||||
# - data_1d.close: `data_1d.adjclose / (close for the first trading day that is not np.nan)`
|
# - data_1d.close: `data_1d.adjclose / (close for the first trading day that is not np.nan)`
|
||||||
def _calc_factor(df_1d: pd.DataFrame):
|
def _calc_factor(df_1d: pd.DataFrame):
|
||||||
try:
|
try:
|
||||||
_date = pd.Timestamp(pd.Timestamp(df_1d[_date_field_name].iloc[0]).date())
|
_date = pd.Timestamp(
|
||||||
df_1d["factor"] = data_1d.loc[_date]["close"] / df_1d.loc[df_1d["close"].last_valid_index()]["close"]
|
pd.Timestamp(df_1d[_date_field_name].iloc[0]).date()
|
||||||
|
)
|
||||||
|
df_1d["factor"] = (
|
||||||
|
data_1d.loc[_date]["close"]
|
||||||
|
/ df_1d.loc[df_1d["close"].last_valid_index()]["close"]
|
||||||
|
)
|
||||||
df_1d["paused"] = data_1d.loc[_date]["paused"]
|
df_1d["paused"] = data_1d.loc[_date]["paused"]
|
||||||
except Exception:
|
except Exception:
|
||||||
df_1d["factor"] = np.nan
|
df_1d["factor"] = np.nan
|
||||||
df_1d["paused"] = np.nan
|
df_1d["paused"] = np.nan
|
||||||
return df_1d
|
return df_1d
|
||||||
|
|
||||||
df = df.groupby([df[_date_field_name].dt.date], group_keys=False).apply(_calc_factor)
|
df = df.groupby([df[_date_field_name].dt.date], group_keys=False).apply(
|
||||||
|
_calc_factor
|
||||||
|
)
|
||||||
if consistent_1d:
|
if consistent_1d:
|
||||||
# the date sequence is consistent with 1d
|
# the date sequence is consistent with 1d
|
||||||
df.set_index(_date_field_name, inplace=True)
|
df.set_index(_date_field_name, inplace=True)
|
||||||
df = df.reindex(
|
df = df.reindex(
|
||||||
generate_minutes_calendar_from_daily(
|
generate_minutes_calendar_from_daily(
|
||||||
calendars=pd.to_datetime(data_1d.reset_index()[_date_field_name].drop_duplicates()),
|
calendars=pd.to_datetime(
|
||||||
|
data_1d.reset_index()[_date_field_name].drop_duplicates()
|
||||||
|
),
|
||||||
freq=frequence,
|
freq=frequence,
|
||||||
am_range=("09:30:00", "11:29:00"),
|
am_range=("09:30:00", "11:29:00"),
|
||||||
pm_range=("13:00:00", "14:59:00"),
|
pm_range=("13:00:00", "14:59:00"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
df[_symbol_field_name] = df.loc[df[_symbol_field_name].first_valid_index()][_symbol_field_name]
|
df[_symbol_field_name] = df.loc[df[_symbol_field_name].first_valid_index()][
|
||||||
|
_symbol_field_name
|
||||||
|
]
|
||||||
df.index.names = [_date_field_name]
|
df.index.names = [_date_field_name]
|
||||||
df.reset_index(inplace=True)
|
df.reset_index(inplace=True)
|
||||||
for _col in ["open", "close", "high", "low", "volume"]:
|
for _col in ["open", "close", "high", "low", "volume"]:
|
||||||
@@ -806,7 +941,10 @@ def calc_paused_num(df: pd.DataFrame, _date_field_name, _symbol_field_name):
|
|||||||
_date_field_name,
|
_date_field_name,
|
||||||
_symbol_field_name,
|
_symbol_field_name,
|
||||||
}
|
}
|
||||||
if _df.loc[:, list(check_fields)].isna().values.all() or (_df["volume"] == 0).all():
|
if (
|
||||||
|
_df.loc[:, list(check_fields)].isna().values.all()
|
||||||
|
or (_df["volume"] == 0).all()
|
||||||
|
):
|
||||||
all_nan_nums += 1
|
all_nan_nums += 1
|
||||||
not_nan_nums = 0
|
not_nan_nums = 0
|
||||||
_df["paused"] = 1
|
_df["paused"] = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user