dexbot 1.6.5 → 1.6.6

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.
Files changed (155) hide show
  1. package/CHANGELOG.md +36 -4
  2. package/README.md +104 -35
  3. package/analysis/README.md +11 -16
  4. package/analysis/account_resolver.ts +1 -11
  5. package/analysis/bot_usage/kibana_bot_queries.ts +1 -1
  6. package/analysis/chain_pool.ts +1 -1
  7. package/analysis/fills_source.ts +0 -6
  8. package/analysis/grid_correction_check.ts +20 -26
  9. package/analysis/resolve_source.ts +1 -1
  10. package/analysis/trade_profitability.ts +2 -5
  11. package/analysis/trend_detection/README.md +1 -3
  12. package/analysis/trend_detection/package.json +1 -1
  13. package/claw/package.json +1 -1
  14. package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
  15. package/claw/runtimes/openclaw-plugin/package.json +1 -1
  16. package/claw/tests/test_claw_mcp_transport.ts +2 -2
  17. package/dist/analysis/account_resolver.d.ts +1 -4
  18. package/dist/analysis/account_resolver.d.ts.map +1 -1
  19. package/dist/analysis/account_resolver.js +1 -1
  20. package/dist/analysis/account_resolver.js.map +1 -1
  21. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -2
  22. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
  23. package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -1
  24. package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
  25. package/dist/analysis/chain_pool.d.ts +1 -3
  26. package/dist/analysis/chain_pool.d.ts.map +1 -1
  27. package/dist/analysis/chain_pool.js +1 -1
  28. package/dist/analysis/chain_pool.js.map +1 -1
  29. package/dist/analysis/fills_source.d.ts +1 -51
  30. package/dist/analysis/fills_source.d.ts.map +1 -1
  31. package/dist/analysis/fills_source.js +1 -1
  32. package/dist/analysis/fills_source.js.map +1 -1
  33. package/dist/analysis/grid_correction_check.d.ts +2 -3
  34. package/dist/analysis/grid_correction_check.d.ts.map +1 -1
  35. package/dist/analysis/grid_correction_check.js +18 -26
  36. package/dist/analysis/grid_correction_check.js.map +1 -1
  37. package/dist/analysis/resolve_source.d.ts +1 -1
  38. package/dist/analysis/resolve_source.d.ts.map +1 -1
  39. package/dist/analysis/trade_profitability.d.ts.map +1 -1
  40. package/dist/analysis/trade_profitability.js +2 -7
  41. package/dist/analysis/trade_profitability.js.map +1 -1
  42. package/dist/dexbot.d.ts.map +1 -1
  43. package/dist/dexbot.js +60 -74
  44. package/dist/dexbot.js.map +1 -1
  45. package/dist/market_adapter/core/kibana_candles.d.ts +1 -15
  46. package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -1
  47. package/dist/market_adapter/core/kibana_candles.js +1 -1
  48. package/dist/market_adapter/core/kibana_candles.js.map +1 -1
  49. package/dist/market_adapter/inputs/fetch_lp_data.d.ts +1 -35
  50. package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
  51. package/dist/market_adapter/inputs/fetch_lp_data.js +10 -54
  52. package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
  53. package/dist/market_adapter/inputs/kibana_feed_source.d.ts +1 -8
  54. package/dist/market_adapter/inputs/kibana_feed_source.d.ts.map +1 -1
  55. package/dist/market_adapter/inputs/kibana_feed_source.js +1 -1
  56. package/dist/market_adapter/inputs/kibana_feed_source.js.map +1 -1
  57. package/dist/market_adapter/inputs/window_cache.d.ts +2 -63
  58. package/dist/market_adapter/inputs/window_cache.d.ts.map +1 -1
  59. package/dist/market_adapter/inputs/window_cache.js +22 -102
  60. package/dist/market_adapter/inputs/window_cache.js.map +1 -1
  61. package/dist/modules/account_bots.d.ts +16 -2
  62. package/dist/modules/account_bots.d.ts.map +1 -1
  63. package/dist/modules/account_bots.js +107 -44
  64. package/dist/modules/account_bots.js.map +1 -1
  65. package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -1
  66. package/dist/modules/bitshares-native/crypto/ecc.browser.js +0 -31
  67. package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -1
  68. package/dist/modules/credit_runtime.d.ts +0 -2
  69. package/dist/modules/credit_runtime.d.ts.map +1 -1
  70. package/dist/modules/credit_runtime.js +1 -10
  71. package/dist/modules/credit_runtime.js.map +1 -1
  72. package/dist/modules/dexbot_class.d.ts +13 -10
  73. package/dist/modules/dexbot_class.d.ts.map +1 -1
  74. package/dist/modules/dexbot_class.js +0 -9
  75. package/dist/modules/dexbot_class.js.map +1 -1
  76. package/dist/modules/dexbot_cow_runtime.d.ts +13 -0
  77. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  78. package/dist/modules/dexbot_cow_runtime.js +13 -1
  79. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  80. package/dist/modules/order/accounting.d.ts +4 -18
  81. package/dist/modules/order/accounting.d.ts.map +1 -1
  82. package/dist/modules/order/accounting.js +4 -34
  83. package/dist/modules/order/accounting.js.map +1 -1
  84. package/dist/modules/order/export.d.ts +9 -12
  85. package/dist/modules/order/export.d.ts.map +1 -1
  86. package/dist/modules/order/export.js +9 -12
  87. package/dist/modules/order/export.js.map +1 -1
  88. package/dist/modules/order/grid.d.ts +35 -40
  89. package/dist/modules/order/grid.d.ts.map +1 -1
  90. package/dist/modules/order/grid.js +43 -43
  91. package/dist/modules/order/grid.js.map +1 -1
  92. package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
  93. package/dist/modules/order/grid_reconcile.js +111 -20
  94. package/dist/modules/order/grid_reconcile.js.map +1 -1
  95. package/dist/modules/order/grid_reconcile_internal.d.ts +5 -3
  96. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  97. package/dist/modules/order/grid_reconcile_internal.js +18 -3
  98. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  99. package/dist/modules/order/manager.d.ts +0 -8
  100. package/dist/modules/order/manager.d.ts.map +1 -1
  101. package/dist/modules/order/manager.js +0 -10
  102. package/dist/modules/order/manager.js.map +1 -1
  103. package/dist/modules/order/utils/order.d.ts +22 -7
  104. package/dist/modules/order/utils/order.d.ts.map +1 -1
  105. package/dist/modules/order/utils/order.js +103 -21
  106. package/dist/modules/order/utils/order.js.map +1 -1
  107. package/dist/modules/order/utils/withPoolRef.d.ts +12 -0
  108. package/dist/modules/order/utils/withPoolRef.d.ts.map +1 -1
  109. package/dist/modules/order/utils/withPoolRef.js +17 -0
  110. package/dist/modules/order/utils/withPoolRef.js.map +1 -1
  111. package/dist/modules/order/working_grid.d.ts +8 -13
  112. package/dist/modules/order/working_grid.d.ts.map +1 -1
  113. package/dist/modules/order/working_grid.js +8 -29
  114. package/dist/modules/order/working_grid.js.map +1 -1
  115. package/dist/scripts/sync-version.js +0 -22
  116. package/dist/scripts/sync-version.js.map +1 -1
  117. package/dist/scripts/update_dist_freshness.d.ts +12 -0
  118. package/dist/scripts/update_dist_freshness.d.ts.map +1 -1
  119. package/dist/scripts/update_dist_freshness.js +30 -1
  120. package/dist/scripts/update_dist_freshness.js.map +1 -1
  121. package/docs/BITSHARES_ONBOARDING.md +9 -6
  122. package/docs/COW_INVARIANTS.md +1 -0
  123. package/docs/DEXBOT_COMPARISON.md +11 -11
  124. package/docs/EVOLUTION.md +8 -7
  125. package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
  126. package/docs/GRID_PRICE_INVARIANT.md +518 -0
  127. package/docs/GRID_RECALCULATION.md +1 -1
  128. package/docs/GRID_RECONCILE.md +60 -39
  129. package/docs/ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md +556 -0
  130. package/docs/README.md +3 -3
  131. package/docs/WORKFLOW.md +12 -6
  132. package/docs/architecture.md +40 -38
  133. package/docs/developer_guide.md +4 -8
  134. package/market_adapter/README.md +16 -12
  135. package/modules/README.md +1 -1
  136. package/package.json +7 -3
  137. package/scripts/README.md +0 -9
  138. package/scripts/reset-settings.sh +1 -1
  139. package/analysis/ama_fitting/package.json +0 -12
  140. package/analysis/analyze_derivatives.ts +0 -320
  141. package/analysis/derivative_chart_generator.ts +0 -874
  142. package/analysis/trend_detection/SIGNAL_DOCUMENTATION.md +0 -403
  143. package/analysis/trend_detection/derivative_analyzer.ts +0 -1059
  144. package/dist/analysis/analyze_derivatives.d.ts +0 -68
  145. package/dist/analysis/analyze_derivatives.d.ts.map +0 -1
  146. package/dist/analysis/analyze_derivatives.js +0 -287
  147. package/dist/analysis/analyze_derivatives.js.map +0 -1
  148. package/dist/analysis/derivative_chart_generator.d.ts +0 -12
  149. package/dist/analysis/derivative_chart_generator.d.ts.map +0 -1
  150. package/dist/analysis/derivative_chart_generator.js +0 -891
  151. package/dist/analysis/derivative_chart_generator.js.map +0 -1
  152. package/dist/analysis/trend_detection/derivative_analyzer.d.ts +0 -248
  153. package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +0 -1
  154. package/dist/analysis/trend_detection/derivative_analyzer.js +0 -910
  155. package/dist/analysis/trend_detection/derivative_analyzer.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.6.6] - 2026-09-25 - Stale Cancellation Guard Hardening
6
+
7
+ ### 2026-09-25
8
+
9
+ - **Fix(update)**: make the dist freshness check honor the build's `tsconfig.json` exclude — the updater derived expected `dist/` outputs by walking every `.ts` under the compiled roots, so the archived `analysis/legacy/tests` (compiled only by `tsconfig.tests.json`) was read as a missing production output and the post-build check aborted with `Build left dist/ incomplete or stale (is missing dist/analysis/legacy/tests/test_derivative_chart.js)` after a successful build, blocking the restart. `collectCompiledSources` now reads the root `tsconfig.json` `exclude` directory prefixes and skips them, mirroring the compiler; regression in `tests/test_update_dist_freshness.ts` (`scripts/update_dist_freshness.ts`, `tests/test_update_dist_freshness.ts`).
10
+
11
+ - **Refactor(analysis)**: archive the legacy SMA/MACD/RSI derivative analyzer — the classic-indicator tool (superseded by the live Kalman/Hurst/PE stack, with no production importer since `modules/` and `market_adapter/core/` hold none of its symbols) moves to `analysis/legacy/` with a local README. It loses its `analysis:derivatives` npm script, is scrubbed from the centralized docs (`analysis/README.md`, `analysis/trend_detection/README.md`, `scripts/README.md`, `docs/README.md`, `docs/architecture.md`, `docs/developer_guide.md`, `docs/DEXBOT_COMPARISON.md`), and is excluded from the published npm package (`!analysis/legacy` + `!dist/analysis/legacy`). Its four regression tests move under `analysis/legacy/tests/` out of the default `npm test` glob, with a new opt-in `npm run test:legacy`; the production build excludes that path while `tsconfig.tests.json` still typechecks it. Full suite 296/296 pass (`analysis/legacy/`, `package.json`, `tsconfig.json`, `tsconfig.tests.json`, docs).
12
+
13
+ - **Refactor(cache)**: drop legacy run-relative candle-cache migration — stable calendar-month shards are now the only supported format: `*.chunk_*` files are ignored (never loaded, never deleted) instead of being absorbed into shards, and the `*.fetch_manifest.json` identity fallback is removed. The LP fetcher's progress output reads `Window N/M` (was `Chunk N/M`) and its match predicate is renamed `isLpShardMatch`. Refresh/retry/tail semantics are unchanged. Behavioral impact: installs holding only legacy chunks re-fetch once on next run, and the stale files remain inert on disk. Full suite 292/292 pass (`market_adapter/inputs/window_cache.ts`, `market_adapter/inputs/fetch_lp_data.ts`, `tests/test_window_cache.ts`, `market_adapter/README.md`).
14
+
15
+ ### 2026-09-24
16
+
17
+ - **Fix(order-engine)**: close stale-cancellation replays across the correction queue, COW orphan maintenance, and startup reconciliation. Drain-time validation now rechecks live ownership and source-specific geometry for cancel-only, type-mismatch, and gap-evacuation decisions; COW auto-cancel skips adopted orders; startup Phase 2 validates each plan against its own unchanged chain order and live slot/geometry instead of requiring whole-book snapshot equality. Surplus settlement uses only the current live owner and skips stale snapshot fallback. Centralized live-owner lookup across the guards and added regression coverage for truncated/failed pre-cancel reads, per-plan snapshot independence, and stale settlement (`modules/order/utils/order.ts`, `modules/order/grid_reconcile.ts`, `modules/order/grid_reconcile_internal.ts`, `modules/dexbot_cow_runtime.ts`, `tests/test_correction_queue_staleness.ts`, `tests/test_grid_reconcile_regressions.ts`, `tests/test_uncertain_broadcast.ts`).
18
+
19
+ ### 2026-09-23
20
+
21
+ - **Refactor(bot-editor)**: unify the configurator menu labels — abbreviated aliases give way to full names so the same term reads identically in the editor and the docs: `HealthChk` → `Health Check`, `PrefNode` → `Preferred Node`, `Incr` → `Increment`, and `Log lvl` → `Log Level`. The run-together `GridPrice`, `MarketOrder`, and `EdgeOrder` labels keep their casing. Display-only — stored keys, defaults, and validation are unchanged; the `README.md` configurator reference aliases and the `4) Log Level` heading are updated to match (`modules/account_bots.ts`, `README.md`).
22
+
23
+ - **Feat(bot-editor)**: render `5) List bots` as a `Name / Account / Pair` table — the flat `N: name A / B` line gains a bold header and columns derived from the longest value in each field, with palette colors (grey index, green name, orange account, cyan pair) replacing the unlabeled white text, and the pair now reads `A/B` with no spaces around the slash. The `[inactive]`/`(dryRun)` suffixes are colored red/yellow so they stand out. Readability only (`modules/account_bots.ts`).
24
+
25
+ - **Refactor(settings)**: regroup the General Settings menu by concern — `1) Grid Health` → `1) Grid Drift`, `2) Order Recovery` → `2) Order Maint.` (which now also edits the Health Check Interval, moved out of Node Config, so the `Health Check` value reads next to the dust threshold it schedules), and `3) Node Config` narrows to `Nodes` + `Preferred Node`; all five rows are padded to a shared value column. Display/prompt grouping only — stored keys, defaults, and validation are unchanged. Docs: the `README.md` global-settings reference is regrouped to mirror the editor, and `docs/GRID_RECALCULATION.md`'s menu reference now reads `1) Grid Drift` (`modules/account_bots.ts`, `README.md`, `docs/GRID_RECALCULATION.md`).
26
+
27
+ - **Refactor(bot-editor)**: align the per-bot editor with the `bots.json`/runtime vocabulary — the `5) Funding` section is now `5) Inventory` with `Orders` → `MarketOrder` (active window, counted from the market) and `Reserve` → `EdgeOrder` (edge-pinned insurance orders); the `Preferred account` prompts read `Blockchain account`; and `startPrice (pool, book or A/B)` reads `startPrice (pool, book or price)`. `poolRef` is now prompted only when `startPrice` is `pool`: a dormant pin is preserved rather than cleared when switching to `book`/numeric, and the `3) Price` summary renders a dormant pin as grey `ignored` instead of a value that no longer applies. Reserve order counts accept `0`–`100` per side (was `0`–`20`), matching the active-order cap, and the `1)`–`6)` summary rows are column-aligned. Display/validation only — stored keys and defaults are unchanged. New `formatPoolRefLabel` dormant-pin case in `tests/test_account_bots_adapter.ts` (`modules/account_bots.ts`).
28
+
29
+ - **Refactor(cli)**: rebuild `dexbot help` as grouped sections — `printCLIUsage` replaces the hand-padded flat list (which had drifted: duplicate `order` rows, missing `dw`/`export`/`clear-orders`/`clear-market-adapter`/`clear-all`) with five groups (Runtime, Trading, Config, Analysis, Files) plus a Help & options block, deriving the command-column width from the longest entry so alignment cannot drift again. Same commands and aliases; output-only (`dexbot.ts`).
30
+
31
+ - **Docs**: regroup the README configurator reference to mirror the editor — the per-bot parameter tables are split into `1) Pair` … `6) Adapter` and the global-settings tables into `1) Grid Drift` … `5) Updater`, with the previously-undocumented edge-`reserveOrders` semantics and adapter-flag storage (`market_adapter_whitelist.json`, not `bots.json`) called out; the CLI examples gain `export` and the `clear-*` variants. `docs/WORKFLOW.md`'s command table is synced (aliases `keys`/`bots`/`stats`, `dw`, the three `clear-*` commands, `help`), `docs/DEXBOT_COMPARISON.md` now credits the interactive `dexbot bot` editor instead of "manual JSON only", and `market_adapter/README.md` + `scripts/reset-settings.sh` spell the full path `dexbot bot` → `2) Modify bot` → `6) Adapter` (`README.md`, `docs/WORKFLOW.md`, `docs/DEXBOT_COMPARISON.md`, `market_adapter/README.md`, `scripts/reset-settings.sh`).
32
+
33
+ - **Fix(bot-editor)**: accept the pool label's own vocabulary in the `poolRef` prompt — the `3) Price` summary reads green `Pool: default` when the runtime auto-selects the pair's pool, but the pin prompt showed `[none]` and rejected `default`/`pool`/`auto` as invalid, so a user typing what the summary displayed hit an error. `askPoolRef` now treats `default`/`pool`/`auto` as clear aliases (same as `none`/`clear`/`off`/`no`), and when `startPrice` is `pool` the unpinned prompt renders `[default]` instead of `[none]`, matching the summary, and the now-redundant `(none to clear)` hint is dropped from the prompt. New `isPoolStartPrice`/`isPoolRefClearInput` helpers. Display/parsing only — a pin is still either a concrete `1.19.x` ID or absent, and `withPoolRef` is unchanged. Tests: `tests/test_account_bots_adapter.ts` (`modules/account_bots.ts`).
34
+
35
+ - **Fix(grid)**: make `startPrice` the master price source over a pinned `poolRef` — `initializeGrid` passed `manager.config.priceMode || 'auto'`, and `priceMode` is never populated in the bot runtime path, so `startPrice: "book"` was derived as `"auto"` and a pinned `poolRef` won over the order book. New `resolveStartPriceMode()` (`modules/order/utils/withPoolRef.ts`) derives the mode from `startPrice` itself, so `"book"` ignores the pin while `"pool"`/`"auto"` still consult it. Behavioral impact: a bot with `startPrice: "book"` + a pinned pool prices from the order book as documented (previously the pool); numeric startPrice is unchanged. Tests: `tests/test_pool_ref_price.ts` (book mode never fetches the pinned pool; mode resolution) (`modules/order/grid.ts`, `modules/order/utils/withPoolRef.ts`).
36
+
5
37
  ## [1.6.5] - 2026-09-23 - Editor-Managed Whitelist Flags, GridPrice Normalization, Pool/Health Cues, Log-Symmetric Range Tilt, Centralized Bot Defaults, Dynamic-Weight CLI, Update Self-Heal
6
38
 
7
39
  ### 2026-09-23
@@ -20,7 +52,7 @@ All notable changes to this project will be documented in this file.
20
52
 
21
53
  - **Fix(update)**: rebuild when source is current but `dist/` is stale — the git update flow exited before `npm run build` when there were no incoming commits, and tsc's incremental cache will not re-emit an output it believes is current (it will not even recreate a deleted file), so a `dist/` that lagged its source stayed stale while every later run reported "already up to date"; the old guard only checked the `dist/modules/dexbot_class.js` mtime, so a stale `dist/dexbot.js` (holding the CLI alias table) went unnoticed. New `scripts/update_dist_freshness.ts` detects missing/stale outputs without invoking the compiler over exactly the root tsconfig include roots; `scripts/update.ts` self-heals on the no-op path (force a full rebuild, then restart), re-checks and force-emits on the normal path, and `assertDistBundleFresh()` replaces the single-marker guard with a full-bundle check. New `tests/test_update_dist_freshness.ts` covers missing entries, missing/stale counterparts, root-level entry points, and non-compiled files.
22
54
 
23
- - **Feat(defaults)**: centralize bot defaults, settings-doc building, and whitelist flags — seven scattered producers applied `DEFAULT_CONFIG` and whitelist defaults independently and had already drifted. New `modules/bot_defaults.ts` (`seedBotDraft`/`seedBotEntry`/`seedBotRuntimeConfig` with classified key sets, `normalizeBotDraft`/`normalizeBotEntry`) now backs the editor draft, `bot_settings` + claw, and the `OrderManager` constructor. `buildDefaultGeneralSettings()` (`modules/constants.ts`) and `buildNodesView()` (`modules/settings_merge.ts`) give the first-run generator, the editor fallback (`account_bots.loadGeneralSettings`), and the local-overrides merge one shared document (`loadGeneralSettings`/`saveGeneralSettings` now exported). `DEFAULT_WHITELIST_FLAGS`/`AMA_ONLY`/`ALL_ENABLED` constants replace every inline flag literal. Behavioral impact: a draft's `gridPrice` follows a `DEFAULT_CONFIG.gridPrice` override (default stays null here); a missing `bot.active` sources `DEFAULT_CONFIG.active` (was hardcoded true) and claw no longer coerces present null/0, unifying on `active !== false`; `OrderManager` clones absent defaults so config mutations cannot leak into the global default; brand-new first-run settings files gain `NODE_MANAGEMENT`, drop `ANCHOR:{}`, and match the editor key order. Existing `bots.json`/`general.settings.json` are not rewritten (merge output verified byte-identical to a pre-refactor baseline). Tests: 295/295 files passed; new `tests/test_bot_defaults_characterization.ts`, `tests/test_bot_defaults_parity.ts`, and a claw delegation test.
55
+ - **Feat(defaults)**: centralize bot defaults, settings-doc building, and whitelist flags — seven scattered producers applied `DEFAULT_CONFIG` and whitelist defaults independently and had already drifted. New `modules/bot_defaults.ts` (`seedBotDraft`/`seedBotEntry`/`seedBotRuntimeConfig` with classified key sets, `normalizeBotDraft`/`normalizeBotEntry`) now backs the editor draft, `bot_settings` + claw, and the `OrderManager` constructor. `buildDefaultGeneralSettings()` (`modules/constants.ts`) and `buildNodesView()` (`modules/settings_merge.ts`) give the first-run generator, the editor fallback (`account_bots.loadGeneralSettings`), and the local-overrides merge one shared document (`loadGeneralSettings`/`saveGeneralSettings` now exported). `DEFAULT_WHITELIST_FLAGS`/`AMA_ONLY`/`ALL_ENABLED` constants replace every inline flag literal. Behavioral impact: a draft's `gridPrice` follows a `DEFAULT_CONFIG.gridPrice` override (the default was still null at this stage of the refactor; a subsequent change in the same release set it to `ama3`); a missing `bot.active` sources `DEFAULT_CONFIG.active` (was hardcoded true) and claw no longer coerces present null/0, unifying on `active !== false`; `OrderManager` clones absent defaults so config mutations cannot leak into the global default; brand-new first-run settings files gain `NODE_MANAGEMENT`, drop `ANCHOR:{}`, and match the editor key order. Existing `bots.json`/`general.settings.json` are not rewritten (merge output verified byte-identical to a pre-refactor baseline). Tests: 295/295 files passed; new `tests/test_bot_defaults_characterization.ts`, `tests/test_bot_defaults_parity.ts`, and a claw delegation test.
24
56
 
25
57
  - **Feat(bot-editor)**: manage market-adapter whitelist flags from the editor — the per-bot Price/Weight/Range flags (`ama`/`dynamicWeight`/`asymmetricBounds`) previously required running the `dexbot white` script with the correct `botKey`; a wrong key silently wrote a useless entry and the script remained the only way to flip a single flag. New `6) Adapter` section in `modules/account_bots.ts` stages the three flags and commits them only after `bots.json` saved (migrating the entry on rename); `parseBooleanInput` fixes `askBoolean` parsing `'true'` as false and accepting any garbage (`y`/`yes`/`true`, `n`/`no`/`false`, Enter keeps current). `modules/market_adapter_whitelist.ts` gains `setWhitelistFlags()`/`renameWhitelistEntry()` read-modify-write helpers — an occupied key refuses the rename, a malformed file aborts instead of clobbering, legacy array-form entries are preserved, and keys are written sorted. Docs now point to `dexbot bot` -> `6) Adapter`. New `tests/test_account_bots_adapter.ts` (boolean parsing, flag writes, rename/collision, legacy and malformed-file coverage); `npm test` 293 passed / 0 failed, `verify:browser-bundle` 39/39, `tsc --noEmit` clean. Risk: writes touch the same file `dexbot white` owned; unchanged flags are never rewritten.
26
58
 
@@ -763,10 +795,10 @@ All notable changes to this project will be documented in this file.
763
795
  - **Fix**: prevent bot hangs via centralized timeout + node failover — after exhausting 3-attempt retry budget, `withBlockchainRetry` force-blacklists the stuck node and reconnects to a healthy one. All blockchain ops (fetchAccountTotals, readOpenOrders, syncFromOpenOrders, reconcileGridOrders) get automatic failover. Default `_fillProcessingLock` acquisition timeout (20s) prevents indefinite waits. `recalculateGrid` wrapped in 10-minute `Promise.race` ceiling (`modules/order/utils/system.ts`, `modules/order/manager.ts`, `modules/order/grid.ts`).
764
796
  - **Refactor**: centralize `withBlockchainRetry` into shared utility in `system.ts` — replaces local copy in `grid.ts` and inline `Promise.race` in `dexbot_startup_runtime.ts`, giving the startup path retries + node failover too (`modules/order/utils/system.ts`, `modules/order/grid.ts`, `modules/dexbot_startup_runtime.ts`).
765
797
  - **Fix**: prevent duplicate grid-level CREATEs via 4-layer validator guard — `validateCreateTargetSlots` extended with slot occupancy, master grid price collision, chain orphan collision, and same-batch duplicate detection. Also hardens `checkSpreadCondition` against TOCTOU between lock release and broadcast (`modules/order/utils/validate.ts`, `modules/order/grid.ts`, `modules/dexbot_cow_runtime.ts`).
766
- - **Fix**: prevent false-positive excess cancellation on fresh grid — guard `_reconcileStartupSide` cancelCount with `matchedOnGrid > 0` to avoid destroying legitimate orders when no grid slot yet assigned ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#fresh-grid-guard)). Fix reconcile timeout death spiral by overriding timeout to 300s so Phase 2 batch creates finish in one shot (`modules/order/grid.ts`, `modules/order/grid_reconcile_internal.ts`).
798
+ - **Fix**: prevent false-positive excess cancellation on fresh grid — guard `_reconcileStartupSide` cancelCount with `matchedOnGrid > 0` to avoid destroying legitimate orders when no grid slot yet assigned ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#fresh-grid-guard-matchedongrid--0)). Fix reconcile timeout death spiral by overriding timeout to 300s so Phase 2 batch creates finish in one shot (`modules/order/grid.ts`, `modules/order/grid_reconcile_internal.ts`).
767
799
  - **Fix**: prevent cross-side spread correction via boundary-correct type filter — hoist boundary computation before both candidate pools and filter `typedSpreadCandidates` by `getSlotCorrectType(o) === railType` to prevent activating a SPREAD slot on the wrong rail after fill-induced boundary shifts (`modules/order/grid.ts`).
768
800
  - **Fix**: remove dead PARTIAL filter in `recalculateGrid` (raw chain `limit_order` objects never have a `state` property) and fix `withBlockchainRetry` logger arg — pass `manager.logger` directly instead of `{ logger: manager.logger }` (`modules/order/grid.ts`).
769
- - **Fix**: cancel stale surplus orders after Phase 2 settles in reconcileGridOrders — new Phase 3 pass re-fetches chain orders and cancels any exceeding per-side target that are not tracked by any grid slot's `orderId` ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#phase-3--stale-surplus-cleanup)). Catches orphan orders whose ID was lost when the grid reinitialized mid-resync.
801
+ - **Fix**: cancel stale surplus orders after Phase 2 settles in reconcileGridOrders — new Phase 3 pass re-fetches chain orders and cancels any exceeding per-side target that are not tracked by any grid slot's `orderId` ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#phase-3--fresh-re-read-adoption-stale-surplus-cleanup)). Catches orphan orders whose ID was lost when the grid reinitialized mid-resync.
770
802
  - **Test**: new `testNoExcessCancelWhenMatchedOnGridIsZero` regression test — fresh grid with `matchedOnGrid=0`, non-zero chainCount+targetCount asserts zero cancel calls (`tests/test_grid_reconcile_regressions.ts`).
771
803
  - **Test**: `testPhase3CancelsStaleSurplusUntrackedByGrid` — 7 chain sells, target 5, all-VIRTUAL grid with matchedOnGrid=0, verifies Phase 3 cancels exactly 2 untracked surplus and does NOT cancel any tracked order (`tests/test_grid_reconcile_regressions.ts`).
772
804
  - **Test**: 9 scenarios in `test_validate_create_target_slots.ts` covering all four guard layers, released slots, malformed chain candidates, and no-assets fallback (`tests/test_validate_create_target_slots.ts`).
@@ -1314,7 +1346,7 @@ All notable changes to this project will be documented in this file.
1314
1346
 
1315
1347
  ### 2026-07-01
1316
1348
 
1317
- - **Fix**: prevent stale dust duplicates at the same price level — sync engine rejects orphan adoption when an active order already occupies that price. Reconcile unconditionally cancels duplicate chain orders on chain via `_cancelChainOrder` with `releaseUntrackedFunds: true` ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#duplicate-tolerance-5%C3%97-multiplier)). Dust detection expanded to interior partials sharing a price level with an active sibling.
1349
+ - **Fix**: prevent stale dust duplicates at the same price level — sync engine rejects orphan adoption when an active order already occupies that price. Reconcile unconditionally cancels duplicate chain orders on chain via `_cancelChainOrder` with `releaseUntrackedFunds: true` ([GRID_RECONCILE.md](docs/GRID_RECONCILE.md#duplicate-cancellation)). Dust detection expanded to interior partials sharing a price level with an active sibling.
1318
1350
  - **Chore**: version bumped to 1.0.5 across all manifests.
1319
1351
  - **Docs**: updated `CHANGELOG.md`, `docs/EVOLUTION.md`, `docs/README.md`, `docs/DEXBOT_COMPARISON.md`, `docs/FUND_MOVEMENT_AND_ACCOUNTING.md`.
1320
1352
 
package/README.md CHANGED
@@ -169,26 +169,28 @@ Keep the default settings first, and tune these:
169
169
  (super-mountain); the default `{ "sell": 1.0, "buy": 1.0 }` suits most
170
170
  setups.
171
171
 
172
- 4. **Set `gridPrice` to `"ama"`** — so the market adapter can center the grid
173
- on AMA. Pick a specific preset if desired: `"ama1"` is the fastest,
174
- `"ama4"` the slowest, and `"ama"` uses the pair's default preset.
172
+ 4. **Enable AMA** — new bots anchor on `gridPrice: "ama3"`, but the market
173
+ adapter only goes live once its per-bot `Price` flag is on. Open
174
+ `dexbot bot` → `2) Modify bot` → pick the bot → `6) Adapter` and set the
175
+ flags:
175
176
 
176
- 5. **Set the adapter flags** — `dexbot bot` → `2) Modify bot` → pick the bot
177
- → `6) Adapter`:
178
-
179
- - `Price` — AMA pricing and live adapter writes (turn **on** for AMA bots;
180
- without it the adapter only dry-runs)
177
+ - `Price` — **on for AMA bots**; without it the adapter only dry-runs
181
178
  - `Weight` — dynamic buy/sell weights (opt-in)
182
179
  - `Range` — AMA-slope range scaling (opt-in)
183
180
 
181
+ To change how closely the grid center tracks the market, set `gridPrice`
182
+ in `3) Price` to `"ama1"`–`"ama4"`: `"ama1"` reacts fastest, `"ama4"`
183
+ slowest and steadiest (higher numbers smooth more), or `"ama"` for the
184
+ pair's default preset.
185
+
184
186
  The flags are stored per bot in `market_adapter_whitelist.json` in the
185
187
  profiles directory and can be changed any time from the same editor
186
188
  section. Boolean prompts accept `y`/`yes`/`true` and `n`/`no`/`false`;
187
189
  Enter keeps the current value.
188
190
 
189
- 6. **Start DEXBot2** with `dexbot start`.
191
+ 5. **Start DEXBot2** with `dexbot start`.
190
192
 
191
- 7. **Tune `minPrice` / `maxPrice`** around the market's volatility range. Once
193
+ 6. **Tune `minPrice` / `maxPrice`** around the market's volatility range. Once
192
194
  AMA is active, tighten them around the maximum expected market volatility
193
195
  instead of using an unnecessarily wide range.
194
196
 
@@ -200,39 +202,106 @@ Configuration options from `dexbot bot`, stored in `bots.json` in the profiles d
200
202
 
201
203
  <details><summary><mark>Full parameter reference (click to expand)</mark></summary>
202
204
 
205
+ Grouped exactly as the bot editor shows them (`dexbot bot` → `2) Modify bot` → pick the bot):
206
+
207
+ **`1) Pair`**
208
+
203
209
  | Parameter | Type | Description |
204
210
  | :--- | :--- | :--- |
205
211
  | **`assetA`** | string | Base asset |
206
212
  | **`assetB`** | string | Quote asset |
213
+
214
+ **`2) Identity`**
215
+
216
+ | Parameter | Type | Description |
217
+ | :--- | :--- | :--- |
207
218
  | **`name`** | string | Friendly name for logging and CLI selection |
208
- | **`active`** | boolean | `false` to keep config without running |
209
- | **`dryRun`** | boolean | Simulate orders without broadcasting |
210
219
  | **`preferredAccount`** | string | BitShares account name for trading |
211
- | **`startPrice`** | num \| str | Initial price and adapter source. Default `"pool"` uses the liquidity-pool price; `"book"` uses the live order book mid price (best bid/ask); a number uses a fixed anchor. |
212
- | **`poolRef`** | string \| null | Optional pinned pool ID for `startPrice: "pool"`. Overrides pool discovery with a direct fetch (e.g. `"1.19.48"` or `"48"`). Useful when the trading pair has no native pool. Default `null`. |
213
- | **`minPrice`** | num \| str | Lower bound. Default `"2x"` means `gridPrice / 2` when AMA is active, otherwise `startPrice / 2`. |
214
- | **`maxPrice`** | num \| str | Upper bound. Default `"2x"` means `gridPrice * 2` when AMA is active, otherwise `startPrice * 2`. |
215
- | **`gridPrice`** | num \| str \| null | Grid reference. Use `"ama"` for the recommended AMA center (`"ama"` picks the pair's default preset; `"ama1"`–`"ama4"` pin fastest to slowest); `null` falls back to `startPrice`; numeric values use that fixed value. |
216
- | **`incrementPercent`** | number | Geometric step between orders. Default `0.5` = 0.5%. |
217
- | **`targetSpreadPercent`** | number | Width of the empty spread zone between buy and sell orders. Default `2` = 2%. Profit per completed cycle ≈ `spread - increment - fees`. |
218
- | **`weightDistribution`** | object | Advanced sizing control per side. Range `-1` to `2`: `-1` = super-valley, `0` = valley, `0.5` = neutral, `1` = mountain (default), `2` = super-mountain. Higher weight = more funds in orders near the market price; lower weight = more funds shifted toward the grid edge. Default `{ Sell: 1.0, Buy: 1.0 }`; leave unchanged for normal setup. |
219
- | **`botFunds`** | object | Capital: `{ Sell: "100%", Buy: 100% }`. Numbers or percentage strings |
220
- | **`activeOrders`** | object | Target active orders per side: `{ S: 20, B: 20 }` |
221
- | **`reserveOrders`** | object | Edge-pinned insurance orders resting live outside the active window, to catch fat fingers: `{ S: 0, B: 0 }` |
220
+ | **`active`** | boolean | Default `true`. `false` keeps the config without running it |
221
+ | **`dryRun`** | boolean | Default `false`. Simulate orders without broadcasting |
222
+
223
+ **`3) Price`**
224
+
225
+ | Parameter | Type | Description |
226
+ | :--- | :--- | :--- |
227
+ | **`minPrice`** | num \| str | `Range` lower bound. Default `"2x"` means `gridPrice / 2` when AMA is active, otherwise `startPrice / 2` |
228
+ | **`maxPrice`** | num \| str | `Range` upper bound. Default `"2x"` means `gridPrice * 2` when AMA is active, otherwise `startPrice * 2` |
229
+ | **`startPrice`** | num \| str | `Start` — initial price and adapter source. Default `"pool"` uses the liquidity-pool price; `"book"` uses the live order book mid price (best bid/ask); a number uses a fixed anchor |
230
+ | **`poolRef`** | string \| null | `Pool` — optional pinned pool ID for `startPrice: "pool"`. Overrides pool discovery with a direct fetch (e.g. `"1.19.48"` or `"48"`). Useful when the trading pair has no native pool. Ignored when `startPrice` is `"book"` or a number — `startPrice` is the master source. Default `null`; in the editor, `none`/`clear` (or the aliases `default`/`pool`/`auto`) clears the pin |
231
+ | **`gridPrice`** | num \| str \| null | `GridPrice` — grid reference for the x-factor bounds. Use `"ama"` for the recommended AMA center (`"ama"` picks the pair's default preset; `"ama1"`–`"ama4"` pin fastest to slowest; default `"ama3"`); `null` falls back to `startPrice`; numeric values use that fixed value |
232
+
233
+ **`4) Grid`**
234
+
235
+ | Parameter | Type | Description |
236
+ | :--- | :--- | :--- |
237
+ | **`weightDistribution`** | object | `Weights` — advanced sizing control per side. Range `-1` to `2`: `-1` = super-valley, `0` = valley, `0.5` = neutral, `1` = mountain (default), `2` = super-mountain. Higher weight = more funds in orders near the market price; lower weight = more funds shifted toward the grid edge. Default `{ sell: 1, buy: 1 }`; leave unchanged for normal setup |
238
+ | **`incrementPercent`** | number | `Increment` — geometric step between orders. Default `0.5` = 0.5% |
239
+ | **`targetSpreadPercent`** | number | `Spread` — width of the empty spread zone between buy and sell orders. Default `2` = 2%.<br>Profit per completed cycle ≈ `spread - increment - fees`. Must be at least 2.1 × `incrementPercent` |
240
+
241
+ **`5) Inventory`**
242
+
243
+ | Parameter | Type | Description |
244
+ | :--- | :--- | :--- |
245
+ | **`botFunds`** | object | `Sell`/`Buy` — capital allocation: `{ sell: "100%", buy: "100%" }`. Numbers or percentage strings |
246
+ | **`activeOrders`** | object | `MarketOrder` — target active orders per side, counted closest to the market: `{ sell: 20, buy: 20 }` |
247
+ | **`reserveOrders`** | object | `EdgeOrder` — edge-pinned insurance orders resting live outside the active window, to catch fat fingers: `{ buy: 0, sell: 0 }` (`buy` pins the grid floor, `sell` the grid ceiling; `0` disables per side) |
248
+
249
+ **`6) Adapter`**
250
+
251
+ These three booleans are stored per bot in `market_adapter_whitelist.json`, **not** in `bots.json`:
252
+
253
+ | Flag | Description |
254
+ | :--- | :--- |
255
+ | `ama` (Price) | AMA pricing and live adapter writes. Turn on for AMA bots; without it the adapter only dry-runs |
256
+ | `dynamicWeight` (Weight) | Dynamic buy/sell weights (opt-in; only takes effect while Price is on) |
257
+ | `asymmetricBounds` (Range) | AMA-slope range scaling (opt-in; only takes effect while Price is on) |
222
258
 
223
259
  </details>
224
260
 
225
- ### General Options (Global)
261
+ ### General Settings (Global)
262
+
263
+ General settings via `dexbot bot`, stored in `general.settings.json` in the profiles directory:
226
264
 
227
- Global settings via `dexbot bot`, stored in `general.settings.json` in the profiles directory:
265
+ <details><summary><mark>General settings reference (click to expand)</mark></summary>
228
266
 
229
- <details><summary><mark>Global settings reference (click to expand)</mark></summary>
267
+ Grouped exactly as `dexbot bot` → `6) General settings` shows them:
230
268
 
231
- - **Grid Health**: Grid Funds Regeneration % (default `3%`), RMS Divergence Threshold % (default `14.3%`), AMA Δ Threshold % (default `1%`, AMA center move that triggers a grid reset), AMA-Slope Δ Threshold % (default `8%`, slope-delta trigger as a percentage of max AMA slope)
232
- - **Order Recovery**: Partial Dust Threshold % (default `5%`), Dust Cancel Delay (default `30s`, `-1` = off, `0` = instant)
233
- - **Node Configuration**: Node List (10 default public BitShares nodes), Health Check Interval (default `240 min`), Preferred Node (default `none`)
234
- - **Log Level**: `debug`, `info`, `warn`, `error`, `critical`. Fine-grained category control via `LOGGING_CONFIG` (see [Logging](docs/LOGGING.md))
235
- - **Updater**: Active (default `OFF`), Branch (`auto`/`main`/`dev`/`test`), Interval (default `1 day`), Time (default `00:00`)
269
+ **`1) Grid Drift`**
270
+
271
+ | Setting | Default | Description |
272
+ | :--- | :--- | :--- |
273
+ | Grid Funds Regeneration % | `3` | `Funds` — recalculates grid size when spare funds reach this % of a side's allocation (or the tracked grid overshoots allocation by this %) |
274
+ | RMS Divergence Threshold % | `14.3` | `RMS` — triggers a grid reset when the calculated grid diverges from on-chain state; `0` disables (JSON only) |
275
+ | AMA Δ Threshold % | `1` | `AMA Δ` — % move in the AMA center price that triggers a grid reset |
276
+ | AMA-Slope Δ Threshold % | `8` | `AMA-Slope Δ` — slope-delta trigger as a percentage of max AMA slope |
277
+
278
+ **`2) Order Maint.`**
279
+
280
+ | Setting | Default | Description |
281
+ | :--- | :--- | :--- |
282
+ | Partial Dust Threshold % | `5` | `Dust Threshold` — orders below this % of their ideal size are treated as dust and rotated (cancelled and re-placed at proper size) to keep the grid symmetric |
283
+ | Health Check Interval (min) | `240` | `Health Check` — how often nodes are health-checked (stored as milliseconds) |
284
+
285
+ **`3) Node Config`**
286
+
287
+ | Setting | Default | Description |
288
+ | :--- | :--- | :--- |
289
+ | Node List | 7 public BitShares nodes | `Nodes` — sub-editor: `A` add, `R` remove (at least one must remain), `D` done |
290
+ | Preferred Node | `none` | Pin one node URL; empty = automatic latency-based selection with failover |
291
+
292
+ **`4) Log Level`**
293
+
294
+ | Setting | Default | Description |
295
+ | :--- | :--- | :--- |
296
+ | Log Level | `info` | `debug`, `info`, `warn`, `error`. `critical` is only accepted by editing `general.settings.json` directly. Fine-grained category control via `LOGGING_CONFIG` (see [Logging](docs/LOGGING.md)) |
297
+
298
+ **`5) Updater`**
299
+
300
+ | Setting | Default | Description |
301
+ | :--- | :--- | :--- |
302
+ | Active | `OFF` | Enables the automated updater (editor shows `[ON/OFF]`) |
303
+ | Branch | `auto` | `main`, `dev`, `test`, or `auto` (detected current branch) |
304
+ | Schedule | `1` at `00:00` | Cron schedule (`Interval` days, `Time` HH:mm, 24h) |
236
305
 
237
306
  </details>
238
307
 
@@ -258,20 +327,20 @@ First-run details and common mistakes are covered in the [BitShares Onboarding T
258
327
 
259
328
  ```bash
260
329
  dexbot key # Master password/keyring
261
- dexbot bot # Interactive bot configurator (adapter Price/Weight/Range flags: 6) Adapter)
330
+ dexbot bot # Interactive bot configurator (adapter flags: 2) Modify bot → 6) Adapter)
262
331
 
263
332
  dexbot reset {all|<bot>} # Regenerate grid
264
333
  dexbot disable {all|<bot>} # Disable bot in config
265
334
  dexbot enable {all|<bot>} # Enable bot in config
266
335
 
267
336
  dexbot stat # Runtime status (unlock or PM2)
268
- dexbot order [<bot>] # Analyze order grids
269
- dexbot order --export # Export as HTML to analysis/charts/
337
+ dexbot order [<bot>] # Analyze order grids (--export → HTML to analysis/charts/)
270
338
  dexbot tv <bot|pool|A/B> # TradingView 1h chart with AMA overlay (default: 3 months)
271
339
  dexbot credit [<bot>] # Live summed MPA + borrowed-credit positions per asset per bot
340
+ dexbot export <bot> # Export trades + settings (CSV/JSON) for analysis/
272
341
 
273
342
  dexbot update # Update DEXBot2
274
- dexbot clear # Clear log files
343
+ dexbot clear # Clear log files (also clear-orders, clear-market-adapter, clear-all)
275
344
  dexbot default # Reset settings to defaults
276
345
  ```
277
346
 
@@ -21,7 +21,7 @@ Tools that inspect DEXBot trading behavior and the market data it operates on. O
21
21
  | Tool | Ask this when… | One-line command |
22
22
  |------|----------------|------------------|
23
23
  | [`trade_profitability.ts`](#trade-profitability-analyzer-trade_profitabilityts) | "Is my bot making money?" — PnL, R-multiples, drawdown | `npm run analysis:trade-pnl -- <account-id>` |
24
- | [`grid_correction_check.ts`](#grid-correction-check-grid_correction_checkts) | "Is my grid placing orders monotonically?" — sell/buy price inversion detector | `npm run analysis:grid-check -- --bot-key <bot-key>` |
24
+ | [`grid_correction_check.ts`](#last-fill-guard-check-grid_correction_checkts) | "Are fills respecting the pivot ± half-increment guard?" | `npm run analysis:grid-check -- --bot-key <bot-key>` |
25
25
  | [`analyze_risk_profile.ts`](#risk-profile-analyzer-analyze_risk_profilets) | "How wide should my Safe Range clamps be?" | `node dist/analysis/analyze_risk_profile.js --bot-key <bot-key>` |
26
26
  | [`analyze_trade_heatmap.ts`](#trade-heatmap-analyze_trade_heatmapts) | "Where did trade volume cluster vs the AMA?" | `node dist/analysis/analyze_trade_heatmap.js --bot-key <bot-key>` |
27
27
  | [`tradingview/analyze_tradingview.ts`](#tradingview-chart-tradingviewanalyze_tradingviewts) | "Just give me a candle chart" | `dexbot tv <bot-key>` |
@@ -32,8 +32,6 @@ Tools that inspect DEXBot trading behavior and the market data it operates on. O
32
32
  | [`ama_fitting/`](#ama-fitting) | "Which AMA preset fits this market?" | `node dist/analysis/ama_fitting/optimizer_high_resolution.js --data <lp-file>` |
33
33
  | [`bot_fitting/`](#bot-fitting) | "What spread / increment / ratio for my grid?" | `node dist/analysis/bot_fitting/backtest_ama_sweep.js --data <lp-file>` |
34
34
 
35
- > `analyze_derivatives.ts` (SMA / MACD / RSI derivative layer, uses `derivative_chart_generator.ts`) is a legacy tool surfaced via `npm run analysis:derivatives` — kept for reference.
36
-
37
35
  > `<account-id>` = a BitShares `1.2.x` account ID or name. `<bot-key>` = a key from `profiles/bots.json`. `<lp-file>` = a JSON file under `market_adapter/data/lp/<pair>/lp_pool_<id>_<interval>.json`.
38
36
 
39
37
  ## Key Terms
@@ -164,7 +162,6 @@ node dist/analysis/trade_profitability.js 1.2.123456 \
164
162
  | `--end <iso>` | — | End time |
165
163
  | `--hours <n>` | `168` (7d) | Lookback hours (alternative to start/end) |
166
164
  | `--asset <id>` | all | Filter to one base asset ID |
167
- | `--lookup` | off | Legacy (no-op): account names always resolve automatically |
168
165
  | `--refresh-account` | off | Force re-resolution and update the stored `accountId` |
169
166
  | `--csv <file>` | — | Export chronologically sorted trade list |
170
167
  | `--json <file>` | — | Export full analysis with per-pair PnL data |
@@ -223,11 +220,11 @@ node dist/analysis/trade_profitability.js 1.2.123456 \
223
220
 
224
221
  </details>
225
222
 
226
- ### Grid Correction Check (`grid_correction_check.ts`)
223
+ ### LAST-FILL-GUARD Check (`grid_correction_check.ts`)
227
224
 
228
- Validates grid discipline from the same Kibana fill pipeline as `trade_profitability.ts`: two consecutive same-direction fills on a pair must be monotonic — sell prices rising, buy prices falling (equal is OK). An inversion means the bot placed an order below its own previous sell (or above its own previous buy), e.g. an orphaned order filling outside grid accounting. Used as the external regression gate for the orphan-fix plans in `docs/ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md`.
225
+ Validates LAST-FILL-GUARD discipline from the same Kibana fill pipeline as `trade_profitability.ts`. For a previous fill at price `x` and grid increment `i`, the next order must satisfy `BUY < x × (1 − i/2/100)` and `SELL > x × (1 + i/2/100)`, regardless of the previous fill's side. A violation is a buy or sell fill inside the prohibited half-increment band around its pivot.
229
226
 
230
- **Pipeline:** Kibana `fill_order` query (paginated `search_after`) → on-chain asset precision resolution → buy/sell classification → chronological sort → per-order/price-epoch aggregation (partial fills at one price collapsed to weighted-average; repriced order lifetimes kept separate) → consecutive same-direction pair comparison → violation report with daily histogram.
227
+ **Pipeline:** Kibana `fill_order` query (paginated `search_after`) → on-chain asset precision resolution → buy/sell classification → chronological sort → per-order/price-epoch aggregation (partial fills at one price collapsed to weighted-average; repriced order lifetimes kept separate) → consecutive pivot-band comparison → violation report with daily histogram.
231
228
 
232
229
  ```bash
233
230
  # Per-order aggregated check (default), last 7 days
@@ -239,8 +236,8 @@ npm run analysis:grid-check -- --bot-key <bot-key> --hours 720 --json out.json -
239
236
  # Raw fill granularity instead of per-order aggregation
240
237
  npm run analysis:grid-check -- --bot-key <bot-key> --per-fill --hours 168
241
238
 
242
- # Forgive small adverse moves within 0.1%
243
- npm run analysis:grid-check -- --bot-key <bot-key> --hours 168 --tolerance 0.1
239
+ # Override the bot's configured grid increment
240
+ npm run analysis:grid-check -- --bot-key <bot-key> --hours 168 --increment 0.5
244
241
  ```
245
242
 
246
243
  Exit code `0` = pass, `2` = violations found, `1` = fatal error. Bot keys resolve via `profiles/bots.json` (`--list-bots` to enumerate); the account defaults to the bot's stored `accountId` when present (no chain lookup — the ID is auto-saved next to `preferredAccount` after the first successful name resolution, re-verified with `--refresh-account`), otherwise `preferredAccount` is resolved on-chain, and can be overridden with `--account <1.2.x|name>`.
@@ -253,18 +250,18 @@ Exit code `0` = pass, `2` = violations found, `1` = fatal error. Bot keys resolv
253
250
  | `--hours <n>` | `168` | Lookback hours from now |
254
251
  | `--start <iso>` / `--end <iso>` | — | Absolute time window |
255
252
  | `--account <id>` | bot `preferredAccount` | Override account ID or name |
256
- | `--lookup` | off | Legacy (no-op): account names always resolve via BitShares node when no stored ID exists |
257
253
  | `--refresh-account` | off | Force re-resolution of `preferredAccount` and update the stored `accountId` when it changed |
254
+ | `--increment <pct>` | bot config / `0.5` | Grid increment used to derive the half-increment guard band |
258
255
  | `--per-fill` | off | Check at fill granularity instead of per-order aggregated |
259
256
  | `--include-cross-pair` | off | Also check consecutive fills across different pairs |
260
- | `--tolerance <pct>` | `0` | Adverse price move (%) forgiven before flagging |
257
+ | `--tolerance <pct>` | — | Deprecated compatibility alias for `--increment`; its value is doubled and a warning is emitted |
261
258
  | `--json <file>` / `--csv <file>` | — | Export violations |
262
- | `--verbose` | off | Print the full trade sequence |
259
+ | `--verbose` | off | Print the fetched trade sequence before checking |
263
260
  | `--list-bots` | — | List available bot keys and exit |
264
261
 
265
262
  </details>
266
263
 
267
- **Notes:** strict sat-level comparison is the ground truth (`--tolerance` only forgives small inversions); partial fills at one price are collapsed to a weighted-average price in the default mode, but fills after a native order repricing are kept in separate price epochs so updated orders are not mixed together.
264
+ **Notes:** this is an offline approximation of decision-time placement. Batch-placed orders can share an earlier pivot, and the tool does not model the runtime spread-correction bypass. In the default mode, partial fills at one price are collapsed to a weighted average while fills from separate native order repricing epochs remain independent.
268
265
 
269
266
  ## Charts & Visualization
270
267
 
@@ -395,7 +392,6 @@ Shared analyzers and chart renderers for the dynamic-weight signal path. Core en
395
392
  **Research docs:**
396
393
  - [README.md](trend_detection/README.md) — directory overview and module index
397
394
  - [DYNAMIC_WEIGHT_RESEARCH.md](trend_detection/DYNAMIC_WEIGHT_RESEARCH.md) — AMA+Kalman blend with Hurst/PE regime gating, formula reference, knob guide
398
- - [SIGNAL_DOCUMENTATION.md](trend_detection/SIGNAL_DOCUMENTATION.md) — legacy SMA/MACD/RSI derivative signal layer
399
395
 
400
396
  <details><summary>Modules (click to expand)</summary>
401
397
 
@@ -509,7 +505,6 @@ These npm scripts wrap common analysis runners:
509
505
  | `npm run analysis:tradingview` | `node dist/analysis/tradingview/analyze_tradingview.js` |
510
506
  | `npm run analysis:trade-pnl` | `node dist/analysis/trade_profitability.js` |
511
507
  | `npm run analysis:grid-check` | `node dist/analysis/grid_correction_check.js` |
512
- | `npm run analysis:derivatives` | `node dist/analysis/analyze_derivatives.js` (legacy SMA/MACD/RSI layer, reference only) |
513
508
  | `npm run ama:chart:lp-local` | `node dist/analysis/ama_fitting/generate_unified_comparison_chart.js` (chart also auto-generated by optimizer) |
514
509
 
515
510
  All accept `--` forwarded flags.
@@ -521,7 +516,7 @@ npm run analysis:tradingview -- --source market_adapter --bot-key <bot-key>
521
516
  # Trade PnL
522
517
  npm run analysis:trade-pnl -- 1.2.123456 --hours 720
523
518
 
524
- # Grid correction check (monotonicity regression gate)
519
+ # LAST-FILL-GUARD check
525
520
  npm run analysis:grid-check -- --bot-key <bot-key> --hours 168
526
521
 
527
522
  # File-based
@@ -158,14 +158,4 @@ async function resolveAccountRef(accountRef: string, options: ResolveOptions = {
158
158
  return { accountId: String(id), botKey: null, botMeta: null, source: 'resolved', reason: null };
159
159
  }
160
160
 
161
- export {
162
- ACCOUNT_ID_RE,
163
- lookupNameOnChain,
164
- resolveBotAccount,
165
- resolveAccountRef,
166
- ResolveOptions,
167
- ResolvedAccount,
168
- ResolveSource,
169
- ResolveFailure,
170
- NameLookup,
171
- };
161
+ export { resolveBotAccount, resolveAccountRef };
@@ -207,5 +207,5 @@ function buildTopUpdaterAccountsQuery(lookbackHours: number, topN: number = 200,
207
207
 
208
208
  // ─── Exports ──────────────────────────────────────────────────────────────────
209
209
 
210
- export { DEFAULT_CONFIG, kibanaSearch, buildOrderPriceQuery, buildTopSellerAccountsQuery, buildTopCancellerAccountsQuery, buildTopFilledAccountsQuery, buildTopUpdaterAccountsQuery, OP_LIMIT_ORDER_UPDATE }
210
+ export { DEFAULT_CONFIG, kibanaSearch, buildOrderPriceQuery, buildTopSellerAccountsQuery, buildTopCancellerAccountsQuery, buildTopFilledAccountsQuery, buildTopUpdaterAccountsQuery }
211
211
 
@@ -44,4 +44,4 @@ async function withReadOnlyClient<T>(fn: (client: any) => Promise<T>): Promise<T
44
44
  }
45
45
  }
46
46
 
47
- export { defaultNodePool, withReadOnlyClient };
47
+ export { withReadOnlyClient };
@@ -219,16 +219,10 @@ async function fetchAllFills(config: any, accountId: string, gte: string, lte: s
219
219
 
220
220
  export {
221
221
  BTS_ID,
222
- OP_FILL_ORDER,
223
- ASSETS,
224
- resolvedPrecisions,
225
222
  assetSymbol,
226
223
  assetPrec,
227
224
  toReal,
228
225
  resolveAssetPrecisions,
229
- buildFillQuery,
230
226
  fetchAllFills,
231
- AssetInfo,
232
- AssetAmount,
233
227
  FillRecord,
234
228
  };
@@ -2,9 +2,9 @@
2
2
  'use strict';
3
3
 
4
4
  /**
5
- * GRID CORRECTION CHECK
5
+ * LAST-FILL-GUARD CHECK
6
6
  *
7
- * Validates LAST-FILL-GUARD discipline (ceb53819): pivot ± halfIncrement
7
+ * Validates LAST-FILL-GUARD discipline: pivot ± halfIncrement
8
8
  * Last fill @x with increment i (half=i/2) gates BOTH sides regardless of
9
9
  * last side — BUY must be < x*(1-half/100), SELL > x*(1+half/100).
10
10
  * e.g. x=1000, i=0.5% => BUY < 997.5 / SELL > 1002.5.
@@ -21,7 +21,7 @@
21
21
  * modules/constants.ts:DEFAULT_CONFIG.incrementPercent fallback (0.5).
22
22
  *
23
23
  * Fetches fill_order operations from Kibana (same pipeline as
24
- * trade_profitability.ts) and checks for price-order violations.
24
+ * trade_profitability.ts) and checks for last-fill guard violations.
25
25
  *
26
26
  * Usage:
27
27
  * node dist/analysis/grid_correction_check.js --bot-key <bot-key> --hours 168
@@ -166,7 +166,6 @@ Time range (one of):
166
166
 
167
167
  Options:
168
168
  --account <id> Override account ID (default: from bot preferredAccount)
169
- --lookup Legacy: account names always resolve via BitShares node
170
169
  --refresh-account Force re-resolution of preferredAccount and update the
171
170
  stored accountId when it changed (default: reuse the
172
171
  stored accountId with no chain lookup)
@@ -176,7 +175,7 @@ Options:
176
175
  --include-cross-pair Check consecutive fills across different pairs (default: same pair only)
177
176
  --json <file> Export violations as JSON
178
177
  --csv <file> Export violations as CSV
179
- --verbose Show all consecutive pairs, not just violations
178
+ --verbose Print the fetched trade sequence before checking
180
179
  --list-bots List available bot keys and exit
181
180
  --help, -h Show this help
182
181
 
@@ -208,7 +207,6 @@ function parseArgs() {
208
207
  start: null,
209
208
  end: null,
210
209
  account: null,
211
- lookup: false,
212
210
  refreshAccount: false,
213
211
  perFill: false,
214
212
  includeCrossPair: false,
@@ -225,7 +223,6 @@ function parseArgs() {
225
223
  case '--start': opts.start = args[++i]; break;
226
224
  case '--end': opts.end = args[++i]; break;
227
225
  case '--account': opts.account = args[++i]; break;
228
- case '--lookup': opts.lookup = true; break;
229
226
  case '--refresh-account': opts.refreshAccount = true; break;
230
227
  case '--per-fill': opts.perFill = true; break;
231
228
  case '--include-cross-pair': opts.includeCrossPair = true; break;
@@ -472,10 +469,9 @@ function detectViolations(
472
469
  items: (TradeFill | AggregatedOrder)[],
473
470
  includeCrossPair: boolean,
474
471
  incrementPercent: number,
475
- ): { violations: Violation[]; checkedPairs: number; sameDirectionPairs: number } {
472
+ ): { violations: Violation[]; checkedTransitions: number } {
476
473
  const violations: Violation[] = [];
477
- let checkedPairs = 0;
478
- let sameDirectionPairs = 0;
474
+ let checkedTransitions = 0;
479
475
 
480
476
  // Helper for a single chronological sequence (already filtered to one pair or global)
481
477
  function checkSequence(seq: (TradeFill | AggregatedOrder)[]) {
@@ -484,8 +480,7 @@ function detectViolations(
484
480
  const curr = seq[i] as any;
485
481
  // Skip same orderId (multi-fill split of one order) — aggregated mode already collapsed, but per-fill may split
486
482
  if (prev.orderId && prev.orderId === curr.orderId) continue;
487
- checkedPairs++;
488
- if (prev.direction === curr.direction) sameDirectionPairs++;
483
+ checkedTransitions++;
489
484
 
490
485
  const check = isLastFillGuardBlocked(curr.price, curr.direction, prev.price, prev.direction, incrementPercent);
491
486
  if (check.blocked) {
@@ -528,7 +523,7 @@ function detectViolations(
528
523
  }
529
524
  // Sort violations chronologically for reporting
530
525
  violations.sort((a, b) => new Date(a.curr.time).getTime() - new Date(b.curr.time).getTime());
531
- return { violations, checkedPairs, sameDirectionPairs };
526
+ return { violations, checkedTransitions };
532
527
  }
533
528
 
534
529
  // ─── Reporting ────────────────────────────────────────────────────────────────
@@ -541,8 +536,7 @@ function printReport(
541
536
  trades: TradeFill[],
542
537
  orders: AggregatedOrder[] | null,
543
538
  violations: Violation[],
544
- checkedPairs: number,
545
- sameDirectionPairs: number,
539
+ checkedTransitions: number,
546
540
  skipped: number,
547
541
  rangeLabel: string,
548
542
  botKey: string,
@@ -565,7 +559,7 @@ function printReport(
565
559
 
566
560
  console.log('');
567
561
  console.log('═══════════════════════════════════════════════════════════════════');
568
- console.log(' GRID CORRECTION CHECK — LAST-FILL-GUARD (pivot ± halfIncrement)');
562
+ console.log(' LAST-FILL-GUARD CHECK (pivot ± halfIncrement)');
569
563
  console.log('═══════════════════════════════════════════════════════════════════');
570
564
  console.log(` Bot key: ${botKey}${botMeta?.name ? ` (name: ${botMeta.name})` : ''}`);
571
565
  if (botMeta) console.log(` Pair: ${botMeta.assetA ?? '?'} / ${botMeta.assetB ?? '?'}`);
@@ -582,16 +576,16 @@ function printReport(
582
576
  if (orders) console.log(` Orders (aggregated): ${orders.length} (from ${trades.length} fills)`);
583
577
  console.log(` Pairs observed: ${[...pairGroups.keys()].join(', ') || '-'}`);
584
578
  if (skipped > 0) console.log(` Skipped (precision): ${skipped}`);
585
- console.log(` Pairs checked: ${checkedPairs} consecutive pairs (same-direction pairs: ${sameDirectionPairs})`);
586
- console.log(` Violations: ${violations.length}${checkedPairs > 0 ? ` (${((violations.length / checkedPairs) * 100).toFixed(2)}%)` : ''}`);
579
+ console.log(` Transitions checked: ${checkedTransitions} consecutive fill/order transitions`);
580
+ console.log(` Violations: ${violations.length}${checkedTransitions > 0 ? ` (${((violations.length / checkedTransitions) * 100).toFixed(2)}%)` : ''}`);
587
581
  console.log('');
588
582
 
589
583
  if (violations.length === 0) {
590
- console.log(' ✅ PASS — no grid inversions detected (all BUY < pivot-half, SELL > pivot+half).');
584
+ console.log(' ✅ PASS — no LAST-FILL-GUARD violations detected (all BUY < pivot-half, SELL > pivot+half).');
591
585
  console.log('');
592
- if (checkedPairs === 0) {
593
- console.log(' Note: no consecutive pairs in range to check.');
594
- console.log(' (Need at least two fills/orders on the same pair.)');
586
+ if (checkedTransitions === 0) {
587
+ console.log(' Note: no consecutive transitions in range to check.');
588
+ console.log(' (Need at least two fills/orders to form a transition.)');
595
589
  }
596
590
  console.log('');
597
591
  return;
@@ -709,7 +703,7 @@ async function main() {
709
703
  const opts = parseArgs();
710
704
  const { gte, lte, label } = resolveTimeRange(opts);
711
705
 
712
- console.log(`\nGrid correction check — bot-key: ${opts.botKey}`);
706
+ console.log(`\nLast-fill guard check — bot-key: ${opts.botKey}`);
713
707
  console.log(`Range: ${label}`);
714
708
 
715
709
  const resolvedAccount = await resolveBotAccount(opts.botKey, {
@@ -770,10 +764,10 @@ async function main() {
770
764
  items = orders;
771
765
  }
772
766
 
773
- const { violations, checkedPairs, sameDirectionPairs } = detectViolations(items, opts.includeCrossPair, incrementPercent);
767
+ const { violations, checkedTransitions } = detectViolations(items, opts.includeCrossPair, incrementPercent);
774
768
 
775
769
  const ordersForReport = opts.perFill ? null : (items as AggregatedOrder[]);
776
- printReport(trades, ordersForReport, violations, checkedPairs, sameDirectionPairs, skipped, label, opts.botKey, accountId, botMeta, opts.perFill, opts.includeCrossPair, incrementPercent, gte, lte);
770
+ printReport(trades, ordersForReport, violations, checkedTransitions, skipped, label, opts.botKey, accountId, botMeta, opts.perFill, opts.includeCrossPair, incrementPercent, gte, lte);
777
771
 
778
772
  if (opts.json) exportJson(opts.json, violations, trades, label, opts.botKey, accountId, incrementPercent);
779
773
  if (opts.csv) exportCsv(opts.csv, violations);
@@ -781,7 +775,7 @@ async function main() {
781
775
  process.exit(violations.length > 0 ? 2 : 0);
782
776
  }
783
777
 
784
- export { isLastFillGuardBlocked, classifyFills, aggregateByOrder, detectViolations, TradeFill, FillRecord, Violation, AggregatedOrder };
778
+ export { isLastFillGuardBlocked, classifyFills, aggregateByOrder, detectViolations, TradeFill, Violation, AggregatedOrder };
785
779
 
786
780
  if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
787
781
  main().catch(e => {
@@ -96,4 +96,4 @@ function resolveSource(config: SourceConfig, options: { quiet?: boolean } = {}):
96
96
  }
97
97
 
98
98
  export { resolveSource, listAvailableBots }
99
- export type { SourceConfig, SourceResolution }
99
+ export type { SourceConfig }