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,35 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
1
2
|
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import os from 'node:os';
|
|
4
|
-
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
5
6
|
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
|
|
6
|
-
import { calculateAMA } from '../../market_adapter/core/strategies/ama.js';
|
|
7
|
+
import { calculateAMA, getAmaWarmupBars } from '../../market_adapter/core/strategies/ama.js';
|
|
8
|
+
import { computeAverageAmaSlopePct } from '../../market_adapter/core/strategies/ama_slope_model.js';
|
|
7
9
|
import { range } from '../math_utils.js';
|
|
8
10
|
import { parseListOrRange, loadLpData, fmt } from './shared_utils.js';
|
|
9
11
|
import { getStorage } from '../../modules/storage/index.js';
|
|
10
12
|
import { PATHS } from '../../modules/paths.js';
|
|
13
|
+
import { GRID_LIMITS, MARKET_ADAPTER } from '../../modules/constants.js';
|
|
14
|
+
// Production grid geometry + slope-ratio offset — shared with bot_fitting so
|
|
15
|
+
// both tools build byte-identical grids for identical params (#12).
|
|
16
|
+
import { buildProductionGrid, computeGridPriceOffsetPct } from './backtest_bot_fitting.js';
|
|
11
17
|
const { readJSON, writeJSON } = getStorage();
|
|
12
|
-
'use strict';
|
|
13
18
|
|
|
14
19
|
/**
|
|
15
20
|
* AMA SWEEP BACKTEST — persistent grid simulation
|
|
16
21
|
*
|
|
17
22
|
* Models the real bot mechanics:
|
|
18
23
|
* - Orders sit at FIXED chain prices until canceled or filled
|
|
19
|
-
* -
|
|
20
|
-
*
|
|
24
|
+
* - Slot rotation: a filled buy re-offers its base ONE RAIL STEP UP; when
|
|
25
|
+
* that refill sells, one increment (minus fees) is booked and the freed
|
|
26
|
+
* quote re-bids one rail step down — anchor-&-refill cycling
|
|
27
|
+
* - Unlinked (initial-grid) sells execute only against held inventory;
|
|
28
|
+
* bought-and-held base carries across resets as a weighted-average-entry
|
|
29
|
+
* position whose final mark is reported informationally, not scored
|
|
21
30
|
* - Order sizing depends on capital, ratio (range width), and weight profile
|
|
22
31
|
* - Three weight profiles: valley, neutral, mountain (symmetric buy/sell)
|
|
23
32
|
*
|
|
24
33
|
* Usage:
|
|
25
|
-
*
|
|
26
|
-
*
|
|
34
|
+
* node dist/analysis/bot_fitting/backtest_ama_sweep.js --data <path-to-lp-candles.json>
|
|
35
|
+
* node dist/analysis/bot_fitting/backtest_ama_sweep.js --data <path-to-lp-candles.json> --spread 4:16:1 --increment 0.5:4:0.25
|
|
27
36
|
*/
|
|
28
37
|
|
|
29
|
-
|
|
30
|
-
const DEFAULT_MAX_ORDERS = 20; // matches bot default activeOrders per side
|
|
38
|
+
const DEFAULT_MAX_ORDERS = 20; // weight-profile sizing cap per side (search abstraction)
|
|
31
39
|
const DEFAULT_FEE_ROUNDTRIP_PCT = 0.20;
|
|
32
|
-
|
|
40
|
+
// Canonical spread floor from production grid limits (modules/constants.ts).
|
|
41
|
+
const DEFAULT_MIN_SPREAD_FACTOR = GRID_LIMITS.MIN_SPREAD_FACTOR;
|
|
33
42
|
const DEFAULT_CAPITAL = 10000; // notional units per side
|
|
34
43
|
const DEFAULT_BTS_CREATE_FEE = 0.48260;
|
|
35
44
|
const DEFAULT_BTS_CANCEL_FEE = 0.00482;
|
|
@@ -47,13 +56,21 @@ const WEIGHT_PROFILES = {
|
|
|
47
56
|
};
|
|
48
57
|
|
|
49
58
|
// Search grid defaults — centered around bot defaults (spread=2%, increment=0.5%)
|
|
50
|
-
// Spread =
|
|
51
|
-
//
|
|
59
|
+
// Spread = targetSpreadPercent for the gapSlots spread zone (production
|
|
60
|
+
// semantics, matching bot_fitting — the legacy half-spread dead zone is gone).
|
|
61
|
+
// Increment = geometric rail step between successive orders on the same side.
|
|
52
62
|
const DEFAULT_SPREAD_VALUES = [...range(0.5, 4, 0.25), ...range(5, 12, 1)];
|
|
53
63
|
const DEFAULT_INCREMENT_VALUES = [...range(0.2, 2, 0.1), ...range(2.5, 8, 0.5)];
|
|
54
64
|
const DEFAULT_RATIO_VALUES = [1.05, 1.1, 1.15, 1.2, 1.3, 1.5, 2, 3, 5, 10];
|
|
55
|
-
// Reposition threshold:
|
|
56
|
-
|
|
65
|
+
// Reposition threshold: production default (MARKET_ADAPTER
|
|
66
|
+
// AMA_DELTA_THRESHOLD_PERCENT = 1%); --reposition overrides.
|
|
67
|
+
const DEFAULT_REPOSITION_PCT = MARKET_ADAPTER.AMA_DELTA_THRESHOLD_PERCENT;
|
|
68
|
+
|
|
69
|
+
// Trigger B / grid-price offset (asymmetricBounds whitelist) — same constants
|
|
70
|
+
// as bot_fitting, shared semantics with the live adapter.
|
|
71
|
+
const SLOPE_TRIGGER_FACTOR = MARKET_ADAPTER.AMA_SLOPE_DELTA_THRESHOLD_PERCENT;
|
|
72
|
+
const SLOPE_MAX_PCT = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_MAX_SLOPE_PCT;
|
|
73
|
+
const SLOPE_LOOKBACK_BARS = MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_LOOKBACK_BARS;
|
|
57
74
|
|
|
58
75
|
|
|
59
76
|
function parseArgs() {
|
|
@@ -69,6 +86,7 @@ function parseArgs() {
|
|
|
69
86
|
minSpreadFactor: number;
|
|
70
87
|
capital: number;
|
|
71
88
|
repositionPct: number;
|
|
89
|
+
asymmetricBounds: boolean;
|
|
72
90
|
btsCreateFee: number;
|
|
73
91
|
btsCancelFee: number;
|
|
74
92
|
makerCreateFactor: number;
|
|
@@ -85,6 +103,7 @@ function parseArgs() {
|
|
|
85
103
|
minSpreadFactor: DEFAULT_MIN_SPREAD_FACTOR,
|
|
86
104
|
capital: DEFAULT_CAPITAL,
|
|
87
105
|
repositionPct: DEFAULT_REPOSITION_PCT,
|
|
106
|
+
asymmetricBounds: false,
|
|
88
107
|
btsCreateFee: DEFAULT_BTS_CREATE_FEE,
|
|
89
108
|
btsCancelFee: DEFAULT_BTS_CANCEL_FEE,
|
|
90
109
|
makerCreateFactor: DEFAULT_BTS_MAKER_CREATE_FACTOR,
|
|
@@ -94,6 +113,7 @@ function parseArgs() {
|
|
|
94
113
|
|
|
95
114
|
for (let i = 0; i < args.length; i++) {
|
|
96
115
|
const arg = args[i];
|
|
116
|
+
if (arg === '--asymmetric-bounds') { out.asymmetricBounds = true; continue; }
|
|
97
117
|
const val = args[i + 1];
|
|
98
118
|
if (arg === '--help' || arg === '-h') { printHelp(); process.exit(0); }
|
|
99
119
|
if (!val) continue;
|
|
@@ -133,14 +153,15 @@ function printHelp() {
|
|
|
133
153
|
console.log('Options:');
|
|
134
154
|
console.log(' --data <path> LP candle JSON');
|
|
135
155
|
console.log(' --results <path> AMA optimizer results JSON');
|
|
136
|
-
console.log(' --spread <spec>
|
|
156
|
+
console.log(' --spread <spec> Target spread % (gapSlots zone): 1:10:0.5 or 2,4,8');
|
|
137
157
|
console.log(' --increment <spec> Increment values (%): 0.5:5:0.5 or 1,2,3');
|
|
138
158
|
console.log(' --ratio <spec> Max/min ratio: 1.5,2,3,5');
|
|
139
|
-
console.log(' --max-orders <n>
|
|
159
|
+
console.log(' --max-orders <n> Size cap per side (default: 20)');
|
|
140
160
|
console.log(' --fee <pct> Round-trip fee % (default: 0.20)');
|
|
141
161
|
console.log(' --min-spread-factor <n> Spread >= factor * increment (default: 2.1)');
|
|
142
162
|
console.log(' --capital <n> Notional capital per side (default: 10000)');
|
|
143
|
-
console.log(' --reposition <pct> AMA drift % to trigger re-center (default:
|
|
163
|
+
console.log(' --reposition <pct> AMA drift % to trigger re-center (default: 1.00, production)');
|
|
164
|
+
console.log(' --asymmetric-bounds Enable slope-delta reset (B) + grid price offset (whitelist semantics)');
|
|
144
165
|
console.log(' --bts-create-fee <n> BTS create fee (default: 0.48260)');
|
|
145
166
|
console.log(' --bts-cancel-fee <n> BTS cancel fee (default: 0.00482)');
|
|
146
167
|
console.log(' --maker-create-factor Maker share of create fee (default: 0.10)');
|
|
@@ -203,119 +224,135 @@ function allocateFundsByWeights(totalFunds: number, n: number, weight: number, i
|
|
|
203
224
|
// ── Persistent grid simulation ───────────────────────────────────────────────
|
|
204
225
|
|
|
205
226
|
/**
|
|
206
|
-
* Build a fresh grid centered at `center
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* So spread controls the dead zone around center (no orders within spread/2),
|
|
215
|
-
* and increment is the gap between successive orders on the same side.
|
|
227
|
+
* Build a fresh grid centered at `center` using the SHARED production
|
|
228
|
+
* geometry (buildProductionGrid from backtest_bot_fitting — createOrderGrid
|
|
229
|
+
* port): master rail at √(1±inc) offsets bounded by [center/ratio,
|
|
230
|
+
* center*ratio] with a calculateGapSlots spread zone. This guarantees the
|
|
231
|
+
* sweep and bot_fitting build byte-identical grids for identical params
|
|
232
|
+
* (#12). Weight-profile sizing is applied over the capped nearest-to-gap
|
|
233
|
+
* levels, index 0 = closest to the gap.
|
|
216
234
|
*
|
|
217
235
|
* Returns arrays of buy and sell order objects with fixed chain prices and sizes.
|
|
218
236
|
*/
|
|
219
237
|
function buildGrid(center: number, params: any, capitalPerSide: number, weightFactor: number) {
|
|
220
238
|
const { incrementPct, maxMinRatio, maxOrders, spreadPct } = params;
|
|
221
|
-
const
|
|
222
|
-
const maxBound = center * maxMinRatio;
|
|
223
|
-
const halfSpread = spreadPct / 200; // as fraction
|
|
224
|
-
|
|
225
|
-
const buys: any[] = [];
|
|
226
|
-
const sells: any[] = [];
|
|
239
|
+
const built = buildProductionGrid(center, spreadPct, incrementPct, maxMinRatio, maxOrders);
|
|
227
240
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const offset = halfSpread + (k - 1) * incrementPct;
|
|
231
|
-
if (offset >= 0.95) continue;
|
|
232
|
-
const buyPrice = center * (1 - offset);
|
|
233
|
-
const sellPrice = center * (1 + offset);
|
|
234
|
-
|
|
235
|
-
// Bounds check — skip levels outside ratio range
|
|
236
|
-
if (buyPrice < minBound || sellPrice > maxBound) continue;
|
|
237
|
-
|
|
238
|
-
buys.push({ level: k, price: buyPrice, filledBar: -1, size: 0 });
|
|
239
|
-
sells.push({ level: k, price: sellPrice, filledBar: -1, size: 0 });
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Size allocation — index 0 = closest to center
|
|
243
|
-
const buySizes = allocateFundsByWeights(capitalPerSide, buys.length, weightFactor, incrementPct);
|
|
244
|
-
const sellSizes = allocateFundsByWeights(capitalPerSide, sells.length, weightFactor, incrementPct);
|
|
245
|
-
buys.forEach((o, i) => { o.size = buySizes[i] || 0; });
|
|
246
|
-
sells.forEach((o, i) => { o.size = sellSizes[i] || 0; });
|
|
247
|
-
|
|
248
|
-
return { buys, sells };
|
|
249
|
-
}
|
|
241
|
+
const buySizes = allocateFundsByWeights(capitalPerSide, built.buys.length, weightFactor, incrementPct);
|
|
242
|
+
const sellSizes = allocateFundsByWeights(capitalPerSide, built.sells.length, weightFactor, incrementPct);
|
|
250
243
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (!Number.isFinite(order.size) || order.size <= 0) continue;
|
|
263
|
-
const grossPct = (exitPrice / order.price - 1) * 100;
|
|
264
|
-
const netPct = grossPct - feeRoundtripPct;
|
|
265
|
-
grossUnits += order.size * (grossPct / 100);
|
|
266
|
-
profitUnits += order.size * (netPct / 100);
|
|
267
|
-
closedOrders++;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
for (const order of openSells.values()) {
|
|
271
|
-
if (!order?.filled || !Number.isFinite(order.price) || order.price <= 0) continue;
|
|
272
|
-
if (!Number.isFinite(order.size) || order.size <= 0) continue;
|
|
273
|
-
const grossPct = (order.price / exitPrice - 1) * 100;
|
|
274
|
-
const netPct = grossPct - feeRoundtripPct;
|
|
275
|
-
grossUnits += order.size * (grossPct / 100);
|
|
276
|
-
profitUnits += order.size * (netPct / 100);
|
|
277
|
-
closedOrders++;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return { grossUnits, profitUnits, closedOrders };
|
|
244
|
+
// Level k = k-th slot from the gap on each side. Each placed slot also
|
|
245
|
+
// carries its MASTER-RAIL index so rotation hops land on adjacent rail
|
|
246
|
+
// nodes (live anchor-&-refill hop) instead of a flat ×(1+inc).
|
|
247
|
+
const buys: any[] = built.buys.map((price: number, i: number) => {
|
|
248
|
+
const k = built.buys.length - i;
|
|
249
|
+
return { level: k, price, railIdx: built.buySliceStart + i, cooldownUntil: -1, size: buySizes[k - 1] || 0 };
|
|
250
|
+
});
|
|
251
|
+
const sells: any[] = built.sells.map((price: number, i: number) => ({
|
|
252
|
+
level: i + 1, price, railIdx: built.sellStartIdx + i, cooldownUntil: -1, size: sellSizes[i] || 0,
|
|
253
|
+
}));
|
|
254
|
+
return { buys, sells, rail: built.rail };
|
|
281
255
|
}
|
|
282
256
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Mark the held inventory position to `markPrice` in capital units.
|
|
259
|
+
*
|
|
260
|
+
* Carried bags are a REAL risk the drawdown tracker should see bar-by-bar,
|
|
261
|
+
* but their mark is informational for scoring: realized rotation profit plus
|
|
262
|
+
* op fees drive netProfit, and the end-of-run position is reported separately
|
|
263
|
+
* instead of being dumped into totals.
|
|
264
|
+
*/
|
|
265
|
+
function markInventoryAtPrice(inventory: { units: number; cost: number }, exitPrice: number, feeRoundtripPct: number) {
|
|
266
|
+
if (!Number.isFinite(exitPrice) || exitPrice <= 0 || inventory.units <= 0) {
|
|
267
|
+
return { grossUnits: 0, profitUnits: 0 };
|
|
290
268
|
}
|
|
291
|
-
|
|
269
|
+
const avgEntry = inventory.cost / inventory.units;
|
|
270
|
+
const grossUnits = (exitPrice - avgEntry) * inventory.units;
|
|
271
|
+
const feeUnits = avgEntry * inventory.units * ((feeRoundtripPct / 2) / 100);
|
|
272
|
+
return { grossUnits, profitUnits: grossUnits - feeUnits };
|
|
292
273
|
}
|
|
293
274
|
|
|
294
275
|
function simulatePersistentGrid(candles: any[], amaValues: number[], params: any, weightName: string, weightFactor: number) {
|
|
295
|
-
const { spreadPct, incrementPct, maxMinRatio,
|
|
296
|
-
capital, repositionThreshold, btsCreateFee, btsCancelFee,
|
|
276
|
+
const { spreadPct, incrementPct, maxMinRatio, feeRoundtripPct,
|
|
277
|
+
capital, repositionThreshold, asymmetricBounds, btsCreateFee, btsCancelFee,
|
|
297
278
|
makerCreateFactor, txFeePrice } = params;
|
|
298
|
-
|
|
279
|
+
// Warmup follows production AMA seeding/convergence (getAmaWarmupBars,
|
|
280
|
+
// passed via params.warmupBars from sweepOneAma) instead of an arbitrary
|
|
281
|
+
// fraction of the dataset. Direct callers that omit warmupBars fall back
|
|
282
|
+
// to the legacy 10% cut.
|
|
283
|
+
const warmupParam = Number.isFinite(params.warmupBars)
|
|
284
|
+
? params.warmupBars
|
|
285
|
+
: Math.max(20, Math.floor(candles.length * 0.1));
|
|
286
|
+
const skip = Math.min(warmupParam, Math.max(0, candles.length - 2));
|
|
299
287
|
const capitalPerSide = capital;
|
|
288
|
+
const makerCreateFeeBts = btsCreateFee * makerCreateFactor;
|
|
289
|
+
const slopeDeltaThresholdPct = (SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT;
|
|
290
|
+
|
|
291
|
+
// First tradable bar: need a finite positive AMA to anchor the grid.
|
|
292
|
+
let startIdx = Math.min(skip, candles.length - 1);
|
|
293
|
+
let gridCenter = Number.NaN;
|
|
294
|
+
for (let j = startIdx; j < candles.length; j++) {
|
|
295
|
+
const v = amaValues[j];
|
|
296
|
+
if (Number.isFinite(v) && v > 0) { gridCenter = v; startIdx = j; break; }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Production AMA slope series (%/bar averaged over the lookback window) —
|
|
300
|
+
// feeds trigger B and the grid price offset when asymmetricBounds is on.
|
|
301
|
+
const slopeAt: (number | null)[] = new Array(candles.length).fill(null);
|
|
302
|
+
for (let j = SLOPE_LOOKBACK_BARS; j < candles.length; j++) {
|
|
303
|
+
const s = computeAverageAmaSlopePct(amaValues[j], amaValues[j - SLOPE_LOOKBACK_BARS], SLOPE_LOOKBACK_BARS);
|
|
304
|
+
if (s != null && Number.isFinite(s)) slopeAt[j] = s;
|
|
305
|
+
}
|
|
300
306
|
|
|
301
|
-
// State
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
// State — slot-rotation engine (mirrors simulateForParams in
|
|
308
|
+
// backtest_bot_fitting, with weight-profile sized orders):
|
|
309
|
+
// orders: id -> { side, price, size, linkedBuyPrice, linkedEntryBar,
|
|
310
|
+
// cooldownUntil }. linkedBuyPrice != null marks an armed
|
|
311
|
+
// refill sell created by a specific filled buy (one-increment rotation).
|
|
312
|
+
const orders = new Map<number, any>();
|
|
313
|
+
let nextOrderId = 0;
|
|
314
|
+
// Bought-and-held base across the whole run (weighted-average entry pool).
|
|
315
|
+
// Never negative — unfundable sells stay pending instead of shorting.
|
|
316
|
+
const inventory = { units: 0, cost: 0 };
|
|
317
|
+
const stepUpFrac = 1 + incrementPct; // one-rail-step rotation distance
|
|
318
|
+
|
|
319
|
+
let btsFeesBts = 0;
|
|
320
|
+
let offsetAppliedCount = 0;
|
|
321
|
+
// Master rail of the CURRENT epoch — rotation hops read adjacent nodes.
|
|
322
|
+
let activeRail: number[] = [];
|
|
323
|
+
|
|
324
|
+
const placeInitialGrid = (center: number, slopePct: number | null) => {
|
|
325
|
+
const offsetPct = (asymmetricBounds && slopePct != null)
|
|
326
|
+
? computeGridPriceOffsetPct(slopePct, spreadPct)
|
|
327
|
+
: 0;
|
|
328
|
+
if (offsetPct !== 0) offsetAppliedCount++;
|
|
329
|
+
const effCenter = center * (1 + offsetPct / 100);
|
|
330
|
+
const grid = buildGrid(effCenter, params, capitalPerSide, weightFactor);
|
|
331
|
+
activeRail = grid.rail;
|
|
332
|
+
orders.clear();
|
|
333
|
+
for (const o of grid.buys) {
|
|
334
|
+
orders.set(nextOrderId++, { side: 'buy', price: o.price, size: o.size, railIdx: o.railIdx, linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1 });
|
|
335
|
+
}
|
|
336
|
+
for (const o of grid.sells) {
|
|
337
|
+
orders.set(nextOrderId++, { side: 'sell', price: o.price, size: o.size, railIdx: o.railIdx, linkedBuyPrice: null, linkedEntryBar: -1, cooldownUntil: -1 });
|
|
338
|
+
}
|
|
339
|
+
btsFeesBts += (grid.buys.length + grid.sells.length) * makerCreateFeeBts;
|
|
340
|
+
};
|
|
305
341
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const openSells = new Map();
|
|
309
|
-
// Place initial orders
|
|
310
|
-
for (const o of grid.buys) openBuys.set(o.level, { price: o.price, size: o.size, bar: skip });
|
|
311
|
-
for (const o of grid.sells) openSells.set(o.level, { price: o.price, size: o.size, bar: skip });
|
|
342
|
+
if (Number.isFinite(gridCenter)) placeInitialGrid(gridCenter, slopeAt[startIdx]);
|
|
343
|
+
let lastRepositionBar = startIdx;
|
|
312
344
|
|
|
313
345
|
let matchedPairs = 0;
|
|
314
|
-
let
|
|
346
|
+
let cyclesTotal = 0;
|
|
347
|
+
let rotationCount = 0; // linked ping-pong rotations (buy → refill sell)
|
|
348
|
+
let inventorySaleCount = 0; // unlinked sells executed against held bags
|
|
349
|
+
let totalProfitUnits = 0; // REALIZED profit in capital units (size * netPct)
|
|
315
350
|
let totalGrossUnits = 0;
|
|
316
351
|
let touchedOrders = 0;
|
|
317
352
|
let canceledOnReposition = 0;
|
|
318
353
|
let repositionCount = 0;
|
|
354
|
+
let driftTriggerCount = 0;
|
|
355
|
+
let slopeTriggerCount = 0;
|
|
319
356
|
let peakOpenOrders = 0;
|
|
320
357
|
let imbalanceSum = 0;
|
|
321
358
|
let imbalanceSamples = 0;
|
|
@@ -329,22 +366,30 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
329
366
|
let runningProfit = 0;
|
|
330
367
|
let peakEquityProfit = 0;
|
|
331
368
|
let maxDrawdown = 0;
|
|
332
|
-
// Track inventory risk:
|
|
333
|
-
|
|
369
|
+
// Track inventory risk: bought-and-held base, carried across resets —
|
|
370
|
+
// resets never realize inventory (#4). Long-only (no unfunded shorts).
|
|
371
|
+
let inventoryExposure = 0; // held base units (long-only, ≥ 0)
|
|
334
372
|
let maxInventoryExposure = 0;
|
|
335
373
|
|
|
336
|
-
const
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
|
|
374
|
+
const invAvgEntry = () => (inventory.units > 0 ? inventory.cost / inventory.units : 0);
|
|
375
|
+
const liveBars = candles.length - startIdx - 1;
|
|
376
|
+
const ordersPerSide = [...orders.values()].filter((o) => o.side === 'buy').length;
|
|
377
|
+
|
|
378
|
+
// Slope-delta baseline: mirrors botState.gridRangeScalingAmaSlope —
|
|
379
|
+
// seeded at bootstrap and re-seeded on every reset.
|
|
380
|
+
let slopeBaseline: number | null = null;
|
|
381
|
+
for (let j = startIdx + 1; j < candles.length; j++) {
|
|
382
|
+
if (slopeAt[j] != null) { slopeBaseline = slopeAt[j]; break; }
|
|
383
|
+
}
|
|
340
384
|
|
|
341
|
-
for (let i =
|
|
385
|
+
for (let i = startIdx + 1; i < candles.length; i++) {
|
|
342
386
|
const ama = amaValues[i];
|
|
343
387
|
const hi = candles[i].high;
|
|
344
388
|
const lo = candles[i].low;
|
|
345
389
|
const gridAgeBars = i - lastRepositionBar;
|
|
346
390
|
|
|
347
|
-
// ── Reposition check:
|
|
391
|
+
// ── Reposition check: trigger A (AMA drift, ratchet) or trigger B
|
|
392
|
+
// (slope delta, only under the asymmetricBounds whitelist gate).
|
|
348
393
|
const drift = Math.abs(ama - gridCenter) / gridCenter;
|
|
349
394
|
const driftPct = drift * 100;
|
|
350
395
|
centerDriftSumPct += driftPct;
|
|
@@ -352,106 +397,151 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
352
397
|
gridAgeSumBars += gridAgeBars;
|
|
353
398
|
if (gridAgeBars > maxGridAgeBars) maxGridAgeBars = gridAgeBars;
|
|
354
399
|
if (drift >= repositionThreshold * 0.5) nearThresholdBars++;
|
|
355
|
-
if (drift >= repositionThreshold) {
|
|
356
|
-
triggerDriftSumPct += driftPct;
|
|
357
|
-
canceledOnReposition += countCancelableOrders(openBuys, openSells);
|
|
358
|
-
repositionCount++;
|
|
359
|
-
const exitPrice = Number.isFinite(ama) && ama > 0 ? ama : candles[i].close;
|
|
360
|
-
const forcedClose = closeFilledInventoryAtPrice(openBuys, openSells, exitPrice, feeRoundtripPct);
|
|
361
|
-
totalGrossUnits += forcedClose.grossUnits;
|
|
362
|
-
totalProfitUnits += forcedClose.profitUnits;
|
|
363
|
-
runningProfit += forcedClose.profitUnits;
|
|
364
|
-
// Unmatched inventory is realized on reposition (position closed at market)
|
|
365
|
-
inventoryExposure = 0;
|
|
366
|
-
openBuys.clear();
|
|
367
|
-
openSells.clear();
|
|
368
400
|
|
|
401
|
+
let shouldReposition = drift >= repositionThreshold;
|
|
402
|
+
if (shouldReposition) { triggerDriftSumPct += driftPct; driftTriggerCount++; }
|
|
403
|
+
if (!shouldReposition && asymmetricBounds && slopeBaseline != null && slopeAt[i] != null) {
|
|
404
|
+
const slopeDeltaPct = Math.abs(slopeAt[i]! - slopeBaseline);
|
|
405
|
+
if (slopeDeltaPct >= slopeDeltaThresholdPct) { shouldReposition = true; slopeTriggerCount++; }
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (shouldReposition && Number.isFinite(ama) && ama > 0) {
|
|
409
|
+
canceledOnReposition += orders.size;
|
|
410
|
+
btsFeesBts += orders.size * btsCancelFee;
|
|
411
|
+
orders.clear(); // inventory survives — resync never market-sells
|
|
412
|
+
repositionCount++;
|
|
369
413
|
// Re-center grid
|
|
370
414
|
gridCenter = ama;
|
|
371
|
-
|
|
415
|
+
if (slopeAt[i] != null) slopeBaseline = slopeAt[i];
|
|
416
|
+
placeInitialGrid(gridCenter, slopeAt[i]);
|
|
372
417
|
lastRepositionBar = i;
|
|
373
|
-
|
|
374
|
-
for (const o of grid.buys) openBuys.set(o.level, { price: o.price, size: o.size, bar: i });
|
|
375
|
-
for (const o of grid.sells) openSells.set(o.level, { price: o.price, size: o.size, bar: i });
|
|
376
418
|
}
|
|
377
419
|
|
|
378
420
|
// ── Track imbalance & peak ──────────────────────────────────────
|
|
379
|
-
const currentOpen =
|
|
421
|
+
const currentOpen = orders.size;
|
|
380
422
|
if (currentOpen > peakOpenOrders) peakOpenOrders = currentOpen;
|
|
381
|
-
|
|
423
|
+
let buyCountNow = 0;
|
|
424
|
+
for (const [, o] of orders) { if (o.side === 'buy') buyCountNow++; }
|
|
425
|
+
imbalanceSum += Math.abs(buyCountNow - (orders.size - buyCountNow));
|
|
382
426
|
imbalanceSamples++;
|
|
383
427
|
|
|
384
|
-
// ──
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
if (
|
|
391
|
-
filledBuysThisBar.push({ lvl, order });
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
for (const [lvl, order] of openSells) {
|
|
395
|
-
if (!order.filled && hi >= order.price) {
|
|
396
|
-
filledSellsThisBar.push({ lvl, order });
|
|
397
|
-
}
|
|
428
|
+
// ── Fill detection against FIXED chain prices ───────────────────
|
|
429
|
+
const filledBuysThisBar: { id: number; order: any }[] = [];
|
|
430
|
+
const filledSellsThisBar: { id: number; order: any }[] = [];
|
|
431
|
+
for (const [id, o] of orders) {
|
|
432
|
+
if (i < o.cooldownUntil || !(o.size > 0)) continue;
|
|
433
|
+
if (o.side === 'buy' && lo <= o.price) filledBuysThisBar.push({ id, order: o });
|
|
434
|
+
else if (o.side === 'sell' && hi >= o.price) filledSellsThisBar.push({ id, order: o });
|
|
398
435
|
}
|
|
436
|
+
touchedOrders += filledBuysThisBar.length + filledSellsThisBar.length;
|
|
437
|
+
// Base held BEFORE this bar's intakes — unlinked sells may only
|
|
438
|
+
// dispose against pre-existing funds (same-bar funding not assumed).
|
|
439
|
+
const disposablesAtBarStart = inventory.units;
|
|
399
440
|
|
|
400
|
-
//
|
|
441
|
+
// ── Buy intakes first: base enters the inventory pool, refill armed
|
|
442
|
+
// at the ADJACENT MASTER-RAIL NODE above (cooldown blocks same-bar).
|
|
401
443
|
for (const fb of filledBuysThisBar) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
444
|
+
orders.delete(fb.id);
|
|
445
|
+
inventory.units += fb.order.size;
|
|
446
|
+
inventory.cost += fb.order.price * fb.order.size;
|
|
447
|
+
const upIdx = (fb.order.railIdx ?? -1) + 1;
|
|
448
|
+
const refillPrice = activeRail[upIdx] ?? fb.order.price * stepUpFrac;
|
|
449
|
+
orders.set(nextOrderId++, {
|
|
450
|
+
side: 'sell',
|
|
451
|
+
price: refillPrice,
|
|
452
|
+
size: fb.order.size,
|
|
453
|
+
railIdx: upIdx,
|
|
454
|
+
linkedBuyPrice: fb.order.price,
|
|
455
|
+
linkedEntryBar: i,
|
|
456
|
+
cooldownUntil: i + 1,
|
|
457
|
+
});
|
|
458
|
+
btsFeesBts += makerCreateFeeBts;
|
|
406
459
|
}
|
|
407
460
|
|
|
408
|
-
//
|
|
461
|
+
// ── Sell disposals: linked refills book the one-rail-hop rotation;
|
|
462
|
+
// unlinked sells need held inventory. Linked resolve FIRST.
|
|
463
|
+
filledSellsThisBar.sort((a, b) => ((a.order.linkedBuyPrice != null ? 0 : 1) - (b.order.linkedBuyPrice != null ? 0 : 1)));
|
|
464
|
+
let disposables = disposablesAtBarStart;
|
|
409
465
|
for (const fs of filledSellsThisBar) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
466
|
+
const order = fs.order;
|
|
467
|
+
const size = order.size;
|
|
468
|
+
if (order.linkedBuyPrice != null) {
|
|
469
|
+
const grossPct = (order.price / order.linkedBuyPrice - 1) * 100;
|
|
470
|
+
const netPct = grossPct - feeRoundtripPct;
|
|
471
|
+
totalGrossUnits += size * (grossPct / 100);
|
|
472
|
+
totalProfitUnits += size * (netPct / 100);
|
|
473
|
+
runningProfit += size * (netPct / 100);
|
|
474
|
+
cyclesTotal++;
|
|
475
|
+
rotationCount++;
|
|
476
|
+
matchedPairs++;
|
|
477
|
+
matchedOpenDurationBars += Math.abs(i - order.linkedEntryBar);
|
|
478
|
+
// Dispose the base this rotation bought (at pool-average cost).
|
|
479
|
+
const applied = Math.min(size, inventory.units);
|
|
480
|
+
inventory.cost -= applied * invAvgEntry();
|
|
481
|
+
inventory.units -= applied;
|
|
482
|
+
// Its disposal also drains the pre-bar funding budget —
|
|
483
|
+
// otherwise later unlinked sales could overspend stock.
|
|
484
|
+
disposables -= applied;
|
|
485
|
+
// Freed quote re-bids the ADJACENT RAIL NODE below.
|
|
486
|
+
const downIdx = (order.railIdx ?? 0) - 1;
|
|
487
|
+
const rebidPrice = activeRail[downIdx] ?? order.price / stepUpFrac;
|
|
488
|
+
orders.delete(fs.id);
|
|
489
|
+
orders.set(nextOrderId++, {
|
|
490
|
+
side: 'buy',
|
|
491
|
+
price: rebidPrice,
|
|
492
|
+
size,
|
|
493
|
+
railIdx: downIdx,
|
|
494
|
+
linkedBuyPrice: null,
|
|
495
|
+
linkedEntryBar: -1,
|
|
496
|
+
cooldownUntil: i + 1,
|
|
497
|
+
});
|
|
498
|
+
btsFeesBts += makerCreateFeeBts;
|
|
499
|
+
} else if (disposables >= size - 1e-12) {
|
|
500
|
+
const avgEntry = invAvgEntry();
|
|
501
|
+
const grossPct = (order.price / avgEntry - 1) * 100;
|
|
502
|
+
const netPct = grossPct - feeRoundtripPct;
|
|
503
|
+
totalGrossUnits += size * (grossPct / 100);
|
|
504
|
+
totalProfitUnits += size * (netPct / 100);
|
|
505
|
+
runningProfit += size * (netPct / 100);
|
|
506
|
+
cyclesTotal++;
|
|
507
|
+
inventorySaleCount++;
|
|
508
|
+
matchedPairs++;
|
|
509
|
+
inventory.cost -= avgEntry * size;
|
|
510
|
+
inventory.units -= size;
|
|
511
|
+
disposables -= size;
|
|
512
|
+
orders.delete(fs.id); // sold bag is gone; slot not re-armed
|
|
513
|
+
} else {
|
|
514
|
+
// Unfundable (not enough base): stays open, retries next bar.
|
|
515
|
+
order.cooldownUntil = i + 1;
|
|
516
|
+
}
|
|
435
517
|
}
|
|
436
518
|
|
|
437
|
-
// Track max inventory exposure
|
|
438
|
-
|
|
439
|
-
if (absExposure > maxInventoryExposure) maxInventoryExposure = absExposure;
|
|
519
|
+
// Track max inventory exposure (long-only)
|
|
520
|
+
if (inventory.units > maxInventoryExposure) maxInventoryExposure = inventory.units;
|
|
440
521
|
|
|
441
522
|
// ── Drawdown tracking ───────────────────────────────────────────
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const equityProfit = runningProfit
|
|
523
|
+
// Realized equity only: carried bags are reported informationally and
|
|
524
|
+
// excluded from scoring, so their (unbounded, balance-free) marks must
|
|
525
|
+
// not distort the risk term either. Bag risk stays visible via
|
|
526
|
+
// finalInventoryUnits / finalInventoryMarkUnits.
|
|
527
|
+
const equityProfit = runningProfit;
|
|
447
528
|
if (equityProfit > peakEquityProfit) peakEquityProfit = equityProfit;
|
|
448
529
|
const dd = peakEquityProfit - equityProfit;
|
|
449
530
|
if (dd > maxDrawdown) maxDrawdown = dd;
|
|
450
531
|
}
|
|
451
532
|
|
|
452
|
-
|
|
533
|
+
// ── End-of-run inventory mark (informational, NOT in profit) ────────
|
|
534
|
+
// Bought-and-held base is real carried risk but unrealized bag marks are
|
|
535
|
+
// excluded from netProfit/scoring so trend combos can't dump phantom
|
|
536
|
+
// paper profit into the objective. Drawdown likewise tracks REALIZED
|
|
537
|
+
// equity only; bag risk stays visible through these info fields.
|
|
538
|
+
inventoryExposure = inventory.units;
|
|
539
|
+
const lastClose = candles.length > 0 ? candles[candles.length - 1].close : NaN;
|
|
540
|
+
const finalInventoryMark = markInventoryAtPrice(inventory, lastClose, feeRoundtripPct);
|
|
541
|
+
|
|
542
|
+
const fillEfficiency = touchedOrders > 0 ? (cyclesTotal / touchedOrders) * 100 : 0;
|
|
453
543
|
const pairsPerDay = liveBars > 0 ? matchedPairs / (liveBars / 24) : 0;
|
|
454
|
-
const avgOpenDurationBars =
|
|
544
|
+
const avgOpenDurationBars = rotationCount > 0 ? matchedOpenDurationBars / rotationCount : 0;
|
|
455
545
|
const avgImbalance = imbalanceSamples > 0 ? imbalanceSum / imbalanceSamples : 0;
|
|
456
546
|
const avgProfitPerPair = matchedPairs > 0 ? totalProfitUnits / matchedPairs : 0;
|
|
457
547
|
const profitPerCapital = capital > 0 ? totalProfitUnits / (capital * 2) : 0; // total capital = 2 sides
|
|
@@ -461,9 +551,11 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
461
551
|
const nearThresholdBarsPct = liveBars > 0 ? (nearThresholdBars / liveBars) * 100 : 0;
|
|
462
552
|
const avgTriggerDriftPct = repositionCount > 0 ? triggerDriftSumPct / repositionCount : 0;
|
|
463
553
|
const avgCancelOrdersPerReposition = repositionCount > 0 ? canceledOnReposition / repositionCount : 0;
|
|
464
|
-
|
|
465
|
-
|
|
554
|
+
// Exact BTS fee totals (creates + cancels + per-cycle refills), not an
|
|
555
|
+
// estimate — the live bot pays the same per-op fees.
|
|
556
|
+
const totalRepositionFeesBts = btsFeesBts;
|
|
466
557
|
const feePerDayBts = liveBars > 0 ? totalRepositionFeesBts / (liveBars / 24) : 0;
|
|
558
|
+
const estimatedFeePerRepositionBts = repositionCount > 0 ? totalRepositionFeesBts / repositionCount : 0;
|
|
467
559
|
const totalRepositionFeeUnits = totalRepositionFeesBts * txFeePrice;
|
|
468
560
|
const netProfitUnits = totalProfitUnits - totalRepositionFeeUnits;
|
|
469
561
|
const netProfitPerCapital = capital > 0 ? netProfitUnits / (capital * 2) : 0;
|
|
@@ -480,10 +572,16 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
480
572
|
incrementPct: incrementPct * 100, // store as %
|
|
481
573
|
maxMinRatio,
|
|
482
574
|
matchedPairs,
|
|
575
|
+
cyclesTotal,
|
|
576
|
+
rotationCount,
|
|
577
|
+
inventorySaleCount,
|
|
483
578
|
touchedOrders,
|
|
484
579
|
fillEfficiency,
|
|
485
580
|
totalProfitUnits,
|
|
486
581
|
totalGrossUnits,
|
|
582
|
+
finalInventoryUnits: inventoryExposure,
|
|
583
|
+
finalInventoryAvgEntry: inventory.units > 0 ? inventory.cost / inventory.units : 0,
|
|
584
|
+
finalInventoryMarkUnits: finalInventoryMark.profitUnits, // informational
|
|
487
585
|
profitPerCapital,
|
|
488
586
|
pairsPerDay,
|
|
489
587
|
avgOpenDurationBars,
|
|
@@ -492,6 +590,8 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
492
590
|
avgImbalance,
|
|
493
591
|
canceledOnReposition,
|
|
494
592
|
repositionCount,
|
|
593
|
+
driftTriggerCount,
|
|
594
|
+
slopeTriggerCount,
|
|
495
595
|
maxDrawdown,
|
|
496
596
|
maxDrawdownPct,
|
|
497
597
|
maxInventoryExposure,
|
|
@@ -501,6 +601,7 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
501
601
|
maxCenterDriftPct,
|
|
502
602
|
nearThresholdBarsPct,
|
|
503
603
|
avgTriggerDriftPct,
|
|
604
|
+
offsetAppliedCount,
|
|
504
605
|
makerCreateFeeBts,
|
|
505
606
|
btsCancelFee,
|
|
506
607
|
avgCancelOrdersPerReposition,
|
|
@@ -520,6 +621,8 @@ function simulatePersistentGrid(candles: any[], amaValues: number[], params: any
|
|
|
520
621
|
|
|
521
622
|
function sweepOneAma(strategy: any, candles: any[], closes: number[], weightEntries: [string, number][], cfg: any) {
|
|
522
623
|
const amaValues = calculateAMA(closes, { erPeriod: strategy.er, fastPeriod: strategy.fast, slowPeriod: strategy.slow });
|
|
624
|
+
// Production-aligned warmup: ER window + convergence (getAmaWarmupBars).
|
|
625
|
+
const warmupBars = getAmaWarmupBars(strategy.er, strategy.slow, 0, strategy.fast);
|
|
523
626
|
let best: any = null;
|
|
524
627
|
const top5: any[] = [];
|
|
525
628
|
const allSims: any[] = [];
|
|
@@ -541,10 +644,12 @@ function sweepOneAma(strategy: any, candles: any[], closes: number[], weightEntr
|
|
|
541
644
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
542
645
|
capital: cfg.capital,
|
|
543
646
|
repositionThreshold: cfg.repositionPct / 100,
|
|
647
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
544
648
|
btsCreateFee: cfg.btsCreateFee,
|
|
545
649
|
btsCancelFee: cfg.btsCancelFee,
|
|
546
650
|
makerCreateFactor: cfg.makerCreateFactor,
|
|
547
651
|
txFeePrice: cfg.txFeePrice,
|
|
652
|
+
warmupBars,
|
|
548
653
|
}, weightName, weightFactor);
|
|
549
654
|
|
|
550
655
|
if (!best || sim.score > best.score) best = sim;
|
|
@@ -573,8 +678,10 @@ function sweepOneAma(strategy: any, candles: any[], closes: number[], weightEntr
|
|
|
573
678
|
if (!isMainThread) {
|
|
574
679
|
const { strategy, candles, closes, weightEntries, cfg } = workerData;
|
|
575
680
|
const result = sweepOneAma(strategy, candles, closes, weightEntries, cfg);
|
|
576
|
-
|
|
577
|
-
process.exit(0)
|
|
681
|
+
parentPort!.postMessage(result);
|
|
682
|
+
// Exit naturally: an explicit process.exit(0) here can race the
|
|
683
|
+
// postMessage flush and silently drop the result (same pattern as
|
|
684
|
+
// optimizer_high_resolution.ts workers, which exit on their own).
|
|
578
685
|
}
|
|
579
686
|
|
|
580
687
|
// ── Parallel dispatch (main thread) ─────────────────────────────────────────
|
|
@@ -585,7 +692,9 @@ function runParallel(strategies: any[], candles: any[], closes: number[], weight
|
|
|
585
692
|
|
|
586
693
|
return Promise.all(strategies.map((strategy) => {
|
|
587
694
|
return new Promise((resolve, reject) => {
|
|
588
|
-
|
|
695
|
+
// ESM: resolve this module's path from import.meta.url
|
|
696
|
+
// (__filename is undefined in ES modules).
|
|
697
|
+
const worker = new Worker(fileURLToPath(import.meta.url), {
|
|
589
698
|
workerData: { strategy, candles, closes, weightEntries, cfg },
|
|
590
699
|
});
|
|
591
700
|
worker.on('message', resolve);
|
|
@@ -620,9 +729,11 @@ async function run() {
|
|
|
620
729
|
console.log(` Spread: ${cfg.spreadValues[0]}..${cfg.spreadValues[cfg.spreadValues.length - 1]}% (${cfg.spreadValues.length})`);
|
|
621
730
|
console.log(` Increment: ${cfg.incrementValues[0]}..${cfg.incrementValues[cfg.incrementValues.length - 1]}% (${cfg.incrementValues.length})`);
|
|
622
731
|
console.log(` Ratio: ${cfg.ratioValues[0]}..${cfg.ratioValues[cfg.ratioValues.length - 1]} (${cfg.ratioValues.length})`);
|
|
623
|
-
console.log(` Max orders: ${cfg.maxOrders}/side (
|
|
732
|
+
console.log(` Max orders: ${cfg.maxOrders}/side (size cap) | Capital: ${cfg.capital}/side | Fee: ${cfg.feeRoundtripPct}%`);
|
|
624
733
|
console.log(` Spread floor: > fee (${cfg.feeRoundtripPct}%)`);
|
|
625
|
-
console.log(`
|
|
734
|
+
console.log(` Reset (A): ${cfg.repositionPct}% AMA drift from grid center (ratchet)`);
|
|
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| >= ${fmt((SLOPE_TRIGGER_FACTOR / 100) * SLOPE_MAX_PCT, 4)}% (lookback ${SLOPE_LOOKBACK_BARS})${cfg.asymmetricBounds ? '' : ' [gated off]'}`);
|
|
626
737
|
console.log(` Tx model: create=${fmt(cfg.btsCreateFee, 5)} BTS, cancel=${fmt(cfg.btsCancelFee, 5)} BTS, maker=${fmt(cfg.makerCreateFactor * 100, 1)}%, 1 BTS=${fmt(cfg.txFeePrice, 2)} units`);
|
|
627
738
|
console.log(` Combos/AMA: ${totalCombos} | Total: ${totalCombos * strategies.length}\n`);
|
|
628
739
|
|
|
@@ -755,7 +866,9 @@ async function run() {
|
|
|
755
866
|
console.log(` Repositions: ${winner.sim.repositionCount}`);
|
|
756
867
|
console.log(` Grid age: avg ${fmt(winner.sim.avgGridAgeBars, 1)} bars | max ${fmt(winner.sim.maxGridAgeBars, 0)} bars`);
|
|
757
868
|
console.log(` Drift: avg ${fmt(winner.sim.avgCenterDriftPct, 2)}% | max ${fmt(winner.sim.maxCenterDriftPct, 2)}% | near-threshold ${fmt(winner.sim.nearThresholdBarsPct, 1)}%`);
|
|
758
|
-
console.log(` Tx burn: ${fmt(winner.sim.estimatedFeePerRepositionBts, 4)} BTS/reposition | ${fmt(winner.sim.feePerDayBts, 2)} BTS/day`);
|
|
869
|
+
console.log(` Tx burn: ${fmt(winner.sim.estimatedFeePerRepositionBts, 4)} BTS/reposition | ${fmt(winner.sim.feePerDayBts, 2)} BTS/day (exact per-op totals)`);
|
|
870
|
+
console.log(` Cycles: ${winner.sim.cyclesTotal} rotations (${winner.sim.rotationCount} rail-step + ${winner.sim.inventorySaleCount} inventory sales)`);
|
|
871
|
+
console.log(` Carried: ${fmt(winner.sim.finalInventoryUnits, 4)} base @ ${fmt(winner.sim.finalInventoryAvgEntry, 6)} avg (mark ${fmt(winner.sim.finalInventoryMarkUnits, 2)} units — info only, not scored)`);
|
|
759
872
|
console.log(` Score: ${fmt(winner.sim.score, 2)}`);
|
|
760
873
|
|
|
761
874
|
// ── Save JSON ───────────────────────────────────────────────────────────
|
|
@@ -772,6 +885,7 @@ async function run() {
|
|
|
772
885
|
capitalPerSide: cfg.capital,
|
|
773
886
|
feeRoundtripPct: cfg.feeRoundtripPct,
|
|
774
887
|
repositionPct: cfg.repositionPct,
|
|
888
|
+
asymmetricBounds: cfg.asymmetricBounds,
|
|
775
889
|
btsCreateFee: cfg.btsCreateFee,
|
|
776
890
|
btsCancelFee: cfg.btsCancelFee,
|
|
777
891
|
makerCreateFactor: cfg.makerCreateFactor,
|
|
@@ -786,6 +900,7 @@ async function run() {
|
|
|
786
900
|
totalCombos: totalCombos * strategies.length,
|
|
787
901
|
},
|
|
788
902
|
scoring: 'netProfitPerCapital * 100 * log10(max(1, matchedPairs)) - maxDrawdownPct * 0.5',
|
|
903
|
+
gridModel: 'production createOrderGrid port (shared with bot_fitting): master rail sqrt(1±inc) + gapSlots spread zone; slot rotation (filled buy re-offers one rail step up, freed quote re-bids one step down, ~increment% per completed rotation); unlinked sells execute only against held inventory at weighted-average entry; bought base carries across resets and the end-of-run inventory mark is informational (excluded from scoring); exact per-op BTS fees',
|
|
789
904
|
},
|
|
790
905
|
strategies,
|
|
791
906
|
perAma: byAma.map((row) => ({
|
|
@@ -809,9 +924,11 @@ async function run() {
|
|
|
809
924
|
console.log(`\nSaved: ${path.relative(process.cwd(), outPath)}`);
|
|
810
925
|
}
|
|
811
926
|
|
|
812
|
-
|
|
927
|
+
// Main-thread only: workers inherit process.argv[1], so the entry guard alone
|
|
928
|
+
// would also match inside workers and re-run main() there.
|
|
929
|
+
if (isMainThread && process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
813
930
|
run().catch((err) => { console.error(err); process.exit(1); });
|
|
814
931
|
}
|
|
815
932
|
|
|
816
|
-
export { WEIGHT_PROFILES, allocateFundsByWeights, buildGrid,
|
|
933
|
+
export { WEIGHT_PROFILES, allocateFundsByWeights, buildGrid, markInventoryAtPrice, simulatePersistentGrid, sweepOneAma }
|
|
817
934
|
|