exness-data-preprocess 2.1.0__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. exness_data_preprocess-3.0.0/.github/dependabot.yml +26 -0
  2. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.github/workflows/publish.yml +4 -4
  3. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.gitignore +4 -2
  4. exness_data_preprocess-3.0.0/.moon/toolchain.yml +2 -0
  5. exness_data_preprocess-3.0.0/.moon/workspace.yml +8 -0
  6. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.pre-commit-config.yaml +4 -4
  7. exness_data_preprocess-3.0.0/.prototools +5 -0
  8. exness_data_preprocess-3.0.0/.python-version +1 -0
  9. exness_data_preprocess-3.0.0/.releaserc.yml +24 -0
  10. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/CHANGELOG.md +31 -0
  11. exness_data_preprocess-3.0.0/CLAUDE.md +31 -0
  12. exness_data_preprocess-3.0.0/CONTRIBUTING.md +32 -0
  13. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/PKG-INFO +23 -24
  14. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/README.md +20 -20
  15. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/CLICKHOUSE_USER_GUIDE.md +32 -45
  16. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/EXNESS_DATA_SOURCES.md +3 -1
  17. exness_data_preprocess-3.0.0/docs/README.md +31 -0
  18. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-11-duckdb-removal-clickhouse/spec.md +5 -14
  19. exness_data_preprocess-3.0.0/docs/release-notes/2.1.1.md +24 -0
  20. exness_data_preprocess-3.0.0/docs/release-notes/3.0.0.md +29 -0
  21. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md +27 -16
  22. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/README.md +2 -2
  23. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +16 -12
  24. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/README.md +1 -2
  25. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +68 -57
  26. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +7 -0
  27. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/04-discoveries-and-plan-evolution.md +7 -7
  28. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/findings/phase4-5-statistical-tests-survivorship-report.md +3 -2
  29. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +6 -6
  30. exness_data_preprocess-3.0.0/examples/basic_usage.py +65 -0
  31. exness_data_preprocess-3.0.0/moon.yml +77 -0
  32. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/package-lock.json +210 -235
  33. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/package.json +4 -4
  34. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/pyproject.toml +4 -8
  35. exness_data_preprocess-3.0.0/scripts/clickhouse-start.sh +60 -0
  36. exness_data_preprocess-3.0.0/scripts/clickhouse-stop.sh +52 -0
  37. exness_data_preprocess-3.0.0/scripts/e2e-ephemeral.sh +149 -0
  38. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/scripts/generate_dbeaver_config.py +2 -3
  39. exness_data_preprocess-3.0.0/scripts/publish-release-notes.sh +51 -0
  40. exness_data_preprocess-3.0.0/scripts/smoke_install.sh +16 -0
  41. exness_data_preprocess-3.0.0/scripts/validate_clickhouse.py +342 -0
  42. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/__init__.py +5 -2
  43. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_client.py +3 -4
  44. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_manager.py +206 -45
  45. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_ohlc_generator.py +33 -16
  46. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_query_engine.py +87 -50
  47. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/downloader.py +13 -2
  48. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/models.py +20 -17
  49. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/processor.py +89 -33
  50. exness_data_preprocess-3.0.0/tests/README.md +28 -0
  51. exness_data_preprocess-3.0.0/tests/conftest.py +94 -0
  52. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_basic.py +3 -23
  53. exness_data_preprocess-3.0.0/tests/test_database_bootstrap_order.py +90 -0
  54. exness_data_preprocess-3.0.0/tests/test_date_bounds.py +31 -0
  55. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_functional_regression.py +1 -23
  56. exness_data_preprocess-3.0.0/tests/test_package_structure.py +70 -0
  57. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_processor_pydantic.py +1 -24
  58. exness_data_preprocess-3.0.0/tests/test_tick_seq.py +53 -0
  59. exness_data_preprocess-3.0.0/uv.toml +2 -0
  60. exness_data_preprocess-2.1.0/.cz.toml +0 -12
  61. exness_data_preprocess-2.1.0/.github/workflows/ci.yml +0 -25
  62. exness_data_preprocess-2.1.0/.github/workflows/pre-commit-autoupdate.yml +0 -38
  63. exness_data_preprocess-2.1.0/.mise.toml +0 -518
  64. exness_data_preprocess-2.1.0/.releaserc.yml +0 -22
  65. exness_data_preprocess-2.1.0/CLAUDE.md +0 -152
  66. exness_data_preprocess-2.1.0/CONTRIBUTING.md +0 -282
  67. exness_data_preprocess-2.1.0/Makefile +0 -62
  68. exness_data_preprocess-2.1.0/cliff-release-notes.toml +0 -131
  69. exness_data_preprocess-2.1.0/cliff.toml +0 -144
  70. exness_data_preprocess-2.1.0/docs/DATABASE_SCHEMA.md +0 -952
  71. exness_data_preprocess-2.1.0/docs/MODULE_ARCHITECTURE.md +0 -1085
  72. exness_data_preprocess-2.1.0/docs/PRIORITY3_CLEANUP_PLAN.yaml +0 -386
  73. exness_data_preprocess-2.1.0/docs/README.md +0 -238
  74. exness_data_preprocess-2.1.0/docs/REPOSITORY_REFACTORING_PLAN.yaml +0 -375
  75. exness_data_preprocess-2.1.0/docs/RESEARCH_PATTERNS.md +0 -236
  76. exness_data_preprocess-2.1.0/docs/TRADING_HOURS_RESEARCH.md +0 -1690
  77. exness_data_preprocess-2.1.0/docs/UNIFIED_DUCKDB_PLAN_v2.md +0 -641
  78. exness_data_preprocess-2.1.0/docs/archive/PHASE4_DRY_RUN_CONFIG_PLAN.yaml +0 -362
  79. exness_data_preprocess-2.1.0/docs/archive/PHASE7_v1.5.0_REFACTORING_PLAN.md +0 -585
  80. exness_data_preprocess-2.1.0/docs/archive/PHASE7_v1.6.0_REFACTORING_PROGRESS.md +0 -1164
  81. exness_data_preprocess-2.1.0/docs/archive/PYDANTIC_REFACTORING_PLAN_v0.2.0_COMPLETE.md +0 -985
  82. exness_data_preprocess-2.1.0/docs/archive/PYDANTIC_REFACTORING_STATUS_v0.2.0_COMPLETE.md +0 -221
  83. exness_data_preprocess-2.1.0/docs/optimization/OPTIMIZATION_OPPORTUNITIES_2025-10-18.md +0 -558
  84. exness_data_preprocess-2.1.0/docs/phases/PHASE2_SESSION_VECTORIZATION_PLAN.yaml +0 -268
  85. exness_data_preprocess-2.1.0/docs/phases/PHASE3_SQL_GAP_DETECTION_PLAN.yaml +0 -298
  86. exness_data_preprocess-2.1.0/docs/releases/RELEASE_NOTES.md +0 -21
  87. exness_data_preprocess-2.1.0/docs/releases/RELEASE_NOTES_SHORT.md +0 -40
  88. exness_data_preprocess-2.1.0/docs/setup/GITHUB_PYPI_SETUP.md +0 -372
  89. exness_data_preprocess-2.1.0/docs/validation/E2E_VALIDATION_RESULTS_v1.6.0.md +0 -318
  90. exness_data_preprocess-2.1.0/docs/validation/SPIKE_TEST_RESULTS_PHASE1_2025-10-18.md +0 -279
  91. exness_data_preprocess-2.1.0/docs/validation/SPIKE_TEST_RESULTS_PHASE2_2025-10-18.md +0 -352
  92. exness_data_preprocess-2.1.0/examples/basic_usage.py +0 -216
  93. exness_data_preprocess-2.1.0/examples/batch_processing.py +0 -467
  94. exness_data_preprocess-2.1.0/scripts/migrate_duckdb_to_clickhouse.py +0 -541
  95. exness_data_preprocess-2.1.0/scripts/validate_migration_data.py +0 -632
  96. exness_data_preprocess-2.1.0/src/exness_data_preprocess/config.py +0 -123
  97. exness_data_preprocess-2.1.0/tests/README.md +0 -167
  98. exness_data_preprocess-2.1.0/tests/conftest.py +0 -79
  99. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/LICENSE +0 -0
  100. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-09-codebase-pruning.md +0 -0
  101. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-09-exness-clickhouse-migration.md +0 -0
  102. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md +0 -0
  103. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-10-clickhouse-pydantic-config.md +0 -0
  104. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-11-duckdb-removal-clickhouse.md +0 -0
  105. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-after.dot +0 -0
  106. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-arch.dot +0 -0
  107. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-before.dot +0 -0
  108. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-09-codebase-pruning/spec.md +0 -0
  109. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-09-exness-clickhouse-migration/spec.md +0 -0
  110. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-10-clickhouse-e2e-validation-pipeline/spec.md +0 -0
  111. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-10-clickhouse-pydantic-config/spec.md +0 -0
  112. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
  113. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
  114. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
  115. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
  116. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
  117. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
  118. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
  119. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/hurdle-model/hurdle_decomposition.png +0 -0
  120. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/cv_mode_comparison.png +0 -0
  121. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/distribution_overlay.png +0 -0
  122. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/signal_quality_comparison.png +0 -0
  123. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/variance_decomposition.png +0 -0
  124. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
  125. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
  126. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +0 -0
  127. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
  128. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/README.md +0 -0
  129. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/findings/baseline-sep2024-comprehensive-summary.md +0 -0
  130. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/findings/phase2-mean-reversion-report.md +0 -0
  131. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/findings/phase3-volatility-model-report.md +0 -0
  132. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/01_mean_reversion_analysis.py +0 -0
  133. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/02_volatility_model_simple.py +0 -0
  134. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/03_liquidity_crisis_detection.py +0 -0
  135. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/04_regime_detection_analysis.py +0 -0
  136. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase1_data_validation.py +0 -0
  137. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase2_mean_reversion.py +0 -0
  138. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase3_volatility_model.py +0 -0
  139. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase4_statistical_tests.py +0 -0
  140. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias.py +0 -0
  141. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias_v1.0.1.py +0 -0
  142. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6a_interval_analysis.py +0 -0
  143. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6b_price_clustering.py +0 -0
  144. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6c_combined_pattern.py +0 -0
  145. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/diagnostic_burst_decay.py +0 -0
  146. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_interactive_dashboard.py +0 -0
  147. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_lightweight_dashboard.py +0 -0
  148. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/prepare_visualization_data.py +0 -0
  149. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_base.py +0 -0
  150. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_gap_detector.py +0 -0
  151. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/exchanges.py +0 -0
  152. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/session_detector.py +0 -0
  153. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/tick_loader.py +0 -0
  154. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/__init__.py +0 -0
  155. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_models.py +0 -0
  156. {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_types.py +0 -0
@@ -0,0 +1,26 @@
1
+ # Dependency update PRs. Replaces the scheduled pre-commit-autoupdate workflow.
2
+ # No `uv` entry: uv.lock is not tracked and this is a library, so the only possible updates
3
+ # would be raising the `>=` floors in pyproject.toml, which narrows what downstream users can install.
4
+ version: 2
5
+ updates:
6
+ - package-ecosystem: "pre-commit"
7
+ directory: "/"
8
+ schedule:
9
+ interval: "weekly"
10
+ commit-message:
11
+ prefix: "chore(deps)"
12
+ - package-ecosystem: "github-actions"
13
+ directory: "/"
14
+ schedule:
15
+ interval: "weekly"
16
+ commit-message:
17
+ prefix: "ci(deps)"
18
+ - package-ecosystem: "npm"
19
+ directory: "/"
20
+ schedule:
21
+ interval: "monthly"
22
+ commit-message:
23
+ prefix: "chore(deps)"
24
+ groups:
25
+ semantic-release:
26
+ patterns: ["*"]
@@ -10,9 +10,9 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
 
12
12
  steps:
13
- - uses: actions/checkout@v4
13
+ - uses: actions/checkout@v7
14
14
 
15
- - uses: actions/setup-python@v5
15
+ - uses: actions/setup-python@v7
16
16
  with:
17
17
  python-version: '3.12'
18
18
 
@@ -23,7 +23,7 @@ jobs:
23
23
  run: python -m build
24
24
 
25
25
  - name: Upload distribution artifacts
26
- uses: actions/upload-artifact@v4
26
+ uses: actions/upload-artifact@v7
27
27
  with:
28
28
  name: dist
29
29
  path: dist/
@@ -41,7 +41,7 @@ jobs:
41
41
 
42
42
  steps:
43
43
  - name: Download distribution artifacts
44
- uses: actions/download-artifact@v4
44
+ uses: actions/download-artifact@v8
45
45
  with:
46
46
  name: dist
47
47
  path: dist/
@@ -41,7 +41,6 @@ venv.bak/
41
41
  .ipynb_checkpoints
42
42
 
43
43
  # pyenv
44
- .python-version
45
44
 
46
45
  # Environments
47
46
  .env.local
@@ -106,7 +105,6 @@ node_modules/
106
105
 
107
106
  # Link checking (lychee)
108
107
  .lychee*
109
- .lycheecache
110
108
 
111
109
  # DBeaver (credentials in generated JSON)
112
110
  # ADR: /docs/adr/2025-12-10-clickhouse-pydantic-config.md
@@ -116,3 +114,7 @@ node_modules/
116
114
  # Claude Code local files
117
115
  .claude/
118
116
  .lint-relative-paths-results.txt
117
+
118
+ # moon (task runner) local cache
119
+ .moon/cache/
120
+ .moon/docker/
@@ -0,0 +1,2 @@
1
+ # yaml-language-server: $schema=https://moonrepo.dev/schemas/toolchain.json
2
+ # No moon-managed toolchains: tasks run on the `system` platform (uv from proto on PATH).
@@ -0,0 +1,8 @@
1
+ # yaml-language-server: $schema=https://moonrepo.dev/schemas/workspace.json
2
+ # moon runs this repo's tasks; proto (.prototools) pins the tools.
3
+ projects:
4
+ repo: '.'
5
+
6
+ vcs:
7
+ client: 'git'
8
+ defaultBranch: 'main'
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/commitizen-tools/commitizen
3
- rev: v4.9.1
3
+ rev: v4.19.2
4
4
  hooks:
5
5
  - id: commitizen
6
6
  stages: [commit-msg]
@@ -8,7 +8,7 @@ repos:
8
8
  stages: [pre-push]
9
9
  args: [--rev-range, origin/main..HEAD]
10
10
  - repo: https://github.com/pre-commit/pre-commit-hooks
11
- rev: v4.4.0
11
+ rev: v6.0.0
12
12
  hooks:
13
13
  - id: trailing-whitespace
14
14
  - id: end-of-file-fixer
@@ -17,8 +17,8 @@ repos:
17
17
  - id: check-merge-conflict
18
18
  - id: debug-statements
19
19
  - repo: https://github.com/astral-sh/ruff-pre-commit
20
- rev: v0.13.0
20
+ rev: v0.17.1
21
21
  hooks:
22
- - id: ruff
22
+ - id: ruff-check
23
23
  args: [--fix, --unsafe-fixes]
24
24
  - id: ruff-format
@@ -0,0 +1,5 @@
1
+ # proto — repo-local toolchain versions.
2
+ # uv owns Python: the interpreter version is .python-version, and uv.toml makes uv use only its own
3
+ # managed build. ClickHouse comes from the system PATH (e.g. Homebrew), not from proto.
4
+ uv = "latest"
5
+ moon = "2.6.1"
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,24 @@
1
+ # semantic-release configuration for Python project
2
+ # Uses @semantic-release/exec instead of @semantic-release/npm
3
+ branches:
4
+ - main
5
+
6
+ plugins:
7
+ - "@semantic-release/commit-analyzer"
8
+ - "@semantic-release/release-notes-generator"
9
+ - "@semantic-release/changelog"
10
+ - - "@semantic-release/exec"
11
+ # `uv version --frozen` rewrites [project].version in pyproject.toml only (uv.lock is not tracked).
12
+ # __version__ is read from the installed distribution metadata, so nothing else needs bumping.
13
+ # The release narrative is a tracked file written in the PR before the release; without it
14
+ # there is no release. After @semantic-release/github publishes, the body is rebuilt as
15
+ # narrative + generated section (idempotent; see scripts/publish-release-notes.sh).
16
+ - verifyReleaseCmd: "test -s docs/release-notes/${nextRelease.version}.md || { echo 'missing docs/release-notes/${nextRelease.version}.md' >&2; exit 1; }"
17
+ prepareCmd: "uv version ${nextRelease.version} --frozen"
18
+ successCmd: "bash scripts/publish-release-notes.sh ${nextRelease.version}"
19
+ - - "@semantic-release/git"
20
+ - assets:
21
+ - pyproject.toml
22
+ - CHANGELOG.md
23
+ message: "chore(release): bump version ${lastRelease.version} → ${nextRelease.version} [skip ci]"
24
+ - "@semantic-release/github"
@@ -1,3 +1,34 @@
1
+ # [3.0.0](https://github.com/terrylica/exness-data-preprocess/compare/v2.1.1...v3.0.0) (2026-10-19)
2
+
3
+
4
+ * fix!: keep distinct ticks that share a timestamp; read with FINAL; make force_redownload work ([e7ac22b](https://github.com/terrylica/exness-data-preprocess/commit/e7ac22ba659c7eb1c03f3ad1f223d23bff515304)), closes [#23](https://github.com/terrylica/exness-data-preprocess/issues/23)
5
+ * refactor!: remove the unused config module, ExnessDataProcessor(config=...) and pyyaml ([b43be4a](https://github.com/terrylica/exness-data-preprocess/commit/b43be4a09702c6135a41b27256345952c83e6708)), closes [#21](https://github.com/terrylica/exness-data-preprocess/issues/21)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * apply review findings (inclusive end_date day, cursor pruning, scoped ASOF build side, forced re-download) ([dd3a0b3](https://github.com/terrylica/exness-data-preprocess/commit/dd3a0b373689116d600f43ff489e3076a66eb13e)), closes [#23](https://github.com/terrylica/exness-data-preprocess/issues/23) [#24](https://github.com/terrylica/exness-data-preprocess/issues/24)
11
+ * **query:** bind datetime parameters as DateTime64(6, 'UTC') so filters are not shifted on non-UTC servers ([1f88c41](https://github.com/terrylica/exness-data-preprocess/commit/1f88c41b372306bb5e929d131e1338d71e9ac539)), closes [#24](https://github.com/terrylica/exness-data-preprocess/issues/24)
12
+ * report real storage_bytes and OHLC bar counts instead of placeholders ([a970be5](https://github.com/terrylica/exness-data-preprocess/commit/a970be5f75b8dbddff890e92a628388261f10026)), closes [#19](https://github.com/terrylica/exness-data-preprocess/issues/19)
13
+
14
+
15
+ ### BREAKING CHANGES
16
+
17
+ * raw_spread_ticks and standard_ticks gain a `seq` column and sort by (instrument, timestamp, seq); existing tables are migrated in place by ensure_schema() (re-download months with update_data(..., force_redownload=True) to restore ticks the old key collapsed). CursorResult.next_cursor is now an opaque "<timestamp>#<seq>" string rather than a plain timestamp. Tick counts, tick queries and OHLC generation read with FINAL.
18
+ * ExnessDataProcessor() no longer accepts a `config` argument, the exness_data_preprocess.config module (ConfigModel, load_config, get_default_config_path) is removed, and PyYAML is no longer installed as a dependency. Configure through environment variables (CLICKHOUSE_*, EXNESS_DOWNLOAD_DIR).
19
+
20
+ ## [2.1.1](https://github.com/terrylica/exness-data-preprocess/compare/v2.1.0...v2.1.1) (2026-10-19)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **clickhouse:** resolve the binary from PATH instead of a dead mise shim ([2e5cbe0](https://github.com/terrylica/exness-data-preprocess/commit/2e5cbe0bd3c51f0d95d6c1baf583a98727a12d36))
26
+ * **e2e:** apply review findings (memory cap, isolated downloads, marker selection, signals) ([ec2d8aa](https://github.com/terrylica/exness-data-preprocess/commit/ec2d8aaea4cc1f2ca7bb5527208345ad2d526a4b)), closes [#6](https://github.com/terrylica/exness-data-preprocess/issues/6)
27
+ * **processor:** bootstrap exness database before first get_client() call ([0cc55a4](https://github.com/terrylica/exness-data-preprocess/commit/0cc55a43fa482e48870f4685d170f2b2ff1aa941))
28
+ * **release:** bump the version with `uv version`, read __version__ from metadata ([aa86693](https://github.com/terrylica/exness-data-preprocess/commit/aa866932bb41517629a51186af740555cc959774)), closes [#4](https://github.com/terrylica/exness-data-preprocess/issues/4)
29
+ * **scripts:** resolve ruff lint errors and formatting issues ([68d939f](https://github.com/terrylica/exness-data-preprocess/commit/68d939f5fafdd2692b5ef6f1ad4e5811e3364a87))
30
+ * **types:** make `moon run repo:check` green (mypy 15 errors to 0) ([79b2259](https://github.com/terrylica/exness-data-preprocess/commit/79b2259af62e4d5086016669d8dba825fd69dbd9)), closes [#7](https://github.com/terrylica/exness-data-preprocess/issues/7)
31
+
1
32
  # [2.1.0](https://github.com/terrylica/exness-data-preprocess/compare/v2.0.0...v2.1.0) (2025-12-28)
2
33
 
3
34
 
@@ -0,0 +1,31 @@
1
+ # CLAUDE.md
2
+
3
+ `exness-data-preprocess`: downloads Exness forex ticks from ticks.ex2archive.com into ClickHouse (database `exness`: `raw_spread_ticks`, `standard_ticks`, `ohlc_1m`, plus `exchange_sessions` and `holidays`) and serves tick and OHLC queries. Entry point: `ExnessDataProcessor`. User docs: [README.md](/README.md); index of the rest: [docs/README.md](/docs/README.md).
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ uv sync --dev
9
+ moon run repo:check # offline gate: ruff check + ruff format --check + mypy + pytest
10
+ moon run repo:e2e # hermetic: throwaway ClickHouse on free ports, pytest with ClickHouse required,
11
+ # validate_clickhouse.py all (incl. a real EURUSD download), examples/basic_usage.py
12
+ moon run repo:build # sdist + wheel into dist/
13
+ ```
14
+
15
+ `repo:validate`, `repo:clickhouse-start` / `repo:clickhouse-stop` and `repo:validate-clickhouse-*` target a persistent local server on :8123 (see [moon.yml](/moon.yml)).
16
+
17
+ ## Toolchain
18
+
19
+ - proto pins uv (`.prototools`); uv owns Python. `.python-version` pins 3.11 and wins. If `UV_PYTHON` is exported in the shell, it overrides the pin, so run `env -u UV_PYTHON uv ...` or the venv is built on the wrong interpreter.
20
+ - Releases: write `docs/release-notes/<next>.md` (narrative paragraph + Keep a Changelog bullets, one line each) in the PR before releasing; semantic-release (`npm run release`) refuses to release without it, runs `uv version <next> --frozen`, and `scripts/publish-release-notes.sh` rebuilds the GitHub Release body as narrative + generated section. pyproject.toml is the only place the version lives; `__version__` reads installed metadata. Publishing is `.github/workflows/publish.yml` (PyPI Trusted Publishing on a GitHub Release), the only publish path.
21
+ - Dependency update PRs come from `.github/dependabot.yml`. No other CI runs in Actions; gates are local.
22
+
23
+ ## Invariants
24
+
25
+ - `ensure_database_bootstrap()` must run before the first `get_client()` that binds the `exness` database (`tests/test_database_bootstrap_order.py`).
26
+ - Insert DataFrames with `client.insert_df(...)`, never `client.insert(data=df)` (that takes row sequences).
27
+ - Tables are ReplacingMergeTree. Tick tables dedupe on `(instrument, timestamp, seq)`: `seq` (`assign_tick_seq`) numbers same-timestamp ticks in source order, so distinct ticks sharing a timestamp are kept and re-inserting a month is idempotent. Duplicates only collapse at merge time, so every read whose answer depends on duplicates (counts, tick/OHLC rows, the OHLC build) uses `FINAL`; keep it that way.
28
+ - Datetime query parameters are typed `DateTime64(6, 'UTC')`, never bare `DateTime64`: a bare one parses naive text in the server's time zone and shifts every filter on a non-UTC server. `repo:e2e` runs its server in America/New_York to catch this.
29
+ - ClickHouse-backed tests are marked `clickhouse` or use `processor_with_clickhouse` (fixture users get the marker at collection, so `-m clickhouse` selects them); `conftest.py` skips them with the probe's reason unless `EXNESS_REQUIRE_CLICKHOUSE=1`. A server that holds :8123 but rejects the credentials (el02's shared system ClickHouse) counts as unavailable. Use `repo:e2e`, not that server.
30
+ - `gapless-crypto-clickhouse` also uses localhost:8123. `clickhouse-stop` only stops the PID in this repo's pidfile.
31
+ - ADRs and design specs under `docs/adr/` and `docs/design/` are historical records: add new ones, don't rewrite old ones.
@@ -0,0 +1,32 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/terrylica/exness-data-preprocess.git
7
+ cd exness-data-preprocess
8
+ uv sync --dev # Python version comes from .python-version
9
+ ```
10
+
11
+ You also need [moon](https://moonrepo.dev/) (pinned through proto) for the task runner and a `clickhouse` binary on `PATH` for the end-to-end run.
12
+
13
+ ## Before you open a pull request
14
+
15
+ ```bash
16
+ moon run repo:check # ruff check, ruff format --check, mypy, pytest
17
+ moon run repo:e2e # throwaway ClickHouse + full pytest + validate checks + examples
18
+ ```
19
+
20
+ Both gates run locally; GitHub Actions only publishes releases and runs Dependabot. See [tests/README.md](/tests/README.md) for how ClickHouse-backed tests are selected and skipped.
21
+
22
+ ## Commits and releases
23
+
24
+ Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `perf:`, `chore:`, `ci:`); the commitizen pre-commit hook checks them (`uv run pre-commit install --hook-type commit-msg --hook-type pre-push`). semantic-release derives the next version and the changelog from them, so never edit the version or `CHANGELOG.md` by hand.
25
+
26
+ ## Reporting issues
27
+
28
+ Include the package version (`uv pip show exness-data-preprocess`), Python version, OS, a minimal reproduction, and the full traceback.
29
+
30
+ ## License
31
+
32
+ Contributions are licensed under the MIT License.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: exness-data-preprocess
3
- Version: 2.1.0
3
+ Version: 3.0.0
4
4
  Summary: Professional Exness forex tick data preprocessing with ClickHouse backend. Provides efficient storage with lossless precision and direct queryability.
5
5
  Project-URL: Homepage, https://github.com/terrylica/exness-data-preprocess
6
6
  Project-URL: Documentation, https://github.com/terrylica/exness-data-preprocess#readme
@@ -26,16 +26,15 @@ Classifier: Topic :: Office/Business :: Financial :: Investment
26
26
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
27
27
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
28
  Requires-Python: >=3.11
29
- Requires-Dist: clickhouse-connect>=0.7.0
29
+ Requires-Dist: clickhouse-connect>=1.11.0
30
30
  Requires-Dist: exchange-calendars>=4.5.6
31
31
  Requires-Dist: pandas>=2.0.0
32
32
  Requires-Dist: pydantic>=2.0.0
33
- Requires-Dist: pyyaml>=6.0.0
34
33
  Provides-Extra: examples
35
34
  Requires-Dist: tqdm>=4.65.0; extra == 'examples'
36
35
  Description-Content-Type: text/markdown
37
36
 
38
- # exness-data-preprocess v2.0.0
37
+ # exness-data-preprocess
39
38
 
40
39
  Forex tick data preprocessing with ClickHouse backend. Downloads, stores, and queries tick data from Exness public repository.
41
40
 
@@ -83,16 +82,16 @@ import exness_data_preprocess as edp
83
82
  # Context manager (recommended)
84
83
  with edp.ExnessDataProcessor() as processor:
85
84
  # Query ticks
86
- df = processor.query_ticks('EURUSD', 'raw_spread', '2024-01-01', '2024-01-31')
85
+ df = processor.query_ticks("EURUSD", "raw_spread", "2024-01-01", "2024-01-31")
87
86
 
88
87
  # Query OHLC
89
- df = processor.query_ohlc('EURUSD', '1m', '2024-01-01', '2024-01-31')
88
+ df = processor.query_ohlc("EURUSD", "1m", "2024-01-01", "2024-01-31")
90
89
 
91
90
  # Get coverage info
92
- cov = processor.get_data_coverage('EURUSD')
91
+ cov = processor.get_data_coverage("EURUSD")
93
92
 
94
93
  # Download new data (incremental)
95
- result = processor.update_data('EURUSD', start_date='2022-01-01')
94
+ result = processor.update_data("EURUSD", start_date="2022-01-01")
96
95
  ```
97
96
 
98
97
  ### API Methods
@@ -108,19 +107,19 @@ with edp.ExnessDataProcessor() as processor:
108
107
 
109
108
  ```python
110
109
  # UpdateResult
111
- result.months_added # int: months downloaded
112
- result.raw_ticks_added # int: raw spread ticks added
113
- result.standard_ticks_added # int: standard ticks added
114
- result.ohlc_bars # int: OHLC bars generated
115
- result.storage_bytes # int: storage used
110
+ result.months_added # int: months downloaded
111
+ result.raw_ticks_added # int: raw spread ticks added
112
+ result.standard_ticks_added # int: standard ticks added
113
+ result.ohlc_bars # int: OHLC bars generated
114
+ result.storage_bytes # int: storage used
116
115
 
117
116
  # CoverageInfo
118
- cov.raw_spread_ticks # int: total raw spread ticks
119
- cov.standard_ticks # int: total standard ticks
120
- cov.ohlc_bars # int: total OHLC bars
121
- cov.earliest_date # str: earliest timestamp
122
- cov.latest_date # str: latest timestamp
123
- cov.storage_bytes # int: storage used
117
+ cov.raw_spread_ticks # int: total raw spread ticks
118
+ cov.standard_ticks # int: total standard ticks
119
+ cov.ohlc_bars # int: total OHLC bars
120
+ cov.earliest_date # str: earliest timestamp
121
+ cov.latest_date # str: latest timestamp
122
+ cov.storage_bytes # int: storage used
124
123
  ```
125
124
 
126
125
  ## Direct SQL Access
@@ -170,8 +169,8 @@ ORDER BY ts"
170
169
  | ---------- | ---------------------- | ------------------- |
171
170
  | instrument | LowCardinality(String) | - |
172
171
  | timestamp | DateTime64(6, 'UTC') | DoubleDelta, LZ4 |
173
- | bid | Float64 | Gorilla(8), ZSTD(1) |
174
- | ask | Float64 | Gorilla(8), ZSTD(1) |
172
+ | bid | Float64 | Gorilla, ZSTD |
173
+ | ask | Float64 | Gorilla, ZSTD |
175
174
 
176
175
  ### OHLC Table
177
176
 
@@ -218,8 +217,8 @@ uv run mypy src/
218
217
  ## Documentation
219
218
 
220
219
  - [ClickHouse User Guide](/docs/CLICKHOUSE_USER_GUIDE.md) - Detailed ClickHouse usage
221
- - [Database Schema](/docs/DATABASE_SCHEMA.md) - 27-column OHLC specification
222
- - [Module Architecture](/docs/MODULE_ARCHITECTURE.md) - 13 modules with SLOs
220
+ - [Schema](#schema) - summary above; the DDL in [`clickhouse_manager.py`](/src/exness_data_preprocess/clickhouse_manager.py) is authoritative
221
+ - [Exness Data Sources](/docs/EXNESS_DATA_SOURCES.md) - archive layout and variants
223
222
  - [ADR: ClickHouse Migration](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) - Architecture decision
224
223
 
225
224
  ## License
@@ -1,4 +1,4 @@
1
- # exness-data-preprocess v2.0.0
1
+ # exness-data-preprocess
2
2
 
3
3
  Forex tick data preprocessing with ClickHouse backend. Downloads, stores, and queries tick data from Exness public repository.
4
4
 
@@ -46,16 +46,16 @@ import exness_data_preprocess as edp
46
46
  # Context manager (recommended)
47
47
  with edp.ExnessDataProcessor() as processor:
48
48
  # Query ticks
49
- df = processor.query_ticks('EURUSD', 'raw_spread', '2024-01-01', '2024-01-31')
49
+ df = processor.query_ticks("EURUSD", "raw_spread", "2024-01-01", "2024-01-31")
50
50
 
51
51
  # Query OHLC
52
- df = processor.query_ohlc('EURUSD', '1m', '2024-01-01', '2024-01-31')
52
+ df = processor.query_ohlc("EURUSD", "1m", "2024-01-01", "2024-01-31")
53
53
 
54
54
  # Get coverage info
55
- cov = processor.get_data_coverage('EURUSD')
55
+ cov = processor.get_data_coverage("EURUSD")
56
56
 
57
57
  # Download new data (incremental)
58
- result = processor.update_data('EURUSD', start_date='2022-01-01')
58
+ result = processor.update_data("EURUSD", start_date="2022-01-01")
59
59
  ```
60
60
 
61
61
  ### API Methods
@@ -71,19 +71,19 @@ with edp.ExnessDataProcessor() as processor:
71
71
 
72
72
  ```python
73
73
  # UpdateResult
74
- result.months_added # int: months downloaded
75
- result.raw_ticks_added # int: raw spread ticks added
76
- result.standard_ticks_added # int: standard ticks added
77
- result.ohlc_bars # int: OHLC bars generated
78
- result.storage_bytes # int: storage used
74
+ result.months_added # int: months downloaded
75
+ result.raw_ticks_added # int: raw spread ticks added
76
+ result.standard_ticks_added # int: standard ticks added
77
+ result.ohlc_bars # int: OHLC bars generated
78
+ result.storage_bytes # int: storage used
79
79
 
80
80
  # CoverageInfo
81
- cov.raw_spread_ticks # int: total raw spread ticks
82
- cov.standard_ticks # int: total standard ticks
83
- cov.ohlc_bars # int: total OHLC bars
84
- cov.earliest_date # str: earliest timestamp
85
- cov.latest_date # str: latest timestamp
86
- cov.storage_bytes # int: storage used
81
+ cov.raw_spread_ticks # int: total raw spread ticks
82
+ cov.standard_ticks # int: total standard ticks
83
+ cov.ohlc_bars # int: total OHLC bars
84
+ cov.earliest_date # str: earliest timestamp
85
+ cov.latest_date # str: latest timestamp
86
+ cov.storage_bytes # int: storage used
87
87
  ```
88
88
 
89
89
  ## Direct SQL Access
@@ -133,8 +133,8 @@ ORDER BY ts"
133
133
  | ---------- | ---------------------- | ------------------- |
134
134
  | instrument | LowCardinality(String) | - |
135
135
  | timestamp | DateTime64(6, 'UTC') | DoubleDelta, LZ4 |
136
- | bid | Float64 | Gorilla(8), ZSTD(1) |
137
- | ask | Float64 | Gorilla(8), ZSTD(1) |
136
+ | bid | Float64 | Gorilla, ZSTD |
137
+ | ask | Float64 | Gorilla, ZSTD |
138
138
 
139
139
  ### OHLC Table
140
140
 
@@ -181,8 +181,8 @@ uv run mypy src/
181
181
  ## Documentation
182
182
 
183
183
  - [ClickHouse User Guide](/docs/CLICKHOUSE_USER_GUIDE.md) - Detailed ClickHouse usage
184
- - [Database Schema](/docs/DATABASE_SCHEMA.md) - 27-column OHLC specification
185
- - [Module Architecture](/docs/MODULE_ARCHITECTURE.md) - 13 modules with SLOs
184
+ - [Schema](#schema) - summary above; the DDL in [`clickhouse_manager.py`](/src/exness_data_preprocess/clickhouse_manager.py) is authoritative
185
+ - [Exness Data Sources](/docs/EXNESS_DATA_SOURCES.md) - archive layout and variants
186
186
  - [ADR: ClickHouse Migration](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) - Architecture decision
187
187
 
188
188
  ## License
@@ -1,4 +1,4 @@
1
- # ClickHouse User Guide - exness-data-preprocess v2.0.0
1
+ # ClickHouse User Guide - exness-data-preprocess
2
2
 
3
3
  **Package**: `exness-data-preprocess` - Professional forex tick data preprocessing with ClickHouse backend
4
4
 
@@ -17,9 +17,9 @@
17
17
  5. [Querying OHLC Data](#querying-ohlc-data)
18
18
  6. [Data Coverage](#data-coverage)
19
19
  7. [Updating Data](#updating-data)
20
- 8. [26-Column OHLC Schema](#26-column-ohlc-schema)
20
+ 8. [27-Column OHLC Schema](#27-column-ohlc-schema)
21
21
  9. [Direct ClickHouse SQL Patterns](#direct-clickhouse-sql-patterns)
22
- 10. [mise Tasks for ClickHouse](#mise-tasks-for-clickhouse)
22
+ 10. [moon Tasks for ClickHouse](#moon-tasks-for-clickhouse)
23
23
  11. [Environment Configuration](#environment-configuration)
24
24
  12. [Pagination Patterns](#pagination-patterns)
25
25
  13. [Troubleshooting](#troubleshooting)
@@ -66,10 +66,10 @@ processor.close()
66
66
 
67
67
  ```bash
68
68
  # Start ClickHouse server
69
- mise run clickhouse:start
69
+ moon run repo:clickhouse-start
70
70
 
71
71
  # Verify connection
72
- mise run clickhouse:status
72
+ uv run python scripts/validate_clickhouse.py status
73
73
  ```
74
74
 
75
75
  Default connection: `localhost:8123` (HTTP interface)
@@ -183,7 +183,7 @@ df_std = processor.query_ticks(
183
183
  )
184
184
 
185
185
  # Calculate spread statistics
186
- df_std['spread'] = df_std['ask'] - df_std['bid']
186
+ df_std["spread"] = df_std["ask"] - df_std["bid"]
187
187
  print(f"Mean spread: {df_std['spread'].mean() * 10000:.4f} pips")
188
188
  ```
189
189
 
@@ -356,9 +356,9 @@ print(f"Gap months: {', '.join(result.gap_months)}")
356
356
 
357
357
  ---
358
358
 
359
- ## 26-Column OHLC Schema
359
+ ## 27-Column OHLC Schema
360
360
 
361
- The `ohlc_1m` table contains 26 columns organized into categories:
361
+ The `ohlc_1m` table contains 27 columns organized into categories:
362
362
 
363
363
  ### Core OHLC (5 columns)
364
364
 
@@ -542,53 +542,51 @@ ORDER BY instrument;
542
542
 
543
543
  ---
544
544
 
545
- ## mise Tasks for ClickHouse
545
+ ## moon Tasks for ClickHouse
546
546
 
547
547
  ### Server Management
548
548
 
549
549
  ```bash
550
- # Start ClickHouse server (mise-installed)
551
- mise run clickhouse:start
550
+ # Start ClickHouse server (clickhouse binary on PATH)
551
+ moon run repo:clickhouse-start
552
552
 
553
- # Stop ClickHouse server
554
- mise run clickhouse:stop
553
+ # Stop the server this repo started (by pidfile)
554
+ moon run repo:clickhouse-stop
555
555
 
556
556
  # Check connection status
557
- mise run clickhouse:status
558
-
559
- # Fail fast if ClickHouse not running
560
- mise run clickhouse:ensure
557
+ uv run python scripts/validate_clickhouse.py status
561
558
  ```
562
559
 
560
+ The server listens on `localhost:8123`. `gapless-crypto-clickhouse` runs its own local server on the same port with a different data directory, so only one of the two can be up at a time.
561
+
563
562
  ### Validation Tasks
564
563
 
565
564
  ```bash
566
- # Run full E2E validation (requires ClickHouse)
567
- mise run validate
565
+ # Run full local validation: lint + typecheck + tests + build + ClickHouse E2E (requires ClickHouse)
566
+ moon run repo:validate
568
567
 
569
568
  # Validate ClickHouse schema
570
- mise run validate:clickhouse-schema
569
+ moon run repo:validate-clickhouse-schema
571
570
 
572
571
  # Validate data queries
573
- mise run validate:clickhouse-data
572
+ moon run repo:validate-clickhouse-data
574
573
 
575
574
  # Validate pagination
576
- mise run validate:clickhouse-pagination
575
+ moon run repo:validate-clickhouse-pagination
577
576
 
578
577
  # Validate OHLC queries
579
- mise run validate:clickhouse-ohlc
578
+ moon run repo:validate-clickhouse-ohlc
580
579
  ```
581
580
 
582
581
  ### Quick Reference
583
582
 
584
- | Task | Description |
585
- | ------------------------------ | ------------------------------- |
586
- | `mise run clickhouse:start` | Start mise-installed ClickHouse |
587
- | `mise run clickhouse:stop` | Stop ClickHouse server |
588
- | `mise run clickhouse:status` | Check Python client connection |
589
- | `mise run clickhouse:ensure` | Fail fast if not running |
590
- | `mise run validate` | Full E2E validation pipeline |
591
- | `mise run validate:clickhouse` | All ClickHouse validations |
583
+ | Task | Description |
584
+ | ----------------------------------- | ------------------------------------------- |
585
+ | `moon run repo:clickhouse-start` | Start the ClickHouse server found on PATH |
586
+ | `moon run repo:clickhouse-stop` | Stop the server this repo started |
587
+ | `moon run repo:check` | Offline gate: lint + typecheck + tests |
588
+ | `moon run repo:validate` | Full E2E validation pipeline |
589
+ | `moon run repo:validate-clickhouse` | All ClickHouse validations |
592
590
 
593
591
  ---
594
592
 
@@ -605,18 +603,7 @@ mise run validate:clickhouse-ohlc
605
603
  | `CLICKHOUSE_PASSWORD` | (empty) | Password |
606
604
  | `CLICKHOUSE_DATABASE` | `exness` | Default database |
607
605
 
608
- ### mise Configuration
609
-
610
- Configuration is defined in `.mise.toml`:
611
-
612
- ```toml
613
- [env]
614
- CLICKHOUSE_NAME = "exness-clickhouse-local"
615
- CLICKHOUSE_MODE = "local"
616
- CLICKHOUSE_HOST = "localhost"
617
- CLICKHOUSE_PORT = "8123"
618
- CLICKHOUSE_DATABASE = "exness"
619
- ```
606
+ The variables above are read with these defaults, so local mode needs no configuration.
620
607
 
621
608
  ---
622
609
 
@@ -690,7 +677,7 @@ ERROR: ClickHouse not running on port 8123
690
677
  **Solution**:
691
678
 
692
679
  ```bash
693
- mise run clickhouse:start
680
+ moon run repo:clickhouse-start
694
681
  ```
695
682
 
696
683
  ### Connection Refused
@@ -715,7 +702,7 @@ If queries return empty DataFrames:
715
702
 
716
703
  ### Schema Mismatch
717
704
 
718
- If OHLC columns don't match expected 26-column schema:
705
+ If OHLC columns don't match expected 27-column schema:
719
706
 
720
707
  ```bash
721
708
  # Regenerate OHLC for instrument
@@ -203,6 +203,7 @@ done
203
203
  import requests
204
204
  from pathlib import Path
205
205
 
206
+
206
207
  def download_exness_variant(pair: str, year: int, month: int, variant: str = "") -> Path:
207
208
  """
208
209
  Download Exness tick data for specific variant.
@@ -224,13 +225,14 @@ def download_exness_variant(pair: str, year: int, month: int, variant: str = "")
224
225
  response = requests.get(url, stream=True)
225
226
  response.raise_for_status()
226
227
 
227
- with open(output, 'wb') as f:
228
+ with open(output, "wb") as f:
228
229
  for chunk in response.iter_content(chunk_size=8192):
229
230
  f.write(chunk)
230
231
 
231
232
  print(f"✅ Downloaded: {output} ({output.stat().st_size / 1024 / 1024:.2f} MB)")
232
233
  return output
233
234
 
235
+
234
236
  # Example: Phase7 dual-variant download
235
237
  raw_spread = download_exness_variant("EURUSD", 2024, 9, "Raw_Spread")
236
238
  standard = download_exness_variant("EURUSD", 2024, 9)