echolon 0.2.0__tar.gz → 0.3.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.
- echolon-0.3.2/CHANGELOG.md +30 -0
- echolon-0.3.2/PKG-INFO +96 -0
- echolon-0.3.2/README.md +58 -0
- echolon-0.3.2/docs/API_REFERENCE.md +188 -0
- echolon-0.3.2/docs/COMPONENT_GUIDE.md +115 -0
- echolon-0.3.2/docs/CONFIG_REFERENCE.md +68 -0
- echolon-0.3.2/docs/ERROR_CATALOG.md +19 -0
- echolon-0.3.2/docs/PATTERNS.md +185 -0
- echolon-0.3.2/docs/QUICK_START.md +50 -0
- echolon-0.3.2/docs/errors/CFG-001.md +35 -0
- echolon-0.3.2/docs/errors/CFG-002.md +40 -0
- echolon-0.3.2/docs/errors/DAT-001.md +41 -0
- echolon-0.3.2/docs/errors/IND-001.md +31 -0
- echolon-0.3.2/docs/errors/IND-002.md +36 -0
- echolon-0.3.2/docs/errors/PRM-001.md +44 -0
- echolon-0.3.2/docs/errors/PRM-002.md +50 -0
- echolon-0.3.2/docs/errors/STR-001.md +35 -0
- echolon-0.3.2/docs/errors/STR-002.md +48 -0
- echolon-0.3.2/docs/errors/STR-003.md +42 -0
- echolon-0.3.2/docs/errors/VAL-001.md +50 -0
- echolon-0.3.2/docs/errors/VAL-002.md +34 -0
- echolon-0.3.2/docs/errors/VAL-003.md +38 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/__init__.py +3 -1
- echolon-0.3.2/echolon/native/__init__.py +9 -0
- echolon-0.3.2/echolon/native/cli/examples.py +46 -0
- echolon-0.3.2/echolon/native/cli/init.py +34 -0
- echolon-0.3.2/echolon/native/cli/main.py +31 -0
- echolon-0.3.2/echolon/native/cli/run.py +55 -0
- echolon-0.3.2/echolon/native/cli/schema.py +37 -0
- echolon-0.3.2/echolon/native/cli/validate.py +57 -0
- echolon-0.3.2/echolon/native/examples_registry.py +18 -0
- echolon-0.3.2/echolon/native/templates/__init__.py +16 -0
- echolon-0.3.2/echolon/native/templates/minimal/README.md +12 -0
- echolon-0.3.2/echolon/native/templates/minimal/entry.py +19 -0
- echolon-0.3.2/echolon/native/templates/minimal/exit.py +24 -0
- echolon-0.3.2/echolon/native/templates/minimal/risk.py +12 -0
- echolon-0.3.2/echolon/native/templates/minimal/sizer.py +16 -0
- echolon-0.3.2/echolon/native/templates/minimal/strategy.py +24 -0
- echolon-0.3.2/echolon/native/templates/minimal/strategy_indicator_list.json +1 -0
- echolon-0.3.2/echolon/native/templates/minimal/strategy_params.py +26 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/README.md +5 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/entry.py +29 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/exit.py +39 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/risk.py +12 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/sizer.py +16 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/strategy.py +24 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/strategy_indicator_list.json +1 -0
- echolon-0.3.2/echolon/native/templates/momentum_breakout/strategy_params.py +27 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/README.md +5 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/entry.py +29 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/exit.py +39 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/risk.py +12 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/sizer.py +16 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/strategy.py +24 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/strategy_indicator_list.json +1 -0
- echolon-0.3.2/echolon/native/templates/rsi_mean_reversion/strategy_params.py +30 -0
- echolon-0.3.2/echolon/native/validation/__init__.py +30 -0
- echolon-0.3.2/echolon/native/validation/errors.py +227 -0
- echolon-0.3.2/echolon/native/validation/indicator_validator.py +75 -0
- echolon-0.3.2/echolon/native/validation/strategy_validator.py +126 -0
- echolon-0.3.2/examples/01_minimal/README.md +30 -0
- echolon-0.3.2/examples/01_minimal/entry.py +19 -0
- echolon-0.3.2/examples/01_minimal/exit.py +24 -0
- echolon-0.3.2/examples/01_minimal/risk.py +12 -0
- echolon-0.3.2/examples/01_minimal/sizer.py +16 -0
- echolon-0.3.2/examples/01_minimal/strategy.py +24 -0
- echolon-0.3.2/examples/01_minimal/strategy_indicator_list.json +1 -0
- echolon-0.3.2/examples/01_minimal/strategy_params.py +26 -0
- echolon-0.3.2/examples/02_momentum_breakout/README.md +37 -0
- echolon-0.3.2/examples/02_momentum_breakout/entry.py +29 -0
- echolon-0.3.2/examples/02_momentum_breakout/exit.py +39 -0
- echolon-0.3.2/examples/02_momentum_breakout/risk.py +12 -0
- echolon-0.3.2/examples/02_momentum_breakout/sizer.py +16 -0
- echolon-0.3.2/examples/02_momentum_breakout/strategy.py +24 -0
- echolon-0.3.2/examples/02_momentum_breakout/strategy_indicator_list.json +1 -0
- echolon-0.3.2/examples/02_momentum_breakout/strategy_params.py +27 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/README.md +37 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/entry.py +29 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/exit.py +39 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/risk.py +12 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/sizer.py +16 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/strategy.py +24 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/strategy_indicator_list.json +1 -0
- echolon-0.3.2/examples/03_rsi_mean_reversion/strategy_params.py +30 -0
- echolon-0.3.2/llms.txt +37 -0
- {echolon-0.2.0 → echolon-0.3.2}/pyproject.toml +9 -1
- echolon-0.3.2/tests/__init__.py +0 -0
- echolon-0.3.2/tests/native/__init__.py +0 -0
- echolon-0.3.2/tests/native/test_ai_native_smoke.py +105 -0
- echolon-0.3.2/tests/native/test_cli_examples.py +30 -0
- echolon-0.3.2/tests/native/test_cli_init.py +57 -0
- echolon-0.3.2/tests/native/test_cli_run.py +41 -0
- echolon-0.3.2/tests/native/test_cli_schema.py +37 -0
- echolon-0.3.2/tests/native/test_cli_validate.py +113 -0
- echolon-0.3.2/tests/native/test_errors.py +140 -0
- echolon-0.3.2/tests/native/test_indicator_validator.py +57 -0
- echolon-0.3.2/tests/native/test_strategy_validator.py +149 -0
- echolon-0.2.0/PKG-INFO +0 -42
- echolon-0.2.0/README.md +0 -5
- {echolon-0.2.0 → echolon-0.3.2}/.gitignore +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/LICENSE +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/backtest_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/feature_flags.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/indicator_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/encoding.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/registry.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/trading_target.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/core/types.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/crypto/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/crypto/config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/crypto/perpetuals.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/factory.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/constants.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/instruments.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/phases.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/markets/shfe/sessions.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/optuna_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/quant_engine.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/quick_start.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/config/settings.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/base.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/binance/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/binance/perpetual_extractor.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/shfe/day_extractor.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/shfe/live_day_extractor.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/extractors/shfe/minute_extractor.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/loaders/calendar_loader.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/loaders/ohlcv_loader.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/loaders/session_availability_loader.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/run_pipeline.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/schemas/ohlcv.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/schemas/standard_schema.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/calendar_generator.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/contract_splitter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/ohlcv_resampler.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/ohlcv_standardizer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/session_filter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/data_pipeline/transformers/shfe_session_analyzer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/indicator_dictionary.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/indicator_mapping.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/market_regime.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/price_channel.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/sr_zone.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/interday/ta_lib.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/indicator_dictionary.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/indicator_mapping.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/indicators.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/market_context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/calculators/intraday/ta_lib.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/interday_analysis_indicators.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/interday_indicators_classification.md +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/interday_indicators_documentation.md +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/intraday_analysis_indicators.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/intraday_indicators_classification.md +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/config/intraday_indicators_documentation.md +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/engine/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/engine/processor.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/optimization/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/optimization/interday_regime_optimizer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/optimization/regime_utils.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/registry/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/registry/utils.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/run_indicators.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/utils/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/utils/indicator_loader.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/indicators/utils/merge_indicators.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/lib/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/lib/json_utils.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/lib/regime_utils.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/lib/stats_utils.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/lib/strategy_log.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest → echolon-0.3.2/echolon/native/cli}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/LOGGING_DESIGN.md +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/__init__.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest/engine → echolon-0.3.2/echolon/quant_engine/backtest}/__init__.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest/engine/futures → echolon-0.3.2/echolon/quant_engine/backtest/engine}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/analyzers.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/backtest_runner.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/backtrader_engine.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/backtrader_strategy.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/enriched_pandas_data.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest/engine/hooks → echolon-0.3.2/echolon/quant_engine/backtest/engine/futures}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/futures/enhanced_position.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest/engine/hooks/contract_aware → echolon-0.3.2/echolon/quant_engine/backtest/engine/hooks}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/hooks/base.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/backtest/optimization → echolon-0.3.2/echolon/quant_engine/backtest/engine/hooks/contract_aware}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/hooks/contract_aware/broker.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/hooks/contract_aware/hook.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/hooks/contract_aware/observer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/hooks/session_aware.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/engine/optimization_runner.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core → echolon-0.3.2/echolon/quant_engine/backtest/optimization}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/optimization/optuna_study.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/optimization/select_best_trial.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/portfolio_backtest_runner.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/portfolio_metrics.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/wfa/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/wfa/analyzer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/wfa/drs_calculator.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/wfa/runner.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/backtest/wfa/window.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/calculate_mfe_mae.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core/base → echolon-0.3.2/echolon/quant_engine/core}/__init__.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core/base/hooks → echolon-0.3.2/echolon/quant_engine/core/base}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/base_component.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/base_strategy.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core/frequency → echolon-0.3.2/echolon/quant_engine/core/base/hooks}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/hooks/component_hook_base.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/hooks/forced_exit_strategy_hook.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/hooks/session_aware_component_hook.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/hooks/session_aware_strategy_hook.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/hooks/strategy_hook_base.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/parameter_architecture.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/base/state_manager.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core/interfaces → echolon-0.3.2/echolon/quant_engine/core/frequency}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/frequency/interday_context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/frequency/intraday_context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/frequency/session_context_provider.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/core/logging → echolon-0.3.2/echolon/quant_engine/core/interfaces}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/interfaces/frequency_context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/interfaces/market_adapter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/interfaces/session_context.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/interfaces/trading_interfaces.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/data_loader → echolon-0.3.2/echolon/quant_engine/core/logging}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/core/logging/strategy_logger.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/data_loader/SHFE_loader.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/market_adapters → echolon-0.3.2/echolon/quant_engine/data_loader}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/data_loader/contract_data.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/config/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/config/deploy_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/config/logging_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/config/portfolio_deploy_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/config/trading_calendar.csv +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/data_pipeline/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/data_pipeline/trading_util.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/capital_slot.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/dashboard_aggregator.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/dashboard_data_generator.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/dashboard_data_sender.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/portfolio_risk_overlay.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/portfolio_trading_runner.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/slot_aware_portfolio.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/trading_data_logger.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/trading_runner.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/engine/trading_slot.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/ccxt/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/ccxt/ccxt_client.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/ccxt/ccxt_engine.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/miniqmt/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/miniqmt/qmt_client.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/miniqmt/qmt_engine.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/deploy/platforms/miniqmt/xtdc_client.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/engine_factory.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/logging_utils.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/market_adapters/crypto → echolon-0.3.2/echolon/quant_engine/market_adapters}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/base_adapter.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/market_adapters/shfe → echolon-0.3.2/echolon/quant_engine/market_adapters/crypto}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/crypto/crypto_adapter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/crypto/crypto_session_provider.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/crypto/perpetual_rules.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/crypto/session_config.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/market_adapters/us_futures → echolon-0.3.2/echolon/quant_engine/market_adapters/shfe}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/shfe/contract_rules.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/shfe/shfe_adapter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/shfe/shfe_session_provider.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/shfe/trading_calendar.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/schemas → echolon-0.3.2/echolon/quant_engine/market_adapters/us_futures}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/us_futures/cme_adapter.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/market_adapters/us_futures/session_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/reporting.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/run_backtest.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/schemas/README.md +0 -0
- {echolon-0.2.0/echolon/quant_engine/strategy → echolon-0.3.2/echolon/quant_engine/schemas}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/schemas/backtest_results.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/schemas/selected_trial.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/schemas/strategy_log.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/schemas/trade_log.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/strategy/al_s1 → echolon-0.3.2/echolon/quant_engine/strategy}/__init__.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/strategy/cu_s1 → echolon-0.3.2/echolon/quant_engine/strategy/al_s1}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/entry.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/exit.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/regime_params.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/risk.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/selected_robust_trial.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/sizer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/strategy.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/strategy_code_combined.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/strategy_indicator_list.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/al_s1/strategy_params.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/strategy/generators → echolon-0.3.2/echolon/quant_engine/strategy/cu_s1}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/entry.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/exit.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/regime_params.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/risk.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/selected_robust_trial.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/sizer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/strategy.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/strategy_code_combined.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/strategy_indicator_list.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/cu_s1/strategy_params.py +0 -0
- {echolon-0.2.0/echolon/quant_engine/strategy/zn_s1 → echolon-0.3.2/echolon/quant_engine/strategy/generators}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/generators/strategy_params_generator.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/loader.py +0 -0
- {echolon-0.2.0/tests → echolon-0.3.2/echolon/quant_engine/strategy/zn_s1}/__init__.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/entry.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/exit.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/regime_params.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/risk.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/selected_robust_trial.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/sizer.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/strategy.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/strategy_code_combined.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/strategy_indicator_list.json +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/strategy/zn_s1/strategy_params.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/echolon/quant_engine/types.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_backtest_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_imports.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_indicator_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_market_adapters.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_optuna_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_optuna_optimizer_config.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_quick_start.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_strategy_loader.py +0 -0
- {echolon-0.2.0 → echolon-0.3.2}/tests/test_trading_context.py +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.0 — AI-Native Layer (unreleased)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `echolon.native` subpackage with error system, validators, CLI, and templates
|
|
7
|
+
- `EchelonError` class hierarchy with 13 initial error codes
|
|
8
|
+
- `echolon` CLI with 5 commands: `validate`, `init-strategy`, `run`, `schema`, `examples`
|
|
9
|
+
- 3 strategy templates: `minimal`, `momentum_breakout`, `rsi_mean_reversion`
|
|
10
|
+
- 3 working examples at `examples/`
|
|
11
|
+
- `llms.txt` at repo root (AI agent entry point)
|
|
12
|
+
- `docs/` directory with QUICK_START, API_REFERENCE, COMPONENT_GUIDE, CONFIG_REFERENCE, PATTERNS, ERROR_CATALOG, and per-error docs
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Added `typer>=0.9.0` as a dependency for the CLI
|
|
16
|
+
|
|
17
|
+
## 0.2.0 — Config Interface
|
|
18
|
+
|
|
19
|
+
### Breaking Changes
|
|
20
|
+
- BacktestRunner, OptunaOptimizer, WFARunner, and PortfolioBacktestRunner now require explicit configs
|
|
21
|
+
- Removed module-level globals from `echolon.config.quant_engine`
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- BacktestConfig, OptunaConfig, IndicatorConfig Pydantic models
|
|
25
|
+
- `TradingContext.from_market()` classmethod
|
|
26
|
+
- `echolon.quick_start()` convenience helper
|
|
27
|
+
|
|
28
|
+
## 0.1.0 — Initial Release
|
|
29
|
+
|
|
30
|
+
Initial extraction from DolphinQuantStrategy monorepo.
|
echolon-0.3.2/PKG-INFO
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: echolon
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: See what others can't. Market-agnostic quantitative trading engine for futures backtesting, optimization, and deployment.
|
|
5
|
+
Project-URL: Homepage, https://github.com/dolphinquant/echolon
|
|
6
|
+
Project-URL: Repository, https://github.com/dolphinquant/echolon
|
|
7
|
+
Author-email: DolphinQuant <contact@dolphinquant.com>
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: CTA,SHFE,backtesting,futures,quantitative-trading
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: apscheduler>=3.10.0
|
|
18
|
+
Requires-Dist: backtrader>=1.9.78
|
|
19
|
+
Requires-Dist: ccxt>=4.0.0
|
|
20
|
+
Requires-Dist: matplotlib>=3.7.0
|
|
21
|
+
Requires-Dist: numpy>=1.24.0
|
|
22
|
+
Requires-Dist: optuna>=3.0.0
|
|
23
|
+
Requires-Dist: pandas>=2.0.0
|
|
24
|
+
Requires-Dist: psutil>=5.9.0
|
|
25
|
+
Requires-Dist: pyarrow>=14.0.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
28
|
+
Requires-Dist: pytz>=2023.3
|
|
29
|
+
Requires-Dist: scikit-learn>=1.3.0
|
|
30
|
+
Requires-Dist: scipy>=1.11.0
|
|
31
|
+
Requires-Dist: structlog>=23.0.0
|
|
32
|
+
Requires-Dist: ta-lib>=0.4.28
|
|
33
|
+
Requires-Dist: typer>=0.9.0
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# Echolon
|
|
40
|
+
|
|
41
|
+
See what others can't.
|
|
42
|
+
|
|
43
|
+
> Private development repo. Full README with launch content coming before public release.
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
Echolon exposes typed configuration via Pydantic models. Each component
|
|
48
|
+
receives only the configs it needs.
|
|
49
|
+
|
|
50
|
+
### Quick start
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import echolon
|
|
54
|
+
|
|
55
|
+
ctx, bt, opt = echolon.quick_start(
|
|
56
|
+
market="shfe",
|
|
57
|
+
instrument="cu",
|
|
58
|
+
start_date="2020-01-01",
|
|
59
|
+
end_date="2025-12-31",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Override defaults as needed
|
|
63
|
+
opt.n_trials = 500
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Full API
|
|
67
|
+
|
|
68
|
+
- `TradingContext` — market, instrument, frequency
|
|
69
|
+
- `BacktestConfig` — dates, paths, thresholds
|
|
70
|
+
- `OptunaConfig` — trials, target, parallelism
|
|
71
|
+
- `WFAConfig` — walk-forward windows
|
|
72
|
+
- `IndicatorConfig` — indicator period caps (defaults usually fine)
|
|
73
|
+
|
|
74
|
+
### Environment variables
|
|
75
|
+
|
|
76
|
+
- `ECHOLON_WORKSPACE_DIR` (default `./workspace`) — results, strategy code
|
|
77
|
+
- `ECHOLON_DATA_DIR` (default `./data`) — market data, indicator cache
|
|
78
|
+
- `ECHOLON_LOG_LEVEL` (default `INFO`)
|
|
79
|
+
- `ECHOLON_N_JOBS_DEFAULT` (default `-1`) — Optuna parallelism
|
|
80
|
+
|
|
81
|
+
## AI-Native Documentation
|
|
82
|
+
|
|
83
|
+
Echolon is designed for both humans and AI coding agents. See:
|
|
84
|
+
|
|
85
|
+
- [`llms.txt`](./llms.txt) — AI agent entry point with instructions
|
|
86
|
+
- [`docs/`](./docs/) — structured documentation
|
|
87
|
+
- [`examples/`](./examples/) — working strategies to learn from
|
|
88
|
+
|
|
89
|
+
## CLI
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install echolon
|
|
93
|
+
echolon init-strategy my_first --template minimal
|
|
94
|
+
echolon validate my_first/
|
|
95
|
+
echolon run my_first/ --instrument cu --start 2020-01-01 --end 2023-12-31
|
|
96
|
+
```
|
echolon-0.3.2/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Echolon
|
|
2
|
+
|
|
3
|
+
See what others can't.
|
|
4
|
+
|
|
5
|
+
> Private development repo. Full README with launch content coming before public release.
|
|
6
|
+
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
Echolon exposes typed configuration via Pydantic models. Each component
|
|
10
|
+
receives only the configs it needs.
|
|
11
|
+
|
|
12
|
+
### Quick start
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import echolon
|
|
16
|
+
|
|
17
|
+
ctx, bt, opt = echolon.quick_start(
|
|
18
|
+
market="shfe",
|
|
19
|
+
instrument="cu",
|
|
20
|
+
start_date="2020-01-01",
|
|
21
|
+
end_date="2025-12-31",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Override defaults as needed
|
|
25
|
+
opt.n_trials = 500
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Full API
|
|
29
|
+
|
|
30
|
+
- `TradingContext` — market, instrument, frequency
|
|
31
|
+
- `BacktestConfig` — dates, paths, thresholds
|
|
32
|
+
- `OptunaConfig` — trials, target, parallelism
|
|
33
|
+
- `WFAConfig` — walk-forward windows
|
|
34
|
+
- `IndicatorConfig` — indicator period caps (defaults usually fine)
|
|
35
|
+
|
|
36
|
+
### Environment variables
|
|
37
|
+
|
|
38
|
+
- `ECHOLON_WORKSPACE_DIR` (default `./workspace`) — results, strategy code
|
|
39
|
+
- `ECHOLON_DATA_DIR` (default `./data`) — market data, indicator cache
|
|
40
|
+
- `ECHOLON_LOG_LEVEL` (default `INFO`)
|
|
41
|
+
- `ECHOLON_N_JOBS_DEFAULT` (default `-1`) — Optuna parallelism
|
|
42
|
+
|
|
43
|
+
## AI-Native Documentation
|
|
44
|
+
|
|
45
|
+
Echolon is designed for both humans and AI coding agents. See:
|
|
46
|
+
|
|
47
|
+
- [`llms.txt`](./llms.txt) — AI agent entry point with instructions
|
|
48
|
+
- [`docs/`](./docs/) — structured documentation
|
|
49
|
+
- [`examples/`](./examples/) — working strategies to learn from
|
|
50
|
+
|
|
51
|
+
## CLI
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install echolon
|
|
55
|
+
echolon init-strategy my_first --template minimal
|
|
56
|
+
echolon validate my_first/
|
|
57
|
+
echolon run my_first/ --instrument cu --start 2020-01-01 --end 2023-12-31
|
|
58
|
+
```
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
All public Echolon classes and their signatures.
|
|
4
|
+
|
|
5
|
+
## BacktestConfig
|
|
6
|
+
|
|
7
|
+
**Module:** `echolon.config.backtest_config`
|
|
8
|
+
|
|
9
|
+
**Purpose:** Configuration for a single backtest run — dates, paths, thresholds.
|
|
10
|
+
|
|
11
|
+
**Signature:**
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
BacktestConfig(
|
|
15
|
+
start_date: str, # "YYYY-MM-DD"
|
|
16
|
+
end_date: str, # "YYYY-MM-DD"
|
|
17
|
+
strategy_dir: Path,
|
|
18
|
+
market_data_dir: Path,
|
|
19
|
+
indicator_dir: Path,
|
|
20
|
+
results_dir: Path,
|
|
21
|
+
max_drawdown_pct: float = 15.0,
|
|
22
|
+
is_end_date: Optional[str] = None,
|
|
23
|
+
oos_start_date: Optional[str] = None,
|
|
24
|
+
market_research_end_date: Optional[str] = None,
|
|
25
|
+
)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Example:**
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from echolon import BacktestConfig
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
|
|
34
|
+
cfg = BacktestConfig(
|
|
35
|
+
start_date="2020-01-01",
|
|
36
|
+
end_date="2023-12-31",
|
|
37
|
+
strategy_dir=Path("./my_strategy"),
|
|
38
|
+
market_data_dir=Path("./data/market"),
|
|
39
|
+
indicator_dir=Path("./data/indicators"),
|
|
40
|
+
results_dir=Path("./results"),
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Common errors:** CFG-001, CFG-002.
|
|
45
|
+
|
|
46
|
+
## OptunaConfig
|
|
47
|
+
|
|
48
|
+
**Module:** `echolon.config.optuna_config`
|
|
49
|
+
|
|
50
|
+
**Purpose:** Optuna hyperparameter optimization settings.
|
|
51
|
+
|
|
52
|
+
**Signature:**
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
OptunaConfig(
|
|
56
|
+
n_trials: int = 100,
|
|
57
|
+
n_jobs: int = -1,
|
|
58
|
+
timeout: Optional[int] = None,
|
|
59
|
+
target: Literal["sharpe_ratio", "total_return", "annual_return", "drawdown", "multi_objective"] = "sharpe_ratio",
|
|
60
|
+
n_trials_debug: int = 20,
|
|
61
|
+
aggressive_memory_management: bool = False,
|
|
62
|
+
enhanced_monitoring: bool = True,
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## IndicatorConfig
|
|
67
|
+
|
|
68
|
+
**Module:** `echolon.config.indicator_config`
|
|
69
|
+
|
|
70
|
+
**Purpose:** Technical indicator period caps (most users never override).
|
|
71
|
+
|
|
72
|
+
**Signature:**
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
IndicatorConfig(
|
|
76
|
+
interday_caps: dict[str, int],
|
|
77
|
+
intraday_caps: dict[str, int],
|
|
78
|
+
)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## TradingContext
|
|
82
|
+
|
|
83
|
+
**Module:** `echolon.config.markets.core.context`
|
|
84
|
+
|
|
85
|
+
**Purpose:** Market + instrument + frequency runtime context.
|
|
86
|
+
|
|
87
|
+
**Classmethod:**
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
TradingContext.from_market(
|
|
91
|
+
market: str, # e.g., "shfe"
|
|
92
|
+
instrument: str, # e.g., "cu"
|
|
93
|
+
frequency: str = "interday",
|
|
94
|
+
bar_size: str = "1d",
|
|
95
|
+
) -> TradingContext
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## quick_start()
|
|
99
|
+
|
|
100
|
+
**Module:** `echolon`
|
|
101
|
+
|
|
102
|
+
**Purpose:** Build sensible default configs for common cases.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from echolon import quick_start
|
|
106
|
+
|
|
107
|
+
ctx, bt, opt = quick_start(
|
|
108
|
+
market="shfe",
|
|
109
|
+
instrument="cu",
|
|
110
|
+
start_date="2020-01-01",
|
|
111
|
+
end_date="2023-12-31",
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## EntrySignalOutput
|
|
116
|
+
|
|
117
|
+
**Module:** `echolon.quant_engine.types`
|
|
118
|
+
|
|
119
|
+
**Returned by:** `entry_rule.generate_signal()`
|
|
120
|
+
|
|
121
|
+
**Required fields:**
|
|
122
|
+
- `signal: Literal['LONG', 'SHORT', 'HOLD']`
|
|
123
|
+
- `strength: float` (0.0 to 1.0)
|
|
124
|
+
- `type: str`
|
|
125
|
+
- `entry_reason: str`
|
|
126
|
+
- `regime: str`
|
|
127
|
+
|
|
128
|
+
**Optional:**
|
|
129
|
+
- `intent: Optional[OrderIntent]` — required for non-HOLD signals
|
|
130
|
+
|
|
131
|
+
**Common errors:** VAL-001, VAL-002.
|
|
132
|
+
|
|
133
|
+
## ExitSignalOutput
|
|
134
|
+
|
|
135
|
+
**Returned by:** `exit_rule.should_exit()`
|
|
136
|
+
|
|
137
|
+
**Required fields:**
|
|
138
|
+
- `should_exit: bool`
|
|
139
|
+
- `exit_reason: str`
|
|
140
|
+
- `position_size: float` (≥ 0)
|
|
141
|
+
- `bars_since_entry: int` (≥ 0)
|
|
142
|
+
|
|
143
|
+
**Optional:**
|
|
144
|
+
- `intent: Optional[OrderIntent]` — required when `should_exit=True`
|
|
145
|
+
|
|
146
|
+
## RiskOutput
|
|
147
|
+
|
|
148
|
+
**Returned by:** `risk_manager.can_trade()`
|
|
149
|
+
|
|
150
|
+
**Required fields:**
|
|
151
|
+
- `trading_allowed: bool`
|
|
152
|
+
- `risk_reason: str`
|
|
153
|
+
|
|
154
|
+
## SizerOutput
|
|
155
|
+
|
|
156
|
+
**Returned by:** `position_sizer.calculate_size(signal_data)`
|
|
157
|
+
|
|
158
|
+
**Required fields:**
|
|
159
|
+
- `calculated_size: int` (≥ 0, whole contracts)
|
|
160
|
+
- `signal_direction: Literal['LONG', 'SHORT', 'HOLD']`
|
|
161
|
+
- `sizing_reason: str`
|
|
162
|
+
- `raw_size: float` (≥ 0)
|
|
163
|
+
|
|
164
|
+
## OrderIntent (enum)
|
|
165
|
+
|
|
166
|
+
**Module:** `echolon.quant_engine.core.interfaces.trading_interfaces`
|
|
167
|
+
|
|
168
|
+
**Values:**
|
|
169
|
+
- `ENTRY_LONG`, `ENTRY_SHORT`
|
|
170
|
+
- `EXIT_LONG`, `EXIT_SHORT`
|
|
171
|
+
- `FORCED_EXIT`
|
|
172
|
+
- `ROLLOVER_CLOSE`, `ROLLOVER_OPEN`
|
|
173
|
+
|
|
174
|
+
## EchelonError
|
|
175
|
+
|
|
176
|
+
**Module:** `echolon` (top-level) or `echolon.native.validation.errors`
|
|
177
|
+
|
|
178
|
+
**Base class** for all Echolon validation errors. Every error has `code`, `what`, `why`, `fix`, `context`, `docs_url`.
|
|
179
|
+
|
|
180
|
+
**Subclasses:**
|
|
181
|
+
- `ValidationError` (VAL-xxx)
|
|
182
|
+
- `ConfigError` (CFG-xxx)
|
|
183
|
+
- `StrategyStructureError` (STR-xxx)
|
|
184
|
+
- `IndicatorError` (IND-xxx)
|
|
185
|
+
- `ParameterError` (PRM-xxx)
|
|
186
|
+
- `DataError` (DAT-xxx)
|
|
187
|
+
|
|
188
|
+
See [ERROR_CATALOG.md](ERROR_CATALOG.md).
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Component Guide
|
|
2
|
+
|
|
3
|
+
Every Echolon strategy has 4 components. This guide explains each one.
|
|
4
|
+
|
|
5
|
+
## entry_rule (entry.py)
|
|
6
|
+
|
|
7
|
+
**Class name:** `entry_rule` (exact — required by StrategyLoader)
|
|
8
|
+
**Base:** `BaseComponent`
|
|
9
|
+
**Method:** `generate_signal() -> EntrySignalOutput`
|
|
10
|
+
|
|
11
|
+
Called every bar when there is no open position and no pending orders.
|
|
12
|
+
|
|
13
|
+
**Example:**
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from echolon.quant_engine.core.base.base_component import BaseComponent
|
|
17
|
+
from echolon.quant_engine.core.interfaces.trading_interfaces import OrderIntent
|
|
18
|
+
from echolon.quant_engine.types import EntrySignalOutput
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class entry_rule(BaseComponent):
|
|
22
|
+
def __init__(self, trading_engine, **params):
|
|
23
|
+
super().__init__(trading_engine, **params)
|
|
24
|
+
self.rsi_period = self.params["rsi_period"]
|
|
25
|
+
|
|
26
|
+
def generate_signal(self) -> EntrySignalOutput:
|
|
27
|
+
rsi = self.get_indicator(f"rsi_{self.rsi_period}")
|
|
28
|
+
regime = self.get_market_regime()
|
|
29
|
+
if rsi < 30:
|
|
30
|
+
return EntrySignalOutput(
|
|
31
|
+
signal="LONG", strength=1.0,
|
|
32
|
+
type="oversold_entry",
|
|
33
|
+
entry_reason=f"RSI({self.rsi_period})={rsi} < 30",
|
|
34
|
+
intent=OrderIntent.ENTRY_LONG,
|
|
35
|
+
regime=regime,
|
|
36
|
+
)
|
|
37
|
+
return EntrySignalOutput(
|
|
38
|
+
signal="HOLD", strength=0.0, type="hold",
|
|
39
|
+
entry_reason="Not oversold", regime=regime,
|
|
40
|
+
)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Common errors:**
|
|
44
|
+
- VAL-001: missing required field
|
|
45
|
+
- VAL-003: wrong __init__ signature
|
|
46
|
+
- IND-001: uppercase indicator name
|
|
47
|
+
|
|
48
|
+
## exit_rule (exit.py)
|
|
49
|
+
|
|
50
|
+
**Class name:** `exit_rule`
|
|
51
|
+
**Base:** `BaseComponent`
|
|
52
|
+
**Method:** `should_exit() -> ExitSignalOutput`
|
|
53
|
+
|
|
54
|
+
Called every bar when there is an open position.
|
|
55
|
+
|
|
56
|
+
Stateful exit rules (trailing stops, bars-held counters) must reset their state when there is no position. See the minimal template's `exit.py`.
|
|
57
|
+
|
|
58
|
+
## risk_manager (risk.py)
|
|
59
|
+
|
|
60
|
+
**Class name:** `risk_manager`
|
|
61
|
+
**Base:** `BaseComponent`
|
|
62
|
+
**Method:** `can_trade() -> RiskOutput`
|
|
63
|
+
|
|
64
|
+
Called at the start of every bar. Returns `trading_allowed=True` to permit trading, `False` to block all new entries.
|
|
65
|
+
|
|
66
|
+
Use cases: max daily loss, max consecutive losses, trading-hours filter.
|
|
67
|
+
|
|
68
|
+
## position_sizer (sizer.py)
|
|
69
|
+
|
|
70
|
+
**Class name:** `position_sizer`
|
|
71
|
+
**Base:** `BaseComponent`
|
|
72
|
+
**Method:** `calculate_size(signal_data: EntrySignalOutput) -> SizerOutput`
|
|
73
|
+
|
|
74
|
+
Called after `entry_rule.generate_signal()` produces a non-HOLD signal. Receives the signal (so sizer can branch on regime, strength, etc.).
|
|
75
|
+
|
|
76
|
+
The sizer MUST call `self.validate_and_convert_position_size(raw_float)` before setting `calculated_size` — this rounds to whole contracts and handles edge cases.
|
|
77
|
+
|
|
78
|
+
## Data access helpers
|
|
79
|
+
|
|
80
|
+
All components inherit these helpers from `BaseComponent`:
|
|
81
|
+
|
|
82
|
+
- `self.get_current_price() -> float` — close of current bar
|
|
83
|
+
- `self.get_indicator(name: str) -> float` — value of pre-computed indicator (use lowercase names!)
|
|
84
|
+
- `self.get_market_regime() -> str` — one of: `ranging`, `trending_up`, `trending_down`, `volatile`
|
|
85
|
+
- `self.params: dict` — parameters from strategy_params.py
|
|
86
|
+
- `self.portfolio: IPortfolio` — access position info
|
|
87
|
+
- `self.validate_and_convert_position_size(float) -> int` — sizer helper
|
|
88
|
+
|
|
89
|
+
## Strategy coordinator (strategy.py)
|
|
90
|
+
|
|
91
|
+
**Class name:** `strategy_main`
|
|
92
|
+
**Base:** `BaseStrategy`
|
|
93
|
+
**Method:** `_execute_bar() -> None` (not `on_bar`)
|
|
94
|
+
|
|
95
|
+
The canonical pattern:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
def _execute_bar(self) -> None:
|
|
99
|
+
risk_out = self.risk_manager.can_trade()
|
|
100
|
+
if not risk_out.trading_allowed:
|
|
101
|
+
return
|
|
102
|
+
if self.has_position() and not self.has_pending_orders():
|
|
103
|
+
exit_out = self.exit_rule.should_exit()
|
|
104
|
+
if exit_out.should_exit and exit_out.intent is not None:
|
|
105
|
+
self.exit(exit_out.intent)
|
|
106
|
+
return
|
|
107
|
+
if not self.has_position() and not self.has_pending_orders():
|
|
108
|
+
entry_out = self.entry_rule.generate_signal()
|
|
109
|
+
if entry_out.signal != "HOLD" and entry_out.intent is not None:
|
|
110
|
+
sizer_out = self.position_sizer.calculate_size(entry_out)
|
|
111
|
+
if sizer_out.calculated_size > 0:
|
|
112
|
+
self.entry(entry_out.intent, sizer_out.calculated_size)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Every bundled template uses this exact pattern. Only customize if your strategy truly needs a different structure.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
Echolon uses Pydantic v2 models for all configuration. Each config class is a typed object — IDEs and LLMs can introspect it.
|
|
4
|
+
|
|
5
|
+
## BacktestConfig
|
|
6
|
+
|
|
7
|
+
See [API_REFERENCE.md#backtestconfig](API_REFERENCE.md#backtestconfig).
|
|
8
|
+
|
|
9
|
+
Common mistakes:
|
|
10
|
+
- `end_date` before `start_date` → CFG-001
|
|
11
|
+
- Missing directory path → CFG-002
|
|
12
|
+
|
|
13
|
+
## OptunaConfig
|
|
14
|
+
|
|
15
|
+
See [API_REFERENCE.md#optunaconfig](API_REFERENCE.md#optunaconfig).
|
|
16
|
+
|
|
17
|
+
The `target` field accepts:
|
|
18
|
+
- `"sharpe_ratio"` — maximize risk-adjusted return (default)
|
|
19
|
+
- `"total_return"` — maximize absolute return
|
|
20
|
+
- `"annual_return"` — maximize annualized return
|
|
21
|
+
- `"drawdown"` — minimize max drawdown
|
|
22
|
+
- `"multi_objective"` — Pareto frontier over Sharpe + drawdown
|
|
23
|
+
|
|
24
|
+
## TradingContext
|
|
25
|
+
|
|
26
|
+
Runtime context: market, instrument, frequency, bar size.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from echolon import TradingContext
|
|
30
|
+
|
|
31
|
+
ctx = TradingContext.from_market(
|
|
32
|
+
market="shfe",
|
|
33
|
+
instrument="cu",
|
|
34
|
+
frequency="interday",
|
|
35
|
+
bar_size="1d",
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Environment Variables
|
|
40
|
+
|
|
41
|
+
| Variable | Default | Purpose |
|
|
42
|
+
|----------|---------|---------|
|
|
43
|
+
| `ECHOLON_WORKSPACE_DIR` | `./workspace` | Workspace root |
|
|
44
|
+
| `ECHOLON_DATA_DIR` | `./data` | Market data + indicators |
|
|
45
|
+
| `ECHOLON_LOG_LEVEL` | `INFO` | Logging verbosity |
|
|
46
|
+
| `ECHOLON_N_JOBS_DEFAULT` | `-1` | Default Optuna parallelism |
|
|
47
|
+
|
|
48
|
+
Set via shell export, `.env` file, or Docker env config.
|
|
49
|
+
|
|
50
|
+
## quick_start()
|
|
51
|
+
|
|
52
|
+
For common cases, use the convenience helper:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from echolon import quick_start
|
|
56
|
+
|
|
57
|
+
ctx, bt, opt = quick_start(
|
|
58
|
+
market="shfe",
|
|
59
|
+
instrument="cu",
|
|
60
|
+
start_date="2020-01-01",
|
|
61
|
+
end_date="2023-12-31",
|
|
62
|
+
)
|
|
63
|
+
# Override anything
|
|
64
|
+
opt.n_trials = 500
|
|
65
|
+
bt.max_drawdown_pct = 20.0
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`quick_start` uses env vars for paths with fallbacks to `./workspace` and `./data`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Error Catalog
|
|
2
|
+
|
|
3
|
+
All Echolon errors use stable codes. Click any code for the full fix guide.
|
|
4
|
+
|
|
5
|
+
| Code | Category | What went wrong |
|
|
6
|
+
|------|----------|-----------------|
|
|
7
|
+
| [VAL-001](errors/VAL-001.md) | Validation | Missing required field in component output |
|
|
8
|
+
| [VAL-002](errors/VAL-002.md) | Validation | Invalid enum value in signal field |
|
|
9
|
+
| [VAL-003](errors/VAL-003.md) | Validation | Component class signature mismatch |
|
|
10
|
+
| [CFG-001](errors/CFG-001.md) | Config | end_date before start_date |
|
|
11
|
+
| [CFG-002](errors/CFG-002.md) | Config | Required directory does not exist |
|
|
12
|
+
| [STR-001](errors/STR-001.md) | Structure | Strategy directory missing required file |
|
|
13
|
+
| [STR-002](errors/STR-002.md) | Structure | Required class not found in file |
|
|
14
|
+
| [STR-003](errors/STR-003.md) | Structure | Required method not implemented |
|
|
15
|
+
| [IND-001](errors/IND-001.md) | Indicator | Indicator name casing mismatch |
|
|
16
|
+
| [IND-002](errors/IND-002.md) | Indicator | Indicator not declared in JSON |
|
|
17
|
+
| [PRM-001](errors/PRM-001.md) | Parameter | Missing 'printlog' key in component params |
|
|
18
|
+
| [PRM-002](errors/PRM-002.md) | Parameter | DEFAULT_PARAMS structure mismatch |
|
|
19
|
+
| [DAT-001](errors/DAT-001.md) | Data | Missing OHLCV file |
|