This commit is contained in:
Haozhe Wu committed 2026-07-18 19:25:52 +08:00
commit 96f7a9174c
2 files changed
+81 -2

No files matched your search

+22 -2
View File
@@ -162,8 +162,22 @@ def _normalize_side(raw: Any) -> str:
raise ValueError(f"Unsupported trade side: {raw!r}")
def _is_empty_code(raw: Any) -> bool:
"""True for None/NaN/blank securities codes from CSV/Excel cells."""
if raw is None:
return True
try:
if pd.isna(raw):
return True
except (TypeError, ValueError):
pass
return not str(raw).strip()
def _qualify_a_share(code: str) -> str:
"""Append .SH/.SZ/.BJ suffix to a bare A-share ticker."""
if _is_empty_code(code):
raise ValueError("empty securities code")
code = str(code).strip().zfill(6)
if "." in code:
return code.upper()
@@ -193,13 +207,16 @@ def parse_tonghuashun(df: pd.DataFrame) -> list[TradeRecord]:
"""
records: list[TradeRecord] = []
for _, row in df.iterrows():
raw_code = row.get("证券代码", "")
if _is_empty_code(raw_code):
continue
qty = _to_float(row.get("成交数量"))
price = _to_float(row.get("成交价格"))
amount = _to_float(row.get("成交金额")) or qty * price
fee = _to_float(row.get("手续费")) + _to_float(row.get("印花税")) + _to_float(row.get("过户费"))
records.append(TradeRecord(
datetime=str(row.get("成交时间", "")).strip(),
symbol=_qualify_a_share(row.get("证券代码", "")),
symbol=_qualify_a_share(raw_code),
name=str(row.get("证券名称", "")).strip(),
side=_normalize_side(row.get("操作")),
quantity=qty,
@@ -219,6 +236,9 @@ def parse_eastmoney(df: pd.DataFrame) -> list[TradeRecord]:
"""
records: list[TradeRecord] = []
for _, row in df.iterrows():
raw_code = row.get("股票代码", "")
if _is_empty_code(raw_code):
continue
raw_date = str(row.get("成交日期", "")).strip()
raw_time = str(row.get("成交时间", "")).strip()
if len(raw_date) == 8 and raw_date.isdigit():
@@ -232,7 +252,7 @@ def parse_eastmoney(df: pd.DataFrame) -> list[TradeRecord]:
fee = _to_float(row.get("佣金")) + _to_float(row.get("印花税"))
records.append(TradeRecord(
datetime=dt,
symbol=_qualify_a_share(row.get("股票代码", "")),
symbol=_qualify_a_share(raw_code),
name=str(row.get("股票名称", "")).strip(),
side=_normalize_side(row.get("买卖标志")),
quantity=qty,
+59
View File
@@ -19,6 +19,8 @@ from src.tools.trade_journal_parsers import (
_infer_market_from_symbol,
_normalize_side,
_qualify_a_share,
parse_tonghuashun,
parse_eastmoney,
detect_format,
parse_file,
records_to_dataframe,
@@ -506,3 +508,60 @@ def test_analyze_with_filter(allow_tmp: Path) -> None:
assert result["status"] == "ok"
assert result["total_records"] == 1
assert result["filter_applied"] == "symbol=AAPL"
def test_qualify_a_share_rejects_empty() -> None:
with pytest.raises(ValueError, match="empty"):
_qualify_a_share("")
with pytest.raises(ValueError, match="empty"):
_qualify_a_share(" ")
def test_parse_tonghuashun_skips_blank_code_rows() -> None:
df = pd.DataFrame([{
"成交时间": "2024-01-01 10:00:00", "证券代码": "", "证券名称": "",
"操作": "买入", "成交数量": 100, "成交价格": 10.0, "成交金额": 1000,
"手续费": 0, "印花税": 0, "过户费": 0,
}, {
"成交时间": "2024-01-01 10:01:00", "证券代码": "600519", "证券名称": "茅台",
"操作": "买入", "成交数量": 100, "成交价格": 10.0, "成交金额": 1000,
"手续费": 0, "印花税": 0, "过户费": 0,
}])
rec = parse_tonghuashun(df)
assert len(rec) == 1
assert rec[0].symbol == "600519.SH"
def test_qualify_a_share_rejects_nan() -> None:
with pytest.raises(ValueError, match="empty"):
_qualify_a_share(float("nan"))
def test_parse_tonghuashun_skips_nan_code_rows() -> None:
df = pd.DataFrame([{
"成交时间": "2024-01-01 10:00:00", "证券代码": float("nan"), "证券名称": "",
"操作": "买入", "成交数量": 100, "成交价格": 10.0, "成交金额": 1000,
"手续费": 0, "印花税": 0, "过户费": 0,
}, {
"成交时间": "2024-01-01 10:01:00", "证券代码": "600519", "证券名称": "茅台",
"操作": "买入", "成交数量": 100, "成交价格": 10.0, "成交金额": 1000,
"手续费": 0, "印花税": 0, "过户费": 0,
}])
rec = parse_tonghuashun(df)
assert len(rec) == 1
assert rec[0].symbol == "600519.SH"
def test_parse_eastmoney_skips_nan_code_rows() -> None:
df = pd.DataFrame([{
"成交日期": "20240101", "成交时间": "10:00:00", "股票代码": float("nan"),
"股票名称": "", "买卖标志": "B", "成交数量": 100, "成交均价": 10.0,
"成交金额": 1000, "佣金": 0, "印花税": 0,
}, {
"成交日期": "20240101", "成交时间": "10:01:00", "股票代码": "000001",
"股票名称": "平安", "买卖标志": "B", "成交数量": 100, "成交均价": 10.0,
"成交金额": 1000, "佣金": 0, "印花税": 0,
}])
rec = parse_eastmoney(df)
assert len(rec) == 1
assert rec[0].symbol == "000001.SZ"