dexbot 1.4.19 → 1.4.21
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 +36 -0
- package/README.md +22 -12
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -2
- package/analysis/ama_fitting/calibrate_convergence_er.ts +1 -1
- package/analysis/ama_fitting/optimizer_high_resolution.ts +2 -1
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/analyze_derivatives.ts +4 -2
- package/analysis/analyze_dynamic_weight.ts +3 -1
- package/analysis/analyze_kalman.ts +3 -1
- package/analysis/analyze_regime.ts +3 -1
- package/analysis/analyze_regime_windows.ts +3 -1
- package/analysis/analyze_volatility.ts +2 -2
- package/analysis/bot_fitting/backtest_ama_sweep.ts +2 -1
- package/analysis/bot_fitting/backtest_bot_fitting.ts +17 -12
- package/analysis/bot_fitting/shared_utils.ts +1 -1
- package/analysis/bot_key_utils.ts +1 -5
- package/analysis/bot_usage/kibana_bot_queries.ts +1 -256
- package/analysis/chart_css.ts +1 -1
- package/analysis/chart_utils.ts +24 -0
- package/analysis/derivative_chart_generator.ts +3 -2
- package/analysis/math_utils.ts +1 -8
- package/analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md +1 -1
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +91 -55
- package/analysis/trend_detection/package.json +1 -1
- package/claw/ecosystem.config.cjs +2 -3
- package/claw/examples/claw_profiles_example.ts +4 -1
- package/claw/examples/memu_integration_example.ts +17 -17
- package/claw/modules/chain_actions.ts +51 -54
- package/claw/modules/chain_broadcast.ts +66 -104
- package/claw/modules/claw_bridge.ts +60 -80
- package/claw/modules/claw_catalog.ts +48 -17
- package/claw/modules/claw_infra.ts +1 -5
- package/claw/modules/claw_launcher.ts +47 -49
- package/claw/modules/claw_skill_md.ts +14 -16
- package/claw/modules/credit_runtime_adapter.ts +2 -18
- package/claw/modules/decision_loop.ts +4 -0
- package/claw/modules/dexbot_bridge.ts +1 -1
- package/claw/modules/dexbot_profiles.ts +8 -22
- package/claw/modules/honest_ecosystem.ts +24 -8
- package/claw/modules/launcher_paths.ts +4 -2
- package/claw/modules/liquidity_pools.ts +10 -3
- package/claw/modules/mcp_utils.ts +109 -0
- package/claw/modules/memu_bridge.ts +76 -54
- package/claw/modules/mpa_utils.ts +26 -3
- package/claw/modules/position_discovery.ts +16 -27
- package/claw/modules/position_manager.ts +32 -41
- package/claw/modules/position_manager_watch.ts +3 -2
- package/claw/modules/short_mpa_strategy.ts +1 -9
- package/claw/modules/skill_utils.ts +5 -3
- package/claw/modules/utils.ts +9 -1
- package/claw/package.json +1 -1
- package/claw/runtimes/openclaw-plugin/index.ts +27 -10
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/scripts/claw_bridge.ts +1 -1
- package/claw/scripts/claw_mcp_server.ts +19 -78
- package/claw/scripts/honest_assets_report.ts +19 -84
- package/claw/scripts/memu_mcp_server.ts +57 -155
- package/claw/tests/test_claw_bridge.ts +6 -2
- package/claw/tests/test_claw_mcp_transport.ts +2 -2
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -2
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js +1 -1
- package/dist/analysis/ama_fitting/calibrate_convergence_er.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 +2 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js.map +1 -1
- package/dist/analysis/analyze_derivatives.d.ts.map +1 -1
- package/dist/analysis/analyze_derivatives.js +4 -2
- package/dist/analysis/analyze_derivatives.js.map +1 -1
- package/dist/analysis/analyze_dynamic_weight.js +3 -1
- package/dist/analysis/analyze_dynamic_weight.js.map +1 -1
- package/dist/analysis/analyze_kalman.js +3 -1
- package/dist/analysis/analyze_kalman.js.map +1 -1
- package/dist/analysis/analyze_regime.js +3 -1
- package/dist/analysis/analyze_regime.js.map +1 -1
- package/dist/analysis/analyze_regime_windows.js +3 -1
- package/dist/analysis/analyze_regime_windows.js.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.map +1 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js +2 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js.map +1 -1
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js +18 -13
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.d.ts +1 -12
- package/dist/analysis/bot_fitting/shared_utils.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.js +1 -1
- package/dist/analysis/bot_fitting/shared_utils.js.map +1 -1
- package/dist/analysis/bot_key_utils.d.ts +1 -1
- package/dist/analysis/bot_key_utils.d.ts.map +1 -1
- package/dist/analysis/bot_key_utils.js +1 -5
- package/dist/analysis/bot_key_utils.js.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -337
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -241
- package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
- package/dist/analysis/chart_css.d.ts +1 -15
- package/dist/analysis/chart_css.d.ts.map +1 -1
- package/dist/analysis/chart_css.js +1 -1
- package/dist/analysis/chart_css.js.map +1 -1
- package/dist/analysis/chart_utils.d.ts +0 -3
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +25 -0
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +3 -2
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/math_utils.d.ts +3 -5
- package/dist/analysis/math_utils.d.ts.map +1 -1
- package/dist/analysis/math_utils.js +3 -5
- package/dist/analysis/math_utils.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 +82 -50
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/bot.js +2 -2
- package/dist/bot.js.map +1 -1
- package/dist/credential-daemon.js +1 -1
- package/dist/credential-daemon.js.map +1 -1
- package/dist/dexbot.d.ts.map +1 -1
- package/dist/dexbot.js +20 -17
- package/dist/dexbot.js.map +1 -1
- package/dist/market_adapter/ama_signal_runner.js +3 -3
- package/dist/market_adapter/core/kibana_client.d.ts +1 -3
- package/dist/market_adapter/core/kibana_client.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_client.js +1 -1
- package/dist/market_adapter/core/kibana_client.js.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.d.ts +1 -2
- package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.js +9 -4
- package/dist/market_adapter/core/market_adapter_service.js.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.d.ts +1 -2
- package/dist/market_adapter/core/strategies/regime_gate.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.js +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +2 -2
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts +5 -5
- package/dist/market_adapter/inputs/fetch_lp_data.js +5 -5
- package/dist/market_adapter/inputs/kibana_source.d.ts +1 -2
- package/dist/market_adapter/inputs/kibana_source.d.ts.map +1 -1
- package/dist/market_adapter/inputs/kibana_source.js +1 -1
- package/dist/market_adapter/inputs/kibana_source.js.map +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts +1 -2
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.js +4 -4
- package/dist/market_adapter/lp_chart_strategy_loader.js.map +1 -1
- package/dist/market_adapter/market_adapter.d.ts.map +1 -1
- package/dist/market_adapter/market_adapter.js +2 -1
- package/dist/market_adapter/market_adapter.js.map +1 -1
- package/dist/modules/account_bots.d.ts +3 -0
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +156 -46
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/account_orders.d.ts +1 -7
- package/dist/modules/account_orders.d.ts.map +1 -1
- package/dist/modules/account_orders.js +9 -17
- package/dist/modules/account_orders.js.map +1 -1
- package/dist/modules/bitshares_client.d.ts +2 -14
- package/dist/modules/bitshares_client.d.ts.map +1 -1
- package/dist/modules/bitshares_client.js +22 -31
- package/dist/modules/bitshares_client.js.map +1 -1
- package/dist/modules/bot_settings.js +1 -1
- package/dist/modules/bot_settings.js.map +1 -1
- package/dist/modules/chain_keys.js +2 -2
- package/dist/modules/chain_keys.js.map +1 -1
- package/dist/modules/chain_orders.d.ts +2 -3
- package/dist/modules/chain_orders.d.ts.map +1 -1
- package/dist/modules/chain_orders.js +8 -25
- package/dist/modules/chain_orders.js.map +1 -1
- package/dist/modules/config.d.ts +2 -0
- package/dist/modules/config.d.ts.map +1 -1
- package/dist/modules/config.js +6 -1
- package/dist/modules/config.js.map +1 -1
- package/dist/modules/constants.d.ts +0 -1
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +1 -5
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credential_policy.js +1 -1
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +3 -2
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +0 -7
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +95 -0
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +22 -2
- 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 +5 -2
- package/dist/modules/fund_registry.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +6 -7
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +6 -0
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +2 -3
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +7 -15
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +1 -0
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/status_reporting.d.ts +1 -2
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -4
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/order/accounting.js +2 -2
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/format.d.ts +0 -8
- package/dist/modules/order/format.d.ts.map +1 -1
- package/dist/modules/order/format.js +0 -8
- package/dist/modules/order/format.js.map +1 -1
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +146 -32
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/logger.js +1 -1
- package/dist/modules/order/logger.js.map +1 -1
- package/dist/modules/order/logger_state.d.ts +1 -13
- package/dist/modules/order/logger_state.d.ts.map +1 -1
- package/dist/modules/order/logger_state.js +1 -11
- package/dist/modules/order/logger_state.js.map +1 -1
- package/dist/modules/order/manager.d.ts +13 -0
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +75 -2
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/processed_fill_store.d.ts +0 -5
- package/dist/modules/order/processed_fill_store.d.ts.map +1 -1
- package/dist/modules/order/processed_fill_store.js +1 -12
- package/dist/modules/order/processed_fill_store.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +10 -3
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +80 -1
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +138 -2
- 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 +10 -2
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/paths.d.ts +26 -1
- package/dist/modules/paths.d.ts.map +1 -1
- package/dist/modules/paths.js +39 -6
- package/dist/modules/paths.js.map +1 -1
- package/dist/modules/runtime_settings.js +3 -1
- package/dist/modules/runtime_settings.js.map +1 -1
- package/dist/modules/settings_merge.d.ts.map +1 -1
- package/dist/modules/settings_merge.js +3 -1
- package/dist/modules/settings_merge.js.map +1 -1
- package/dist/modules/storage/browser_adapter.d.ts +8 -3
- package/dist/modules/storage/browser_adapter.d.ts.map +1 -1
- package/dist/modules/storage/browser_adapter.js +53 -4
- package/dist/modules/storage/browser_adapter.js.map +1 -1
- package/dist/modules/utils/sanitize_key.d.ts +7 -0
- package/dist/modules/utils/sanitize_key.d.ts.map +1 -0
- package/dist/modules/utils/sanitize_key.js +15 -0
- package/dist/modules/utils/sanitize_key.js.map +1 -0
- package/dist/pm2.js +6 -6
- package/dist/pm2.js.map +1 -1
- package/dist/scripts/analyze-git.js +2 -1
- package/dist/scripts/analyze-git.js.map +1 -1
- package/dist/scripts/analyze-orders.d.ts +2 -2
- package/dist/scripts/analyze-orders.d.ts.map +1 -1
- package/dist/scripts/analyze-orders.js +6 -14
- package/dist/scripts/analyze-orders.js.map +1 -1
- package/dist/scripts/runner.js +1 -1
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/update.js +1 -1
- package/dist/scripts/update.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +63 -18
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +5 -14
- package/docs/COW_INVARIANTS.md +4 -4
- package/docs/CREDENTIAL_SECURITY.md +0 -11
- package/docs/DEXBOT_COMPARISON.md +11 -11
- package/docs/EVOLUTION.md +12 -10
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +27 -83
- package/docs/GRID_RECALCULATION.md +1 -13
- package/docs/GRID_RECONCILE.md +24 -24
- package/docs/LIFECYCLE.md +4 -4
- package/docs/LOGGING.md +1 -1
- package/docs/MPA_CREDIT_USAGE.md +3 -3
- package/docs/README.md +2 -2
- package/docs/WORKFLOW.md +2 -2
- package/docs/architecture.md +43 -38
- package/docs/developer_guide.md +16 -18
- package/market_adapter/README.md +0 -2
- package/modules/README.md +2 -1
- package/package.json +2 -3
- package/scripts/README.md +1 -1
- package/scripts/lib/dexbot-paths.sh +20 -11
- package/claw/openclaw.plugin.json +0 -13
- package/dist/market_adapter/merge_lp_data.d.ts +0 -3
- package/dist/market_adapter/merge_lp_data.d.ts.map +0 -1
- package/dist/market_adapter/merge_lp_data.js +0 -125
- package/dist/market_adapter/merge_lp_data.js.map +0 -1
- package/dist/market_adapter/utils/paths.d.ts +0 -3
- package/dist/market_adapter/utils/paths.d.ts.map +0 -1
- package/dist/market_adapter/utils/paths.js +0 -5
- package/dist/market_adapter/utils/paths.js.map +0 -1
|
@@ -111,7 +111,7 @@ function _snapshotFundState(manager) {
|
|
|
111
111
|
sellLocked: Number(manager.accountTotals?.sellLocked || 0),
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
-
import { floatToBlockchainInt, getPrecisionByOrderType, getPrecisionsForManager, calculateOrderCreationFees, calculateOrderSizes, calculateRotationOrderSizes, calculateAvailableFundsValue, calculateGridSideDivergenceMetric, getPrecisionSlack, getMinOrderSize, getSingleDustThreshold, getGridBestPrices, calculateSpreadFromOrders, allocateFundsByWeights, calculateGapSlots as _mathGapSlots, findPriceCollision, getBtsSide, getSellStartIdx, resolveGapBand, countGapBandSpread, adjustBudgetForBtsFees, clamp, } from './utils/math.js';
|
|
114
|
+
import { floatToBlockchainInt, getPrecisionByOrderType, getPrecisionsForManager, calculateOrderCreationFees, calculateOrderSizes, calculateRotationOrderSizes, calculateAvailableFundsValue, calculateGridSideDivergenceMetric, getPrecisionSlack, getMinOrderSize, getSingleDustThreshold, getGridBestPrices, calculateSpreadFromOrders, allocateFundsByWeights, calculateGapSlots as _mathGapSlots, findPriceCollision, getBtsSide, getSellStartIdx, resolveGapBand, countGapBandSpread, validatePersistedBoundary, adjustBudgetForBtsFees, clamp, } from './utils/math.js';
|
|
115
115
|
import { filterOrdersByType, checkSizesBeforeMinimum, checkSizeThreshold, resolveConfiguredPriceBound, shouldFlagOutOfSpread, isOrderHealthy, isPhantomOrder, isSlotAvailable, isOrderOnChain, isOrderPlaced, hasOnChainId, isEmptyGridSlot, parseSlotIndex, calculateIdealBoundary, assignGridRoles, resolveOnChainRetypeType } from './utils/order.js';
|
|
116
116
|
import { loadAmaCenterPrice, loadAmaCenterSnapshot, withBlockchainRetry } from './utils/system.js';
|
|
117
117
|
import { derivePriceWithPoolRef } from './utils/withPoolRef.js';
|
|
@@ -468,10 +468,57 @@ export async function loadGrid(manager, grid, boundaryIdx = null) {
|
|
|
468
468
|
await manager.resetFunds();
|
|
469
469
|
manager.funds.btsFeesOwed = savedBtsFeesOwed;
|
|
470
470
|
});
|
|
471
|
+
// RESTORE-TIME BOUNDARY GATE: a persisted boundary is untrusted
|
|
472
|
+
// disk state. Any writer bug that committed AND persisted an
|
|
473
|
+
// overrun boundary (e.g. the pre-5eb3ca7 promotion path) would
|
|
474
|
+
// otherwise legalize itself on every restart: resolveGapBand
|
|
475
|
+
// re-derives sellStartIdx from whatever value is restored, and
|
|
476
|
+
// none of the runtime gates (commit gate, detectors) run before
|
|
477
|
+
// this point. Validate against the snapshot BEFORE restoring;
|
|
478
|
+
// on failure attempt to repair by re-deriving the structural
|
|
479
|
+
// center boundary from slot prices, falling back to "no boundary"
|
|
480
|
+
// (callers sync against chain right after load either way).
|
|
481
|
+
const loadGapSlots = calculateGapSlots(manager.config?.incrementPercent, manager.config?.targetSpreadPercent, manager.config?.gridLimits);
|
|
482
|
+
let restoredBoundary = typeof boundaryIdx === 'number' ? boundaryIdx : null;
|
|
483
|
+
if (restoredBoundary !== null) {
|
|
484
|
+
const check = validatePersistedBoundary(restoredBoundary, grid, loadGapSlots);
|
|
485
|
+
if (!check.ok) {
|
|
486
|
+
manager.logger?.log?.(`[GRID-LOAD] Persisted boundary rejected (${check.reason}): ${check.detail}. ` +
|
|
487
|
+
`Attempting re-derivation from slot prices.`, 'error');
|
|
488
|
+
restoredBoundary = null;
|
|
489
|
+
const startPrice = Number(manager.config?.startPrice);
|
|
490
|
+
if (Number.isFinite(startPrice) && Array.isArray(grid) && grid.length > 0) {
|
|
491
|
+
const priceSorted = [...grid].sort((a, b) => Number(a.price) - Number(b.price));
|
|
492
|
+
const derived = calculateIdealBoundary(priceSorted.map((s) => ({ price: s.price })), startPrice, loadGapSlots);
|
|
493
|
+
if (Number.isInteger(derived) && derived >= 0
|
|
494
|
+
&& validatePersistedBoundary(derived, priceSorted, loadGapSlots).ok) {
|
|
495
|
+
// boundaryIdx indexes the STORED array ordering, not
|
|
496
|
+
// the price-sorted copy — map the anchor slot back
|
|
497
|
+
// so the repair stays correct even if a snapshot is
|
|
498
|
+
// not price-sorted (the honest-load path assumes it;
|
|
499
|
+
// the repair path must not inherit that silently).
|
|
500
|
+
const anchorSlot = priceSorted[derived];
|
|
501
|
+
let mappedIdx = grid.indexOf(anchorSlot);
|
|
502
|
+
if (mappedIdx === -1 && anchorSlot?.id != null) {
|
|
503
|
+
mappedIdx = grid.findIndex((s) => s && s.id === anchorSlot.id);
|
|
504
|
+
}
|
|
505
|
+
if (mappedIdx >= 0) {
|
|
506
|
+
restoredBoundary = mappedIdx;
|
|
507
|
+
manager.logger?.log?.(`[GRID-LOAD] Persisted boundary repaired: ${boundaryIdx} -> ${mappedIdx} ` +
|
|
508
|
+
`(re-derived from slot prices, sorted idx ${derived}).`, 'warn');
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (restoredBoundary === null) {
|
|
513
|
+
manager.logger?.log?.(`[GRID-LOAD] Could not re-derive a safe boundary; continuing without one. ` +
|
|
514
|
+
`The next sync cycle will reconcile grid geometry against the chain.`, 'error');
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
471
518
|
// Restore boundary index for StrategyEngine
|
|
472
|
-
if (
|
|
473
|
-
manager._restoreBoundary(
|
|
474
|
-
manager.logger?.log?.(`Restored boundary index: ${
|
|
519
|
+
if (restoredBoundary !== null) {
|
|
520
|
+
manager._restoreBoundary(restoredBoundary);
|
|
521
|
+
manager.logger?.log?.(`Restored boundary index: ${restoredBoundary}`, 'info');
|
|
475
522
|
}
|
|
476
523
|
// Reassign slot types based on current boundary.
|
|
477
524
|
// Every slot's type must match its position in the price-sorted rail
|
|
@@ -479,11 +526,11 @@ export async function loadGrid(manager, grid, boundaryIdx = null) {
|
|
|
479
526
|
// split spread zones and ILLEGAL_SPREAD_STATE errors. The subsequent
|
|
480
527
|
// sync will detect type mismatches with chain orders (e.g. a BUY-zone
|
|
481
528
|
// slot holding a SELL chain order) and auto-cancel + recreate them.
|
|
482
|
-
if (
|
|
483
|
-
const gapSlots =
|
|
529
|
+
if (restoredBoundary !== null) {
|
|
530
|
+
const gapSlots = loadGapSlots;
|
|
484
531
|
manager._gapSlots = gapSlots;
|
|
485
|
-
const buyEndIdx =
|
|
486
|
-
const sellStartIdx = getSellStartIdx(
|
|
532
|
+
const buyEndIdx = restoredBoundary;
|
|
533
|
+
const sellStartIdx = getSellStartIdx(restoredBoundary, gapSlots);
|
|
487
534
|
let reassignCount = 0;
|
|
488
535
|
grid = grid.map((slot, i) => {
|
|
489
536
|
const correctType = (i <= buyEndIdx)
|
|
@@ -535,7 +582,7 @@ export async function loadGrid(manager, grid, boundaryIdx = null) {
|
|
|
535
582
|
return slot;
|
|
536
583
|
});
|
|
537
584
|
if (reassignCount > 0) {
|
|
538
|
-
manager.logger?.log?.(`[GRID-TYPE-CORRECT] Reassigned ${reassignCount} stale slot type(s) based on boundary ${
|
|
585
|
+
manager.logger?.log?.(`[GRID-TYPE-CORRECT] Reassigned ${reassignCount} stale slot type(s) based on boundary ${restoredBoundary}`, 'warn');
|
|
539
586
|
}
|
|
540
587
|
}
|
|
541
588
|
// Gap 6: Grid size cap — validate grid slot count against expected maximum.
|
|
@@ -1986,29 +2033,53 @@ export function determineOrderSideByFunds(manager, currentMarketPrice) {
|
|
|
1986
2033
|
}
|
|
1987
2034
|
return { side, reason: side ? `Choosing ${side}` : 'Insufficient funds or committed inventory' };
|
|
1988
2035
|
}
|
|
2036
|
+
/**
|
|
2037
|
+
* Resolve the MIN_SPREAD_ORDERS gap reserve used by boundary promotion.
|
|
2038
|
+
* Promotion may never consume the last `reserve` empty slots of the gap
|
|
2039
|
+
* band — this is the floor that keeps the spread from being zeroed.
|
|
2040
|
+
*/
|
|
2041
|
+
function resolveMinSpreadOrdersReserve(manager) {
|
|
2042
|
+
const raw = Number(manager?.config?.gridLimits?.MIN_SPREAD_ORDERS ?? GRID_LIMITS.MIN_SPREAD_ORDERS);
|
|
2043
|
+
return (Number.isFinite(raw) && raw >= 0) ? Math.floor(raw) : GRID_LIMITS.MIN_SPREAD_ORDERS;
|
|
2044
|
+
}
|
|
1989
2045
|
// Collect contiguous empty gap-band slots adjacent to a rail edge for boundary
|
|
1990
2046
|
// promotion. BUY walks upward from the boundary into the gap, SELL walks
|
|
1991
2047
|
// downward from the sell start; both stop at the first unavailable slot.
|
|
1992
2048
|
// Mirrors are collapsed into one directional walk (step +/- 1).
|
|
1993
2049
|
//
|
|
1994
|
-
//
|
|
1995
|
-
//
|
|
1996
|
-
// buyEndIdx
|
|
1997
|
-
//
|
|
1998
|
-
//
|
|
1999
|
-
//
|
|
2000
|
-
//
|
|
2001
|
-
//
|
|
2002
|
-
|
|
2050
|
+
// PROMOTION CAP (gap-band geometry): promotion may consume at most
|
|
2051
|
+
// bandSize − MIN_SPREAD_ORDERS slots, where bandSize = sellStartIdx −
|
|
2052
|
+
// buyEndIdx − 1. The previous cap (the OPPOSITE RAIL's span) constrained
|
|
2053
|
+
// nothing: for BUY it was the sell rail's length and for SELL the buy
|
|
2054
|
+
// rail's length, so a single correction could promote every gap slot and
|
|
2055
|
+
// zero the spread. Reserving MIN_SPREAD_ORDERS empty slots guarantees the
|
|
2056
|
+
// gap never closes within this path regardless of quota.
|
|
2057
|
+
//
|
|
2058
|
+
// DEFENSE-IN-DEPTH WALK BOUNDS: the loop itself also stops
|
|
2059
|
+
// MIN_SPREAD_ORDERS short of the opposite rail edge (idx <= sellStartIdx−1−
|
|
2060
|
+
// reserve for BUY / idx >= buyEndIdx+1+reserve for SELL), so even if the
|
|
2061
|
+
// cap above is ever miscomputed the walk cannot consume the reserved gap.
|
|
2062
|
+
// When bandSize <= reserve the bound disables promotion entirely.
|
|
2063
|
+
function _collectPromotableBoundarySlots(allSlotsByPrice, railType, buyEndIdx, sellStartIdx, quota, spreadReserve, maxDepth) {
|
|
2003
2064
|
const isBuy = railType === ORDER_TYPES.BUY;
|
|
2004
|
-
const
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2065
|
+
const bandSize = Math.max(0, sellStartIdx - buyEndIdx - 1);
|
|
2066
|
+
// Depth is bounded by three independent caps (defense-in-depth):
|
|
2067
|
+
// reserve cap — keep MIN_SPREAD_ORDERS empties in the band
|
|
2068
|
+
// stranding cap— the boundary slide must never move a placed
|
|
2069
|
+
// opposite-rail order into the implied spread band;
|
|
2070
|
+
// constraining DEPTH here (not clamping the derived
|
|
2071
|
+
// boundary afterwards) keeps the promoted slots'
|
|
2072
|
+
// classification consistent with the new geometry
|
|
2073
|
+
// walk bounds — hard stop short of the opposite rail edge, even if
|
|
2074
|
+
// both caps above were ever miscomputed
|
|
2075
|
+
const maxPromotable = Math.max(0, bandSize - spreadReserve);
|
|
2076
|
+
const promotionQuota = Math.min(quota, maxPromotable, Math.max(0, maxDepth));
|
|
2009
2077
|
const promoted = [];
|
|
2010
2078
|
const step = isBuy ? 1 : -1;
|
|
2011
|
-
for (let idx = isBuy ? buyEndIdx + 1 : sellStartIdx - 1; promoted.length < promotionQuota
|
|
2079
|
+
for (let idx = isBuy ? buyEndIdx + 1 : sellStartIdx - 1; promoted.length < promotionQuota
|
|
2080
|
+
&& (isBuy
|
|
2081
|
+
? idx <= sellStartIdx - 1 - spreadReserve
|
|
2082
|
+
: idx >= buyEndIdx + 1 + spreadReserve); idx += step) {
|
|
2012
2083
|
const slot = allSlotsByPrice[idx];
|
|
2013
2084
|
if (!slot || !isSlotAvailable(slot))
|
|
2014
2085
|
break;
|
|
@@ -2130,9 +2201,37 @@ export async function prepareSpreadCorrectionOrders(manager, preferredSide, outO
|
|
|
2130
2201
|
// fiction. Without promotion there is nothing to commit, so falling
|
|
2131
2202
|
// back to the pre-existing candidate paths is safe.
|
|
2132
2203
|
const promotedCandidates = [];
|
|
2204
|
+
const spreadReserve = resolveMinSpreadOrdersReserve(manager);
|
|
2205
|
+
// STRANDING DEPTH CAP: the post-commit geometry re-derives the band
|
|
2206
|
+
// from the new boundary, sliding it over opposite-rail slots. A
|
|
2207
|
+
// slide may never swallow an already-PLACED order into that band, so
|
|
2208
|
+
// promotion depth is capped up-front — constraining depth keeps the
|
|
2209
|
+
// derived boundary consistent with every promoted slot's placement;
|
|
2210
|
+
// clamping the boundary afterwards would not.
|
|
2211
|
+
let maxPromotionDepth = Infinity;
|
|
2212
|
+
if (railType === ORDER_TYPES.BUY) {
|
|
2213
|
+
for (let idx = Math.max(sellStartIdx, 0); idx < allSlotsByPrice.length; idx++) {
|
|
2214
|
+
if (allSlotsByPrice[idx]?.orderId) {
|
|
2215
|
+
// Implied sell zone must start at/below the lowest placed
|
|
2216
|
+
// sell: B' + gapSlots + 1 <= idx => depth <= idx − G − 1 − B.
|
|
2217
|
+
maxPromotionDepth = idx - gapSlots - 1 - buyEndIdx;
|
|
2218
|
+
break;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
else {
|
|
2223
|
+
for (let idx = Math.min(buyEndIdx, allSlotsByPrice.length - 1); idx >= 0; idx--) {
|
|
2224
|
+
if (allSlotsByPrice[idx]?.orderId) {
|
|
2225
|
+
// Boundary may not drop below the highest placed buy:
|
|
2226
|
+
// B' = B − depth >= idx => depth <= B − idx.
|
|
2227
|
+
maxPromotionDepth = buyEndIdx - idx;
|
|
2228
|
+
break;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2133
2232
|
if (boundaryKnown && orphanedVirtualCandidates.length + typedSpreadCandidates.length < missingSlots) {
|
|
2134
2233
|
const rawQuota = missingSlots - orphanedVirtualCandidates.length - typedSpreadCandidates.length;
|
|
2135
|
-
promotedCandidates.push(..._collectPromotableBoundarySlots(allSlotsByPrice, railType, buyEndIdx, sellStartIdx, rawQuota));
|
|
2234
|
+
promotedCandidates.push(..._collectPromotableBoundarySlots(allSlotsByPrice, railType, buyEndIdx, sellStartIdx, rawQuota, spreadReserve, maxPromotionDepth));
|
|
2136
2235
|
if (promotedCandidates.length > 0) {
|
|
2137
2236
|
manager.logger?.log?.(`[SPREAD-CORRECTION] ${promotedCandidates.length} gap slot(s) available for boundary promotion on ${sideName}`, 'info');
|
|
2138
2237
|
}
|
|
@@ -2316,15 +2415,30 @@ export async function prepareSpreadCorrectionOrders(manager, preferredSide, outO
|
|
|
2316
2415
|
boundaryIdx = railType === ORDER_TYPES.BUY
|
|
2317
2416
|
? buyEndIdx + maxDist
|
|
2318
2417
|
: buyEndIdx - maxDist;
|
|
2418
|
+
// PROMOTION BOUNDARY BACKSTOP (refusal-only): the boundary is
|
|
2419
|
+
// DERIVED from the placed promoted set (buyEndIdx ± maxDist),
|
|
2420
|
+
// so shifting it here would silently strand those fresh orders
|
|
2421
|
+
// inside the implied band. All real constraints — the
|
|
2422
|
+
// MIN_SPREAD_ORDERS reserve and opposite-rail stranding — are
|
|
2423
|
+
// enforced UPSTREAM as walk-depth caps. This backstop only
|
|
2424
|
+
// verifies array limits plus the reserve ceiling; any
|
|
2425
|
+
// violation signals an internal inconsistency, so promotion is
|
|
2426
|
+
// refused loudly instead of silently re-geometried.
|
|
2319
2427
|
const maxIdx = allSlotsByPrice.length - 1;
|
|
2320
|
-
const
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2428
|
+
const lo = 0;
|
|
2429
|
+
const hi = railType === ORDER_TYPES.BUY
|
|
2430
|
+
? Math.min(maxIdx, sellStartIdx - 1 - spreadReserve)
|
|
2431
|
+
: maxIdx;
|
|
2432
|
+
if (lo > hi || boundaryIdx < lo || boundaryIdx > hi) {
|
|
2433
|
+
manager.logger?.log?.(`[SPREAD-CORRECTION] Boundary promotion refused on ${sideName}: ` +
|
|
2434
|
+
`derived boundary ${boundaryIdx} violates safe range [${lo}, ${hi}] ` +
|
|
2435
|
+
`(band ${buyEndIdx + 1}..${sellStartIdx - 1})`, 'warn');
|
|
2436
|
+
boundaryIdx = undefined;
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
manager.logger?.log?.(`[SPREAD-CORRECTION] Boundary promotion on ${sideName}: ` +
|
|
2440
|
+
`${buyEndIdx} -> ${boundaryIdx} (${placedPromotedIds.size} placed, maxDist ${maxDist})`, 'info');
|
|
2325
2441
|
}
|
|
2326
|
-
manager.logger?.log?.(`[SPREAD-CORRECTION] Boundary promotion on ${sideName}: ` +
|
|
2327
|
-
`${buyEndIdx} -> ${boundaryIdx} (${placedPromotedIds.size} placed, maxDist ${maxDist})`, 'info');
|
|
2328
2442
|
}
|
|
2329
2443
|
else {
|
|
2330
2444
|
boundaryIdx = undefined;
|