exness-data-preprocess 2.1.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.1.0 → exness_data_preprocess-2.1.1}/.gitignore +4 -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.1.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.1.0 → exness_data_preprocess-2.1.1}/CHANGELOG.md +12 -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.0 → exness_data_preprocess-2.1.1}/PKG-INFO +22 -22
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/README.md +20 -20
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/CLICKHOUSE_USER_GUIDE.md +32 -45
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/EXNESS_DATA_SOURCES.md +3 -1
- exness_data_preprocess-2.1.1/docs/README.md +31 -0
- {exness_data_preprocess-2.1.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.1.0 → exness_data_preprocess-2.1.1}/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md +27 -16
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/README.md +2 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +16 -12
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/README.md +1 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +68 -57
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +7 -0
- {exness_data_preprocess-2.1.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.1.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.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +6 -6
- 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.1.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.1.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.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/__init__.py +5 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_client.py +3 -4
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_manager.py +76 -20
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_ohlc_generator.py +2 -2
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_query_engine.py +10 -10
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/downloader.py +8 -1
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/models.py +13 -11
- {exness_data_preprocess-2.1.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.1.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.1.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.1.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.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/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-2.1.1}/.github/workflows/publish.yml +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/LICENSE +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-codebase-pruning.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-09-exness-clickhouse-migration.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-10-clickhouse-pydantic-config.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/2025-12-11-duckdb-removal-clickhouse.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-after.dot +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-arch.dot +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/adr/diagrams/2025-12-10-clickhouse-pydantic-config-before.dot +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-codebase-pruning/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-09-exness-clickhouse-migration/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-10-clickhouse-e2e-validation-pipeline/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/design/2025-12-10-clickhouse-pydantic-config/spec.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/hurdle-model/hurdle_decomposition.png +0 -0
- {exness_data_preprocess-2.1.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.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/distribution_overlay.png +0 -0
- {exness_data_preprocess-2.1.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.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/variance_decomposition.png +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/docs/research/eurusd-zero-spread-deviations/README.md +0 -0
- {exness_data_preprocess-2.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.0 → exness_data_preprocess-2.1.1}/package-lock.json +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/package.json +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_base.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/clickhouse_gap_detector.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/config.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/exchanges.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/session_detector.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/src/exness_data_preprocess/tick_loader.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/tests/__init__.py +0 -0
- {exness_data_preprocess-2.1.0 → exness_data_preprocess-2.1.1}/tests/test_models.py +0 -0
- {exness_data_preprocess-2.1.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,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,15 @@
|
|
|
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
|
+
|
|
1
13
|
# [2.1.0](https://github.com/terrylica/exness-data-preprocess/compare/v2.0.0...v2.1.0) (2025-12-28)
|
|
2
14
|
|
|
3
15
|
|
|
@@ -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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: exness-data-preprocess
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.1
|
|
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
|
|
@@ -35,7 +35,7 @@ Provides-Extra: examples
|
|
|
35
35
|
Requires-Dist: tqdm>=4.65.0; extra == 'examples'
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
37
37
|
|
|
38
|
-
# exness-data-preprocess
|
|
38
|
+
# exness-data-preprocess
|
|
39
39
|
|
|
40
40
|
Forex tick data preprocessing with ClickHouse backend. Downloads, stores, and queries tick data from Exness public repository.
|
|
41
41
|
|
|
@@ -83,16 +83,16 @@ import exness_data_preprocess as edp
|
|
|
83
83
|
# Context manager (recommended)
|
|
84
84
|
with edp.ExnessDataProcessor() as processor:
|
|
85
85
|
# Query ticks
|
|
86
|
-
df = processor.query_ticks(
|
|
86
|
+
df = processor.query_ticks("EURUSD", "raw_spread", "2024-01-01", "2024-01-31")
|
|
87
87
|
|
|
88
88
|
# Query OHLC
|
|
89
|
-
df = processor.query_ohlc(
|
|
89
|
+
df = processor.query_ohlc("EURUSD", "1m", "2024-01-01", "2024-01-31")
|
|
90
90
|
|
|
91
91
|
# Get coverage info
|
|
92
|
-
cov = processor.get_data_coverage(
|
|
92
|
+
cov = processor.get_data_coverage("EURUSD")
|
|
93
93
|
|
|
94
94
|
# Download new data (incremental)
|
|
95
|
-
result = processor.update_data(
|
|
95
|
+
result = processor.update_data("EURUSD", start_date="2022-01-01")
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
### API Methods
|
|
@@ -108,19 +108,19 @@ with edp.ExnessDataProcessor() as processor:
|
|
|
108
108
|
|
|
109
109
|
```python
|
|
110
110
|
# UpdateResult
|
|
111
|
-
result.months_added
|
|
112
|
-
result.raw_ticks_added
|
|
113
|
-
result.standard_ticks_added
|
|
114
|
-
result.ohlc_bars
|
|
115
|
-
result.storage_bytes
|
|
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
116
|
|
|
117
117
|
# 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
|
|
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
124
|
```
|
|
125
125
|
|
|
126
126
|
## Direct SQL Access
|
|
@@ -170,8 +170,8 @@ ORDER BY ts"
|
|
|
170
170
|
| ---------- | ---------------------- | ------------------- |
|
|
171
171
|
| instrument | LowCardinality(String) | - |
|
|
172
172
|
| timestamp | DateTime64(6, 'UTC') | DoubleDelta, LZ4 |
|
|
173
|
-
| bid | Float64 | Gorilla
|
|
174
|
-
| ask | Float64 | Gorilla
|
|
173
|
+
| bid | Float64 | Gorilla, ZSTD |
|
|
174
|
+
| ask | Float64 | Gorilla, ZSTD |
|
|
175
175
|
|
|
176
176
|
### OHLC Table
|
|
177
177
|
|
|
@@ -218,8 +218,8 @@ uv run mypy src/
|
|
|
218
218
|
## Documentation
|
|
219
219
|
|
|
220
220
|
- [ClickHouse User Guide](/docs/CLICKHOUSE_USER_GUIDE.md) - Detailed ClickHouse usage
|
|
221
|
-
- [
|
|
222
|
-
- [
|
|
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
223
|
- [ADR: ClickHouse Migration](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) - Architecture decision
|
|
224
224
|
|
|
225
225
|
## 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)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
Start with the project [README](/README.md) (install, API, schema summary). The schema DDL in [`clickhouse_manager.py`](/src/exness_data_preprocess/clickhouse_manager.py) is authoritative; tasks are in [`moon.yml`](/moon.yml).
|
|
4
|
+
|
|
5
|
+
## Guides
|
|
6
|
+
|
|
7
|
+
| Document | Covers |
|
|
8
|
+
| ---------------------------------------------------------- | ------------------------------------------------------------- |
|
|
9
|
+
| [CLICKHOUSE_USER_GUIDE.md](/docs/CLICKHOUSE_USER_GUIDE.md) | Connecting, querying, pagination, resampling, troubleshooting |
|
|
10
|
+
| [EXNESS_DATA_SOURCES.md](/docs/EXNESS_DATA_SOURCES.md) | ticks.ex2archive.com layout, Raw_Spread vs Standard variants |
|
|
11
|
+
|
|
12
|
+
## Decisions
|
|
13
|
+
|
|
14
|
+
Architecture Decision Records in [`adr/`](/docs/adr/), each with an implementation spec in [`design/`](/docs/design/) under the same date-slug. They are historical records: they describe the repository as it was when written and are not edited afterwards.
|
|
15
|
+
|
|
16
|
+
| ADR | Decision |
|
|
17
|
+
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
|
|
18
|
+
| [2025-12-09 exness-clickhouse-migration](/docs/adr/2025-12-09-exness-clickhouse-migration.md) | Move storage from DuckDB to ClickHouse |
|
|
19
|
+
| [2025-12-09 codebase-pruning](/docs/adr/2025-12-09-codebase-pruning.md) | Dependency, documentation and code pruning |
|
|
20
|
+
| [2025-12-10 clickhouse-e2e-validation-pipeline](/docs/adr/2025-12-10-clickhouse-e2e-validation-pipeline.md) | Pagination API and E2E validation |
|
|
21
|
+
| [2025-12-10 clickhouse-pydantic-config](/docs/adr/2025-12-10-clickhouse-pydantic-config.md) | Pydantic connection config, DBeaver output |
|
|
22
|
+
| [2025-12-11 duckdb-removal-clickhouse](/docs/adr/2025-12-11-duckdb-removal-clickhouse.md) | ClickHouse-only backend (the 2.x line) |
|
|
23
|
+
|
|
24
|
+
## Research
|
|
25
|
+
|
|
26
|
+
Completed studies with their scripts. Several predate the ClickHouse backend and were run on DuckDB; their findings are about the data, not the storage.
|
|
27
|
+
|
|
28
|
+
- [eurusd-spread-analysis/](/docs/research/eurusd-spread-analysis/README.md): Raw_Spread vs Standard spread variance
|
|
29
|
+
- [eurusd-zero-spread-deviations/](/docs/research/eurusd-zero-spread-deviations/README.md): zero-spread deviation multi-period study
|
|
30
|
+
- [compression-benchmarks/](/docs/research/compression-benchmarks/README.md): tick storage compression comparison
|
|
31
|
+
- [HYBRID_SESSION_DETECTION_ANALYSIS.md](/docs/research/HYBRID_SESSION_DETECTION_ANALYSIS.md): session and holiday detection approach
|
|
@@ -136,13 +136,9 @@ class UpdateResult(BaseModel):
|
|
|
136
136
|
"""Result of update_data() operation."""
|
|
137
137
|
|
|
138
138
|
# RENAMED: ClickHouse-idiomatic names
|
|
139
|
-
database: str = Field(
|
|
140
|
-
description="ClickHouse database name (e.g., 'exness')"
|
|
141
|
-
)
|
|
139
|
+
database: str = Field(description="ClickHouse database name (e.g., 'exness')")
|
|
142
140
|
storage_bytes: int = Field(
|
|
143
|
-
default=0,
|
|
144
|
-
ge=0,
|
|
145
|
-
description="Total storage in bytes (from system.tables)"
|
|
141
|
+
default=0, ge=0, description="Total storage in bytes (from system.tables)"
|
|
146
142
|
)
|
|
147
143
|
|
|
148
144
|
# Keep other fields unchanged
|
|
@@ -158,14 +154,8 @@ class CoverageInfo(BaseModel):
|
|
|
158
154
|
"""Data coverage information."""
|
|
159
155
|
|
|
160
156
|
# RENAMED: ClickHouse-idiomatic names
|
|
161
|
-
database: str = Field(
|
|
162
|
-
|
|
163
|
-
)
|
|
164
|
-
storage_bytes: int = Field(
|
|
165
|
-
default=0,
|
|
166
|
-
ge=0,
|
|
167
|
-
description="Total storage in bytes"
|
|
168
|
-
)
|
|
157
|
+
database: str = Field(description="ClickHouse database name")
|
|
158
|
+
storage_bytes: int = Field(default=0, ge=0, description="Total storage in bytes")
|
|
169
159
|
|
|
170
160
|
# Keep other fields
|
|
171
161
|
instrument: str
|
|
@@ -286,6 +276,7 @@ def clickhouse_client():
|
|
|
286
276
|
except ClickHouseConnectionError:
|
|
287
277
|
pytest.skip("ClickHouse not available")
|
|
288
278
|
|
|
279
|
+
|
|
289
280
|
@pytest.fixture
|
|
290
281
|
def processor_with_clickhouse(temp_dir, clickhouse_client):
|
|
291
282
|
"""Processor with ClickHouse backend."""
|