dexbot 1.4.22 → 1.4.23
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 +22 -0
- package/README.md +7 -4
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +3 -3
- package/analysis/ama_fitting/optimizer_high_resolution.ts +4 -4
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/tradingview/README.md +24 -4
- package/analysis/tradingview/tradingview_uplot_chart_generator.ts +84 -42
- 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/ama_fitting/analyze_lambda_vs_slow.js +3 -3
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js +4 -4
- package/dist/analysis/ama_fitting/optimizer_high_resolution.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 +84 -42
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
- package/dist/market_adapter/market_adapter.d.ts.map +1 -1
- package/dist/market_adapter/market_adapter.js +6 -2
- package/dist/market_adapter/market_adapter.js.map +1 -1
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +46 -11
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/constants.js +7 -7
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +17 -3
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +29 -3
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +54 -10
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +13 -0
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/scripts/analyze-orders.d.ts.map +1 -1
- package/dist/scripts/analyze-orders.js +26 -2
- package/dist/scripts/analyze-orders.js.map +1 -1
- package/dist/scripts/sync-version.js +5 -2
- package/dist/scripts/sync-version.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +15 -10
- package/docs/DEXBOT_COMPARISON.md +18 -18
- package/docs/EVOLUTION.md +9 -8
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
- package/docs/GRID_RECALCULATION.md +1 -1
- package/docs/README.md +3 -3
- package/market_adapter/README.md +13 -8
- package/package.json +1 -1
- package/analysis/results/ama_sweep_results_lp_pool_133_1h.json +0 -2455
- package/analysis/results/bot_fitting_results_lp_pool_133_1h.json +0 -218
- package/analysis/tradingview/h-bts_tradingview.html +0 -1570
- package/analysis/tradingview/t-bts_tradingview.html +0 -1570
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.4.23] - 2026-08-28 - Even AMA Ladder, BTS Fee-Carve Fix, Price-Bound Rejection, TradingView Axis, Doc Realignment
|
|
6
|
+
|
|
7
|
+
### 2026-08-26
|
|
8
|
+
|
|
9
|
+
- **Fix(analysis)**: survive numeric botFunds values in analyze-orders — `botFunds` could arrive as a bare number (e.g. from upstream contribution #13) instead of the `{base,quote}` object shape the dynamic-weight path expected, throwing on property access; `analyze-orders` now normalizes numeric botFunds into the object form before use, with a regression test covering the number input (`scripts/analyze-orders.ts`, `tests/test_analyze_orders_dynamic_weight.ts`).
|
|
10
|
+
|
|
11
|
+
### 2026-08-27
|
|
12
|
+
|
|
13
|
+
- **Docs(readme)**: add Arch/Manjaro Git install instruction — the prerequisites block assumed apt/debian-based package managers; a one-liner for `pacman -S git` is added alongside the existing distros (`README.md`).
|
|
14
|
+
- **Fix(order)**: reject sub-1x price-bound multipliers resolving above market (#15) — `minPrice`/`maxPrice` accepted multipliers like `0.5x` that resolve to a price above the current market (e.g. 0.5x of a higher anchor), silently placing the whole grid off-market; the editor now blocks sub-1x multipliers whose resolved price would sit above market, the multiplier parser reports the resolved price for validation, and `utils/math.ts`/`utils/order.ts` gain the rejection helpers with `tests/test_utils.ts` coverage (`modules/account_bots.ts`, `modules/order/grid.ts`, `modules/order/utils/math.ts`, `modules/order/utils/order.ts`, `tests/test_utils.ts`).
|
|
15
|
+
- **Fix**: deep-merge nested kalman override instead of wholesale replace — the AMA-grid-price override path replaced the entire nested `kalman` config object with the raw override, dropping sibling keys; the override now deep-merges into the existing kalman subtree, with `tests/test_dynamic_weight_override_wiring.ts` coverage (`market_adapter/market_adapter.ts`, `tests/test_dynamic_weight_override_wiring.ts`).
|
|
16
|
+
- **Tune**: even geometric AMA slowPeriod ladder (+16% steps) — the `AMA_SLOW_PERIOD_LADDER` used uneven spacing between rungs; the geometric step is normalized to a constant +16% ratio so preset spacing is uniform and predictable (`modules/constants.ts`).
|
|
17
|
+
- **Docs**: align AMA preset references with constants ladder, fix stale warmup math — docs and a few analysis scripts cited AMA ladder values and warmup formulas that had drifted from `modules/constants.ts`; references are corrected to the live ladder, stale warmup/window math fixed, and `scripts/sync-version.ts` hardened to sync the version into the docs-derived constants it consumes (`analysis/ama_fitting/analyze_lambda_vs_slow.ts`, `analysis/ama_fitting/optimizer_high_resolution.ts`, `analysis/tradingview/README.md`, `docs/GRID_RECALCULATION.md`, `docs/README.md`, `market_adapter/README.md`, `modules/constants.ts`, `scripts/sync-version.ts`, `tests/test_market_adapter_logic.ts`).
|
|
18
|
+
- **Fix(tradingview)**: working price-axis zoom, log density, and 4-digit labels — the TradingView-style chart exporter's price-axis interaction regressed: wheel zoom on the gutter, log-scale density, and 4-digit axis labels are restored with the same `UPLOT_SHARED_SCRIPT` range-callback contract used elsewhere (`analysis/tradingview/tradingview_uplot_chart_generator.ts`).
|
|
19
|
+
- **Docs**: reorder Reference Docs from general to specific — `README.md`'s Reference Docs section is reordered so the broad architecture/lifecycle docs lead and the narrower per-subsystem docs follow, matching the reader's narrowing path (`README.md`).
|
|
20
|
+
|
|
21
|
+
### 2026-08-28
|
|
22
|
+
|
|
23
|
+
- **Docs**: enrich BitShares onboarding links and restructure closing sections — `docs/BITSHARES_ONBOARDING.md` adds more precise links to the relevant BitShares resources and reorganizes the closing sections (next steps, troubleshooting, support) for better flow (`docs/BITSHARES_ONBOARDING.md`).
|
|
24
|
+
- **Fix(analysis)**: ensure charts dir exists before writing order-analysis export — `analyze-orders --export` wrote the HTML report into `analysis/charts/` but assumed the directory already existed, throwing on a fresh checkout; the export now materializes the charts directory before writing (`scripts/analyze-orders.ts`).
|
|
25
|
+
- **Fix(grid)**: stop BTS-pair fee carve from clipping the non-BTS side budget — the BTS-pair fee carve adjusted the budget for both sides of a BTS-quoted pair, so carving the BTS-side fee also shrank the opposite (non-BTS) asset's budget below what it should hold; the carve now only trims the BTS leg, leaving the non-BTS side's budget intact, with extended `tests/test_grid_logic.ts` coverage (`modules/order/grid.ts`, `tests/test_grid_logic.ts`).
|
|
26
|
+
|
|
5
27
|
## [1.4.22] - 2026-08-25 - tsx Removal Completion, Exact AMA Bootstrap, Research Parity, Canonical Grid Bounds, Modules-Wide Audit
|
|
6
28
|
|
|
7
29
|
### 2026-08-26
|
package/README.md
CHANGED
|
@@ -65,6 +65,9 @@ Install Git:
|
|
|
65
65
|
sudo apt-get update
|
|
66
66
|
sudo apt-get install git
|
|
67
67
|
|
|
68
|
+
# Arch/Manjaro
|
|
69
|
+
sudo pacman -S git
|
|
70
|
+
|
|
68
71
|
# Fedora/RHEL
|
|
69
72
|
sudo dnf install git
|
|
70
73
|
```
|
|
@@ -301,14 +304,14 @@ Logs are written to `logs/` in the profiles directory in all modes: the monolith
|
|
|
301
304
|
### Reference Docs
|
|
302
305
|
|
|
303
306
|
- **[Docs Index](docs/README.md)** - Main documentation hub
|
|
304
|
-
- **[Claw API Boundary](claw/docs/AI_BOT_LIBRARY_API.md)** - Responsibility split between the AI layer and the DEXBot2 execution layer
|
|
305
307
|
- **[Architecture](docs/architecture.md)** - System design, fill processing pipeline, and testing strategy
|
|
306
308
|
- **[Lifecycle](docs/LIFECYCLE.md)** - End-to-end walkthrough: startup, fill-driven, and AMA-driven flows with diagrams
|
|
307
|
-
- **[Developer Guide](docs/developer_guide.md)** - Development guide, environment variables, examples, and glossary
|
|
308
|
-
- **[Copy-on-Write Plan](docs/COPY_ON_WRITE_MASTER_PLAN.md)** - Copy-on-Write grid architecture
|
|
309
|
-
- **[Fund Movement & Accounting](docs/FUND_MOVEMENT_AND_ACCOUNTING.md)** - Fund accounting, grid topology, and rotation mechanics
|
|
310
309
|
- **[Evolution Report](docs/EVOLUTION.md)** - Project timeline, architecture phases, and release history
|
|
310
|
+
- **[Developer Guide](docs/developer_guide.md)** - Development guide, environment variables, examples, and glossary
|
|
311
311
|
- **[Workflow](docs/WORKFLOW.md)** - Project workflow and contribution guide
|
|
312
|
+
- **[Fund Movement & Accounting](docs/FUND_MOVEMENT_AND_ACCOUNTING.md)** - Fund accounting, grid topology, and rotation mechanics
|
|
313
|
+
- **[Copy-on-Write Plan](docs/COPY_ON_WRITE_MASTER_PLAN.md)** - Copy-on-Write grid architecture
|
|
314
|
+
- **[Claw API Boundary](claw/docs/AI_BOT_LIBRARY_API.md)** - Responsibility split between the AI layer and the DEXBot2 execution layer
|
|
312
315
|
|
|
313
316
|
## 🤝 Contributing
|
|
314
317
|
|
|
@@ -191,9 +191,9 @@ function generateChartHtml(results: any, metricCache: any, fixEr: any, fixFast:
|
|
|
191
191
|
|
|
192
192
|
const amaAnnotations = [
|
|
193
193
|
{ label: 'AMA1', lambda: 0.0031, slow: 62.1, color: '#ef5350' },
|
|
194
|
-
{ label: 'AMA2', lambda: 0.0025, slow:
|
|
195
|
-
{ label: 'AMA3', lambda: 0.00185, slow:
|
|
196
|
-
{ label: 'AMA4', lambda: 0.0013, slow:
|
|
194
|
+
{ label: 'AMA2', lambda: 0.0025, slow: 72.0, color: '#fb8c00' },
|
|
195
|
+
{ label: 'AMA3', lambda: 0.00185, slow: 83.6, color: '#5c9ee6' },
|
|
196
|
+
{ label: 'AMA4', lambda: 0.0013, slow: 96.9, color: '#26a69a' },
|
|
197
197
|
].filter(a => a.lambda >= xs[0] && a.lambda <= xs[xs.length - 1]);
|
|
198
198
|
|
|
199
199
|
return `<!DOCTYPE html>
|
|
@@ -53,10 +53,10 @@ const DEFAULT_SEARCH = {
|
|
|
53
53
|
// Override individually via --ama1Weight, --ama2Weight, etc. CLI flags.
|
|
54
54
|
|
|
55
55
|
const AMA_OBJECTIVES = [
|
|
56
|
-
{ key: 'AMA1', name: 'AMA1
|
|
57
|
-
{ key: 'AMA2', name: 'AMA2
|
|
58
|
-
{ key: 'AMA3', name: 'AMA3
|
|
59
|
-
{ key: 'AMA4', name: 'AMA4
|
|
56
|
+
{ key: 'AMA1', name: 'AMA1', distanceCapQuantile: 0.25, distanceWeight: 0.0031 },
|
|
57
|
+
{ key: 'AMA2', name: 'AMA2', distanceCapQuantile: 0.30, distanceWeight: 0.0025 },
|
|
58
|
+
{ key: 'AMA3', name: 'AMA3', distanceCapQuantile: 0.35, distanceWeight: 0.00185 },
|
|
59
|
+
{ key: 'AMA4', name: 'AMA4', distanceCapQuantile: 0.40, distanceWeight: 0.0013 },
|
|
60
60
|
];
|
|
61
61
|
|
|
62
62
|
function cloneObjectives() {
|
|
@@ -74,7 +74,7 @@ node dist/analysis/tradingview/analyze_tradingview.js \
|
|
|
74
74
|
1. Reads `profiles/bots.json` to find the bot's `assetA`, `assetB`, and `ama` settings.
|
|
75
75
|
2. Resolves the candle file at `market_adapter/data/market_adapter_<bot-key>_1h.json`.
|
|
76
76
|
3. Looks up the matching market profile in `profiles/market_profiles.json` for AMA defaults.
|
|
77
|
-
4. AMA settings priority: bot-specific `ama` object > market profile > constants (AMA3, slowPeriod
|
|
77
|
+
4. AMA settings priority: bot-specific `ama` object > market profile > constants (AMA3, slowPeriod 83.6).
|
|
78
78
|
|
|
79
79
|
> The candle file must exist — run the market adapter LP exporter first if needed (see [Getting Blockchain Data](#getting-blockchain-data)).
|
|
80
80
|
|
|
@@ -108,14 +108,34 @@ If you pass a raw JSON file, the runner normalizes the candles before rendering.
|
|
|
108
108
|
Use the market adapter LP exporter to pull blockchain-backed candles before generating the HTML:
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
+
# Auto mode — resolves pool + precisions from bots.json / blockchain
|
|
112
|
+
node dist/market_adapter/inputs/fetch_lp_data.js --bot BTS-USDT --interval 1h --lookback 4392h
|
|
113
|
+
|
|
114
|
+
# Or with an explicit date range
|
|
115
|
+
node dist/market_adapter/inputs/fetch_lp_data.js --bot BTS-USDT --interval 1h --start 2026-02-23 --end 2026-08-23
|
|
116
|
+
|
|
117
|
+
# Manual mode — no blockchain needed
|
|
111
118
|
node dist/market_adapter/inputs/fetch_lp_data.js --pool 133 --precA 4 --precB 5 --interval 1h --lookback 26280h
|
|
112
119
|
```
|
|
113
120
|
|
|
114
121
|
For date range fetching, use `--start` and `--end` (e.g. `--start 2024-03-06 --end 2025-03-06`).
|
|
115
122
|
|
|
116
|
-
That writes a JSON file under `market_adapter/data/lp/` which you can then pass to the TradingView exporter
|
|
123
|
+
That writes a JSON file under `market_adapter/data/lp/` which you can then pass to the TradingView exporter:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
market_adapter/data/lp/<pair>/lp_pool_<id>_<interval>.json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Flag | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `--bot <name>` | Bot name from `profiles/bots.json` (auto-resolves pool) |
|
|
132
|
+
| `--pool <id>` | Manual mode, no blockchain needed (requires `--precA/--precB`) |
|
|
133
|
+
| `--interval <1m\|5m\|15m\|30m\|1h\|2h\|4h\|6h\|12h\|1d\|1w>` | Candle bucket size (bare numbers = seconds, e.g. `1800` = 30m) |
|
|
134
|
+
| `--lookback <N>h` | Hours back from now |
|
|
135
|
+
| `--start / --end` | Explicit date range (e.g. `2026-02-23`) |
|
|
136
|
+
| `--out <path>` | Custom output path |
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
> **Note:** the fetcher may not exit on its own after printing `Saved:` (the live BitShares WebSocket + node monitor keep the process alive). It is safe to Ctrl+C once the file is saved.
|
|
119
139
|
|
|
120
140
|
## CLI Flags
|
|
121
141
|
|
|
@@ -129,7 +149,7 @@ For manual pool discovery, use `--pool`, `--precA`, and `--precB` instead of `--
|
|
|
129
149
|
| `--sma-period <n>` | SMA period | `500` |
|
|
130
150
|
| `--ama-er-period <n>` | AMA ER period | `781` |
|
|
131
151
|
| `--ama-fast-period <n>` | AMA fast period | `5.2` |
|
|
132
|
-
| `--ama-slow-period <n>` | AMA slow period | `
|
|
152
|
+
| `--ama-slow-period <n>` | AMA slow period | `83.6` |
|
|
133
153
|
| `--price-scale <log\|linear>` | Price axis scale | `log` |
|
|
134
154
|
| `--scale <log\|linear>` | Alias for `--price-scale` | `log` |
|
|
135
155
|
| `--vwap-bars <n>` | Rolling VWMA window | `500` |
|
|
@@ -618,42 +618,77 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
618
618
|
}, { passive: false });
|
|
619
619
|
}
|
|
620
620
|
function clamp(v, lo, hi) { return Math.max(lo, Math.min(hi, v)); }
|
|
621
|
+
// Significant-digit price formatting (5 "active" digits), matching the
|
|
622
|
+
// DEXBot order-price style (formatCurrency) but with one extra digit.
|
|
623
|
+
// Very small values get SI micro-suffixes (m/µ/n/p/...); large values
|
|
624
|
+
// get comma grouping. Examples: 34.935 -> "34.935", 119.975 -> "119.98",
|
|
625
|
+
// 3014.9 -> "3,014.9", 0.00567 -> "5.67m".
|
|
621
626
|
function fmtPrice(v) {
|
|
622
627
|
if (v == null || !Number.isFinite(v)) return '-';
|
|
623
|
-
const
|
|
624
|
-
if (
|
|
625
|
-
|
|
626
|
-
if (abs
|
|
627
|
-
|
|
628
|
+
const num = Number(v);
|
|
629
|
+
if (num === 0) return '0';
|
|
630
|
+
const abs = Math.abs(num);
|
|
631
|
+
if (abs < 0.1) {
|
|
632
|
+
if (abs >= 0.001) return fmtPrice(num * 1000) + 'm';
|
|
633
|
+
if (abs >= 0.000001) return fmtPrice(num * 1e6) + 'µ';
|
|
634
|
+
if (abs >= 1e-9) return fmtPrice(num * 1e9) + 'n';
|
|
635
|
+
if (abs >= 1e-12) return fmtPrice(num * 1e12) + 'p';
|
|
636
|
+
if (abs >= 1e-15) return fmtPrice(num * 1e15) + 'f';
|
|
637
|
+
if (abs >= 1e-18) return fmtPrice(num * 1e18) + 'a';
|
|
638
|
+
return num.toFixed(6);
|
|
639
|
+
}
|
|
640
|
+
const digits = 4;
|
|
641
|
+
let intDigits = Math.floor(Math.log10(abs)) + 1;
|
|
642
|
+
if (abs < 1) intDigits = 1;
|
|
643
|
+
const formatted = intDigits >= digits ? String(Math.round(num)) : num.toFixed(digits - intDigits);
|
|
644
|
+
return intDigits >= 4 ? formatted.replace(/\B(?=(\d{3})+(?!\d))/g, ',') : formatted;
|
|
628
645
|
}
|
|
629
646
|
function fmtPriceAxis(vals) {
|
|
630
647
|
if (!Array.isArray(vals) || vals.length === 0) return [];
|
|
631
|
-
|
|
632
|
-
for (let i = 1; i < vals.length; i++) {
|
|
633
|
-
const d = Math.abs(Number(vals[i]) - Number(vals[i - 1]));
|
|
634
|
-
if (Number.isFinite(d) && d > 0 && d < step) step = d;
|
|
635
|
-
}
|
|
636
|
-
let decimals = 4;
|
|
637
|
-
if (Number.isFinite(step) && step > 0) decimals = Math.ceil(-Math.log10(step));
|
|
638
|
-
decimals = Math.max(0, Math.min(10, decimals));
|
|
639
|
-
return vals.map((v) => (v == null || !Number.isFinite(v)) ? '' : Number(v).toFixed(decimals));
|
|
648
|
+
return vals.map((v) => (v == null || !Number.isFinite(v)) ? '' : fmtPrice(v));
|
|
640
649
|
}
|
|
641
650
|
function fmtPriceLabel(v) {
|
|
642
651
|
if (v == null || !Number.isFinite(v)) return '-';
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
652
|
+
return fmtPrice(v);
|
|
653
|
+
}
|
|
654
|
+
function logAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace) {
|
|
655
|
+
if (!Number.isFinite(scaleMin) || !Number.isFinite(scaleMax) || scaleMin <= 0 || scaleMax <= 0) return [];
|
|
656
|
+
let h = 600;
|
|
657
|
+
if (self && self.bbox && Number.isFinite(self.bbox.height)) h = self.bbox.height / (self.pxRatio || 1);
|
|
658
|
+
else if (self && self.over && self.over.clientHeight) h = self.over.clientHeight;
|
|
659
|
+
const target = Math.max(8, Math.min(16, Math.floor(h / 30)));
|
|
660
|
+
const lmin = Math.log10(scaleMin);
|
|
661
|
+
const lmax = Math.log10(scaleMax);
|
|
662
|
+
const out = [];
|
|
663
|
+
for (let i = 0; i <= target; i++) {
|
|
664
|
+
out.push(Math.pow(10, lmin + (lmax - lmin) * (i / target)));
|
|
665
|
+
}
|
|
666
|
+
return out;
|
|
649
667
|
}
|
|
668
|
+
// Significant-digit volume formatting (4 "active" digits) with K/M/B/T
|
|
669
|
+
// suffixes, matching the price-axis style. Examples: 1234567 -> "1235K",
|
|
670
|
+
// 1234567890 -> "1.235B".
|
|
650
671
|
function fmtVolume(v) {
|
|
651
672
|
if (v == null || !Number.isFinite(v)) return '-';
|
|
652
|
-
const
|
|
653
|
-
if (
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
673
|
+
const num = Number(v);
|
|
674
|
+
if (num === 0) return '0';
|
|
675
|
+
const abs = Math.abs(num);
|
|
676
|
+
const units = [[1e12, 'T'], [1e9, 'B'], [1e6, 'M'], [1e3, 'K']];
|
|
677
|
+
for (const [factor, suffix] of units) {
|
|
678
|
+
if (abs >= factor) {
|
|
679
|
+
const scaled = num / factor;
|
|
680
|
+
const a = Math.abs(scaled);
|
|
681
|
+
let intDigits = Math.floor(Math.log10(a)) + 1;
|
|
682
|
+
if (a < 1) intDigits = 1;
|
|
683
|
+
const digits = 4;
|
|
684
|
+
const formatted = intDigits >= digits ? String(Math.round(scaled)) : scaled.toFixed(digits - intDigits);
|
|
685
|
+
return formatted + suffix;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
let intDigits = Math.floor(Math.log10(abs)) + 1;
|
|
689
|
+
if (abs < 1) intDigits = 1;
|
|
690
|
+
const digits = 4;
|
|
691
|
+
return intDigits >= digits ? String(Math.round(num)) : num.toFixed(digits - intDigits);
|
|
657
692
|
}
|
|
658
693
|
function candleDirection(open, close) {
|
|
659
694
|
if (close > open) return 'up';
|
|
@@ -1447,12 +1482,15 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1447
1482
|
scale: 'y',
|
|
1448
1483
|
side: 1,
|
|
1449
1484
|
size: 84,
|
|
1450
|
-
space:
|
|
1485
|
+
space: isLogScale ? 1 : 45,
|
|
1451
1486
|
stroke: '#ffffff',
|
|
1452
1487
|
grid: { stroke: '#272f3a' },
|
|
1453
1488
|
ticks: { stroke: '#414b57', width: 1 },
|
|
1454
1489
|
font: '600 13px Segoe UI, sans-serif',
|
|
1455
|
-
|
|
1490
|
+
splits: isLogScale ? logAxisSplits : undefined,
|
|
1491
|
+
values: (u, vals) => isLogScale
|
|
1492
|
+
? vals.map((v) => (Number.isFinite(v) ? fmtPrice(v) : ''))
|
|
1493
|
+
: fmtPriceAxis(vals),
|
|
1456
1494
|
},
|
|
1457
1495
|
],
|
|
1458
1496
|
hooks: {
|
|
@@ -1505,17 +1543,19 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1505
1543
|
lastRenderedPriceScale = currentPriceScale;
|
|
1506
1544
|
return priceChart;
|
|
1507
1545
|
}
|
|
1508
|
-
// True when clientX sits over the price-axis
|
|
1509
|
-
//
|
|
1510
|
-
//
|
|
1511
|
-
//
|
|
1546
|
+
// True when clientX sits over the price-axis region. The chart canvas
|
|
1547
|
+
// (plot + axis gutters) can be wider than the viewport and the right
|
|
1548
|
+
// gutter clipped off-screen, so we key the price zone off the ON-SCREEN
|
|
1549
|
+
// chart container width (always reachable) rather than the far-right gutter.
|
|
1550
|
+
// The rightmost ~120px of the container zooms price; the rest pans time.
|
|
1512
1551
|
function inYAxisZone(chart, clientX) {
|
|
1513
1552
|
const rootRect = chart.root.getBoundingClientRect();
|
|
1514
|
-
if (!rootRect || rootRect.width <= 0
|
|
1515
|
-
const
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1553
|
+
if (!rootRect || rootRect.width <= 0) return false;
|
|
1554
|
+
const x = clientX - rootRect.left;
|
|
1555
|
+
if (chart === priceChart) {
|
|
1556
|
+
return x > rootRect.width - 120;
|
|
1557
|
+
}
|
|
1558
|
+
return false;
|
|
1519
1559
|
}
|
|
1520
1560
|
let priceMarkerLabel = null;
|
|
1521
1561
|
let priceMarkerLine = null;
|
|
@@ -1668,6 +1708,7 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1668
1708
|
const onMove = (e) => {
|
|
1669
1709
|
if (!dragging || !startRange) return;
|
|
1670
1710
|
e.preventDefault();
|
|
1711
|
+
chart.root.style.cursor = 'ns-resize';
|
|
1671
1712
|
const deltaPx = e.clientY - startClientY;
|
|
1672
1713
|
if (!Number.isFinite(deltaPx) || deltaPx === 0) return;
|
|
1673
1714
|
const factor = Math.exp(deltaPx / 350);
|
|
@@ -1680,12 +1721,13 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1680
1721
|
if (!dragging) return;
|
|
1681
1722
|
dragging = false;
|
|
1682
1723
|
startRange = null;
|
|
1683
|
-
|
|
1724
|
+
chart.root.style.cursor = '';
|
|
1684
1725
|
window.removeEventListener('mousemove', onMove);
|
|
1685
1726
|
window.removeEventListener('mouseup', endDrag);
|
|
1686
1727
|
};
|
|
1687
1728
|
chart.root.addEventListener('mousedown', (e) => {
|
|
1688
1729
|
if (!e || e.button !== 0 || e.ctrlKey || e.metaKey || e.altKey) return;
|
|
1730
|
+
// capture phase so we pre-empt uPlot's own plot drag when in the y-zone
|
|
1689
1731
|
const rect = chart.root.getBoundingClientRect();
|
|
1690
1732
|
if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) return;
|
|
1691
1733
|
if (chart !== priceChart || !inYAxisZone(chart, e.clientX)) return;
|
|
@@ -1696,14 +1738,14 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1696
1738
|
dragging = true;
|
|
1697
1739
|
startClientY = e.clientY;
|
|
1698
1740
|
startRange = range;
|
|
1699
|
-
|
|
1741
|
+
chart.root.style.cursor = 'ns-resize';
|
|
1700
1742
|
window.addEventListener('mousemove', onMove);
|
|
1701
1743
|
window.addEventListener('mouseup', endDrag, { once: true });
|
|
1702
|
-
});
|
|
1744
|
+
}, true);
|
|
1703
1745
|
}
|
|
1704
1746
|
function bindYAxisReset(chart) {
|
|
1705
1747
|
chart.root.addEventListener('dblclick', (e) => {
|
|
1706
|
-
if (chart !== priceChart
|
|
1748
|
+
if (chart !== priceChart) return;
|
|
1707
1749
|
manualYRange = null;
|
|
1708
1750
|
const vis = visiblePriceRange(chart);
|
|
1709
1751
|
if (vis) chart.setScale('y', { min: vis[0], max: vis[1] });
|
|
@@ -1774,10 +1816,10 @@ function generateHTML(data: any, title: any = 'TradingView Style Research') {
|
|
|
1774
1816
|
chart.root.style.cursor = inYAxisZone(chart, e.clientX) ? 'ns-resize' : '';
|
|
1775
1817
|
});
|
|
1776
1818
|
}
|
|
1777
|
-
chart.
|
|
1819
|
+
chart.root.addEventListener('mousemove', () => {
|
|
1778
1820
|
if (chart.cursor.idx != null) updateLegend(chart.cursor.idx);
|
|
1779
1821
|
});
|
|
1780
|
-
chart.
|
|
1822
|
+
chart.root.addEventListener('mouseleave', refreshLegend);
|
|
1781
1823
|
chart.root.addEventListener('mouseenter', () => chart.root.classList.add('is-hovered'));
|
|
1782
1824
|
chart.root.addEventListener('mouseleave', () => chart.root.classList.remove('is-hovered'));
|
|
1783
1825
|
});
|
package/claw/package.json
CHANGED
|
@@ -30,7 +30,7 @@ async function testParserAcceptsJsonlAcrossChunksAndSingleBuffer() {
|
|
|
30
30
|
capabilities: {},
|
|
31
31
|
clientInfo: {
|
|
32
32
|
name: 'claw-mcp-transport-test',
|
|
33
|
-
version: '1.4.
|
|
33
|
+
version: '1.4.23'
|
|
34
34
|
},
|
|
35
35
|
protocolVersion: '2024-11-05'
|
|
36
36
|
}
|
|
@@ -187,7 +187,7 @@ async function testMainEntrypointHandlesRealProcessInitialize() {
|
|
|
187
187
|
capabilities: {},
|
|
188
188
|
clientInfo: {
|
|
189
189
|
name: 'claw-mcp-transport-test',
|
|
190
|
-
version: '1.4.
|
|
190
|
+
version: '1.4.23'
|
|
191
191
|
},
|
|
192
192
|
protocolVersion: '2024-11-05'
|
|
193
193
|
}
|
|
@@ -194,9 +194,9 @@ function generateChartHtml(results, metricCache, fixEr, fixFast, dataLabel, _cha
|
|
|
194
194
|
const uplotCSS = fs.readFileSync(path.join(PATHS.ANALYSIS.ASSETS_DIR, 'uPlot.min.css'), 'utf8');
|
|
195
195
|
const amaAnnotations = [
|
|
196
196
|
{ label: 'AMA1', lambda: 0.0031, slow: 62.1, color: '#ef5350' },
|
|
197
|
-
{ label: 'AMA2', lambda: 0.0025, slow:
|
|
198
|
-
{ label: 'AMA3', lambda: 0.00185, slow:
|
|
199
|
-
{ label: 'AMA4', lambda: 0.0013, slow:
|
|
197
|
+
{ label: 'AMA2', lambda: 0.0025, slow: 72.0, color: '#fb8c00' },
|
|
198
|
+
{ label: 'AMA3', lambda: 0.00185, slow: 83.6, color: '#5c9ee6' },
|
|
199
|
+
{ label: 'AMA4', lambda: 0.0013, slow: 96.9, color: '#26a69a' },
|
|
200
200
|
].filter(a => a.lambda >= xs[0] && a.lambda <= xs[xs.length - 1]);
|
|
201
201
|
return `<!DOCTYPE html>
|
|
202
202
|
<html lang="en">
|
|
@@ -44,10 +44,10 @@ const DEFAULT_SEARCH = {
|
|
|
44
44
|
// Each AMA has its own λ that controls the movement-vs-distance tradeoff.
|
|
45
45
|
// Override individually via --ama1Weight, --ama2Weight, etc. CLI flags.
|
|
46
46
|
const AMA_OBJECTIVES = [
|
|
47
|
-
{ key: 'AMA1', name: 'AMA1
|
|
48
|
-
{ key: 'AMA2', name: 'AMA2
|
|
49
|
-
{ key: 'AMA3', name: 'AMA3
|
|
50
|
-
{ key: 'AMA4', name: 'AMA4
|
|
47
|
+
{ key: 'AMA1', name: 'AMA1', distanceCapQuantile: 0.25, distanceWeight: 0.0031 },
|
|
48
|
+
{ key: 'AMA2', name: 'AMA2', distanceCapQuantile: 0.30, distanceWeight: 0.0025 },
|
|
49
|
+
{ key: 'AMA3', name: 'AMA3', distanceCapQuantile: 0.35, distanceWeight: 0.00185 },
|
|
50
|
+
{ key: 'AMA4', name: 'AMA4', distanceCapQuantile: 0.40, distanceWeight: 0.0013 },
|
|
51
51
|
];
|
|
52
52
|
function cloneObjectives() {
|
|
53
53
|
return AMA_OBJECTIVES.map((o) => ({ ...o }));
|