exness-data-preprocess 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.cz.toml +1 -1
  2. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.gitignore +1 -0
  3. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/CHANGELOG.md +7 -0
  4. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/CLAUDE.md +112 -41
  5. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/GITHUB_PYPI_SETUP.md +1 -1
  6. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/PKG-INFO +8 -7
  7. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/PYDANTIC_REFACTORING_PLAN.md +9 -10
  8. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/README.md +6 -6
  9. exness_data_preprocess-0.3.1/RELEASE_NOTES.md +6 -0
  10. exness_data_preprocess-0.3.1/cliff-release-notes.toml +131 -0
  11. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/DATABASE_SCHEMA.md +122 -26
  12. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/README.md +32 -3
  13. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/UNIFIED_DUCKDB_PLAN_v2.md +2 -2
  14. exness_data_preprocess-0.3.1/docs/plans/PHASE7_v1.5.0_REFACTORING_PLAN.md +544 -0
  15. exness_data_preprocess-0.3.1/docs/plans/PHASE7_v1.6.0_REFACTORING_PROGRESS.md +1119 -0
  16. exness_data_preprocess-0.3.1/docs/plans/REFACTORING_CHECKLIST.md +202 -0
  17. exness_data_preprocess-0.3.1/docs/plans/SESSION_2025-10-15_SUMMARY.md +305 -0
  18. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/pyproject.toml +2 -1
  19. exness_data_preprocess-0.3.1/src/exness_data_preprocess/database_manager.py +208 -0
  20. exness_data_preprocess-0.3.1/src/exness_data_preprocess/downloader.py +82 -0
  21. exness_data_preprocess-0.3.1/src/exness_data_preprocess/exchanges.py +164 -0
  22. exness_data_preprocess-0.3.1/src/exness_data_preprocess/gap_detector.py +157 -0
  23. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/src/exness_data_preprocess/models.py +1 -3
  24. exness_data_preprocess-0.3.1/src/exness_data_preprocess/ohlc_generator.py +199 -0
  25. exness_data_preprocess-0.3.1/src/exness_data_preprocess/processor.py +412 -0
  26. exness_data_preprocess-0.3.1/src/exness_data_preprocess/query_engine.py +290 -0
  27. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/src/exness_data_preprocess/schema.py +77 -11
  28. exness_data_preprocess-0.3.1/src/exness_data_preprocess/session_detector.py +121 -0
  29. exness_data_preprocess-0.3.1/src/exness_data_preprocess/tick_loader.py +67 -0
  30. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/README.md +2 -2
  31. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/conftest.py +2 -5
  32. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/test_functional_regression.py +12 -18
  33. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/test_models.py +8 -3
  34. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/test_processor_pydantic.py +3 -2
  35. exness_data_preprocess-0.3.0/RELEASE_NOTES.md +0 -22
  36. exness_data_preprocess-0.3.0/src/exness_data_preprocess/processor.py +0 -773
  37. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.github/workflows/ci.yml +0 -0
  38. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.github/workflows/pre-commit-autoupdate.yml +0 -0
  39. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.github/workflows/publish.yml +0 -0
  40. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/.pre-commit-config.yaml +0 -0
  41. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/AUTHORS.md +0 -0
  42. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/CONTRIBUTING.md +0 -0
  43. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/LICENSE +0 -0
  44. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/PYDANTIC_REFACTORING_STATUS.md +0 -0
  45. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/cliff.toml +0 -0
  46. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/EXNESS_DATA_SOURCES.md +0 -0
  47. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/archive/UNIFIED_DUCKDB_PLAN_v1.0.0_LEGACY.md +0 -0
  48. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/implementation-plan.yaml +0 -0
  49. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/planning-index.yaml +0 -0
  50. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/compression-benchmarks/README.md +0 -0
  51. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/compression-benchmarks/test_all_compression_methods.py +0 -0
  52. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/compression-benchmarks/test_delta_encoding_properly.py +0 -0
  53. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/compression-benchmarks/test_parquet_compression_methods.py +0 -0
  54. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/01-methodology.md +0 -0
  55. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/02-mode-truncated-analysis.md +0 -0
  56. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/03-hurdle-model-analysis.md +0 -0
  57. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/04-temporal-patterns.md +0 -0
  58. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/05-final-recommendations.md +0 -0
  59. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/README.md +0 -0
  60. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/scripts/reproduction_guide.md +0 -0
  61. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/hurdle-model/hurdle_decomposition.png +0 -0
  62. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/cv_mode_comparison.png +0 -0
  63. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/distribution_overlay.png +0 -0
  64. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/signal_quality_comparison.png +0 -0
  65. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/mode-truncated/variance_decomposition.png +0 -0
  66. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/concentration_curve.png +0 -0
  67. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-spread-analysis/visualizations/temporal/percentile_analysis.png +0 -0
  68. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/01-methodology.md +0 -0
  69. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/02-baseline-sep2024.md +0 -0
  70. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/03-multiperiod-validation.md +0 -0
  71. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/04-discoveries-and-plan-evolution.md +0 -0
  72. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/README.md +0 -0
  73. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/findings/baseline-sep2024-comprehensive-summary.md +0 -0
  74. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/findings/phase2-mean-reversion-report.md +0 -0
  75. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/findings/phase3-volatility-model-report.md +0 -0
  76. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/findings/phase4-5-statistical-tests-survivorship-report.md +0 -0
  77. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/01_mean_reversion_analysis.py +0 -0
  78. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/02_volatility_model_simple.py +0 -0
  79. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/03_liquidity_crisis_detection.py +0 -0
  80. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/baseline-sep2024/04_regime_detection_analysis.py +0 -0
  81. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase1_data_validation.py +0 -0
  82. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase2_mean_reversion.py +0 -0
  83. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase3_volatility_model.py +0 -0
  84. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase4_statistical_tests.py +0 -0
  85. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias.py +0 -0
  86. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase5_survivorship_bias_v1.0.1.py +0 -0
  87. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6a_interval_analysis.py +0 -0
  88. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6b_price_clustering.py +0 -0
  89. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/multiperiod-validation/phase6c_combined_pattern.py +0 -0
  90. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/reproduction_guide.md +0 -0
  91. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/diagnostic_burst_decay.py +0 -0
  92. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_interactive_dashboard.py +0 -0
  93. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/generate_lightweight_dashboard.py +0 -0
  94. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/docs/research/eurusd-zero-spread-deviations/scripts/visualization/prepare_visualization_data.py +0 -0
  95. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/examples/basic_usage.py +0 -0
  96. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/examples/batch_processing.py +0 -0
  97. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/src/exness_data_preprocess/__init__.py +0 -0
  98. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/src/exness_data_preprocess/cli.py +0 -0
  99. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/__init__.py +0 -0
  100. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/archive/E2E_TESTING_PLAN_v1.0.0.md +0 -0
  101. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/test_basic.py +0 -0
  102. {exness_data_preprocess-0.3.0 → exness_data_preprocess-0.3.1}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  [tool.commitizen]
2
2
  name = "cz_conventional_commits"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  tag_format = "v$major.$minor.$patch"
5
5
  update_changelog_on_bump = true
6
6
  version_files = [
@@ -72,6 +72,7 @@ data/
72
72
  *.zip
73
73
  *.csv
74
74
  temp/
75
+ eurusd
75
76
 
76
77
  # macOS
77
78
  .DS_Store
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
 
9
+ ### ♻️ Refactoring
10
+
11
+ - **schema**: Centralize OHLC schema in schema.py module - Create schema.py with OHLCSchema class as single source of truth - Reduce coupling from 42 to 5 update locations (88% reduction) - Replace hardcoded column lists in docs with pointers to schema.py - Delete obsolete PYDANTIC_TEST_STRATEGY.md (tests implemented) - Delete add_schema_comments.py (functionality merged into processor) - Update tests to use OHLCSchema.get_required_columns() - Achieve maximum DRY: future column additions require 1-2 file updates BREAKING CHANGE: None (additive refactoring, no API changes)
12
+
13
+
9
14
  ### ✨ Features
10
15
 
11
16
  - Implement pydantic v2 models with dual-variant e2e testing - Add Pydantic v2 models (UpdateResult, CoverageInfo) for type-safe API - Update processor to use Pydantic types (PairType, TimeframeType, VariantType) - Remove deprecated api.py module (broken functionality) - Implement comprehensive test suite (48 tests, 100% passing): * test_models.py - Pydantic model validation (13 tests) * test_types.py - Type safety and helpers (15 tests) * test_processor_pydantic.py - Integration tests (6 tests) * test_functional_regression.py - v2.0.0 regression tests (10 tests) - Fix Standard variant downloads (variant="" not "Standard") - Add true end-to-end testing with real Exness downloads - Test data: EURUSD August 2024 (815K Raw_Spread + 877K Standard ticks) - Update documentation and add refactoring status tracking - Coverage: models.py 100%, __init__.py 100%, processor.py 45% BREAKING CHANGE: api.py removed (use ExnessDataProcessor directly)
@@ -20,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
20
25
 
21
26
  - **release**: Bump version 0.1.0 → 0.2.0 [skip ci]
22
27
 
28
+ - **release**: Bump version 0.2.0 → 0.3.0 [skip ci]
29
+
23
30
 
24
31
  ### ✨ Features
25
32
 
@@ -68,45 +68,105 @@ doppler run --project claude-config --config dev -- uv publish --token "$PYPI_TO
68
68
 
69
69
  ## Codebase Architecture
70
70
 
71
- ### Module Structure
72
-
73
- **Core Components**:
74
-
75
- 1. **`processor.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/processor.py`) - Main `ExnessDataProcessor` class
76
- - **Lines 29-899**: Complete processor implementation
77
- - **Lines 75-113**: `download_exness_zip()` - Downloads monthly ZIP files from ticks.ex2archive.com
78
- - **Lines 115-232**: `_get_or_create_db()` - Database initialization with schema and COMMENT ON statements
79
- - **Lines 234-245**: `_load_ticks_from_zip()` - CSV parsing from ZIP files
80
- - **Lines 247-275**: `_append_ticks_to_db()` - Tick insertion with PRIMARY KEY duplicate prevention
81
- - **Lines 277-377**: `_discover_missing_months()` - Gap detection for incremental updates
82
- - **Lines 379-516**: `update_data()` - Main entry point for downloading and updating data
83
- - **Lines 518-549**: `_regenerate_ohlc()` - Phase7 13-column OHLC (v1.2.0) generation with LEFT JOIN
84
- - **Lines 551-603**: `query_ticks()` - Tick queries with date range and SQL filters
85
- - **Lines 605-706**: `query_ohlc()` - OHLC queries with on-demand resampling (1m/5m/15m/1h/4h/1d)
86
- - **Lines 708-821**: `add_schema_comments()` / `add_schema_comments_all()` - Retrofit self-documentation
87
- - **Lines 823-899**: `get_data_coverage()` - Coverage statistics and metadata
88
-
89
- 2. **`api.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/api.py`) - Simple wrapper functions
71
+ ### Module Structure (v1.3.0 - Facade Pattern)
72
+
73
+ **Architecture**: Thin facade orchestrator with 7 focused modules (414 lines processor, 1,146 lines extracted)
74
+
75
+ **Core Facade**:
76
+
77
+ 1. **`processor.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/processor.py`) - Thin orchestrator facade (414 lines)
78
+ - **Responsibility**: Coordinate workflow, delegate to specialized modules
79
+ - **Pattern**: Facade pattern - all public methods delegate to modules
80
+ - **Lines 76-110**: `__init__()` - Initialize 7 module dependencies
81
+ - **Lines 111-132**: `download_exness_zip()` - Delegates to downloader module
82
+ - **Lines 134-145**: `_get_or_create_db()` - Delegates to database_manager module
83
+ - **Lines 147-150**: `_load_ticks_from_zip()` - Delegates to tick_loader module
84
+ - **Lines 152-162**: `_append_ticks_to_db()` - Delegates to database_manager module
85
+ - **Lines 164-176**: `_discover_missing_months()` - Delegates to gap_detector module
86
+ - **Lines 178-315**: `update_data()` - Main workflow orchestrator
87
+ - **Lines 317-326**: `_regenerate_ohlc()` - Delegates to ohlc_generator module
88
+ - **Lines 328-357**: `query_ticks()` - Delegates to query_engine module
89
+ - **Lines 359-386**: `query_ohlc()` - Delegates to query_engine module
90
+ - **Lines 388-414**: `get_data_coverage()` - Delegates to query_engine module
91
+
92
+ **Specialized Modules**:
93
+
94
+ 2. **`downloader.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/downloader.py`) - HTTP download operations (89 lines)
95
+ - **Responsibility**: Download Exness ZIP files from ticks.ex2archive.com
96
+ - **SLOs**: Availability (raise on failure), Correctness (URL patterns), Observability (logging), Maintainability (httpx library)
97
+ - **Class**: `ExnessDownloader`
98
+ - **Methods**: `download_zip(year, month, pair, variant)`
99
+
100
+ 3. **`tick_loader.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/tick_loader.py`) - CSV parsing (67 lines)
101
+ - **Responsibility**: Load tick data from ZIP files into pandas DataFrames
102
+ - **SLOs**: Availability (raise on failure), Correctness (timestamp parsing), Observability (logging), Maintainability (pandas library)
103
+ - **Class**: `TickLoader`
104
+ - **Methods**: `load_from_zip(zip_path)` (static method)
105
+
106
+ 4. **`database_manager.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/database_manager.py`) - Database operations (213 lines)
107
+ - **Responsibility**: Database initialization, schema creation, tick insertion with PRIMARY KEY duplicate prevention
108
+ - **SLOs**: Availability (raise on failure), Correctness (schema integrity), Observability (DuckDB logging), Maintainability (DuckDB library)
109
+ - **Class**: `DatabaseManager`
110
+ - **Methods**: `get_or_create_db(pair)`, `append_ticks(duckdb_path, df, table_name)`
111
+
112
+ 5. **`session_detector.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/session_detector.py`) - Holiday and session detection (121 lines)
113
+ - **Responsibility**: Detect holidays (US, UK, major) and trading sessions for 10 global exchanges using exchange_calendars
114
+ - **SLOs**: Availability (raise on failure), Correctness (official calendars), Observability (logging), Maintainability (exchange_calendars library)
115
+ - **Class**: `SessionDetector`
116
+ - **Methods**: `detect_sessions_and_holidays(dates_df)`
117
+
118
+ 6. **`gap_detector.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/gap_detector.py`) - Incremental update logic (163 lines)
119
+ - **Responsibility**: Discover missing months for incremental database updates
120
+ - **SLOs**: Availability (raise on failure), Correctness (gap detection), Observability (logging), Maintainability (DuckDB library)
121
+ - **Class**: `GapDetector`
122
+ - **Methods**: `discover_missing_months(pair, start_date)`
123
+
124
+ 7. **`ohlc_generator.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/ohlc_generator.py`) - OHLC generation (210 lines)
125
+ - **Responsibility**: Generate Phase7 30-column OHLC from dual-variant tick data with LEFT JOIN, normalized metrics, and exchange session detection
126
+ - **SLOs**: Availability (raise on failure), Correctness (Phase7 schema), Observability (logging), Maintainability (DuckDB + exchange_calendars)
127
+ - **Class**: `OHLCGenerator`
128
+ - **Methods**: `regenerate_ohlc(duckdb_path)`
129
+
130
+ 8. **`query_engine.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/query_engine.py`) - Query operations (283 lines)
131
+ - **Responsibility**: Query tick and OHLC data with date filtering, SQL filters, and on-demand resampling (1m/5m/15m/1h/4h/1d)
132
+ - **SLOs**: Availability (raise on failure), Correctness (SQL queries), Observability (DuckDB logging), Maintainability (DuckDB library)
133
+ - **Class**: `QueryEngine`
134
+ - **Methods**: `query_ticks()`, `query_ohlc()`, `get_data_coverage()`
135
+
136
+ **Legacy Components**:
137
+
138
+ 9. **`api.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/api.py`) - Simple wrapper functions
90
139
  - Convenience functions wrapping `ExnessDataProcessor` methods
91
140
  - Legacy v1.0.0 API compatibility layer (to be deprecated)
92
141
 
93
- 3. **`cli.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/cli.py`) - Command-line interface
94
- - Entry point: `exness-preprocess` command
95
- - Commands for download, query, coverage operations
142
+ 10. **`cli.py`** (`/Users/terryli/eon/exness-data-preprocess/src/exness_data_preprocess/cli.py`) - Command-line interface
143
+ - Entry point: `exness-preprocess` command
144
+ - Commands for download, query, coverage operations
96
145
 
97
146
  ### Key Design Patterns
98
147
 
148
+ **Facade Pattern** (v1.3.0):
149
+ - **processor.py** is a thin orchestrator (414 lines) coordinating 7 specialized modules
150
+ - All public methods delegate to modules (no business logic in processor)
151
+ - **Separation of concerns**: Each module has single responsibility
152
+ - **SLO-based design**: All modules define SLOs (Availability, Correctness, Observability, Maintainability)
153
+ - **Zero regressions**: All 48 tests pass after 7-module extraction (53% line reduction)
154
+ - **Off-the-shelf libraries**: httpx, pandas, DuckDB, exchange_calendars (no custom implementations)
155
+
99
156
  **Unified Single-File Architecture** (v2.0.0):
100
157
  - ONE DuckDB file per instrument (e.g., `eurusd.duckdb`) containing all historical data
101
158
  - NO monthly file separation (major change from v1.0.0)
102
159
  - Incremental updates with automatic gap detection
103
160
  - PRIMARY KEY constraints prevent duplicates during updates
104
161
 
105
- **Phase7 13-Column OHLC Schema** (v1.2.0):
162
+ **Phase7 30-Column OHLC Schema** (v1.5.0):
106
163
  - BID-only OHLC from Raw_Spread variant
107
164
  - Dual spreads: `raw_spread_avg` and `standard_spread_avg`
108
165
  - Dual tick counts: `tick_count_raw_spread` and `tick_count_standard`
109
166
  - Normalized metrics: `range_per_spread`, `range_per_tick`, `body_per_spread`, `body_per_tick`
167
+ - Timezone/session tracking: `ny_hour`, `london_hour`, `ny_session`, `london_session` (v1.3.0+)
168
+ - Holiday tracking: `is_us_holiday`, `is_uk_holiday`, `is_major_holiday` (v1.4.0+)
169
+ - Global exchange sessions: 10 binary flags (`is_nyse_session`, `is_lse_session`, `is_xswx_session`, `is_xfra_session`, `is_xtse_session`, `is_xnze_session`, `is_xtks_session`, `is_xasx_session`, `is_xhkg_session`, `is_xses_session`) covering 24-hour forex trading (v1.5.0)
110
170
  - Generated via LEFT JOIN between Raw_Spread and Standard variants
111
171
 
112
172
  **Self-Documentation**:
@@ -114,14 +174,16 @@ doppler run --project claude-config --config dev -- uv publish --token "$PYPI_TO
114
174
  - Queryable via `duckdb_tables()` and `duckdb_columns()` system functions
115
175
  - Enables BI tools and IDEs to display inline help
116
176
 
117
- **Data Flow**:
177
+ **Data Flow** (Module-Based Architecture v1.3.0):
118
178
  ```
119
179
  Exness Repository (monthly ZIPs)
120
- → Automatic Gap Detection
121
- → Download Missing Months (Raw_Spread + Standard)
122
- → DuckDB Storage (PRIMARY KEY prevents duplicates)
123
- → Phase7 OHLC Generation
124
- → Query Interface (date ranges, SQL filters, resampling)
180
+ → gap_detector.py (discover missing months)
181
+ → downloader.py (download Raw_Spread + Standard)
182
+ → tick_loader.py (parse CSV from ZIP)
183
+ → database_manager.py (append to DuckDB, PRIMARY KEY prevents duplicates)
184
+ → ohlc_generator.py (Phase7 30-column OHLC with LEFT JOIN)
185
+ → session_detector.py (holidays + 10 exchange sessions)
186
+ → query_engine.py (tick/OHLC queries, date filters, resampling)
125
187
  ```
126
188
 
127
189
  ### Database Schema (per instrument)
@@ -139,8 +201,8 @@ Each `.duckdb` file contains:
139
201
  - Reference data for spread comparison
140
202
 
141
203
  3. **`ohlc_1m`** table:
142
- - **Schema**: Phase7 13-column (v1.2.0) - See [`schema.py`](src/exness_data_preprocess/schema.py)
143
- - **Details**: BID-only OHLC with dual-variant spreads, tick counts, and normalized metrics
204
+ - **Schema**: Phase7 30-column (v1.5.0) - See [`schema.py`](src/exness_data_preprocess/schema.py)
205
+ - **Details**: BID-only OHLC with dual-variant spreads, tick counts, normalized metrics, and 10 global exchange sessions
144
206
  - **Reference**: [`DATABASE_SCHEMA.md`](docs/DATABASE_SCHEMA.md)
145
207
 
146
208
  4. **`metadata`** table:
@@ -180,7 +242,7 @@ Each `.duckdb` file contains:
180
242
  - ✅ **Dual-variant storage**: Raw_Spread + Standard in same database
181
243
  - ✅ **PRIMARY KEY constraints**: Prevents duplicates during incremental updates
182
244
  - ✅ **Automatic gap detection**: Downloads only missing months
183
- - ✅ **Phase7 13-column OHLC (v1.2.0)**: Dual spreads + dual tick counts
245
+ - ✅ **Phase7 30-column OHLC (v1.5.0)**: Dual spreads + dual tick counts + 10 global exchange sessions
184
246
  - ✅ **Date range queries**: Sub-15ms query performance
185
247
  - ✅ **On-demand resampling**: Any timeframe (5m, 1h, 1d) in <15ms
186
248
 
@@ -207,21 +269,29 @@ Each `.duckdb` file contains:
207
269
  - `/tmp/exness-duckdb-test/test_refactored_processor.py` - Validation test
208
270
  - `/tmp/exness-duckdb-test/test_queries_only.py` - Query validation test
209
271
 
210
- ### Phase7 13-Column OHLC Schema v1.2.0 (✅ Implemented)
272
+ ### Phase7 30-Column OHLC Schema v1.5.0 (✅ Implemented)
211
273
 
212
- **Decision**: Dual-variant BID-only OHLC with 13 columns capturing both Raw_Spread and Standard characteristics plus normalized metrics
274
+ **Decision**: Dual-variant BID-only OHLC with 30 columns capturing Raw_Spread and Standard characteristics, normalized metrics, and 10 global exchange sessions
213
275
 
214
- **Schema**: Phase7 13-column (v1.2.0)
276
+ **Schema**: Phase7 30-column (v1.5.0)
215
277
  - **Definition**: See [`schema.py`](src/exness_data_preprocess/schema.py)
216
278
  - **Documentation**: See [`DATABASE_SCHEMA.md`](docs/DATABASE_SCHEMA.md)
279
+ - **Architecture**: Exchange Registry Pattern for dynamic session column generation
217
280
 
218
281
  **Key Features**:
219
282
  - ✅ **BID-only OHLC**: Uses Raw_Spread Bid prices (execution prices)
220
283
  - ✅ **Dual spreads**: Tracks both Raw_Spread (zero-spreads) and Standard (market spreads)
221
284
  - ✅ **Dual tick counts**: Records tick counts from both variants
285
+ - ✅ **Normalized metrics** (v1.2.0): range_per_spread, range_per_tick, body_per_spread, body_per_tick
286
+ - ✅ **Timezone/session tracking** (v1.3.0): ny_hour, london_hour, ny_session, london_session with automatic DST handling
287
+ - ✅ **Holiday tracking** (v1.4.0): is_us_holiday, is_uk_holiday, is_major_holiday via exchange_calendars
288
+ - ✅ **10 Global Exchange Sessions** (v1.5.0): is_nyse_session, is_lse_session, is_xswx_session, is_xfra_session, is_xtse_session, is_xnze_session, is_xtks_session, is_xasx_session, is_xhkg_session, is_xses_session covering 24-hour forex trading
222
289
  - ✅ **LEFT JOIN methodology**: Raw_Spread primary, Standard reference
223
290
 
224
- **Implementation**: [`src/exness_data_preprocess/processor.py`](src/exness_data_preprocess/processor.py) (lines 518-549)
291
+ **Implementation**:
292
+ - **OHLC Generation**: [`src/exness_data_preprocess/ohlc_generator.py`](src/exness_data_preprocess/ohlc_generator.py) (210 lines)
293
+ - **Session Detection**: [`src/exness_data_preprocess/session_detector.py`](src/exness_data_preprocess/session_detector.py) (121 lines)
294
+ - **Orchestration**: [`src/exness_data_preprocess/processor.py`](src/exness_data_preprocess/processor.py) (lines 317-326, delegation)
225
295
 
226
296
  **Specification**: [`docs/research/eurusd-zero-spread-deviations/data/plan/phase7_bid_ohlc_construction_v1.1.0.md`](docs/research/eurusd-zero-spread-deviations/data/plan/phase7_bid_ohlc_construction_v1.1.0.md)
227
297
 
@@ -256,7 +326,7 @@ SELECT table_name, column_name, data_type, comment FROM duckdb_columns();
256
326
  - `add_schema_comments(pair)` - Add comments to single database
257
327
  - `add_schema_comments_all()` - Batch-update all databases
258
328
 
259
- **Implementation**: [`src/exness_data_preprocess/processor.py`](src/exness_data_preprocess/processor.py) (lines 138-229, 708-821)
329
+ **Implementation**: [`src/exness_data_preprocess/database_manager.py`](src/exness_data_preprocess/database_manager.py) (schema comments in get_or_create_db method)
260
330
 
261
331
  **Usage Example**: [`examples/add_schema_comments.py`](examples/add_schema_comments.py)
262
332
 
@@ -314,7 +384,7 @@ SELECT table_name, column_name, data_type, comment FROM duckdb_columns();
314
384
  - ✅ **Dual-variant storage** - Raw_Spread + Standard in same database
315
385
  - ✅ **PRIMARY KEY constraints** - Prevents duplicates during incremental updates
316
386
  - ✅ **Automatic gap detection** - Downloads only missing months
317
- - ✅ **Phase7 13-column OHLC (v1.2.0)** - Dual spreads + dual tick counts
387
+ - ✅ **Phase7 30-column OHLC (v1.5.0)** - Dual spreads + dual tick counts + 10 global exchange sessions
318
388
  - ✅ **Date range queries** - Sub-15ms query performance
319
389
  - ✅ **On-demand resampling** - Any timeframe in <15ms
320
390
  - ✅ **SQL filter support** - Direct SQL WHERE clauses on ticks
@@ -359,7 +429,7 @@ SELECT table_name, column_name, data_type, comment FROM duckdb_columns();
359
429
  eurusd.duckdb:
360
430
  ├── raw_spread_ticks # Timestamp (PK), Bid, Ask
361
431
  ├── standard_ticks # Timestamp (PK), Bid, Ask
362
- ├── ohlc_1m # Phase7 13-column schema (v1.2.0)
432
+ ├── ohlc_1m # Phase7 30-column schema (v1.5.0)
363
433
  └── metadata # Coverage tracking
364
434
  ```
365
435
 
@@ -399,6 +469,7 @@ eurusd.duckdb:
399
469
 
400
470
  ---
401
471
 
402
- **Version**: 2.0.0
403
- **Last Updated**: 2025-10-12
472
+ **Version**: 2.0.0 (Architecture) + 1.3.0 (Implementation)
473
+ **Last Updated**: 2025-10-15
404
474
  **Architecture**: Unified Single-File DuckDB Storage with Incremental Updates
475
+ **Implementation**: Facade Pattern with 7 Specialized Modules (Phase 1-4 Complete)
@@ -173,7 +173,7 @@ gh release create v0.1.0 \
173
173
 
174
174
  **Architecture v2.0.0:**
175
175
  - Unified single-file DuckDB storage per instrument
176
- - Phase7 9-column OHLC schema with dual-variant spreads
176
+ - Phase7 13-column (v1.2.0) OHLC schema with dual-variant spreads and normalized metrics
177
177
  - Sub-15ms query performance with date range filtering
178
178
  - PRIMARY KEY constraints prevent duplicates
179
179
  - Automatic gap detection for incremental updates
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exness-data-preprocess
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Professional Exness forex tick data preprocessing with optimal compression (Parquet Zstd-22) and DuckDB OHLC generation. Provides efficient storage (9% smaller than ZIP) 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
@@ -30,6 +30,7 @@ Classifier: Topic :: Scientific/Engineering :: Information Analysis
30
30
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
31
  Requires-Python: >=3.9
32
32
  Requires-Dist: duckdb>=0.9.0
33
+ Requires-Dist: exchange-calendars>=4.5.6
33
34
  Requires-Dist: httpx>=0.25.0
34
35
  Requires-Dist: pandas>=2.0.0
35
36
  Requires-Dist: pyarrow>=16.0.0
@@ -55,14 +56,14 @@ Description-Content-Type: text/markdown
55
56
  [![Downloads](https://img.shields.io/pypi/dm/exness-data-preprocess.svg)](https://pypi.org/project/exness-data-preprocess/)
56
57
  [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
57
58
 
58
- Professional forex tick data preprocessing with unified single-file DuckDB storage. Provides incremental updates, dual-variant storage (Raw_Spread + Standard), and Phase7 13-column OHLC schema (v1.2.0) with sub-15ms query performance.
59
+ Professional forex tick data preprocessing with unified single-file DuckDB storage. Provides incremental updates, dual-variant storage (Raw_Spread + Standard), and Phase7 30-column OHLC schema (v1.5.0) with 10 global exchange sessions and sub-15ms query performance.
59
60
 
60
61
  ## Features
61
62
 
62
63
  - **Unified Single-File Architecture**: One DuckDB file per instrument (eurusd.duckdb)
63
64
  - **Incremental Updates**: Automatic gap detection and download only missing months
64
65
  - **Dual-Variant Storage**: Raw_Spread (primary) + Standard (reference) in same database
65
- - **Phase7 OHLC Schema**: 13-column bars (v1.2.0) with dual spreads, tick counts, and normalized metrics
66
+ - **Phase7 OHLC Schema**: 30-column bars (v1.5.0) with dual spreads, tick counts, normalized metrics, and 10 global exchange sessions
66
67
  - **Fast Queries**: Date range queries with sub-15ms performance
67
68
  - **On-Demand Resampling**: Any timeframe (5m, 1h, 1d) resampled in <15ms
68
69
  - **PRIMARY KEY Constraints**: Prevents duplicate data during incremental updates
@@ -138,7 +139,7 @@ Download Only Missing Months (Raw_Spread + Standard)
138
139
  ↓
139
140
  DuckDB Single-File Storage (PRIMARY KEY prevents duplicates)
140
141
  ↓
141
- Phase7 13-Column OHLC Generation (v1.2.0 - dual spreads, tick counts, normalized metrics)
142
+ Phase7 30-Column OHLC Generation (v1.5.0 - dual spreads, tick counts, normalized metrics, 10 global exchange sessions)
142
143
  ↓
143
144
  Query Interface (date ranges, SQL filters, on-demand resampling)
144
145
  ```
@@ -150,13 +151,13 @@ Query Interface (date ranges, SQL filters, on-demand resampling)
150
151
  **Schema**:
151
152
  - `raw_spread_ticks` table: Timestamp (PK), Bid, Ask
152
153
  - `standard_ticks` table: Timestamp (PK), Bid, Ask
153
- - `ohlc_1m` table: Phase7 13-column schema (v1.2.0)
154
+ - `ohlc_1m` table: Phase7 30-column schema (v1.5.0)
154
155
  - `metadata` table: Coverage tracking
155
156
 
156
- **Phase7 13-Column OHLC (v1.2.0)**:
157
+ **Phase7 30-Column OHLC (v1.5.0)**:
157
158
  - **Column Definitions**: See [`schema.py`](src/exness_data_preprocess/schema.py) - Single source of truth
158
159
  - **Comprehensive Reference**: See [`DATABASE_SCHEMA.md`](docs/DATABASE_SCHEMA.md) - Query examples and usage patterns
159
- - **Key Features**: BID-only OHLC with dual spreads (Raw_Spread + Standard) and normalized spread metrics
160
+ - **Key Features**: BID-only OHLC with dual spreads (Raw_Spread + Standard), normalized spread metrics, and 10 global exchange sessions (XNYS, XLON, XSWX, XFRA, XTSE, XNZE, XTKS, XASX, XHKG, XSES)
160
161
 
161
162
  ### Directory Structure
162
163
 
@@ -159,7 +159,7 @@ class UpdateResult(BaseModel):
159
159
  )
160
160
  ohlc_bars: int = Field(
161
161
  ge=0,
162
- description="Total 1-minute OHLC bars in database (Phase7 9-column schema)"
162
+ description="Total 1-minute OHLC bars in database (Phase7 13-column v1.2.0 schema)"
163
163
  )
164
164
  duckdb_size_mb: float = Field(
165
165
  ge=0,
@@ -347,7 +347,7 @@ def update_data(
347
347
  1. Discover missing months between start_date and current month
348
348
  2. Download missing months from ticks.ex2archive.com (both variants)
349
349
  3. Insert ticks into DuckDB with PRIMARY KEY duplicate prevention
350
- 4. Regenerate Phase7 9-column OHLC with dual spreads
350
+ 4. Regenerate Phase7 13-column (v1.2.0) OHLC with dual spreads and normalized metrics
351
351
  5. Update metadata table with coverage statistics
352
352
 
353
353
  Args:
@@ -559,13 +559,12 @@ def query_ohlc(
559
559
  timeframes. All resampling is performed in-database using DuckDB's window
560
560
  functions for optimal performance (<15ms for most queries).
561
561
 
562
- The returned DataFrame contains Phase7 9-column schema:
563
- - Timestamp: Bar timestamp (UTC)
564
- - Open, High, Low, Close: BID prices from Raw_Spread variant
565
- - raw_spread_avg: Average spread from Raw_Spread variant
566
- - standard_spread_avg: Average spread from Standard variant
567
- - tick_count_raw_spread: Tick count from Raw_Spread variant
568
- - tick_count_standard: Tick count from Standard variant
562
+ The returned DataFrame contains Phase7 13-column (v1.2.0) schema:
563
+ - See schema.py for complete 13-column definition
564
+ - Core: Timestamp, Open, High, Low, Close (BID prices from Raw_Spread)
565
+ - Dual Spreads: raw_spread_avg, standard_spread_avg
566
+ - Dual Tick Counts: tick_count_raw_spread, tick_count_standard
567
+ - Normalized Metrics: range_per_spread, range_per_tick, body_per_spread, body_per_tick
569
568
 
570
569
  Args:
571
570
  pair: Currency pair (EURUSD, GBPUSD, XAUUSD, USDJPY, AUDUSD)
@@ -574,7 +573,7 @@ def query_ohlc(
574
573
  end_date: Optional end date in YYYY-MM-DD format (inclusive)
575
574
 
576
575
  Returns:
577
- DataFrame with Phase7 9-column OHLC schema. Empty if no data in range.
576
+ DataFrame with Phase7 13-column (v1.2.0) OHLC schema. Empty if no data in range.
578
577
 
579
578
  Raises:
580
579
  FileNotFoundError: If database doesn't exist (call update_data first)
@@ -7,14 +7,14 @@
7
7
  [![Downloads](https://img.shields.io/pypi/dm/exness-data-preprocess.svg)](https://pypi.org/project/exness-data-preprocess/)
8
8
  [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
9
9
 
10
- Professional forex tick data preprocessing with unified single-file DuckDB storage. Provides incremental updates, dual-variant storage (Raw_Spread + Standard), and Phase7 13-column OHLC schema (v1.2.0) with sub-15ms query performance.
10
+ Professional forex tick data preprocessing with unified single-file DuckDB storage. Provides incremental updates, dual-variant storage (Raw_Spread + Standard), and Phase7 30-column OHLC schema (v1.5.0) with 10 global exchange sessions and sub-15ms query performance.
11
11
 
12
12
  ## Features
13
13
 
14
14
  - **Unified Single-File Architecture**: One DuckDB file per instrument (eurusd.duckdb)
15
15
  - **Incremental Updates**: Automatic gap detection and download only missing months
16
16
  - **Dual-Variant Storage**: Raw_Spread (primary) + Standard (reference) in same database
17
- - **Phase7 OHLC Schema**: 13-column bars (v1.2.0) with dual spreads, tick counts, and normalized metrics
17
+ - **Phase7 OHLC Schema**: 30-column bars (v1.5.0) with dual spreads, tick counts, normalized metrics, and 10 global exchange sessions
18
18
  - **Fast Queries**: Date range queries with sub-15ms performance
19
19
  - **On-Demand Resampling**: Any timeframe (5m, 1h, 1d) resampled in <15ms
20
20
  - **PRIMARY KEY Constraints**: Prevents duplicate data during incremental updates
@@ -90,7 +90,7 @@ Download Only Missing Months (Raw_Spread + Standard)
90
90
  ↓
91
91
  DuckDB Single-File Storage (PRIMARY KEY prevents duplicates)
92
92
  ↓
93
- Phase7 13-Column OHLC Generation (v1.2.0 - dual spreads, tick counts, normalized metrics)
93
+ Phase7 30-Column OHLC Generation (v1.5.0 - dual spreads, tick counts, normalized metrics, 10 global exchange sessions)
94
94
  ↓
95
95
  Query Interface (date ranges, SQL filters, on-demand resampling)
96
96
  ```
@@ -102,13 +102,13 @@ Query Interface (date ranges, SQL filters, on-demand resampling)
102
102
  **Schema**:
103
103
  - `raw_spread_ticks` table: Timestamp (PK), Bid, Ask
104
104
  - `standard_ticks` table: Timestamp (PK), Bid, Ask
105
- - `ohlc_1m` table: Phase7 13-column schema (v1.2.0)
105
+ - `ohlc_1m` table: Phase7 30-column schema (v1.5.0)
106
106
  - `metadata` table: Coverage tracking
107
107
 
108
- **Phase7 13-Column OHLC (v1.2.0)**:
108
+ **Phase7 30-Column OHLC (v1.5.0)**:
109
109
  - **Column Definitions**: See [`schema.py`](src/exness_data_preprocess/schema.py) - Single source of truth
110
110
  - **Comprehensive Reference**: See [`DATABASE_SCHEMA.md`](docs/DATABASE_SCHEMA.md) - Query examples and usage patterns
111
- - **Key Features**: BID-only OHLC with dual spreads (Raw_Spread + Standard) and normalized spread metrics
111
+ - **Key Features**: BID-only OHLC with dual spreads (Raw_Spread + Standard), normalized spread metrics, and 10 global exchange sessions (XNYS, XLON, XSWX, XFRA, XTSE, XNZE, XTKS, XASX, XHKG, XSES)
112
112
 
113
113
  ### Directory Structure
114
114
 
@@ -0,0 +1,6 @@
1
+
2
+ ## 0.3.0 - 2025-10-15
3
+
4
+
5
+ ---
6
+ **Full Changelog**: https://github.com/Eon-Labs/rangebar/compare/v0.2.0...v0.3.0
@@ -0,0 +1,131 @@
1
+ # git-cliff configuration for GitHub release notes generation
2
+ # Optimized for user-friendly, marketing-style release announcements
3
+
4
+ [changelog]
5
+ header = ""
6
+ body = """
7
+ ## {% if version %}{{ version | trim_start_matches(pat="v") }}{% else %}Unreleased{% endif %} - {{ timestamp | date(format="%Y-%m-%d") }}
8
+
9
+ {% for group, commits in commits | group_by(attribute="group") %}
10
+ ### {{ group }}
11
+ {% for commit in commits | unique(attribute="message") %}
12
+ - {% if commit.breaking %}⚠️ **BREAKING**: {% endif %}\
13
+ {{ commit.message | upper_first }}\
14
+ {% if commit.github.username %} (by @{{ commit.github.username }}){% endif %}
15
+ {% endfor %}
16
+
17
+ {% endfor %}
18
+ ---
19
+ **Full Changelog**: https://github.com/Eon-Labs/rangebar/compare/{{ previous.version }}...{{ version }}
20
+ """
21
+ footer = ""
22
+ trim = true
23
+
24
+ [git]
25
+ conventional_commits = true
26
+ filter_unconventional = false
27
+ split_commits = false
28
+ tag_pattern = "v[0-9]*"
29
+ tag_prefix = "v"
30
+ skip_tags = ""
31
+ ignore_tags = ""
32
+
33
+ [[git.commit_parsers]]
34
+ # Breaking changes (most prominent)
35
+ message = "^.*!:"
36
+ group = "⚠️ Breaking Changes"
37
+
38
+ [[git.commit_parsers]]
39
+ body = ".*BREAKING[- ]CHANGE.*"
40
+ group = "⚠️ Breaking Changes"
41
+
42
+ # Features (user-facing semantic grouping)
43
+ [[git.commit_parsers]]
44
+ message = "^feat\\(sanitization\\)"
45
+ group = "🧹 Codebase Sanitization"
46
+
47
+ [[git.commit_parsers]]
48
+ message = "^feat\\(security\\)"
49
+ group = "🔒 Security Enhancements"
50
+
51
+ [[git.commit_parsers]]
52
+ message = "^feat\\(perf\\)"
53
+ group = "🚀 Performance Improvements"
54
+
55
+ [[git.commit_parsers]]
56
+ message = "^feat\\(deps\\)"
57
+ group = "📦 Dependency Management"
58
+
59
+ [[git.commit_parsers]]
60
+ message = "^feat"
61
+ group = "✨ New Features"
62
+
63
+ # Fixes (user-impacting only)
64
+ [[git.commit_parsers]]
65
+ message = "^fix\\(security\\)"
66
+ group = "🔒 Security Fixes"
67
+
68
+ [[git.commit_parsers]]
69
+ message = "^fix\\(perf\\)"
70
+ group = "🚀 Performance Fixes"
71
+
72
+ [[git.commit_parsers]]
73
+ message = "^fix"
74
+ group = "🐛 Bug Fixes & Improvements"
75
+
76
+ # Infrastructure (consolidated)
77
+ [[git.commit_parsers]]
78
+ message = "^(fix|feat)\\(ci\\)"
79
+ group = "🔧 Infrastructure & CI/CD"
80
+
81
+ [[git.commit_parsers]]
82
+ message = "^(fix|feat)\\(fmt\\)"
83
+ group = "🔧 Infrastructure & CI/CD"
84
+
85
+ [[git.commit_parsers]]
86
+ message = "^(fix|feat)\\(clippy\\)"
87
+ group = "🔧 Infrastructure & CI/CD"
88
+
89
+ # Skip non-user-facing commits (chore, docs, test, etc.)
90
+ [[git.commit_parsers]]
91
+ message = "^chore"
92
+ skip = true
93
+
94
+ [[git.commit_parsers]]
95
+ message = "^docs"
96
+ skip = true
97
+
98
+ [[git.commit_parsers]]
99
+ message = "^test"
100
+ skip = true
101
+
102
+ [[git.commit_parsers]]
103
+ message = "^build"
104
+ skip = true
105
+
106
+ [[git.commit_parsers]]
107
+ message = "^ci"
108
+ skip = true
109
+
110
+ [[git.commit_parsers]]
111
+ message = "^style"
112
+ skip = true
113
+
114
+ [[git.commit_parsers]]
115
+ message = "^refactor"
116
+ skip = true
117
+
118
+ # Catch-all for anything else
119
+ [[git.commit_parsers]]
120
+ message = ".*"
121
+ group = "📝 Other Changes"
122
+
123
+ [[git.commit_preprocessors]]
124
+ # Remove gitmoji to avoid duplication with our emoji groups
125
+ pattern = ':\w+:'
126
+ replace = ""
127
+
128
+ [[git.commit_preprocessors]]
129
+ # Clean up extra whitespace
130
+ pattern = '\s+'
131
+ replace = " "