dexbot 1.4.21 → 1.4.23
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.
- package/CHANGELOG.md +52 -0
- package/README.md +8 -5
- package/analysis/ama_fitting/analyze_ama_price_changes.ts +7 -3
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +6 -6
- package/analysis/ama_fitting/calibrate_convergence_er.ts +7 -5
- package/analysis/ama_fitting/fetch_lp_candles.ts +8 -3
- package/analysis/ama_fitting/generate_unified_comparison_chart.ts +30 -67
- package/analysis/ama_fitting/optimizer_high_resolution.ts +26 -17
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/analyze_derivatives.ts +4 -4
- package/analysis/analyze_dynamic_weight.ts +21 -5
- package/analysis/analyze_kalman.ts +54 -25
- package/analysis/analyze_regime.ts +2 -2
- package/analysis/analyze_regime_windows.ts +27 -19
- package/analysis/analyze_risk_profile.ts +3 -3
- package/analysis/analyze_trade_heatmap.ts +3 -3
- package/analysis/analyze_volatility.ts +2 -2
- package/analysis/bot_fitting/README.md +93 -19
- package/analysis/bot_fitting/backtest_ama_sweep.ts +316 -199
- package/analysis/bot_fitting/backtest_bot_fitting.ts +520 -85
- package/analysis/bot_fitting/shared_utils.ts +15 -9
- package/analysis/bot_key_utils.ts +13 -6
- package/analysis/bot_usage/discover_bot_accounts.ts +5 -3
- package/analysis/bot_usage/kibana_bot_queries.ts +1 -1
- package/analysis/chart_css.ts +6 -4
- package/analysis/chart_ui.ts +0 -1
- package/analysis/chart_utils.ts +11 -2
- package/analysis/derivative_chart_generator.ts +2 -2
- package/analysis/price_sources.ts +8 -2
- package/analysis/resolve_source.ts +1 -1
- package/analysis/trade_profitability.ts +61 -28
- package/analysis/tradingview/README.md +24 -4
- package/analysis/tradingview/analyze_tradingview.ts +1 -1
- package/analysis/tradingview/tradingview_uplot_chart_generator.ts +356 -86
- package/analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md +1 -1
- package/analysis/trend_detection/derivative_analyzer.ts +12 -3
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +25 -27
- package/analysis/trend_detection/hurst_analyzer.ts +1 -1
- package/analysis/trend_detection/kalman_chart_generator.ts +42 -14
- package/analysis/trend_detection/package.json +1 -1
- package/analysis/trend_detection/regime_chart_generator.ts +39 -19
- package/analysis/trend_detection/tests/test_kalman_trend.ts +1 -1
- package/analysis/trend_detection/tests/test_kalman_velocity_smoothing.ts +1 -1
- package/analysis/trend_detection/volatility_chart_generator.ts +1 -1
- package/claw/index.ts +1 -1
- package/claw/modules/claw_bridge.ts +3 -3
- package/claw/modules/claw_catalog.ts +1 -1
- package/claw/modules/claw_launcher.ts +1 -1
- package/claw/modules/claw_skill_md.ts +7 -10
- package/claw/modules/credit_runtime_adapter.ts +1 -1
- package/claw/modules/decision_loop.ts +5 -9
- package/claw/modules/dexbot_bridge.ts +7 -7
- package/claw/modules/feed_price_source.ts +1 -1
- package/claw/modules/kibana_price_source.ts +1 -1
- package/claw/modules/launcher_mode_detector.ts +1 -1
- package/claw/modules/launcher_paths.ts +1 -1
- package/claw/modules/position_discovery.ts +1 -1
- package/claw/modules/position_health.ts +1 -1
- package/claw/package.json +3 -3
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/skills/launcher-ops/references/launcher-workflow.md +2 -2
- package/claw/tests/package.json +1 -1
- package/claw/tests/test_claw_bridge.ts +45 -21
- package/claw/tests/test_claw_catalog_and_credentials.ts +8 -4
- package/claw/tests/test_claw_chain_layer.ts +39 -19
- package/claw/tests/test_claw_data_flow.ts +28 -20
- package/claw/tests/test_claw_domain_logic.ts +25 -19
- package/claw/tests/test_claw_manifest_and_matrix.ts +23 -3
- package/claw/tests/test_claw_mcp_transport.ts +13 -8
- package/claw/tests/test_claw_regressions.ts +254 -128
- package/claw/tests/test_claw_skill_generation.ts +1 -1
- package/claw/tests/test_nullclaw_tmp_integration.ts +2 -3
- package/claw/tests/test_position_health.ts +1 -77
- package/claw/tests/test_position_manager.ts +20 -18
- package/claw/tests/test_position_manager_watch_health.ts +39 -43
- package/claw/tests/test_short_mpa_strategy.ts +20 -17
- package/claw/tsconfig.json +4 -3
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.js +7 -3
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.js.map +1 -1
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +6 -6
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js +7 -5
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js.map +1 -1
- package/dist/analysis/ama_fitting/fetch_lp_candles.js +8 -3
- package/dist/analysis/ama_fitting/fetch_lp_candles.js.map +1 -1
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts +2 -2
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js +31 -75
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js.map +1 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js +25 -17
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js.map +1 -1
- package/dist/analysis/analyze_derivatives.d.ts +0 -18
- package/dist/analysis/analyze_derivatives.d.ts.map +1 -1
- package/dist/analysis/analyze_derivatives.js +4 -4
- package/dist/analysis/analyze_derivatives.js.map +1 -1
- package/dist/analysis/analyze_dynamic_weight.d.ts +0 -11
- package/dist/analysis/analyze_dynamic_weight.d.ts.map +1 -1
- package/dist/analysis/analyze_dynamic_weight.js +19 -5
- package/dist/analysis/analyze_dynamic_weight.js.map +1 -1
- package/dist/analysis/analyze_kalman.d.ts +0 -10
- package/dist/analysis/analyze_kalman.d.ts.map +1 -1
- package/dist/analysis/analyze_kalman.js +51 -26
- package/dist/analysis/analyze_kalman.js.map +1 -1
- package/dist/analysis/analyze_regime.d.ts +0 -17
- package/dist/analysis/analyze_regime.d.ts.map +1 -1
- package/dist/analysis/analyze_regime.js +2 -2
- package/dist/analysis/analyze_regime.js.map +1 -1
- package/dist/analysis/analyze_regime_windows.d.ts +0 -16
- package/dist/analysis/analyze_regime_windows.d.ts.map +1 -1
- package/dist/analysis/analyze_regime_windows.js +28 -21
- package/dist/analysis/analyze_regime_windows.js.map +1 -1
- package/dist/analysis/analyze_risk_profile.js +3 -3
- package/dist/analysis/analyze_risk_profile.js.map +1 -1
- package/dist/analysis/analyze_trade_heatmap.js +3 -3
- package/dist/analysis/analyze_trade_heatmap.js.map +1 -1
- package/dist/analysis/analyze_volatility.d.ts +0 -19
- package/dist/analysis/analyze_volatility.d.ts.map +1 -1
- package/dist/analysis/analyze_volatility.js +2 -2
- package/dist/analysis/analyze_volatility.js.map +1 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts +30 -14
- package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js +330 -193
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js.map +1 -1
- package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts +136 -1
- package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js +527 -83
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.d.ts +1 -1
- package/dist/analysis/bot_fitting/shared_utils.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.js +14 -8
- package/dist/analysis/bot_fitting/shared_utils.js.map +1 -1
- package/dist/analysis/bot_key_utils.d.ts.map +1 -1
- package/dist/analysis/bot_key_utils.js +13 -6
- package/dist/analysis/bot_key_utils.js.map +1 -1
- package/dist/analysis/bot_usage/discover_bot_accounts.js +5 -3
- package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
- package/dist/analysis/chart_css.d.ts +3 -1
- package/dist/analysis/chart_css.d.ts.map +1 -1
- package/dist/analysis/chart_css.js +6 -3
- package/dist/analysis/chart_css.js.map +1 -1
- package/dist/analysis/chart_ui.d.ts.map +1 -1
- package/dist/analysis/chart_ui.js.map +1 -1
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +15 -2
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +2 -2
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/price_sources.d.ts +1 -0
- package/dist/analysis/price_sources.d.ts.map +1 -1
- package/dist/analysis/price_sources.js +8 -2
- package/dist/analysis/price_sources.js.map +1 -1
- package/dist/analysis/resolve_source.d.ts.map +1 -1
- package/dist/analysis/resolve_source.js +1 -1
- package/dist/analysis/resolve_source.js.map +1 -1
- package/dist/analysis/trade_profitability.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.js +58 -29
- package/dist/analysis/trade_profitability.js.map +1 -1
- package/dist/analysis/tradingview/analyze_tradingview.js +1 -1
- package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +356 -86
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts +1 -0
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +1 -1
- package/dist/analysis/trend_detection/derivative_analyzer.js +12 -3
- package/dist/analysis/trend_detection/derivative_analyzer.js.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +26 -27
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/hurst_analyzer.d.ts +1 -1
- package/dist/analysis/trend_detection/hurst_analyzer.d.ts.map +1 -1
- package/dist/analysis/trend_detection/hurst_analyzer.js +1 -1
- package/dist/analysis/trend_detection/hurst_analyzer.js.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.js +41 -13
- package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.js +38 -19
- package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/tests/test_kalman_trend.js +1 -1
- package/dist/analysis/trend_detection/tests/test_kalman_trend.js.map +1 -1
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js +1 -1
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.js +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -1
- package/dist/bot.js +1 -1
- package/dist/bot.js.map +1 -1
- package/dist/credential-daemon.d.ts +1 -1
- package/dist/credential-daemon.js +1 -1
- package/dist/dexbot.d.ts.map +1 -1
- package/dist/dexbot.js +7 -8
- package/dist/dexbot.js.map +1 -1
- package/dist/market_adapter/ama_signal_runner.js +3 -1
- package/dist/market_adapter/ama_signal_runner.js.map +1 -1
- package/dist/market_adapter/candle_utils.d.ts +1 -3
- package/dist/market_adapter/candle_utils.d.ts.map +1 -1
- package/dist/market_adapter/candle_utils.js +1 -11
- package/dist/market_adapter/candle_utils.js.map +1 -1
- package/dist/market_adapter/core/asymmetric_bounds.d.ts.map +1 -1
- package/dist/market_adapter/core/asymmetric_bounds.js +33 -30
- package/dist/market_adapter/core/asymmetric_bounds.js.map +1 -1
- package/dist/market_adapter/core/config_normalizers.d.ts.map +1 -1
- package/dist/market_adapter/core/config_normalizers.js +10 -1
- package/dist/market_adapter/core/config_normalizers.js.map +1 -1
- package/dist/market_adapter/core/kibana_candles.d.ts +18 -42
- package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_candles.js +101 -7
- package/dist/market_adapter/core/kibana_candles.js.map +1 -1
- package/dist/market_adapter/core/kibana_client.d.ts +0 -14
- package/dist/market_adapter/core/kibana_client.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_client.js +39 -6
- package/dist/market_adapter/core/kibana_client.js.map +1 -1
- package/dist/market_adapter/core/kibana_market_candles.d.ts +0 -27
- package/dist/market_adapter/core/kibana_market_candles.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_market_candles.js +1 -1
- package/dist/market_adapter/core/kibana_market_candles.js.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.d.ts +21 -11
- package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.js +95 -37
- package/dist/market_adapter/core/market_adapter_service.js.map +1 -1
- package/dist/market_adapter/core/signals/hurst_analyzer.d.ts +10 -1
- package/dist/market_adapter/core/signals/hurst_analyzer.d.ts.map +1 -1
- package/dist/market_adapter/core/signals/hurst_analyzer.js +28 -17
- package/dist/market_adapter/core/signals/hurst_analyzer.js.map +1 -1
- package/dist/market_adapter/core/signals/kalman_trend_analyzer.d.ts +5 -0
- package/dist/market_adapter/core/signals/kalman_trend_analyzer.d.ts.map +1 -1
- package/dist/market_adapter/core/signals/kalman_trend_analyzer.js +24 -24
- package/dist/market_adapter/core/signals/kalman_trend_analyzer.js.map +1 -1
- package/dist/market_adapter/core/signals/kalman_velocity_smoothing.d.ts.map +1 -1
- package/dist/market_adapter/core/signals/kalman_velocity_smoothing.js +5 -1
- package/dist/market_adapter/core/signals/kalman_velocity_smoothing.js.map +1 -1
- package/dist/market_adapter/core/signals/permutation_entropy_analyzer.d.ts.map +1 -1
- package/dist/market_adapter/core/signals/permutation_entropy_analyzer.js +20 -3
- package/dist/market_adapter/core/signals/permutation_entropy_analyzer.js.map +1 -1
- package/dist/market_adapter/core/strategies/ama.js +1 -1
- package/dist/market_adapter/core/strategies/ama.js.map +1 -1
- package/dist/market_adapter/core/strategies/ama_slope_model.d.ts +2 -2
- package/dist/market_adapter/core/strategies/ama_slope_model.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/ama_slope_model.js +16 -4
- package/dist/market_adapter/core/strategies/ama_slope_model.js.map +1 -1
- package/dist/market_adapter/core/strategies/atr/calculator.d.ts +4 -3
- package/dist/market_adapter/core/strategies/atr/calculator.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/atr/calculator.js +16 -8
- package/dist/market_adapter/core/strategies/atr/calculator.js.map +1 -1
- package/dist/market_adapter/core/strategies/collateral_manager.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/collateral_manager.js +8 -3
- package/dist/market_adapter/core/strategies/collateral_manager.js.map +1 -1
- package/dist/market_adapter/core/strategies/dynamic_weight_series.d.ts +40 -1
- package/dist/market_adapter/core/strategies/dynamic_weight_series.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/dynamic_weight_series.js +116 -2
- package/dist/market_adapter/core/strategies/dynamic_weight_series.js.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.js +26 -20
- package/dist/market_adapter/core/strategies/regime_gate.js.map +1 -1
- package/dist/market_adapter/core/strategies/volatility_shift.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/volatility_shift.js +3 -0
- package/dist/market_adapter/core/strategies/volatility_shift.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +69 -55
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts +0 -26
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.js +67 -14
- package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
- package/dist/market_adapter/inputs/kibana_source.d.ts +4 -28
- package/dist/market_adapter/inputs/kibana_source.d.ts.map +1 -1
- package/dist/market_adapter/inputs/kibana_source.js +5 -2
- package/dist/market_adapter/inputs/kibana_source.js.map +1 -1
- package/dist/market_adapter/lp_chart_core.js +1 -1
- package/dist/market_adapter/lp_chart_core.js.map +1 -1
- package/dist/market_adapter/lp_chart_runner.d.ts +10 -1
- package/dist/market_adapter/lp_chart_runner.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_runner.js +2 -2
- package/dist/market_adapter/lp_chart_runner.js.map +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.js +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.js.map +1 -1
- package/dist/market_adapter/market_adapter.d.ts +1 -2
- package/dist/market_adapter/market_adapter.d.ts.map +1 -1
- package/dist/market_adapter/market_adapter.js +9 -8
- package/dist/market_adapter/market_adapter.js.map +1 -1
- package/dist/market_adapter/test_helpers.d.ts +3 -3
- package/dist/market_adapter/test_helpers.d.ts.map +1 -1
- package/dist/market_adapter/test_helpers.js +3 -3
- package/dist/market_adapter/test_helpers.js.map +1 -1
- package/dist/market_adapter/utils/adapter_client.js +1 -1
- package/dist/market_adapter/utils/adapter_client.js.map +1 -1
- package/dist/market_adapter/utils/atomic_write.js +1 -1
- package/dist/market_adapter/utils/atomic_write.js.map +1 -1
- package/dist/market_adapter/utils/chain.d.ts +0 -2
- package/dist/market_adapter/utils/chain.d.ts.map +1 -1
- package/dist/market_adapter/utils/chain.js +2 -3
- package/dist/market_adapter/utils/chain.js.map +1 -1
- package/dist/market_adapter/utils/data_discovery.d.ts.map +1 -1
- package/dist/market_adapter/utils/data_discovery.js +24 -8
- package/dist/market_adapter/utils/data_discovery.js.map +1 -1
- package/dist/market_adapter/utils/dynamic_grid_snapshot.d.ts.map +1 -1
- package/dist/market_adapter/utils/dynamic_grid_snapshot.js +2 -5
- package/dist/market_adapter/utils/dynamic_grid_snapshot.js.map +1 -1
- package/dist/market_adapter/utils/file_lock.d.ts +4 -1
- package/dist/market_adapter/utils/file_lock.d.ts.map +1 -1
- package/dist/market_adapter/utils/file_lock.js +89 -25
- package/dist/market_adapter/utils/file_lock.js.map +1 -1
- package/dist/market_adapter/utils/native_history.d.ts.map +1 -1
- package/dist/market_adapter/utils/native_history.js +5 -1
- package/dist/market_adapter/utils/native_history.js.map +1 -1
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +47 -12
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/authority_resolver.js +1 -1
- package/dist/modules/authority_resolver.js.map +1 -1
- package/dist/modules/bitshares-native/chain_client.js +1 -1
- package/dist/modules/bitshares-native/chain_client.js.map +1 -1
- package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts +0 -12
- package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -1
- package/dist/modules/bitshares-native/crypto/ecc.browser.js +1 -1
- package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -1
- package/dist/modules/bitshares-native/crypto/ecc_selector.js +1 -1
- package/dist/modules/bitshares-native/crypto/ecc_selector.js.map +1 -1
- package/dist/modules/bitshares-native/index.d.ts.map +1 -1
- package/dist/modules/bitshares-native/index.js +1 -1
- package/dist/modules/bitshares-native/index.js.map +1 -1
- package/dist/modules/bitshares-native/lru_cache.js +1 -1
- package/dist/modules/bitshares-native/lru_cache.js.map +1 -1
- package/dist/modules/bitshares-native/resolvers.d.ts +0 -2
- package/dist/modules/bitshares-native/resolvers.d.ts.map +1 -1
- package/dist/modules/bitshares-native/resolvers.js +18 -4
- package/dist/modules/bitshares-native/resolvers.js.map +1 -1
- package/dist/modules/bitshares-native/serial/chain_constants.js +1 -1
- package/dist/modules/bitshares-native/serial/chain_constants.js.map +1 -1
- package/dist/modules/bitshares-native/serial/index.d.ts.map +1 -1
- package/dist/modules/bitshares-native/serial/index.js +1 -1
- package/dist/modules/bitshares-native/serial/index.js.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.js +1 -1
- package/dist/modules/bitshares-native/serial/operations.js.map +1 -1
- package/dist/modules/bitshares-native/serial/serializer.js +1 -1
- package/dist/modules/bitshares-native/serial/serializer.js.map +1 -1
- package/dist/modules/bitshares-native/serial/types.js +1 -1
- package/dist/modules/bitshares-native/serial/types.js.map +1 -1
- package/dist/modules/bitshares-native/signing_client.js +2 -2
- package/dist/modules/bitshares-native/signing_client.js.map +1 -1
- package/dist/modules/bitshares-native/subscriptions.d.ts.map +1 -1
- package/dist/modules/bitshares-native/subscriptions.js +5 -14
- package/dist/modules/bitshares-native/subscriptions.js.map +1 -1
- package/dist/modules/bitshares-native/transport.js +1 -1
- package/dist/modules/bitshares-native/transport.js.map +1 -1
- package/dist/modules/bitshares-native/tx/builder.js +1 -1
- package/dist/modules/bitshares-native/tx/builder.js.map +1 -1
- package/dist/modules/bitshares-native/tx/tx_cache.d.ts +3 -2
- package/dist/modules/bitshares-native/tx/tx_cache.d.ts.map +1 -1
- package/dist/modules/bitshares-native/tx/tx_cache.js +7 -4
- package/dist/modules/bitshares-native/tx/tx_cache.js.map +1 -1
- package/dist/modules/bitshares_client.js +10 -10
- package/dist/modules/bitshares_client.js.map +1 -1
- package/dist/modules/bot_settings.d.ts.map +1 -1
- package/dist/modules/bot_settings.js +11 -18
- package/dist/modules/bot_settings.js.map +1 -1
- package/dist/modules/bots_file_lock.d.ts +1 -1
- package/dist/modules/bots_file_lock.js +1 -1
- package/dist/modules/broadcast_failure.d.ts +13 -0
- package/dist/modules/broadcast_failure.d.ts.map +1 -1
- package/dist/modules/broadcast_failure.js +0 -13
- package/dist/modules/broadcast_failure.js.map +1 -1
- package/dist/modules/chain_orders.d.ts.map +1 -1
- package/dist/modules/chain_orders.js +15 -17
- package/dist/modules/chain_orders.js.map +1 -1
- package/dist/modules/config.js +1 -1
- package/dist/modules/config.js.map +1 -1
- package/dist/modules/constants.d.ts +21 -20
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +60 -63
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/cr_planner.d.ts +1 -7
- package/dist/modules/cr_planner.d.ts.map +1 -1
- package/dist/modules/cr_planner.js +3 -77
- package/dist/modules/cr_planner.js.map +1 -1
- package/dist/modules/credential_policy.d.ts +0 -4
- package/dist/modules/credential_policy.d.ts.map +1 -1
- package/dist/modules/credential_policy.js +17 -2
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/credit_runtime.d.ts +0 -7
- package/dist/modules/credit_runtime.d.ts.map +1 -1
- package/dist/modules/credit_runtime.js +21 -60
- package/dist/modules/credit_runtime.js.map +1 -1
- package/dist/modules/crypto/index.d.ts +0 -2
- package/dist/modules/crypto/index.d.ts.map +1 -1
- package/dist/modules/crypto/index.js +0 -2
- package/dist/modules/crypto/index.js.map +1 -1
- package/dist/modules/crypto/sync.js.map +1 -1
- package/dist/modules/daemon_node_health.js +1 -1
- package/dist/modules/daemon_node_health.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +8 -134
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +36 -197
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_credential_client.js +1 -1
- package/dist/modules/dexbot_credential_client.js.map +1 -1
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_fill_runtime.js +3 -6
- package/dist/modules/dexbot_fill_runtime.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts +6 -34
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +27 -19
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/dexbot_startup_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_startup_runtime.js +31 -15
- package/dist/modules/dexbot_startup_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts +2 -2
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +9 -6
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/fund_registry.d.ts.map +1 -1
- package/dist/modules/fund_registry.js +19 -4
- package/dist/modules/fund_registry.js.map +1 -1
- package/dist/modules/general_settings.d.ts +1 -2
- package/dist/modules/general_settings.d.ts.map +1 -1
- package/dist/modules/general_settings.js +1 -2
- package/dist/modules/general_settings.js.map +1 -1
- package/dist/modules/graceful_shutdown.d.ts.map +1 -1
- package/dist/modules/graceful_shutdown.js +10 -1
- package/dist/modules/graceful_shutdown.js.map +1 -1
- package/dist/modules/grid_price_source.d.ts +19 -0
- package/dist/modules/grid_price_source.d.ts.map +1 -0
- package/dist/modules/grid_price_source.js +23 -0
- package/dist/modules/grid_price_source.js.map +1 -0
- package/dist/modules/key_store.d.ts +0 -5
- package/dist/modules/key_store.d.ts.map +1 -1
- package/dist/modules/key_store.js +1 -14
- package/dist/modules/key_store.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +9 -19
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/child_env.d.ts +1 -2
- package/dist/modules/launcher/child_env.d.ts.map +1 -1
- package/dist/modules/launcher/child_env.js +1 -1
- package/dist/modules/launcher/child_env.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +2 -14
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +3 -14
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/market_adapter_watchdog.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_watchdog.js +3 -2
- package/dist/modules/launcher/market_adapter_watchdog.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts +0 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +3 -18
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/runtime_entry.d.ts.map +1 -1
- package/dist/modules/launcher/runtime_entry.js +4 -5
- package/dist/modules/launcher/runtime_entry.js.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -1
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/launcher/supervisor_control.js +1 -1
- package/dist/modules/launcher/supervisor_control.js.map +1 -1
- package/dist/modules/market_adapter_whitelist.d.ts +2 -2
- package/dist/modules/market_adapter_whitelist.d.ts.map +1 -1
- package/dist/modules/market_adapter_whitelist.js +12 -6
- package/dist/modules/market_adapter_whitelist.js.map +1 -1
- package/dist/modules/node_failure_ledger.d.ts +23 -0
- package/dist/modules/node_failure_ledger.d.ts.map +1 -1
- package/dist/modules/node_failure_ledger.js +0 -23
- package/dist/modules/node_failure_ledger.js.map +1 -1
- package/dist/modules/node_manager.d.ts.map +1 -1
- package/dist/modules/node_manager.js +3 -3
- package/dist/modules/node_manager.js.map +1 -1
- package/dist/modules/order/accounting.js +1 -1
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/async_lock.d.ts +6 -0
- package/dist/modules/order/async_lock.d.ts.map +1 -1
- package/dist/modules/order/async_lock.js +11 -0
- package/dist/modules/order/async_lock.js.map +1 -1
- package/dist/modules/order/export.d.ts +1 -1
- package/dist/modules/order/export.js +10 -10
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/format.d.ts +1 -0
- package/dist/modules/order/format.d.ts.map +1 -1
- package/dist/modules/order/format.js +0 -6
- package/dist/modules/order/format.js.map +1 -1
- package/dist/modules/order/grid.d.ts +2 -12
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +40 -27
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile.d.ts +1 -1
- package/dist/modules/order/grid_reconcile.js +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +1 -1
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/logger.d.ts +3 -0
- package/dist/modules/order/logger.d.ts.map +1 -1
- package/dist/modules/order/logger.js +22 -13
- package/dist/modules/order/logger.js.map +1 -1
- package/dist/modules/order/logger_state.d.ts +4 -9
- package/dist/modules/order/logger_state.d.ts.map +1 -1
- package/dist/modules/order/logger_state.js +5 -14
- package/dist/modules/order/logger_state.js.map +1 -1
- package/dist/modules/order/manager.d.ts +1 -4
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +34 -33
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/processed_fill_store.d.ts.map +1 -1
- package/dist/modules/order/processed_fill_store.js +9 -3
- package/dist/modules/order/processed_fill_store.js.map +1 -1
- package/dist/modules/order/strategy.d.ts +6 -4
- package/dist/modules/order/strategy.d.ts.map +1 -1
- package/dist/modules/order/strategy.js +6 -4
- package/dist/modules/order/strategy.js.map +1 -1
- package/dist/modules/order/sync_engine.js +7 -7
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +29 -3
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +54 -10
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +14 -2
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/system.d.ts +3 -8
- package/dist/modules/order/utils/system.d.ts.map +1 -1
- package/dist/modules/order/utils/system.js +14 -4
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/order/utils/validate.js +1 -1
- package/dist/modules/order/utils/validate.js.map +1 -1
- package/dist/modules/path_api.js +1 -1
- package/dist/modules/path_api.js.map +1 -1
- package/dist/modules/paths.d.ts +1 -7
- package/dist/modules/paths.d.ts.map +1 -1
- package/dist/modules/paths.js +1 -1
- package/dist/modules/paths.js.map +1 -1
- package/dist/modules/process_discovery.d.ts +3 -0
- package/dist/modules/process_discovery.d.ts.map +1 -1
- package/dist/modules/process_discovery.js +15 -1
- package/dist/modules/process_discovery.js.map +1 -1
- package/dist/modules/runtime_settings.js +1 -1
- package/dist/modules/runtime_settings.js.map +1 -1
- package/dist/modules/settings_merge.d.ts +5 -1
- package/dist/modules/settings_merge.d.ts.map +1 -1
- package/dist/modules/settings_merge.js +14 -3
- package/dist/modules/settings_merge.js.map +1 -1
- package/dist/modules/socket_json_client.d.ts.map +1 -1
- package/dist/modules/socket_json_client.js +12 -2
- package/dist/modules/socket_json_client.js.map +1 -1
- package/dist/modules/storage/browser_adapter.d.ts.map +1 -1
- package/dist/modules/storage/browser_adapter.js +5 -3
- package/dist/modules/storage/browser_adapter.js.map +1 -1
- package/dist/modules/storage/index.d.ts +1 -1
- package/dist/modules/storage/index.js +1 -1
- package/dist/modules/types.d.ts +1 -1
- package/dist/modules/types.d.ts.map +1 -1
- package/dist/modules/validate_profiles.d.ts.map +1 -1
- package/dist/modules/validate_profiles.js +6 -8
- package/dist/modules/validate_profiles.js.map +1 -1
- package/dist/pm2.d.ts.map +1 -1
- package/dist/pm2.js +2 -3
- package/dist/pm2.js.map +1 -1
- package/dist/scripts/analyze-git.d.ts +1 -1
- package/dist/scripts/analyze-git.js +1 -1
- package/dist/scripts/analyze-orders.d.ts.map +1 -1
- package/dist/scripts/analyze-orders.js +61 -18
- package/dist/scripts/analyze-orders.js.map +1 -1
- package/dist/scripts/diagnose-pool-history.js +1 -1
- package/dist/scripts/divergence-calc.d.ts +1 -1
- package/dist/scripts/divergence-calc.js +3 -3
- package/dist/scripts/native_release_gates.js +4 -2
- package/dist/scripts/native_release_gates.js.map +1 -1
- package/dist/scripts/print_grid.d.ts +1 -1
- package/dist/scripts/print_grid.js +1 -1
- package/dist/scripts/run-tests.js +38 -19
- package/dist/scripts/run-tests.js.map +1 -1
- package/dist/scripts/runner.d.ts +3 -5
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +3 -5
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/sync-version.d.ts +2 -2
- package/dist/scripts/sync-version.js +7 -4
- package/dist/scripts/sync-version.js.map +1 -1
- package/dist/scripts/update.d.ts +1 -1
- package/dist/scripts/update.js +1 -1
- package/dist/scripts/validate_bots.d.ts +1 -1
- package/dist/scripts/validate_bots.js +1 -1
- package/dist/scripts/verify-browser-bundle.d.ts +1 -1
- package/dist/scripts/verify-browser-bundle.js +1 -1
- package/dist/unlock.js +4 -4
- package/dist/unlock.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +15 -10
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +9 -9
- package/docs/DEXBOT_COMPARISON.md +19 -19
- package/docs/EVOLUTION.md +18 -44
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
- package/docs/GRID_RECALCULATION.md +1 -1
- package/docs/README.md +3 -3
- package/docs/architecture.md +5 -5
- package/docs/developer_guide.md +6 -6
- package/market_adapter/README.md +13 -8
- package/package.json +22 -14
- package/scripts/README.md +33 -7
- package/scripts/clean-dist.js +10 -2
- package/tests/README.md +4 -3
|
@@ -1,15 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { calculateAMA, getAmaWarmupBars } from '../../market_adapter/core/strategies/ama.js';
|
|
6
|
+
import { computeAverageAmaSlopePct } from '../../market_adapter/core/strategies/ama_slope_model.js';
|
|
4
7
|
import { range } from '../math_utils.js';
|
|
5
8
|
import { parseListOrRange, loadLpData, fmt } from './shared_utils.js';
|
|
6
9
|
import { getStorage } from '../../modules/storage/index.js';
|
|
7
10
|
import { PATHS } from '../../modules/paths.js';
|
|
11
|
+
import { GRID_LIMITS, MARKET_ADAPTER } from '../../modules/constants.js';
|
|
8
12
|
const { ensureDir, readJSON, writeJSON } = getStorage();
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
// Default mirrors production sizing: createOrderGrid sizes EVERY rail slot in
|
|
14
|
+
// bounds (modules/order/grid.ts), it does not cap per side. Infinity = all
|
|
15
|
+
// slots; --active-orders N restores a bounded run.
|
|
16
|
+
const DEFAULT_ACTIVE_ORDERS = Infinity;
|
|
11
17
|
const DEFAULT_FEE_ROUNDTRIP_PCT = 0.20;
|
|
12
|
-
|
|
18
|
+
// BTS operation fees — same model as backtest_ama_sweep. Every placement
|
|
19
|
+
// (initial grid, reset rebuild, per-cycle slot refill) pays a maker create
|
|
20
|
+
// fee, every cancel pays a cancel fee. Fees are converted into percentage
|
|
21
|
+
// points against --bts-fee-capital so they deduct from net capture in the
|
|
22
|
+
// same units as the rest of the accounting.
|
|
23
|
+
const DEFAULT_BTS_CREATE_FEE = 0.48260;
|
|
24
|
+
const DEFAULT_BTS_CANCEL_FEE = 0.00482;
|
|
25
|
+
const DEFAULT_BTS_MAKER_CREATE_FACTOR = 0.10;
|
|
26
|
+
const DEFAULT_TX_FEE_PRICE = 1.0;
|
|
27
|
+
const DEFAULT_BTS_FEE_CAPITAL = 10000;
|
|
28
|
+
// ── Production grid-reset triggers (MARKET_ADAPTER, modules/constants.ts) ────
|
|
29
|
+
//
|
|
30
|
+
// Trigger A — AMA delta: the live adapter records the AMA center and writes a
|
|
31
|
+
// recalculate.<botKey>.trigger when AMA moves ±AMA_DELTA_THRESHOLD_PERCENT
|
|
32
|
+
// from that recorded center; the center re-records only when a trigger fires
|
|
33
|
+
// (ratchet semantics — see analyze_ama_price_changes.trackRepositions).
|
|
34
|
+
// --reposition-pct overrides the default.
|
|
35
|
+
const DEFAULT_REPOSITION_PCT = MARKET_ADAPTER.AMA_DELTA_THRESHOLD_PERCENT;
|
|
36
|
+
//
|
|
37
|
+
// Trigger B — AMA slope delta, plus the grid price offset, are BOTH gated in
|
|
38
|
+
// production behind the per-bot asymmetricBounds whitelist
|
|
39
|
+
// (market_adapter_service.ts: isGridRangeScalingWhitelisted consumes both
|
|
40
|
+
// shouldTrigger at the slope-reset write and computeGridPriceOffsetPlan via
|
|
41
|
+
// README "asymmetricBounds whitelist also enables gridPriceOffsetPct").
|
|
42
|
+
// The sim therefore exposes one switch, default OFF (typical non-whitelisted
|
|
43
|
+
// bot): --asymmetric-bounds enables slope-delta resets AND slope-ratio offset.
|
|
44
|
+
// Trigger B fires when |slopePct_now − baseline| reaches
|
|
45
|
+
// (AMA_SLOPE_DELTA_THRESHOLD_PERCENT / 100) × DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT,
|
|
46
|
+
// where slopePct is the average per-bar AMA change over
|
|
47
|
+
// DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS (computeAverageAmaSlopePct) and the
|
|
48
|
+
// baseline mirrors botState.gridRangeScalingAmaSlope (re-seeded every reset).
|
|
49
|
+
const SLOPE_TRIGGER_FACTOR = MARKET_ADAPTER.AMA_SLOPE_DELTA_THRESHOLD_PERCENT;
|
|
50
|
+
const SLOPE_MAX_PCT = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT;
|
|
51
|
+
const SLOPE_LOOKBACK_BARS = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS;
|
|
52
|
+
const SLOPE_NEUTRAL_ZONE_PCT = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_NEUTRAL_ZONE_PCT;
|
|
53
|
+
// Spread-gap floor knobs (GRID_LIMITS): the effective target spread is
|
|
54
|
+
// clamped up to incrementPercent × MIN_SPREAD_FACTOR and the gap is never
|
|
55
|
+
// narrower than MIN_SPREAD_ORDERS slots — mirrored from calculateGapSlots
|
|
56
|
+
// (modules/order/utils/math.ts).
|
|
57
|
+
const DEFAULT_MIN_SPREAD_FACTOR = GRID_LIMITS.MIN_SPREAD_FACTOR;
|
|
13
58
|
// Inventory-risk penalty weights (in score points)
|
|
14
59
|
const RISK_W_DURATION = 1.0; // avg open bars
|
|
15
60
|
const RISK_W_PEAK_OPEN = 2.0; // peak simultaneous open orders
|
|
@@ -29,6 +74,13 @@ function parseArgs() {
|
|
|
29
74
|
activeOrders: DEFAULT_ACTIVE_ORDERS,
|
|
30
75
|
feeRoundtripPct: DEFAULT_FEE_ROUNDTRIP_PCT,
|
|
31
76
|
minSpreadFactor: DEFAULT_MIN_SPREAD_FACTOR,
|
|
77
|
+
repositionPct: DEFAULT_REPOSITION_PCT,
|
|
78
|
+
asymmetricBounds: false,
|
|
79
|
+
btsCreateFee: DEFAULT_BTS_CREATE_FEE,
|
|
80
|
+
btsCancelFee: DEFAULT_BTS_CANCEL_FEE,
|
|
81
|
+
makerCreateFactor: DEFAULT_BTS_MAKER_CREATE_FACTOR,
|
|
82
|
+
txFeePrice: DEFAULT_TX_FEE_PRICE,
|
|
83
|
+
btsFeeCapital: DEFAULT_BTS_FEE_CAPITAL,
|
|
32
84
|
riskWDuration: RISK_W_DURATION,
|
|
33
85
|
riskWPeakOpen: RISK_W_PEAK_OPEN,
|
|
34
86
|
riskWImbalance: RISK_W_IMBALANCE,
|
|
@@ -36,6 +88,12 @@ function parseArgs() {
|
|
|
36
88
|
};
|
|
37
89
|
for (let i = 0; i < args.length; i++) {
|
|
38
90
|
const arg = args[i];
|
|
91
|
+
// Valueless boolean flag — must be handled before the value lookup
|
|
92
|
+
// below (and before the trailing-arg `if (!val) continue` guard).
|
|
93
|
+
if (arg === '--asymmetric-bounds') {
|
|
94
|
+
out.asymmetricBounds = true;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
39
97
|
const val = args[i + 1];
|
|
40
98
|
if (!val)
|
|
41
99
|
continue;
|
|
@@ -72,6 +130,30 @@ function parseArgs() {
|
|
|
72
130
|
out.minSpreadFactor = Number(val);
|
|
73
131
|
i++;
|
|
74
132
|
break;
|
|
133
|
+
case '--reposition-pct':
|
|
134
|
+
out.repositionPct = Number(val);
|
|
135
|
+
i++;
|
|
136
|
+
break;
|
|
137
|
+
case '--bts-create-fee':
|
|
138
|
+
out.btsCreateFee = Number(val);
|
|
139
|
+
i++;
|
|
140
|
+
break;
|
|
141
|
+
case '--bts-cancel-fee':
|
|
142
|
+
out.btsCancelFee = Number(val);
|
|
143
|
+
i++;
|
|
144
|
+
break;
|
|
145
|
+
case '--maker-create-factor':
|
|
146
|
+
out.makerCreateFactor = Number(val);
|
|
147
|
+
i++;
|
|
148
|
+
break;
|
|
149
|
+
case '--tx-fee-price':
|
|
150
|
+
out.txFeePrice = Number(val);
|
|
151
|
+
i++;
|
|
152
|
+
break;
|
|
153
|
+
case '--bts-fee-capital':
|
|
154
|
+
out.btsFeeCapital = Number(val);
|
|
155
|
+
i++;
|
|
156
|
+
break;
|
|
75
157
|
case '--risk-duration':
|
|
76
158
|
out.riskWDuration = Number(val);
|
|
77
159
|
i++;
|
|
@@ -156,113 +238,432 @@ function loadAmaStrategies(resultsPath) {
|
|
|
156
238
|
}
|
|
157
239
|
return out;
|
|
158
240
|
}
|
|
159
|
-
|
|
160
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Spread-gap width in slots — direct port of calculateGapSlots
|
|
243
|
+
* (modules/order/utils/math.ts:1228). The effective target spread is clamped
|
|
244
|
+
* up to incrementPercent × MIN_SPREAD_FACTOR and the gap never drops below
|
|
245
|
+
* MIN_SPREAD_ORDERS slots. `incrementPercent`/`targetSpreadPercent` in PERCENT
|
|
246
|
+
* units, matching the production signature.
|
|
247
|
+
*/
|
|
248
|
+
function computeGapSlots(incrementPercent, targetSpreadPercent) {
|
|
249
|
+
const step = 1 + (incrementPercent / 100);
|
|
250
|
+
const minSpreadPercent = incrementPercent * GRID_LIMITS.MIN_SPREAD_FACTOR;
|
|
251
|
+
const effectiveTargetSpread = Math.max(targetSpreadPercent || 0, minSpreadPercent);
|
|
252
|
+
const requiredSteps = Math.ceil(Math.log(1 + (effectiveTargetSpread / 100)) / Math.log(step));
|
|
253
|
+
return Math.max(GRID_LIMITS.MIN_SPREAD_ORDERS, requiredSteps - 1);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Slope-ratio grid price offset — port of computeGridPriceOffsetPlan
|
|
257
|
+
* (market_adapter/core/market_adapter_service.ts:92-119) combined with the
|
|
258
|
+
* trend/slopeRatio semantics of computeAmaSlopeWeights
|
|
259
|
+
* (market_adapter/core/strategies/ama_slope_model.ts):
|
|
260
|
+
*
|
|
261
|
+
* maxGridPriceOffsetPct = targetSpreadPercent / 2
|
|
262
|
+
* slopeRatio = min(|slopePct| / DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT, 1)
|
|
263
|
+
* direction = sign(slopePct) (0 inside the neutral zone)
|
|
264
|
+
* offsetPct = direction × slopeRatio × maxGridPriceOffsetPct
|
|
265
|
+
*
|
|
266
|
+
* Production applies this to startPrice (grid.ts:982: startPrice × (1 +
|
|
267
|
+
* offset/100)) only for asymmetricBounds-whitelisted bots; the sim applies it
|
|
268
|
+
* to the placement center on every grid build when asymmetricBounds is on.
|
|
269
|
+
*/
|
|
270
|
+
function computeGridPriceOffsetPct(slopePct, targetSpreadPercent) {
|
|
271
|
+
if (!Number.isFinite(slopePct))
|
|
272
|
+
return 0;
|
|
273
|
+
if (Math.abs(slopePct) <= SLOPE_NEUTRAL_ZONE_PCT)
|
|
274
|
+
return 0;
|
|
275
|
+
const slopeRatio = Math.min(Math.abs(slopePct) / SLOPE_MAX_PCT, 1);
|
|
276
|
+
const maxGridPriceOffsetPct = targetSpreadPercent / 2;
|
|
277
|
+
const direction = slopePct > 0 ? 1 : -1;
|
|
278
|
+
const offsetPct = direction * slopeRatio * maxGridPriceOffsetPct;
|
|
279
|
+
return Math.round(offsetPct * 1e6) / 1e6;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Build a persistent grid with FIXED chain prices from a master rail —
|
|
283
|
+
* port of createOrderGrid (modules/order/grid.ts:374-505):
|
|
284
|
+
*
|
|
285
|
+
* - Master rail: geometric progression starting at √(1±inc) × center and
|
|
286
|
+
* expanding by (1±inc) steps outward, bounded by
|
|
287
|
+
* [center/maxMinRatio, center×maxMinRatio] (grid.ts:428-444).
|
|
288
|
+
* - Spread gap: gapSlots empty slots centered on the center price
|
|
289
|
+
* (calculateIdealBoundary: boundaryIdx = splitIdx − floor(gap/2) − 1;
|
|
290
|
+
* sells start at boundaryIdx + gapSlots + 1).
|
|
291
|
+
* - By default every rail slot in bounds is sized (activeOrders = Infinity,
|
|
292
|
+
* matching production); an explicit cap keeps only the slots nearest the
|
|
293
|
+
* gap on each side.
|
|
294
|
+
*
|
|
295
|
+
* Order prices are placement-time constants — exactly like on-chain orders,
|
|
296
|
+
* they do NOT follow AMA after placement.
|
|
297
|
+
*/
|
|
298
|
+
function buildProductionGrid(center, spreadPct, incrementPctFrac, maxMinRatio, activeOrders) {
|
|
299
|
+
const stepUp = 1 + incrementPctFrac;
|
|
300
|
+
const stepDown = 1 - incrementPctFrac;
|
|
301
|
+
const minBound = center / maxMinRatio;
|
|
302
|
+
const maxBound = center * maxMinRatio;
|
|
303
|
+
const rail = [];
|
|
304
|
+
let p = center * Math.sqrt(stepUp);
|
|
305
|
+
while (p <= maxBound) {
|
|
306
|
+
rail.push(p);
|
|
307
|
+
p *= stepUp;
|
|
308
|
+
}
|
|
309
|
+
p = center * Math.sqrt(stepDown);
|
|
310
|
+
while (p >= minBound) {
|
|
311
|
+
rail.push(p);
|
|
312
|
+
p *= stepDown;
|
|
313
|
+
}
|
|
314
|
+
rail.sort((a, b) => a - b);
|
|
315
|
+
if (rail.length === 0)
|
|
316
|
+
return { buys: [], sells: [], rail: [], buySliceStart: 0, sellStartIdx: 0 };
|
|
317
|
+
const gapSlots = computeGapSlots(incrementPctFrac * 100, spreadPct);
|
|
318
|
+
let splitIdx = rail.findIndex((v) => v >= center);
|
|
319
|
+
if (splitIdx === -1)
|
|
320
|
+
splitIdx = rail.length;
|
|
321
|
+
const buySpread = Math.floor(gapSlots / 2);
|
|
322
|
+
const boundaryIdx = Math.max(0, Math.min(rail.length - 1, splitIdx - buySpread - 1));
|
|
323
|
+
const sellStartIdx = boundaryIdx + gapSlots + 1;
|
|
324
|
+
// Buys closest to the gap = highest priced below boundary; sells closest =
|
|
325
|
+
// lowest priced above sellStartIdx. Rail + slice offsets are returned so
|
|
326
|
+
// callers can map each placed slot onto its MASTER-RAIL index (rotation
|
|
327
|
+
// walks adjacent rail nodes, exactly like the live anchor-&-refill hop).
|
|
328
|
+
const buySliceStart = Math.max(0, boundaryIdx - activeOrders + 1);
|
|
329
|
+
const sellsArr = rail.slice(sellStartIdx, sellStartIdx + activeOrders);
|
|
330
|
+
return {
|
|
331
|
+
buys: rail.slice(buySliceStart, boundaryIdx + 1),
|
|
332
|
+
sells: sellsArr,
|
|
333
|
+
rail,
|
|
334
|
+
buySliceStart,
|
|
335
|
+
sellStartIdx,
|
|
336
|
+
};
|
|
161
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Slot-rotation simulation with FIXED chain prices, mirroring production
|
|
340
|
+
* anchor-&-refill (strategy.ts) on top of the createOrderGrid geometry:
|
|
341
|
+
*
|
|
342
|
+
* - Initial grid built once at the post-warmup AMA (createOrderGrid geometry
|
|
343
|
+
* via buildProductionGrid); order prices never follow AMA afterwards. When
|
|
344
|
+
* asymmetricBounds is enabled the placement center is shifted by the
|
|
345
|
+
* slope-ratio offset (#3) exactly like the live startPrice offset.
|
|
346
|
+
* - Rotation economics (#1/#2/#15): a FILLED BUY at rail node k instantly
|
|
347
|
+
* re-offers that base at the ADJACENT MASTER-RAIL NODE k+1; when that
|
|
348
|
+
* refill sells, the rotation books exactly one rail hop minus the
|
|
349
|
+
* round-trip fee, and the freed quote re-bids the node k-1 below. Slots
|
|
350
|
+
* cycle on small oscillations between resets — the earnings model of a
|
|
351
|
+
* refilled live slot, not a cross-gap differential.
|
|
352
|
+
* - Inventory-funded selling: an INITIAL (unlinked) sell can only execute
|
|
353
|
+
* against held inventory — it books its proceeds against the weighted
|
|
354
|
+
* average entry of the position (the live bot funds sells from real
|
|
355
|
+
* balances; unfundable sells stay open and retry, never shorting). Base
|
|
356
|
+
* bought in the SAME bar does not fund unlinked sales until the next bar
|
|
357
|
+
* (live balance updates propagate on the next maintenance tick).
|
|
358
|
+
* - Same-bar guard: newly armed/refill orders carry a one-bar cooldown, so
|
|
359
|
+
* a slot that just cycled cannot fill again inside the completion bar.
|
|
360
|
+
* - Grid reset fires on EITHER production trigger:
|
|
361
|
+
* (A) |AMA − recordedCenter| / recordedCenter ≥ repositionThresholdPct
|
|
362
|
+
* (ratchet: recordedCenter updates only when the trigger fires),
|
|
363
|
+
* (B) slope-delta reset, ONLY when asymmetricBounds (whitelist gate):
|
|
364
|
+
* |slopePct_now − slopeBaseline| ≥ slopeDeltaThresholdPct
|
|
365
|
+
* (= AMA_SLOPE_DELTA_THRESHOLD_PERCENT/100 ×
|
|
366
|
+
* DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT), where slopePct is the
|
|
367
|
+
* DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS average-slope series and
|
|
368
|
+
* slopeBaseline mirrors botState.gridRangeScalingAmaSlope — seeded
|
|
369
|
+
* at start and re-seeded on every reset.
|
|
370
|
+
* On reset ALL unfilled orders are canceled (counted); bought-and-held
|
|
371
|
+
* base REMAINS as inventory (live resync never market-sells) and merges
|
|
372
|
+
* into the weighted-average-entry pool; a fresh grid is placed at the
|
|
373
|
+
* new center.
|
|
374
|
+
* - Scoring uses REALIZED rotations and op fees ONLY. The end-of-run
|
|
375
|
+
* inventory position (units × mark-vs-avg-entry) is reported as an
|
|
376
|
+
* informational field — it is real carried risk, but including unrealized
|
|
377
|
+
* bag marks in the ranking objective let trend-following combos dump
|
|
378
|
+
* phantom paper profit into the score.
|
|
379
|
+
* - BTS operation fees (#9): every order placement (initial grid + every
|
|
380
|
+
* armed refill/rebid) pays makerCreateFee × btsCreateFee, every reset
|
|
381
|
+
* cancel pays btsCancelFee; totals are converted to percentage points
|
|
382
|
+
* against the --bts-fee-capital reference and deducted from net capture.
|
|
383
|
+
*
|
|
384
|
+
* Differences from production (by design, documented):
|
|
385
|
+
* #6 bar-granularity triggers and reset-vs-fill ordering (OHLC sim);
|
|
386
|
+
* #7 all-or-nothing fills on raw hi/lo touch (no partial fills/dust/queue);
|
|
387
|
+
* #8 unit sizes / percentage-point accounting instead of capital-weighted
|
|
388
|
+
* dynamic sizing;
|
|
389
|
+
* #10 pool-price fills (no book depth/slippage);
|
|
390
|
+
* #11 no consolidation/dust-cancel/COW/collision mechanics.
|
|
391
|
+
*/
|
|
162
392
|
function simulateForParams(candles, amaValues, params) {
|
|
163
|
-
const { spreadPct, incrementPct, maxMinRatio, activeOrders, feeRoundtripPct, risk } = params;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const
|
|
393
|
+
const { spreadPct, incrementPct, maxMinRatio, activeOrders, feeRoundtripPct, repositionThresholdPct, asymmetricBounds, risk, btsCreateFee, btsCancelFee, makerCreateFactor, txFeePrice, btsFeeCapital } = params;
|
|
394
|
+
// Warmup follows production AMA seeding/convergence (getAmaWarmupBars)
|
|
395
|
+
// instead of an arbitrary fraction of the dataset, so simulations never
|
|
396
|
+
// start on SMA-warmup values when the fitted ER period is large.
|
|
397
|
+
const skip = Math.min(params.warmupBars, Math.max(0, candles.length - 2));
|
|
398
|
+
const singleLegFeePct = feeRoundtripPct / 2;
|
|
399
|
+
const slopeDeltaThresholdPct = (SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT;
|
|
400
|
+
const makerCreateFeeBts = btsCreateFee * makerCreateFactor;
|
|
401
|
+
const stepUpFrac = 1 + incrementPct; // one-rail-step rotation distance
|
|
402
|
+
// First tradable bar: need a finite positive AMA to anchor the chain.
|
|
403
|
+
let startIdx = Math.min(skip, candles.length - 1);
|
|
404
|
+
let gridCenter = Number.NaN;
|
|
405
|
+
for (let j = startIdx; j < candles.length; j++) {
|
|
406
|
+
const v = amaValues[j];
|
|
407
|
+
if (Number.isFinite(v) && v > 0) {
|
|
408
|
+
gridCenter = v;
|
|
409
|
+
startIdx = j;
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Production AMA slope series (%/bar averaged over the lookback window).
|
|
414
|
+
// Evaluated over full history like the live adapter (only bar-index guards).
|
|
415
|
+
const slopeAt = new Array(candles.length).fill(null);
|
|
416
|
+
for (let j = SLOPE_LOOKBACK_BARS; j < candles.length; j++) {
|
|
417
|
+
const s = computeAverageAmaSlopePct(amaValues[j], amaValues[j - SLOPE_LOOKBACK_BARS], SLOPE_LOOKBACK_BARS);
|
|
418
|
+
if (s != null && Number.isFinite(s))
|
|
419
|
+
slopeAt[j] = s;
|
|
420
|
+
}
|
|
421
|
+
// Open orders keyed by running id: { side, price, linkedBuyPrice,
|
|
422
|
+
// linkedEntryBar, cooldownUntil }. linkedBuyPrice != null marks an armed
|
|
423
|
+
// refill sell created by a specific filled buy (one-increment rotation).
|
|
424
|
+
const orders = new Map();
|
|
425
|
+
let nextOrderId = 0;
|
|
426
|
+
// Bought-and-held base across the whole run (weighted-average entry
|
|
427
|
+
// pool). Never negative — sells without inventory stay pending.
|
|
428
|
+
const inv = { units: 0, cost: 0 };
|
|
429
|
+
let btsFeesBts = 0;
|
|
430
|
+
let offsetAppliedCount = 0;
|
|
431
|
+
// Master rail of the CURRENT epoch — rotation hops read adjacent nodes.
|
|
432
|
+
let activeRail = [];
|
|
433
|
+
const placeInitialGrid = (center, slopePct) => {
|
|
434
|
+
const offsetPct = (asymmetricBounds && slopePct != null)
|
|
435
|
+
? computeGridPriceOffsetPct(slopePct, spreadPct)
|
|
436
|
+
: 0;
|
|
437
|
+
if (offsetPct !== 0)
|
|
438
|
+
offsetAppliedCount++;
|
|
439
|
+
const effCenter = center * (1 + offsetPct / 100);
|
|
440
|
+
const built = buildProductionGrid(effCenter, spreadPct, incrementPct, maxMinRatio, activeOrders);
|
|
441
|
+
activeRail = built.rail;
|
|
442
|
+
orders.clear();
|
|
443
|
+
// Rail indices matter: rotation re-offers/re-bids walk ADJACENT
|
|
444
|
+
// master-rail nodes (buy at node k arms a sell at node k+1; the freed
|
|
445
|
+
// quote re-bids node k-1), preserving the exact production hop sizes.
|
|
446
|
+
built.buys.forEach((price, i) => orders.set(nextOrderId++, {
|
|
447
|
+
side: 'buy', price, railIdx: built.buySliceStart + i,
|
|
448
|
+
linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1,
|
|
449
|
+
}));
|
|
450
|
+
built.sells.forEach((price, i) => orders.set(nextOrderId++, {
|
|
451
|
+
side: 'sell', price, railIdx: built.sellStartIdx + i,
|
|
452
|
+
linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1,
|
|
453
|
+
}));
|
|
454
|
+
btsFeesBts += (built.buys.length + built.sells.length) * makerCreateFeeBts;
|
|
455
|
+
};
|
|
168
456
|
let touchedOrders = 0;
|
|
169
|
-
let
|
|
457
|
+
let cyclesTotal = 0;
|
|
458
|
+
let rotationCount = 0; // linked ping-pong rotations (buy → refill sell)
|
|
459
|
+
let inventorySaleCount = 0; // unlinked sells executed against held bags
|
|
170
460
|
let canceledOnReposition = 0;
|
|
461
|
+
let repositionCount = 0;
|
|
462
|
+
let driftTriggerCount = 0;
|
|
463
|
+
let slopeTriggerCount = 0;
|
|
171
464
|
let totalGrossCapturePct = 0;
|
|
172
465
|
let totalNetCapturePct = 0;
|
|
173
|
-
let activeLevelTouches = 0;
|
|
174
466
|
let peakOpenOrders = 0;
|
|
175
467
|
let imbalanceSum = 0;
|
|
176
468
|
let imbalanceSamples = 0;
|
|
177
469
|
let matchedOpenDurationBars = 0;
|
|
178
|
-
|
|
470
|
+
const invAvgEntry = () => (inv.units > 0 ? inv.cost / inv.units : 0);
|
|
471
|
+
if (Number.isFinite(gridCenter))
|
|
472
|
+
placeInitialGrid(gridCenter, slopeAt[startIdx]);
|
|
473
|
+
// Slope-delta baseline: mirrors botState.gridRangeScalingAmaSlope —
|
|
474
|
+
// seeded at bootstrap (first cycle) and re-seeded to the current slope on
|
|
475
|
+
// EVERY grid reset (advanceTriggeredBotState), so trigger B measures how
|
|
476
|
+
// far slope has moved SINCE THE LAST RESET, not bar-over-bar jitter.
|
|
477
|
+
let slopeBaseline = null;
|
|
478
|
+
for (let j = startIdx + 1; j < candles.length; j++) {
|
|
479
|
+
if (slopeAt[j] != null) {
|
|
480
|
+
slopeBaseline = slopeAt[j];
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
for (let i = startIdx + 1; i < candles.length; i++) {
|
|
179
485
|
const ama = amaValues[i];
|
|
180
|
-
const prevAma = amaValues[i - 1];
|
|
181
486
|
const hi = candles[i].high;
|
|
182
487
|
const lo = candles[i].low;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
488
|
+
// ── Grid-reset check: trigger A (AMA delta) always; trigger B
|
|
489
|
+
// (slope delta) only under the asymmetricBounds whitelist gate.
|
|
490
|
+
let shouldReset = false;
|
|
491
|
+
if (Number.isFinite(ama) && ama > 0) {
|
|
492
|
+
const driftPct = (Math.abs(ama - gridCenter) / gridCenter) * 100;
|
|
493
|
+
if (driftPct >= repositionThresholdPct) {
|
|
494
|
+
shouldReset = true;
|
|
495
|
+
driftTriggerCount++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (!shouldReset && asymmetricBounds && slopeBaseline != null && slopeAt[i] != null) {
|
|
499
|
+
const slopeDeltaPct = Math.abs(slopeAt[i] - slopeBaseline);
|
|
500
|
+
if (slopeDeltaPct >= slopeDeltaThresholdPct) {
|
|
501
|
+
shouldReset = true;
|
|
502
|
+
slopeTriggerCount++;
|
|
503
|
+
}
|
|
187
504
|
}
|
|
188
|
-
|
|
505
|
+
if (shouldReset && Number.isFinite(ama) && ama > 0) {
|
|
506
|
+
canceledOnReposition += orders.size;
|
|
507
|
+
btsFeesBts += orders.size * btsCancelFee;
|
|
508
|
+
orders.clear(); // inventory survives — resync never market-sells
|
|
509
|
+
repositionCount++;
|
|
510
|
+
gridCenter = ama; // ratchet the recorded center to the current AMA
|
|
511
|
+
// Re-seed the slope baseline with the current slope (falls back to
|
|
512
|
+
// the previous baseline when slope is not ready — same as
|
|
513
|
+
// advanceTriggeredBotState's `|| previous` chain).
|
|
514
|
+
if (slopeAt[i] != null)
|
|
515
|
+
slopeBaseline = slopeAt[i];
|
|
516
|
+
placeInitialGrid(gridCenter, slopeAt[i]);
|
|
517
|
+
}
|
|
518
|
+
const currentOpen = orders.size;
|
|
189
519
|
if (currentOpen > peakOpenOrders)
|
|
190
520
|
peakOpenOrders = currentOpen;
|
|
191
|
-
|
|
521
|
+
let buyCount = 0;
|
|
522
|
+
for (const [, o] of orders) {
|
|
523
|
+
if (o.side === 'buy')
|
|
524
|
+
buyCount++;
|
|
525
|
+
}
|
|
526
|
+
imbalanceSum += Math.abs(buyCount - (orders.size - buyCount));
|
|
192
527
|
imbalanceSamples++;
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
continue;
|
|
199
|
-
const buyPrice = ama * (1 - r);
|
|
200
|
-
const sellPrice = ama * (1 + r);
|
|
201
|
-
if (buyPrice < minBound || sellPrice > maxBound)
|
|
202
|
-
continue;
|
|
203
|
-
const grossPct = levelGrossSpreadPct(r);
|
|
204
|
-
if (grossPct < spreadPct)
|
|
528
|
+
// ── Fill detection against FIXED chain prices ───────────────────
|
|
529
|
+
const filledBuys = [];
|
|
530
|
+
const filledSells = [];
|
|
531
|
+
for (const [id, o] of orders) {
|
|
532
|
+
if (i < o.cooldownUntil)
|
|
205
533
|
continue;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
534
|
+
if (o.side === 'buy' && lo <= o.price)
|
|
535
|
+
filledBuys.push({ id, order: o });
|
|
536
|
+
else if (o.side === 'sell' && hi >= o.price)
|
|
537
|
+
filledSells.push({ id, order: o });
|
|
538
|
+
}
|
|
539
|
+
touchedOrders += filledBuys.length + filledSells.length;
|
|
540
|
+
// Base held BEFORE this bar's intakes — an unlinked sell may only
|
|
541
|
+
// dispose against pre-existing funds (live balance updates propagate
|
|
542
|
+
// on the next maintenance tick; same-bar funding is not assumed).
|
|
543
|
+
const invAtBarStart = inv.units;
|
|
544
|
+
// ── Buy intakes first: base enters inventory, refill armed at the
|
|
545
|
+
// ADJACENT MASTER-RAIL NODE above (anchor-&-refill hop; cooldown
|
|
546
|
+
// blocks same-bar recycles).
|
|
547
|
+
for (const f of filledBuys) {
|
|
548
|
+
orders.delete(f.id);
|
|
549
|
+
inv.units += 1;
|
|
550
|
+
inv.cost += f.order.price;
|
|
551
|
+
const upIdx = (f.order.railIdx ?? -1) + 1;
|
|
552
|
+
const refillPrice = activeRail[upIdx] ?? f.order.price * stepUpFrac;
|
|
553
|
+
orders.set(nextOrderId++, {
|
|
554
|
+
side: 'sell',
|
|
555
|
+
price: refillPrice,
|
|
556
|
+
railIdx: upIdx,
|
|
557
|
+
linkedBuyPrice: f.order.price,
|
|
558
|
+
linkedEntryBar: i,
|
|
559
|
+
cooldownUntil: i + 1,
|
|
560
|
+
});
|
|
561
|
+
btsFeesBts += makerCreateFeeBts;
|
|
562
|
+
}
|
|
563
|
+
// ── Sell disposals: linked refills book the one-rail-hop rotation;
|
|
564
|
+
// unlinked (initial-grid) sells need held inventory — no shorting.
|
|
565
|
+
// Linked refills resolve FIRST so same-bar cross-gap inventory
|
|
566
|
+
// sales against a fresh bag cannot happen.
|
|
567
|
+
filledSells.sort((a, b) => ((a.order.linkedBuyPrice != null ? 0 : 1) - (b.order.linkedBuyPrice != null ? 0 : 1)));
|
|
568
|
+
let disposables = invAtBarStart;
|
|
569
|
+
for (const f of filledSells) {
|
|
570
|
+
const o = f.order;
|
|
571
|
+
if (o.linkedBuyPrice != null) {
|
|
572
|
+
const grossPct = (o.price / o.linkedBuyPrice - 1) * 100;
|
|
573
|
+
totalGrossCapturePct += grossPct;
|
|
574
|
+
totalNetCapturePct += grossPct - feeRoundtripPct;
|
|
575
|
+
cyclesTotal++;
|
|
576
|
+
rotationCount++;
|
|
577
|
+
matchedOpenDurationBars += Math.abs(i - o.linkedEntryBar);
|
|
578
|
+
// Dispose the unit its own rotation bought.
|
|
579
|
+
const applied = Math.min(1, inv.units);
|
|
580
|
+
inv.cost -= applied * invAvgEntry();
|
|
581
|
+
inv.units -= applied;
|
|
582
|
+
// Its disposal also drains the pre-bar funding budget —
|
|
583
|
+
// otherwise later unlinked sales could overspend stock.
|
|
584
|
+
disposables -= applied;
|
|
585
|
+
// Freed quote re-bids the ADJACENT RAIL NODE below.
|
|
586
|
+
const downIdx = (o.railIdx ?? 0) - 1;
|
|
587
|
+
const rebidPrice = activeRail[downIdx] ?? o.price / stepUpFrac;
|
|
588
|
+
orders.delete(f.id);
|
|
589
|
+
orders.set(nextOrderId++, {
|
|
590
|
+
side: 'buy',
|
|
591
|
+
price: rebidPrice,
|
|
592
|
+
railIdx: downIdx,
|
|
593
|
+
linkedBuyPrice: null,
|
|
594
|
+
linkedEntryBar: -1,
|
|
595
|
+
cooldownUntil: i + 1,
|
|
596
|
+
});
|
|
597
|
+
btsFeesBts += makerCreateFeeBts;
|
|
223
598
|
}
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
599
|
+
else if (disposables >= 1) {
|
|
600
|
+
const avgEntry = invAvgEntry();
|
|
601
|
+
const grossPct = (o.price / avgEntry - 1) * 100;
|
|
602
|
+
totalGrossCapturePct += grossPct;
|
|
603
|
+
totalNetCapturePct += grossPct - feeRoundtripPct;
|
|
604
|
+
cyclesTotal++;
|
|
605
|
+
inventorySaleCount++;
|
|
606
|
+
inv.cost -= avgEntry; // remove that unit at pool-average cost
|
|
607
|
+
inv.units -= 1;
|
|
608
|
+
disposables -= 1;
|
|
609
|
+
orders.delete(f.id); // sold bag is gone; slot not re-armed
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
// Unfundable (no base to sell): stays open, retries next bar.
|
|
613
|
+
o.cooldownUntil = i + 1;
|
|
236
614
|
}
|
|
237
615
|
}
|
|
238
616
|
}
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
|
|
617
|
+
// ── End-of-run inventory mark (informational, NOT in score) ────────
|
|
618
|
+
// Bought-and-held base is real carried risk, but unrealized bag marks are
|
|
619
|
+
// excluded from ranking so trend-following combos can't dump phantom
|
|
620
|
+
// paper profit into the objective. Marked once at the final close with a
|
|
621
|
+
// single-leg exit fee per unit.
|
|
622
|
+
const lastClose = candles.length > 0 ? candles[candles.length - 1].close : NaN;
|
|
623
|
+
const inventoryUnits = inv.units;
|
|
624
|
+
const inventoryAvgEntry = invAvgEntry();
|
|
625
|
+
const inventoryNetPts = inventoryUnits > 0 && Number.isFinite(lastClose) && lastClose > 0
|
|
626
|
+
? (((lastClose / inventoryAvgEntry) - 1) * 100 - singleLegFeePct) * inventoryUnits
|
|
627
|
+
: 0;
|
|
628
|
+
// BTS operation fees → percentage points against the reference capital.
|
|
629
|
+
const btsFeePts = (btsFeesBts * txFeePrice) / Math.max(1, btsFeeCapital) * 100;
|
|
630
|
+
const totalNetCaptureAfterFeesPct = totalNetCapturePct - btsFeePts;
|
|
631
|
+
const fillEfficiency = touchedOrders > 0 ? (cyclesTotal / touchedOrders) * 100 : 0;
|
|
632
|
+
const avgNetPerPair = cyclesTotal > 0 ? totalNetCapturePct / cyclesTotal : 0;
|
|
633
|
+
const utilization = (touchedOrders / Math.max(1, candles.length - skip)) * 100;
|
|
634
|
+
const avgOpenDurationBars = rotationCount > 0 ? (matchedOpenDurationBars / rotationCount) : 0;
|
|
249
635
|
const avgImbalance = imbalanceSamples > 0 ? (imbalanceSum / imbalanceSamples) : 0;
|
|
250
636
|
const riskPenalty = (avgOpenDurationBars * risk.duration) +
|
|
251
637
|
(peakOpenOrders * risk.peakOpen) +
|
|
252
638
|
(avgImbalance * risk.imbalance) +
|
|
253
639
|
(canceledOnReposition * risk.cancel);
|
|
640
|
+
const baseScore = totalNetCaptureAfterFeesPct * (fillEfficiency / 100);
|
|
254
641
|
const score = baseScore - riskPenalty;
|
|
255
642
|
return {
|
|
256
643
|
spreadPct,
|
|
257
644
|
incrementPct,
|
|
258
645
|
maxMinRatio,
|
|
259
646
|
touchedOrders,
|
|
260
|
-
matchedPairs,
|
|
647
|
+
matchedPairs: cyclesTotal,
|
|
648
|
+
cyclesTotal,
|
|
649
|
+
rotationCount,
|
|
650
|
+
inventorySaleCount,
|
|
651
|
+
avgCyclesPerSlot: cyclesTotal / Math.max(1, peakOpenOrders),
|
|
261
652
|
fillEfficiency,
|
|
262
653
|
totalGrossCapturePct,
|
|
263
654
|
totalNetCapturePct,
|
|
655
|
+
btsFeePts,
|
|
656
|
+
btsFeesBts,
|
|
657
|
+
totalNetCaptureAfterFeesPct,
|
|
264
658
|
avgNetPerPair,
|
|
265
659
|
canceledOnReposition,
|
|
660
|
+
repositionCount,
|
|
661
|
+
driftTriggerCount,
|
|
662
|
+
slopeTriggerCount,
|
|
663
|
+
inventoryUnits,
|
|
664
|
+
inventoryAvgEntry,
|
|
665
|
+
inventoryNetPts,
|
|
666
|
+
offsetAppliedCount,
|
|
266
667
|
avgOpenDurationBars,
|
|
267
668
|
peakOpenOrders,
|
|
268
669
|
avgImbalance,
|
|
@@ -290,6 +691,9 @@ function run() {
|
|
|
290
691
|
const candles = loaded.candles;
|
|
291
692
|
const closes = candles.map((c) => c.close);
|
|
292
693
|
const strategies = loadAmaStrategies(cfg.resultsPath);
|
|
694
|
+
if (!Number.isFinite(cfg.repositionPct) || cfg.repositionPct <= 0) {
|
|
695
|
+
throw new Error(`Invalid reposition threshold: ${cfg.repositionPct}`);
|
|
696
|
+
}
|
|
293
697
|
const totalCombos = cfg.spreadValues.length * cfg.incrementValues.length * cfg.ratioValues.length;
|
|
294
698
|
console.log('================================================================================');
|
|
295
699
|
console.log(' BOT FITTING BACKTEST (1h LP candles)');
|
|
@@ -299,26 +703,43 @@ function run() {
|
|
|
299
703
|
console.log(` Spread grid: ${cfg.spreadValues[0]}..${cfg.spreadValues[cfg.spreadValues.length - 1]}% (${cfg.spreadValues.length})`);
|
|
300
704
|
console.log(` Increment: ${cfg.incrementValues[0]}..${cfg.incrementValues[cfg.incrementValues.length - 1]}% (${cfg.incrementValues.length})`);
|
|
301
705
|
console.log(` Max/Min ratio:${cfg.ratioValues[0]}..${cfg.ratioValues[cfg.ratioValues.length - 1]} (${cfg.ratioValues.length})`);
|
|
302
|
-
console.log(` Active orders:${cfg.activeOrders} per side`);
|
|
706
|
+
console.log(` Active orders:${Number.isFinite(cfg.activeOrders) ? cfg.activeOrders : 'all'} per side (Infinity = every rail slot, matching production)`);
|
|
303
707
|
console.log(` Fee RT: ${cfg.feeRoundtripPct}%`);
|
|
304
708
|
console.log(` Spread floor: spread >= ${cfg.minSpreadFactor} x increment`);
|
|
709
|
+
console.log(` Reset (A): AMA drift >= ${cfg.repositionPct}% from recorded center${cfg.repositionPct === DEFAULT_REPOSITION_PCT ? ' (AMA_DELTA_THRESHOLD_PERCENT)' : ''}`);
|
|
710
|
+
console.log(` Asym. bounds: ${cfg.asymmetricBounds ? 'ON — slope reset (B) + grid price offset enabled (whitelist semantics)' : 'OFF — typical non-whitelisted bot (production default)'}`);
|
|
711
|
+
console.log(` Reset (B): |slope - slope@lastReset| >= ${(SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT}% (${SLOPE_TRIGGER_FACTOR}% x ${SLOPE_MAX_PCT}, lookback ${SLOPE_LOOKBACK_BARS})${cfg.asymmetricBounds ? '' : ' [gated off]'}`);
|
|
712
|
+
console.log(` Tx fees: create=${fmt(cfg.btsCreateFee * cfg.makerCreateFactor, 5)} BTS, cancel=${fmt(cfg.btsCancelFee, 5)} BTS, 1 BTS=${fmt(cfg.txFeePrice, 2)} units, capital=${fmt(cfg.btsFeeCapital, 0)}`);
|
|
305
713
|
console.log(` Risk W: duration=${cfg.riskWDuration}, peakOpen=${cfg.riskWPeakOpen}, imbalance=${cfg.riskWImbalance}, cancel=${cfg.riskWCancel}`);
|
|
306
714
|
console.log(` Combos/AMA: ${totalCombos}\n`);
|
|
307
715
|
const byAma = [];
|
|
308
716
|
for (const s of strategies) {
|
|
309
717
|
const amaValues = calculateAMA(closes, { erPeriod: s.er, fastPeriod: s.fast, slowPeriod: s.slow });
|
|
718
|
+
// Production-aligned warmup: ER window + convergence (getAmaWarmupBars).
|
|
719
|
+
const warmupBars = getAmaWarmupBars(s.er, s.slow, 0, s.fast);
|
|
310
720
|
let best = null;
|
|
311
721
|
for (const spreadPct of cfg.spreadValues) {
|
|
312
722
|
for (const incrementPct of cfg.incrementValues) {
|
|
723
|
+
// Dedup guard only: computeGapSlots clamps the effective target
|
|
724
|
+
// spread up to increment × MIN_SPREAD_FACTOR, so combos below the
|
|
725
|
+
// floor would build an identical grid to the floored combo.
|
|
726
|
+
if (spreadPct + Number.EPSILON < (cfg.minSpreadFactor * incrementPct))
|
|
727
|
+
continue;
|
|
313
728
|
for (const maxMinRatio of cfg.ratioValues) {
|
|
314
|
-
if (spreadPct + Number.EPSILON < (cfg.minSpreadFactor * incrementPct))
|
|
315
|
-
continue;
|
|
316
729
|
const sim = simulateForParams(candles, amaValues, {
|
|
317
730
|
spreadPct,
|
|
318
731
|
incrementPct: incrementPct / 100,
|
|
319
732
|
maxMinRatio,
|
|
320
733
|
activeOrders: cfg.activeOrders,
|
|
321
734
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
735
|
+
repositionThresholdPct: cfg.repositionPct,
|
|
736
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
737
|
+
btsCreateFee: cfg.btsCreateFee,
|
|
738
|
+
btsCancelFee: cfg.btsCancelFee,
|
|
739
|
+
makerCreateFactor: cfg.makerCreateFactor,
|
|
740
|
+
txFeePrice: cfg.txFeePrice,
|
|
741
|
+
btsFeeCapital: cfg.btsFeeCapital,
|
|
742
|
+
warmupBars,
|
|
322
743
|
risk: {
|
|
323
744
|
duration: cfg.riskWDuration,
|
|
324
745
|
peakOpen: cfg.riskWPeakOpen,
|
|
@@ -335,8 +756,8 @@ function run() {
|
|
|
335
756
|
}
|
|
336
757
|
console.log('BEST PARAMS PER AMA');
|
|
337
758
|
console.log('--------------------------------------------------------------------------------');
|
|
338
|
-
console.log('AMA | spread | incr | ratio |
|
|
339
|
-
console.log('
|
|
759
|
+
console.log('AMA | spread | incr | ratio | cyc | fill% | net% | risk | score | inv-units (info)');
|
|
760
|
+
console.log('---------------------------------|--------|------|-------|-------|-------|--------|-------|-------|-----------------');
|
|
340
761
|
for (const row of byAma) {
|
|
341
762
|
const b = row.best;
|
|
342
763
|
if (!b)
|
|
@@ -349,8 +770,10 @@ function run() {
|
|
|
349
770
|
`${fmt(b.fillEfficiency, 1).padStart(5)} | ` +
|
|
350
771
|
`${fmt(b.totalNetCapturePct, 1).padStart(6)} | ` +
|
|
351
772
|
`${fmt(b.riskPenalty, 1).padStart(5)} | ` +
|
|
352
|
-
`${fmt(b.score, 1).padStart(5)}`
|
|
773
|
+
`${fmt(b.score, 1).padStart(5)} | ` +
|
|
774
|
+
`${fmt(b.inventoryUnits, 0).padStart(8)} (${fmt(b.inventoryNetPts, 1)} pts)`);
|
|
353
775
|
}
|
|
776
|
+
console.log('(* end-of-run inventory mark: informational only — excluded from scoring)');
|
|
354
777
|
console.log();
|
|
355
778
|
const outName = `bot_fitting_results_${path.basename(cfg.dataPath, '.json')}.json`;
|
|
356
779
|
const outPath = path.join(PATHS.ANALYSIS.RESULTS_DIR, outName);
|
|
@@ -361,18 +784,34 @@ function run() {
|
|
|
361
784
|
dataPath: path.relative(process.cwd(), cfg.dataPath),
|
|
362
785
|
resultsPath: path.relative(process.cwd(), cfg.resultsPath),
|
|
363
786
|
candles: candles.length,
|
|
364
|
-
activeOrders: cfg.activeOrders,
|
|
787
|
+
activeOrders: Number.isFinite(cfg.activeOrders) ? cfg.activeOrders : 'all',
|
|
365
788
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
789
|
+
btsCreateFee: cfg.btsCreateFee,
|
|
790
|
+
btsCancelFee: cfg.btsCancelFee,
|
|
791
|
+
makerCreateFactor: cfg.makerCreateFactor,
|
|
792
|
+
txFeePrice: cfg.txFeePrice,
|
|
793
|
+
btsFeeCapital: cfg.btsFeeCapital,
|
|
366
794
|
search: {
|
|
367
795
|
spreadValues: cfg.spreadValues,
|
|
368
796
|
incrementValues: cfg.incrementValues,
|
|
369
797
|
ratioValues: cfg.ratioValues,
|
|
370
798
|
minSpreadFactor: cfg.minSpreadFactor,
|
|
799
|
+
repositionPct: cfg.repositionPct,
|
|
800
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
371
801
|
combosPerAma: totalCombos,
|
|
372
802
|
},
|
|
373
803
|
scoring: {
|
|
374
|
-
baseScore: '
|
|
375
|
-
|
|
804
|
+
baseScore: 'totalNetCaptureAfterFeesPct * (fillEfficiency / 100)',
|
|
805
|
+
gridModel: 'persistent fixed chain prices (createOrderGrid port): master rail at sqrt(1±inc) offsets bounded by [center/ratio, center*ratio], gapSlots spread zone centered on center; prices never follow AMA after placement',
|
|
806
|
+
spreadParam: 'targetSpreadPercent for calculateGapSlots (floored at increment * MIN_SPREAD_FACTOR)',
|
|
807
|
+
resetTriggers: `(A) AMA drift >= ${cfg.repositionPct}% from recorded center (ratchet)${cfg.asymmetricBounds ? ` OR (B) |slope - slopeAtLastReset| >= ${(SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT}% over ${SLOPE_LOOKBACK_BARS}-bar average slope (baseline re-seeded on every reset)` : ' (trigger B gated off — asymmetricBounds whitelist)'}`,
|
|
808
|
+
gridPriceOffset: cfg.asymmetricBounds ? 'slope-ratio offset applied to placement center (direction * min(|slope|/maxSlopePct,1) * targetSpread/2) on every grid build' : 'disabled (asymmetricBounds whitelist)',
|
|
809
|
+
repositionAccounting: 'unfilled orders canceled + counted (incl armed refills/rebids); bought-and-held base carries across resets in a weighted-average-entry inventory pool (resync never market-sells); end-of-run inventory mark is informational and excluded from scoring',
|
|
810
|
+
cycleEconomics: 'slot rotation: filled buy re-offers one rail step up; that refill selling books ~increment% minus round-trip fee and the freed quote re-bids one step down; unlinked initial-grid sells only execute against held inventory at weighted-average entry (no shorting)',
|
|
811
|
+
totalGrossCapturePct: 'sum of realized per-rotation gross from actual fixed prices (linked rotations + inventory sales)',
|
|
812
|
+
totalNetCapturePct: 'realized gross - roundtrip fee per completed disposition; excludes the end-of-run inventory mark',
|
|
813
|
+
btsFees: `every order placement (initial grid + armed refills/rebids) pays maker create (${cfg.btsCreateFee}*${cfg.makerCreateFactor} BTS), every reset cancel pays ${cfg.btsCancelFee} BTS; btsFeePts = total BTS * txFeePrice / btsFeeCapital * 100 deducted from net before scoring`,
|
|
814
|
+
warmup: 'getAmaWarmupBars(er, slow, 0, fast)',
|
|
376
815
|
riskPenalty: `avgOpenDurationBars*${cfg.riskWDuration} + peakOpenOrders*${cfg.riskWPeakOpen} + avgImbalance*${cfg.riskWImbalance} + canceledOnReposition*${cfg.riskWCancel}`,
|
|
377
816
|
finalScore: 'baseScore - riskPenalty',
|
|
378
817
|
},
|
|
@@ -381,5 +820,10 @@ function run() {
|
|
|
381
820
|
});
|
|
382
821
|
console.log(`Saved: ${path.relative(process.cwd(), outPath)}`);
|
|
383
822
|
}
|
|
384
|
-
|
|
823
|
+
// Main-thread entry guard: importing this module (e.g. from the logic tests)
|
|
824
|
+
// must not execute the CLI run.
|
|
825
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
826
|
+
run();
|
|
827
|
+
}
|
|
828
|
+
export { computeGapSlots, computeGridPriceOffsetPct, buildProductionGrid, simulateForParams };
|
|
385
829
|
//# sourceMappingURL=backtest_bot_fitting.js.map
|