desic-okx-agent 0.2.1 → 0.3.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/README.en.md +90 -10
- package/README.md +76 -10
- package/dist/account/private-websocket.js +4 -4
- package/dist/account/private-websocket.js.map +1 -1
- package/dist/account/service.d.ts +12 -1
- package/dist/account/service.js +18 -0
- package/dist/account/service.js.map +1 -1
- package/dist/bars/rate-limiter.d.ts +18 -0
- package/dist/bars/rate-limiter.js +84 -0
- package/dist/bars/rate-limiter.js.map +1 -0
- package/dist/bars/schema.d.ts +36 -0
- package/dist/bars/schema.js +134 -0
- package/dist/bars/schema.js.map +1 -0
- package/dist/bars/service.d.ts +60 -0
- package/dist/bars/service.js +120 -0
- package/dist/bars/service.js.map +1 -0
- package/dist/bars/store.d.ts +105 -0
- package/dist/bars/store.js +415 -0
- package/dist/bars/store.js.map +1 -0
- package/dist/bars/timeframe.d.ts +40 -0
- package/dist/bars/timeframe.js +146 -0
- package/dist/bars/timeframe.js.map +1 -0
- package/dist/bars/types.d.ts +68 -0
- package/dist/bars/types.js +13 -0
- package/dist/bars/types.js.map +1 -0
- package/dist/cli/data-render.d.ts +37 -0
- package/dist/cli/data-render.js +143 -0
- package/dist/cli/data-render.js.map +1 -0
- package/dist/cli/doctor.js +7 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.js +757 -26
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/live-render.d.ts +24 -0
- package/dist/cli/live-render.js +85 -0
- package/dist/cli/live-render.js.map +1 -0
- package/dist/cli/range.d.ts +28 -0
- package/dist/cli/range.js +63 -0
- package/dist/cli/range.js.map +1 -0
- package/dist/cli/render.js +3 -0
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/strategy-render.d.ts +36 -0
- package/dist/cli/strategy-render.js +391 -0
- package/dist/cli/strategy-render.js.map +1 -0
- package/dist/cli/width.d.ts +18 -0
- package/dist/cli/width.js +71 -0
- package/dist/cli/width.js.map +1 -0
- package/dist/config/loader.js +1 -1
- package/dist/config/schema.d.ts +7 -0
- package/dist/config/schema.js +24 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/core/okx-client.d.ts +9 -1
- package/dist/core/okx-client.js +14 -5
- package/dist/core/okx-client.js.map +1 -1
- package/dist/i18n/locale.d.ts +24 -0
- package/dist/i18n/locale.js +65 -0
- package/dist/i18n/locale.js.map +1 -0
- package/dist/i18n/messages.d.ts +333 -0
- package/dist/i18n/messages.js +660 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/live/account-snapshot.d.ts +30 -0
- package/dist/live/account-snapshot.js +130 -0
- package/dist/live/account-snapshot.js.map +1 -0
- package/dist/live/cutoff-queue.d.ts +42 -0
- package/dist/live/cutoff-queue.js +69 -0
- package/dist/live/cutoff-queue.js.map +1 -0
- package/dist/live/execution-key.d.ts +23 -0
- package/dist/live/execution-key.js +31 -0
- package/dist/live/execution-key.js.map +1 -0
- package/dist/live/failures.d.ts +37 -0
- package/dist/live/failures.js +57 -0
- package/dist/live/failures.js.map +1 -0
- package/dist/live/gates.d.ts +65 -0
- package/dist/live/gates.js +136 -0
- package/dist/live/gates.js.map +1 -0
- package/dist/live/loop.d.ts +56 -0
- package/dist/live/loop.js +197 -0
- package/dist/live/loop.js.map +1 -0
- package/dist/live/preconditions.d.ts +48 -0
- package/dist/live/preconditions.js +69 -0
- package/dist/live/preconditions.js.map +1 -0
- package/dist/live/reconcile.d.ts +46 -0
- package/dist/live/reconcile.js +104 -0
- package/dist/live/reconcile.js.map +1 -0
- package/dist/live/runner.d.ts +57 -0
- package/dist/live/runner.js +160 -0
- package/dist/live/runner.js.map +1 -0
- package/dist/live/schema.d.ts +18 -0
- package/dist/live/schema.js +91 -0
- package/dist/live/schema.js.map +1 -0
- package/dist/live/service.d.ts +144 -0
- package/dist/live/service.js +303 -0
- package/dist/live/service.js.map +1 -0
- package/dist/live/session.d.ts +85 -0
- package/dist/live/session.js +234 -0
- package/dist/live/session.js.map +1 -0
- package/dist/live/sizing.d.ts +62 -0
- package/dist/live/sizing.js +79 -0
- package/dist/live/sizing.js.map +1 -0
- package/dist/live/store.d.ts +123 -0
- package/dist/live/store.js +350 -0
- package/dist/live/store.js.map +1 -0
- package/dist/live/types.d.ts +82 -0
- package/dist/live/types.js +2 -0
- package/dist/live/types.js.map +1 -0
- package/dist/market/websocket.d.ts +16 -1
- package/dist/market/websocket.js +60 -5
- package/dist/market/websocket.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +15 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/network/connectivity.d.ts +9 -1
- package/dist/network/connectivity.js +28 -1
- package/dist/network/connectivity.js.map +1 -1
- package/dist/report/chart-script.d.ts +12 -0
- package/dist/report/chart-script.js +146 -0
- package/dist/report/chart-script.js.map +1 -0
- package/dist/report/compare-html.d.ts +8 -0
- package/dist/report/compare-html.js +254 -0
- package/dist/report/compare-html.js.map +1 -0
- package/dist/report/compare-script.d.ts +12 -0
- package/dist/report/compare-script.js +109 -0
- package/dist/report/compare-script.js.map +1 -0
- package/dist/report/compare.d.ts +61 -0
- package/dist/report/compare.js +205 -0
- package/dist/report/compare.js.map +1 -0
- package/dist/report/fetch.d.ts +20 -0
- package/dist/report/fetch.js +56 -0
- package/dist/report/fetch.js.map +1 -0
- package/dist/report/html.d.ts +54 -0
- package/dist/report/html.js +641 -0
- package/dist/report/html.js.map +1 -0
- package/dist/report/open.d.ts +42 -0
- package/dist/report/open.js +114 -0
- package/dist/report/open.js.map +1 -0
- package/dist/runtime/server.d.ts +16 -1
- package/dist/runtime/server.js +112 -9
- package/dist/runtime/server.js.map +1 -1
- package/dist/setup/installer.d.ts +1 -0
- package/dist/setup/installer.js +8 -0
- package/dist/setup/installer.js.map +1 -1
- package/dist/setup/wizard.js +19 -22
- package/dist/setup/wizard.js.map +1 -1
- package/dist/strategy/constants.d.ts +23 -0
- package/dist/strategy/constants.js +24 -0
- package/dist/strategy/constants.js.map +1 -0
- package/dist/strategy/environment.d.ts +52 -0
- package/dist/strategy/environment.js +187 -0
- package/dist/strategy/environment.js.map +1 -0
- package/dist/strategy/instrument.d.ts +29 -0
- package/dist/strategy/instrument.js +39 -0
- package/dist/strategy/instrument.js.map +1 -0
- package/dist/strategy/optimize.d.ts +73 -0
- package/dist/strategy/optimize.js +113 -0
- package/dist/strategy/optimize.js.map +1 -0
- package/dist/strategy/parameter-space.d.ts +59 -0
- package/dist/strategy/parameter-space.js +221 -0
- package/dist/strategy/parameter-space.js.map +1 -0
- package/dist/strategy/python-bridge.d.ts +24 -0
- package/dist/strategy/python-bridge.js +114 -0
- package/dist/strategy/python-bridge.js.map +1 -0
- package/dist/strategy/schema.d.ts +9 -0
- package/dist/strategy/schema.js +91 -0
- package/dist/strategy/schema.js.map +1 -0
- package/dist/strategy/service.d.ts +138 -0
- package/dist/strategy/service.js +745 -0
- package/dist/strategy/service.js.map +1 -0
- package/dist/strategy/settings.d.ts +162 -0
- package/dist/strategy/settings.js +243 -0
- package/dist/strategy/settings.js.map +1 -0
- package/dist/strategy/store.d.ts +96 -0
- package/dist/strategy/store.js +367 -0
- package/dist/strategy/store.js.map +1 -0
- package/dist/strategy/templates.d.ts +11 -0
- package/dist/strategy/templates.js +134 -0
- package/dist/strategy/templates.js.map +1 -0
- package/dist/strategy/types.d.ts +111 -0
- package/dist/strategy/types.js +2 -0
- package/dist/strategy/types.js.map +1 -0
- package/dist/tools/catalog.d.ts +16 -0
- package/dist/tools/catalog.js +118 -17
- package/dist/tools/catalog.js.map +1 -1
- package/dist/trade/service.d.ts +12 -0
- package/dist/trade/service.js +24 -7
- package/dist/trade/service.js.map +1 -1
- package/dist/tui/app.d.ts +23 -0
- package/dist/tui/app.js +322 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/commands.d.ts +70 -0
- package/dist/tui/commands.js +313 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/entries.d.ts +17 -0
- package/dist/tui/entries.js +24 -0
- package/dist/tui/entries.js.map +1 -0
- package/dist/tui/execute.d.ts +26 -0
- package/dist/tui/execute.js +664 -0
- package/dist/tui/execute.js.map +1 -0
- package/dist/tui/history.d.ts +17 -0
- package/dist/tui/history.js +48 -0
- package/dist/tui/history.js.map +1 -0
- package/dist/tui/index.d.ts +8 -0
- package/dist/tui/index.js +48 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/line-editor.d.ts +44 -0
- package/dist/tui/line-editor.js +98 -0
- package/dist/tui/line-editor.js.map +1 -0
- package/dist/tui/progress.d.ts +23 -0
- package/dist/tui/progress.js +46 -0
- package/dist/tui/progress.js.map +1 -0
- package/dist/tui/settings-editor.d.ts +18 -0
- package/dist/tui/settings-editor.js +115 -0
- package/dist/tui/settings-editor.js.map +1 -0
- package/docs/live-trading.md +455 -0
- package/docs/strategy-research.md +597 -0
- package/package.json +10 -1
- package/python/desic_strategy/__init__.py +34 -0
- package/python/desic_strategy/actions.py +158 -0
- package/python/desic_strategy/context.py +164 -0
- package/python/desic_strategy/engine.py +614 -0
- package/python/desic_strategy/indicators.py +159 -0
- package/python/desic_strategy/live.py +253 -0
- package/python/desic_strategy/policy.py +193 -0
- package/python/desic_strategy/portfolio.py +152 -0
- package/python/desic_strategy/report.py +319 -0
- package/python/desic_strategy/runner.py +574 -0
- package/python/desic_strategy/timeframe.py +150 -0
- package/python/main.py +18 -0
- package/skills/okx-live-trading/SKILL.md +117 -0
- package/skills/okx-live-trading/agents/openai.yaml +9 -0
- package/skills/okx-live-trading/references/lifecycle.md +128 -0
- package/skills/okx-strategy-research/SKILL.md +113 -0
- package/skills/okx-strategy-research/agents/openai.yaml +9 -0
- package/skills/okx-strategy-research/references/execution-semantics.md +107 -0
- package/skills/okx-strategy-research/references/field-traps.md +142 -0
- package/skills/okx-strategy-research/references/python-api.md +121 -0
- package/skills/okx-strategy-research/references/tools-and-data.md +192 -0
- package/skills/okx-trading/SKILL.md +11 -10
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { activeMessages } from "../i18n/locale.js";
|
|
2
|
+
import { displayWidth, padEndDisplay, renderTable } from "./width.js";
|
|
3
|
+
import { MINIMUM_ANNUALIZATION_DAYS } from "../strategy/constants.js";
|
|
4
|
+
import { describeSpace } from "../strategy/parameter-space.js";
|
|
5
|
+
import { describeRankBasis } from "../strategy/optimize.js";
|
|
6
|
+
import { formatBarTime, formatCount, formatDuration } from "./data-render.js";
|
|
7
|
+
export function formatValidation(result, file) {
|
|
8
|
+
const text = activeMessages();
|
|
9
|
+
if (result.valid)
|
|
10
|
+
return `✓ ${file} ${text.policyPassed}`;
|
|
11
|
+
const lines = [`✗ ${file} ${text.policyViolations(result.violations.length)}`];
|
|
12
|
+
for (const violation of result.violations) {
|
|
13
|
+
lines.push(` ${text.violationLine(violation.line, violation.message)}`);
|
|
14
|
+
}
|
|
15
|
+
return lines.join("\n");
|
|
16
|
+
}
|
|
17
|
+
export function formatViolations(violations) {
|
|
18
|
+
const text = activeMessages();
|
|
19
|
+
return violations.map((item) => ` ${text.violationLine(item.line, item.message)}`).join("\n");
|
|
20
|
+
}
|
|
21
|
+
export function formatRunTable(runs) {
|
|
22
|
+
const text = activeMessages();
|
|
23
|
+
if (runs.length === 0)
|
|
24
|
+
return `${text.noRuns}\n ${text.runsHint}`;
|
|
25
|
+
const rows = [
|
|
26
|
+
["RUN", "STRATEGY", "INSTRUMENT", "STATUS", "RETURN", "MAX DD", "TRADES", "CREATED"],
|
|
27
|
+
...runs.map((run) => {
|
|
28
|
+
const metrics = run.metrics ?? {};
|
|
29
|
+
return [
|
|
30
|
+
run.id,
|
|
31
|
+
run.strategyName,
|
|
32
|
+
run.instId,
|
|
33
|
+
run.status === "running" ? `${run.status} ${run.progressPct.toFixed(0)}%` : run.status,
|
|
34
|
+
metric(metrics.returnPct, "%", true),
|
|
35
|
+
metric(metrics.maxDrawdownPct, "%"),
|
|
36
|
+
metrics.tradeCount === undefined ? "-" : formatCount(Number(metrics.tradeCount)),
|
|
37
|
+
formatBarTime(run.createdAt)
|
|
38
|
+
];
|
|
39
|
+
})
|
|
40
|
+
];
|
|
41
|
+
return renderTable(rows);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Full report for one run.
|
|
45
|
+
*
|
|
46
|
+
* Grouped by the question each block answers — how much was made, how much risk
|
|
47
|
+
* that took, what the strategy did, and what the costs were — because a flat
|
|
48
|
+
* list of twenty numbers hides the ones that matter.
|
|
49
|
+
*/
|
|
50
|
+
export function formatRunDetail(run) {
|
|
51
|
+
const text = activeMessages();
|
|
52
|
+
const lines = [
|
|
53
|
+
`${run.id} ${run.strategyName} ${run.instId}`,
|
|
54
|
+
"",
|
|
55
|
+
`${label(text.statusLabel)} ${run.status}${run.status === "running" ? ` ${run.progressPct.toFixed(1)}%` : ""}`,
|
|
56
|
+
`${label(text.barsLabel)} ${formatCount(run.barCount)} ${text.includingPreloaded(formatCount(run.preloadBars))}`,
|
|
57
|
+
`${label(text.snapshotLabel)} ${run.dataSnapshotId ?? "-"}`
|
|
58
|
+
];
|
|
59
|
+
if (run.status === "running" && run.etaMs !== null) {
|
|
60
|
+
lines.push(`${label(text.etaLabel)} ${formatDuration(run.etaMs)}`);
|
|
61
|
+
}
|
|
62
|
+
if (run.startedAt !== null && run.finishedAt !== null) {
|
|
63
|
+
lines.push(`${label(text.elapsedLabel)} ${formatDuration(run.finishedAt - run.startedAt)}`);
|
|
64
|
+
}
|
|
65
|
+
if (run.error)
|
|
66
|
+
lines.push(`${label(text.errorLabel)} ${run.error}`);
|
|
67
|
+
const metrics = run.metrics;
|
|
68
|
+
if (!metrics)
|
|
69
|
+
return lines.join("\n");
|
|
70
|
+
const days = Number(metrics.evaluationDays ?? 0);
|
|
71
|
+
lines.push("", text.performance, row(text.netProfit, `${metric(metrics.netProfitUsdt, "", true)} USDT`), row(text.returnLabel, metric(metrics.returnPct, "%", true)), row(text.annualized, metrics.annualizedReturnPct === null || metrics.annualizedReturnPct === undefined
|
|
72
|
+
? `- (${text.annualizedWithheld(MINIMUM_ANNUALIZATION_DAYS)})`
|
|
73
|
+
: metric(metrics.annualizedReturnPct, "%", true)), row(text.maxDrawdown, `${metric(metrics.maxDrawdownPct, "%")} (${metric(metrics.maxDrawdownUsdt, "")} USDT)`), row(text.drawdownRecovery, `${formatCount(Number(metrics.longestDrawdownBars ?? 0))} bars`), "", text.riskAdjusted, row(text.sharpeLabel, metric(metrics.sharpe, "")), row(text.sortinoLabel, metric(metrics.sortino, "")), row(text.calmarLabel, metric(metrics.calmar, "")), "", text.activity, row(text.tradesLabel, `${formatCount(Number(metrics.tradeCount ?? 0))} (${text.longShort(Number(metrics.longTradeCount ?? 0), Number(metrics.shortTradeCount ?? 0))})`), row(text.winRate, metric(metrics.winRatePct, "%")), row(text.profitFactor, `${metric(metrics.profitFactor, "")} (${text.netOfFees})`), row(text.expectancy, `${metric(metrics.expectancyUsdt, "", true)} USDT`), row(text.averageWinLoss, `${metric(metrics.averageWinUsdt, "", true)} / ${metric(metrics.averageLossUsdt, "", true)} USDT`), row(text.largestWinLoss, `${metric(metrics.largestWinUsdt, "", true)} / ${metric(metrics.largestLossUsdt, "", true)} USDT`), row(text.streaks, `${formatCount(Number(metrics.maxConsecutiveWins ?? 0))}W / ${formatCount(Number(metrics.maxConsecutiveLosses ?? 0))}L`), row(text.holdingTime, `${metric(metrics.averageHoldingBars, "")} bars`), row(text.tradesPerDay, metric(metrics.tradesPerDay, "")), "", text.costs, row(text.feesLabel, `${metric(metrics.totalFeesUsdt, "")} USDT`), row(text.feesOfGross, metrics.feesPctOfGross === null || metrics.feesPctOfGross === undefined
|
|
74
|
+
? "-"
|
|
75
|
+
: metric(metrics.feesPctOfGross, "%")), row(text.turnover, `${metric(metrics.turnoverUsdt, "")} USDT`), row(text.exposure, metric(metrics.exposurePct, "%")));
|
|
76
|
+
const assumptions = run.assumptions;
|
|
77
|
+
if (assumptions) {
|
|
78
|
+
// Shown with the result, because a return figure is meaningless without the
|
|
79
|
+
// leverage, budget, and costs that produced it.
|
|
80
|
+
const contract = (assumptions.contract ?? {});
|
|
81
|
+
const fixedBudget = assumptions.entryBudgetUsdt;
|
|
82
|
+
lines.push("", text.assumptionsHeading, row(text.settingEquity, `${metric(assumptions.initialEquityUsdt, "")} USDT`), row(text.settingLeverage, `${metric(assumptions.leverage, "")}x`), row(text.settingMarginSafety, `${metric(assumptions.marginSafetyMultiplier, "")}x`), row(text.settingBudgetPct, fixedBudget === null || fixedBudget === undefined
|
|
83
|
+
? percent(assumptions.entryBudgetPct)
|
|
84
|
+
: `${metric(fixedBudget, "")} USDT`), row(text.settingTakerFee, bps(assumptions.takerFeeRate)), row(text.settingMakerFee, bps(assumptions.makerFeeRate)), row(text.settingEntrySlippage, `${metric(assumptions.entrySlippageBps, "")} / ${metric(assumptions.exitSlippageBps, "")} bps`), row(text.settingPreload, `${formatCount(Number(assumptions.preloadBars ?? 0))} bars`), row(text.settingCloseAtEnd, assumptions.closeAtEnd === false ? text.no : text.yes), row("contract", `${metric(contract.contractValue, "")} ${String(contract.contractValueCurrency ?? "")} x${metric(contract.contractMultiplier, "")} lot ${metric(contract.lotSize, "")}`));
|
|
85
|
+
const params = assumptions.params;
|
|
86
|
+
if (params && Object.keys(params).length) {
|
|
87
|
+
lines.push(row("params", Object.entries(params).map(([key, value]) => `${key}=${String(value)}`).join(" ")));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (metrics.marginExhausted === true) {
|
|
91
|
+
lines.push("", `! ${text.marginExhaustedWarning}`, ` ${text.marginExhaustedDetail}`);
|
|
92
|
+
}
|
|
93
|
+
// Costs above the gross edge are the usual reason a plausible signal loses
|
|
94
|
+
// money, so call it out rather than leaving it to be spotted in the numbers.
|
|
95
|
+
const feeShare = Number(metrics.feesPctOfGross ?? 0);
|
|
96
|
+
if (feeShare > 100) {
|
|
97
|
+
lines.push("", `! ${text.feesLabel} ${metric(feeShare, "%")} ${text.feesOfGross}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push("", `${text.simulationNote} ${days.toFixed(1)}d`);
|
|
100
|
+
return lines.join("\n");
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Braille sparkline of the equity curve.
|
|
104
|
+
*
|
|
105
|
+
* Each column carries two samples in the left-hand dots, so a curve reads at a
|
|
106
|
+
* glance without needing a graphical terminal.
|
|
107
|
+
*/
|
|
108
|
+
export function formatEquitySparkline(points, width = 60, height = 6) {
|
|
109
|
+
const text = activeMessages();
|
|
110
|
+
if (points.length < 2)
|
|
111
|
+
return ` ${text.notEnoughPoints}`;
|
|
112
|
+
const values = points.map((point) => point.equityUsdt);
|
|
113
|
+
const minimum = Math.min(...values);
|
|
114
|
+
const maximum = Math.max(...values);
|
|
115
|
+
const span = maximum - minimum;
|
|
116
|
+
const columns = Math.max(8, Math.min(width, points.length));
|
|
117
|
+
const rows = Math.max(2, height);
|
|
118
|
+
const dotRows = rows * 4;
|
|
119
|
+
// Two horizontal samples per column, four vertical dots per row.
|
|
120
|
+
const grid = Array.from({ length: rows }, () => Array.from({ length: columns }, () => 0));
|
|
121
|
+
for (let column = 0; column < columns; column += 1) {
|
|
122
|
+
for (let half = 0; half < 2; half += 1) {
|
|
123
|
+
const position = (column * 2 + half) / (columns * 2 - 1);
|
|
124
|
+
const index = Math.min(values.length - 1, Math.round(position * (values.length - 1)));
|
|
125
|
+
const value = values[index];
|
|
126
|
+
const normalized = span === 0 ? 0.5 : (value - minimum) / span;
|
|
127
|
+
const dot = Math.min(dotRows - 1, Math.max(0, Math.round(normalized * (dotRows - 1))));
|
|
128
|
+
const row = rows - 1 - Math.floor(dot / 4);
|
|
129
|
+
const dotRow = 3 - (dot % 4);
|
|
130
|
+
grid[row][column] |= brailleBit(half, dotRow);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const lines = grid.map((row) => row.map((mask) => String.fromCodePoint(0x2800 + mask)).join(""));
|
|
134
|
+
const labelled = lines.map((line, index) => {
|
|
135
|
+
if (index === 0)
|
|
136
|
+
return ` ${line} ${maximum.toFixed(2)}`;
|
|
137
|
+
if (index === lines.length - 1)
|
|
138
|
+
return ` ${line} ${minimum.toFixed(2)}`;
|
|
139
|
+
return ` ${line}`;
|
|
140
|
+
});
|
|
141
|
+
const first = points[0];
|
|
142
|
+
const last = points.at(-1);
|
|
143
|
+
labelled.push(` ${formatBarTime(first.timeMs)} → ${formatBarTime(last.timeMs)} UTC (${formatCount(points.length)})`);
|
|
144
|
+
return labelled.join("\n");
|
|
145
|
+
}
|
|
146
|
+
export function formatTradeTable(trades, limit = 20) {
|
|
147
|
+
const text = activeMessages();
|
|
148
|
+
if (trades.length === 0)
|
|
149
|
+
return ` ${text.noClosedTrades}`;
|
|
150
|
+
const rows = [
|
|
151
|
+
["SIDE", "QTY", "ENTRY", "EXIT", "NET PNL", "RET%", "FEES", "BARS", "OPENED"],
|
|
152
|
+
...trades.slice(0, limit).map((trade) => [
|
|
153
|
+
String(trade.side ?? "-"),
|
|
154
|
+
metric(trade.quantity, ""),
|
|
155
|
+
metric(trade.entryPrice, ""),
|
|
156
|
+
metric(trade.exitPrice, ""),
|
|
157
|
+
metric(trade.netPnlUsdt ?? trade.realizedPnlUsdt, "", true),
|
|
158
|
+
metric(trade.returnPct, "%", true),
|
|
159
|
+
metric(trade.feesUsdt, ""),
|
|
160
|
+
trade.holdingBars === undefined ? "-" : formatCount(Number(trade.holdingBars)),
|
|
161
|
+
trade.openedAtMs === undefined ? "-" : formatBarTime(Number(trade.openedAtMs))
|
|
162
|
+
])
|
|
163
|
+
];
|
|
164
|
+
const output = renderTable(rows)
|
|
165
|
+
.split("\n")
|
|
166
|
+
.map((line) => ` ${line}`)
|
|
167
|
+
.join("\n");
|
|
168
|
+
return trades.length > limit ? `${output}\n ${text.coverageMore(formatCount(trades.length - limit))}` : output;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Candidate table for one optimize run.
|
|
172
|
+
*
|
|
173
|
+
* Training and validation columns sit side by side on purpose. The pair is the
|
|
174
|
+
* result; either number alone invites the mistake the split exists to prevent —
|
|
175
|
+
* quoting a figure measured on the very bars that selected the parameters.
|
|
176
|
+
*/
|
|
177
|
+
export function formatOptimizationReport(report) {
|
|
178
|
+
const text = activeMessages();
|
|
179
|
+
const run = report.run;
|
|
180
|
+
const lines = [`${run.id} ${run.strategyName} ${run.instId}`, ""];
|
|
181
|
+
lines.push(`${label(text.statusLabel)} ${run.status}${run.status === "running" ? ` ${run.progressPct.toFixed(1)}%` : ""}`);
|
|
182
|
+
lines.push(`${label(text.spaceLabel)} ${describeSpace(report.space) || "-"}`);
|
|
183
|
+
lines.push(`${label(text.candidatesLabel)} ${text.candidatesOf(formatCount(report.completed), formatCount(report.budget), formatCount(report.combinations))}${report.failed > 0 ? ` · ${text.candidatesFailed(formatCount(report.failed))}` : ""}`);
|
|
184
|
+
if (report.split) {
|
|
185
|
+
lines.push(`${label(text.trainLabel)} ${formatBarTime(report.split.trainStartMs)} → ${formatBarTime(report.split.trainEndMs)} (${formatCount(report.split.trainBars)} ${text.barsColumn.toLowerCase()})`, `${label(text.validationLabel)} ${formatBarTime(report.split.validationStartMs)} → ${formatBarTime(report.split.validationEndMs)} (${formatCount(report.split.validationBars)} ${text.barsColumn.toLowerCase()})`);
|
|
186
|
+
}
|
|
187
|
+
if (run.error)
|
|
188
|
+
lines.push(`${label(text.errorLabel)} ${run.error}`);
|
|
189
|
+
if (run.dataSnapshotId)
|
|
190
|
+
lines.push(`${label(text.snapshotLabel)} ${run.dataSnapshotId}`);
|
|
191
|
+
const evaluated = report.candidates.filter((candidate) => candidate.status === "completed");
|
|
192
|
+
if (evaluated.length === 0) {
|
|
193
|
+
lines.push("", ` ${text.noCandidatesYet}`);
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
// Only the varied parameters get a column: repeating the constant ones on every
|
|
197
|
+
// row costs the width that the metric pairs need.
|
|
198
|
+
const keys = Object.keys(report.space).sort();
|
|
199
|
+
const header = [
|
|
200
|
+
"#",
|
|
201
|
+
...keys,
|
|
202
|
+
text.trainReturn,
|
|
203
|
+
text.validationReturn,
|
|
204
|
+
text.trainDrawdown,
|
|
205
|
+
text.validationDrawdown,
|
|
206
|
+
text.tradesLabel,
|
|
207
|
+
text.verdictColumn
|
|
208
|
+
];
|
|
209
|
+
const rows = [
|
|
210
|
+
header,
|
|
211
|
+
...evaluated.map((candidate, position) => [
|
|
212
|
+
String(position + 1),
|
|
213
|
+
...keys.map((key) => formatParam(candidate.params[key])),
|
|
214
|
+
metric(candidate.train?.returnPct, "%", true),
|
|
215
|
+
metric(candidate.validation?.returnPct, "%", true),
|
|
216
|
+
metric(candidate.train?.maxDrawdownPct, "%"),
|
|
217
|
+
metric(candidate.validation?.maxDrawdownPct, "%"),
|
|
218
|
+
candidate.validation?.tradeCount === undefined ? "-" : formatCount(Number(candidate.validation.tradeCount)),
|
|
219
|
+
verdictText(candidate.verdict, text)
|
|
220
|
+
])
|
|
221
|
+
];
|
|
222
|
+
lines.push("", renderTable(rows));
|
|
223
|
+
const failures = report.candidates.filter((candidate) => candidate.status === "failed");
|
|
224
|
+
if (failures.length > 0) {
|
|
225
|
+
lines.push("", text.candidatesFailed(formatCount(failures.length)));
|
|
226
|
+
for (const candidate of failures.slice(0, 3)) {
|
|
227
|
+
lines.push(` ${formatParams(candidate.params)} ${candidate.error ?? "-"}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const basis = report.rankBasis;
|
|
231
|
+
if (basis) {
|
|
232
|
+
const validationDays = report.split ? report.split.validationBars / 1_440 : 0;
|
|
233
|
+
lines.push("", ` ${describeRankBasis(basis, validationDays)}`);
|
|
234
|
+
}
|
|
235
|
+
// The point of the exercise, stated rather than implied: the validation column
|
|
236
|
+
// is the reportable one, and a wide gap between the two is the warning.
|
|
237
|
+
lines.push(` ${text.overfitNote}`);
|
|
238
|
+
// The split removes the worst of the bias but not all of it. Ranking N
|
|
239
|
+
// candidates by their validation score selects for a high one, so the leader's
|
|
240
|
+
// figure is optimistic by an amount that grows with the candidate count. Saying
|
|
241
|
+
// so is the difference between a held-back segment and a genuinely clean
|
|
242
|
+
// estimate.
|
|
243
|
+
if (evaluated.length > 1)
|
|
244
|
+
lines.push(` ${text.selectionNote}`);
|
|
245
|
+
return lines.join("\n");
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Side-by-side metrics for two or more runs.
|
|
249
|
+
*
|
|
250
|
+
* Warnings lead, because a comparison of runs that were never comparable is worse
|
|
251
|
+
* than no comparison: the table looks authoritative either way.
|
|
252
|
+
*/
|
|
253
|
+
export function formatComparison(report) {
|
|
254
|
+
const text = activeMessages();
|
|
255
|
+
const lines = [];
|
|
256
|
+
for (const warning of report.warnings) {
|
|
257
|
+
lines.push(` ! ${warning.message}`);
|
|
258
|
+
}
|
|
259
|
+
if (report.warnings.length > 0)
|
|
260
|
+
lines.push("");
|
|
261
|
+
// One column per run, one row per metric — the transpose of a single report,
|
|
262
|
+
// because reading down a column is how a difference is spotted.
|
|
263
|
+
const rows = [["", ...report.runs.map((run) => run.id)]];
|
|
264
|
+
rows.push([text.strategyColumn, ...report.runs.map((run) => run.strategyName)]);
|
|
265
|
+
rows.push([text.instrumentColumn, ...report.runs.map((run) => run.instId)]);
|
|
266
|
+
rows.push([text.statusLabel, ...report.runs.map((run) => run.status)]);
|
|
267
|
+
for (const [label, key, kind] of COMPARED_METRICS) {
|
|
268
|
+
rows.push([
|
|
269
|
+
label(text),
|
|
270
|
+
...report.runs.map((run) => {
|
|
271
|
+
const value = run.metrics?.[key];
|
|
272
|
+
// A trade count is a whole number; `50.00` reads as a measurement.
|
|
273
|
+
if (kind === "count") {
|
|
274
|
+
return value === null || value === undefined ? "-" : formatCount(Number(value));
|
|
275
|
+
}
|
|
276
|
+
// A signed percentage keeps both its sign and its unit: `+12.40` alone
|
|
277
|
+
// reads as USDT, and dropping the sign from a return hides a loss.
|
|
278
|
+
return metric(value, kind === "plain" ? "" : "%", kind === "signed");
|
|
279
|
+
})
|
|
280
|
+
]);
|
|
281
|
+
}
|
|
282
|
+
lines.push(renderTable(rows));
|
|
283
|
+
if (report.differingAssumptions.length > 0) {
|
|
284
|
+
// Only the assumptions that actually differ. With twenty rows per run, a full
|
|
285
|
+
// matrix buries the two values that changed.
|
|
286
|
+
lines.push("", text.differingAssumptionsHeading);
|
|
287
|
+
const table = [["", ...report.runs.map((run) => run.id)]];
|
|
288
|
+
for (const entry of report.differingAssumptions) {
|
|
289
|
+
table.push([entry.key, ...entry.values.map((value) => value ?? "-")]);
|
|
290
|
+
}
|
|
291
|
+
lines.push(renderTable(table));
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
lines.push("", ` ${text.assumptionsIdentical}`);
|
|
295
|
+
}
|
|
296
|
+
if (report.sharedAssumptions.length > 0) {
|
|
297
|
+
lines.push("", ` ${text.sharedAssumptionsNote(String(report.sharedAssumptions.length))}`);
|
|
298
|
+
}
|
|
299
|
+
lines.push("", ` ${text.compareNormalizedNote}`);
|
|
300
|
+
return lines.join("\n");
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Metrics worth putting side by side, in reading order.
|
|
304
|
+
*
|
|
305
|
+
* Deliberately shorter than a single run's report: a comparison answers "which of
|
|
306
|
+
* these is better and at what cost", and twenty rows per run makes that harder to
|
|
307
|
+
* see rather than easier.
|
|
308
|
+
*/
|
|
309
|
+
const COMPARED_METRICS = [
|
|
310
|
+
[(text) => text.returnLabel, "returnPct", "signed"],
|
|
311
|
+
[(text) => text.maxDrawdown, "maxDrawdownPct", "pct"],
|
|
312
|
+
[(text) => text.calmarLabel, "calmar", "plain"],
|
|
313
|
+
[(text) => text.sharpeLabel, "sharpe", "plain"],
|
|
314
|
+
[(text) => text.tradesLabel, "tradeCount", "count"],
|
|
315
|
+
[(text) => text.winRate, "winRatePct", "pct"],
|
|
316
|
+
[(text) => text.profitFactor, "profitFactor", "plain"],
|
|
317
|
+
[(text) => text.feesLabel, "totalFeesUsdt", "plain"],
|
|
318
|
+
[(text) => text.feesOfGross, "feesPctOfGross", "pct"],
|
|
319
|
+
[(text) => text.exposure, "exposurePct", "pct"]
|
|
320
|
+
];
|
|
321
|
+
function formatParam(value) {
|
|
322
|
+
if (value === undefined)
|
|
323
|
+
return "-";
|
|
324
|
+
return Number.isInteger(value) ? String(value) : String(value);
|
|
325
|
+
}
|
|
326
|
+
function formatParams(params) {
|
|
327
|
+
return Object.entries(params)
|
|
328
|
+
.map(([key, value]) => `${key}=${formatParam(value)}`)
|
|
329
|
+
.join(" ");
|
|
330
|
+
}
|
|
331
|
+
function verdictText(verdict, text) {
|
|
332
|
+
switch (verdict) {
|
|
333
|
+
case "holds":
|
|
334
|
+
return text.verdictHolds;
|
|
335
|
+
case "overfit":
|
|
336
|
+
return text.verdictOverfit;
|
|
337
|
+
case "weak":
|
|
338
|
+
return text.verdictWeak;
|
|
339
|
+
case "unexplained":
|
|
340
|
+
return text.verdictUnexplained;
|
|
341
|
+
default:
|
|
342
|
+
return "-";
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function label(value) {
|
|
346
|
+
return padEndDisplay(value, 12);
|
|
347
|
+
}
|
|
348
|
+
function row(name, value) {
|
|
349
|
+
// Padded in cells so a Chinese label does not push the value out of column.
|
|
350
|
+
return ` ${padEndDisplay(name, Math.max(16, displayWidth(name) + 1))} ${value}`;
|
|
351
|
+
}
|
|
352
|
+
function brailleBit(half, dotRow) {
|
|
353
|
+
// Braille dot ordering is column-major: 1,2,3 then 7 on the left.
|
|
354
|
+
const left = [0x01, 0x02, 0x04, 0x40];
|
|
355
|
+
const right = [0x08, 0x10, 0x20, 0x80];
|
|
356
|
+
return half === 0 ? left[dotRow] : right[dotRow];
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Formats a metric, adding an explicit sign only where direction is meaningful.
|
|
360
|
+
*
|
|
361
|
+
* Drawdown, exposure, and win rate are magnitudes, never gains, so a leading "+"
|
|
362
|
+
* on them reads as a profit and misleads at a glance.
|
|
363
|
+
*/
|
|
364
|
+
/** A rate rendered in basis points, which is how fees are quoted in practice. */
|
|
365
|
+
function bps(value) {
|
|
366
|
+
const parsed = Number(value);
|
|
367
|
+
if (!Number.isFinite(parsed))
|
|
368
|
+
return "-";
|
|
369
|
+
return `${(parsed * 10_000).toFixed(2)} bps`;
|
|
370
|
+
}
|
|
371
|
+
function percent(value) {
|
|
372
|
+
const parsed = Number(value);
|
|
373
|
+
if (!Number.isFinite(parsed))
|
|
374
|
+
return "-";
|
|
375
|
+
return `${(parsed * 100).toFixed(2)}%`;
|
|
376
|
+
}
|
|
377
|
+
function metric(value, suffix, signed = false) {
|
|
378
|
+
if (value === null || value === undefined)
|
|
379
|
+
return "-";
|
|
380
|
+
const parsed = Number(value);
|
|
381
|
+
if (!Number.isFinite(parsed))
|
|
382
|
+
return "-";
|
|
383
|
+
const magnitude = Math.abs(parsed);
|
|
384
|
+
const formatted = magnitude >= 1_000_000
|
|
385
|
+
? `${(parsed / 1_000_000).toFixed(2)}M`
|
|
386
|
+
: magnitude >= 1_000
|
|
387
|
+
? parsed.toFixed(0)
|
|
388
|
+
: parsed.toFixed(2);
|
|
389
|
+
return `${signed && parsed > 0 ? "+" : ""}${formatted}${suffix}`;
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=strategy-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy-render.js","sourceRoot":"","sources":["../../src/cli/strategy-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal display width, not string length.
|
|
3
|
+
*
|
|
4
|
+
* A CJK glyph occupies two terminal cells but counts as one JavaScript
|
|
5
|
+
* character, so `padEnd` under-pads it and every column after a Chinese label
|
|
6
|
+
* drifts left. Emoji and other wide symbols behave the same way.
|
|
7
|
+
*/
|
|
8
|
+
/** Width in terminal cells, ignoring ANSI escape sequences. */
|
|
9
|
+
export declare function displayWidth(value: string): number;
|
|
10
|
+
/** Pads on the right to a target number of cells. */
|
|
11
|
+
export declare function padEndDisplay(value: string, target: number): string;
|
|
12
|
+
/** Pads on the left to a target number of cells. */
|
|
13
|
+
export declare function padStartDisplay(value: string, target: number): string;
|
|
14
|
+
/**
|
|
15
|
+
* Renders rows as a table whose columns line up in cells rather than characters.
|
|
16
|
+
* The final column is never padded, so trailing whitespace stays out of output.
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderTable(rows: string[][]): string;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal display width, not string length.
|
|
3
|
+
*
|
|
4
|
+
* A CJK glyph occupies two terminal cells but counts as one JavaScript
|
|
5
|
+
* character, so `padEnd` under-pads it and every column after a Chinese label
|
|
6
|
+
* drifts left. Emoji and other wide symbols behave the same way.
|
|
7
|
+
*/
|
|
8
|
+
/** Ranges that render two cells wide in a monospace terminal. */
|
|
9
|
+
const WIDE_RANGES = [
|
|
10
|
+
[0x1100, 0x115f], // Hangul Jamo
|
|
11
|
+
[0x2e80, 0x303e], // CJK radicals, Kangxi, punctuation
|
|
12
|
+
[0x3041, 0x33ff], // Hiragana, Katakana, CJK compatibility
|
|
13
|
+
[0x3400, 0x4dbf], // CJK extension A
|
|
14
|
+
[0x4e00, 0x9fff], // CJK unified ideographs
|
|
15
|
+
[0xa000, 0xa4cf], // Yi
|
|
16
|
+
[0xac00, 0xd7a3], // Hangul syllables
|
|
17
|
+
[0xf900, 0xfaff], // CJK compatibility ideographs
|
|
18
|
+
[0xfe10, 0xfe19], // vertical forms
|
|
19
|
+
[0xfe30, 0xfe6f], // CJK compatibility forms
|
|
20
|
+
[0xff00, 0xff60], // fullwidth forms
|
|
21
|
+
[0xffe0, 0xffe6], // fullwidth signs
|
|
22
|
+
[0x1f300, 0x1f64f], // emoji
|
|
23
|
+
[0x1f900, 0x1f9ff],
|
|
24
|
+
[0x20000, 0x3fffd] // CJK extensions B+
|
|
25
|
+
];
|
|
26
|
+
function charWidth(codePoint) {
|
|
27
|
+
// Combining marks add no width of their own.
|
|
28
|
+
if (codePoint >= 0x0300 && codePoint <= 0x036f)
|
|
29
|
+
return 0;
|
|
30
|
+
for (const [start, end] of WIDE_RANGES) {
|
|
31
|
+
if (codePoint >= start && codePoint <= end)
|
|
32
|
+
return 2;
|
|
33
|
+
}
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
/** Width in terminal cells, ignoring ANSI escape sequences. */
|
|
37
|
+
export function displayWidth(value) {
|
|
38
|
+
const plain = value.replace(/\u001b\[[0-9;]*[A-Za-z]/g, "");
|
|
39
|
+
let width = 0;
|
|
40
|
+
for (const character of plain) {
|
|
41
|
+
width += charWidth(character.codePointAt(0) ?? 0);
|
|
42
|
+
}
|
|
43
|
+
return width;
|
|
44
|
+
}
|
|
45
|
+
/** Pads on the right to a target number of cells. */
|
|
46
|
+
export function padEndDisplay(value, target) {
|
|
47
|
+
return value + " ".repeat(Math.max(0, target - displayWidth(value)));
|
|
48
|
+
}
|
|
49
|
+
/** Pads on the left to a target number of cells. */
|
|
50
|
+
export function padStartDisplay(value, target) {
|
|
51
|
+
return " ".repeat(Math.max(0, target - displayWidth(value))) + value;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Renders rows as a table whose columns line up in cells rather than characters.
|
|
55
|
+
* The final column is never padded, so trailing whitespace stays out of output.
|
|
56
|
+
*/
|
|
57
|
+
export function renderTable(rows) {
|
|
58
|
+
const widths = [];
|
|
59
|
+
for (const row of rows) {
|
|
60
|
+
row.forEach((cell, index) => {
|
|
61
|
+
widths[index] = Math.max(widths[index] ?? 0, displayWidth(cell));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return rows
|
|
65
|
+
.map((row) => row
|
|
66
|
+
.map((cell, index) => (index === row.length - 1 ? cell : padEndDisplay(cell, widths[index] ?? 0)))
|
|
67
|
+
.join(" ")
|
|
68
|
+
.trimEnd())
|
|
69
|
+
.join("\n");
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=width.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"width.js","sourceRoot":"","sources":["../../src/cli/width.ts"],"names":[],"mappings":"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"}
|
package/dist/config/loader.js
CHANGED
|
@@ -30,7 +30,7 @@ export function applyEnvironment(config, env) {
|
|
|
30
30
|
if (supplied === 0)
|
|
31
31
|
return config;
|
|
32
32
|
const name = env.OKX_ACCOUNT?.trim() || "default";
|
|
33
|
-
const environment = env.OKX_ENVIRONMENT === "
|
|
33
|
+
const environment = env.OKX_ENVIRONMENT === "demo" ? "demo" : "live";
|
|
34
34
|
return RuntimeConfigSchema.parse({
|
|
35
35
|
...config,
|
|
36
36
|
defaultAccount: name,
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export declare const RuntimeConfigSchema: z.ZodObject<{
|
|
|
20
20
|
passphrase: z.ZodString;
|
|
21
21
|
}, z.core.$strict>>>;
|
|
22
22
|
market: z.ZodPrefault<z.ZodObject<{
|
|
23
|
+
environment: z.ZodDefault<z.ZodEnum<{
|
|
24
|
+
demo: "demo";
|
|
25
|
+
live: "live";
|
|
26
|
+
}>>;
|
|
23
27
|
prewarm: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
24
28
|
bars: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
25
29
|
idleSubscriptionMs: z.ZodDefault<z.ZodNumber>;
|
|
@@ -27,6 +31,9 @@ export declare const RuntimeConfigSchema: z.ZodObject<{
|
|
|
27
31
|
orderBookDepth: z.ZodDefault<z.ZodNumber>;
|
|
28
32
|
recentTradeLimit: z.ZodDefault<z.ZodNumber>;
|
|
29
33
|
}, z.core.$strict>>;
|
|
34
|
+
live: z.ZodPrefault<z.ZodObject<{
|
|
35
|
+
agentAccess: z.ZodDefault<z.ZodBoolean>;
|
|
36
|
+
}, z.core.$strict>>;
|
|
30
37
|
proxy: z.ZodDefault<z.ZodObject<{
|
|
31
38
|
url: z.ZodOptional<z.ZodString>;
|
|
32
39
|
}, z.core.$strict>>;
|
package/dist/config/schema.js
CHANGED
|
@@ -9,6 +9,16 @@ export const RuntimeConfigSchema = z.strictObject({
|
|
|
9
9
|
defaultAccount: z.string().min(1).optional(),
|
|
10
10
|
accounts: z.record(z.string(), AccountSchema).default({}),
|
|
11
11
|
market: z.strictObject({
|
|
12
|
+
/**
|
|
13
|
+
* Which OKX environment supplies market data.
|
|
14
|
+
*
|
|
15
|
+
* Its own setting rather than following the default account: demo and live are
|
|
16
|
+
* separate matching environments with separate feeds, so tying this to the
|
|
17
|
+
* account would silently change where bars come from the moment someone
|
|
18
|
+
* switched accounts, leaving one store holding two incompatible sources.
|
|
19
|
+
* Defaults to `live` so an existing installation keeps the feed it has.
|
|
20
|
+
*/
|
|
21
|
+
environment: z.enum(["demo", "live"]).default("live"),
|
|
12
22
|
prewarm: z.array(z.string().min(1)).default(["BTC-USDT-SWAP", "ETH-USDT-SWAP"]),
|
|
13
23
|
bars: z.array(z.string().min(1)).default(["1m", "5m", "15m", "1H", "4H", "1D"]),
|
|
14
24
|
idleSubscriptionMs: z.number().int().min(60_000).default(900_000),
|
|
@@ -16,6 +26,20 @@ export const RuntimeConfigSchema = z.strictObject({
|
|
|
16
26
|
orderBookDepth: z.number().int().min(5).max(400).default(50),
|
|
17
27
|
recentTradeLimit: z.number().int().min(10).max(10_000).default(1_000)
|
|
18
28
|
}).prefault({}),
|
|
29
|
+
live: z.strictObject({
|
|
30
|
+
/**
|
|
31
|
+
* Whether MCP clients may create and enable live profiles.
|
|
32
|
+
*
|
|
33
|
+
* Off by default, and deliberately not something an upgrade turns on: installing a new
|
|
34
|
+
* version must never be what gives an agent the ability to commit money. Turning it on is
|
|
35
|
+
* one explicit act, which also makes it a kill switch.
|
|
36
|
+
*
|
|
37
|
+
* Even when on, a real-money profile still requires its own name typed back — that
|
|
38
|
+
* precondition is checked for every caller, so an agent can prepare and verify a strategy
|
|
39
|
+
* end to end on demo while the last step on live stays a person's.
|
|
40
|
+
*/
|
|
41
|
+
agentAccess: z.boolean().default(false)
|
|
42
|
+
}).prefault({}),
|
|
19
43
|
proxy: z.strictObject({
|
|
20
44
|
url: z.string().url().optional()
|
|
21
45
|
}).default({}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,15 @@ export declare class OkxClient {
|
|
|
4
4
|
private timeOffsetMs;
|
|
5
5
|
private readonly dispatcher?;
|
|
6
6
|
constructor(baseUrl?: string, proxyUrl?: string);
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Reads a public endpoint.
|
|
9
|
+
*
|
|
10
|
+
* `headers` exists so a caller can select the demo environment with
|
|
11
|
+
* `x-simulated-trading`. Public market data differs between environments — demo is
|
|
12
|
+
* a separate matching venue — so backfilling history without it would mix live
|
|
13
|
+
* bars into a demo store.
|
|
14
|
+
*/
|
|
15
|
+
publicGet<T = Record<string, unknown>>(path: string, query?: Record<string, unknown>, headers?: Record<string, string>): Promise<T[]>;
|
|
8
16
|
privateGet<T = Record<string, unknown>>(path: string, account: AccountCredentials, query?: Record<string, unknown>, headers?: Record<string, string>): Promise<T[]>;
|
|
9
17
|
privatePost<T = Record<string, unknown>>(path: string, account: AccountCredentials, body: unknown, attributed?: boolean): Promise<T[]>;
|
|
10
18
|
syncTime(): Promise<void>;
|