test_validate_data_pipeline.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import importlib.util
  2. import sys
  3. from pathlib import Path
  4. from okx_codex_trader.models import Candle
  5. def load_data_validation_module():
  6. path = Path(__file__).resolve().parents[1] / "scripts" / "validate_data_pipeline.py"
  7. spec = importlib.util.spec_from_file_location("validate_data_pipeline", path)
  8. assert spec is not None
  9. module = importlib.util.module_from_spec(spec)
  10. assert spec.loader is not None
  11. sys.modules[spec.name] = module
  12. spec.loader.exec_module(module)
  13. return module
  14. def build_candles(count: int) -> list[Candle]:
  15. return [
  16. Candle(
  17. symbol="BTC-USDT-SWAP",
  18. ts=index * 60_000,
  19. open=100.0 + index,
  20. high=101.0 + index,
  21. low=99.0 + index,
  22. close=100.5 + index,
  23. volume=1_000.0 + index,
  24. )
  25. for index in range(count)
  26. ]
  27. def test_audit_candles_passes_clean_ohlcv_pipeline():
  28. module = load_data_validation_module()
  29. audit = module.audit_candles(candles=build_candles(80), symbol="BTC-USDT-SWAP", bar="1m")
  30. assert audit.passed
  31. assert audit.rows == 80
  32. assert audit.duplicate_timestamps == 0
  33. assert audit.unexpected_intervals == 0
  34. assert audit.invalid_ohlc_rows == 0
  35. assert audit.invalid_volume_rows == 0
  36. assert audit.cache_roundtrip_matches
  37. assert audit.frame_conversion_matches
  38. def test_audit_candles_fails_duplicate_gap_and_invalid_ohlcv():
  39. module = load_data_validation_module()
  40. candles = build_candles(5)
  41. candles[2] = Candle(
  42. symbol="BTC-USDT-SWAP",
  43. ts=candles[1].ts,
  44. open=100.0,
  45. high=99.0,
  46. low=101.0,
  47. close=100.0,
  48. volume=-1.0,
  49. )
  50. audit = module.audit_candles(candles=candles, symbol="BTC-USDT-SWAP", bar="1m")
  51. assert not audit.passed
  52. assert audit.duplicate_timestamps == 1
  53. assert audit.non_increasing_steps == 1
  54. assert audit.unexpected_intervals == 2
  55. assert audit.invalid_ohlc_rows == 1
  56. assert audit.invalid_volume_rows == 1
  57. def test_audit_candles_reports_live_overlap_mismatches():
  58. module = load_data_validation_module()
  59. candles = build_candles(3)
  60. live = [
  61. candles[0],
  62. Candle(
  63. symbol="BTC-USDT-SWAP",
  64. ts=candles[1].ts,
  65. open=candles[1].open,
  66. high=candles[1].high,
  67. low=candles[1].low,
  68. close=candles[1].close + 1.0,
  69. volume=candles[1].volume,
  70. ),
  71. ]
  72. audit = module.audit_candles(candles=candles, symbol="BTC-USDT-SWAP", bar="1m", live_candles=live)
  73. assert not audit.passed
  74. assert audit.live_overlap_rows == 2
  75. assert audit.live_mismatches == 1