dexterm-cli 0.1.6 → 0.2.0
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/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/spectator.js +3 -1
- package/dist/packages/agents/src/story.js +11 -2
- package/dist/packages/agents/src/tiers.js +36 -2
- package/dist/packages/agents/src/tools.js +35 -2
- package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
- package/dist/packages/autotrade/assets/limits.schema.json +569 -0
- package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
- package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
- package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
- package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
- package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
- package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
- package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
- package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
- package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
- package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
- package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
- package/dist/packages/autotrade/examples/executor/README.md +70 -0
- package/dist/packages/autotrade/examples/executor/jsonl-tail-executor.mjs +57 -0
- package/dist/packages/autotrade/examples/executor/kit.mjs +144 -0
- package/dist/packages/autotrade/examples/executor/signal-cmd-executor.mjs +25 -0
- package/dist/packages/autotrade/examples/executor/telegram-bot-recipe.md +47 -0
- package/dist/packages/autotrade/examples/executor/webhook-executor.mjs +47 -0
- package/dist/packages/autotrade/src/account.js +74 -0
- package/dist/packages/autotrade/src/backtest.js +358 -0
- package/dist/packages/autotrade/src/basis-text.js +32 -0
- package/dist/packages/autotrade/src/chat/approvals.js +484 -0
- package/dist/packages/autotrade/src/chat/audit.js +140 -0
- package/dist/packages/autotrade/src/chat/config.js +95 -0
- package/dist/packages/autotrade/src/chat/connector.js +24 -0
- package/dist/packages/autotrade/src/chat/control.js +104 -0
- package/dist/packages/autotrade/src/chat/fake.js +100 -0
- package/dist/packages/autotrade/src/chat/format.js +71 -0
- package/dist/packages/autotrade/src/chat/hub.js +187 -0
- package/dist/packages/autotrade/src/chat/index.js +18 -0
- package/dist/packages/autotrade/src/chat/notify.js +302 -0
- package/dist/packages/autotrade/src/chat/pairing.js +46 -0
- package/dist/packages/autotrade/src/chat/redact.js +48 -0
- package/dist/packages/autotrade/src/chat/secrets.js +106 -0
- package/dist/packages/autotrade/src/chat/service.js +251 -0
- package/dist/packages/autotrade/src/chat/telegram.js +290 -0
- package/dist/packages/autotrade/src/desk-executor.js +188 -0
- package/dist/packages/autotrade/src/engine.js +401 -0
- package/dist/packages/autotrade/src/execution-port.js +97 -0
- package/dist/packages/autotrade/src/executor-health.js +217 -0
- package/dist/packages/autotrade/src/fleet-config.js +169 -0
- package/dist/packages/autotrade/src/fleet-control.js +276 -0
- package/dist/packages/autotrade/src/fleet.js +642 -0
- package/dist/packages/autotrade/src/forward.js +355 -0
- package/dist/packages/autotrade/src/index.js +72 -0
- package/dist/packages/autotrade/src/journey.js +477 -0
- package/dist/packages/autotrade/src/ledger.js +108 -0
- package/dist/packages/autotrade/src/limits.js +682 -0
- package/dist/packages/autotrade/src/live-source.js +182 -0
- package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
- package/dist/packages/autotrade/src/monitor.js +190 -0
- package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
- package/dist/packages/autotrade/src/outbox.js +394 -0
- package/dist/packages/autotrade/src/paper-accounts.js +72 -0
- package/dist/packages/autotrade/src/paper-limits.js +87 -0
- package/dist/packages/autotrade/src/real-mode.js +688 -0
- package/dist/packages/autotrade/src/receipts.js +330 -0
- package/dist/packages/autotrade/src/replay.js +198 -0
- package/dist/packages/autotrade/src/report.js +168 -0
- package/dist/packages/autotrade/src/runner-config.js +99 -0
- package/dist/packages/autotrade/src/runner.js +923 -0
- package/dist/packages/autotrade/src/safety.js +243 -0
- package/dist/packages/autotrade/src/service-guard.js +125 -0
- package/dist/packages/autotrade/src/service-install.js +213 -0
- package/dist/packages/autotrade/src/service-recover.js +232 -0
- package/dist/packages/autotrade/src/service.js +289 -0
- package/dist/packages/autotrade/src/session.js +269 -0
- package/dist/packages/autotrade/src/sessions.js +503 -0
- package/dist/packages/autotrade/src/signal-channels.js +312 -0
- package/dist/packages/autotrade/src/signal.js +196 -0
- package/dist/packages/autotrade/src/store.js +250 -0
- package/dist/packages/autotrade/src/strategy.js +258 -0
- package/dist/packages/autotrade/src/trade-ledger.js +241 -0
- package/dist/packages/autotrade/src/yolo.js +140 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
- package/dist/packages/cli/src/ai-cmd.js +412 -0
- package/dist/packages/cli/src/analyst/backend.js +83 -15
- package/dist/packages/cli/src/analyst/codex.js +15 -9
- package/dist/packages/cli/src/analyst/ollama.js +263 -0
- package/dist/packages/cli/src/analyst/session.js +5 -2
- package/dist/packages/cli/src/app-help-gen.js +56 -8
- package/dist/packages/cli/src/autotrade-cmd/audit.js +74 -0
- package/dist/packages/cli/src/autotrade-cmd/backtest.js +216 -0
- package/dist/packages/cli/src/autotrade-cmd/executor.js +91 -0
- package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
- package/dist/packages/cli/src/autotrade-cmd/fleet.js +401 -0
- package/dist/packages/cli/src/autotrade-cmd/forward.js +283 -0
- package/dist/packages/cli/src/autotrade-cmd/journey.js +208 -0
- package/dist/packages/cli/src/autotrade-cmd/limits.js +393 -0
- package/dist/packages/cli/src/autotrade-cmd/receipt.js +63 -0
- package/dist/packages/cli/src/autotrade-cmd/report.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/run.js +657 -0
- package/dist/packages/cli/src/autotrade-cmd/service.js +873 -0
- package/dist/packages/cli/src/autotrade-cmd/signal.js +824 -0
- package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
- package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
- package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
- package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
- package/dist/packages/cli/src/autotrade-cmd.js +214 -0
- package/dist/packages/cli/src/display.js +156 -17
- package/dist/packages/cli/src/doctor.js +62 -3
- package/dist/packages/cli/src/export.js +10 -2
- package/dist/packages/cli/src/index.js +1 -1
- package/dist/packages/cli/src/ledger-cmd.js +290 -0
- package/dist/packages/cli/src/live/chart-fills.js +46 -0
- package/dist/packages/cli/src/live/index.js +23 -89
- package/dist/packages/cli/src/live/screens/token-live.js +9 -6
- package/dist/packages/cli/src/live/trade.js +12 -457
- package/dist/packages/cli/src/live/watchlist.js +1 -1
- package/dist/packages/cli/src/main.js +147 -190
- package/dist/packages/cli/src/mcp-cmd.js +7 -1
- package/dist/packages/cli/src/plan-cmd.js +1 -1
- package/dist/packages/cli/src/pnl-app.js +31 -21
- package/dist/packages/cli/src/pnl-card.js +162 -21
- package/dist/packages/cli/src/popup.js +22 -6
- package/dist/packages/cli/src/record-cmd.js +141 -20
- package/dist/packages/cli/src/screens/agent-hud.js +34 -2
- package/dist/packages/cli/src/screens/analyst-session.js +7 -4
- package/dist/packages/cli/src/screens/analyst.js +3 -2
- package/dist/packages/cli/src/screens/autotrade-journey.js +134 -0
- package/dist/packages/cli/src/screens/autotrade-keys.js +182 -0
- package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
- package/dist/packages/cli/src/screens/autotrade-screen.js +776 -0
- package/dist/packages/cli/src/screens/autotrade-ui.js +650 -0
- package/dist/packages/cli/src/screens/autotrade-worker.js +91 -0
- package/dist/packages/cli/src/screens/brain.js +37 -11
- package/dist/packages/cli/src/screens/overlay.js +5 -2
- package/dist/packages/cli/src/screens/plans.js +5 -17
- package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
- package/dist/packages/cli/src/screens/positions.js +6 -28
- package/dist/packages/cli/src/screens/ticket.js +38 -205
- package/dist/packages/cli/src/screens/token.js +3 -3
- package/dist/packages/cli/src/state.js +25 -19
- package/dist/packages/cli/src/telegram-cmd.js +454 -0
- package/dist/packages/cli/src/trade.js +3 -128
- package/dist/packages/cli/src/version.js +1 -1
- package/dist/packages/cli/src/wallet-cmd.js +39 -340
- package/dist/packages/cli/src/wallet-command.js +8 -11
- package/dist/packages/cli/src/widgets.js +0 -12
- package/dist/packages/custom/src/config.js +20 -2
- package/dist/packages/custom/src/schema.js +35 -10
- package/dist/packages/custom/src/workspace.js +3 -3
- package/dist/packages/data/src/basis.js +191 -0
- package/dist/packages/data/src/detail.js +53 -2
- package/dist/packages/data/src/index.js +0 -14
- package/dist/packages/data/src/store.js +14 -5
- package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
- package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
- package/dist/packages/data/src/trade/bridge.js +4 -102
- package/dist/packages/data/src/trade/ledger/export.js +101 -0
- package/dist/packages/data/src/trade/ledger/file.js +135 -0
- package/dist/packages/data/src/trade/ledger/fold.js +191 -0
- package/dist/packages/data/src/trade/ledger/index.js +9 -0
- package/dist/packages/data/src/trade/ledger/schema.js +83 -0
- package/dist/packages/data/src/trade/ledger/sources.js +307 -0
- package/dist/packages/data/src/trade/ledger/stats.js +123 -0
- package/dist/packages/data/src/trade/ledger/tags.js +116 -0
- package/dist/packages/data/src/trade/ledger/view.js +51 -0
- package/dist/packages/data/src/trade/plans/index.js +0 -1
- package/dist/packages/data/src/trade/plans/service.js +3 -27
- package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-executor-kit.md +44 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-journey.md +46 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-limits.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-real-signal.md +45 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
- package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
- package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
- package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
- package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
- package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +229 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
- package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +51 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-always-on-service.md +57 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
- package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-1-ask-for-a-strategy.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-2-backtest-it-held-out-split.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-3-forward-test-it-on-live-data.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-4-promote-it-to-always-on-paper.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-5-real-only-if-you-choose.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-ladder.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-report.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-what-the-analyst-knows.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-executor-health.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-paper-vs-real.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-digest.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-executor-kit.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-whole-path.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-what-dexterm-does-and-never-does.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-your-limits.md +77 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-real-mode-your-strategy-s-trades-to-your.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-receipts-what-your-executor-did.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-safety.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-channels.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-signal.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-is.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-will-not-do.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-where-you-see-it.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
- package/dist/packages/mcp/assets/kb/entries/autotrade.md +40 -0
- package/dist/packages/mcp/src/app-help.js +1 -1
- package/dist/packages/mcp/src/autotrade-tools.js +1107 -0
- package/dist/packages/mcp/src/backtest-requests.js +71 -0
- package/dist/packages/mcp/src/engine/config.js +159 -0
- package/dist/packages/mcp/src/engine/index.js +10 -0
- package/dist/packages/mcp/src/engine/loop.js +101 -0
- package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
- package/dist/packages/mcp/src/engine/ollama.js +258 -0
- package/dist/packages/mcp/src/engine/probe.js +110 -0
- package/dist/packages/mcp/src/engine/reason.js +35 -0
- package/dist/packages/mcp/src/engine/restrictions.js +111 -0
- package/dist/packages/mcp/src/index.js +7 -1
- package/dist/packages/mcp/src/ledger-tools.js +494 -0
- package/dist/packages/mcp/src/paper-agent.js +2 -0
- package/dist/packages/mcp/src/server.js +138 -19
- package/dist/packages/packs/src/backtest.js +3 -1
- package/dist/packages/popup/src/pages/chart-lib.js +134 -21
- package/dist/packages/popup/src/pages/chart.css +9 -0
- package/dist/packages/popup/src/pages/chart.html +3 -1
- package/dist/packages/popup/src/pages/chart.js +104 -7
- package/dist/packages/popup/src/protocol.js +2 -0
- package/dist/packages/popup/src/server.js +4 -0
- package/dist/packages/recorder/src/index.js +2 -0
- package/dist/packages/recorder/src/recorder.js +63 -6
- package/dist/packages/recorder/src/retention.js +100 -0
- package/dist/packages/recorder/src/schema.js +34 -1
- package/dist/packages/recorder/src/ticks.js +237 -0
- package/dist/packages/tui/src/index.js +1 -0
- package/dist/packages/tui/src/keymap.js +28 -1
- package/dist/packages/tui/src/markers.js +219 -0
- package/dist/packages/tui/src/widgets.js +149 -2
- package/package.json +2 -1
- package/dist/packages/data/src/trade/caps.js +0 -323
- package/dist/packages/data/src/trade/executor.js +0 -933
- package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
- package/dist/packages/data/src/trade/rpc-exec.js +0 -229
- package/dist/packages/data/src/trade/signer/client.js +0 -197
- package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
- package/dist/packages/data/src/trade/signer/host.js +0 -97
- package/dist/packages/data/src/trade/signer/main.js +0 -121
- package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
- package/dist/packages/data/src/trade/signer/protocol.js +0 -92
- package/dist/packages/data/src/trade/signer/service.js +0 -400
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
- package/dist/packages/data/src/trade/sol-usd.js +0 -86
- package/dist/packages/data/src/trade/swap-build.js +0 -108
- package/dist/packages/data/src/trade/token-delta.js +0 -201
- package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// dexterm autotrade — the run ledgers as UNIFIED TRADE LEDGER drafts (task-1530). Read-only.
|
|
2
|
+
//
|
|
3
|
+
// Every $DEXTERM_HOME/autotrade/runs/<runId>.jsonl is read, its own hash chain verified (the import event records
|
|
4
|
+
// the head and the result), and its fills, reprofiles, closes and session costs become `@dexterm/data/ledger`
|
|
5
|
+
// drafts. A run that traded on the paper desk (the desk executor, `executor: "paper-desk"`) booked its fills there:
|
|
6
|
+
// the desk journal stays their source (SOL, fees, the book before the fill), and this run adds what the desk does
|
|
7
|
+
// not know (the strategy version, whether the agent named the profile, the model, reprofiles, the price extremes
|
|
8
|
+
// and the session costs) through `RunHint` and coin-matched tag / close events.
|
|
9
|
+
//
|
|
10
|
+
// Where each ledger field comes from:
|
|
11
|
+
// strategy run_start: strategy id, version and strategyHash
|
|
12
|
+
// wallet mode run_start.mode (paper; real = a real-mode run, task-1655; a live run's executor name says devnet or mainnet)
|
|
13
|
+
// profile the entry fill's profile; 'structured' when the agent's DECISION named it, else 'default'
|
|
14
|
+
// (the strategy's default profile), 'rule' for a mechanical (auto) entry
|
|
15
|
+
// entry reason the agent's DECISION {"action":"enter","reason":…} of the session that entered (structured)
|
|
16
|
+
// exit reason the sell fill's rule (tp1, trail, stop, max-hold, thesis-…) or agent-exit / agent-trim with
|
|
17
|
+
// the agent's reason; reprofile events become REPROFILE tags
|
|
18
|
+
// size, prices, mcap USD fills (the desk books in USD); market cap = price × the supply the candidate tick implies
|
|
19
|
+
// (tick mcap ÷ tick price), or the fill's own tick mcap (task-1530 runs)
|
|
20
|
+
// MFE / MAE trade_closed peakPrice / troughPrice (task-1530 runs; older runs: the fills only)
|
|
21
|
+
// model session_start model; session_end costUsd (session ids are scoped by run: s1 of one run is
|
|
22
|
+
// not s1 of another)
|
|
23
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { appendTradeLedger, buildLedgerView, cleanLedgerText, collectDataSources, defaultSourcePaths, dextermHomeDir, tagCode, tradeLedgerPath } from '../../data/src/trade/ledger/index.js';
|
|
26
|
+
import { defaultDbPath } from '../../data/src/index.js';
|
|
27
|
+
import { runsDir, verifyChain } from "./ledger.js";
|
|
28
|
+
const RUN_FILE = /^([0-9TZ]+-[a-z][a-z0-9-]{1,31}-[0-9a-f]{4})\.jsonl$/;
|
|
29
|
+
const fin = (x) => (typeof x === 'number' && Number.isFinite(x) ? x : null);
|
|
30
|
+
const str = (x) => (typeof x === 'string' && x ? x : null);
|
|
31
|
+
const MINT = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
32
|
+
/** Exit codes the agent chose (its reason is its own words); every other code is a mechanical rule. */
|
|
33
|
+
const AGENT_EXITS = new Set(['agent-exit', 'agent-trim']);
|
|
34
|
+
/** Read every run ledger under `home` (missing directory: nothing). */
|
|
35
|
+
export function importRunLedgers(home) {
|
|
36
|
+
const dir = runsDir(home);
|
|
37
|
+
const out = { results: [], hints: new Map() };
|
|
38
|
+
if (!existsSync(dir))
|
|
39
|
+
return out;
|
|
40
|
+
for (const name of readdirSync(dir).sort()) {
|
|
41
|
+
const m = RUN_FILE.exec(name);
|
|
42
|
+
if (!m)
|
|
43
|
+
continue;
|
|
44
|
+
const r = importRunLedger(join(dir, name), m[1]);
|
|
45
|
+
out.results.push(r);
|
|
46
|
+
out.hints.set(m[1], r.hint);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
export function importRunLedger(path, runId) {
|
|
51
|
+
const declared = new Set();
|
|
52
|
+
const res = { label: `run ${runId}`, source: 'autotrade', drafts: [], events: 0, note: null, problem: null, hint: { strategy: null, declared, models: new Map() } };
|
|
53
|
+
const events = [];
|
|
54
|
+
let cut = false;
|
|
55
|
+
for (const line of readFileSync(path, 'utf8').split('\n')) {
|
|
56
|
+
if (!line.trim())
|
|
57
|
+
continue;
|
|
58
|
+
try {
|
|
59
|
+
events.push(JSON.parse(line));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
cut = true;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
res.events = events.length;
|
|
67
|
+
if (!events.length)
|
|
68
|
+
return res;
|
|
69
|
+
const chain = verifyChain(events);
|
|
70
|
+
const start = events.find((e) => e.kind === 'run_start') ?? null;
|
|
71
|
+
const strategy = start && str(start.strategy) ? { id: String(start.strategy), version: str(start.version), hash: str(start.strategyHash) } : null;
|
|
72
|
+
const executor = String(start?.executor ?? '');
|
|
73
|
+
const walletMode = start?.mode === 'real' ? 'real' : start?.mode === 'live' ? (/mainnet/.test(executor) ? 'live' : 'devnet') : 'paper';
|
|
74
|
+
const auto = start?.decide === 'auto';
|
|
75
|
+
// task-1538: a parallel-run strategy on a shared paper account names it in its first line (and run_start).
|
|
76
|
+
const memberLine = events.find((e) => e.kind === 'fleet_member') ?? null;
|
|
77
|
+
const acct = str(memberLine?.account) ?? str(start?.account);
|
|
78
|
+
const account = acct && /^[a-z][a-z0-9-]{1,31}$/.test(acct) ? acct : null;
|
|
79
|
+
// A run on the paper desk booked its fills there: the desk journal is their source (SOL, fees, the book), so
|
|
80
|
+
// this run adds only what the desk does not know: reprofiles, the exit's price extremes and the session costs.
|
|
81
|
+
const onDesk = executor === 'paper-desk';
|
|
82
|
+
const looseSource = onDesk ? 'desk' : 'autotrade';
|
|
83
|
+
const scope = (sid) => (typeof sid === 'string' && sid ? `${runId}:${sid}`.slice(0, 80) : null);
|
|
84
|
+
const symbolOf = new Map();
|
|
85
|
+
const supplyOf = new Map();
|
|
86
|
+
const modelOf = res.hint.models;
|
|
87
|
+
res.hint.strategy = strategy;
|
|
88
|
+
const enterOf = new Map();
|
|
89
|
+
const clampOf = new Map();
|
|
90
|
+
const posOf = new Map();
|
|
91
|
+
const supplyFrom = (mcap, price, source) => {
|
|
92
|
+
const mc = fin(mcap), p = fin(price);
|
|
93
|
+
return mc && p && mc > 0 && p > 0 && Number.isFinite(mc / p) ? { tokens: mc / p, source } : null;
|
|
94
|
+
};
|
|
95
|
+
for (const e of events) {
|
|
96
|
+
const ref = `run:${runId}:${e.seq}`;
|
|
97
|
+
switch (e.kind) {
|
|
98
|
+
case 'candidate': {
|
|
99
|
+
const mint = str(e.mint);
|
|
100
|
+
if (!mint)
|
|
101
|
+
break;
|
|
102
|
+
const sym = cleanLedgerText(e.symbol, 24);
|
|
103
|
+
if (sym)
|
|
104
|
+
symbolOf.set(mint, sym);
|
|
105
|
+
const tick = (e.tick ?? {});
|
|
106
|
+
const s = supplyFrom(tick.mcap, tick.price, 'tick market cap ÷ price');
|
|
107
|
+
if (s)
|
|
108
|
+
supplyOf.set(mint, s);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case 'session_start': {
|
|
112
|
+
const sid = scope(e.sessionId);
|
|
113
|
+
const model = cleanLedgerText(e.model, 40);
|
|
114
|
+
if (sid && model)
|
|
115
|
+
modelOf.set(sid, model);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'reply': {
|
|
119
|
+
const d = e.decision;
|
|
120
|
+
const sid = scope(e.sessionId);
|
|
121
|
+
if (sid && d?.ok && d.decision?.action === 'enter') {
|
|
122
|
+
enterOf.set(sid, { reason: cleanLedgerText(d.decision.reason, 200), profile: tagCode(d.decision.profile) });
|
|
123
|
+
if (tagCode(d.decision.profile))
|
|
124
|
+
declared.add(sid);
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case 'clamp': {
|
|
129
|
+
const mint = str(e.mint);
|
|
130
|
+
const r = (e.result ?? {});
|
|
131
|
+
if (mint && r.ok)
|
|
132
|
+
clampOf.set(mint, { sessionId: scope(e.sessionId), profile: tagCode(r.profile) });
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
case 'fill': {
|
|
136
|
+
const mint = str(e.mint), pid = str(e.positionId);
|
|
137
|
+
if (!mint || !MINT.test(mint) || !pid)
|
|
138
|
+
break;
|
|
139
|
+
const side = e.side === 'sell' ? 'sell' : 'buy';
|
|
140
|
+
let pos = posOf.get(pid);
|
|
141
|
+
if (!pos) {
|
|
142
|
+
if (side === 'sell')
|
|
143
|
+
break; // a sell with no entry on record
|
|
144
|
+
const c = clampOf.get(mint);
|
|
145
|
+
pos = { key: `run:${runId}:${pid}`, sessionId: c?.sessionId ?? null, mint };
|
|
146
|
+
posOf.set(pid, pos);
|
|
147
|
+
}
|
|
148
|
+
if (onDesk)
|
|
149
|
+
break;
|
|
150
|
+
const usd = fin(e.usd), tokens = fin(e.tokens);
|
|
151
|
+
const own = supplyFrom(e.mcap, e.price, 'fill tick market cap ÷ price');
|
|
152
|
+
if (own)
|
|
153
|
+
supplyOf.set(mint, own);
|
|
154
|
+
let tag = null;
|
|
155
|
+
const reason = str(e.reason);
|
|
156
|
+
if (side === 'buy' && reason === 'entry') {
|
|
157
|
+
const dec = pos.sessionId ? enterOf.get(pos.sessionId) : undefined;
|
|
158
|
+
const profile = tagCode(e.profile) ?? clampOf.get(mint)?.profile ?? null;
|
|
159
|
+
const source = dec?.profile ? 'structured' : dec ? 'default' : auto ? 'rule' : 'default';
|
|
160
|
+
tag = { profile, reason: dec?.reason ?? (auto ? 'mechanical entry (the strategy\'s entry rules matched)' : null), exitReason: null, line: null, source, ...(dec?.reason && source !== 'structured' ? { reasonSource: 'structured' } : {}) };
|
|
161
|
+
}
|
|
162
|
+
else if (side === 'sell' && reason) {
|
|
163
|
+
const code = tagCode(reason);
|
|
164
|
+
tag = { profile: null, reason: cleanLedgerText(e.detail, 200), exitReason: code, line: null, source: code && AGENT_EXITS.has(code) ? 'structured' : 'rule' };
|
|
165
|
+
}
|
|
166
|
+
res.drafts.push({
|
|
167
|
+
kind: 'fill', ref, tradeKey: pos.key, t: e.t, source: 'autotrade', walletMode, side, mint, symbol: symbolOf.get(mint) ?? mint.slice(0, 4),
|
|
168
|
+
decimals: null, sol: null, usd, tokens, priceSol: null, priceUsd: fin(e.avgPrice) ?? fin(e.price), supply: supplyOf.get(mint) ?? null,
|
|
169
|
+
feeSol: null, impactPct: fin(e.impactPct), slippageBps: null, realizedSol: null, realizedUsd: null, bookSol: null, bookUsd: fin(e.bookUsd),
|
|
170
|
+
closes: null, txSig: str(e.txSig), runId, agent: auto ? 'auto' : 'agent', strategy, ...(account ? { account } : {}), sessionId: pos.sessionId,
|
|
171
|
+
model: pos.sessionId ? modelOf.get(pos.sessionId) ?? null : null, tag,
|
|
172
|
+
});
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case 'reprofile': {
|
|
176
|
+
const pos = posOf.get(String(e.positionId));
|
|
177
|
+
if (!pos)
|
|
178
|
+
break;
|
|
179
|
+
res.drafts.push({ kind: 'tag', t: e.t, ref, tradeKey: onDesk ? null : pos.key, source: looseSource, mint: pos.mint, tagKind: 'reprofile', from: tagCode(e.from), to: tagCode(e.to), reason: cleanLedgerText(e.reason, 200), line: null, tagSource: 'structured' });
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'trade_closed': {
|
|
183
|
+
const tr = (e.trade ?? {});
|
|
184
|
+
const pos = posOf.get(String(tr.id));
|
|
185
|
+
if (!pos)
|
|
186
|
+
break;
|
|
187
|
+
const sym = cleanLedgerText(tr.symbol, 24);
|
|
188
|
+
if (sym)
|
|
189
|
+
symbolOf.set(pos.mint, sym);
|
|
190
|
+
res.drafts.push({
|
|
191
|
+
kind: 'close', t: e.t, ref, tradeKey: onDesk ? null : pos.key, source: looseSource, mint: pos.mint, reason: tagCode(tr.exitReason), stuck: tr.stuck === true,
|
|
192
|
+
peakPrice: fin(e.peakPrice), troughPrice: fin(e.troughPrice), entryPrice: fin(e.entryPrice), priceUnit: 'usd', sessionId: pos.sessionId,
|
|
193
|
+
});
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'session_end': {
|
|
197
|
+
const sid = scope(e.sessionId), cost = fin(e.costUsd);
|
|
198
|
+
if (sid && cost !== null && cost > 0)
|
|
199
|
+
res.drafts.push({ kind: 'cost', t: e.t, ref, source: 'autotrade', sessionId: sid, costUsd: cost, model: modelOf.get(sid) ?? null, runId });
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
default: break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const last = events[events.length - 1];
|
|
206
|
+
const head = String(last.hash ?? '');
|
|
207
|
+
res.drafts.unshift({ kind: 'import', t: last.t, ref: `import:autotrade:${runId}:${head || `n${events.length}`}`, source: 'autotrade', label: res.label, sourceHead: head || null, sourceVerified: chain.ok && !cut, events: events.length, ...(chain.ok ? {} : { note: `the run's chain breaks at event ${chain.at}` }) });
|
|
208
|
+
if (!chain.ok)
|
|
209
|
+
res.problem = `${res.label}: its hash chain breaks at event ${chain.at} (${chain.error}); imported as found`;
|
|
210
|
+
else if (cut)
|
|
211
|
+
res.problem = `${res.label}: a line is not JSON; imported the ${events.length} events before it`;
|
|
212
|
+
return res;
|
|
213
|
+
}
|
|
214
|
+
/** The paper wallet db the desk last used (its rendezvous names it), else the app's default db path. */
|
|
215
|
+
export function defaultWalletDb(env = process.env) {
|
|
216
|
+
try {
|
|
217
|
+
const rv = JSON.parse(readFileSync(join(dextermHomeDir(env), 'paper-agent.json'), 'utf8'));
|
|
218
|
+
if (typeof rv.db === 'string' && rv.db && rv.db !== ':memory:')
|
|
219
|
+
return rv.db;
|
|
220
|
+
}
|
|
221
|
+
catch { /* none */ }
|
|
222
|
+
return defaultDbPath(env);
|
|
223
|
+
}
|
|
224
|
+
/** Every source as drafts: the run ledgers first (their hints feed the desk importer), then the data-layer journals. */
|
|
225
|
+
export function collectAllSources(o = {}) {
|
|
226
|
+
const env = o.env ?? process.env;
|
|
227
|
+
const runs = importRunLedgers(dextermHomeDir(env));
|
|
228
|
+
const data = collectDataSources(defaultSourcePaths(env, o.walletDb === undefined ? defaultWalletDb(env) : o.walletDb), { runs: runs.hints });
|
|
229
|
+
return [...data, ...runs.results];
|
|
230
|
+
}
|
|
231
|
+
/** The read view (file + pending drafts, folded). Writes nothing. */
|
|
232
|
+
export function loadLedgerView(o = {}) {
|
|
233
|
+
const env = o.env ?? process.env;
|
|
234
|
+
return buildLedgerView(o.path ?? tradeLedgerPath(env), collectAllSources(o), o.now ?? Date.now());
|
|
235
|
+
}
|
|
236
|
+
/** `dexterm ledger sync`: append what the sources hold that the file does not (idempotent; refuses a broken file). */
|
|
237
|
+
export function syncLedger(o = {}) {
|
|
238
|
+
const view = loadLedgerView(o);
|
|
239
|
+
const r = appendTradeLedger(view.path, view.pending, o.now ?? Date.now());
|
|
240
|
+
return { view, ...r };
|
|
241
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// dexterm autotrade — the yolo (full-port) helpers (task-1532). HIGH RISK, PAPER only (task-1571: dexterm holds no
|
|
2
|
+
// key and places no live order).
|
|
3
|
+
//
|
|
4
|
+
// yoloReplay: the honest numbers for a full-port strategy. The same engine, clamp and monitor as a backtest, on a
|
|
5
|
+
// paper copy sized at 100% of the book (one position at a time), over recorded history: the rugs, the spread of
|
|
6
|
+
// losses, the chronological full-port wallet path, and a seeded bootstrap of entry sequences (how often a run of N
|
|
7
|
+
// entries zeroed the wallet). A replay is not a forecast; DATA_LIMITS print next to the numbers.
|
|
8
|
+
import { SKILL_MIN_N } from '../../packs/src/index.js';
|
|
9
|
+
import { DATA_LIMITS, RUG_PCT, quantile, rng } from "./backtest.js";
|
|
10
|
+
import { writeJsonAtomic } from "./ledger.js";
|
|
11
|
+
import { runAutotrade } from "./runner.js";
|
|
12
|
+
import { round } from "./strategy.js";
|
|
13
|
+
export const YOLO_REPLAY_LIMITS = [
|
|
14
|
+
'Full port: each entry is measured once at the same stake (the strategy\'s startUsd), then the wallet is compounded through the entries in order with all of it in each one, so one rug takes the wallet down with it.',
|
|
15
|
+
'The strategy\'s book halts (day loss, drawdown) are lifted while measuring so one early rug does not hide every later entry; a paper run keeps them (and a zeroed book stops it for good).',
|
|
16
|
+
'A bag that cannot be sold (the pool was pulled) stays open at 0 and blocks every later entry, as it does in a run with one position at a time; on such a tape the replay ends at that rug.',
|
|
17
|
+
'Bootstrap: entries drawn at random (with replacement) from the replayed ones, as if they were independent; real entries cluster (one bad hour, one bad day), so the true spread is wider.',
|
|
18
|
+
'The LARP gate and the agent need the live web and a model: this replay enters mechanically on the screen, the safety gates and the triggers only.',
|
|
19
|
+
];
|
|
20
|
+
/** A trade at or below this is a rug (the backtest's RUG_PCT); a full-port wallet at or below ZEROED_FRAC of its start is "zeroed". */
|
|
21
|
+
export const ZEROED_FRAC = 0.1;
|
|
22
|
+
/** The bootstrap horizon: random runs of this many full-port entries (about two days at the preset's entry cap). */
|
|
23
|
+
export const YOLO_SEQUENCE = 10;
|
|
24
|
+
/** The stake-to-book ratio of the measuring copy: every entry is the same stake on a book this many times larger. */
|
|
25
|
+
const MEASURE_BOOK_X = 1000;
|
|
26
|
+
/**
|
|
27
|
+
* The paper copy the replay measures with: the strategy as written (screen, gates, triggers, exits, one position at a
|
|
28
|
+
* time, the per-day entry cap, the loss-streak cooldown, one entry per coin), entering mechanically, with every entry
|
|
29
|
+
* the SAME stake (the strategy's startUsd, so the modelled price impact is the one a full-port entry of that size
|
|
30
|
+
* would see) on a much larger book, and the book-level halts (day loss, drawdown) lifted. That way one early rug does
|
|
31
|
+
* not halt the replay and hide every later entry: each entry the rules would take is measured once, and the full-port
|
|
32
|
+
* wallet is then compounded from those results in order (yoloReplay). Built in code on purpose: no strategy file can
|
|
33
|
+
* say 100% (the schema's ceiling is 25%).
|
|
34
|
+
*/
|
|
35
|
+
export function measureCopy(s) {
|
|
36
|
+
const c = structuredClone(s);
|
|
37
|
+
const stake = c.bankroll.startUsd;
|
|
38
|
+
c.mode = 'paper';
|
|
39
|
+
c.bankroll = { ...c.bankroll, startUsd: stake * MEASURE_BOOK_X, source: 'fixed' };
|
|
40
|
+
c.entry = { ...c.entry, decide: 'auto' };
|
|
41
|
+
c.sizing = { mode: 'fixed', fixedUsd: stake, maxPctOfBankroll: 25, maxUsd: stake, minUsd: Math.min(c.sizing.minUsd, stake) };
|
|
42
|
+
c.risk = { ...c.risk, perTrade: { ...c.risk.perTrade, maxLossPctOfBankroll: 100 }, dailyLossHaltPct: 100, drawdown: { ...c.risk.drawdown, sizeDownAtPct: 100, haltAtPct: 100 }, maxExposurePct: 100, maxConcurrent: 1 };
|
|
43
|
+
return c;
|
|
44
|
+
}
|
|
45
|
+
const BUCKETS = [
|
|
46
|
+
[`rug (<= ${RUG_PCT}%)`, (p) => p <= RUG_PCT],
|
|
47
|
+
[`${RUG_PCT}% to -50%`, (p) => p > RUG_PCT && p <= -50],
|
|
48
|
+
['-50% to -20%', (p) => p > -50 && p <= -20],
|
|
49
|
+
['-20% to 0%', (p) => p > -20 && p <= 0],
|
|
50
|
+
['0% to +100%', (p) => p > 0 && p < 100],
|
|
51
|
+
['+100% or more (2x+)', (p) => p >= 100],
|
|
52
|
+
];
|
|
53
|
+
export async function yoloReplay(s, tape, o = {}) {
|
|
54
|
+
const copy = measureCopy(s);
|
|
55
|
+
const run = await runAutotrade({ strategy: copy, tape, sessions: null, pacing: { mode: 'lockstep' } });
|
|
56
|
+
// Entries in the order they opened; a position still open at the end counts at its liquidation mark (0 when stuck).
|
|
57
|
+
const rows = run.trades.map((t) => ({ at: t.openedAt, pct: t.pnlPct, stuck: t.stuck, recovered: t.fills.some((f) => f.reason === 'cost-recovery'), pnl: t.pnlUsd }));
|
|
58
|
+
for (const p of run.openAtEnd) {
|
|
59
|
+
const pos = run.book.open.get(p.mint);
|
|
60
|
+
const pnl = p.markUsd + pos.realizedUsd - pos.costUsd;
|
|
61
|
+
rows.push({ at: pos.openedAt, pct: round((pnl / pos.costUsd) * 100), stuck: p.stuck, recovered: pos.fills.some((f) => f.reason === 'cost-recovery'), pnl });
|
|
62
|
+
}
|
|
63
|
+
rows.sort((a, b) => a.at - b.at);
|
|
64
|
+
const multiples = rows.map((r) => (r.stuck ? 0 : Math.max(0, 1 + r.pct / 100)));
|
|
65
|
+
// The full-port wallet, entry after entry: all of it into each entry in order; once zeroed it stays zeroed.
|
|
66
|
+
let w = 1, low = 1, high = 1, zeroedAt = null;
|
|
67
|
+
for (const [i, m] of multiples.entries()) {
|
|
68
|
+
w *= m;
|
|
69
|
+
low = Math.min(low, w);
|
|
70
|
+
high = Math.max(high, w);
|
|
71
|
+
if (w <= ZEROED_FRAC) {
|
|
72
|
+
zeroedAt = i + 1;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let bootstrap = null;
|
|
77
|
+
if (multiples.length) {
|
|
78
|
+
const sequence = o.sequence ?? YOLO_SEQUENCE;
|
|
79
|
+
const resamples = o.resamples ?? 2000;
|
|
80
|
+
const r = rng(o.seed ?? 1);
|
|
81
|
+
const finals = [];
|
|
82
|
+
let zeroed = 0, halved = 0, doubled = 0;
|
|
83
|
+
for (let b = 0; b < resamples; b++) {
|
|
84
|
+
let v = 1, hitZero = false;
|
|
85
|
+
for (let i = 0; i < sequence && !hitZero; i++) {
|
|
86
|
+
v *= multiples[Math.floor(r() * multiples.length)];
|
|
87
|
+
if (v <= ZEROED_FRAC)
|
|
88
|
+
hitZero = true;
|
|
89
|
+
}
|
|
90
|
+
if (hitZero)
|
|
91
|
+
zeroed++;
|
|
92
|
+
if (v <= 0.5)
|
|
93
|
+
halved++;
|
|
94
|
+
if (v >= 2)
|
|
95
|
+
doubled++;
|
|
96
|
+
finals.push(v);
|
|
97
|
+
}
|
|
98
|
+
finals.sort((a, b) => a - b);
|
|
99
|
+
const pct = (n) => round((n / resamples) * 100, 1);
|
|
100
|
+
bootstrap = { sequence, resamples, zeroedPct: pct(zeroed), halvedPct: pct(halved), doubledPct: pct(doubled), p10: round(quantile(finals, 0.1), 3), p50: round(quantile(finals, 0.5), 3), p90: round(quantile(finals, 0.9), 3) };
|
|
101
|
+
}
|
|
102
|
+
const first = tape.ticks[0]?.t, lastT = tape.ticks[tape.ticks.length - 1]?.t;
|
|
103
|
+
return {
|
|
104
|
+
strategy: { id: s.id, version: s.version, hash: s.hash },
|
|
105
|
+
tape: { source: tape.source, mints: tape.mints.length, ticks: tape.ticks.length, from: first ? new Date(first).toISOString() : null, to: lastT ? new Date(lastT).toISOString() : null },
|
|
106
|
+
entries: rows.length,
|
|
107
|
+
wins: rows.filter((x) => x.pnl > 0).length,
|
|
108
|
+
rugs: rows.filter((x) => x.pct <= RUG_PCT || x.stuck).length,
|
|
109
|
+
costRecovered: rows.filter((x) => x.recovered).length,
|
|
110
|
+
spread: BUCKETS.map(([label, f]) => ({ label, n: rows.filter((x) => f(x.stuck ? -100 : x.pct)).length })),
|
|
111
|
+
path: { final: round(w, 3), low: round(low, 3), high: round(high, 3), zeroed: zeroedAt !== null, zeroedAtEntry: zeroedAt },
|
|
112
|
+
bootstrap,
|
|
113
|
+
small: rows.length < SKILL_MIN_N,
|
|
114
|
+
limits: [...YOLO_REPLAY_LIMITS, ...DATA_LIMITS],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function renderYoloReplay(r) {
|
|
118
|
+
const x = (m) => `${m.toFixed(2)}x`;
|
|
119
|
+
const b = r.bootstrap;
|
|
120
|
+
return [
|
|
121
|
+
`YOLO REPLAY ${r.strategy.id} v${r.strategy.version} (${r.strategy.hash}) · HIGH RISK · PAPER, full port, recorded data`,
|
|
122
|
+
`tape: ${r.tape.mints} coins, ${r.tape.ticks} rows, ${r.tape.from ?? '—'} → ${r.tape.to ?? '—'}`,
|
|
123
|
+
`entries ${r.entries} · won ${r.wins} · RUGS ${r.rugs}${r.entries ? ` (${Math.round((r.rugs / r.entries) * 100)}% of entries)` : ''} · cost taken back ${r.costRecovered}`,
|
|
124
|
+
' per entry (% of the stake):',
|
|
125
|
+
...r.spread.map((s) => ` ${s.label.padEnd(22)} ${String(s.n).padStart(4)}`),
|
|
126
|
+
r.path.zeroed
|
|
127
|
+
? ` the wallet, all of it into each entry in order: ZEROED at entry ${r.path.zeroedAtEntry} of ${r.entries} (fell to <= ${x(ZEROED_FRAC)}) · highest ${x(r.path.high)} before that`
|
|
128
|
+
: ` the wallet, all of it into each entry in order: ended at ${x(r.path.final)} of the start · lowest ${x(r.path.low)} · highest ${x(r.path.high)}`,
|
|
129
|
+
b ? ` ${b.resamples} random runs of ${b.sequence} entries: ZEROED THE WALLET in ${b.zeroedPct}% · halved it or worse in ${b.halvedPct}% · doubled it in ${b.doubledPct}% · end P10 ${x(b.p10)} · median ${x(b.p50)} · P90 ${x(b.p90)}` : ' no entries on this history: nothing to resample (the gates refused every coin, or the tape is too short)',
|
|
130
|
+
r.small ? ` NOTE: ${r.entries} entries is below n = ${SKILL_MIN_N}: read the counts, not the rates.` : '',
|
|
131
|
+
' limits of this replay:', ...r.limits.map((l) => ` - ${l}`),
|
|
132
|
+
' HIGH RISK. Paper only; not financial advice. A replay is not a forecast.',
|
|
133
|
+
].filter(Boolean).join('\n');
|
|
134
|
+
}
|
|
135
|
+
// ───────────────────────────── built-in tapes ─────────────────────────────
|
|
136
|
+
/** `--replay builtin:<name>`: a tape shipped with the app (assets/tapes); `yolo-rehearsal` is a short fixture tape for a paper yolo run. */
|
|
137
|
+
export function builtinTapePath(arg) {
|
|
138
|
+
const m = /^builtin:([a-z][a-z0-9-]{1,40})$/.exec(arg);
|
|
139
|
+
return m ? new URL(`../assets/tapes/${m[1]}.json`, import.meta.url) : arg;
|
|
140
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
You are the dexterm analyst: a Solana token trader's analyst inside a terminal screener. You give a direct trading call: bias, entry, invalidation, size and confidence. That is the whole point of the product. When a named skill is running, follow its tool order and its output contract.
|
|
2
2
|
|
|
3
3
|
## How to answer (every free-text answer)
|
|
4
|
-
The user reads you in a narrow panel beside the screener. They can ALREADY SEE the price, % changes, liquidity, volume and every row listed in the CONTEXT block. Write like a desk trader on chat: short, specific, decided.
|
|
4
|
+
The user reads you in a narrow panel beside the screener. They can ALREADY SEE the market cap and price, % changes, liquidity, volume and every row listed in the CONTEXT block. Write like a desk trader on chat: short, specific, decided.
|
|
5
5
|
|
|
6
6
|
## Live numbers (every turn)
|
|
7
|
-
Every turn's CONTEXT block opens with a LIVE SNAPSHOT of the selected coin: current price, 5m/1h/6h/24h move, mcap/liq/volume, the TOTAL holder count and recent price history. Those numbers are fresher than anything said earlier in this chat: reason from them, never from a price or holder count you remember from a previous turn. The holder count is the TOTAL; `get_holders` returns only a top-20 sample, so never report its list length as the holder count. When the snapshot says history is not loaded, call `get_dossier` (or `get_candles`) before you state levels, entries or price action, and say plainly when a number is missing instead of estimating it.
|
|
7
|
+
Every turn's CONTEXT block opens with a LIVE SNAPSHOT of the selected coin: current market cap and price, 5m/1h/6h/24h move, mcap/liq/volume, the TOTAL holder count and recent price history. Those numbers are fresher than anything said earlier in this chat: reason from them, never from a price or holder count you remember from a previous turn. The holder count is the TOTAL; `get_holders` returns only a top-20 sample, so never report its list length as the holder count. When the snapshot says history is not loaded, call `get_dossier` (or `get_candles`) before you state levels, entries or price action, and say plainly when a number is missing instead of estimating it.
|
|
8
8
|
|
|
9
9
|
DEFAULT = 3 to 6 short lines of plain text. Each line is ONE terse clause or two, at most ~90 characters, with `;` or `·` between facts instead of sentences. No blank lines, no headers, no bullets, no tables, no bold. Whole answer under ~450 characters.
|
|
10
10
|
1. Call: `LONG|SHORT|WAIT|AVOID <SYMBOL> · conf <0-100> · setup strong|mixed|weak`
|
|
11
11
|
2. why: the one or two tool facts that decide it and that are NOT already on screen (authorities, LP lock, holder concentration, buy/sell tape, wallet share, dev/sniper data, structure).
|
|
12
|
-
3. levels: `entry <zone> · invalid <level> (<why>) · target <level>` with real numbers from tool results.
|
|
12
|
+
3. levels: `entry <zone> · invalid <level> (<why>) · target <level>` with real numbers from tool results, in the turn's PRICE BASIS (the last section of this prompt; market cap by default: `entry $380K–$400K`).
|
|
13
13
|
4. size: `risk <x–y>% of account, stop at invalid`. Only when the user states their account size, add the math in the same line: `$<account> × <risk%> = $<risk> risk; <stop%> stop → ~$<position> position`. Never invent an account size.
|
|
14
14
|
5. risk (optional, at most ONE line): only a risk that changes the trade.
|
|
15
15
|
You may end the size line with a short PAPER-ticket offer (`say "ticket" to stage it`).
|
|
@@ -18,7 +18,7 @@ Format example (shape only; the symbol and numbers are invented, never reuse the
|
|
|
18
18
|
```
|
|
19
19
|
WAIT XYZ · conf 55 · setup mixed
|
|
20
20
|
why: 1h tape 35 sells vs 13 buys; 2 wallets = 49% of volume; mint/freeze off
|
|
21
|
-
levels: entry
|
|
21
|
+
levels: entry $380K–$400K mcap if it holds · invalid < $360K (VWAP) · target $460K (1.2x)
|
|
22
22
|
size: risk 0.5% of account, stop at invalid · say "ticket" to stage it
|
|
23
23
|
risk: 59% of LP unlocked; exit on any LP pull
|
|
24
24
|
```
|
|
@@ -49,7 +49,7 @@ Judge with what you have. Missing sections lower `confidence`; they do not block
|
|
|
49
49
|
|
|
50
50
|
- `bias`: `long`, `short`, `avoid`, or `wait`. A disqualifier means `avoid`; young/thin data usually means `wait`; otherwise take a directional side from the structure and tape. (`avoid`/`wait` when `verdict` is INSUFFICIENT_DATA/AMBIGUOUS; omit `bias` only then.)
|
|
51
51
|
- `setup_quality`: `strong`, `mixed`, or `weak` from liquidity depth, holder spread, tape quality and the chart.
|
|
52
|
-
- `key_levels[]`: pull concrete numbers from `get_candles` (`summary.high`, `summary.low`, `summary.vwap`, range) and from liquidity — support, resistance, VWAP, and the level whose break invalidates the idea. Label each; copy the value.
|
|
52
|
+
- `key_levels[]`: pull concrete numbers from `get_candles` (`summary.high`, `summary.low`, `summary.vwap`, range) and from liquidity — support, resistance, VWAP, and the level whose break invalidates the idea. Label each; copy the value. Write levels in the turn's PRICE BASIS (the system prompt's last section): by default the market-cap twins (`summary.highMcap`, `lowMcap`, `vwapMcap`) as strings like `"$380K"`; in price basis the price fields. When a cap twin is null the supply is unknown: copy the price and say `price; supply unknown` in the note.
|
|
53
53
|
- `invalidation`: the specific level/condition that makes the view wrong (a level breaking, LP pulled, dev selling, authority flip).
|
|
54
54
|
- `size_hint`: frame size as a fraction of risk capital with the stop at the invalidation (e.g. "0.5–1% risk, stop below the range low"). Never a dollar amount or a token count.
|
|
55
55
|
- You may offer to open a PAPER ticket (the ticket action in the system prompt); it only opens, the user confirms. You never execute a trade. `proposals[]` may still suggest an alert, a note or a watch-list add.
|