from __future__ import annotations import unittest from datahub.normalize import ( AMOUNT_THOUSAND_YUAN, AMOUNT_WAN_YUAN, VOLUME_LOT, apply_qfq, normalize_auction, normalize_daily, normalize_index_daily, normalize_moneyflow, normalize_valuation, review_daily_to_canonical, ) from tests.fixtures import RAW class NormalizeTests(unittest.TestCase): def test_daily_matches_architecture_and_review_native_conversion(self) -> None: raw = RAW["daily"][0] hub = normalize_daily(raw, adj_factor=1.1) # review stores Tushare native units; canonical = review * factor review_native = dict(raw) converted = review_daily_to_canonical(review_native) self.assertEqual(hub["amount"], converted["amount"]) self.assertEqual(hub["amount"], raw["amount"] * AMOUNT_THOUSAND_YUAN) self.assertEqual(hub["volume"], raw["vol"] * VOLUME_LOT) self.assertEqual(hub["close"], 10.2) self.assertEqual(hub["adj_factor"], 1.1) self.assertEqual(hub["ts_code"], "600000.SH") def test_moneyflow_wan_to_yuan(self) -> None: raw = RAW["moneyflow"][0] hub = normalize_moneyflow(raw) self.assertEqual(hub["net_mf_amount"], raw["net_mf_amount"] * AMOUNT_WAN_YUAN) self.assertEqual(hub["buy_lg_amount"], 30 * AMOUNT_WAN_YUAN) def test_valuation_mv_wan_to_yuan(self) -> None: raw = RAW["daily_basic"][0] hub = normalize_valuation(raw) self.assertEqual(hub["total_mv"], 1000 * AMOUNT_WAN_YUAN) self.assertEqual(hub["circ_mv"], 800 * AMOUNT_WAN_YUAN) def test_index_daily_amount_thousand_yuan(self) -> None: raw = RAW["index_daily"][0] hub = normalize_index_daily(raw) self.assertEqual(hub["amount"], raw["amount"] * AMOUNT_THOUSAND_YUAN) self.assertEqual(hub["volume"], raw["vol"] * VOLUME_LOT) def test_auction_amount_already_yuan(self) -> None: raw = RAW["stk_auction"][0] hub = normalize_auction(raw) self.assertEqual(hub["amount"], raw["amount"]) self.assertEqual(hub["volume"], raw["vol"] * VOLUME_LOT) def test_field_diff_against_review_native_is_explained(self) -> None: """Golden: every non-zero diff vs review-native daily is a documented unit factor.""" raw = RAW["daily"][0] hub = normalize_daily(raw) diffs = {} for key in ("open", "high", "low", "close", "pct_chg"): if hub[key] != raw[key]: diffs[key] = (raw[key], hub[key]) self.assertEqual(diffs, {}) self.assertNotEqual(hub["amount"], raw["amount"]) self.assertEqual(hub["amount"] / raw["amount"], AMOUNT_THOUSAND_YUAN) self.assertEqual(hub["volume"] / raw["vol"], VOLUME_LOT) def test_qfq_formula(self) -> None: self.assertEqual(apply_qfq(10.0, 1.1, 2.2), 5.0) none_price = apply_qfq(None, 1.1, 2.2) self.assertIsNone(none_price) if __name__ == "__main__": unittest.main()