rangebar 12.1.0__tar.gz → 12.1.2__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 (300) hide show
  1. {rangebar-12.1.0 → rangebar-12.1.2}/.mise.toml +13 -0
  2. {rangebar-12.1.0 → rangebar-12.1.2}/CHANGELOG.md +14 -0
  3. {rangebar-12.1.0 → rangebar-12.1.2}/Cargo.lock +9 -9
  4. {rangebar-12.1.0 → rangebar-12.1.2}/Cargo.toml +1 -1
  5. {rangebar-12.1.0 → rangebar-12.1.2}/PKG-INFO +1 -1
  6. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/interbar.rs +59 -7
  7. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/processor.rs +22 -2
  8. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/constants.py +11 -0
  9. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/helpers.py +37 -2
  10. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/range_bars.py +21 -1
  11. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/core.py +8 -1
  12. {rangebar-12.1.0 → rangebar-12.1.2}/.cargo/config.toml +0 -0
  13. {rangebar-12.1.0 → rangebar-12.1.2}/.gitignore +0 -0
  14. {rangebar-12.1.0 → rangebar-12.1.2}/.mcp.json +0 -0
  15. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/bench.toml +0 -0
  16. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/cache.toml +0 -0
  17. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/checksum.toml +0 -0
  18. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/deps.toml +0 -0
  19. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/dev.toml +0 -0
  20. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/diag.toml +0 -0
  21. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/prof.toml +0 -0
  22. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/release.toml +0 -0
  23. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/research.toml +0 -0
  24. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/smoke.toml +0 -0
  25. {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/validate.toml +0 -0
  26. {rangebar-12.1.0 → rangebar-12.1.2}/.pre-commit-config.yaml +0 -0
  27. {rangebar-12.1.0 → rangebar-12.1.2}/.releaserc.yml +0 -0
  28. {rangebar-12.1.0 → rangebar-12.1.2}/CLAUDE.md +0 -0
  29. {rangebar-12.1.0 → rangebar-12.1.2}/LICENSE +0 -0
  30. {rangebar-12.1.0 → rangebar-12.1.2}/README.md +0 -0
  31. {rangebar-12.1.0 → rangebar-12.1.2}/RESUME.md +0 -0
  32. {rangebar-12.1.0 → rangebar-12.1.2}/STATISTICAL_VALIDITY_AUDIT.md +0 -0
  33. {rangebar-12.1.0 → rangebar-12.1.2}/benches/rangebar_bench.rs +0 -0
  34. {rangebar-12.1.0 → rangebar-12.1.2}/build.rs +0 -0
  35. {rangebar-12.1.0 → rangebar-12.1.2}/crates/CLAUDE.md +0 -0
  36. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/CHANGELOG.md +0 -0
  37. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/Cargo.toml +0 -0
  38. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/README.md +0 -0
  39. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/arrow_export.rs +0 -0
  40. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/checkpoint.rs +0 -0
  41. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/fixed_point.rs +0 -0
  42. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/drawdown.rs +0 -0
  43. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/features.rs +0 -0
  44. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/ith.rs +0 -0
  45. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/mod.rs +0 -0
  46. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/normalize.rs +0 -0
  47. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/types.rs +0 -0
  48. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/lib.rs +0 -0
  49. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_data_loader.rs +0 -0
  50. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_utils/generators.rs +0 -0
  51. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_utils/mod.rs +0 -0
  52. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/timestamp.rs +0 -0
  53. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/types.rs +0 -0
  54. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_boundary_validation.rs +0 -0
  55. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_date_real_data_validation.rs +0 -0
  56. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_year_boundary_test.rs +0 -0
  57. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs +0 -0
  58. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/CHANGELOG.md +0 -0
  59. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/Cargo.toml +0 -0
  60. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/README.md +0 -0
  61. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/checksum.rs +0 -0
  62. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/historical.rs +0 -0
  63. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/mod.rs +0 -0
  64. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/symbols.rs +0 -0
  65. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/websocket.rs +0 -0
  66. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/builder.rs +0 -0
  67. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/client.rs +0 -0
  68. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/conversion.rs +0 -0
  69. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/mod.rs +0 -0
  70. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/types.rs +0 -0
  71. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/lib.rs +0 -0
  72. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/CHANGELOG.md +0 -0
  73. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/Cargo.toml +0 -0
  74. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/README.md +0 -0
  75. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/indicators.rs +0 -0
  76. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/lib.rs +0 -0
  77. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/processor.rs +0 -0
  78. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/replay_buffer.rs +0 -0
  79. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/stats.rs +0 -0
  80. {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/universal.rs +0 -0
  81. {rangebar-12.1.0 → rangebar-12.1.2}/deny.toml +0 -0
  82. {rangebar-12.1.0 → rangebar-12.1.2}/docs/ARCHITECTURE.md +0 -0
  83. {rangebar-12.1.0 → rangebar-12.1.2}/docs/CONTEXT.md +0 -0
  84. {rangebar-12.1.0 → rangebar-12.1.2}/docs/MEMORY_REMEDIATION_PLAN.md +0 -0
  85. {rangebar-12.1.0 → rangebar-12.1.2}/docs/adr/2026-01-31-realtime-streaming-api.md +0 -0
  86. {rangebar-12.1.0 → rangebar-12.1.2}/docs/analysis/2025-10-10-flash-crash.md +0 -0
  87. {rangebar-12.1.0 → rangebar-12.1.2}/docs/api.md +0 -0
  88. {rangebar-12.1.0 → rangebar-12.1.2}/docs/development/PERFORMANCE.md +0 -0
  89. {rangebar-12.1.0 → rangebar-12.1.2}/docs/development/RELEASE.md +0 -0
  90. {rangebar-12.1.0 → rangebar-12.1.2}/docs/migration-v8.md +0 -0
  91. {rangebar-12.1.0 → rangebar-12.1.2}/docs/plans/issue-59-inter-bar-features.md +0 -0
  92. {rangebar-12.1.0 → rangebar-12.1.2}/docs/rangebar_core_api.md +0 -0
  93. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-02-intrabar-microstructure-claude-opus.md +0 -0
  94. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-02-intrabar-microstructure-gemini-3-pro.md +0 -0
  95. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-03-cfm-optimal-threshold-gemini-3-pro.md +0 -0
  96. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-03-memory-efficient-streaming.md +0 -0
  97. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/INDEX.md +0 -0
  98. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/adversarial-audit-methodology.md +0 -0
  99. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/external/time-to-convergence-stationarity-gap.md +0 -0
  100. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/labeling-for-ml.md +0 -0
  101. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/market-regime-patterns.md +0 -0
  102. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/multi-threshold-patterns.md +0 -0
  103. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/multifactor-patterns.md +0 -0
  104. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/pattern-research-summary.md +0 -0
  105. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/price-action-patterns.md +0 -0
  106. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/tda-parameter-sensitivity-audit.md +0 -0
  107. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/tda-regime-patterns.md +0 -0
  108. {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/volatility-regime-patterns.md +0 -0
  109. {rangebar-12.1.0 → rangebar-12.1.2}/docs/verification/issue-62-verification-report.md +0 -0
  110. {rangebar-12.1.0 → rangebar-12.1.2}/examples/README.md +0 -0
  111. {rangebar-12.1.0 → rangebar-12.1.2}/examples/backtesting_integration.py +0 -0
  112. {rangebar-12.1.0 → rangebar-12.1.2}/examples/basic_usage.py +0 -0
  113. {rangebar-12.1.0 → rangebar-12.1.2}/examples/binance_csv_example.py +0 -0
  114. {rangebar-12.1.0 → rangebar-12.1.2}/examples/get_range_bars_example.py +0 -0
  115. {rangebar-12.1.0 → rangebar-12.1.2}/examples/validate_output.py +0 -0
  116. {rangebar-12.1.0 → rangebar-12.1.2}/examples/with_clickhouse_cache.py +0 -0
  117. {rangebar-12.1.0 → rangebar-12.1.2}/package-lock.json +0 -0
  118. {rangebar-12.1.0 → rangebar-12.1.2}/package.json +0 -0
  119. {rangebar-12.1.0 → rangebar-12.1.2}/pyproject.toml +0 -0
  120. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/CLAUDE.md +0 -0
  121. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/__init__.py +0 -0
  122. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/__init__.pyi +0 -0
  123. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/checkpoint.py +0 -0
  124. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/cli.py +0 -0
  125. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/CLAUDE.md +0 -0
  126. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/__init__.py +0 -0
  127. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/bulk_operations.py +0 -0
  128. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/cache.py +0 -0
  129. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/client.py +0 -0
  130. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/config.py +0 -0
  131. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/mixin.py +0 -0
  132. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/preflight.py +0 -0
  133. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/query_operations.py +0 -0
  134. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/schema.sql +0 -0
  135. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/tunnel.py +0 -0
  136. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/conversion.py +0 -0
  137. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/exceptions.py +0 -0
  138. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/exness.py +0 -0
  139. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/hooks.py +0 -0
  140. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/logging.py +0 -0
  141. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/__init__.py +0 -0
  142. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/pushover.py +0 -0
  143. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/telegram.py +0 -0
  144. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/__init__.py +0 -0
  145. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/count_bounded.py +0 -0
  146. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/models.py +0 -0
  147. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/precompute.py +0 -0
  148. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/tick_fetcher.py +0 -0
  149. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/ouroboros.py +0 -0
  150. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/__init__.py +0 -0
  151. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/api.py +0 -0
  152. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/resource_guard.py +0 -0
  153. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/__init__.py +0 -0
  154. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/checksum_registry.py +0 -0
  155. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/parquet.py +0 -0
  156. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/streaming.py +0 -0
  157. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/threshold.py +0 -0
  158. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/__init__.py +0 -0
  159. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/cache_staleness.py +0 -0
  160. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/continuity.py +0 -0
  161. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/gap_classification.py +0 -0
  162. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/post_storage.py +0 -0
  163. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/tier1.py +0 -0
  164. {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/tier2.py +0 -0
  165. {rangebar-12.1.0 → rangebar-12.1.2}/rust-toolchain.toml +0 -0
  166. {rangebar-12.1.0 → rangebar-12.1.2}/rustfmt.toml +0 -0
  167. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/adwin_regime_detection_polars.py +0 -0
  168. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/analyze_flash_crash.py +0 -0
  169. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/bootstrap_permutation_validation_polars.py +0 -0
  170. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/build-release.sh +0 -0
  171. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cache_clear.py +0 -0
  172. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cache_status.py +0 -0
  173. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/check-release-config.sh +0 -0
  174. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/coarse_to_fine_cascade.py +0 -0
  175. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_pattern_audit_polars.py +0 -0
  176. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_regime_analysis_polars.py +0 -0
  177. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_rv_alignment_analysis_polars.py +0 -0
  178. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_asset_correlation_polars.py +0 -0
  179. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_regime_correlation_polars.py +0 -0
  180. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_threshold_alignment.py +0 -0
  181. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/dependency_monitor.sh +0 -0
  182. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/direction_patterns_reaudit.py +0 -0
  183. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/download_exness_eurusd.py +0 -0
  184. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/download_exness_forex.py +0 -0
  185. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_autocorrelation.py +0 -0
  186. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_autocorrelation_audit.py +0 -0
  187. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_volatility_prediction.py +0 -0
  188. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fdr_corrected_patterns.py +0 -0
  189. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_all_symbols.py +0 -0
  190. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_2025_2026.py +0 -0
  191. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_littleblack.py +0 -0
  192. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_retry.py +0 -0
  193. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/historical_formation_patterns_polars.py +0 -0
  194. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/historical_formation_regime_polars.py +0 -0
  195. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_adjusted_kelly_polars.py +0 -0
  196. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_adjusted_psr_analysis_polars.py +0 -0
  197. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_exponent_analysis_polars.py +0 -0
  198. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_multi_estimator_audit.py +0 -0
  199. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_clickhouse.py +0 -0
  200. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_patterns.py +0 -0
  201. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_simple.py +0 -0
  202. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/monitor_population.py +0 -0
  203. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multi_threshold_pattern_analysis_polars.py +0 -0
  204. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multibar_continuation.py +0 -0
  205. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multibar_forward_returns_polars.py +0 -0
  206. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_multigranularity_patterns.py +0 -0
  207. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_patterns.py +0 -0
  208. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_patterns_polars.py +0 -0
  209. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multithreshold_combinations_polars.py +0 -0
  210. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multithreshold_regime_combinations_polars.py +0 -0
  211. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/oos_validation_polars.py +0 -0
  212. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/parameter_sensitivity_polars.py +0 -0
  213. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_correlation_analysis_polars.py +0 -0
  214. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_return_profiles_polars.py +0 -0
  215. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_return_stats.py +0 -0
  216. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_1000dbps.py +0 -0
  217. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_250dbps.py +0 -0
  218. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_250dbps_extended.py +0 -0
  219. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_safe.py +0 -0
  220. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/position_sizing_analysis_polars.py +0 -0
  221. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/process_exness_eurusd_to_cache.py +0 -0
  222. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/profiling_tools.sh +0 -0
  223. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/psr_mintrl_analysis_polars.py +0 -0
  224. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/publish-to-pypi.sh +0 -0
  225. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/publish-wheels.sh +0 -0
  226. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/purge_crypto_low_threshold.py +0 -0
  227. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regenerate_cache.py +0 -0
  228. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis.py +0 -0
  229. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis_50dbps_polars.py +0 -0
  230. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis_polars.py +0 -0
  231. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_transition_analysis_polars.py +0 -0
  232. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_large_scale_benchmark.sh +0 -0
  233. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_analysis.py +0 -0
  234. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_multi_symbol.py +0 -0
  235. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_wfo.py +0 -0
  236. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/rv_return_profile_analysis_polars.py +0 -0
  237. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/semantic-release.sh +0 -0
  238. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_break_event_alignment_polars.py +0 -0
  239. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_conditioned_patterns.py +0 -0
  240. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_cupy_accelerated.py +0 -0
  241. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_gpu_analysis.py +0 -0
  242. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_hurst_by_regime_polars.py +0 -0
  243. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_parameter_sweep_audit.py +0 -0
  244. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_regime_hurst_analysis_polars.py +0 -0
  245. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_regime_pattern_analysis_polars.py +0 -0
  246. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_ripser_plusplus.py +0 -0
  247. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_rolling_threshold.py +0 -0
  248. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_solusdt_250_audit.py +0 -0
  249. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_solusdt_250_littleblack.py +0 -0
  250. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_structural_break_analysis_polars.py +0 -0
  251. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_volatility_forecast.py +0 -0
  252. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_3way.py +0 -0
  253. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_abstain.py +0 -0
  254. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_audit.py +0 -0
  255. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/temporal_safe_patterns_polars.py +0 -0
  256. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_alignment_analysis_polars.py +0 -0
  257. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_pattern_analysis_polars.py +0 -0
  258. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_pattern_audit_polars.py +0 -0
  259. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_factor_hurst_analysis_polars.py +0 -0
  260. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_factor_pattern_analysis_polars.py +0 -0
  261. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/transaction_cost_analysis_polars.py +0 -0
  262. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/trend_filter_analysis.py +0 -0
  263. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/upload_eurusd_to_clickhouse.py +0 -0
  264. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_clickhouse.py +0 -0
  265. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_memory_efficiency.py +0 -0
  266. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_microstructure_features.py +0 -0
  267. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_n_range_bars.py +0 -0
  268. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volatility_regime_analysis_polars.py +0 -0
  269. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volatility_regime_audit_polars.py +0 -0
  270. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volume_conditioned_patterns.py +0 -0
  271. {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volume_conditioned_patterns_polars.py +0 -0
  272. {rangebar-12.1.0 → rangebar-12.1.2}/src/lib.rs +0 -0
  273. {rangebar-12.1.0 → rangebar-12.1.2}/test_data/BTCUSDT/BTCUSDT_aggTrades_20250901.csv +0 -0
  274. {rangebar-12.1.0 → rangebar-12.1.2}/test_data/ETHUSDT/ETHUSDT_aggTrades_20250901.csv +0 -0
  275. {rangebar-12.1.0 → rangebar-12.1.2}/test_data/README.md +0 -0
  276. {rangebar-12.1.0 → rangebar-12.1.2}/tests/conftest.py +0 -0
  277. {rangebar-12.1.0 → rangebar-12.1.2}/tests/fixtures/.gitignore +0 -0
  278. {rangebar-12.1.0 → rangebar-12.1.2}/tests/fixtures/BTCUSDT-aggTrades-2024-01-01.zip +0 -0
  279. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_cache_schema_evolution.py +0 -0
  280. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_clickhouse.py +0 -0
  281. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_clickhouse_integration.py +0 -0
  282. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_crypto_minimum_threshold.py +0 -0
  283. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_e2e_optimized.py +0 -0
  284. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_edge_cases.py +0 -0
  285. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_examples.py +0 -0
  286. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_get_n_range_bars.py +0 -0
  287. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_get_range_bars_e2e.py +0 -0
  288. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_issue_5_reproduction.py +0 -0
  289. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_issues_7_8.py +0 -0
  290. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_microstructure_features.py +0 -0
  291. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_ouroboros.py +0 -0
  292. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_polars_only_downstream.py +0 -0
  293. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_preflight.py +0 -0
  294. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_python_api.py +0 -0
  295. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_real_data.py +0 -0
  296. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_rust_bindings.py +0 -0
  297. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_storage.py +0 -0
  298. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_streaming.py +0 -0
  299. {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_validation_presets.py +0 -0
  300. {rangebar-12.1.0 → rangebar-12.1.2}/uv.lock +0 -0
@@ -27,6 +27,19 @@ RANGEBAR_FOREX_MIN_THRESHOLD = "50"
27
27
  RANGEBAR_EQUITIES_MIN_THRESHOLD = "100"
28
28
  RANGEBAR_UNKNOWN_MIN_THRESHOLD = "1"
29
29
 
30
+ # =============================================================================
31
+ # SSoT: Microstructure Feature Defaults (Issue #68)
32
+ # =============================================================================
33
+ # When include_microstructure=True, these defaults are used unless overridden.
34
+ # INTER_BAR_LOOKBACK_COUNT: Trades in lookback window for inter-bar features.
35
+ # - Recommended: 100-500 (200 is good balance of signal vs compute)
36
+ # - Set to 0 to disable inter-bar features while keeping intra-bar
37
+ # INCLUDE_INTRA_BAR_FEATURES: Enable ITH + statistical features within bars.
38
+ # - "true" enables 22 intra_* columns (ITH, complexity, statistical)
39
+ # - "false" disables (use if you only need lookback_* features)
40
+ RANGEBAR_INTER_BAR_LOOKBACK_COUNT = "200"
41
+ RANGEBAR_INCLUDE_INTRA_BAR_FEATURES = "true"
42
+
30
43
  # =============================================================================
31
44
  # GitHub Account Isolation
32
45
  # =============================================================================
@@ -1,3 +1,17 @@
1
+ ## [12.1.2](https://github.com/terrylica/rangebar-py/compare/v12.1.1...v12.1.2) (2026-02-04)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **interbar:** preserve lookback trades across bar boundaries ([#68](https://github.com/terrylica/rangebar-py/issues/68)) ([d8e3fc9](https://github.com/terrylica/rangebar-py/commit/d8e3fc94bc160c20314801e5e3be684969972888))
7
+
8
+ ## [12.1.1](https://github.com/terrylica/rangebar-py/compare/v12.1.0...v12.1.1) (2026-02-03)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **microstructure:** auto-enable v12 features when include_microstructure=True ([9288e2f](https://github.com/terrylica/rangebar-py/commit/9288e2f5bc2f412d81d1954d308cea938d027b48)), closes [#68](https://github.com/terrylica/rangebar-py/issues/68)
14
+
1
15
  # [12.1.0](https://github.com/terrylica/rangebar-py/compare/v12.0.2...v12.1.0) (2026-02-03)
2
16
 
3
17
 
@@ -3337,7 +3337,7 @@ dependencies = [
3337
3337
 
3338
3338
  [[package]]
3339
3339
  name = "rangebar"
3340
- version = "12.1.0"
3340
+ version = "12.1.2"
3341
3341
  dependencies = [
3342
3342
  "chrono",
3343
3343
  "insta",
@@ -3359,7 +3359,7 @@ dependencies = [
3359
3359
 
3360
3360
  [[package]]
3361
3361
  name = "rangebar-batch"
3362
- version = "12.1.0"
3362
+ version = "12.1.2"
3363
3363
  dependencies = [
3364
3364
  "polars",
3365
3365
  "rangebar-core",
@@ -3371,7 +3371,7 @@ dependencies = [
3371
3371
 
3372
3372
  [[package]]
3373
3373
  name = "rangebar-cli"
3374
- version = "12.1.0"
3374
+ version = "12.1.2"
3375
3375
  dependencies = [
3376
3376
  "chrono",
3377
3377
  "clap",
@@ -3396,7 +3396,7 @@ dependencies = [
3396
3396
 
3397
3397
  [[package]]
3398
3398
  name = "rangebar-config"
3399
- version = "12.1.0"
3399
+ version = "12.1.2"
3400
3400
  dependencies = [
3401
3401
  "chrono",
3402
3402
  "config",
@@ -3408,7 +3408,7 @@ dependencies = [
3408
3408
 
3409
3409
  [[package]]
3410
3410
  name = "rangebar-core"
3411
- version = "12.1.0"
3411
+ version = "12.1.2"
3412
3412
  dependencies = [
3413
3413
  "ahash",
3414
3414
  "arrow",
@@ -3425,7 +3425,7 @@ dependencies = [
3425
3425
 
3426
3426
  [[package]]
3427
3427
  name = "rangebar-io"
3428
- version = "12.1.0"
3428
+ version = "12.1.2"
3429
3429
  dependencies = [
3430
3430
  "polars",
3431
3431
  "rangebar-core",
@@ -3435,7 +3435,7 @@ dependencies = [
3435
3435
 
3436
3436
  [[package]]
3437
3437
  name = "rangebar-providers"
3438
- version = "12.1.0"
3438
+ version = "12.1.2"
3439
3439
  dependencies = [
3440
3440
  "chrono",
3441
3441
  "csv",
@@ -3455,7 +3455,7 @@ dependencies = [
3455
3455
 
3456
3456
  [[package]]
3457
3457
  name = "rangebar-py"
3458
- version = "12.1.0"
3458
+ version = "12.1.2"
3459
3459
  dependencies = [
3460
3460
  "arrow",
3461
3461
  "arrow-array",
@@ -3474,7 +3474,7 @@ dependencies = [
3474
3474
 
3475
3475
  [[package]]
3476
3476
  name = "rangebar-streaming"
3477
- version = "12.1.0"
3477
+ version = "12.1.2"
3478
3478
  dependencies = [
3479
3479
  "async-trait",
3480
3480
  "chrono",
@@ -10,7 +10,7 @@ resolver = "2"
10
10
  [workspace.package]
11
11
  # CRITICAL: Prevent crates.io publishing - this is a PyPI-only project
12
12
  publish = false
13
- version = "12.1.0"
13
+ version = "12.1.2"
14
14
  authors = ["Terry Li <terry@eonlabs.com>"]
15
15
  categories = ["algorithms", "data-structures", "finance"]
16
16
  documentation = "https://docs.rs/rangebar"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rangebar
3
- Version: 12.1.0
3
+ Version: 12.1.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Financial and Insurance Industry
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -145,41 +145,93 @@ pub struct TradeHistory {
145
145
  trades: VecDeque<TradeSnapshot>,
146
146
  /// Configuration for lookback
147
147
  config: InterBarConfig,
148
+ /// Timestamp threshold: trades with timestamp < this are protected from pruning.
149
+ /// Set to the oldest timestamp we might need for lookback computation.
150
+ /// Updated each time a new bar opens.
151
+ protected_until: Option<i64>,
148
152
  }
149
153
 
150
154
  impl TradeHistory {
151
155
  /// Create new trade history with given configuration
152
156
  pub fn new(config: InterBarConfig) -> Self {
153
157
  let capacity = match &config.lookback_mode {
154
- LookbackMode::FixedCount(n) => *n,
155
- LookbackMode::FixedWindow(_) => 1000, // Initial capacity for time-based
158
+ LookbackMode::FixedCount(n) => *n * 2, // 2x capacity to hold pre-bar + in-bar trades
159
+ LookbackMode::FixedWindow(_) => 2000, // Initial capacity for time-based
156
160
  };
157
161
  Self {
158
162
  trades: VecDeque::with_capacity(capacity),
159
163
  config,
164
+ protected_until: None,
160
165
  }
161
166
  }
162
167
 
163
168
  /// Push a new trade to the history buffer
164
169
  ///
165
- /// Automatically prunes old entries based on lookback mode.
170
+ /// Automatically prunes old entries based on lookback mode, but preserves
171
+ /// trades needed for lookback computation (timestamp < protected_until).
166
172
  pub fn push(&mut self, trade: &AggTrade) {
167
173
  let snapshot = TradeSnapshot::from(trade);
168
174
  self.trades.push_back(snapshot);
169
- self.prune(trade.timestamp);
175
+ self.prune();
176
+ }
177
+
178
+ /// Notify that a new bar has opened at the given timestamp
179
+ ///
180
+ /// This sets the protection threshold to ensure trades from before the bar
181
+ /// opened are preserved for lookback computation. The protection extends
182
+ /// until the next bar opens and calls this method again.
183
+ pub fn on_bar_open(&mut self, bar_open_time: i64) {
184
+ // Protect all trades with timestamp < bar_open_time
185
+ // These are the trades that can be used for lookback computation
186
+ self.protected_until = Some(bar_open_time);
187
+ }
188
+
189
+ /// Notify that the current bar has closed
190
+ ///
191
+ /// This is intentionally a no-op. We keep protection until the next bar opens,
192
+ /// which ensures the lookback window is available for feature computation.
193
+ pub fn on_bar_close(&mut self) {
194
+ // No-op: Keep protection until next bar opens
195
+ // This ensures lookback trades survive between bars
170
196
  }
171
197
 
172
198
  /// Prune old trades based on lookback configuration
173
- fn prune(&mut self, current_timestamp: i64) {
199
+ ///
200
+ /// Pruning logic:
201
+ /// - For FixedCount(n): Keep up to 2*n trades total, but never prune trades
202
+ /// with timestamp < protected_until (needed for lookback)
203
+ /// - For FixedWindow: Standard time-based pruning, but respect protected_until
204
+ fn prune(&mut self) {
174
205
  match &self.config.lookback_mode {
175
206
  LookbackMode::FixedCount(n) => {
176
- while self.trades.len() > *n {
207
+ // Keep at most 2*n trades (n for lookback + n for next bar's lookback)
208
+ let max_trades = *n * 2;
209
+ while self.trades.len() > max_trades {
210
+ // Check if front trade is protected
211
+ if let Some(front) = self.trades.front() {
212
+ if let Some(protected) = self.protected_until {
213
+ if front.timestamp < protected {
214
+ // Don't prune protected trades
215
+ break;
216
+ }
217
+ }
218
+ }
177
219
  self.trades.pop_front();
178
220
  }
179
221
  }
180
222
  LookbackMode::FixedWindow(window_us) => {
181
- let cutoff = current_timestamp - window_us;
223
+ // Find the oldest trade we need
224
+ let newest_timestamp = self.trades.back().map(|t| t.timestamp).unwrap_or(0);
225
+ let cutoff = newest_timestamp - window_us;
226
+
182
227
  while let Some(front) = self.trades.front() {
228
+ // Respect protection
229
+ if let Some(protected) = self.protected_until {
230
+ if front.timestamp < protected {
231
+ break;
232
+ }
233
+ }
234
+ // Prune if outside time window
183
235
  if front.timestamp < cutoff {
184
236
  self.trades.pop_front();
185
237
  } else {
@@ -260,6 +260,10 @@ impl RangeBarProcessor {
260
260
  // This matches the batch path's defer_open semantics - the breaching trade
261
261
  // closes the current bar, and the NEXT trade opens the new bar.
262
262
  if self.defer_open {
263
+ // Issue #68: Notify history that new bar is opening (preserves pre-bar trades)
264
+ if let Some(ref mut history) = self.trade_history {
265
+ history.on_bar_open(trade.timestamp);
266
+ }
263
267
  self.current_bar_state = Some(if self.include_intra_bar_features {
264
268
  RangeBarState::new_with_trade_accumulation(&trade, self.threshold_decimal_bps)
265
269
  } else {
@@ -272,6 +276,10 @@ impl RangeBarProcessor {
272
276
  match &mut self.current_bar_state {
273
277
  None => {
274
278
  // First trade - initialize new bar
279
+ // Issue #68: Notify history that new bar is opening (preserves pre-bar trades)
280
+ if let Some(ref mut history) = self.trade_history {
281
+ history.on_bar_open(trade.timestamp);
282
+ }
275
283
  self.current_bar_state = Some(if self.include_intra_bar_features {
276
284
  RangeBarState::new_with_trade_accumulation(&trade, self.threshold_decimal_bps)
277
285
  } else {
@@ -313,9 +321,11 @@ impl RangeBarProcessor {
313
321
 
314
322
  // Issue #59: Compute inter-bar features from lookback window
315
323
  // Features are computed from trades BEFORE bar.open_time (no lookahead)
316
- if let Some(ref history) = self.trade_history {
324
+ if let Some(ref mut history) = self.trade_history {
317
325
  let inter_bar_features = history.compute_features(bar_state.bar.open_time);
318
326
  bar_state.bar.set_inter_bar_features(&inter_bar_features);
327
+ // Issue #68: Notify history that bar is closing (resumes normal pruning)
328
+ history.on_bar_close();
319
329
  }
320
330
 
321
331
  // Issue #59: Compute intra-bar features from accumulated trades
@@ -451,6 +461,10 @@ impl RangeBarProcessor {
451
461
 
452
462
  if defer_open {
453
463
  // Previous bar closed, this agg_record opens new bar
464
+ // Issue #68: Notify history that new bar is opening (preserves pre-bar trades)
465
+ if let Some(ref mut history) = self.trade_history {
466
+ history.on_bar_open(agg_record.timestamp);
467
+ }
454
468
  current_bar = Some(if self.include_intra_bar_features {
455
469
  RangeBarState::new_with_trade_accumulation(agg_record, self.threshold_decimal_bps)
456
470
  } else {
@@ -463,6 +477,10 @@ impl RangeBarProcessor {
463
477
  match current_bar {
464
478
  None => {
465
479
  // First bar initialization
480
+ // Issue #68: Notify history that new bar is opening (preserves pre-bar trades)
481
+ if let Some(ref mut history) = self.trade_history {
482
+ history.on_bar_open(agg_record.timestamp);
483
+ }
466
484
  current_bar = Some(if self.include_intra_bar_features {
467
485
  RangeBarState::new_with_trade_accumulation(agg_record, self.threshold_decimal_bps)
468
486
  } else {
@@ -504,10 +522,12 @@ impl RangeBarProcessor {
504
522
  bar_state.bar.compute_microstructure_features();
505
523
 
506
524
  // Issue #59: Compute inter-bar features from lookback window
507
- if let Some(ref history) = self.trade_history {
525
+ if let Some(ref mut history) = self.trade_history {
508
526
  let inter_bar_features =
509
527
  history.compute_features(bar_state.bar.open_time);
510
528
  bar_state.bar.set_inter_bar_features(&inter_bar_features);
529
+ // Issue #68: Notify history that bar is closing (resumes normal pruning)
530
+ history.on_bar_close();
511
531
  }
512
532
 
513
533
  // Issue #59: Compute intra-bar features from accumulated trades
@@ -11,6 +11,12 @@ SSoT (Single Source of Truth) for:
11
11
  - _CRYPTO_BASES: Known crypto base symbols for asset class detection
12
12
  - _FOREX_CURRENCIES: Known forex currencies for asset class detection
13
13
  - MEM_GUARDS: Memory guard registry (Issue #49)
14
+
15
+ Environment Variable SSoT (from .mise.toml):
16
+ - RANGEBAR_CRYPTO_MIN_THRESHOLD: Minimum threshold for crypto (1000 dbps)
17
+ - RANGEBAR_FOREX_MIN_THRESHOLD: Minimum threshold for forex (50 dbps)
18
+ - RANGEBAR_INTER_BAR_LOOKBACK_COUNT: Lookback for inter-bar features (200)
19
+ - RANGEBAR_INCLUDE_INTRA_BAR_FEATURES: Auto-enable intra-bar features (true)
14
20
  """
15
21
 
16
22
  from __future__ import annotations
@@ -341,4 +347,9 @@ MEM_GUARDS: dict[str, dict[str, str]] = {
341
347
  "location": "orchestration/helpers.py:304",
342
348
  "stage": "processing",
343
349
  },
350
+ "MEM-012": {
351
+ "description": "Streaming bar batches (10K) to prevent OOM",
352
+ "location": "orchestration/helpers.py:236",
353
+ "stage": "processing",
354
+ },
344
355
  }
@@ -94,12 +94,28 @@ def _stream_range_bars_binance(
94
94
  "cm": MarketType.FuturesCM,
95
95
  }[market]
96
96
 
97
+ # Issue #68: Auto-enable v12 features when include_microstructure=True
98
+ # SSoT: Defaults from mise.toml env vars
99
+ import os
100
+
101
+ effective_lookback = inter_bar_lookback_count
102
+ if include_microstructure and effective_lookback is None:
103
+ effective_lookback = int(
104
+ os.environ.get("RANGEBAR_INTER_BAR_LOOKBACK_COUNT", "200")
105
+ )
106
+
107
+ enable_intra = False
108
+ if include_microstructure:
109
+ intra_env = os.environ.get("RANGEBAR_INCLUDE_INTRA_BAR_FEATURES", "true")
110
+ enable_intra = intra_env.lower() in ("true", "1", "yes")
111
+
97
112
  # Create processor with symbol for checkpoint support
98
113
  processor = RangeBarProcessor(
99
114
  threshold_decimal_bps,
100
115
  symbol=symbol,
101
116
  prevent_same_timestamp_close=prevent_same_timestamp_close,
102
- inter_bar_lookback_count=inter_bar_lookback_count,
117
+ inter_bar_lookback_count=effective_lookback,
118
+ include_intra_bar_features=enable_intra,
103
119
  )
104
120
  bar_buffer: list[dict] = []
105
121
 
@@ -285,6 +301,7 @@ def _process_binance_trades(
285
301
  symbol: str | None = None,
286
302
  prevent_same_timestamp_close: bool = True,
287
303
  inter_bar_lookback_count: int | None = None,
304
+ include_intra_bar_features: bool = False,
288
305
  ) -> tuple[pd.DataFrame, RangeBarProcessor]:
289
306
  """Process Binance trades to range bars (internal).
290
307
 
@@ -307,6 +324,8 @@ def _process_binance_trades(
307
324
  Timestamp gating for flash crash prevention
308
325
  inter_bar_lookback_count : int, optional
309
326
  Lookback trade count for inter-bar features (Issue #59)
327
+ include_intra_bar_features : bool, default=False
328
+ Enable intra-bar features (Issue #59)
310
329
 
311
330
  Returns
312
331
  -------
@@ -348,11 +367,27 @@ def _process_binance_trades(
348
367
 
349
368
  # Use provided processor or create new one
350
369
  if processor is None:
370
+ # Issue #68: Auto-enable v12 features when include_microstructure=True
371
+ # This ensures all code paths apply defaults, not just range_bars.py
372
+ import os
373
+
374
+ effective_lookback = inter_bar_lookback_count
375
+ if include_microstructure and effective_lookback is None:
376
+ effective_lookback = int(
377
+ os.environ.get("RANGEBAR_INTER_BAR_LOOKBACK_COUNT", "200")
378
+ )
379
+
380
+ enable_intra = include_intra_bar_features
381
+ if include_microstructure and not enable_intra:
382
+ intra_env = os.environ.get("RANGEBAR_INCLUDE_INTRA_BAR_FEATURES", "true")
383
+ enable_intra = intra_env.lower() in ("true", "1", "yes")
384
+
351
385
  processor = RangeBarProcessor(
352
386
  threshold_decimal_bps,
353
387
  symbol=symbol,
354
388
  prevent_same_timestamp_close=prevent_same_timestamp_close,
355
- inter_bar_lookback_count=inter_bar_lookback_count,
389
+ inter_bar_lookback_count=effective_lookback,
390
+ include_intra_bar_features=enable_intra,
356
391
  )
357
392
 
358
393
  # MEM-012: Stream bars in batches instead of accumulating all in memory
@@ -544,6 +544,25 @@ def get_range_bars(
544
544
  any_data_found = True
545
545
 
546
546
  # Process segment (reuse processor for state continuity within segment)
547
+ # Issue #68: Auto-enable v12 features when include_microstructure=True
548
+ # SSoT: Defaults from mise.toml env vars (RANGEBAR_INTER_BAR_LOOKBACK_COUNT,
549
+ # RANGEBAR_INCLUDE_INTRA_BAR_FEATURES)
550
+ import os
551
+
552
+ effective_lookback = inter_bar_lookback_count
553
+ if include_microstructure and effective_lookback is None:
554
+ # Read from env (mise SSoT) with fallback
555
+ effective_lookback = int(
556
+ os.environ.get("RANGEBAR_INTER_BAR_LOOKBACK_COUNT", "200")
557
+ )
558
+
559
+ # Intra-bar features: auto-enable if microstructure requested
560
+ # SSoT from mise.toml, defaults to True when include_microstructure=True
561
+ enable_intra = False
562
+ if include_microstructure:
563
+ intra_env = os.environ.get("RANGEBAR_INCLUDE_INTRA_BAR_FEATURES", "true")
564
+ enable_intra = intra_env.lower() in ("true", "1", "yes")
565
+
547
566
  segment_bars, processor = _process_binance_trades(
548
567
  segment_ticks,
549
568
  threshold_decimal_bps,
@@ -552,7 +571,8 @@ def get_range_bars(
552
571
  processor=processor,
553
572
  symbol=symbol,
554
573
  prevent_same_timestamp_close=prevent_same_timestamp_close,
555
- inter_bar_lookback_count=inter_bar_lookback_count,
574
+ inter_bar_lookback_count=effective_lookback,
575
+ include_intra_bar_features=enable_intra,
556
576
  )
557
577
 
558
578
  if segment_bars is not None and not segment_bars.empty:
@@ -100,6 +100,7 @@ class RangeBarProcessor:
100
100
  *,
101
101
  prevent_same_timestamp_close: bool = True,
102
102
  inter_bar_lookback_count: int | None = None,
103
+ include_intra_bar_features: bool = False,
103
104
  ) -> None:
104
105
  """Initialize processor with given threshold.
105
106
 
@@ -112,7 +113,11 @@ class RangeBarProcessor:
112
113
  prevent_same_timestamp_close : bool, default=True
113
114
  Timestamp gating for flash crash prevention (Issue #36)
114
115
  inter_bar_lookback_count : int, optional
115
- Lookback trade count for inter-bar features (Issue #59)
116
+ Lookback trade count for inter-bar features (Issue #59).
117
+ Enables 16 lookback_* features computed from trades BEFORE bar opens.
118
+ include_intra_bar_features : bool, default=False
119
+ Enable intra-bar features (Issue #59). When True, computes 22 intra_*
120
+ features from trades WITHIN each bar, including ITH metrics.
116
121
 
117
122
  Raises
118
123
  ------
@@ -134,11 +139,13 @@ class RangeBarProcessor:
134
139
  symbol,
135
140
  prevent_same_timestamp_close,
136
141
  inter_bar_lookback_count,
142
+ include_intra_bar_features,
137
143
  )
138
144
  self.threshold_decimal_bps = threshold_decimal_bps
139
145
  self.symbol = symbol
140
146
  self.prevent_same_timestamp_close = prevent_same_timestamp_close
141
147
  self.inter_bar_lookback_count = inter_bar_lookback_count
148
+ self.include_intra_bar_features = include_intra_bar_features
142
149
 
143
150
  @classmethod
144
151
  def from_checkpoint(cls, checkpoint: dict) -> RangeBarProcessor:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes