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.
- exness_data_preprocess-2.1.1/.github/dependabot.yml +26 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.gitignore +8 -2
- exness_data_preprocess-2.1.1/.moon/toolchain.yml +2 -0
- exness_data_preprocess-2.1.1/.moon/workspace.yml +8 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.pre-commit-config.yaml +4 -4
- exness_data_preprocess-2.1.1/.prototools +5 -0
- exness_data_preprocess-2.1.1/.python-version +1 -0
- exness_data_preprocess-2.1.1/.releaserc.yml +24 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/CHANGELOG.md +25 -0
- exness_data_preprocess-2.1.1/CLAUDE.md +30 -0
- exness_data_preprocess-2.1.1/CONTRIBUTING.md +32 -0
- exness_data_preprocess-2.1.1/PKG-INFO +227 -0
- exness_data_preprocess-2.1.1/README.md +190 -0
- exness_data_preprocess-2.1.1/docs/CLICKHOUSE_USER_GUIDE.md +742 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/EXNESS_DATA_SOURCES.md +12 -36
- exness_data_preprocess-2.1.1/docs/README.md +31 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-exness-clickhouse-migration.md +1 -1
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-pydantic-config.md +2 -3
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-11-duckdb-removal-clickhouse.md +0 -2
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-11-duckdb-removal-clickhouse/spec.md +5 -14
- exness_data_preprocess-2.1.1/docs/release-notes/2.1.1.md +24 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md +51 -35
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/README.md +11 -9
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +21 -17
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/README.md +7 -8
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +71 -60
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +9 -2
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +4 -4
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/README.md +17 -17
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +10 -10
- exness_data_preprocess-2.1.1/examples/basic_usage.py +65 -0
- exness_data_preprocess-2.1.1/moon.yml +77 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/package.json +4 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/pyproject.toml +3 -6
- exness_data_preprocess-2.1.1/scripts/clickhouse-start.sh +60 -0
- exness_data_preprocess-2.1.1/scripts/clickhouse-stop.sh +52 -0
- exness_data_preprocess-2.1.1/scripts/e2e-ephemeral.sh +147 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/scripts/generate_dbeaver_config.py +2 -3
- exness_data_preprocess-2.1.1/scripts/publish-release-notes.sh +49 -0
- exness_data_preprocess-2.1.1/scripts/smoke_install.sh +16 -0
- exness_data_preprocess-2.1.1/scripts/validate_clickhouse.py +185 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/__init__.py +5 -2
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_client.py +9 -4
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_manager.py +76 -20
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_ohlc_generator.py +14 -28
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_query_engine.py +10 -10
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/downloader.py +8 -1
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/models.py +13 -11
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/processor.py +53 -12
- exness_data_preprocess-2.1.1/tests/README.md +28 -0
- exness_data_preprocess-2.1.1/tests/conftest.py +94 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_basic.py +3 -23
- exness_data_preprocess-2.1.1/tests/test_database_bootstrap_order.py +90 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_functional_regression.py +1 -23
- exness_data_preprocess-2.1.1/tests/test_package_structure.py +71 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_processor_pydantic.py +1 -24
- exness_data_preprocess-2.1.1/uv.toml +2 -0
- exness_data_preprocess-2.0.0/.cz.toml +0 -12
- exness_data_preprocess-2.0.0/.github/workflows/ci.yml +0 -25
- exness_data_preprocess-2.0.0/.github/workflows/pre-commit-autoupdate.yml +0 -38
- exness_data_preprocess-2.0.0/.mise.toml +0 -518
- exness_data_preprocess-2.0.0/.releaserc.yml +0 -22
- exness_data_preprocess-2.0.0/CLAUDE.md +0 -152
- exness_data_preprocess-2.0.0/CONTRIBUTING.md +0 -282
- exness_data_preprocess-2.0.0/Makefile +0 -62
- exness_data_preprocess-2.0.0/PKG-INFO +0 -584
- exness_data_preprocess-2.0.0/README.md +0 -547
- exness_data_preprocess-2.0.0/cliff-release-notes.toml +0 -131
- exness_data_preprocess-2.0.0/cliff.toml +0 -144
- exness_data_preprocess-2.0.0/docs/DATABASE_SCHEMA.md +0 -955
- exness_data_preprocess-2.0.0/docs/MODULE_ARCHITECTURE.md +0 -1088
- exness_data_preprocess-2.0.0/docs/PRIORITY3_CLEANUP_PLAN.yaml +0 -386
- exness_data_preprocess-2.0.0/docs/README.md +0 -266
- exness_data_preprocess-2.0.0/docs/REPOSITORY_REFACTORING_PLAN.yaml +0 -375
- exness_data_preprocess-2.0.0/docs/RESEARCH_PATTERNS.md +0 -236
- exness_data_preprocess-2.0.0/docs/TRADING_HOURS_RESEARCH.md +0 -1684
- exness_data_preprocess-2.0.0/docs/UNIFIED_DUCKDB_PLAN_v2.md +0 -642
- exness_data_preprocess-2.0.0/docs/archive/PHASE4_DRY_RUN_CONFIG_PLAN.yaml +0 -362
- exness_data_preprocess-2.0.0/docs/archive/PHASE7_v1.5.0_REFACTORING_PLAN.md +0 -585
- exness_data_preprocess-2.0.0/docs/archive/PHASE7_v1.6.0_REFACTORING_PROGRESS.md +0 -1164
- exness_data_preprocess-2.0.0/docs/archive/PYDANTIC_REFACTORING_PLAN_v0.2.0_COMPLETE.md +0 -985
- exness_data_preprocess-2.0.0/docs/archive/PYDANTIC_REFACTORING_STATUS_v0.2.0_COMPLETE.md +0 -222
- exness_data_preprocess-2.0.0/docs/optimization/OPTIMIZATION_OPPORTUNITIES_2025-10-18.md +0 -558
- exness_data_preprocess-2.0.0/docs/phases/PHASE2_SESSION_VECTORIZATION_PLAN.yaml +0 -268
- exness_data_preprocess-2.0.0/docs/phases/PHASE3_SQL_GAP_DETECTION_PLAN.yaml +0 -298
- exness_data_preprocess-2.0.0/docs/releases/RELEASE_NOTES.md +0 -21
- exness_data_preprocess-2.0.0/docs/releases/RELEASE_NOTES_SHORT.md +0 -40
- exness_data_preprocess-2.0.0/docs/research/gap_detection_implementation_example.py +0 -193
- exness_data_preprocess-2.0.0/docs/setup/GITHUB_PYPI_SETUP.md +0 -372
- exness_data_preprocess-2.0.0/docs/validation/E2E_VALIDATION_RESULTS_v1.6.0.md +0 -318
- exness_data_preprocess-2.0.0/docs/validation/SPIKE_TEST_RESULTS_PHASE1_2025-10-18.md +0 -279
- exness_data_preprocess-2.0.0/docs/validation/SPIKE_TEST_RESULTS_PHASE2_2025-10-18.md +0 -352
- exness_data_preprocess-2.0.0/examples/basic_usage.py +0 -216
- exness_data_preprocess-2.0.0/examples/batch_processing.py +0 -467
- exness_data_preprocess-2.0.0/tests/README.md +0 -162
- exness_data_preprocess-2.0.0/tests/conftest.py +0 -79
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/.github/workflows/publish.yml +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/LICENSE +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-codebase-pruning.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md +0 -0
- {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
- {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
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-codebase-pruning/spec.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-exness-clickhouse-migration/spec.md +0 -0
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-10-clickhouse-pydantic-config/spec.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/package-lock.json +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_base.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_gap_detector.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/config.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/exchanges.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/session_detector.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/tick_loader.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/__init__.py +0 -0
- {exness_data_preprocess-2.0.0 → exness_data_preprocess-2.1.1}/tests/test_models.py +0 -0
- {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/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/commitizen-tools/commitizen
|
|
3
|
-
rev: v4.
|
|
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:
|
|
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.
|
|
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 @@
|
|
|
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
|