desic-okx-agent 0.2.0 → 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.
Files changed (237) hide show
  1. package/README.en.md +353 -0
  2. package/README.md +194 -190
  3. package/dist/account/private-websocket.js +4 -4
  4. package/dist/account/private-websocket.js.map +1 -1
  5. package/dist/account/service.d.ts +12 -1
  6. package/dist/account/service.js +18 -0
  7. package/dist/account/service.js.map +1 -1
  8. package/dist/bars/rate-limiter.d.ts +18 -0
  9. package/dist/bars/rate-limiter.js +84 -0
  10. package/dist/bars/rate-limiter.js.map +1 -0
  11. package/dist/bars/schema.d.ts +36 -0
  12. package/dist/bars/schema.js +134 -0
  13. package/dist/bars/schema.js.map +1 -0
  14. package/dist/bars/service.d.ts +60 -0
  15. package/dist/bars/service.js +120 -0
  16. package/dist/bars/service.js.map +1 -0
  17. package/dist/bars/store.d.ts +105 -0
  18. package/dist/bars/store.js +415 -0
  19. package/dist/bars/store.js.map +1 -0
  20. package/dist/bars/timeframe.d.ts +40 -0
  21. package/dist/bars/timeframe.js +146 -0
  22. package/dist/bars/timeframe.js.map +1 -0
  23. package/dist/bars/types.d.ts +68 -0
  24. package/dist/bars/types.js +13 -0
  25. package/dist/bars/types.js.map +1 -0
  26. package/dist/cli/data-render.d.ts +37 -0
  27. package/dist/cli/data-render.js +143 -0
  28. package/dist/cli/data-render.js.map +1 -0
  29. package/dist/cli/doctor.js +7 -3
  30. package/dist/cli/doctor.js.map +1 -1
  31. package/dist/cli/index.js +758 -27
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli/live-render.d.ts +24 -0
  34. package/dist/cli/live-render.js +85 -0
  35. package/dist/cli/live-render.js.map +1 -0
  36. package/dist/cli/range.d.ts +28 -0
  37. package/dist/cli/range.js +63 -0
  38. package/dist/cli/range.js.map +1 -0
  39. package/dist/cli/render.js +3 -0
  40. package/dist/cli/render.js.map +1 -1
  41. package/dist/cli/strategy-render.d.ts +36 -0
  42. package/dist/cli/strategy-render.js +391 -0
  43. package/dist/cli/strategy-render.js.map +1 -0
  44. package/dist/cli/width.d.ts +18 -0
  45. package/dist/cli/width.js +71 -0
  46. package/dist/cli/width.js.map +1 -0
  47. package/dist/config/loader.js +1 -1
  48. package/dist/config/schema.d.ts +7 -0
  49. package/dist/config/schema.js +24 -0
  50. package/dist/config/schema.js.map +1 -1
  51. package/dist/core/okx-client.d.ts +9 -1
  52. package/dist/core/okx-client.js +14 -5
  53. package/dist/core/okx-client.js.map +1 -1
  54. package/dist/i18n/locale.d.ts +24 -0
  55. package/dist/i18n/locale.js +65 -0
  56. package/dist/i18n/locale.js.map +1 -0
  57. package/dist/i18n/messages.d.ts +333 -0
  58. package/dist/i18n/messages.js +660 -0
  59. package/dist/i18n/messages.js.map +1 -0
  60. package/dist/live/account-snapshot.d.ts +30 -0
  61. package/dist/live/account-snapshot.js +130 -0
  62. package/dist/live/account-snapshot.js.map +1 -0
  63. package/dist/live/cutoff-queue.d.ts +42 -0
  64. package/dist/live/cutoff-queue.js +69 -0
  65. package/dist/live/cutoff-queue.js.map +1 -0
  66. package/dist/live/execution-key.d.ts +23 -0
  67. package/dist/live/execution-key.js +31 -0
  68. package/dist/live/execution-key.js.map +1 -0
  69. package/dist/live/failures.d.ts +37 -0
  70. package/dist/live/failures.js +57 -0
  71. package/dist/live/failures.js.map +1 -0
  72. package/dist/live/gates.d.ts +65 -0
  73. package/dist/live/gates.js +136 -0
  74. package/dist/live/gates.js.map +1 -0
  75. package/dist/live/loop.d.ts +56 -0
  76. package/dist/live/loop.js +197 -0
  77. package/dist/live/loop.js.map +1 -0
  78. package/dist/live/preconditions.d.ts +48 -0
  79. package/dist/live/preconditions.js +69 -0
  80. package/dist/live/preconditions.js.map +1 -0
  81. package/dist/live/reconcile.d.ts +46 -0
  82. package/dist/live/reconcile.js +104 -0
  83. package/dist/live/reconcile.js.map +1 -0
  84. package/dist/live/runner.d.ts +57 -0
  85. package/dist/live/runner.js +160 -0
  86. package/dist/live/runner.js.map +1 -0
  87. package/dist/live/schema.d.ts +18 -0
  88. package/dist/live/schema.js +91 -0
  89. package/dist/live/schema.js.map +1 -0
  90. package/dist/live/service.d.ts +144 -0
  91. package/dist/live/service.js +303 -0
  92. package/dist/live/service.js.map +1 -0
  93. package/dist/live/session.d.ts +85 -0
  94. package/dist/live/session.js +234 -0
  95. package/dist/live/session.js.map +1 -0
  96. package/dist/live/sizing.d.ts +62 -0
  97. package/dist/live/sizing.js +79 -0
  98. package/dist/live/sizing.js.map +1 -0
  99. package/dist/live/store.d.ts +123 -0
  100. package/dist/live/store.js +350 -0
  101. package/dist/live/store.js.map +1 -0
  102. package/dist/live/types.d.ts +82 -0
  103. package/dist/live/types.js +2 -0
  104. package/dist/live/types.js.map +1 -0
  105. package/dist/market/websocket.d.ts +16 -1
  106. package/dist/market/websocket.js +60 -5
  107. package/dist/market/websocket.js.map +1 -1
  108. package/dist/mcp/server.d.ts +1 -0
  109. package/dist/mcp/server.js +15 -1
  110. package/dist/mcp/server.js.map +1 -1
  111. package/dist/network/connectivity.d.ts +9 -1
  112. package/dist/network/connectivity.js +28 -1
  113. package/dist/network/connectivity.js.map +1 -1
  114. package/dist/report/chart-script.d.ts +12 -0
  115. package/dist/report/chart-script.js +146 -0
  116. package/dist/report/chart-script.js.map +1 -0
  117. package/dist/report/compare-html.d.ts +8 -0
  118. package/dist/report/compare-html.js +254 -0
  119. package/dist/report/compare-html.js.map +1 -0
  120. package/dist/report/compare-script.d.ts +12 -0
  121. package/dist/report/compare-script.js +109 -0
  122. package/dist/report/compare-script.js.map +1 -0
  123. package/dist/report/compare.d.ts +61 -0
  124. package/dist/report/compare.js +205 -0
  125. package/dist/report/compare.js.map +1 -0
  126. package/dist/report/fetch.d.ts +20 -0
  127. package/dist/report/fetch.js +56 -0
  128. package/dist/report/fetch.js.map +1 -0
  129. package/dist/report/html.d.ts +54 -0
  130. package/dist/report/html.js +641 -0
  131. package/dist/report/html.js.map +1 -0
  132. package/dist/report/open.d.ts +42 -0
  133. package/dist/report/open.js +114 -0
  134. package/dist/report/open.js.map +1 -0
  135. package/dist/runtime/server.d.ts +16 -1
  136. package/dist/runtime/server.js +112 -9
  137. package/dist/runtime/server.js.map +1 -1
  138. package/dist/setup/installer.d.ts +1 -0
  139. package/dist/setup/installer.js +8 -0
  140. package/dist/setup/installer.js.map +1 -1
  141. package/dist/setup/wizard.d.ts +3 -0
  142. package/dist/setup/wizard.js +131 -6
  143. package/dist/setup/wizard.js.map +1 -1
  144. package/dist/strategy/constants.d.ts +23 -0
  145. package/dist/strategy/constants.js +24 -0
  146. package/dist/strategy/constants.js.map +1 -0
  147. package/dist/strategy/environment.d.ts +52 -0
  148. package/dist/strategy/environment.js +187 -0
  149. package/dist/strategy/environment.js.map +1 -0
  150. package/dist/strategy/instrument.d.ts +29 -0
  151. package/dist/strategy/instrument.js +39 -0
  152. package/dist/strategy/instrument.js.map +1 -0
  153. package/dist/strategy/optimize.d.ts +73 -0
  154. package/dist/strategy/optimize.js +113 -0
  155. package/dist/strategy/optimize.js.map +1 -0
  156. package/dist/strategy/parameter-space.d.ts +59 -0
  157. package/dist/strategy/parameter-space.js +221 -0
  158. package/dist/strategy/parameter-space.js.map +1 -0
  159. package/dist/strategy/python-bridge.d.ts +24 -0
  160. package/dist/strategy/python-bridge.js +114 -0
  161. package/dist/strategy/python-bridge.js.map +1 -0
  162. package/dist/strategy/schema.d.ts +9 -0
  163. package/dist/strategy/schema.js +91 -0
  164. package/dist/strategy/schema.js.map +1 -0
  165. package/dist/strategy/service.d.ts +138 -0
  166. package/dist/strategy/service.js +745 -0
  167. package/dist/strategy/service.js.map +1 -0
  168. package/dist/strategy/settings.d.ts +162 -0
  169. package/dist/strategy/settings.js +243 -0
  170. package/dist/strategy/settings.js.map +1 -0
  171. package/dist/strategy/store.d.ts +96 -0
  172. package/dist/strategy/store.js +367 -0
  173. package/dist/strategy/store.js.map +1 -0
  174. package/dist/strategy/templates.d.ts +11 -0
  175. package/dist/strategy/templates.js +134 -0
  176. package/dist/strategy/templates.js.map +1 -0
  177. package/dist/strategy/types.d.ts +111 -0
  178. package/dist/strategy/types.js +2 -0
  179. package/dist/strategy/types.js.map +1 -0
  180. package/dist/tools/catalog.d.ts +16 -0
  181. package/dist/tools/catalog.js +118 -17
  182. package/dist/tools/catalog.js.map +1 -1
  183. package/dist/trade/service.d.ts +12 -0
  184. package/dist/trade/service.js +24 -7
  185. package/dist/trade/service.js.map +1 -1
  186. package/dist/tui/app.d.ts +23 -0
  187. package/dist/tui/app.js +322 -0
  188. package/dist/tui/app.js.map +1 -0
  189. package/dist/tui/commands.d.ts +70 -0
  190. package/dist/tui/commands.js +313 -0
  191. package/dist/tui/commands.js.map +1 -0
  192. package/dist/tui/entries.d.ts +17 -0
  193. package/dist/tui/entries.js +24 -0
  194. package/dist/tui/entries.js.map +1 -0
  195. package/dist/tui/execute.d.ts +26 -0
  196. package/dist/tui/execute.js +664 -0
  197. package/dist/tui/execute.js.map +1 -0
  198. package/dist/tui/history.d.ts +17 -0
  199. package/dist/tui/history.js +48 -0
  200. package/dist/tui/history.js.map +1 -0
  201. package/dist/tui/index.d.ts +8 -0
  202. package/dist/tui/index.js +48 -0
  203. package/dist/tui/index.js.map +1 -0
  204. package/dist/tui/line-editor.d.ts +44 -0
  205. package/dist/tui/line-editor.js +98 -0
  206. package/dist/tui/line-editor.js.map +1 -0
  207. package/dist/tui/progress.d.ts +23 -0
  208. package/dist/tui/progress.js +46 -0
  209. package/dist/tui/progress.js.map +1 -0
  210. package/dist/tui/settings-editor.d.ts +18 -0
  211. package/dist/tui/settings-editor.js +115 -0
  212. package/dist/tui/settings-editor.js.map +1 -0
  213. package/docs/live-trading.md +455 -0
  214. package/docs/strategy-research.md +597 -0
  215. package/package.json +11 -1
  216. package/python/desic_strategy/__init__.py +34 -0
  217. package/python/desic_strategy/actions.py +158 -0
  218. package/python/desic_strategy/context.py +164 -0
  219. package/python/desic_strategy/engine.py +614 -0
  220. package/python/desic_strategy/indicators.py +159 -0
  221. package/python/desic_strategy/live.py +253 -0
  222. package/python/desic_strategy/policy.py +193 -0
  223. package/python/desic_strategy/portfolio.py +152 -0
  224. package/python/desic_strategy/report.py +319 -0
  225. package/python/desic_strategy/runner.py +574 -0
  226. package/python/desic_strategy/timeframe.py +150 -0
  227. package/python/main.py +18 -0
  228. package/skills/okx-live-trading/SKILL.md +117 -0
  229. package/skills/okx-live-trading/agents/openai.yaml +9 -0
  230. package/skills/okx-live-trading/references/lifecycle.md +128 -0
  231. package/skills/okx-strategy-research/SKILL.md +113 -0
  232. package/skills/okx-strategy-research/agents/openai.yaml +9 -0
  233. package/skills/okx-strategy-research/references/execution-semantics.md +107 -0
  234. package/skills/okx-strategy-research/references/field-traps.md +142 -0
  235. package/skills/okx-strategy-research/references/python-api.md +121 -0
  236. package/skills/okx-strategy-research/references/tools-and-data.md +192 -0
  237. 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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"}
@@ -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 === "live" ? "live" : "demo";
33
+ const environment = env.OKX_ENVIRONMENT === "demo" ? "demo" : "live";
34
34
  return RuntimeConfigSchema.parse({
35
35
  ...config,
36
36
  defaultAccount: name,
@@ -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>>;
@@ -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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,YAAY,CAAC;IAC1C,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,YAAY,CAAC;IAChD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACzD,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC;QACrB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;QAC/E,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/E,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACjE,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC7D,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;KACtE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IACf,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC;QACpB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;KACjC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC;QAC3B,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QACtD,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;KACnD,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;CAChB,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,cAAc,GAAkB,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC"}
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
- publicGet<T = Record<string, unknown>>(path: string, query?: Record<string, unknown>): Promise<T[]>;
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>;