dexbot 1.6.2 → 1.6.4
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 +53 -3
- package/README.md +11 -7
- package/analysis/README.md +20 -14
- package/analysis/account_resolver.ts +171 -0
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -5
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/bot_usage/discover_bot_accounts.ts +20 -27
- package/analysis/chain_pool.ts +47 -0
- package/analysis/chart_utils.ts +33 -20
- package/analysis/derivative_chart_generator.ts +2 -3
- package/analysis/fills_source.ts +234 -0
- package/analysis/grid_correction_check.ts +104 -244
- package/analysis/results/ama_sweep_results_lp_pool_133_1h.json +2455 -0
- package/analysis/results/bot_fitting_results_lp_pool_133_1h.json +218 -0
- package/analysis/trade_profitability.ts +169 -304
- package/analysis/tradingview/README.md +2 -2
- package/analysis/tradingview/h-bts_tradingview.html +1570 -0
- package/analysis/tradingview/t-bts_tradingview.html +1570 -0
- package/analysis/tradingview/tradingview_uplot_chart_generator.ts +3 -4
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +2 -3
- package/analysis/trend_detection/kalman_chart_generator.ts +2 -3
- package/analysis/trend_detection/package.json +1 -1
- package/analysis/trend_detection/regime_chart_generator.ts +2 -3
- package/analysis/trend_detection/volatility_chart_generator.ts +2 -3
- 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 +43 -0
- package/dist/analysis/account_resolver.d.ts.map +1 -0
- package/dist/analysis/account_resolver.js +137 -0
- package/dist/analysis/account_resolver.js.map +1 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -4
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/bot_usage/discover_bot_accounts.js +20 -28
- package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
- package/dist/analysis/chain_pool.d.ts +10 -0
- package/dist/analysis/chain_pool.d.ts.map +1 -0
- package/dist/analysis/chain_pool.js +47 -0
- package/dist/analysis/chain_pool.js.map +1 -0
- package/dist/analysis/chart_utils.d.ts +14 -1
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +32 -22
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +2 -3
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/fills_source.d.ts +79 -0
- package/dist/analysis/fills_source.d.ts.map +1 -0
- package/dist/analysis/fills_source.js +186 -0
- package/dist/analysis/fills_source.js.map +1 -0
- package/dist/analysis/grid_correction_check.d.ts +4 -20
- package/dist/analysis/grid_correction_check.d.ts.map +1 -1
- package/dist/analysis/grid_correction_check.js +95 -248
- package/dist/analysis/grid_correction_check.js.map +1 -1
- package/dist/analysis/trade_profitability.d.ts +18 -19
- package/dist/analysis/trade_profitability.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.js +136 -280
- package/dist/analysis/trade_profitability.js.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +3 -4
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -1
- package/dist/market_adapter/lp_chart_core.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_core.js +2 -3
- package/dist/market_adapter/lp_chart_core.js.map +1 -1
- package/dist/modules/account_bots.d.ts +1 -18
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +1 -1
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.d.ts +1 -84
- package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.js +1 -38
- package/dist/modules/bitshares-native/serial/operations.js.map +1 -1
- package/dist/modules/cli_colors.d.ts +0 -1
- package/dist/modules/cli_colors.d.ts.map +1 -1
- package/dist/modules/constants.js +5 -5
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credential_policy.d.ts +1 -25
- package/dist/modules/credential_policy.d.ts.map +1 -1
- package/dist/modules/credential_policy.js +1 -1
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/credential_runtime.d.ts +1 -6
- package/dist/modules/credential_runtime.d.ts.map +1 -1
- package/dist/modules/credential_runtime.js +1 -1
- package/dist/modules/credential_runtime.js.map +1 -1
- package/dist/modules/credential_session_cache.d.ts +1 -5
- package/dist/modules/credential_session_cache.d.ts.map +1 -1
- package/dist/modules/credential_session_cache.js +1 -1
- package/dist/modules/credential_session_cache.js.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.d.ts +1 -2
- package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.js +1 -1
- package/dist/modules/crypto/pure_secp256k1.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +9 -8
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +9 -8
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +87 -7
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +489 -14
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_fill_runtime.d.ts +1 -17
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_fill_runtime.js +1 -1
- package/dist/modules/dexbot_fill_runtime.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +21 -5
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts +1 -7
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +1 -1
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/launcher/adapter_requirement.d.ts +1 -5
- package/dist/modules/launcher/adapter_requirement.d.ts.map +1 -1
- package/dist/modules/launcher/adapter_requirement.js +1 -1
- package/dist/modules/launcher/adapter_requirement.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts +1 -6
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +1 -1
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts +1 -3
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/launch_modes.d.ts +1 -2
- package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
- package/dist/modules/launcher/launch_modes.js +1 -1
- package/dist/modules/launcher/launch_modes.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +1 -3
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts +1 -5
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +1 -1
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/status_reporting.d.ts +1 -2
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -1
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/order/export.d.ts +1 -8
- package/dist/modules/order/export.d.ts.map +1 -1
- package/dist/modules/order/export.js +1 -1
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/grid.d.ts +7 -0
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +52 -98
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts +1 -10
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +2 -2
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +10 -2
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +20 -7
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +25 -20
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +1 -10
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +1 -1
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts +45 -7
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +160 -15
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/system.d.ts +0 -15
- package/dist/modules/order/utils/system.d.ts.map +1 -1
- package/dist/modules/order/utils/system.js +2 -2
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/process_discovery.d.ts +0 -3
- package/dist/modules/process_discovery.d.ts.map +1 -1
- package/dist/modules/process_discovery.js +1 -1
- package/dist/modules/process_discovery.js.map +1 -1
- package/dist/modules/utils/chain_logs.d.ts +1 -2
- package/dist/modules/utils/chain_logs.d.ts.map +1 -1
- package/dist/modules/utils/chain_logs.js +1 -1
- package/dist/modules/utils/chain_logs.js.map +1 -1
- package/dist/scripts/analyze-git.js +2 -2
- package/dist/scripts/analyze-git.js.map +1 -1
- package/dist/scripts/update.js +46 -31
- package/dist/scripts/update.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +110 -40
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +10 -207
- package/docs/COW_INVARIANTS.md +16 -10
- package/docs/DEXBOT_COMPARISON.md +3 -3
- package/docs/EVOLUTION.md +75 -29
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +6 -6
- package/docs/GRID_RECALCULATION.md +14 -6
- package/docs/GRID_RECONCILE.md +28 -25
- package/docs/LIFECYCLE.md +12 -11
- package/docs/README.md +48 -42
- package/docs/architecture.md +19 -30
- package/docs/developer_guide.md +3 -3
- package/package.json +1 -1
- package/scripts/git-viewer.sh +1 -1
- package/tests/README.md +10 -1
|
@@ -37,81 +37,26 @@ import fs from 'node:fs';
|
|
|
37
37
|
import { pathToFileURL } from 'node:url';
|
|
38
38
|
import * as KC from '../market_adapter/core/kibana_client.js';
|
|
39
39
|
import * as C from '../modules/constants.js';
|
|
40
|
-
import {
|
|
40
|
+
import { loadBotSettings, computeBotKey } from './bot_key_utils.js';
|
|
41
|
+
import { resolveBotAccount } from './account_resolver.js';
|
|
42
|
+
import {
|
|
43
|
+
BTS_ID,
|
|
44
|
+
FillRecord,
|
|
45
|
+
assetPrec,
|
|
46
|
+
assetSymbol,
|
|
47
|
+
fetchAllFills,
|
|
48
|
+
resolveAssetPrecisions,
|
|
49
|
+
toReal,
|
|
50
|
+
} from './fills_source.js';
|
|
41
51
|
|
|
42
52
|
const { kibanaSearch, DEFAULT_CONFIG: BASE_CONFIG } = KC;
|
|
43
53
|
|
|
44
|
-
const
|
|
45
|
-
const BTS_ID = '1.3.0';
|
|
46
|
-
|
|
47
|
-
interface AssetInfo { symbol: string; precision: number; }
|
|
48
|
-
const ASSETS: Record<string, AssetInfo> = {
|
|
49
|
-
'1.3.0': { symbol: 'BTS', precision: 5 },
|
|
50
|
-
'1.3.118': { symbol: 'GBP', precision: 4 },
|
|
51
|
-
'1.3.119': { symbol: 'JPY', precision: 2 },
|
|
52
|
-
'1.3.120': { symbol: 'EUR', precision: 4 },
|
|
53
|
-
'1.3.1325': { symbol: 'RUBLE', precision: 5 },
|
|
54
|
-
'1.3.2512': { symbol: 'EVRAZ', precision: 4 },
|
|
55
|
-
'1.3.3291': { symbol: 'TWENTIX', precision: 5 },
|
|
56
|
-
'1.3.4099': { symbol: 'XBTSX.STH', precision: 6 },
|
|
57
|
-
'1.3.4156': { symbol: 'XBTSX.DOGE', precision: 5 },
|
|
58
|
-
'1.3.4157': { symbol: 'XBTSX.BTC', precision: 8 },
|
|
59
|
-
'1.3.4159': { symbol: 'XBTSX.LTC', precision: 8 },
|
|
60
|
-
'1.3.4176': { symbol: 'XBTSX.DASH', precision: 8 },
|
|
61
|
-
'1.3.4274': { symbol: 'XBTSX.BCH', precision: 8 },
|
|
62
|
-
'1.3.4760': { symbol: 'XBTSX.ETH', precision: 7 },
|
|
63
|
-
'1.3.5537': { symbol: 'IOB.XRP', precision: 4 },
|
|
64
|
-
'1.3.5541': { symbol: 'XBTSX.BNB', precision: 7 },
|
|
65
|
-
'1.3.5589': { symbol: 'XBTSX.USDT', precision: 6 },
|
|
66
|
-
'1.3.5641': { symbol: 'HONEST.CNY', precision: 4 },
|
|
67
|
-
'1.3.5649': { symbol: 'HONEST.USD', precision: 4 },
|
|
68
|
-
'1.3.5650': { symbol: 'HONEST.BTC', precision: 8 },
|
|
69
|
-
'1.3.5659': { symbol: 'HONEST.ETH', precision: 6 },
|
|
70
|
-
'1.3.5870': { symbol: 'XBTSX.FIL', precision: 6 },
|
|
71
|
-
'1.3.5887': { symbol: 'XBTSX.RUB', precision: 4 },
|
|
72
|
-
'1.3.5902': { symbol: 'XBTSX.USDC', precision: 6 },
|
|
73
|
-
'1.3.6013': { symbol: 'XBTSX.HIVE', precision: 6 },
|
|
74
|
-
'1.3.6124': { symbol: 'XBTSX.AVAX', precision: 6 },
|
|
75
|
-
'1.3.6139': { symbol: 'XBTSX.XAUT', precision: 6 },
|
|
76
|
-
'1.3.6166': { symbol: 'XBTSX.MATIC', precision: 5 },
|
|
77
|
-
'1.3.6241': { symbol: 'XBTSX.ETC', precision: 7 },
|
|
78
|
-
'1.3.6268': { symbol: 'BTWTY.EOS', precision: 4 },
|
|
79
|
-
'1.3.6301': { symbol: 'HONEST.MONEY', precision: 8 },
|
|
80
|
-
'1.3.6304': { symbol: 'HONEST.ADA', precision: 8 },
|
|
81
|
-
'1.3.6305': { symbol: 'HONEST.DOT', precision: 8 },
|
|
82
|
-
'1.3.6309': { symbol: 'HONEST.ATOM', precision: 8 },
|
|
83
|
-
'1.3.6311': { symbol: 'HONEST.ALGO', precision: 8 },
|
|
84
|
-
'1.3.6312': { symbol: 'HONEST.FIL', precision: 8 },
|
|
85
|
-
'1.3.6313': { symbol: 'HONEST.EOS', precision: 8 },
|
|
86
|
-
'1.3.6315': { symbol: 'HONEST.EUR', precision: 4 },
|
|
87
|
-
'1.3.6316': { symbol: 'HONEST.GBP', precision: 4 },
|
|
88
|
-
'1.3.6317': { symbol: 'HONEST.JPY', precision: 4 },
|
|
89
|
-
'1.3.6444': { symbol: 'IOB.XLM', precision: 4 },
|
|
90
|
-
'1.3.6573': { symbol: 'XBTSX.DAI', precision: 6 },
|
|
91
|
-
'1.3.6620': { symbol: 'XBTSX.A', precision: 6 },
|
|
92
|
-
'1.3.6627': { symbol: 'XBTSX.LINK', precision: 6 },
|
|
93
|
-
};
|
|
94
|
-
const resolvedPrecisions: Record<string, number> = {};
|
|
95
|
-
function assetSymbol(id: string): string { return ASSETS[id]?.symbol ?? id; }
|
|
96
|
-
function assetPrec(id: string): number | undefined { return ASSETS[id]?.precision ?? resolvedPrecisions[id]; }
|
|
97
|
-
function toReal(amount: number, assetId: string): number {
|
|
98
|
-
const p = assetPrec(assetId);
|
|
99
|
-
if (p === undefined) return NaN;
|
|
100
|
-
return amount / Math.pow(10, p);
|
|
101
|
-
}
|
|
54
|
+
const OP_LIMIT_ORDER_UPDATE = 77;
|
|
102
55
|
|
|
103
56
|
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
104
|
-
interface
|
|
105
|
-
time: string;
|
|
106
|
-
blockNum: number;
|
|
107
|
-
opNum: number;
|
|
57
|
+
interface OrderUpdate {
|
|
108
58
|
orderId: string;
|
|
109
|
-
|
|
110
|
-
pays: { amount: number; asset_id: string };
|
|
111
|
-
receives: { amount: number; asset_id: string };
|
|
112
|
-
fee: { amount: number; asset_id: string };
|
|
113
|
-
isMaker: boolean;
|
|
114
|
-
sort: any[];
|
|
59
|
+
sequence: number;
|
|
115
60
|
}
|
|
116
61
|
interface TradeFill {
|
|
117
62
|
time: string;
|
|
@@ -225,7 +170,6 @@ Options:
|
|
|
225
170
|
--refresh-account Force re-resolution of preferredAccount and update the
|
|
226
171
|
stored accountId when it changed (default: reuse the
|
|
227
172
|
stored accountId with no chain lookup)
|
|
228
|
-
--node <url> BitShares node URL for account / precision resolution
|
|
229
173
|
--increment <pct> Grid increment percent (default: from bot config or ${Number((C as any)?.DEFAULT_CONFIG?.incrementPercent ?? 0.5)})
|
|
230
174
|
--tolerance <pct> Deprecated alias for --increment (kept for compat, prefer --increment)
|
|
231
175
|
--per-fill Check at fill granularity (default: per-order aggregated)
|
|
@@ -266,7 +210,6 @@ function parseArgs() {
|
|
|
266
210
|
account: null,
|
|
267
211
|
lookup: false,
|
|
268
212
|
refreshAccount: false,
|
|
269
|
-
node: C.NODE_MANAGEMENT.DEFAULT_NODES[0],
|
|
270
213
|
perFill: false,
|
|
271
214
|
includeCrossPair: false,
|
|
272
215
|
incrementPercent: null as number | null,
|
|
@@ -284,7 +227,6 @@ function parseArgs() {
|
|
|
284
227
|
case '--account': opts.account = args[++i]; break;
|
|
285
228
|
case '--lookup': opts.lookup = true; break;
|
|
286
229
|
case '--refresh-account': opts.refreshAccount = true; break;
|
|
287
|
-
case '--node': opts.node = args[++i]; break;
|
|
288
230
|
case '--per-fill': opts.perFill = true; break;
|
|
289
231
|
case '--include-cross-pair': opts.includeCrossPair = true; break;
|
|
290
232
|
case '--increment': opts.incrementPercent = parseFloat(args[++i]); break;
|
|
@@ -341,183 +283,68 @@ function resolveTimeRange(opts: any): { gte: string; lte: string; label: string
|
|
|
341
283
|
return { gte, lte, label };
|
|
342
284
|
}
|
|
343
285
|
|
|
344
|
-
// ─── Account resolution
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
process.env.LOG_LEVEL = prevLevel;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
async function resolveAccountForBot(botKey: string, overrideAccount: string | null, nodeUrl: string, doRefresh: boolean): Promise<{ accountId: string; botMeta: any }> {
|
|
365
|
-
const botMeta = loadBotMeta(botKey);
|
|
366
|
-
if (!botMeta && !overrideAccount) {
|
|
367
|
-
console.error(`Error: bot key '${botKey}' not found in profiles/bots.json and no --account provided.`);
|
|
368
|
-
console.error(`Use --list-bots to see available keys, or pass --account <1.2.x> explicitly.`);
|
|
369
|
-
process.exit(1);
|
|
370
|
-
}
|
|
371
|
-
// An explicit --account always wins and is never persisted.
|
|
372
|
-
if (overrideAccount) {
|
|
373
|
-
if (/^1\.2\.\d+$/.test(String(overrideAccount))) {
|
|
374
|
-
return { accountId: String(overrideAccount), botMeta };
|
|
375
|
-
}
|
|
376
|
-
console.log(` Resolving account name '${overrideAccount}'...`);
|
|
377
|
-
const resolvedOverride = await resolveAccountId(String(overrideAccount), nodeUrl);
|
|
378
|
-
if (!resolvedOverride) {
|
|
379
|
-
console.error(`Error: failed to resolve --account '${overrideAccount}' to 1.2.x`);
|
|
380
|
-
process.exit(1);
|
|
381
|
-
}
|
|
382
|
-
console.log(` → ${resolvedOverride}`);
|
|
383
|
-
return { accountId: String(resolvedOverride), botMeta };
|
|
384
|
-
}
|
|
385
|
-
const prefRaw = botMeta?.preferredAccount != null ? String(botMeta.preferredAccount) : null;
|
|
386
|
-
const prefIsId = !!prefRaw && /^1\.2\.\d+$/.test(prefRaw);
|
|
387
|
-
const storedId = /^1\.2\.\d+$/.test(String(botMeta?.accountId ?? '')) ? String(botMeta.accountId) : null;
|
|
388
|
-
// An explicit 1.2.x preferredAccount is authoritative: the stored accountId
|
|
389
|
-
// is a derived cache and must never override it. Self-heal the cache.
|
|
390
|
-
if (prefIsId) {
|
|
391
|
-
if (storedId && storedId !== prefRaw && persistBotAccountId(botKey, prefRaw as string)) {
|
|
392
|
-
console.log(` Updated stale stored accountId ${storedId} → ${prefRaw} from preferredAccount`);
|
|
393
|
-
}
|
|
394
|
-
return { accountId: prefRaw as string, botMeta };
|
|
395
|
-
}
|
|
396
|
-
if (!prefRaw) {
|
|
397
|
-
console.error(`Error: bot '${botKey}' has no preferredAccount and no --account provided.`);
|
|
398
|
-
process.exit(1);
|
|
399
|
-
}
|
|
400
|
-
// Name + fresh-enough cache + no refresh requested: offline-friendly fast path.
|
|
401
|
-
if (storedId && !doRefresh) {
|
|
402
|
-
console.log(` Using stored accountId ${storedId} from profiles/bots.json (no lookup needed; pass --refresh-account to re-verify)`);
|
|
403
|
-
return { accountId: storedId, botMeta };
|
|
404
|
-
}
|
|
405
|
-
// No cache, or --refresh-account: resolve the name on-chain.
|
|
406
|
-
console.log(` Resolving account name '${prefRaw}'...`);
|
|
407
|
-
const resolved = await resolveAccountId(prefRaw, nodeUrl);
|
|
408
|
-
if (!resolved) {
|
|
409
|
-
console.error(`Error: failed to resolve account name '${prefRaw}' to 1.2.x`);
|
|
410
|
-
process.exit(1);
|
|
411
|
-
}
|
|
412
|
-
console.log(` → ${resolved}`);
|
|
413
|
-
if (!storedId && persistBotAccountId(botKey, resolved)) {
|
|
414
|
-
console.log(` Stored accountId ${resolved} in profiles/bots.json for '${botKey}'`);
|
|
415
|
-
} else if (storedId && storedId !== resolved && persistBotAccountId(botKey, resolved)) {
|
|
416
|
-
console.log(` Updated stored accountId ${storedId} → ${resolved} in profiles/bots.json for '${botKey}'`);
|
|
417
|
-
} else if (storedId === resolved) {
|
|
418
|
-
console.log(` Stored accountId ${resolved} confirmed up to date`);
|
|
419
|
-
}
|
|
420
|
-
return { accountId: String(resolved), botMeta };
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// ─── Asset precision resolution ───────────────────────────────────────────────
|
|
424
|
-
async function resolveAssetPrecisions(fills: FillRecord[], nodeUrl: string | null): Promise<void> {
|
|
425
|
-
const unknownIds = new Set<string>();
|
|
426
|
-
for (const f of fills) {
|
|
427
|
-
for (const id of [f.pays.asset_id, f.receives.asset_id, f.fee.asset_id]) {
|
|
428
|
-
if (id !== BTS_ID && !(id in ASSETS) && !(id in resolvedPrecisions)) unknownIds.add(id);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (unknownIds.size === 0 || !nodeUrl) return;
|
|
432
|
-
const ids = [...unknownIds];
|
|
433
|
-
console.log(` Resolving ${ids.length} unknown asset(s) from blockchain...`);
|
|
434
|
-
const { createReadOnlyClient } = await import('../modules/bitshares-native/index.js');
|
|
435
|
-
const client = createReadOnlyClient({ nodes: [nodeUrl] });
|
|
436
|
-
try {
|
|
437
|
-
await client.connect();
|
|
438
|
-
const assets = await client.db('get_assets', [ids]);
|
|
439
|
-
if (Array.isArray(assets)) {
|
|
440
|
-
for (const asset of assets) {
|
|
441
|
-
if (asset?.id && asset.precision != null) {
|
|
442
|
-
resolvedPrecisions[asset.id] = asset.precision;
|
|
443
|
-
console.log(` ${asset.id} → ${asset.symbol || '?'} (precision ${asset.precision})`);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
const missing = ids.filter(id => !(id in resolvedPrecisions));
|
|
448
|
-
if (missing.length > 0) console.warn(` [warn] ${missing.length} asset(s) not found on chain: ${missing.join(', ')}`);
|
|
449
|
-
} catch (e: any) {
|
|
450
|
-
console.warn(` [warn] Asset resolution failed: ${e.message}`);
|
|
451
|
-
} finally {
|
|
452
|
-
try { client.disconnect(); } catch (_) {}
|
|
286
|
+
// ─── Account resolution errors ────────────────────────────────────────────────
|
|
287
|
+
/** Map a shared account-resolver failure onto this tool's operator-facing hint. */
|
|
288
|
+
function reportAccountFailure(resolved: any, opts: any): void {
|
|
289
|
+
switch (resolved.reason) {
|
|
290
|
+
case 'bot-not-found':
|
|
291
|
+
console.error(`Error: bot key '${opts.botKey}' not found in profiles/bots.json and no --account provided.`);
|
|
292
|
+
console.error('Use --list-bots to see available keys, or pass --account <1.2.x> explicitly.');
|
|
293
|
+
break;
|
|
294
|
+
case 'override-unresolved':
|
|
295
|
+
console.error(`Error: failed to resolve --account '${opts.account}' to 1.2.x`);
|
|
296
|
+
break;
|
|
297
|
+
case 'no-preferred-account':
|
|
298
|
+
console.error(`Error: bot '${opts.botKey}' has no preferredAccount and no --account provided.`);
|
|
299
|
+
break;
|
|
300
|
+
default:
|
|
301
|
+
console.error(`Error: failed to resolve account name '${resolved?.botMeta?.preferredAccount ?? opts.botKey}' to 1.2.x`);
|
|
453
302
|
}
|
|
454
303
|
}
|
|
455
304
|
|
|
456
305
|
// ─── Kibana fetch ─────────────────────────────────────────────────────────────
|
|
457
|
-
function
|
|
458
|
-
return {
|
|
459
|
-
size,
|
|
460
|
-
track_total_hits: false,
|
|
461
|
-
_source: [
|
|
462
|
-
'block_data.block_time',
|
|
463
|
-
'block_data.block_num',
|
|
464
|
-
'operation_id_num',
|
|
465
|
-
'operation_history.op_object.pays',
|
|
466
|
-
'operation_history.op_object.receives',
|
|
467
|
-
'operation_history.op_object.fee',
|
|
468
|
-
'operation_history.op_object.order_id',
|
|
469
|
-
'operation_history.op_object.account_id',
|
|
470
|
-
'operation_history.op_object.is_maker',
|
|
471
|
-
],
|
|
472
|
-
query: {
|
|
473
|
-
bool: {
|
|
474
|
-
filter: [
|
|
475
|
-
{ term: { operation_type: OP_FILL_ORDER } },
|
|
476
|
-
{ term: { 'operation_history.op_object.account_id.keyword': accountId } },
|
|
477
|
-
{ range: { 'block_data.block_time': { gte, lte } } },
|
|
478
|
-
],
|
|
479
|
-
},
|
|
480
|
-
},
|
|
481
|
-
sort: [
|
|
482
|
-
{ 'block_data.block_time': { order: 'asc' } },
|
|
483
|
-
{ operation_id_num: { order: 'asc' } },
|
|
484
|
-
],
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
async function fetchAllFills(config: any, accountId: string, gte: string, lte: string): Promise<FillRecord[]> {
|
|
306
|
+
async function fetchAllOrderUpdates(config: any, accountId: string, gte: string, lte: string): Promise<OrderUpdate[]> {
|
|
489
307
|
const pageSize = 10000;
|
|
490
|
-
const
|
|
308
|
+
const updates: OrderUpdate[] = [];
|
|
491
309
|
let searchAfter: any[] | null = null;
|
|
492
310
|
const cfg = { ...BASE_CONFIG, timeout: 60000, ...config };
|
|
493
311
|
while (true) {
|
|
494
|
-
const query =
|
|
495
|
-
|
|
312
|
+
const query: any = {
|
|
313
|
+
size: pageSize,
|
|
314
|
+
track_total_hits: false,
|
|
315
|
+
_source: [
|
|
316
|
+
'block_data.block_num', 'operation_id_num',
|
|
317
|
+
'operation_history.op_object.order',
|
|
318
|
+
'operation_history.op_object.seller',
|
|
319
|
+
],
|
|
320
|
+
query: { bool: { filter: [
|
|
321
|
+
{ term: { operation_type: OP_LIMIT_ORDER_UPDATE } },
|
|
322
|
+
{ term: { 'operation_history.op_object.seller.keyword': accountId } },
|
|
323
|
+
{ range: { 'block_data.block_time': { gte, lte } } },
|
|
324
|
+
] } },
|
|
325
|
+
sort: [
|
|
326
|
+
{ 'block_data.block_num': { order: 'asc' } },
|
|
327
|
+
{ operation_id_num: { order: 'asc' } },
|
|
328
|
+
],
|
|
329
|
+
};
|
|
330
|
+
if (searchAfter) query.search_after = searchAfter;
|
|
496
331
|
const result: any = await kibanaSearch(cfg, query);
|
|
497
332
|
const hits = result?.hits?.hits ?? [];
|
|
498
333
|
if (!hits.length) break;
|
|
499
334
|
for (const hit of hits) {
|
|
500
|
-
const
|
|
501
|
-
const op =
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
orderId: op.order_id ?? '',
|
|
508
|
-
accountId: op.account_id ?? '',
|
|
509
|
-
pays: { amount: Number(op.pays.amount ?? 0), asset_id: op.pays.asset_id ?? '' },
|
|
510
|
-
receives: { amount: Number(op.receives.amount ?? 0), asset_id: op.receives.asset_id ?? '' },
|
|
511
|
-
fee: { amount: Number(op.fee?.amount ?? 0), asset_id: op.fee?.asset_id ?? '' },
|
|
512
|
-
isMaker: op.is_maker ?? false,
|
|
513
|
-
sort: hit.sort,
|
|
514
|
-
});
|
|
335
|
+
const source = hit?._source || {};
|
|
336
|
+
const op = source.operation_history?.op_object || {};
|
|
337
|
+
const orderId = op.order;
|
|
338
|
+
if (!orderId) continue;
|
|
339
|
+
const blockNum = Number(source.block_data?.block_num ?? 0);
|
|
340
|
+
const opNum = Number(source.operation_id_num ?? 0);
|
|
341
|
+
updates.push({ orderId, sequence: blockNum * 1e6 + opNum });
|
|
515
342
|
}
|
|
516
|
-
|
|
517
|
-
searchAfter =
|
|
518
|
-
if (!
|
|
343
|
+
const last = hits[hits.length - 1];
|
|
344
|
+
searchAfter = last?.sort;
|
|
345
|
+
if (!searchAfter || hits.length < pageSize) break;
|
|
519
346
|
}
|
|
520
|
-
return
|
|
347
|
+
return updates;
|
|
521
348
|
}
|
|
522
349
|
|
|
523
350
|
// ─── Fill classification ─────────────────────────────────────────────────────
|
|
@@ -578,11 +405,31 @@ function classifyFills(fills: FillRecord[]): { trades: TradeFill[]; skipped: num
|
|
|
578
405
|
return { trades, skipped };
|
|
579
406
|
}
|
|
580
407
|
|
|
581
|
-
// ─── Per-order aggregation
|
|
582
|
-
|
|
408
|
+
// ─── Per-order/price-epoch aggregation ───────────────────────────────────────
|
|
409
|
+
// Collapses partial fills at one order lifetime, but never mixes fills from
|
|
410
|
+
// different native limit_order_update repricings of the same order ID.
|
|
411
|
+
function aggregateByOrder(trades: TradeFill[], updates: OrderUpdate[] = []): AggregatedOrder[] {
|
|
412
|
+
const updatesByOrder = new Map<string, number[]>();
|
|
413
|
+
for (const update of updates) {
|
|
414
|
+
const list = updatesByOrder.get(update.orderId) || [];
|
|
415
|
+
list.push(update.sequence);
|
|
416
|
+
updatesByOrder.set(update.orderId, list);
|
|
417
|
+
}
|
|
418
|
+
for (const list of updatesByOrder.values()) list.sort((a, b) => a - b);
|
|
419
|
+
|
|
583
420
|
const map = new Map<string, { trades: TradeFill[] }>();
|
|
584
421
|
for (const t of trades) {
|
|
585
|
-
|
|
422
|
+
// An update is ordered before the fills it can affect. The epoch is
|
|
423
|
+
// therefore the latest update sequence at or before this fill.
|
|
424
|
+
const orderUpdates = updatesByOrder.get(t.orderId) || [];
|
|
425
|
+
let epoch = 0;
|
|
426
|
+
for (const sequence of orderUpdates) {
|
|
427
|
+
if (sequence <= t.sequence) epoch = sequence;
|
|
428
|
+
else break;
|
|
429
|
+
}
|
|
430
|
+
const k = t.orderId
|
|
431
|
+
? `${t.orderId}:${t.direction}:${t.baseAsset}:${t.quoteAsset}:${epoch}`
|
|
432
|
+
: `__fill_${t.sequence}`;
|
|
586
433
|
if (!map.has(k)) map.set(k, { trades: [] });
|
|
587
434
|
map.get(k)!.trades.push(t);
|
|
588
435
|
}
|
|
@@ -865,21 +712,34 @@ async function main() {
|
|
|
865
712
|
console.log(`\nGrid correction check — bot-key: ${opts.botKey}`);
|
|
866
713
|
console.log(`Range: ${label}`);
|
|
867
714
|
|
|
868
|
-
const
|
|
715
|
+
const resolvedAccount = await resolveBotAccount(opts.botKey, {
|
|
716
|
+
overrideAccount: opts.account,
|
|
717
|
+
refresh: opts.refreshAccount,
|
|
718
|
+
});
|
|
719
|
+
if (!resolvedAccount.accountId) {
|
|
720
|
+
reportAccountFailure(resolvedAccount, opts);
|
|
721
|
+
process.exit(1);
|
|
722
|
+
}
|
|
723
|
+
const accountId = resolvedAccount.accountId;
|
|
724
|
+
const botMeta = resolvedAccount.botMeta;
|
|
869
725
|
console.log(`Account: ${accountId}${botMeta ? ` (${botMeta.assetA}/${botMeta.assetB})` : ''}`);
|
|
870
726
|
const incrementPercent = resolveIncrementPercent(botMeta, opts.incrementPercent);
|
|
871
727
|
console.log(`Increment: ${incrementPercent}% (halfInc ${incrementPercent/2}%)${opts.incrementPercent == null && botMeta?.incrementPercent != null ? ' — from bot config' : opts.incrementPercent != null ? ' — from --increment' : ' — default'}`);
|
|
872
728
|
|
|
873
|
-
console.log(`\nFetching fills from Kibana...`);
|
|
874
|
-
const fills = await
|
|
729
|
+
console.log(`\nFetching fills and order updates from Kibana...`);
|
|
730
|
+
const [fills, orderUpdates] = await Promise.all([
|
|
731
|
+
fetchAllFills({}, accountId, gte, lte),
|
|
732
|
+
fetchAllOrderUpdates({}, accountId, gte, lte),
|
|
733
|
+
]);
|
|
875
734
|
console.log(` Fetched ${fills.length} fill_order operation(s)`);
|
|
735
|
+
console.log(` Fetched ${orderUpdates.length} limit_order_update operation(s)`);
|
|
876
736
|
|
|
877
737
|
if (fills.length === 0) {
|
|
878
738
|
console.log('\nNo fills in range — nothing to check.');
|
|
879
739
|
process.exit(0);
|
|
880
740
|
}
|
|
881
741
|
|
|
882
|
-
await resolveAssetPrecisions(fills
|
|
742
|
+
await resolveAssetPrecisions(fills);
|
|
883
743
|
|
|
884
744
|
const { trades, skipped } = classifyFills(fills);
|
|
885
745
|
console.log(` Classified ${trades.length} trade(s)${skipped > 0 ? `, ${skipped} skipped (unknown precision)` : ''}`);
|
|
@@ -905,8 +765,8 @@ async function main() {
|
|
|
905
765
|
if (opts.perFill) {
|
|
906
766
|
items = trades;
|
|
907
767
|
} else {
|
|
908
|
-
const orders = aggregateByOrder(trades);
|
|
909
|
-
console.log(` Aggregated into ${orders.length} order(s) (
|
|
768
|
+
const orders = aggregateByOrder(trades, orderUpdates);
|
|
769
|
+
console.log(` Aggregated into ${orders.length} order epoch(s) (partial fills collapsed; repriced orders kept separate)`);
|
|
910
770
|
items = orders;
|
|
911
771
|
}
|
|
912
772
|
|