exness-data-preprocess 2.0.0__tar.gz → 2.1.1__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 (154) hide show
  1. exness_data_preprocess-2.1.1/.github/dependabot.yml +26 -0
  2. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.gitignore +8 -2
  3. exness_data_preprocess-2.1.1/.moon/toolchain.yml +2 -0
  4. exness_data_preprocess-2.1.1/.moon/workspace.yml +8 -0
  5. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.pre-commit-config.yaml +4 -4
  6. exness_data_preprocess-2.1.1/.prototools +5 -0
  7. exness_data_preprocess-2.1.1/.python-version +1 -0
  8. exness_data_preprocess-2.1.1/.releaserc.yml +24 -0
  9. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/CHANGELOG.md +25 -0
  10. exness_data_preprocess-2.1.1/CLAUDE.md +30 -0
  11. exness_data_preprocess-2.1.1/CONTRIBUTING.md +32 -0
  12. exness_data_preprocess-2.1.1/PKG-INFO +227 -0
  13. exness_data_preprocess-2.1.1/README.md +190 -0
  14. exness_data_preprocess-2.1.1/docs/CLICKHOUSE_USER_GUIDE.md +742 -0
  15. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/EXNESS_DATA_SOURCES.md +12 -36
  16. exness_data_preprocess-2.1.1/docs/README.md +31 -0
  17. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-exness-clickhouse-migration.md +1 -1
  18. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-pydantic-config.md +2 -3
  19. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-11-duckdb-removal-clickhouse.md +0 -2
  20. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-11-duckdb-removal-clickhouse/spec.md +5 -14
  21. exness_data_preprocess-2.1.1/docs/release-notes/2.1.1.md +24 -0
  22. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md +51 -35
  23. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/README.md +11 -9
  24. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +21 -17
  25. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/README.md +7 -8
  26. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +71 -60
  27. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +9 -2
  28. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +4 -4
  29. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/04-discoveries-and-plan-evolution.md +7 -7
  30. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/README.md +17 -17
  31. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/findings/phase4-5-statistical-tests-survivorship-report.md +3 -2
  32. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +10 -10
  33. exness_data_preprocess-2.1.1/examples/basic_usage.py +65 -0
  34. exness_data_preprocess-2.1.1/moon.yml +77 -0
  35. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/package.json +4 -0
  36. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/pyproject.toml +3 -6
  37. exness_data_preprocess-2.1.1/scripts/clickhouse-start.sh +60 -0
  38. exness_data_preprocess-2.1.1/scripts/clickhouse-stop.sh +52 -0
  39. exness_data_preprocess-2.1.1/scripts/e2e-ephemeral.sh +147 -0
  40. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/scripts/generate_dbeaver_config.py +2 -3
  41. exness_data_preprocess-2.1.1/scripts/publish-release-notes.sh +49 -0
  42. exness_data_preprocess-2.1.1/scripts/smoke_install.sh +16 -0
  43. exness_data_preprocess-2.1.1/scripts/validate_clickhouse.py +185 -0
  44. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/__init__.py +5 -2
  45. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_client.py +9 -4
  46. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_manager.py +76 -20
  47. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_ohlc_generator.py +14 -28
  48. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_query_engine.py +10 -10
  49. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/downloader.py +8 -1
  50. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/models.py +13 -11
  51. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/processor.py +53 -12
  52. exness_data_preprocess-2.1.1/tests/README.md +28 -0
  53. exness_data_preprocess-2.1.1/tests/conftest.py +94 -0
  54. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_basic.py +3 -23
  55. exness_data_preprocess-2.1.1/tests/test_database_bootstrap_order.py +90 -0
  56. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_functional_regression.py +1 -23
  57. exness_data_preprocess-2.1.1/tests/test_package_structure.py +71 -0
  58. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_processor_pydantic.py +1 -24
  59. exness_data_preprocess-2.1.1/uv.toml +2 -0
  60. exness_data_preprocess-2.0.0/.cz.toml +0 -12
  61. exness_data_preprocess-2.0.0/.github/workflows/ci.yml +0 -25
  62. exness_data_preprocess-2.0.0/.github/workflows/pre-commit-autoupdate.yml +0 -38
  63. exness_data_preprocess-2.0.0/.mise.toml +0 -518
  64. exness_data_preprocess-2.0.0/.releaserc.yml +0 -22
  65. exness_data_preprocess-2.0.0/CLAUDE.md +0 -152
  66. exness_data_preprocess-2.0.0/CONTRIBUTING.md +0 -282
  67. exness_data_preprocess-2.0.0/Makefile +0 -62
  68. exness_data_preprocess-2.0.0/PKG-INFO +0 -584
  69. exness_data_preprocess-2.0.0/README.md +0 -547
  70. exness_data_preprocess-2.0.0/cliff-release-notes.toml +0 -131
  71. exness_data_preprocess-2.0.0/cliff.toml +0 -144
  72. exness_data_preprocess-2.0.0/docs/DATABASE_SCHEMA.md +0 -955
  73. exness_data_preprocess-2.0.0/docs/MODULE_ARCHITECTURE.md +0 -1088
  74. exness_data_preprocess-2.0.0/docs/PRIORITY3_CLEANUP_PLAN.yaml +0 -386
  75. exness_data_preprocess-2.0.0/docs/README.md +0 -266
  76. exness_data_preprocess-2.0.0/docs/REPOSITORY_REFACTORING_PLAN.yaml +0 -375
  77. exness_data_preprocess-2.0.0/docs/RESEARCH_PATTERNS.md +0 -236
  78. exness_data_preprocess-2.0.0/docs/TRADING_HOURS_RESEARCH.md +0 -1684
  79. exness_data_preprocess-2.0.0/docs/UNIFIED_DUCKDB_PLAN_v2.md +0 -642
  80. exness_data_preprocess-2.0.0/docs/archive/PHASE4_DRY_RUN_CONFIG_PLAN.yaml +0 -362
  81. exness_data_preprocess-2.0.0/docs/archive/PHASE7_v1.5.0_REFACTORING_PLAN.md +0 -585
  82. exness_data_preprocess-2.0.0/docs/archive/PHASE7_v1.6.0_REFACTORING_PROGRESS.md +0 -1164
  83. exness_data_preprocess-2.0.0/docs/archive/PYDANTIC_REFACTORING_PLAN_v0.2.0_COMPLETE.md +0 -985
  84. exness_data_preprocess-2.0.0/docs/archive/PYDANTIC_REFACTORING_STATUS_v0.2.0_COMPLETE.md +0 -222
  85. exness_data_preprocess-2.0.0/docs/optimization/OPTIMIZATION_OPPORTUNITIES_2025-10-18.md +0 -558
  86. exness_data_preprocess-2.0.0/docs/phases/PHASE2_SESSION_VECTORIZATION_PLAN.yaml +0 -268
  87. exness_data_preprocess-2.0.0/docs/phases/PHASE3_SQL_GAP_DETECTION_PLAN.yaml +0 -298
  88. exness_data_preprocess-2.0.0/docs/releases/RELEASE_NOTES.md +0 -21
  89. exness_data_preprocess-2.0.0/docs/releases/RELEASE_NOTES_SHORT.md +0 -40
  90. exness_data_preprocess-2.0.0/docs/research/gap_detection_implementation_example.py +0 -193
  91. exness_data_preprocess-2.0.0/docs/setup/GITHUB_PYPI_SETUP.md +0 -372
  92. exness_data_preprocess-2.0.0/docs/validation/E2E_VALIDATION_RESULTS_v1.6.0.md +0 -318
  93. exness_data_preprocess-2.0.0/docs/validation/SPIKE_TEST_RESULTS_PHASE1_2025-10-18.md +0 -279
  94. exness_data_preprocess-2.0.0/docs/validation/SPIKE_TEST_RESULTS_PHASE2_2025-10-18.md +0 -352
  95. exness_data_preprocess-2.0.0/examples/basic_usage.py +0 -216
  96. exness_data_preprocess-2.0.0/examples/batch_processing.py +0 -467
  97. exness_data_preprocess-2.0.0/tests/README.md +0 -162
  98. exness_data_preprocess-2.0.0/tests/conftest.py +0 -79
  99. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.github/workflows/publish.yml +0 -0
  100. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/LICENSE +0 -0
  101. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-codebase-pruning.md +0 -0
  102. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md +0 -0
  103. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-after.dot +0 -0
  104. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-arch.dot +0 -0
  105. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-before.dot +0 -0
  106. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-codebase-pruning/spec.md +0 -0
  107. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-exness-clickhouse-migration/spec.md +0 -0
  108. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-10-clickhouse-e2e-validation-pipeline/spec.md +0 -0
  109. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-10-clickhouse-pydantic-config/spec.md +0 -0
  110. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
  111. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
  112. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
  113. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
  114. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
  115. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
  116. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
  117. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/hurdle-model/hurdle_decomposition.png +0 -0
  118. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/cv_mode_comparison.png +0 -0
  119. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/distribution_overlay.png +0 -0
  120. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/signal_quality_comparison.png +0 -0
  121. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/variance_decomposition.png +0 -0
  122. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
  123. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
  124. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
  125. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/findings/baseline-sep2024-comprehensive-summary.md +0 -0
  126. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/findings/phase2-mean-reversion-report.md +0 -0
  127. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/findings/phase3-volatility-model-report.md +0 -0
  128. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/01_mean_reversion_analysis.py +0 -0
  129. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/02_volatility_model_simple.py +0 -0
  130. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/03_liquidity_crisis_detection.py +0 -0
  131. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/04_regime_detection_analysis.py +0 -0
  132. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase1_data_validation.py +0 -0
  133. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase2_mean_reversion.py +0 -0
  134. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase3_volatility_model.py +0 -0
  135. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase4_statistical_tests.py +0 -0
  136. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias.py +0 -0
  137. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias_v1.0.1.py +0 -0
  138. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6a_interval_analysis.py +0 -0
  139. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6b_price_clustering.py +0 -0
  140. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6c_combined_pattern.py +0 -0
  141. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/diagnostic_burst_decay.py +0 -0
  142. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_interactive_dashboard.py +0 -0
  143. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_lightweight_dashboard.py +0 -0
  144. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/prepare_visualization_data.py +0 -0
  145. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/package-lock.json +0 -0
  146. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_base.py +0 -0
  147. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_gap_detector.py +0 -0
  148. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/config.py +0 -0
  149. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/exchanges.py +0 -0
  150. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/session_detector.py +0 -0
  151. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/tick_loader.py +0 -0
  152. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/__init__.py +0 -0
  153. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_models.py +0 -0
  154. {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/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: ["*"]
@@ -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,9 +105,16 @@ 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
113
111
  .dbeaver/
114
112
  .dbeaver-workspace/
113
+
114
+ # Claude Code local files
115
+ .claude/
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,28 @@
1
+ ## [2.1.1](https://github.com/terrylica/exness-data-preprocess/compare/v2.1.0...v2.1.1) (2026-10-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **clickhouse:** resolve the binary from PATH instead of a dead mise shim ([2e5cbe0](https://github.com/terrylica/exness-data-preprocess/commit/2e5cbe0bd3c51f0d95d6c1baf583a98727a12d36))
7
+ * **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)
8
+ * **processor:** bootstrap exness database before first get_client() call ([0cc55a4](https://github.com/terrylica/exness-data-preprocess/commit/0cc55a43fa482e48870f4685d170f2b2ff1aa941))
9
+ * **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)
10
+ * **scripts:** resolve ruff lint errors and formatting issues ([68d939f](https://github.com/terrylica/exness-data-preprocess/commit/68d939f5fafdd2692b5ef6f1ad4e5811e3364a87))
11
+ * **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)
12
+
13
+ # [2.1.0](https://github.com/terrylica/exness-data-preprocess/compare/v2.0.0...v2.1.0) (2025-12-28)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * **clickhouse:** add parameters support to execute_command and fix OHLC generator ([391b939](https://github.com/terrylica/exness-data-preprocess/commit/391b939bd2f7e6baad8945d98fc63e8843799682))
19
+ * **docs:** fix 22 broken links identified by lychee link checker ([a85862e](https://github.com/terrylica/exness-data-preprocess/commit/a85862e7af58bdd9e28eef59f364f56e0df37c24))
20
+
21
+
22
+ ### Features
23
+
24
+ * **scripts:** add DuckDB to ClickHouse migration scripts ([1920903](https://github.com/terrylica/exness-data-preprocess/commit/1920903df113bea810cc3607273d6f2ececd3f4b))
25
+
1
26
  # [2.0.0](https://github.com/terrylica/exness-data-preprocess/compare/v1.2.1...v2.0.0) (2025-12-27)
2
27
 
3
28
 
@@ -0,0 +1,30 @@
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: re-inserting a month is safe; duplicates collapse at merge time, so counts can be higher until a merge or `FINAL`.
28
+ - 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.
29
+ - `gapless-crypto-clickhouse` also uses localhost:8123. `clickhouse-stop` only stops the PID in this repo's pidfile.
30
+ - 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.
@@ -0,0 +1,227 @@
1
+ Metadata-Version: 2.5
2
+ Name: exness-data-preprocess
3
+ Version: 2.1.1
4
+ Summary: Professional Exness forex tick data preprocessing with ClickHouse backend. Provides efficient storage with lossless precision and direct queryability.
5
+ Project-URL: Homepage, https://github.com/terrylica/exness-data-preprocess
6
+ Project-URL: Documentation, https://github.com/terrylica/exness-data-preprocess#readme
7
+ Project-URL: Repository, https://github.com/terrylica/exness-data-preprocess.git
8
+ Project-URL: Bug Tracker, https://github.com/terrylica/exness-data-preprocess/issues
9
+ Project-URL: Source Code, https://github.com/terrylica/exness-data-preprocess
10
+ Project-URL: Changelog, https://github.com/terrylica/exness-data-preprocess/blob/main/CHANGELOG.md
11
+ Author-email: Eon Labs <terry@eonlabs.com>
12
+ Maintainer-email: Terry Li <terry@eonlabs.com>
13
+ License: MIT
14
+ License-File: LICENSE
15
+ Keywords: backtesting,clickhouse,data-engineering,efficient-storage,eurusd,exness,financial-data,forex,forex-data,lossless,microstructure,ohlc,pandas,preprocessing,quantitative-finance,queryable,tick-data,time-series
16
+ Classifier: Development Status :: 3 - Alpha
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: Financial and Insurance Industry
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Office/Business :: Financial :: Investment
26
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
27
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
+ Requires-Python: >=3.11
29
+ Requires-Dist: clickhouse-connect>=0.7.0
30
+ Requires-Dist: exchange-calendars>=4.5.6
31
+ Requires-Dist: pandas>=2.0.0
32
+ Requires-Dist: pydantic>=2.0.0
33
+ Requires-Dist: pyyaml>=6.0.0
34
+ Provides-Extra: examples
35
+ Requires-Dist: tqdm>=4.65.0; extra == 'examples'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # exness-data-preprocess
39
+
40
+ Forex tick data preprocessing with ClickHouse backend. Downloads, stores, and queries tick data from Exness public repository.
41
+
42
+ ## Data Inventory (Validated 2025-12-28)
43
+
44
+ | Instrument | raw_spread_ticks | standard_ticks | ohlc_1m | Date Range |
45
+ | ---------- | ---------------- | -------------- | --------- | ----------------------- |
46
+ | EURUSD | 56,687,313 | 62,203,144 | 1,466,724 | 2022-01-02 → 2025-12-26 |
47
+ | XAUUSD | 166,820,410 | 167,871,871 | 1,401,953 | 2022-01-02 → 2025-12-26 |
48
+
49
+ **Total**: 453.6M ticks, 2.87M OHLC bars in 5.99 GiB
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.11+
54
+ - ClickHouse running on `localhost:8123`
55
+
56
+ ## Verify ClickHouse
57
+
58
+ ```bash
59
+ # Check ClickHouse is running
60
+ clickhouse client --query "SELECT version()"
61
+
62
+ # Check exness database exists
63
+ clickhouse client --query "SELECT count() FROM exness.raw_spread_ticks"
64
+ ```
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ # Using uv
70
+ uv pip install exness-data-preprocess
71
+
72
+ # From source
73
+ git clone https://github.com/Eon-Labs/exness-data-preprocess.git
74
+ cd exness-data-preprocess
75
+ uv sync
76
+ ```
77
+
78
+ ## Python API
79
+
80
+ ```python
81
+ import exness_data_preprocess as edp
82
+
83
+ # Context manager (recommended)
84
+ with edp.ExnessDataProcessor() as processor:
85
+ # Query ticks
86
+ df = processor.query_ticks("EURUSD", "raw_spread", "2024-01-01", "2024-01-31")
87
+
88
+ # Query OHLC
89
+ df = processor.query_ohlc("EURUSD", "1m", "2024-01-01", "2024-01-31")
90
+
91
+ # Get coverage info
92
+ cov = processor.get_data_coverage("EURUSD")
93
+
94
+ # Download new data (incremental)
95
+ result = processor.update_data("EURUSD", start_date="2022-01-01")
96
+ ```
97
+
98
+ ### API Methods
99
+
100
+ | Method | Parameters | Returns |
101
+ | --------------------------------------------------- | ---------------------------------------------- | ------------ |
102
+ | `query_ticks(pair, variant, start_date, end_date)` | variant: `raw_spread` or `standard` | DataFrame |
103
+ | `query_ohlc(pair, timeframe, start_date, end_date)` | timeframe: `1m`, `5m`, `15m`, `1h`, `4h`, `1d` | DataFrame |
104
+ | `get_data_coverage(pair)` | | CoverageInfo |
105
+ | `update_data(pair, start_date, delete_zip=True)` | | UpdateResult |
106
+
107
+ ### Return Models
108
+
109
+ ```python
110
+ # 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
116
+
117
+ # 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
124
+ ```
125
+
126
+ ## Direct SQL Access
127
+
128
+ ```bash
129
+ # Count ticks
130
+ clickhouse client --query "SELECT count() FROM exness.raw_spread_ticks WHERE instrument='EURUSD'"
131
+
132
+ # Query tick data
133
+ clickhouse client --query "
134
+ SELECT timestamp, bid, ask
135
+ FROM exness.raw_spread_ticks
136
+ WHERE instrument='EURUSD'
137
+ AND timestamp >= '2024-01-01'
138
+ AND timestamp < '2024-01-02'
139
+ LIMIT 10"
140
+
141
+ # Query OHLC
142
+ clickhouse client --query "
143
+ SELECT timestamp, open, high, low, close
144
+ FROM exness.ohlc_1m
145
+ WHERE instrument='EURUSD'
146
+ AND timestamp >= '2024-01-01'
147
+ LIMIT 10"
148
+
149
+ # Resample to 1h
150
+ clickhouse client --query "
151
+ SELECT
152
+ toStartOfHour(timestamp) AS ts,
153
+ argMin(open, timestamp) AS open,
154
+ max(high) AS high,
155
+ min(low) AS low,
156
+ argMax(close, timestamp) AS close
157
+ FROM exness.ohlc_1m
158
+ WHERE instrument='EURUSD' AND timestamp >= '2024-01-01'
159
+ GROUP BY ts
160
+ ORDER BY ts"
161
+ ```
162
+
163
+ ## Schema
164
+
165
+ ### Tick Tables
166
+
167
+ `exness.raw_spread_ticks`, `exness.standard_ticks`:
168
+
169
+ | Column | Type | Codec |
170
+ | ---------- | ---------------------- | ------------------- |
171
+ | instrument | LowCardinality(String) | - |
172
+ | timestamp | DateTime64(6, 'UTC') | DoubleDelta, LZ4 |
173
+ | bid | Float64 | Gorilla, ZSTD |
174
+ | ask | Float64 | Gorilla, ZSTD |
175
+
176
+ ### OHLC Table
177
+
178
+ `exness.ohlc_1m` (27 columns):
179
+
180
+ | Category | Columns |
181
+ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
182
+ | Core | instrument, timestamp, open, high, low, close |
183
+ | Spreads | raw_spread_avg, standard_spread_avg |
184
+ | Tick counts | tick_count_raw_spread, tick_count_standard |
185
+ | Timezone | ny_hour, london_hour, ny_session, london_session |
186
+ | Holidays | is_us_holiday, is_uk_holiday, is_major_holiday |
187
+ | Sessions | is_nyse_session, is_lse_session, is_xswx_session, is_xfra_session, is_xtse_session, is_xnze_session, is_xtks_session, is_xasx_session, is_xhkg_session, is_xses_session |
188
+
189
+ Engine: `ReplacingMergeTree` (automatic deduplication)
190
+
191
+ Partition: `toYYYYMM(timestamp)`
192
+
193
+ Order: `(instrument, timestamp)`
194
+
195
+ ## Data Source
196
+
197
+ - URL: <https://ticks.ex2archive.com/>
198
+ - Format: Monthly ZIP files with CSV tick data
199
+ - Variants: Raw_Spread (zero spreads) + Standard (market spreads)
200
+ - Precision: Microsecond timestamps
201
+
202
+ ## Development
203
+
204
+ ```bash
205
+ # Setup
206
+ uv sync --dev
207
+
208
+ # Test
209
+ uv run pytest
210
+
211
+ # Lint
212
+ uv run ruff check --fix .
213
+
214
+ # Type check
215
+ uv run mypy src/
216
+ ```
217
+
218
+ ## Documentation
219
+
220
+ - [ClickHouse User Guide](/docs/CLICKHOUSE_USER_GUIDE.md) - Detailed ClickHouse usage
221
+ - [Schema](#schema) - summary above; the DDL in [`clickhouse_manager.py`](/src/exness_data_preprocess/clickhouse_manager.py) is authoritative
222
+ - [Exness Data Sources](/docs/EXNESS_DATA_SOURCES.md) - archive layout and variants
223
+ - [ADR: ClickHouse Migration](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) - Architecture decision
224
+
225
+ ## License
226
+
227
+ MIT
@@ -0,0 +1,190 @@
1
+ # exness-data-preprocess
2
+
3
+ Forex tick data preprocessing with ClickHouse backend. Downloads, stores, and queries tick data from Exness public repository.
4
+
5
+ ## Data Inventory (Validated 2025-12-28)
6
+
7
+ | Instrument | raw_spread_ticks | standard_ticks | ohlc_1m | Date Range |
8
+ | ---------- | ---------------- | -------------- | --------- | ----------------------- |
9
+ | EURUSD | 56,687,313 | 62,203,144 | 1,466,724 | 2022-01-02 → 2025-12-26 |
10
+ | XAUUSD | 166,820,410 | 167,871,871 | 1,401,953 | 2022-01-02 → 2025-12-26 |
11
+
12
+ **Total**: 453.6M ticks, 2.87M OHLC bars in 5.99 GiB
13
+
14
+ ## Requirements
15
+
16
+ - Python 3.11+
17
+ - ClickHouse running on `localhost:8123`
18
+
19
+ ## Verify ClickHouse
20
+
21
+ ```bash
22
+ # Check ClickHouse is running
23
+ clickhouse client --query "SELECT version()"
24
+
25
+ # Check exness database exists
26
+ clickhouse client --query "SELECT count() FROM exness.raw_spread_ticks"
27
+ ```
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ # Using uv
33
+ uv pip install exness-data-preprocess
34
+
35
+ # From source
36
+ git clone https://github.com/Eon-Labs/exness-data-preprocess.git
37
+ cd exness-data-preprocess
38
+ uv sync
39
+ ```
40
+
41
+ ## Python API
42
+
43
+ ```python
44
+ import exness_data_preprocess as edp
45
+
46
+ # Context manager (recommended)
47
+ with edp.ExnessDataProcessor() as processor:
48
+ # Query ticks
49
+ df = processor.query_ticks("EURUSD", "raw_spread", "2024-01-01", "2024-01-31")
50
+
51
+ # Query OHLC
52
+ df = processor.query_ohlc("EURUSD", "1m", "2024-01-01", "2024-01-31")
53
+
54
+ # Get coverage info
55
+ cov = processor.get_data_coverage("EURUSD")
56
+
57
+ # Download new data (incremental)
58
+ result = processor.update_data("EURUSD", start_date="2022-01-01")
59
+ ```
60
+
61
+ ### API Methods
62
+
63
+ | Method | Parameters | Returns |
64
+ | --------------------------------------------------- | ---------------------------------------------- | ------------ |
65
+ | `query_ticks(pair, variant, start_date, end_date)` | variant: `raw_spread` or `standard` | DataFrame |
66
+ | `query_ohlc(pair, timeframe, start_date, end_date)` | timeframe: `1m`, `5m`, `15m`, `1h`, `4h`, `1d` | DataFrame |
67
+ | `get_data_coverage(pair)` | | CoverageInfo |
68
+ | `update_data(pair, start_date, delete_zip=True)` | | UpdateResult |
69
+
70
+ ### Return Models
71
+
72
+ ```python
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
79
+
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
87
+ ```
88
+
89
+ ## Direct SQL Access
90
+
91
+ ```bash
92
+ # Count ticks
93
+ clickhouse client --query "SELECT count() FROM exness.raw_spread_ticks WHERE instrument='EURUSD'"
94
+
95
+ # Query tick data
96
+ clickhouse client --query "
97
+ SELECT timestamp, bid, ask
98
+ FROM exness.raw_spread_ticks
99
+ WHERE instrument='EURUSD'
100
+ AND timestamp >= '2024-01-01'
101
+ AND timestamp < '2024-01-02'
102
+ LIMIT 10"
103
+
104
+ # Query OHLC
105
+ clickhouse client --query "
106
+ SELECT timestamp, open, high, low, close
107
+ FROM exness.ohlc_1m
108
+ WHERE instrument='EURUSD'
109
+ AND timestamp >= '2024-01-01'
110
+ LIMIT 10"
111
+
112
+ # Resample to 1h
113
+ clickhouse client --query "
114
+ SELECT
115
+ toStartOfHour(timestamp) AS ts,
116
+ argMin(open, timestamp) AS open,
117
+ max(high) AS high,
118
+ min(low) AS low,
119
+ argMax(close, timestamp) AS close
120
+ FROM exness.ohlc_1m
121
+ WHERE instrument='EURUSD' AND timestamp >= '2024-01-01'
122
+ GROUP BY ts
123
+ ORDER BY ts"
124
+ ```
125
+
126
+ ## Schema
127
+
128
+ ### Tick Tables
129
+
130
+ `exness.raw_spread_ticks`, `exness.standard_ticks`:
131
+
132
+ | Column | Type | Codec |
133
+ | ---------- | ---------------------- | ------------------- |
134
+ | instrument | LowCardinality(String) | - |
135
+ | timestamp | DateTime64(6, 'UTC') | DoubleDelta, LZ4 |
136
+ | bid | Float64 | Gorilla, ZSTD |
137
+ | ask | Float64 | Gorilla, ZSTD |
138
+
139
+ ### OHLC Table
140
+
141
+ `exness.ohlc_1m` (27 columns):
142
+
143
+ | Category | Columns |
144
+ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
145
+ | Core | instrument, timestamp, open, high, low, close |
146
+ | Spreads | raw_spread_avg, standard_spread_avg |
147
+ | Tick counts | tick_count_raw_spread, tick_count_standard |
148
+ | Timezone | ny_hour, london_hour, ny_session, london_session |
149
+ | Holidays | is_us_holiday, is_uk_holiday, is_major_holiday |
150
+ | Sessions | is_nyse_session, is_lse_session, is_xswx_session, is_xfra_session, is_xtse_session, is_xnze_session, is_xtks_session, is_xasx_session, is_xhkg_session, is_xses_session |
151
+
152
+ Engine: `ReplacingMergeTree` (automatic deduplication)
153
+
154
+ Partition: `toYYYYMM(timestamp)`
155
+
156
+ Order: `(instrument, timestamp)`
157
+
158
+ ## Data Source
159
+
160
+ - URL: <https://ticks.ex2archive.com/>
161
+ - Format: Monthly ZIP files with CSV tick data
162
+ - Variants: Raw_Spread (zero spreads) + Standard (market spreads)
163
+ - Precision: Microsecond timestamps
164
+
165
+ ## Development
166
+
167
+ ```bash
168
+ # Setup
169
+ uv sync --dev
170
+
171
+ # Test
172
+ uv run pytest
173
+
174
+ # Lint
175
+ uv run ruff check --fix .
176
+
177
+ # Type check
178
+ uv run mypy src/
179
+ ```
180
+
181
+ ## Documentation
182
+
183
+ - [ClickHouse User Guide](/docs/CLICKHOUSE_USER_GUIDE.md) - Detailed ClickHouse usage
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
+ - [ADR: ClickHouse Migration](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) - Architecture decision
187
+
188
+ ## License
189
+
190
+ MIT