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.
- exness_data_preprocess-3.0.0/.github/dependabot.yml +26 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.github/workflows/publish.yml +4 -4
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.gitignore +4 -2
- exness_data_preprocess-3.0.0/.moon/toolchain.yml +2 -0
- exness_data_preprocess-3.0.0/.moon/workspace.yml +8 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/.pre-commit-config.yaml +4 -4
- exness_data_preprocess-3.0.0/.prototools +5 -0
- exness_data_preprocess-3.0.0/.python-version +1 -0
- exness_data_preprocess-3.0.0/.releaserc.yml +24 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/CHANGELOG.md +31 -0
- exness_data_preprocess-3.0.0/CLAUDE.md +31 -0
- exness_data_preprocess-3.0.0/CONTRIBUTING.md +32 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/PKG-INFO +23 -24
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/README.md +20 -20
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/CLICKHOUSE_USER_GUIDE.md +32 -45
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/EXNESS_DATA_SOURCES.md +3 -1
- exness_data_preprocess-3.0.0/docs/README.md +31 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-11-duckdb-removal-clickhouse/spec.md +5 -14
- exness_data_preprocess-3.0.0/docs/release-notes/2.1.1.md +24 -0
- exness_data_preprocess-3.0.0/docs/release-notes/3.0.0.md +29 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md +27 -16
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/README.md +2 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +16 -12
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/README.md +1 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +68 -57
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +7 -0
- {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
- {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
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +6 -6
- exness_data_preprocess-3.0.0/examples/basic_usage.py +65 -0
- exness_data_preprocess-3.0.0/moon.yml +77 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/package-lock.json +210 -235
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/package.json +4 -4
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/pyproject.toml +4 -8
- exness_data_preprocess-3.0.0/scripts/clickhouse-start.sh +60 -0
- exness_data_preprocess-3.0.0/scripts/clickhouse-stop.sh +52 -0
- exness_data_preprocess-3.0.0/scripts/e2e-ephemeral.sh +149 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/scripts/generate_dbeaver_config.py +2 -3
- exness_data_preprocess-3.0.0/scripts/publish-release-notes.sh +51 -0
- exness_data_preprocess-3.0.0/scripts/smoke_install.sh +16 -0
- exness_data_preprocess-3.0.0/scripts/validate_clickhouse.py +342 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/__init__.py +5 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_client.py +3 -4
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_manager.py +206 -45
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_ohlc_generator.py +33 -16
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_query_engine.py +87 -50
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/downloader.py +13 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/models.py +20 -17
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/processor.py +89 -33
- exness_data_preprocess-3.0.0/tests/README.md +28 -0
- exness_data_preprocess-3.0.0/tests/conftest.py +94 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_basic.py +3 -23
- exness_data_preprocess-3.0.0/tests/test_database_bootstrap_order.py +90 -0
- exness_data_preprocess-3.0.0/tests/test_date_bounds.py +31 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_functional_regression.py +1 -23
- exness_data_preprocess-3.0.0/tests/test_package_structure.py +70 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_processor_pydantic.py +1 -24
- exness_data_preprocess-3.0.0/tests/test_tick_seq.py +53 -0
- exness_data_preprocess-3.0.0/uv.toml +2 -0
- exness_data_preprocess-2.1.0/.cz.toml +0 -12
- exness_data_preprocess-2.1.0/.github/workflows/ci.yml +0 -25
- exness_data_preprocess-2.1.0/.github/workflows/pre-commit-autoupdate.yml +0 -38
- exness_data_preprocess-2.1.0/.mise.toml +0 -518
- exness_data_preprocess-2.1.0/.releaserc.yml +0 -22
- exness_data_preprocess-2.1.0/CLAUDE.md +0 -152
- exness_data_preprocess-2.1.0/CONTRIBUTING.md +0 -282
- exness_data_preprocess-2.1.0/Makefile +0 -62
- exness_data_preprocess-2.1.0/cliff-release-notes.toml +0 -131
- exness_data_preprocess-2.1.0/cliff.toml +0 -144
- exness_data_preprocess-2.1.0/docs/DATABASE_SCHEMA.md +0 -952
- exness_data_preprocess-2.1.0/docs/MODULE_ARCHITECTURE.md +0 -1085
- exness_data_preprocess-2.1.0/docs/PRIORITY3_CLEANUP_PLAN.yaml +0 -386
- exness_data_preprocess-2.1.0/docs/README.md +0 -238
- exness_data_preprocess-2.1.0/docs/REPOSITORY_REFACTORING_PLAN.yaml +0 -375
- exness_data_preprocess-2.1.0/docs/RESEARCH_PATTERNS.md +0 -236
- exness_data_preprocess-2.1.0/docs/TRADING_HOURS_RESEARCH.md +0 -1690
- exness_data_preprocess-2.1.0/docs/UNIFIED_DUCKDB_PLAN_v2.md +0 -641
- exness_data_preprocess-2.1.0/docs/archive/PHASE4_DRY_RUN_CONFIG_PLAN.yaml +0 -362
- exness_data_preprocess-2.1.0/docs/archive/PHASE7_v1.5.0_REFACTORING_PLAN.md +0 -585
- exness_data_preprocess-2.1.0/docs/archive/PHASE7_v1.6.0_REFACTORING_PROGRESS.md +0 -1164
- exness_data_preprocess-2.1.0/docs/archive/PYDANTIC_REFACTORING_PLAN_v0.2.0_COMPLETE.md +0 -985
- exness_data_preprocess-2.1.0/docs/archive/PYDANTIC_REFACTORING_STATUS_v0.2.0_COMPLETE.md +0 -221
- exness_data_preprocess-2.1.0/docs/optimization/OPTIMIZATION_OPPORTUNITIES_2025-10-18.md +0 -558
- exness_data_preprocess-2.1.0/docs/phases/PHASE2_SESSION_VECTORIZATION_PLAN.yaml +0 -268
- exness_data_preprocess-2.1.0/docs/phases/PHASE3_SQL_GAP_DETECTION_PLAN.yaml +0 -298
- exness_data_preprocess-2.1.0/docs/releases/RELEASE_NOTES.md +0 -21
- exness_data_preprocess-2.1.0/docs/releases/RELEASE_NOTES_SHORT.md +0 -40
- exness_data_preprocess-2.1.0/docs/setup/GITHUB_PYPI_SETUP.md +0 -372
- exness_data_preprocess-2.1.0/docs/validation/E2E_VALIDATION_RESULTS_v1.6.0.md +0 -318
- exness_data_preprocess-2.1.0/docs/validation/SPIKE_TEST_RESULTS_PHASE1_2025-10-18.md +0 -279
- exness_data_preprocess-2.1.0/docs/validation/SPIKE_TEST_RESULTS_PHASE2_2025-10-18.md +0 -352
- exness_data_preprocess-2.1.0/examples/basic_usage.py +0 -216
- exness_data_preprocess-2.1.0/examples/batch_processing.py +0 -467
- exness_data_preprocess-2.1.0/scripts/migrate_duckdb_to_clickhouse.py +0 -541
- exness_data_preprocess-2.1.0/scripts/validate_migration_data.py +0 -632
- exness_data_preprocess-2.1.0/src/exness_data_preprocess/config.py +0 -123
- exness_data_preprocess-2.1.0/tests/README.md +0 -167
- exness_data_preprocess-2.1.0/tests/conftest.py +0 -79
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/LICENSE +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-09-codebase-pruning.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-09-exness-clickhouse-migration.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-10-clickhouse-pydantic-config.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/adr/2025-12-11-duckdb-removal-clickhouse.md +0 -0
- {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
- {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
- {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
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-09-codebase-pruning/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-09-exness-clickhouse-migration/spec.md +0 -0
- {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
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/design/2025-12-10-clickhouse-pydantic-config/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/docs/research/eurusd-zero-spread-deviations/README.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_base.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/clickhouse_gap_detector.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/exchanges.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/session_detector.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/src/exness_data_preprocess/tick_loader.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/__init__.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-3.0.0}/tests/test_models.py +0 -0
- {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@
|
|
13
|
+
- uses: actions/checkout@v7
|
|
14
14
|
|
|
15
|
-
- uses: actions/setup-python@
|
|
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@
|
|
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@
|
|
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/
|
|
@@ -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,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.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: exness-data-preprocess
|
|
3
|
-
Version:
|
|
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>=
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
91
|
+
cov = processor.get_data_coverage("EURUSD")
|
|
93
92
|
|
|
94
93
|
# Download new data (incremental)
|
|
95
|
-
result = processor.update_data(
|
|
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
|
|
112
|
-
result.raw_ticks_added
|
|
113
|
-
result.standard_ticks_added
|
|
114
|
-
result.ohlc_bars
|
|
115
|
-
result.storage_bytes
|
|
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
|
|
119
|
-
cov.standard_ticks
|
|
120
|
-
cov.ohlc_bars
|
|
121
|
-
cov.earliest_date
|
|
122
|
-
cov.latest_date
|
|
123
|
-
cov.storage_bytes
|
|
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
|
|
174
|
-
| ask | Float64 | Gorilla
|
|
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
|
-
- [
|
|
222
|
-
- [
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
55
|
+
cov = processor.get_data_coverage("EURUSD")
|
|
56
56
|
|
|
57
57
|
# Download new data (incremental)
|
|
58
|
-
result = processor.update_data(
|
|
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
|
|
75
|
-
result.raw_ticks_added
|
|
76
|
-
result.standard_ticks_added
|
|
77
|
-
result.ohlc_bars
|
|
78
|
-
result.storage_bytes
|
|
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
|
|
82
|
-
cov.standard_ticks
|
|
83
|
-
cov.ohlc_bars
|
|
84
|
-
cov.earliest_date
|
|
85
|
-
cov.latest_date
|
|
86
|
-
cov.storage_bytes
|
|
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
|
|
137
|
-
| ask | Float64 | Gorilla
|
|
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
|
-
- [
|
|
185
|
-
- [
|
|
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
|
|
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. [
|
|
20
|
+
8. [27-Column OHLC Schema](#27-column-ohlc-schema)
|
|
21
21
|
9. [Direct ClickHouse SQL Patterns](#direct-clickhouse-sql-patterns)
|
|
22
|
-
10. [
|
|
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
|
-
|
|
69
|
+
moon run repo:clickhouse-start
|
|
70
70
|
|
|
71
71
|
# Verify connection
|
|
72
|
-
|
|
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[
|
|
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
|
-
##
|
|
359
|
+
## 27-Column OHLC Schema
|
|
360
360
|
|
|
361
|
-
The `ohlc_1m` table contains
|
|
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
|
-
##
|
|
545
|
+
## moon Tasks for ClickHouse
|
|
546
546
|
|
|
547
547
|
### Server Management
|
|
548
548
|
|
|
549
549
|
```bash
|
|
550
|
-
# Start ClickHouse server (
|
|
551
|
-
|
|
550
|
+
# Start ClickHouse server (clickhouse binary on PATH)
|
|
551
|
+
moon run repo:clickhouse-start
|
|
552
552
|
|
|
553
|
-
# Stop
|
|
554
|
-
|
|
553
|
+
# Stop the server this repo started (by pidfile)
|
|
554
|
+
moon run repo:clickhouse-stop
|
|
555
555
|
|
|
556
556
|
# Check connection status
|
|
557
|
-
|
|
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
|
|
567
|
-
|
|
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
|
-
|
|
569
|
+
moon run repo:validate-clickhouse-schema
|
|
571
570
|
|
|
572
571
|
# Validate data queries
|
|
573
|
-
|
|
572
|
+
moon run repo:validate-clickhouse-data
|
|
574
573
|
|
|
575
574
|
# Validate pagination
|
|
576
|
-
|
|
575
|
+
moon run repo:validate-clickhouse-pagination
|
|
577
576
|
|
|
578
577
|
# Validate OHLC queries
|
|
579
|
-
|
|
578
|
+
moon run repo:validate-clickhouse-ohlc
|
|
580
579
|
```
|
|
581
580
|
|
|
582
581
|
### Quick Reference
|
|
583
582
|
|
|
584
|
-
| Task
|
|
585
|
-
|
|
|
586
|
-
| `
|
|
587
|
-
| `
|
|
588
|
-
| `
|
|
589
|
-
| `
|
|
590
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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)
|