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,17 +1,65 @@
|
|
|
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
13
|
|
|
10
|
-
'use strict';
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
// Default mirrors production sizing: createOrderGrid sizes EVERY rail slot in
|
|
16
|
+
// bounds (modules/order/grid.ts), it does not cap per side. Infinity = all
|
|
17
|
+
// slots; --active-orders N restores a bounded run.
|
|
18
|
+
const DEFAULT_ACTIVE_ORDERS = Infinity;
|
|
13
19
|
const DEFAULT_FEE_ROUNDTRIP_PCT = 0.20;
|
|
14
|
-
|
|
20
|
+
|
|
21
|
+
// BTS operation fees — same model as backtest_ama_sweep. Every placement
|
|
22
|
+
// (initial grid, reset rebuild, per-cycle slot refill) pays a maker create
|
|
23
|
+
// fee, every cancel pays a cancel fee. Fees are converted into percentage
|
|
24
|
+
// points against --bts-fee-capital so they deduct from net capture in the
|
|
25
|
+
// same units as the rest of the accounting.
|
|
26
|
+
const DEFAULT_BTS_CREATE_FEE = 0.48260;
|
|
27
|
+
const DEFAULT_BTS_CANCEL_FEE = 0.00482;
|
|
28
|
+
const DEFAULT_BTS_MAKER_CREATE_FACTOR = 0.10;
|
|
29
|
+
const DEFAULT_TX_FEE_PRICE = 1.0;
|
|
30
|
+
const DEFAULT_BTS_FEE_CAPITAL = 10000;
|
|
31
|
+
|
|
32
|
+
// ── Production grid-reset triggers (MARKET_ADAPTER, modules/constants.ts) ────
|
|
33
|
+
//
|
|
34
|
+
// Trigger A — AMA delta: the live adapter records the AMA center and writes a
|
|
35
|
+
// recalculate.<botKey>.trigger when AMA moves ±AMA_DELTA_THRESHOLD_PERCENT
|
|
36
|
+
// from that recorded center; the center re-records only when a trigger fires
|
|
37
|
+
// (ratchet semantics — see analyze_ama_price_changes.trackRepositions).
|
|
38
|
+
// --reposition-pct overrides the default.
|
|
39
|
+
const DEFAULT_REPOSITION_PCT = MARKET_ADAPTER.AMA_DELTA_THRESHOLD_PERCENT;
|
|
40
|
+
//
|
|
41
|
+
// Trigger B — AMA slope delta, plus the grid price offset, are BOTH gated in
|
|
42
|
+
// production behind the per-bot asymmetricBounds whitelist
|
|
43
|
+
// (market_adapter_service.ts: isGridRangeScalingWhitelisted consumes both
|
|
44
|
+
// shouldTrigger at the slope-reset write and computeGridPriceOffsetPlan via
|
|
45
|
+
// README "asymmetricBounds whitelist also enables gridPriceOffsetPct").
|
|
46
|
+
// The sim therefore exposes one switch, default OFF (typical non-whitelisted
|
|
47
|
+
// bot): --asymmetric-bounds enables slope-delta resets AND slope-ratio offset.
|
|
48
|
+
// Trigger B fires when |slopePct_now − baseline| reaches
|
|
49
|
+
// (AMA_SLOPE_DELTA_THRESHOLD_PERCENT / 100) × DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT,
|
|
50
|
+
// where slopePct is the average per-bar AMA change over
|
|
51
|
+
// DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS (computeAverageAmaSlopePct) and the
|
|
52
|
+
// baseline mirrors botState.gridRangeScalingAmaSlope (re-seeded every reset).
|
|
53
|
+
const SLOPE_TRIGGER_FACTOR = MARKET_ADAPTER.AMA_SLOPE_DELTA_THRESHOLD_PERCENT;
|
|
54
|
+
const SLOPE_MAX_PCT = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT;
|
|
55
|
+
const SLOPE_LOOKBACK_BARS = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS;
|
|
56
|
+
const SLOPE_NEUTRAL_ZONE_PCT = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_NEUTRAL_ZONE_PCT;
|
|
57
|
+
|
|
58
|
+
// Spread-gap floor knobs (GRID_LIMITS): the effective target spread is
|
|
59
|
+
// clamped up to incrementPercent × MIN_SPREAD_FACTOR and the gap is never
|
|
60
|
+
// narrower than MIN_SPREAD_ORDERS slots — mirrored from calculateGapSlots
|
|
61
|
+
// (modules/order/utils/math.ts).
|
|
62
|
+
const DEFAULT_MIN_SPREAD_FACTOR = GRID_LIMITS.MIN_SPREAD_FACTOR;
|
|
15
63
|
|
|
16
64
|
// Inventory-risk penalty weights (in score points)
|
|
17
65
|
const RISK_W_DURATION = 1.0; // avg open bars
|
|
@@ -34,6 +82,13 @@ function parseArgs() {
|
|
|
34
82
|
activeOrders: number;
|
|
35
83
|
feeRoundtripPct: number;
|
|
36
84
|
minSpreadFactor: number;
|
|
85
|
+
repositionPct: number;
|
|
86
|
+
asymmetricBounds: boolean;
|
|
87
|
+
btsCreateFee: number;
|
|
88
|
+
btsCancelFee: number;
|
|
89
|
+
makerCreateFactor: number;
|
|
90
|
+
txFeePrice: number;
|
|
91
|
+
btsFeeCapital: number;
|
|
37
92
|
riskWDuration: number;
|
|
38
93
|
riskWPeakOpen: number;
|
|
39
94
|
riskWImbalance: number;
|
|
@@ -47,6 +102,13 @@ function parseArgs() {
|
|
|
47
102
|
activeOrders: DEFAULT_ACTIVE_ORDERS,
|
|
48
103
|
feeRoundtripPct: DEFAULT_FEE_ROUNDTRIP_PCT,
|
|
49
104
|
minSpreadFactor: DEFAULT_MIN_SPREAD_FACTOR,
|
|
105
|
+
repositionPct: DEFAULT_REPOSITION_PCT,
|
|
106
|
+
asymmetricBounds: false,
|
|
107
|
+
btsCreateFee: DEFAULT_BTS_CREATE_FEE,
|
|
108
|
+
btsCancelFee: DEFAULT_BTS_CANCEL_FEE,
|
|
109
|
+
makerCreateFactor: DEFAULT_BTS_MAKER_CREATE_FACTOR,
|
|
110
|
+
txFeePrice: DEFAULT_TX_FEE_PRICE,
|
|
111
|
+
btsFeeCapital: DEFAULT_BTS_FEE_CAPITAL,
|
|
50
112
|
riskWDuration: RISK_W_DURATION,
|
|
51
113
|
riskWPeakOpen: RISK_W_PEAK_OPEN,
|
|
52
114
|
riskWImbalance: RISK_W_IMBALANCE,
|
|
@@ -55,6 +117,9 @@ function parseArgs() {
|
|
|
55
117
|
|
|
56
118
|
for (let i = 0; i < args.length; i++) {
|
|
57
119
|
const arg = args[i];
|
|
120
|
+
// Valueless boolean flag — must be handled before the value lookup
|
|
121
|
+
// below (and before the trailing-arg `if (!val) continue` guard).
|
|
122
|
+
if (arg === '--asymmetric-bounds') { out.asymmetricBounds = true; continue; }
|
|
58
123
|
const val = args[i + 1];
|
|
59
124
|
if (!val) continue;
|
|
60
125
|
switch (arg) {
|
|
@@ -90,6 +155,30 @@ function parseArgs() {
|
|
|
90
155
|
out.minSpreadFactor = Number(val);
|
|
91
156
|
i++;
|
|
92
157
|
break;
|
|
158
|
+
case '--reposition-pct':
|
|
159
|
+
out.repositionPct = Number(val);
|
|
160
|
+
i++;
|
|
161
|
+
break;
|
|
162
|
+
case '--bts-create-fee':
|
|
163
|
+
out.btsCreateFee = Number(val);
|
|
164
|
+
i++;
|
|
165
|
+
break;
|
|
166
|
+
case '--bts-cancel-fee':
|
|
167
|
+
out.btsCancelFee = Number(val);
|
|
168
|
+
i++;
|
|
169
|
+
break;
|
|
170
|
+
case '--maker-create-factor':
|
|
171
|
+
out.makerCreateFactor = Number(val);
|
|
172
|
+
i++;
|
|
173
|
+
break;
|
|
174
|
+
case '--tx-fee-price':
|
|
175
|
+
out.txFeePrice = Number(val);
|
|
176
|
+
i++;
|
|
177
|
+
break;
|
|
178
|
+
case '--bts-fee-capital':
|
|
179
|
+
out.btsFeeCapital = Number(val);
|
|
180
|
+
i++;
|
|
181
|
+
break;
|
|
93
182
|
case '--risk-duration':
|
|
94
183
|
out.riskWDuration = Number(val);
|
|
95
184
|
i++;
|
|
@@ -178,111 +267,398 @@ function loadAmaStrategies(resultsPath: string) {
|
|
|
178
267
|
return out;
|
|
179
268
|
}
|
|
180
269
|
|
|
181
|
-
|
|
182
|
-
|
|
270
|
+
/**
|
|
271
|
+
* Spread-gap width in slots — direct port of calculateGapSlots
|
|
272
|
+
* (modules/order/utils/math.ts:1228). The effective target spread is clamped
|
|
273
|
+
* up to incrementPercent × MIN_SPREAD_FACTOR and the gap never drops below
|
|
274
|
+
* MIN_SPREAD_ORDERS slots. `incrementPercent`/`targetSpreadPercent` in PERCENT
|
|
275
|
+
* units, matching the production signature.
|
|
276
|
+
*/
|
|
277
|
+
function computeGapSlots(incrementPercent: number, targetSpreadPercent: number) {
|
|
278
|
+
const step = 1 + (incrementPercent / 100);
|
|
279
|
+
const minSpreadPercent = incrementPercent * GRID_LIMITS.MIN_SPREAD_FACTOR;
|
|
280
|
+
const effectiveTargetSpread = Math.max(targetSpreadPercent || 0, minSpreadPercent);
|
|
281
|
+
const requiredSteps = Math.ceil(Math.log(1 + (effectiveTargetSpread / 100)) / Math.log(step));
|
|
282
|
+
return Math.max(GRID_LIMITS.MIN_SPREAD_ORDERS, requiredSteps - 1);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Slope-ratio grid price offset — port of computeGridPriceOffsetPlan
|
|
287
|
+
* (market_adapter/core/market_adapter_service.ts:92-119) combined with the
|
|
288
|
+
* trend/slopeRatio semantics of computeAmaSlopeWeights
|
|
289
|
+
* (market_adapter/core/strategies/ama_slope_model.ts):
|
|
290
|
+
*
|
|
291
|
+
* maxGridPriceOffsetPct = targetSpreadPercent / 2
|
|
292
|
+
* slopeRatio = min(|slopePct| / DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT, 1)
|
|
293
|
+
* direction = sign(slopePct) (0 inside the neutral zone)
|
|
294
|
+
* offsetPct = direction × slopeRatio × maxGridPriceOffsetPct
|
|
295
|
+
*
|
|
296
|
+
* Production applies this to startPrice (grid.ts:982: startPrice × (1 +
|
|
297
|
+
* offset/100)) only for asymmetricBounds-whitelisted bots; the sim applies it
|
|
298
|
+
* to the placement center on every grid build when asymmetricBounds is on.
|
|
299
|
+
*/
|
|
300
|
+
function computeGridPriceOffsetPct(slopePct: number, targetSpreadPercent: number) {
|
|
301
|
+
if (!Number.isFinite(slopePct)) return 0;
|
|
302
|
+
if (Math.abs(slopePct) <= SLOPE_NEUTRAL_ZONE_PCT) return 0;
|
|
303
|
+
const slopeRatio = Math.min(Math.abs(slopePct) / SLOPE_MAX_PCT, 1);
|
|
304
|
+
const maxGridPriceOffsetPct = targetSpreadPercent / 2;
|
|
305
|
+
const direction = slopePct > 0 ? 1 : -1;
|
|
306
|
+
const offsetPct = direction * slopeRatio * maxGridPriceOffsetPct;
|
|
307
|
+
return Math.round(offsetPct * 1e6) / 1e6;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Build a persistent grid with FIXED chain prices from a master rail —
|
|
312
|
+
* port of createOrderGrid (modules/order/grid.ts:374-505):
|
|
313
|
+
*
|
|
314
|
+
* - Master rail: geometric progression starting at √(1±inc) × center and
|
|
315
|
+
* expanding by (1±inc) steps outward, bounded by
|
|
316
|
+
* [center/maxMinRatio, center×maxMinRatio] (grid.ts:428-444).
|
|
317
|
+
* - Spread gap: gapSlots empty slots centered on the center price
|
|
318
|
+
* (calculateIdealBoundary: boundaryIdx = splitIdx − floor(gap/2) − 1;
|
|
319
|
+
* sells start at boundaryIdx + gapSlots + 1).
|
|
320
|
+
* - By default every rail slot in bounds is sized (activeOrders = Infinity,
|
|
321
|
+
* matching production); an explicit cap keeps only the slots nearest the
|
|
322
|
+
* gap on each side.
|
|
323
|
+
*
|
|
324
|
+
* Order prices are placement-time constants — exactly like on-chain orders,
|
|
325
|
+
* they do NOT follow AMA after placement.
|
|
326
|
+
*/
|
|
327
|
+
function buildProductionGrid(center: number, spreadPct: number, incrementPctFrac: number, maxMinRatio: number, activeOrders: number) {
|
|
328
|
+
const stepUp = 1 + incrementPctFrac;
|
|
329
|
+
const stepDown = 1 - incrementPctFrac;
|
|
330
|
+
const minBound = center / maxMinRatio;
|
|
331
|
+
const maxBound = center * maxMinRatio;
|
|
332
|
+
|
|
333
|
+
const rail: number[] = [];
|
|
334
|
+
let p = center * Math.sqrt(stepUp);
|
|
335
|
+
while (p <= maxBound) { rail.push(p); p *= stepUp; }
|
|
336
|
+
p = center * Math.sqrt(stepDown);
|
|
337
|
+
while (p >= minBound) { rail.push(p); p *= stepDown; }
|
|
338
|
+
rail.sort((a, b) => a - b);
|
|
339
|
+
if (rail.length === 0) return { buys: [], sells: [], rail: [], buySliceStart: 0, sellStartIdx: 0 };
|
|
340
|
+
|
|
341
|
+
const gapSlots = computeGapSlots(incrementPctFrac * 100, spreadPct);
|
|
342
|
+
let splitIdx = rail.findIndex((v) => v >= center);
|
|
343
|
+
if (splitIdx === -1) splitIdx = rail.length;
|
|
344
|
+
const buySpread = Math.floor(gapSlots / 2);
|
|
345
|
+
const boundaryIdx = Math.max(0, Math.min(rail.length - 1, splitIdx - buySpread - 1));
|
|
346
|
+
const sellStartIdx = boundaryIdx + gapSlots + 1;
|
|
347
|
+
|
|
348
|
+
// Buys closest to the gap = highest priced below boundary; sells closest =
|
|
349
|
+
// lowest priced above sellStartIdx. Rail + slice offsets are returned so
|
|
350
|
+
// callers can map each placed slot onto its MASTER-RAIL index (rotation
|
|
351
|
+
// walks adjacent rail nodes, exactly like the live anchor-&-refill hop).
|
|
352
|
+
const buySliceStart = Math.max(0, boundaryIdx - activeOrders + 1);
|
|
353
|
+
const sellsArr = rail.slice(sellStartIdx, sellStartIdx + activeOrders);
|
|
354
|
+
return {
|
|
355
|
+
buys: rail.slice(buySliceStart, boundaryIdx + 1),
|
|
356
|
+
sells: sellsArr,
|
|
357
|
+
rail,
|
|
358
|
+
buySliceStart,
|
|
359
|
+
sellStartIdx,
|
|
360
|
+
};
|
|
183
361
|
}
|
|
184
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Slot-rotation simulation with FIXED chain prices, mirroring production
|
|
365
|
+
* anchor-&-refill (strategy.ts) on top of the createOrderGrid geometry:
|
|
366
|
+
*
|
|
367
|
+
* - Initial grid built once at the post-warmup AMA (createOrderGrid geometry
|
|
368
|
+
* via buildProductionGrid); order prices never follow AMA afterwards. When
|
|
369
|
+
* asymmetricBounds is enabled the placement center is shifted by the
|
|
370
|
+
* slope-ratio offset (#3) exactly like the live startPrice offset.
|
|
371
|
+
* - Rotation economics (#1/#2/#15): a FILLED BUY at rail node k instantly
|
|
372
|
+
* re-offers that base at the ADJACENT MASTER-RAIL NODE k+1; when that
|
|
373
|
+
* refill sells, the rotation books exactly one rail hop minus the
|
|
374
|
+
* round-trip fee, and the freed quote re-bids the node k-1 below. Slots
|
|
375
|
+
* cycle on small oscillations between resets — the earnings model of a
|
|
376
|
+
* refilled live slot, not a cross-gap differential.
|
|
377
|
+
* - Inventory-funded selling: an INITIAL (unlinked) sell can only execute
|
|
378
|
+
* against held inventory — it books its proceeds against the weighted
|
|
379
|
+
* average entry of the position (the live bot funds sells from real
|
|
380
|
+
* balances; unfundable sells stay open and retry, never shorting). Base
|
|
381
|
+
* bought in the SAME bar does not fund unlinked sales until the next bar
|
|
382
|
+
* (live balance updates propagate on the next maintenance tick).
|
|
383
|
+
* - Same-bar guard: newly armed/refill orders carry a one-bar cooldown, so
|
|
384
|
+
* a slot that just cycled cannot fill again inside the completion bar.
|
|
385
|
+
* - Grid reset fires on EITHER production trigger:
|
|
386
|
+
* (A) |AMA − recordedCenter| / recordedCenter ≥ repositionThresholdPct
|
|
387
|
+
* (ratchet: recordedCenter updates only when the trigger fires),
|
|
388
|
+
* (B) slope-delta reset, ONLY when asymmetricBounds (whitelist gate):
|
|
389
|
+
* |slopePct_now − slopeBaseline| ≥ slopeDeltaThresholdPct
|
|
390
|
+
* (= AMA_SLOPE_DELTA_THRESHOLD_PERCENT/100 ×
|
|
391
|
+
* DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT), where slopePct is the
|
|
392
|
+
* DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS average-slope series and
|
|
393
|
+
* slopeBaseline mirrors botState.gridRangeScalingAmaSlope — seeded
|
|
394
|
+
* at start and re-seeded on every reset.
|
|
395
|
+
* On reset ALL unfilled orders are canceled (counted); bought-and-held
|
|
396
|
+
* base REMAINS as inventory (live resync never market-sells) and merges
|
|
397
|
+
* into the weighted-average-entry pool; a fresh grid is placed at the
|
|
398
|
+
* new center.
|
|
399
|
+
* - Scoring uses REALIZED rotations and op fees ONLY. The end-of-run
|
|
400
|
+
* inventory position (units × mark-vs-avg-entry) is reported as an
|
|
401
|
+
* informational field — it is real carried risk, but including unrealized
|
|
402
|
+
* bag marks in the ranking objective let trend-following combos dump
|
|
403
|
+
* phantom paper profit into the score.
|
|
404
|
+
* - BTS operation fees (#9): every order placement (initial grid + every
|
|
405
|
+
* armed refill/rebid) pays makerCreateFee × btsCreateFee, every reset
|
|
406
|
+
* cancel pays btsCancelFee; totals are converted to percentage points
|
|
407
|
+
* against the --bts-fee-capital reference and deducted from net capture.
|
|
408
|
+
*
|
|
409
|
+
* Differences from production (by design, documented):
|
|
410
|
+
* #6 bar-granularity triggers and reset-vs-fill ordering (OHLC sim);
|
|
411
|
+
* #7 all-or-nothing fills on raw hi/lo touch (no partial fills/dust/queue);
|
|
412
|
+
* #8 unit sizes / percentage-point accounting instead of capital-weighted
|
|
413
|
+
* dynamic sizing;
|
|
414
|
+
* #10 pool-price fills (no book depth/slippage);
|
|
415
|
+
* #11 no consolidation/dust-cancel/COW/collision mechanics.
|
|
416
|
+
*/
|
|
185
417
|
function simulateForParams(candles: any, amaValues: any, params: any) {
|
|
186
|
-
const { spreadPct, incrementPct, maxMinRatio, activeOrders, feeRoundtripPct,
|
|
187
|
-
|
|
188
|
-
|
|
418
|
+
const { spreadPct, incrementPct, maxMinRatio, activeOrders, feeRoundtripPct,
|
|
419
|
+
repositionThresholdPct, asymmetricBounds, risk,
|
|
420
|
+
btsCreateFee, btsCancelFee, makerCreateFactor, txFeePrice, btsFeeCapital } = params;
|
|
421
|
+
// Warmup follows production AMA seeding/convergence (getAmaWarmupBars)
|
|
422
|
+
// instead of an arbitrary fraction of the dataset, so simulations never
|
|
423
|
+
// start on SMA-warmup values when the fitted ER period is large.
|
|
424
|
+
const skip = Math.min(params.warmupBars, Math.max(0, candles.length - 2));
|
|
425
|
+
const singleLegFeePct = feeRoundtripPct / 2;
|
|
426
|
+
const slopeDeltaThresholdPct = (SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT;
|
|
427
|
+
const makerCreateFeeBts = btsCreateFee * makerCreateFactor;
|
|
428
|
+
const stepUpFrac = 1 + incrementPct; // one-rail-step rotation distance
|
|
429
|
+
|
|
430
|
+
// First tradable bar: need a finite positive AMA to anchor the chain.
|
|
431
|
+
let startIdx = Math.min(skip, candles.length - 1);
|
|
432
|
+
let gridCenter = Number.NaN;
|
|
433
|
+
for (let j = startIdx; j < candles.length; j++) {
|
|
434
|
+
const v = amaValues[j];
|
|
435
|
+
if (Number.isFinite(v) && v > 0) { gridCenter = v; startIdx = j; break; }
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Production AMA slope series (%/bar averaged over the lookback window).
|
|
439
|
+
// Evaluated over full history like the live adapter (only bar-index guards).
|
|
440
|
+
const slopeAt: (number | null)[] = new Array(candles.length).fill(null);
|
|
441
|
+
for (let j = SLOPE_LOOKBACK_BARS; j < candles.length; j++) {
|
|
442
|
+
const s = computeAverageAmaSlopePct(amaValues[j], amaValues[j - SLOPE_LOOKBACK_BARS], SLOPE_LOOKBACK_BARS);
|
|
443
|
+
if (s != null && Number.isFinite(s)) slopeAt[j] = s;
|
|
444
|
+
}
|
|
189
445
|
|
|
190
|
-
|
|
191
|
-
|
|
446
|
+
// Open orders keyed by running id: { side, price, linkedBuyPrice,
|
|
447
|
+
// linkedEntryBar, cooldownUntil }. linkedBuyPrice != null marks an armed
|
|
448
|
+
// refill sell created by a specific filled buy (one-increment rotation).
|
|
449
|
+
const orders = new Map<number, any>();
|
|
450
|
+
let nextOrderId = 0;
|
|
451
|
+
// Bought-and-held base across the whole run (weighted-average entry
|
|
452
|
+
// pool). Never negative — sells without inventory stay pending.
|
|
453
|
+
const inv = { units: 0, cost: 0 };
|
|
454
|
+
|
|
455
|
+
let btsFeesBts = 0;
|
|
456
|
+
let offsetAppliedCount = 0;
|
|
457
|
+
// Master rail of the CURRENT epoch — rotation hops read adjacent nodes.
|
|
458
|
+
let activeRail: number[] = [];
|
|
459
|
+
|
|
460
|
+
const placeInitialGrid = (center: number, slopePct: number | null) => {
|
|
461
|
+
const offsetPct = (asymmetricBounds && slopePct != null)
|
|
462
|
+
? computeGridPriceOffsetPct(slopePct, spreadPct)
|
|
463
|
+
: 0;
|
|
464
|
+
if (offsetPct !== 0) offsetAppliedCount++;
|
|
465
|
+
const effCenter = center * (1 + offsetPct / 100);
|
|
466
|
+
const built = buildProductionGrid(effCenter, spreadPct, incrementPct, maxMinRatio, activeOrders);
|
|
467
|
+
activeRail = built.rail;
|
|
468
|
+
orders.clear();
|
|
469
|
+
// Rail indices matter: rotation re-offers/re-bids walk ADJACENT
|
|
470
|
+
// master-rail nodes (buy at node k arms a sell at node k+1; the freed
|
|
471
|
+
// quote re-bids node k-1), preserving the exact production hop sizes.
|
|
472
|
+
built.buys.forEach((price, i) => orders.set(nextOrderId++, {
|
|
473
|
+
side: 'buy', price, railIdx: built.buySliceStart + i,
|
|
474
|
+
linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1,
|
|
475
|
+
}));
|
|
476
|
+
built.sells.forEach((price, i) => orders.set(nextOrderId++, {
|
|
477
|
+
side: 'sell', price, railIdx: built.sellStartIdx + i,
|
|
478
|
+
linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1,
|
|
479
|
+
}));
|
|
480
|
+
btsFeesBts += (built.buys.length + built.sells.length) * makerCreateFeeBts;
|
|
481
|
+
};
|
|
192
482
|
|
|
193
483
|
let touchedOrders = 0;
|
|
194
|
-
let
|
|
484
|
+
let cyclesTotal = 0;
|
|
485
|
+
let rotationCount = 0; // linked ping-pong rotations (buy → refill sell)
|
|
486
|
+
let inventorySaleCount = 0; // unlinked sells executed against held bags
|
|
195
487
|
let canceledOnReposition = 0;
|
|
488
|
+
let repositionCount = 0;
|
|
489
|
+
let driftTriggerCount = 0;
|
|
490
|
+
let slopeTriggerCount = 0;
|
|
196
491
|
let totalGrossCapturePct = 0;
|
|
197
492
|
let totalNetCapturePct = 0;
|
|
198
|
-
let activeLevelTouches = 0;
|
|
199
493
|
let peakOpenOrders = 0;
|
|
200
494
|
let imbalanceSum = 0;
|
|
201
495
|
let imbalanceSamples = 0;
|
|
202
496
|
let matchedOpenDurationBars = 0;
|
|
203
497
|
|
|
204
|
-
|
|
498
|
+
const invAvgEntry = () => (inv.units > 0 ? inv.cost / inv.units : 0);
|
|
499
|
+
|
|
500
|
+
if (Number.isFinite(gridCenter)) placeInitialGrid(gridCenter, slopeAt[startIdx]);
|
|
501
|
+
|
|
502
|
+
// Slope-delta baseline: mirrors botState.gridRangeScalingAmaSlope —
|
|
503
|
+
// seeded at bootstrap (first cycle) and re-seeded to the current slope on
|
|
504
|
+
// EVERY grid reset (advanceTriggeredBotState), so trigger B measures how
|
|
505
|
+
// far slope has moved SINCE THE LAST RESET, not bar-over-bar jitter.
|
|
506
|
+
let slopeBaseline: number | null = null;
|
|
507
|
+
for (let j = startIdx + 1; j < candles.length; j++) {
|
|
508
|
+
if (slopeAt[j] != null) { slopeBaseline = slopeAt[j]; break; }
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
for (let i = startIdx + 1; i < candles.length; i++) {
|
|
205
512
|
const ama = amaValues[i];
|
|
206
|
-
const prevAma = amaValues[i - 1];
|
|
207
513
|
const hi = candles[i].high;
|
|
208
514
|
const lo = candles[i].low;
|
|
209
515
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
516
|
+
// ── Grid-reset check: trigger A (AMA delta) always; trigger B
|
|
517
|
+
// (slope delta) only under the asymmetricBounds whitelist gate.
|
|
518
|
+
let shouldReset = false;
|
|
519
|
+
if (Number.isFinite(ama) && ama > 0) {
|
|
520
|
+
const driftPct = (Math.abs(ama - gridCenter) / gridCenter) * 100;
|
|
521
|
+
if (driftPct >= repositionThresholdPct) { shouldReset = true; driftTriggerCount++; }
|
|
522
|
+
}
|
|
523
|
+
if (!shouldReset && asymmetricBounds && slopeBaseline != null && slopeAt[i] != null) {
|
|
524
|
+
const slopeDeltaPct = Math.abs(slopeAt[i]! - slopeBaseline);
|
|
525
|
+
if (slopeDeltaPct >= slopeDeltaThresholdPct) { shouldReset = true; slopeTriggerCount++; }
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (shouldReset && Number.isFinite(ama) && ama > 0) {
|
|
529
|
+
canceledOnReposition += orders.size;
|
|
530
|
+
btsFeesBts += orders.size * btsCancelFee;
|
|
531
|
+
orders.clear(); // inventory survives — resync never market-sells
|
|
532
|
+
repositionCount++;
|
|
533
|
+
gridCenter = ama; // ratchet the recorded center to the current AMA
|
|
534
|
+
// Re-seed the slope baseline with the current slope (falls back to
|
|
535
|
+
// the previous baseline when slope is not ready — same as
|
|
536
|
+
// advanceTriggeredBotState's `|| previous` chain).
|
|
537
|
+
if (slopeAt[i] != null) slopeBaseline = slopeAt[i];
|
|
538
|
+
placeInitialGrid(gridCenter, slopeAt[i]);
|
|
214
539
|
}
|
|
215
540
|
|
|
216
|
-
const currentOpen =
|
|
541
|
+
const currentOpen = orders.size;
|
|
217
542
|
if (currentOpen > peakOpenOrders) peakOpenOrders = currentOpen;
|
|
218
|
-
|
|
543
|
+
let buyCount = 0;
|
|
544
|
+
for (const [, o] of orders) { if (o.side === 'buy') buyCount++; }
|
|
545
|
+
imbalanceSum += Math.abs(buyCount - (orders.size - buyCount));
|
|
219
546
|
imbalanceSamples++;
|
|
220
547
|
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
for (
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
548
|
+
// ── Fill detection against FIXED chain prices ───────────────────
|
|
549
|
+
const filledBuys: { id: number; order: any }[] = [];
|
|
550
|
+
const filledSells: { id: number; order: any }[] = [];
|
|
551
|
+
for (const [id, o] of orders) {
|
|
552
|
+
if (i < o.cooldownUntil) continue;
|
|
553
|
+
if (o.side === 'buy' && lo <= o.price) filledBuys.push({ id, order: o });
|
|
554
|
+
else if (o.side === 'sell' && hi >= o.price) filledSells.push({ id, order: o });
|
|
555
|
+
}
|
|
556
|
+
touchedOrders += filledBuys.length + filledSells.length;
|
|
557
|
+
// Base held BEFORE this bar's intakes — an unlinked sell may only
|
|
558
|
+
// dispose against pre-existing funds (live balance updates propagate
|
|
559
|
+
// on the next maintenance tick; same-bar funding is not assumed).
|
|
560
|
+
const invAtBarStart = inv.units;
|
|
561
|
+
|
|
562
|
+
// ── Buy intakes first: base enters inventory, refill armed at the
|
|
563
|
+
// ADJACENT MASTER-RAIL NODE above (anchor-&-refill hop; cooldown
|
|
564
|
+
// blocks same-bar recycles).
|
|
565
|
+
for (const f of filledBuys) {
|
|
566
|
+
orders.delete(f.id);
|
|
567
|
+
inv.units += 1;
|
|
568
|
+
inv.cost += f.order.price;
|
|
569
|
+
const upIdx = (f.order.railIdx ?? -1) + 1;
|
|
570
|
+
const refillPrice = activeRail[upIdx] ?? f.order.price * stepUpFrac;
|
|
571
|
+
orders.set(nextOrderId++, {
|
|
572
|
+
side: 'sell',
|
|
573
|
+
price: refillPrice,
|
|
574
|
+
railIdx: upIdx,
|
|
575
|
+
linkedBuyPrice: f.order.price,
|
|
576
|
+
linkedEntryBar: i,
|
|
577
|
+
cooldownUntil: i + 1,
|
|
578
|
+
});
|
|
579
|
+
btsFeesBts += makerCreateFeeBts;
|
|
580
|
+
}
|
|
253
581
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
582
|
+
// ── Sell disposals: linked refills book the one-rail-hop rotation;
|
|
583
|
+
// unlinked (initial-grid) sells need held inventory — no shorting.
|
|
584
|
+
// Linked refills resolve FIRST so same-bar cross-gap inventory
|
|
585
|
+
// sales against a fresh bag cannot happen.
|
|
586
|
+
filledSells.sort((a, b) => ((a.order.linkedBuyPrice != null ? 0 : 1) - (b.order.linkedBuyPrice != null ? 0 : 1)));
|
|
587
|
+
let disposables = invAtBarStart;
|
|
588
|
+
for (const f of filledSells) {
|
|
589
|
+
const o = f.order;
|
|
590
|
+
if (o.linkedBuyPrice != null) {
|
|
591
|
+
const grossPct = (o.price / o.linkedBuyPrice - 1) * 100;
|
|
592
|
+
totalGrossCapturePct += grossPct;
|
|
593
|
+
totalNetCapturePct += grossPct - feeRoundtripPct;
|
|
594
|
+
cyclesTotal++;
|
|
595
|
+
rotationCount++;
|
|
596
|
+
matchedOpenDurationBars += Math.abs(i - o.linkedEntryBar);
|
|
597
|
+
// Dispose the unit its own rotation bought.
|
|
598
|
+
const applied = Math.min(1, inv.units);
|
|
599
|
+
inv.cost -= applied * invAvgEntry();
|
|
600
|
+
inv.units -= applied;
|
|
601
|
+
// Its disposal also drains the pre-bar funding budget —
|
|
602
|
+
// otherwise later unlinked sales could overspend stock.
|
|
603
|
+
disposables -= applied;
|
|
604
|
+
// Freed quote re-bids the ADJACENT RAIL NODE below.
|
|
605
|
+
const downIdx = (o.railIdx ?? 0) - 1;
|
|
606
|
+
const rebidPrice = activeRail[downIdx] ?? o.price / stepUpFrac;
|
|
607
|
+
orders.delete(f.id);
|
|
608
|
+
orders.set(nextOrderId++, {
|
|
609
|
+
side: 'buy',
|
|
610
|
+
price: rebidPrice,
|
|
611
|
+
railIdx: downIdx,
|
|
612
|
+
linkedBuyPrice: null,
|
|
613
|
+
linkedEntryBar: -1,
|
|
614
|
+
cooldownUntil: i + 1,
|
|
615
|
+
});
|
|
616
|
+
btsFeesBts += makerCreateFeeBts;
|
|
617
|
+
} else if (disposables >= 1) {
|
|
618
|
+
const avgEntry = invAvgEntry();
|
|
619
|
+
const grossPct = (o.price / avgEntry - 1) * 100;
|
|
620
|
+
totalGrossCapturePct += grossPct;
|
|
621
|
+
totalNetCapturePct += grossPct - feeRoundtripPct;
|
|
622
|
+
cyclesTotal++;
|
|
623
|
+
inventorySaleCount++;
|
|
624
|
+
inv.cost -= avgEntry; // remove that unit at pool-average cost
|
|
625
|
+
inv.units -= 1;
|
|
626
|
+
disposables -= 1;
|
|
627
|
+
orders.delete(f.id); // sold bag is gone; slot not re-armed
|
|
628
|
+
} else {
|
|
629
|
+
// Unfundable (no base to sell): stays open, retries next bar.
|
|
630
|
+
o.cooldownUntil = i + 1;
|
|
265
631
|
}
|
|
266
632
|
}
|
|
267
633
|
}
|
|
268
634
|
|
|
269
|
-
//
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
635
|
+
// ── End-of-run inventory mark (informational, NOT in score) ────────
|
|
636
|
+
// Bought-and-held base is real carried risk, but unrealized bag marks are
|
|
637
|
+
// excluded from ranking so trend-following combos can't dump phantom
|
|
638
|
+
// paper profit into the objective. Marked once at the final close with a
|
|
639
|
+
// single-leg exit fee per unit.
|
|
640
|
+
const lastClose = candles.length > 0 ? candles[candles.length - 1].close : NaN;
|
|
641
|
+
const inventoryUnits = inv.units;
|
|
642
|
+
const inventoryAvgEntry = invAvgEntry();
|
|
643
|
+
const inventoryNetPts = inventoryUnits > 0 && Number.isFinite(lastClose) && lastClose > 0
|
|
644
|
+
? (((lastClose / inventoryAvgEntry) - 1) * 100 - singleLegFeePct) * inventoryUnits
|
|
645
|
+
: 0;
|
|
646
|
+
|
|
647
|
+
// BTS operation fees → percentage points against the reference capital.
|
|
648
|
+
const btsFeePts = (btsFeesBts * txFeePrice) / Math.max(1, btsFeeCapital) * 100;
|
|
649
|
+
const totalNetCaptureAfterFeesPct = totalNetCapturePct - btsFeePts;
|
|
650
|
+
|
|
651
|
+
const fillEfficiency = touchedOrders > 0 ? (cyclesTotal / touchedOrders) * 100 : 0;
|
|
652
|
+
const avgNetPerPair = cyclesTotal > 0 ? totalNetCapturePct / cyclesTotal : 0;
|
|
653
|
+
const utilization = (touchedOrders / Math.max(1, candles.length - skip)) * 100;
|
|
654
|
+
const avgOpenDurationBars = rotationCount > 0 ? (matchedOpenDurationBars / rotationCount) : 0;
|
|
280
655
|
const avgImbalance = imbalanceSamples > 0 ? (imbalanceSum / imbalanceSamples) : 0;
|
|
281
656
|
const riskPenalty =
|
|
282
657
|
(avgOpenDurationBars * risk.duration) +
|
|
283
658
|
(peakOpenOrders * risk.peakOpen) +
|
|
284
659
|
(avgImbalance * risk.imbalance) +
|
|
285
660
|
(canceledOnReposition * risk.cancel);
|
|
661
|
+
const baseScore = totalNetCaptureAfterFeesPct * (fillEfficiency / 100);
|
|
286
662
|
const score = baseScore - riskPenalty;
|
|
287
663
|
|
|
288
664
|
return {
|
|
@@ -290,12 +666,26 @@ function simulateForParams(candles: any, amaValues: any, params: any) {
|
|
|
290
666
|
incrementPct,
|
|
291
667
|
maxMinRatio,
|
|
292
668
|
touchedOrders,
|
|
293
|
-
matchedPairs,
|
|
669
|
+
matchedPairs: cyclesTotal,
|
|
670
|
+
cyclesTotal,
|
|
671
|
+
rotationCount,
|
|
672
|
+
inventorySaleCount,
|
|
673
|
+
avgCyclesPerSlot: cyclesTotal / Math.max(1, peakOpenOrders),
|
|
294
674
|
fillEfficiency,
|
|
295
675
|
totalGrossCapturePct,
|
|
296
676
|
totalNetCapturePct,
|
|
677
|
+
btsFeePts,
|
|
678
|
+
btsFeesBts,
|
|
679
|
+
totalNetCaptureAfterFeesPct,
|
|
297
680
|
avgNetPerPair,
|
|
298
681
|
canceledOnReposition,
|
|
682
|
+
repositionCount,
|
|
683
|
+
driftTriggerCount,
|
|
684
|
+
slopeTriggerCount,
|
|
685
|
+
inventoryUnits,
|
|
686
|
+
inventoryAvgEntry,
|
|
687
|
+
inventoryNetPts,
|
|
688
|
+
offsetAppliedCount,
|
|
299
689
|
avgOpenDurationBars,
|
|
300
690
|
peakOpenOrders,
|
|
301
691
|
avgImbalance,
|
|
@@ -324,6 +714,10 @@ function run() {
|
|
|
324
714
|
const closes = candles.map((c: any) => c.close);
|
|
325
715
|
const strategies = loadAmaStrategies(cfg.resultsPath!);
|
|
326
716
|
|
|
717
|
+
if (!Number.isFinite(cfg.repositionPct) || cfg.repositionPct <= 0) {
|
|
718
|
+
throw new Error(`Invalid reposition threshold: ${cfg.repositionPct}`);
|
|
719
|
+
}
|
|
720
|
+
|
|
327
721
|
const totalCombos = cfg.spreadValues.length * cfg.incrementValues.length * cfg.ratioValues.length;
|
|
328
722
|
|
|
329
723
|
console.log('================================================================================');
|
|
@@ -334,9 +728,13 @@ function run() {
|
|
|
334
728
|
console.log(` Spread grid: ${cfg.spreadValues[0]}..${cfg.spreadValues[cfg.spreadValues.length - 1]}% (${cfg.spreadValues.length})`);
|
|
335
729
|
console.log(` Increment: ${cfg.incrementValues[0]}..${cfg.incrementValues[cfg.incrementValues.length - 1]}% (${cfg.incrementValues.length})`);
|
|
336
730
|
console.log(` Max/Min ratio:${cfg.ratioValues[0]}..${cfg.ratioValues[cfg.ratioValues.length - 1]} (${cfg.ratioValues.length})`);
|
|
337
|
-
console.log(` Active orders:${cfg.activeOrders} per side`);
|
|
731
|
+
console.log(` Active orders:${Number.isFinite(cfg.activeOrders) ? cfg.activeOrders : 'all'} per side (Infinity = every rail slot, matching production)`);
|
|
338
732
|
console.log(` Fee RT: ${cfg.feeRoundtripPct}%`);
|
|
339
733
|
console.log(` Spread floor: spread >= ${cfg.minSpreadFactor} x increment`);
|
|
734
|
+
console.log(` Reset (A): AMA drift >= ${cfg.repositionPct}% from recorded center${cfg.repositionPct === DEFAULT_REPOSITION_PCT ? ' (AMA_DELTA_THRESHOLD_PERCENT)' : ''}`);
|
|
735
|
+
console.log(` Asym. bounds: ${cfg.asymmetricBounds ? 'ON — slope reset (B) + grid price offset enabled (whitelist semantics)' : 'OFF — typical non-whitelisted bot (production default)'}`);
|
|
736
|
+
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]'}`);
|
|
737
|
+
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)}`);
|
|
340
738
|
console.log(` Risk W: duration=${cfg.riskWDuration}, peakOpen=${cfg.riskWPeakOpen}, imbalance=${cfg.riskWImbalance}, cancel=${cfg.riskWCancel}`);
|
|
341
739
|
console.log(` Combos/AMA: ${totalCombos}\n`);
|
|
342
740
|
|
|
@@ -344,18 +742,31 @@ function run() {
|
|
|
344
742
|
|
|
345
743
|
for (const s of strategies) {
|
|
346
744
|
const amaValues = calculateAMA(closes, { erPeriod: s.er, fastPeriod: s.fast, slowPeriod: s.slow });
|
|
745
|
+
// Production-aligned warmup: ER window + convergence (getAmaWarmupBars).
|
|
746
|
+
const warmupBars = getAmaWarmupBars(s.er, s.slow, 0, s.fast);
|
|
347
747
|
let best: any = null;
|
|
348
748
|
|
|
349
749
|
for (const spreadPct of cfg.spreadValues) {
|
|
350
750
|
for (const incrementPct of cfg.incrementValues) {
|
|
751
|
+
// Dedup guard only: computeGapSlots clamps the effective target
|
|
752
|
+
// spread up to increment × MIN_SPREAD_FACTOR, so combos below the
|
|
753
|
+
// floor would build an identical grid to the floored combo.
|
|
754
|
+
if (spreadPct + Number.EPSILON < (cfg.minSpreadFactor * incrementPct)) continue;
|
|
351
755
|
for (const maxMinRatio of cfg.ratioValues) {
|
|
352
|
-
if (spreadPct + Number.EPSILON < (cfg.minSpreadFactor * incrementPct)) continue;
|
|
353
756
|
const sim = simulateForParams(candles, amaValues, {
|
|
354
757
|
spreadPct,
|
|
355
758
|
incrementPct: incrementPct / 100,
|
|
356
759
|
maxMinRatio,
|
|
357
760
|
activeOrders: cfg.activeOrders,
|
|
358
761
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
762
|
+
repositionThresholdPct: cfg.repositionPct,
|
|
763
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
764
|
+
btsCreateFee: cfg.btsCreateFee,
|
|
765
|
+
btsCancelFee: cfg.btsCancelFee,
|
|
766
|
+
makerCreateFactor: cfg.makerCreateFactor,
|
|
767
|
+
txFeePrice: cfg.txFeePrice,
|
|
768
|
+
btsFeeCapital: cfg.btsFeeCapital,
|
|
769
|
+
warmupBars,
|
|
359
770
|
risk: {
|
|
360
771
|
duration: cfg.riskWDuration,
|
|
361
772
|
peakOpen: cfg.riskWPeakOpen,
|
|
@@ -373,8 +784,8 @@ function run() {
|
|
|
373
784
|
|
|
374
785
|
console.log('BEST PARAMS PER AMA');
|
|
375
786
|
console.log('--------------------------------------------------------------------------------');
|
|
376
|
-
console.log('AMA | spread | incr | ratio |
|
|
377
|
-
console.log('
|
|
787
|
+
console.log('AMA | spread | incr | ratio | cyc | fill% | net% | risk | score | inv-units (info)');
|
|
788
|
+
console.log('---------------------------------|--------|------|-------|-------|-------|--------|-------|-------|-----------------');
|
|
378
789
|
for (const row of byAma) {
|
|
379
790
|
const b = row.best;
|
|
380
791
|
if (!b) continue;
|
|
@@ -387,9 +798,11 @@ function run() {
|
|
|
387
798
|
`${fmt(b.fillEfficiency, 1).padStart(5)} | ` +
|
|
388
799
|
`${fmt(b.totalNetCapturePct, 1).padStart(6)} | ` +
|
|
389
800
|
`${fmt(b.riskPenalty, 1).padStart(5)} | ` +
|
|
390
|
-
`${fmt(b.score, 1).padStart(5)}`
|
|
801
|
+
`${fmt(b.score, 1).padStart(5)} | ` +
|
|
802
|
+
`${fmt(b.inventoryUnits, 0).padStart(8)} (${fmt(b.inventoryNetPts, 1)} pts)`
|
|
391
803
|
);
|
|
392
804
|
}
|
|
805
|
+
console.log('(* end-of-run inventory mark: informational only — excluded from scoring)');
|
|
393
806
|
console.log();
|
|
394
807
|
|
|
395
808
|
const outName = `bot_fitting_results_${path.basename(cfg.dataPath!, '.json')}.json`;
|
|
@@ -401,18 +814,34 @@ function run() {
|
|
|
401
814
|
dataPath: path.relative(process.cwd(), cfg.dataPath!),
|
|
402
815
|
resultsPath: path.relative(process.cwd(), cfg.resultsPath!),
|
|
403
816
|
candles: candles.length,
|
|
404
|
-
activeOrders: cfg.activeOrders,
|
|
817
|
+
activeOrders: Number.isFinite(cfg.activeOrders) ? cfg.activeOrders : 'all',
|
|
405
818
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
819
|
+
btsCreateFee: cfg.btsCreateFee,
|
|
820
|
+
btsCancelFee: cfg.btsCancelFee,
|
|
821
|
+
makerCreateFactor: cfg.makerCreateFactor,
|
|
822
|
+
txFeePrice: cfg.txFeePrice,
|
|
823
|
+
btsFeeCapital: cfg.btsFeeCapital,
|
|
406
824
|
search: {
|
|
407
825
|
spreadValues: cfg.spreadValues,
|
|
408
826
|
incrementValues: cfg.incrementValues,
|
|
409
827
|
ratioValues: cfg.ratioValues,
|
|
410
828
|
minSpreadFactor: cfg.minSpreadFactor,
|
|
829
|
+
repositionPct: cfg.repositionPct,
|
|
830
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
411
831
|
combosPerAma: totalCombos,
|
|
412
832
|
},
|
|
413
833
|
scoring: {
|
|
414
|
-
baseScore: '
|
|
415
|
-
|
|
834
|
+
baseScore: 'totalNetCaptureAfterFeesPct * (fillEfficiency / 100)',
|
|
835
|
+
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',
|
|
836
|
+
spreadParam: 'targetSpreadPercent for calculateGapSlots (floored at increment * MIN_SPREAD_FACTOR)',
|
|
837
|
+
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)'}`,
|
|
838
|
+
gridPriceOffset: cfg.asymmetricBounds ? 'slope-ratio offset applied to placement center (direction * min(|slope|/maxSlopePct,1) * targetSpread/2) on every grid build' : 'disabled (asymmetricBounds whitelist)',
|
|
839
|
+
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',
|
|
840
|
+
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)',
|
|
841
|
+
totalGrossCapturePct: 'sum of realized per-rotation gross from actual fixed prices (linked rotations + inventory sales)',
|
|
842
|
+
totalNetCapturePct: 'realized gross - roundtrip fee per completed disposition; excludes the end-of-run inventory mark',
|
|
843
|
+
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`,
|
|
844
|
+
warmup: 'getAmaWarmupBars(er, slow, 0, fast)',
|
|
416
845
|
riskPenalty: `avgOpenDurationBars*${cfg.riskWDuration} + peakOpenOrders*${cfg.riskWPeakOpen} + avgImbalance*${cfg.riskWImbalance} + canceledOnReposition*${cfg.riskWCancel}`,
|
|
417
846
|
finalScore: 'baseScore - riskPenalty',
|
|
418
847
|
},
|
|
@@ -423,4 +852,10 @@ function run() {
|
|
|
423
852
|
console.log(`Saved: ${path.relative(process.cwd(), outPath)}`);
|
|
424
853
|
}
|
|
425
854
|
|
|
426
|
-
|
|
855
|
+
// Main-thread entry guard: importing this module (e.g. from the logic tests)
|
|
856
|
+
// must not execute the CLI run.
|
|
857
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
858
|
+
run();
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
export { computeGapSlots, computeGridPriceOffsetPct, buildProductionGrid, simulateForParams };
|