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.
- package/CHANGELOG.md +36 -4
- package/README.md +104 -35
- package/analysis/README.md +11 -16
- package/analysis/account_resolver.ts +1 -11
- package/analysis/bot_usage/kibana_bot_queries.ts +1 -1
- package/analysis/chain_pool.ts +1 -1
- package/analysis/fills_source.ts +0 -6
- package/analysis/grid_correction_check.ts +20 -26
- package/analysis/resolve_source.ts +1 -1
- package/analysis/trade_profitability.ts +2 -5
- package/analysis/trend_detection/README.md +1 -3
- package/analysis/trend_detection/package.json +1 -1
- package/claw/package.json +1 -1
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/tests/test_claw_mcp_transport.ts +2 -2
- package/dist/analysis/account_resolver.d.ts +1 -4
- package/dist/analysis/account_resolver.d.ts.map +1 -1
- package/dist/analysis/account_resolver.js +1 -1
- package/dist/analysis/account_resolver.js.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -2
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
- package/dist/analysis/chain_pool.d.ts +1 -3
- package/dist/analysis/chain_pool.d.ts.map +1 -1
- package/dist/analysis/chain_pool.js +1 -1
- package/dist/analysis/chain_pool.js.map +1 -1
- package/dist/analysis/fills_source.d.ts +1 -51
- package/dist/analysis/fills_source.d.ts.map +1 -1
- package/dist/analysis/fills_source.js +1 -1
- package/dist/analysis/fills_source.js.map +1 -1
- package/dist/analysis/grid_correction_check.d.ts +2 -3
- package/dist/analysis/grid_correction_check.d.ts.map +1 -1
- package/dist/analysis/grid_correction_check.js +18 -26
- package/dist/analysis/grid_correction_check.js.map +1 -1
- package/dist/analysis/resolve_source.d.ts +1 -1
- package/dist/analysis/resolve_source.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.js +2 -7
- package/dist/analysis/trade_profitability.js.map +1 -1
- package/dist/dexbot.d.ts.map +1 -1
- package/dist/dexbot.js +60 -74
- package/dist/dexbot.js.map +1 -1
- package/dist/market_adapter/core/kibana_candles.d.ts +1 -15
- package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_candles.js +1 -1
- package/dist/market_adapter/core/kibana_candles.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts +1 -35
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.js +10 -54
- package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
- package/dist/market_adapter/inputs/kibana_feed_source.d.ts +1 -8
- package/dist/market_adapter/inputs/kibana_feed_source.d.ts.map +1 -1
- package/dist/market_adapter/inputs/kibana_feed_source.js +1 -1
- package/dist/market_adapter/inputs/kibana_feed_source.js.map +1 -1
- package/dist/market_adapter/inputs/window_cache.d.ts +2 -63
- package/dist/market_adapter/inputs/window_cache.d.ts.map +1 -1
- package/dist/market_adapter/inputs/window_cache.js +22 -102
- package/dist/market_adapter/inputs/window_cache.js.map +1 -1
- package/dist/modules/account_bots.d.ts +16 -2
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +107 -44
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -1
- package/dist/modules/bitshares-native/crypto/ecc.browser.js +0 -31
- package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -1
- package/dist/modules/credit_runtime.d.ts +0 -2
- package/dist/modules/credit_runtime.d.ts.map +1 -1
- package/dist/modules/credit_runtime.js +1 -10
- package/dist/modules/credit_runtime.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +13 -10
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +0 -9
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +13 -0
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +13 -1
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/order/accounting.d.ts +4 -18
- package/dist/modules/order/accounting.d.ts.map +1 -1
- package/dist/modules/order/accounting.js +4 -34
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/export.d.ts +9 -12
- package/dist/modules/order/export.d.ts.map +1 -1
- package/dist/modules/order/export.js +9 -12
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/grid.d.ts +35 -40
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +43 -43
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile.js +111 -20
- package/dist/modules/order/grid_reconcile.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts +5 -3
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +18 -3
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +0 -8
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +0 -10
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts +22 -7
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +103 -21
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/withPoolRef.d.ts +12 -0
- package/dist/modules/order/utils/withPoolRef.d.ts.map +1 -1
- package/dist/modules/order/utils/withPoolRef.js +17 -0
- package/dist/modules/order/utils/withPoolRef.js.map +1 -1
- package/dist/modules/order/working_grid.d.ts +8 -13
- package/dist/modules/order/working_grid.d.ts.map +1 -1
- package/dist/modules/order/working_grid.js +8 -29
- package/dist/modules/order/working_grid.js.map +1 -1
- package/dist/scripts/sync-version.js +0 -22
- package/dist/scripts/sync-version.js.map +1 -1
- package/dist/scripts/update_dist_freshness.d.ts +12 -0
- package/dist/scripts/update_dist_freshness.d.ts.map +1 -1
- package/dist/scripts/update_dist_freshness.js +30 -1
- package/dist/scripts/update_dist_freshness.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +9 -6
- package/docs/COW_INVARIANTS.md +1 -0
- package/docs/DEXBOT_COMPARISON.md +11 -11
- package/docs/EVOLUTION.md +8 -7
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
- package/docs/GRID_PRICE_INVARIANT.md +518 -0
- package/docs/GRID_RECALCULATION.md +1 -1
- package/docs/GRID_RECONCILE.md +60 -39
- package/docs/ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md +556 -0
- package/docs/README.md +3 -3
- package/docs/WORKFLOW.md +12 -6
- package/docs/architecture.md +40 -38
- package/docs/developer_guide.md +4 -8
- package/market_adapter/README.md +16 -12
- package/modules/README.md +1 -1
- package/package.json +7 -3
- package/scripts/README.md +0 -9
- package/scripts/reset-settings.sh +1 -1
- package/analysis/ama_fitting/package.json +0 -12
- package/analysis/analyze_derivatives.ts +0 -320
- package/analysis/derivative_chart_generator.ts +0 -874
- package/analysis/trend_detection/SIGNAL_DOCUMENTATION.md +0 -403
- package/analysis/trend_detection/derivative_analyzer.ts +0 -1059
- package/dist/analysis/analyze_derivatives.d.ts +0 -68
- package/dist/analysis/analyze_derivatives.d.ts.map +0 -1
- package/dist/analysis/analyze_derivatives.js +0 -287
- package/dist/analysis/analyze_derivatives.js.map +0 -1
- package/dist/analysis/derivative_chart_generator.d.ts +0 -12
- package/dist/analysis/derivative_chart_generator.d.ts.map +0 -1
- package/dist/analysis/derivative_chart_generator.js +0 -891
- package/dist/analysis/derivative_chart_generator.js.map +0 -1
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts +0 -248
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +0 -1
- package/dist/analysis/trend_detection/derivative_analyzer.js +0 -910
- 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
|
|
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-
|
|
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. **
|
|
173
|
-
|
|
174
|
-
`
|
|
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
|
-
|
|
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
|
-
|
|
191
|
+
5. **Start DEXBot2** with `dexbot start`.
|
|
190
192
|
|
|
191
|
-
|
|
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
|
-
| **`
|
|
212
|
-
| **`
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
|
217
|
-
|
|
|
218
|
-
| **`
|
|
219
|
-
| **`
|
|
220
|
-
| **`
|
|
221
|
-
| **`
|
|
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
|
|
261
|
+
### General Settings (Global)
|
|
262
|
+
|
|
263
|
+
General settings via `dexbot bot`, stored in `general.settings.json` in the profiles directory:
|
|
226
264
|
|
|
227
|
-
|
|
265
|
+
<details><summary><mark>General settings reference (click to expand)</mark></summary>
|
|
228
266
|
|
|
229
|
-
|
|
267
|
+
Grouped exactly as `dexbot bot` → `6) General settings` shows them:
|
|
230
268
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
|
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
|
|
package/analysis/README.md
CHANGED
|
@@ -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`](#
|
|
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
|
-
###
|
|
223
|
+
### LAST-FILL-GUARD Check (`grid_correction_check.ts`)
|
|
227
224
|
|
|
228
|
-
Validates
|
|
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
|
|
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
|
-
#
|
|
243
|
-
npm run analysis:grid-check -- --bot-key <bot-key> --hours 168 --
|
|
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>` |
|
|
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
|
|
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:**
|
|
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
|
-
#
|
|
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
|
|
210
|
+
export { DEFAULT_CONFIG, kibanaSearch, buildOrderPriceQuery, buildTopSellerAccountsQuery, buildTopCancellerAccountsQuery, buildTopFilledAccountsQuery, buildTopUpdaterAccountsQuery }
|
|
211
211
|
|
package/analysis/chain_pool.ts
CHANGED
package/analysis/fills_source.ts
CHANGED
|
@@ -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
|
-
*
|
|
5
|
+
* LAST-FILL-GUARD CHECK
|
|
6
6
|
*
|
|
7
|
-
* Validates LAST-FILL-GUARD discipline
|
|
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
|
|
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
|
|
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[];
|
|
472
|
+
): { violations: Violation[]; checkedTransitions: number } {
|
|
476
473
|
const violations: Violation[] = [];
|
|
477
|
-
let
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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('
|
|
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(`
|
|
586
|
-
console.log(` Violations: ${violations.length}${
|
|
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
|
|
584
|
+
console.log(' ✅ PASS — no LAST-FILL-GUARD violations detected (all BUY < pivot-half, SELL > pivot+half).');
|
|
591
585
|
console.log('');
|
|
592
|
-
if (
|
|
593
|
-
console.log(' Note: no consecutive
|
|
594
|
-
console.log(' (Need at least two fills/orders
|
|
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(`\
|
|
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,
|
|
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,
|
|
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,
|
|
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 => {
|