dexbot 1.6.4 → 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 (240) hide show
  1. package/CHANGELOG.md +75 -3
  2. package/README.md +109 -40
  3. package/analysis/README.md +19 -17
  4. package/analysis/account_resolver.ts +1 -11
  5. package/analysis/analyze_dynamic_weight.ts +9 -3
  6. package/analysis/bot_usage/kibana_bot_queries.ts +1 -1
  7. package/analysis/chain_pool.ts +1 -1
  8. package/analysis/fills_source.ts +0 -6
  9. package/analysis/grid_correction_check.ts +20 -26
  10. package/analysis/resolve_source.ts +1 -1
  11. package/analysis/trade_profitability.ts +2 -5
  12. package/analysis/tradingview/analyze_tradingview.ts +5 -0
  13. package/analysis/tradingview/tradingview_uplot_chart_generator.ts +2 -2
  14. package/analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md +35 -2
  15. package/analysis/trend_detection/README.md +1 -3
  16. package/analysis/trend_detection/dynamic_weight_chart_generator.ts +82 -10
  17. package/analysis/trend_detection/package.json +1 -1
  18. package/claw/modules/dexbot_profiles.ts +4 -3
  19. package/claw/package.json +1 -1
  20. package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
  21. package/claw/runtimes/openclaw-plugin/package.json +1 -1
  22. package/claw/tests/test_claw_mcp_transport.ts +2 -2
  23. package/claw/tests/test_dexbot_profiles.ts +18 -1
  24. package/dist/analysis/account_resolver.d.ts +1 -4
  25. package/dist/analysis/account_resolver.d.ts.map +1 -1
  26. package/dist/analysis/account_resolver.js +1 -1
  27. package/dist/analysis/account_resolver.js.map +1 -1
  28. package/dist/analysis/analyze_dynamic_weight.js +9 -3
  29. package/dist/analysis/analyze_dynamic_weight.js.map +1 -1
  30. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -2
  31. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
  32. package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -1
  33. package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
  34. package/dist/analysis/chain_pool.d.ts +1 -3
  35. package/dist/analysis/chain_pool.d.ts.map +1 -1
  36. package/dist/analysis/chain_pool.js +1 -1
  37. package/dist/analysis/chain_pool.js.map +1 -1
  38. package/dist/analysis/fills_source.d.ts +1 -51
  39. package/dist/analysis/fills_source.d.ts.map +1 -1
  40. package/dist/analysis/fills_source.js +1 -1
  41. package/dist/analysis/fills_source.js.map +1 -1
  42. package/dist/analysis/grid_correction_check.d.ts +2 -3
  43. package/dist/analysis/grid_correction_check.d.ts.map +1 -1
  44. package/dist/analysis/grid_correction_check.js +18 -26
  45. package/dist/analysis/grid_correction_check.js.map +1 -1
  46. package/dist/analysis/resolve_source.d.ts +1 -1
  47. package/dist/analysis/resolve_source.d.ts.map +1 -1
  48. package/dist/analysis/trade_profitability.d.ts.map +1 -1
  49. package/dist/analysis/trade_profitability.js +2 -7
  50. package/dist/analysis/trade_profitability.js.map +1 -1
  51. package/dist/analysis/tradingview/analyze_tradingview.d.ts.map +1 -1
  52. package/dist/analysis/tradingview/analyze_tradingview.js +5 -0
  53. package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -1
  54. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +2 -2
  55. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
  56. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +82 -10
  57. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
  58. package/dist/dexbot.d.ts.map +1 -1
  59. package/dist/dexbot.js +85 -140
  60. package/dist/dexbot.js.map +1 -1
  61. package/dist/market_adapter/core/asymmetric_bounds.d.ts +2 -2
  62. package/dist/market_adapter/core/asymmetric_bounds.d.ts.map +1 -1
  63. package/dist/market_adapter/core/asymmetric_bounds.js +15 -12
  64. package/dist/market_adapter/core/asymmetric_bounds.js.map +1 -1
  65. package/dist/market_adapter/core/kibana_candles.d.ts +1 -15
  66. package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -1
  67. package/dist/market_adapter/core/kibana_candles.js +1 -1
  68. package/dist/market_adapter/core/kibana_candles.js.map +1 -1
  69. package/dist/market_adapter/inputs/fetch_lp_data.d.ts +1 -35
  70. package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
  71. package/dist/market_adapter/inputs/fetch_lp_data.js +10 -54
  72. package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
  73. package/dist/market_adapter/inputs/kibana_feed_source.d.ts +1 -8
  74. package/dist/market_adapter/inputs/kibana_feed_source.d.ts.map +1 -1
  75. package/dist/market_adapter/inputs/kibana_feed_source.js +1 -1
  76. package/dist/market_adapter/inputs/kibana_feed_source.js.map +1 -1
  77. package/dist/market_adapter/inputs/window_cache.d.ts +2 -63
  78. package/dist/market_adapter/inputs/window_cache.d.ts.map +1 -1
  79. package/dist/market_adapter/inputs/window_cache.js +22 -102
  80. package/dist/market_adapter/inputs/window_cache.js.map +1 -1
  81. package/dist/market_adapter/interval_utils.d.ts +1 -1
  82. package/dist/market_adapter/interval_utils.js +1 -1
  83. package/dist/modules/account_bots.d.ts +70 -6
  84. package/dist/modules/account_bots.d.ts.map +1 -1
  85. package/dist/modules/account_bots.js +353 -149
  86. package/dist/modules/account_bots.js.map +1 -1
  87. package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -1
  88. package/dist/modules/bitshares-native/crypto/ecc.browser.js +0 -31
  89. package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -1
  90. package/dist/modules/bot_defaults.d.ts +98 -0
  91. package/dist/modules/bot_defaults.d.ts.map +1 -0
  92. package/dist/modules/bot_defaults.js +169 -0
  93. package/dist/modules/bot_defaults.js.map +1 -0
  94. package/dist/modules/bot_settings.d.ts.map +1 -1
  95. package/dist/modules/bot_settings.js +4 -1
  96. package/dist/modules/bot_settings.js.map +1 -1
  97. package/dist/modules/config.d.ts +1 -0
  98. package/dist/modules/config.d.ts.map +1 -1
  99. package/dist/modules/config.js +1 -0
  100. package/dist/modules/config.js.map +1 -1
  101. package/dist/modules/constants.d.ts +11 -2
  102. package/dist/modules/constants.d.ts.map +1 -1
  103. package/dist/modules/constants.js +40 -27
  104. package/dist/modules/constants.js.map +1 -1
  105. package/dist/modules/credit_runtime.d.ts +0 -2
  106. package/dist/modules/credit_runtime.d.ts.map +1 -1
  107. package/dist/modules/credit_runtime.js +1 -10
  108. package/dist/modules/credit_runtime.js.map +1 -1
  109. package/dist/modules/dexbot_class.d.ts +13 -10
  110. package/dist/modules/dexbot_class.d.ts.map +1 -1
  111. package/dist/modules/dexbot_class.js +0 -9
  112. package/dist/modules/dexbot_class.js.map +1 -1
  113. package/dist/modules/dexbot_cow_runtime.d.ts +13 -0
  114. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  115. package/dist/modules/dexbot_cow_runtime.js +13 -1
  116. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  117. package/dist/modules/dexbot_maintenance_runtime.d.ts +1 -1
  118. package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
  119. package/dist/modules/dexbot_maintenance_runtime.js +9 -4
  120. package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
  121. package/dist/modules/launcher/adapter_requirement.js +1 -1
  122. package/dist/modules/launcher/launch_modes.d.ts +17 -1
  123. package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
  124. package/dist/modules/launcher/launch_modes.js +18 -1
  125. package/dist/modules/launcher/launch_modes.js.map +1 -1
  126. package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
  127. package/dist/modules/launcher/monolithic_runtime.js +8 -1
  128. package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
  129. package/dist/modules/market_adapter_whitelist.d.ts +40 -1
  130. package/dist/modules/market_adapter_whitelist.d.ts.map +1 -1
  131. package/dist/modules/market_adapter_whitelist.js +161 -11
  132. package/dist/modules/market_adapter_whitelist.js.map +1 -1
  133. package/dist/modules/order/accounting.d.ts +4 -18
  134. package/dist/modules/order/accounting.d.ts.map +1 -1
  135. package/dist/modules/order/accounting.js +4 -34
  136. package/dist/modules/order/accounting.js.map +1 -1
  137. package/dist/modules/order/export.d.ts +9 -12
  138. package/dist/modules/order/export.d.ts.map +1 -1
  139. package/dist/modules/order/export.js +9 -12
  140. package/dist/modules/order/export.js.map +1 -1
  141. package/dist/modules/order/grid.d.ts +44 -40
  142. package/dist/modules/order/grid.d.ts.map +1 -1
  143. package/dist/modules/order/grid.js +66 -48
  144. package/dist/modules/order/grid.js.map +1 -1
  145. package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
  146. package/dist/modules/order/grid_reconcile.js +111 -20
  147. package/dist/modules/order/grid_reconcile.js.map +1 -1
  148. package/dist/modules/order/grid_reconcile_internal.d.ts +5 -3
  149. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  150. package/dist/modules/order/grid_reconcile_internal.js +18 -3
  151. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  152. package/dist/modules/order/manager.d.ts +0 -8
  153. package/dist/modules/order/manager.d.ts.map +1 -1
  154. package/dist/modules/order/manager.js +3 -12
  155. package/dist/modules/order/manager.js.map +1 -1
  156. package/dist/modules/order/utils/order.d.ts +22 -7
  157. package/dist/modules/order/utils/order.d.ts.map +1 -1
  158. package/dist/modules/order/utils/order.js +103 -21
  159. package/dist/modules/order/utils/order.js.map +1 -1
  160. package/dist/modules/order/utils/system.d.ts +5 -1
  161. package/dist/modules/order/utils/system.d.ts.map +1 -1
  162. package/dist/modules/order/utils/system.js +5 -2
  163. package/dist/modules/order/utils/system.js.map +1 -1
  164. package/dist/modules/order/utils/withPoolRef.d.ts +12 -0
  165. package/dist/modules/order/utils/withPoolRef.d.ts.map +1 -1
  166. package/dist/modules/order/utils/withPoolRef.js +17 -0
  167. package/dist/modules/order/utils/withPoolRef.js.map +1 -1
  168. package/dist/modules/order/working_grid.d.ts +8 -13
  169. package/dist/modules/order/working_grid.d.ts.map +1 -1
  170. package/dist/modules/order/working_grid.js +8 -29
  171. package/dist/modules/order/working_grid.js.map +1 -1
  172. package/dist/modules/settings_merge.d.ts +10 -1
  173. package/dist/modules/settings_merge.d.ts.map +1 -1
  174. package/dist/modules/settings_merge.js +27 -17
  175. package/dist/modules/settings_merge.js.map +1 -1
  176. package/dist/modules/validate_profiles.d.ts.map +1 -1
  177. package/dist/modules/validate_profiles.js +4 -3
  178. package/dist/modules/validate_profiles.js.map +1 -1
  179. package/dist/scripts/chart_command.d.ts +48 -0
  180. package/dist/scripts/chart_command.d.ts.map +1 -0
  181. package/dist/scripts/chart_command.js +504 -0
  182. package/dist/scripts/chart_command.js.map +1 -0
  183. package/dist/scripts/dw.d.ts +3 -0
  184. package/dist/scripts/dw.d.ts.map +1 -0
  185. package/dist/scripts/dw.js +30 -0
  186. package/dist/scripts/dw.js.map +1 -0
  187. package/dist/scripts/sync-version.js +0 -22
  188. package/dist/scripts/sync-version.js.map +1 -1
  189. package/dist/scripts/tv.d.ts +1 -31
  190. package/dist/scripts/tv.d.ts.map +1 -1
  191. package/dist/scripts/tv.js +10 -463
  192. package/dist/scripts/tv.js.map +1 -1
  193. package/dist/scripts/update.js +99 -62
  194. package/dist/scripts/update.js.map +1 -1
  195. package/dist/scripts/update_dist_freshness.d.ts +58 -0
  196. package/dist/scripts/update_dist_freshness.d.ts.map +1 -0
  197. package/dist/scripts/update_dist_freshness.js +144 -0
  198. package/dist/scripts/update_dist_freshness.js.map +1 -0
  199. package/dist/unlock.js +1 -1
  200. package/dist/unlock.js.map +1 -1
  201. package/docs/BITSHARES_ONBOARDING.md +16 -10
  202. package/docs/COW_INVARIANTS.md +1 -0
  203. package/docs/DEXBOT_COMPARISON.md +11 -11
  204. package/docs/EVOLUTION.md +9 -7
  205. package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +4 -4
  206. package/docs/GRID_PRICE_INVARIANT.md +518 -0
  207. package/docs/GRID_RECALCULATION.md +20 -24
  208. package/docs/GRID_RECONCILE.md +62 -41
  209. package/docs/LOGGING.md +1 -0
  210. package/docs/ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md +556 -0
  211. package/docs/README.md +18 -18
  212. package/docs/WORKFLOW.md +13 -8
  213. package/docs/architecture.md +42 -40
  214. package/docs/developer_guide.md +5 -8
  215. package/market_adapter/README.md +45 -65
  216. package/modules/README.md +3 -2
  217. package/package.json +7 -4
  218. package/scripts/README.md +18 -34
  219. package/scripts/reset-settings.sh +1 -1
  220. package/analysis/ama_fitting/package.json +0 -12
  221. package/analysis/analyze_derivatives.ts +0 -320
  222. package/analysis/derivative_chart_generator.ts +0 -874
  223. package/analysis/trend_detection/SIGNAL_DOCUMENTATION.md +0 -403
  224. package/analysis/trend_detection/derivative_analyzer.ts +0 -1059
  225. package/dist/analysis/analyze_derivatives.d.ts +0 -68
  226. package/dist/analysis/analyze_derivatives.d.ts.map +0 -1
  227. package/dist/analysis/analyze_derivatives.js +0 -287
  228. package/dist/analysis/analyze_derivatives.js.map +0 -1
  229. package/dist/analysis/derivative_chart_generator.d.ts +0 -12
  230. package/dist/analysis/derivative_chart_generator.d.ts.map +0 -1
  231. package/dist/analysis/derivative_chart_generator.js +0 -891
  232. package/dist/analysis/derivative_chart_generator.js.map +0 -1
  233. package/dist/analysis/trend_detection/derivative_analyzer.d.ts +0 -248
  234. package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +0 -1
  235. package/dist/analysis/trend_detection/derivative_analyzer.js +0 -910
  236. package/dist/analysis/trend_detection/derivative_analyzer.js.map +0 -1
  237. package/dist/scripts/generate_market_adapter_whitelist.d.ts +0 -15
  238. package/dist/scripts/generate_market_adapter_whitelist.d.ts.map +0 -1
  239. package/dist/scripts/generate_market_adapter_whitelist.js +0 -191
  240. package/dist/scripts/generate_market_adapter_whitelist.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,78 @@
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
+
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
38
+
39
+ ### 2026-09-23
40
+
41
+ - **Fix(bot-editor)**: treat `gridPrice` deactivating entries as `startPrice` and normalize them to `null` — typing `n`/`no`/`false`/`0`/`f`/`s`/`start`/`none`/blank, or a lone space, now commits `null` and the editor renders it as red `startPrice`, matching the live echo. Previously a whitespace-only entry previewed `startPrice` but a bare-Enter path silently kept the old value (`readInput` trimmed the resolved line, so a typed space was indistinguishable from Enter). `readInput` gains a `trimInput` option (default true, existing callers unchanged); `askGridPriceMode` opts out and tells a bare Enter (keep current) from whitespace (overwrite null). New `GRID_PRICE_UNSET_INPUTS`/`isUnsetGridPrice` in `modules/bot_defaults.ts` is the single spelling set, shared by the editor prompt, the display, and `seedBotDraft`, so a hand-edited `"gridPrice": false`/`"no"` normalizes to null at seed time instead of lingering as a value the runtime only silently degrades. Tests: unset → null (`tests/test_bot_defaults_characterization.ts`), red-startPrice rendering (`tests/test_account_bots_adapter.ts`, which now exports `colorGridPriceValue`), and `trimInput` default-vs-opt-out (`tests/test_read_input.ts`) (`modules/account_bots.ts`, `modules/bot_defaults.ts`, `modules/order/utils/system.ts`).
42
+
43
+ - **Feat(bot-editor)**: clearer `Pool` and `Adapter` status cues — the `3) Price` summary's `Pool:` field no longer reads `none` when the runtime auto-selects the pair's default pool: it shows a green `default` when `startPrice` is `pool`, a grey `none` otherwise, and a pinned `poolRef` still shows its ID (display-only; `formatPoolRefLabel` never touches the stored value; a `gridPrice` of `pool`/`book` is discouraged market-price anchoring and stays red in its own field). `6) Adapter` Weight/Range `false` now render bright yellow (`COLORS.yellowBold`) as optional-rider warnings instead of red; `Price` false stays red as the gate. New `testFormatPoolRefLabel` and a red-`book` assertion in `tests/test_account_bots_adapter.ts` (which now exports `formatPoolRefLabel`).
44
+
45
+ - **Feat(settings)**: expose the AMA-slope reset trigger in General settings — `1) Grid Health` now also edits `MARKET_ADAPTER.AMA_SLOPE_DELTA_THRESHOLD_PERCENT` (default `8%`, range 0.1-100; the slope-delta trigger as a percentage of max AMA slope), and the health line renders both thresholds with the Δ symbol and `%` (`AMA Δ: 1%, AMA-Slope Δ: 8%`); the input prompts are labelled `AMA Δ` / `AMA-Slope Δ` (the unit stays on the health line, not repeated at the prompt). `loadGeneralSettings` validates the new value with the same `>0` guard as the center-delta threshold, so a hand-edited `0`/negative/NaN cannot silently disable the slope reset. Also relabels the first Grid Health value `Ratio` → `Funds` (the trigger is available-funds/allocated-capital, so the old name was vague; config key `GRID_REGENERATION_PERCENTAGE` unchanged) and its prompt `Grid Ratio Regeneration %` → `Grid Funds Regeneration %`. Docs: `README.md` global-settings reference and the `docs/GRID_RECALCULATION.md` range-scaling trigger note updated (`modules/account_bots.ts`, `README.md`, `docs/GRID_RECALCULATION.md`).
46
+
47
+ - **Refactor(whitelist)**: remove the legacy `dexbot whitelist`/`white` command and its bulk generator — `scripts/generate_market_adapter_whitelist.ts` and the `market-adapter:whitelist` npm script are fully superseded by the per-bot editor (`dexbot bot` -> `2) Modify bot` -> `6) Adapter`), which reads/writes `profiles/market_adapter_whitelist.json` directly. The command, script, CLI help/alias/docstring entries, and all docs/tests that referenced it are gone; deleting a bot in the editor now prunes its whitelist entry via a new `removeWhitelistEntry(botKey)` helper (`modules/market_adapter_whitelist.ts`), run only after the `bots.json` save succeeds (`modules/account_bots.ts`), so a deleted bot cannot leave stale flags for a future same-name bot to inherit (a malformed whitelist file aborts the removal and is never silently replaced). Behavioral impact: `dexbot whitelist`/`white` is an unknown command; bots removed by hand-editing `bots.json` still need manual pruning (documented in `market_adapter/README.md`). New `tests/test_account_bots_adapter.ts` case (`dexbot.ts`, `package.json`, `scripts/README.md`, `scripts/reset-settings.sh`, `docs/README.md`, `docs/GRID_RECALCULATION.md`, `docs/WORKFLOW.md`, `market_adapter/README.md`).
48
+
49
+ - **Feat(bot-editor)**: default `gridPrice` to `ama3` and color AMA values as healthy — `DEFAULT_CONFIG.gridPrice` was null (delegating to `startPrice`), so a freshly created bot priced its bounds off `startPrice` while every other AMA-capable path expects a preset; the editor also greened pool/book/numeric exactly like valid AMA values. `DEFAULT_CONFIG.gridPrice` is now `"ama3"` (`modules/constants.ts`), the prompt label reads `gridPrice (ama1/ama2/ama3/ama4)` (bare `ama` still accepted), and `colorGridPriceValue()` greens only AMA values and reds pool/book/numeric/null across the Enter default, live input echo, and `3) Price` menu line. Section `6) Adapter` now renders Price/Weight/Range through `colorBooleanFlag(v, true)` instead of a local gray-for-false lambda, so each flag reads as a health state (green on, red off) like `Active` — the optional Weight/Range off-state was later softened to bright yellow (see the `Fix(bot-editor)` entry above). Input acceptance is unchanged — pool, book, bare ama, ama1..ama4, positive numbers, none/null/startprice, and Enter keeping the current value all still work; red flags "not an AMA value" rather than blocking it. New drafts and configs missing the key seed `ama3`; explicit values in existing bots entries are untouched (seeding fills only undefined), and whitelist flags stay false for a bot with no entry, so an ama3 bot starts in adapter dry-run and falls back to startPrice with a warning until Adapter -> Price is enabled. `modules/bot_defaults.ts` and `tests/test_bot_defaults_characterization.ts` follow the new default.
50
+
51
+ - **Refactor(launcher)**: spawn the supervised bot worker as `worker`, not `test` — `dexbot start` launched the bot as `dist/dexbot.js test`, which read like a test job in htop/ps even though it is the live runtime. `buildDexbotStartArgs` now emits `['worker', ...(dryrun ? ['--dryrun'] : []), botName?]` (`modules/launcher/monolithic_runtime.ts`); `unlock.ts` sets `DEXBOT_LAUNCHER_WORKER=1` on the child env (`modules/config.ts` exposes the flag) and `dexbot.ts` intercepts the internal `worker` command when the marker is set, before command validation, so it never re-enters the supervisor. Public `dexbot start` still delegates to `unlock`; the `test` help wording was clarified. Launcher/unlock tests updated, including an assertion that the child carries the worker marker.
52
+
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.
54
+
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.
56
+
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.
58
+
59
+ - **Feat(market-adapter)**: log-symmetric range-scaling tilt — range scaling previously widened the trend side by `(1+a)` but tightened the opposite side by `(1-a)`, which in log space made the tighten ~40% more aggressive than the widen at the default cap of 0.333x, collapsing the non-trend side toward center. Both bounds now scale by the same factor (down `1/(1+a)`, up `(1+a)`), so `delta log = +/-ln(1+a)` exactly and total log-width (slot count) is preserved while only the band's geometric center translates toward the trend; the widened side is unchanged and the tightened side is now the reciprocal rather than the linear complement. The geometric safe-clamp is mirrored to `base* - 1` so the shifted tightened bound still contains the fixed AMA center (still required: the reciprocal prevents reaching zero, not crossing center). `market_adapter/core/asymmetric_bounds.ts`, `modules/constants.ts`, `market_adapter/README.md`, and tests updated; `tests/test_market_adapter_service.ts` now sets `process.exitCode` on failure so its catch no longer masks a real failure. Behavioral change: with range scaling enabled the non-trend bound sits further from center (a 1.55x base at full tilt lands at +16.5% instead of +3.9%). The live grid build, adapter metrics, analyze-orders display, and the TradingView chart (embedded canonical source) all share this function.
60
+
61
+ - **Docs**: sync documentation index and linked docs with runtime behavior — `docs/README.md` bullets still described pre-1.6.4 behavior (batch cap is `gapSlots+1`, log rotation is 1.1GB total budget / 10 files, the `maxPages` warning is debug-level, duplicate detection is exact slot-price); `docs/architecture.md`'s batcher diagram/table said default cap 4 after 1f2fd7ae raised it to `gapSlots+1`; `docs/GRID_RECONCILE.md` Phase-1 duplicate detection described the removed 5x fuzzy matcher (code uses `priceSlotEqual` exact equality); `docs/FUND_MOVEMENT_AND_ACCOUNTING.md` dust partials are cancelled immediately on detection, not marked for consolidation; `docs/EVOLUTION.md` footer/stats refreshed to repo HEAD. Docs-only.
62
+
63
+ - **Feat(analysis)**: add an `ema` knob to the dynamic-weight chart for AMA input smoothing — the AMA slope channel had no post-filter besides the nz% dead-band, so there was no way to research how much additional slope smoothing (peak trimming, fewer sign flips) improves weight stability before touching live code. The dynamic-weight chart gains an `ema` slider (0-32 bars, 0 = off = previous behavior) that EMA-filters the AMA input before the slope; the clip-percentile pool and canonical `computeDynamicWeightSeries` offsets derive from it, so one source feeds display, clipping, and pipeline. Panel 2 gains a gray dashed Raw fraction-per-mille reference line and legend entry; the knob participates in `SLIDER_RANGES` clamps, copy/paste (`amaEmaSpan`), and init form-restore. `analyze_dynamic_weight` gains `--ema` (absent/NaN/out-of-range all resolve to the clamped default). `DYNAMIC_WEIGHT_RESEARCH` documents the flag row, knob table row, span value table, tuning interactions, and the measured effect on ~8.7k hourly bars (std -3% / peaks -22% / crossings 86 -> 74 at span 9). Research only; default ema = 0 reproduces prior output, the live market adapter and shared `dynamic_weight_series` module are untouched.
64
+
65
+ - **Feat(cli)**: add `dexbot dw` and centralize the chart-command pipeline — `dexbot dw` renders the dynamic-weight research chart through the same fetch pipeline as `dexbot tv`, but the pipeline lived in a tv-branded module with the exporter hardcoded. New `scripts/chart_command.ts` holds the shared pipeline (bot/pool-id/pair target resolution, `--feed`/`--pool`/`--book` routing with pool-first orderbook fallback, MPA/prediction-market guards, cached 1-month candle chunks, temp-JSON handoff) plus a `RENDERERS` registry (analyzer path, exporter label, title kind, usage blurb) so both commands (and future chart commands) are a table row apart; `scripts/tv.ts` and new `scripts/dw.ts` are thin entries with per-command error labels (loading them never triggers a run, test-asserted). Explicit `--ama-er/fast/slow-period` forwarding to the analyzer was dropped — both renderers resolve `resolveAmaConfig()` from `--bot-key` themselves, which also stops silently dropping the 4th field (`erSmoothPeriod`); verified output-identical for tv, and tv stays intentionally 3-param AMA. `analysis/analyze_dynamic_weight.ts` gains `--title` and a clickable `file://` save link; `dexbot.ts` registers `dw` in `CLI_COMMANDS`/`HELP_OWNING_COMMANDS` and the shared tv/dw dispatch (advanced-only, root help/README unchanged; documented in `scripts/README.md`, `analysis/README.md`, `analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md`). Month flags: `--month` canonical (default 3), `--months` a pure alias, invalid values always report `--month`. New `tests/test_dw_cli.ts`; `test_tv_feed_routing` now imports `scripts/chart_command`.
66
+
67
+ ### 2026-09-22
68
+
69
+ - **Feat(log)**: tag RMS structural-divergence logs with `[RMS]` and show the threshold — the RMS reset line logged raw decimal metrics via `formatPrice6` (`buy=0.162000`) with no threshold context, so operators could not tell which level fired or which side breached. `resolveRmsThresholdPct()` is extracted as the single source of truth for the `GRID_COMPARISON.RMS_PERCENTAGE` override chain (previously duplicated inline in `compareGrids`) and surfaced as `thresholdPct` through `compareGrids`/`monitorDivergence`: `modules/order/grid.ts` emits a per-side `[RMS]` debug line (metric vs threshold -> TRIGGER-RESYNC/no trigger) each tick plus a "checks disabled" variant when the threshold is 0, and `modules/dexbot_maintenance_runtime.ts` now prefixes the reset line with `[RMS]` and formats it as 4 significant digits (`buy=16.20%`) with threshold, breaching sides, and the resync reason; the failure warn is also tagged. The threshold check itself is unchanged (same override chain, same percent->decimal scaling), but log line format changes, so log scrapers keyed on the old literals must be updated (no legacy format retained). `GRID_RECALCULATION.md` signatures/examples and the `LOGGING.md` `[RMS]` prefix row updated (including the threshold=0 debug variant). Also fixes a red test left by f859941e (`tests/test_market_adapter_log_format.ts` now expects `asymCap=33%`).
70
+
71
+ - **Fix(config)**: lower the default asymmetric bounds max factor to 0.333 — `ASYMMETRIC_BOUNDS_MAX_ASYMMETRY_FACTOR` moves 0.35 -> 0.333 so the slope-derived grid bound tilt is less aggressive. At the tight end of the supported span range (1.55x) full tilt previously pinched the tightened side to ~0.75% from the AMA center; 0.333 keeps ~3.3%, leaving the narrowing-side slot guard (`minScaleSlots`) more room before it overrides the tilt. Saturated band width moves from 87.75% to 88.91% of the symmetric base; wide 2x spans are effectively unchanged. The TradingView chart fallback and README defaults are synced to `modules/constants.ts`; local overrides in `profiles/general.settings.json` still take precedence at runtime.
72
+
73
+ - **Style(ui)**: normalize bot editor separators — group related fields with `|` in the `dexbot bot` editor summary and keep within-group fields comma-separated, matching the Funding line style: Identity (Name/Account grouped, Active/DryRun comma), Price (Range/Start+Pool/GridPrice grouped with `|`), Grid (Weights group `|`, Incr/Spread comma), Funding (Sell/Buy comma, Orders/Reserve grouped with `|`). Presentational only (`modules/account_bots.ts`).
74
+
75
+ - **Feat(tradingview)**: step the AMA ER stepper by 10 per click — the ER period defaults to 781, so the +/-1 per-click stepper (and its held-repeat) made any meaningful adjustment painfully slow. The step is now 10 (floor stays 1, integer rounding); other steppers (`sma-period`, `vwap-bars`, `fast`, `slow`) are unchanged (`analysis/tradingview/tradingview_uplot_chart_generator.ts`).
76
+
5
77
  ## [1.6.4] - 2026-09-22 - Fund-Driven Spread Correction, GapSlots+1 Batch Cap, Analysis Shared Modules
6
78
 
7
79
  ### 2026-09-21
@@ -723,10 +795,10 @@ All notable changes to this project will be documented in this file.
723
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`).
724
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`).
725
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`).
726
- - **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`).
727
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`).
728
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`).
729
- - **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.
730
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`).
731
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`).
732
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`).
@@ -1274,7 +1346,7 @@ All notable changes to this project will be documented in this file.
1274
1346
 
1275
1347
  ### 2026-07-01
1276
1348
 
1277
- - **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.
1278
1350
  - **Chore**: version bumped to 1.0.5 across all manifests.
1279
1351
  - **Docs**: updated `CHANGELOG.md`, `docs/EVOLUTION.md`, `docs/README.md`, `docs/DEXBOT_COMPARISON.md`, `docs/FUND_MOVEMENT_AND_ACCOUNTING.md`.
1280
1352
 
package/README.md CHANGED
@@ -169,25 +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. **Generate the market-adapter whitelist:**
177
+ - `Price` — **on for AMA bots**; without it the adapter only dry-runs
178
+ - `Weight` — dynamic buy/sell weights (opt-in)
179
+ - `Range` — AMA-slope range scaling (opt-in)
177
180
 
178
- ```bash
179
- dexbot white
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.
181
185
 
182
- This writes `market_adapter_whitelist.json` in the profiles directory. New AMA bots get AMA
183
- live writes only; dynamic weights and range scaling are disabled by default. Use
184
- `dexbot white --dynamic-weight` or `dexbot white --asymmetric-bounds` to opt
185
- newly generated entries into those features; existing entries are preserved.
186
- To overwrite an existing bot, include `--bot <botKey>` with the desired flags.
186
+ The flags are stored per bot in `market_adapter_whitelist.json` in the
187
+ profiles directory and can be changed any time from the same editor
188
+ section. Boolean prompts accept `y`/`yes`/`true` and `n`/`no`/`false`;
189
+ Enter keeps the current value.
187
190
 
188
- 6. **Start DEXBot2** with `dexbot start`.
191
+ 5. **Start DEXBot2** with `dexbot start`.
189
192
 
190
- 7. **Tune `minPrice` / `maxPrice`** around the market's volatility range. Once
193
+ 6. **Tune `minPrice` / `maxPrice`** around the market's volatility range. Once
191
194
  AMA is active, tighten them around the maximum expected market volatility
192
195
  instead of using an unnecessarily wide range.
193
196
 
@@ -199,39 +202,106 @@ Configuration options from `dexbot bot`, stored in `bots.json` in the profiles d
199
202
 
200
203
  <details><summary><mark>Full parameter reference (click to expand)</mark></summary>
201
204
 
205
+ Grouped exactly as the bot editor shows them (`dexbot bot` → `2) Modify bot` → pick the bot):
206
+
207
+ **`1) Pair`**
208
+
202
209
  | Parameter | Type | Description |
203
210
  | :--- | :--- | :--- |
204
211
  | **`assetA`** | string | Base asset |
205
212
  | **`assetB`** | string | Quote asset |
213
+
214
+ **`2) Identity`**
215
+
216
+ | Parameter | Type | Description |
217
+ | :--- | :--- | :--- |
206
218
  | **`name`** | string | Friendly name for logging and CLI selection |
207
- | **`active`** | boolean | `false` to keep config without running |
208
- | **`dryRun`** | boolean | Simulate orders without broadcasting |
209
219
  | **`preferredAccount`** | string | BitShares account name for trading |
210
- | **`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. |
211
- | **`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`. |
212
- | **`minPrice`** | num \| str | Lower bound. Default `"2x"` means `gridPrice / 2` when AMA is active, otherwise `startPrice / 2`. |
213
- | **`maxPrice`** | num \| str | Upper bound. Default `"2x"` means `gridPrice * 2` when AMA is active, otherwise `startPrice * 2`. |
214
- | **`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. |
215
- | **`incrementPercent`** | number | Geometric step between orders. Default `0.5` = 0.5%. |
216
- | **`targetSpreadPercent`** | number | Width of the empty spread zone between buy and sell orders. Default `2` = 2%. Profit per completed cycle ≈ `spread - increment - fees`. |
217
- | **`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. |
218
- | **`botFunds`** | object | Capital: `{ Sell: "100%", Buy: 100% }`. Numbers or percentage strings |
219
- | **`activeOrders`** | object | Target active orders per side: `{ S: 20, B: 20 }` |
220
- | **`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) |
221
258
 
222
259
  </details>
223
260
 
224
- ### General Options (Global)
261
+ ### General Settings (Global)
262
+
263
+ General settings via `dexbot bot`, stored in `general.settings.json` in the profiles directory:
225
264
 
226
- 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>
227
266
 
228
- <details><summary><mark>Global settings reference (click to expand)</mark></summary>
267
+ Grouped exactly as `dexbot bot` → `6) General settings` shows them:
229
268
 
230
- - **Grid Health**: Grid Ratio Regeneration % (default `3%`), RMS Divergence Threshold % (default `14.3%`), AMA Delta Threshold % (default `1%`)
231
- - **Order Recovery**: Partial Dust Threshold % (default `5%`), Dust Cancel Delay (default `30s`, `-1` = off, `0` = instant)
232
- - **Node Configuration**: Node List (10 default public BitShares nodes), Health Check Interval (default `240 min`), Preferred Node (default `none`)
233
- - **Log Level**: `debug`, `info`, `warn`, `error`, `critical`. Fine-grained category control via `LOGGING_CONFIG` (see [Logging](docs/LOGGING.md))
234
- - **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) |
235
305
 
236
306
  </details>
237
307
 
@@ -257,21 +327,20 @@ First-run details and common mistakes are covered in the [BitShares Onboarding T
257
327
 
258
328
  ```bash
259
329
  dexbot key # Master password/keyring
260
- dexbot bot # Interactive bot configurator
261
- dexbot white # AMA whitelist; dynamic weights and range scaling off by default
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,19 +21,17 @@ 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>` |
28
- | [`analyze_dynamic_weight.ts`](#dynamic-weight-research-analyze_dynamic_weightts) | "Are buy/sell weights tuned for this regime?" | `node dist/analysis/analyze_dynamic_weight.js --bot-key <bot-key>` |
28
+ | [`analyze_dynamic_weight.ts`](#dynamic-weight-research-analyze_dynamic_weightts) | "Are buy/sell weights tuned for this regime?" | `dexbot dw <bot-key>` |
29
29
  | [`analyze_volatility.ts`](#volatility-analyze_volatilityts) | "Both weights clipped too hard / not enough?" | `node dist/analysis/analyze_volatility.js --bot-key <bot-key>` |
30
30
  | [`analyze_regime.ts`](#supporting-sub-signals) | "Is the trend/chaos gate too aggressive?" | `node dist/analysis/analyze_regime.js --bot-key <bot-key>` |
31
31
  | [`analyze_kalman.ts`](#supporting-sub-signals) | "Is Kalman's contribution to the blend right?" | `node dist/analysis/analyze_kalman.js --bot-key <bot-key>` |
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
 
@@ -337,6 +334,13 @@ Two weight-tuning paths feed into the market adapter:
337
334
  Interactive 4-panel chart for the asymmetric path: AMA slope plus Kalman confirmation, gated by Hurst Exponent and Permutation Entropy. Use this when tuning buy/sell weight bias, AMA slope offset behavior, and regime damping.
338
335
 
339
336
  ```bash
337
+ # Recommended one-step (advanced): bot, pool, or pair — fetches candles and renders,
338
+ # same pipeline as `dexbot tv`, default 3 months
339
+ dexbot dw <bot-key>
340
+ dexbot dw 133 --month 6
341
+ dexbot dw TOKENA/TOKENB --month 1
342
+
343
+ # Direct analyzer (own candle files, research knobs --alpha/--gain/--dw/--lb/--clip)
340
344
  node dist/analysis/analyze_dynamic_weight.js --bot-key <bot-key>
341
345
 
342
346
  # From LP candle file with custom parameters
@@ -388,7 +392,6 @@ Shared analyzers and chart renderers for the dynamic-weight signal path. Core en
388
392
  **Research docs:**
389
393
  - [README.md](trend_detection/README.md) — directory overview and module index
390
394
  - [DYNAMIC_WEIGHT_RESEARCH.md](trend_detection/DYNAMIC_WEIGHT_RESEARCH.md) — AMA+Kalman blend with Hurst/PE regime gating, formula reference, knob guide
391
- - [SIGNAL_DOCUMENTATION.md](trend_detection/SIGNAL_DOCUMENTATION.md) — legacy SMA/MACD/RSI derivative signal layer
392
395
 
393
396
  <details><summary>Modules (click to expand)</summary>
394
397
 
@@ -502,7 +505,6 @@ These npm scripts wrap common analysis runners:
502
505
  | `npm run analysis:tradingview` | `node dist/analysis/tradingview/analyze_tradingview.js` |
503
506
  | `npm run analysis:trade-pnl` | `node dist/analysis/trade_profitability.js` |
504
507
  | `npm run analysis:grid-check` | `node dist/analysis/grid_correction_check.js` |
505
- | `npm run analysis:derivatives` | `node dist/analysis/analyze_derivatives.js` (legacy SMA/MACD/RSI layer, reference only) |
506
508
  | `npm run ama:chart:lp-local` | `node dist/analysis/ama_fitting/generate_unified_comparison_chart.js` (chart also auto-generated by optimizer) |
507
509
 
508
510
  All accept `--` forwarded flags.
@@ -514,7 +516,7 @@ npm run analysis:tradingview -- --source market_adapter --bot-key <bot-key>
514
516
  # Trade PnL
515
517
  npm run analysis:trade-pnl -- 1.2.123456 --hours 720
516
518
 
517
- # Grid correction check (monotonicity regression gate)
519
+ # LAST-FILL-GUARD check
518
520
  npm run analysis:grid-check -- --bot-key <bot-key> --hours 168
519
521
 
520
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 };
@@ -22,7 +22,7 @@ import { calculateAMA } from '../market_adapter/core/strategies/ama.js';
22
22
  import { computeAmaSlopeWeights, createAmaSlopeClipTracker } from '../market_adapter/core/strategies/ama_slope_model.js';
23
23
  import { MARKET_ADAPTER } from '../modules/constants.js';
24
24
  import { PATHS } from '../modules/paths.js';
25
- import { writeChartFile } from './chart_utils.js';
25
+ import { writeChartFile, toFileUrl } from './chart_utils.js';
26
26
  import { getCandleClose } from './math_utils.js';
27
27
  import { resolveSource, listAvailableBots, type SourceConfig } from './resolve_source.js';
28
28
 
@@ -56,6 +56,7 @@ function parseArgs() {
56
56
  const config: {
57
57
  source: { type: string; config: SourceConfig };
58
58
  chartFile: string;
59
+ title: string | null;
59
60
  alpha: any;
60
61
  gain: any;
61
62
  dispWeight: any;
@@ -64,9 +65,11 @@ function parseArgs() {
64
65
  listBots: boolean;
65
66
  lookbackBars?: number;
66
67
  dispScaleMinPct?: number;
68
+ amaEmaSpan?: number;
67
69
  } = {
68
70
  source: { type: 'market_adapter', config: { botKey: '' } },
69
71
  chartFile: path.join(PATHS.ANALYSIS.CHARTS_DIR, 'dynamic_weight_chart.html'),
72
+ title: null,
70
73
  alpha: MARKET_ADAPTER.DYNAMIC_WEIGHT_ALPHA,
71
74
  gain: MARKET_ADAPTER.DYNAMIC_WEIGHT_GAIN,
72
75
  dispWeight: MARKET_ADAPTER.DYNAMIC_WEIGHT_DW,
@@ -84,10 +87,12 @@ function parseArgs() {
84
87
  config.source.type = 'json';
85
88
  }
86
89
  else if (arg === '--chart') config.chartFile = args[++i];
90
+ else if (arg === '--title') config.title = args[++i] ?? null;
87
91
  else if (arg === '--alpha') config.alpha = parseFloat(args[++i]);
88
92
  else if (arg === '--gain') config.gain = parseFloat(args[++i]);
89
93
  else if (arg === '--dw') config.dispWeight = parseFloat(args[++i]);
90
94
  else if (arg === '--lb') config.lookbackBars = parseInt(args[++i], 10);
95
+ else if (arg === '--ema') config.amaEmaSpan = parseInt(args[++i], 10);
91
96
  else if (arg === '--clip') config.clipPct = parseFloat(args[++i]);
92
97
  else if (arg === '--list-bots') config.listBots = true;
93
98
  else if (arg === '--quiet') config.quiet = true;
@@ -201,6 +206,7 @@ async function main() {
201
206
  ...AMA_WEIGHT_CONFIG,
202
207
  lookbackBars: config.lookbackBars ?? AMA_WEIGHT_CONFIG.lookbackBars,
203
208
  },
209
+ amaEmaSpan: config.amaEmaSpan,
204
210
  alpha: config.alpha,
205
211
  gain: config.gain,
206
212
  dispWeight: config.dispWeight,
@@ -223,11 +229,11 @@ async function main() {
223
229
  amaNeutralZonePct: MARKET_ADAPTER.DYNAMIC_WEIGHT_AMA_NEUTRAL_ZONE_PCT,
224
230
  dispScaleMinPct: MARKET_ADAPTER.DYNAMIC_WEIGHT_DISP_SCALE_MIN_PCT,
225
231
  },
226
- }, 'Dynamic Weight Research Tool');
232
+ }, config.title || 'Dynamic Weight Research Tool');
227
233
 
228
234
  writeChartFile(config.chartFile, html);
229
235
 
230
- if (!config.quiet) console.log(`[DynamicWeight] ✓ Chart saved to ${config.chartFile}`);
236
+ if (!config.quiet) console.log(`\n[DynamicWeight] ✓ Chart saved. Open chart: (${toFileUrl(config.chartFile)})`);
231
237
  } catch (err: unknown) {
232
238
  console.error(`[DynamicWeight] Error: ${(err as any)?.message ?? err}`);
233
239
  process.exit(1);
@@ -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
  };