mirror of
https://ghfast.top/https://github.com/aeroxw/easy_tdx_max.git
synced 2026-09-12 15:44:18 +08:00
style: ruff format 修复预存格式债(CI ruff format --check 转绿)
v1.17.2 引入的 QFQ 重算代码(adjust.py/client.py/test_mac_qfq_integration.py) 含 magic trailing comma 导致 ruff format 期望多行参数展开,CI 的 'ruff format --check src/ tests/' 自 v1.17.0 起一直失败。纯格式变更, 零逻辑改动(20 例 QFQ 测试全过)。
This commit is contained in:
@@ -132,7 +132,11 @@ def apply_forward_adjust(
|
|||||||
if not np.isfinite(factor):
|
if not np.isfinite(factor):
|
||||||
_logger.warning(
|
_logger.warning(
|
||||||
"QFQ 本地重算:事件 %s 因子非法(cum_close=%s fh=%s sz=%s pg=%s),跳过",
|
"QFQ 本地重算:事件 %s 因子非法(cum_close=%s fh=%s sz=%s pg=%s),跳过",
|
||||||
ed.date(), cum_close, fh, sz, pg,
|
ed.date(),
|
||||||
|
cum_close,
|
||||||
|
fh,
|
||||||
|
sz,
|
||||||
|
pg,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
arr[: cum_idx + 1] *= factor
|
arr[: cum_idx + 1] *= factor
|
||||||
|
|||||||
@@ -388,7 +388,10 @@ class MacClient:
|
|||||||
xd = tc.get_xdxr_info(Market(market), code)
|
xd = tc.get_xdxr_info(Market(market), code)
|
||||||
except Exception as exc: # noqa: BLE001 - 降级,不中断 kline 获取
|
except Exception as exc: # noqa: BLE001 - 降级,不中断 kline 获取
|
||||||
_logger.warning(
|
_logger.warning(
|
||||||
"QFQ 本地重算:获取 %s %s XDXR 失败,降级返回服务端 QFQ:%s", market, code, exc,
|
"QFQ 本地重算:获取 %s %s XDXR 失败,降级返回服务端 QFQ:%s",
|
||||||
|
market,
|
||||||
|
code,
|
||||||
|
exc,
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
if xd is None or xd.empty:
|
if xd is None or xd.empty:
|
||||||
@@ -422,7 +425,9 @@ class MacClient:
|
|||||||
_logger.warning("QFQ 本地重算后 %s %s 仍含非法价格,降级返回服务端 QFQ", market, code)
|
_logger.warning("QFQ 本地重算后 %s %s 仍含非法价格,降级返回服务端 QFQ", market, code)
|
||||||
return df
|
return df
|
||||||
_logger.warning(
|
_logger.warning(
|
||||||
"QFQ 本地重算:%s %s 服务端深层历史返回负价,已用 NONE+XDXR 重算前复权", market, code,
|
"QFQ 本地重算:%s %s 服务端深层历史返回负价,已用 NONE+XDXR 重算前复权",
|
||||||
|
market,
|
||||||
|
code,
|
||||||
)
|
)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@@ -1342,7 +1347,10 @@ class AsyncMacClient(AsyncHeartbeatMixin):
|
|||||||
xd = tc.get_xdxr_info(Market(market), code)
|
xd = tc.get_xdxr_info(Market(market), code)
|
||||||
except Exception as exc: # noqa: BLE001 - 降级,不中断 kline 获取
|
except Exception as exc: # noqa: BLE001 - 降级,不中断 kline 获取
|
||||||
_logger.warning(
|
_logger.warning(
|
||||||
"QFQ 本地重算:获取 %s %s XDXR 失败,降级返回服务端 QFQ:%s", market, code, exc,
|
"QFQ 本地重算:获取 %s %s XDXR 失败,降级返回服务端 QFQ:%s",
|
||||||
|
market,
|
||||||
|
code,
|
||||||
|
exc,
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
if xd is None or xd.empty:
|
if xd is None or xd.empty:
|
||||||
@@ -1351,7 +1359,10 @@ class AsyncMacClient(AsyncHeartbeatMixin):
|
|||||||
return xd
|
return xd
|
||||||
|
|
||||||
def _local_recompute_qfq(
|
def _local_recompute_qfq(
|
||||||
self, df: pd.DataFrame, market: int, code: str,
|
self,
|
||||||
|
df: pd.DataFrame,
|
||||||
|
market: int,
|
||||||
|
code: str,
|
||||||
) -> pd.DataFrame:
|
) -> pd.DataFrame:
|
||||||
"""对 QFQ 异常的 K 线用 NONE+XDXR 本地重算前复权(同 MacClient)。"""
|
"""对 QFQ 异常的 K 线用 NONE+XDXR 本地重算前复权(同 MacClient)。"""
|
||||||
from .adjust import apply_forward_adjust, has_bad_prices
|
from .adjust import apply_forward_adjust, has_bad_prices
|
||||||
@@ -1364,7 +1375,9 @@ class AsyncMacClient(AsyncHeartbeatMixin):
|
|||||||
_logger.warning("QFQ 本地重算后 %s %s 仍含非法价格,降级返回服务端 QFQ", market, code)
|
_logger.warning("QFQ 本地重算后 %s %s 仍含非法价格,降级返回服务端 QFQ", market, code)
|
||||||
return df
|
return df
|
||||||
_logger.warning(
|
_logger.warning(
|
||||||
"QFQ 本地重算:%s %s 服务端深层历史返回负价,已用 NONE+XDXR 重算前复权", market, code,
|
"QFQ 本地重算:%s %s 服务端深层历史返回负价,已用 NONE+XDXR 重算前复权",
|
||||||
|
market,
|
||||||
|
code,
|
||||||
)
|
)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@@ -1425,8 +1438,13 @@ class AsyncMacClient(AsyncHeartbeatMixin):
|
|||||||
nps = min(count - nfetched, _KLINE_PAGE_SIZE)
|
nps = min(count - nfetched, _KLINE_PAGE_SIZE)
|
||||||
nb = await self._execute(
|
nb = await self._execute(
|
||||||
SymbolBarCmd(
|
SymbolBarCmd(
|
||||||
market=market, code=code, period=period, times=times,
|
market=market,
|
||||||
start=noffset, count=nps, fq=Adjust.NONE,
|
code=code,
|
||||||
|
period=period,
|
||||||
|
times=times,
|
||||||
|
start=noffset,
|
||||||
|
count=nps,
|
||||||
|
fq=Adjust.NONE,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if not nb:
|
if not nb:
|
||||||
@@ -1439,7 +1457,10 @@ class AsyncMacClient(AsyncHeartbeatMixin):
|
|||||||
if none_bars:
|
if none_bars:
|
||||||
# XDXR 获取涉及同步网络 IO,放线程执行
|
# XDXR 获取涉及同步网络 IO,放线程执行
|
||||||
df = await asyncio.to_thread(
|
df = await asyncio.to_thread(
|
||||||
self._local_recompute_qfq, _to_df(none_bars), market, code,
|
self._local_recompute_qfq,
|
||||||
|
_to_df(none_bars),
|
||||||
|
market,
|
||||||
|
code,
|
||||||
)
|
)
|
||||||
|
|
||||||
delta = _period_to_minutes(period, times)
|
delta = _period_to_minutes(period, times)
|
||||||
|
|||||||
@@ -78,15 +78,21 @@ def test_qfq_negative_triggers_local_recompute():
|
|||||||
def fake_execute(cmd: SymbolBarCmd) -> list[MacBar]:
|
def fake_execute(cmd: SymbolBarCmd) -> list[MacBar]:
|
||||||
return _qfq_broken_bars() if cmd._fq == Adjust.QFQ else _none_bars()
|
return _qfq_broken_bars() if cmd._fq == Adjust.QFQ else _none_bars()
|
||||||
|
|
||||||
with patch.object(client, "_execute", side_effect=fake_execute), patch(
|
with (
|
||||||
"easy_tdx.client.TdxClient"
|
patch.object(client, "_execute", side_effect=fake_execute),
|
||||||
) as MockTdx:
|
patch("easy_tdx.client.TdxClient") as MockTdx,
|
||||||
|
):
|
||||||
# 让 TdxClient 上下文返回手构 XDXR
|
# 让 TdxClient 上下文返回手构 XDXR
|
||||||
mock_inst = MockTdx.from_best_host.return_value.__enter__.return_value
|
mock_inst = MockTdx.from_best_host.return_value.__enter__.return_value
|
||||||
mock_inst.get_xdxr_info.return_value = _xdxr_df()
|
mock_inst.get_xdxr_info.return_value = _xdxr_df()
|
||||||
|
|
||||||
df = client.get_stock_kline(
|
df = client.get_stock_kline(
|
||||||
market=1, code="601088", period=Period.DAILY, start=0, count=4, adjust=Adjust.QFQ,
|
market=1,
|
||||||
|
code="601088",
|
||||||
|
period=Period.DAILY,
|
||||||
|
start=0,
|
||||||
|
count=4,
|
||||||
|
adjust=Adjust.QFQ,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 重算后全部为正
|
# 重算后全部为正
|
||||||
@@ -107,11 +113,17 @@ def test_qfq_clean_does_not_trigger_recompute():
|
|||||||
_bar("2024-01-04", 9.0, Adjust.QFQ),
|
_bar("2024-01-04", 9.0, Adjust.QFQ),
|
||||||
]
|
]
|
||||||
|
|
||||||
with patch.object(client, "_execute", return_value=clean_qfq) as mock_exec, patch(
|
with (
|
||||||
"easy_tdx.client.TdxClient"
|
patch.object(client, "_execute", return_value=clean_qfq) as mock_exec,
|
||||||
) as MockTdx:
|
patch("easy_tdx.client.TdxClient") as MockTdx,
|
||||||
|
):
|
||||||
df = client.get_stock_kline(
|
df = client.get_stock_kline(
|
||||||
market=1, code="601088", period=Period.DAILY, start=0, count=4, adjust=Adjust.QFQ,
|
market=1,
|
||||||
|
code="601088",
|
||||||
|
period=Period.DAILY,
|
||||||
|
start=0,
|
||||||
|
count=4,
|
||||||
|
adjust=Adjust.QFQ,
|
||||||
)
|
)
|
||||||
# QFQ 干净时不应再去拉 XDXR
|
# QFQ 干净时不应再去拉 XDXR
|
||||||
MockTdx.from_best_host.assert_not_called()
|
MockTdx.from_best_host.assert_not_called()
|
||||||
@@ -128,15 +140,21 @@ def test_qfq_recompute_xdxr_failure_degrades_gracefully():
|
|||||||
def fake_execute(cmd: SymbolBarCmd) -> list[MacBar]:
|
def fake_execute(cmd: SymbolBarCmd) -> list[MacBar]:
|
||||||
return _qfq_broken_bars() if cmd._fq == Adjust.QFQ else _none_bars()
|
return _qfq_broken_bars() if cmd._fq == Adjust.QFQ else _none_bars()
|
||||||
|
|
||||||
with patch.object(client, "_execute", side_effect=fake_execute), patch(
|
with (
|
||||||
"easy_tdx.client.TdxClient"
|
patch.object(client, "_execute", side_effect=fake_execute),
|
||||||
) as MockTdx:
|
patch("easy_tdx.client.TdxClient") as MockTdx,
|
||||||
|
):
|
||||||
# XDXR 抛异常 → _fetch_xdxr_records 返回 None → 降级
|
# XDXR 抛异常 → _fetch_xdxr_records 返回 None → 降级
|
||||||
mock_inst = MockTdx.from_best_host.return_value.__enter__.return_value
|
mock_inst = MockTdx.from_best_host.return_value.__enter__.return_value
|
||||||
mock_inst.get_xdxr_info.side_effect = RuntimeError("host unreachable")
|
mock_inst.get_xdxr_info.side_effect = RuntimeError("host unreachable")
|
||||||
|
|
||||||
df = client.get_stock_kline(
|
df = client.get_stock_kline(
|
||||||
market=1, code="601088", period=Period.DAILY, start=0, count=4, adjust=Adjust.QFQ,
|
market=1,
|
||||||
|
code="601088",
|
||||||
|
period=Period.DAILY,
|
||||||
|
start=0,
|
||||||
|
count=4,
|
||||||
|
adjust=Adjust.QFQ,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 降级:返回 NONE 数据(apply_forward_adjust 因 xd=None 原样返回 df)
|
# 降级:返回 NONE 数据(apply_forward_adjust 因 xd=None 原样返回 df)
|
||||||
@@ -148,11 +166,17 @@ def test_qfq_recompute_xdxr_failure_degrades_gracefully():
|
|||||||
def test_none_adjust_skips_recompute():
|
def test_none_adjust_skips_recompute():
|
||||||
"""adjust=NONE 时完全跳过 QFQ 重算逻辑。"""
|
"""adjust=NONE 时完全跳过 QFQ 重算逻辑。"""
|
||||||
client = _make_client()
|
client = _make_client()
|
||||||
with patch.object(client, "_execute", return_value=_none_bars()) as mock_exec, patch(
|
with (
|
||||||
"easy_tdx.client.TdxClient"
|
patch.object(client, "_execute", return_value=_none_bars()) as mock_exec,
|
||||||
) as MockTdx:
|
patch("easy_tdx.client.TdxClient") as MockTdx,
|
||||||
|
):
|
||||||
df = client.get_stock_kline(
|
df = client.get_stock_kline(
|
||||||
market=1, code="601088", period=Period.DAILY, start=0, count=4, adjust=Adjust.NONE,
|
market=1,
|
||||||
|
code="601088",
|
||||||
|
period=Period.DAILY,
|
||||||
|
start=0,
|
||||||
|
count=4,
|
||||||
|
adjust=Adjust.NONE,
|
||||||
)
|
)
|
||||||
MockTdx.from_best_host.assert_not_called()
|
MockTdx.from_best_host.assert_not_called()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user