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.
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise.toml +13 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/CHANGELOG.md +14 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/Cargo.lock +9 -9
- {rangebar-12.1.0 → rangebar-12.1.2}/Cargo.toml +1 -1
- {rangebar-12.1.0 → rangebar-12.1.2}/PKG-INFO +1 -1
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/interbar.rs +59 -7
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/processor.rs +22 -2
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/constants.py +11 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/helpers.py +37 -2
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/range_bars.py +21 -1
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/core.py +8 -1
- {rangebar-12.1.0 → rangebar-12.1.2}/.cargo/config.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.gitignore +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mcp.json +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/bench.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/cache.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/checksum.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/deps.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/dev.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/diag.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/prof.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/release.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/research.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/smoke.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.mise/tasks/validate.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.pre-commit-config.yaml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/.releaserc.yml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/CLAUDE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/LICENSE +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/RESUME.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/STATISTICAL_VALIDITY_AUDIT.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/benches/rangebar_bench.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/build.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/CLAUDE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/CHANGELOG.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/Cargo.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/arrow_export.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/checkpoint.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/fixed_point.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/drawdown.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/features.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/ith.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/mod.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/normalize.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/intrabar/types.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/lib.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_data_loader.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_utils/generators.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/test_utils/mod.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/timestamp.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/src/types.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_boundary_validation.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_date_real_data_validation.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_year_boundary_test.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/CHANGELOG.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/Cargo.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/checksum.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/historical.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/mod.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/symbols.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/binance/websocket.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/builder.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/client.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/conversion.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/mod.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/exness/types.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-providers/src/lib.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/CHANGELOG.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/Cargo.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/indicators.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/lib.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/processor.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/replay_buffer.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/stats.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-streaming/src/universal.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/deny.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/ARCHITECTURE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/CONTEXT.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/MEMORY_REMEDIATION_PLAN.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/adr/2026-01-31-realtime-streaming-api.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/analysis/2025-10-10-flash-crash.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/api.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/development/PERFORMANCE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/development/RELEASE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/migration-v8.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/plans/issue-59-inter-bar-features.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/rangebar_core_api.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-02-intrabar-microstructure-claude-opus.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-02-intrabar-microstructure-gemini-3-pro.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-03-cfm-optimal-threshold-gemini-3-pro.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/2026-02-03-memory-efficient-streaming.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/INDEX.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/adversarial-audit-methodology.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/external/time-to-convergence-stationarity-gap.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/labeling-for-ml.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/market-regime-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/multi-threshold-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/multifactor-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/pattern-research-summary.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/price-action-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/tda-parameter-sensitivity-audit.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/tda-regime-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/research/volatility-regime-patterns.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/docs/verification/issue-62-verification-report.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/backtesting_integration.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/basic_usage.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/binance_csv_example.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/get_range_bars_example.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/validate_output.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/examples/with_clickhouse_cache.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/package-lock.json +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/package.json +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/pyproject.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/CLAUDE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/__init__.pyi +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/checkpoint.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/cli.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/CLAUDE.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/bulk_operations.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/cache.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/client.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/config.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/mixin.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/preflight.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/query_operations.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/schema.sql +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/clickhouse/tunnel.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/conversion.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/exceptions.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/exness.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/hooks.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/logging.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/pushover.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/notify/telegram.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/count_bounded.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/models.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/precompute.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/orchestration/tick_fetcher.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/ouroboros.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/processors/api.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/resource_guard.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/checksum_registry.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/storage/parquet.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/streaming.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/threshold.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/__init__.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/cache_staleness.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/continuity.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/gap_classification.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/post_storage.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/tier1.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/python/rangebar/validation/tier2.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/rust-toolchain.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/rustfmt.toml +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/adwin_regime_detection_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/analyze_flash_crash.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/bootstrap_permutation_validation_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/build-release.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cache_clear.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cache_status.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/check-release-config.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/coarse_to_fine_cascade.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_pattern_audit_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_regime_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/combined_rv_alignment_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_asset_correlation_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_regime_correlation_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/cross_threshold_alignment.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/dependency_monitor.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/direction_patterns_reaudit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/download_exness_eurusd.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/download_exness_forex.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_autocorrelation.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_autocorrelation_audit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/duration_volatility_prediction.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fdr_corrected_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_all_symbols.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_2025_2026.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_littleblack.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/fill_gaps_retry.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/historical_formation_patterns_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/historical_formation_regime_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_adjusted_kelly_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_adjusted_psr_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_exponent_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/hurst_multi_estimator_audit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_clickhouse.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/microstructure_simple.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/monitor_population.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multi_threshold_pattern_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multibar_continuation.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multibar_forward_returns_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_multigranularity_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multifactor_patterns_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multithreshold_combinations_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/multithreshold_regime_combinations_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/oos_validation_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/parameter_sensitivity_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_correlation_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_return_profiles_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/pattern_return_stats.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_1000dbps.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_250dbps.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_250dbps_extended.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/populate_safe.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/position_sizing_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/process_exness_eurusd_to_cache.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/profiling_tools.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/psr_mintrl_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/publish-to-pypi.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/publish-wheels.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/purge_crypto_low_threshold.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regenerate_cache.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis_50dbps_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/regime_transition_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_large_scale_benchmark.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_analysis.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_multi_symbol.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/run_length_momentum_wfo.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/rv_return_profile_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/semantic-release.sh +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_break_event_alignment_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_conditioned_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_cupy_accelerated.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_gpu_analysis.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_hurst_by_regime_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_parameter_sweep_audit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_regime_hurst_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_regime_pattern_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_ripser_plusplus.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_rolling_threshold.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_solusdt_250_audit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_solusdt_250_littleblack.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_structural_break_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_volatility_forecast.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_3way.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_abstain.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/tda_wfo_audit.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/temporal_safe_patterns_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_alignment_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_pattern_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_bar_pattern_audit_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_factor_hurst_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/three_factor_pattern_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/transaction_cost_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/trend_filter_analysis.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/upload_eurusd_to_clickhouse.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_clickhouse.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_memory_efficiency.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_microstructure_features.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/validate_n_range_bars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volatility_regime_analysis_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volatility_regime_audit_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volume_conditioned_patterns.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/scripts/volume_conditioned_patterns_polars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/src/lib.rs +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/test_data/BTCUSDT/BTCUSDT_aggTrades_20250901.csv +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/test_data/ETHUSDT/ETHUSDT_aggTrades_20250901.csv +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/test_data/README.md +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/conftest.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/fixtures/.gitignore +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/fixtures/BTCUSDT-aggTrades-2024-01-01.zip +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_cache_schema_evolution.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_clickhouse.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_clickhouse_integration.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_crypto_minimum_threshold.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_e2e_optimized.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_edge_cases.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_examples.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_get_n_range_bars.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_get_range_bars_e2e.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_issue_5_reproduction.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_issues_7_8.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_microstructure_features.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_ouroboros.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_polars_only_downstream.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_preflight.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_python_api.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_real_data.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_rust_bindings.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_storage.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_streaming.py +0 -0
- {rangebar-12.1.0 → rangebar-12.1.2}/tests/test_validation_presets.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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"
|
|
@@ -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(_) =>
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/cross_date_real_data_validation.rs
RENAMED
|
File without changes
|
|
File without changes
|
{rangebar-12.1.0 → rangebar-12.1.2}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|