desic-okx-agent 0.3.1 → 0.3.3

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 (50) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/i18n/messages.d.ts +27 -0
  4. package/dist/i18n/messages.js +55 -1
  5. package/dist/i18n/messages.js.map +1 -1
  6. package/dist/report/brand-font.d.ts +1 -0
  7. package/dist/report/brand-font.js +4 -0
  8. package/dist/report/brand-font.js.map +1 -0
  9. package/dist/report/chart-script.d.ts +3 -8
  10. package/dist/report/chart-script.js +735 -115
  11. package/dist/report/chart-script.js.map +1 -1
  12. package/dist/report/compare-html.d.ts +1 -6
  13. package/dist/report/compare-html.js +177 -122
  14. package/dist/report/compare-html.js.map +1 -1
  15. package/dist/report/compare-script.d.ts +1 -11
  16. package/dist/report/compare-script.js +310 -64
  17. package/dist/report/compare-script.js.map +1 -1
  18. package/dist/report/fetch.d.ts +32 -0
  19. package/dist/report/fetch.js +42 -0
  20. package/dist/report/fetch.js.map +1 -1
  21. package/dist/report/html.d.ts +1 -1
  22. package/dist/report/html.js +846 -268
  23. package/dist/report/html.js.map +1 -1
  24. package/dist/strategy/service.js +4 -1
  25. package/dist/strategy/service.js.map +1 -1
  26. package/dist/strategy/store.d.ts +12 -1
  27. package/dist/strategy/store.js +32 -1
  28. package/dist/strategy/store.js.map +1 -1
  29. package/dist/tools/catalog.js +20 -1
  30. package/dist/tools/catalog.js.map +1 -1
  31. package/dist/tui/app.js +106 -35
  32. package/dist/tui/app.js.map +1 -1
  33. package/dist/tui/commands.d.ts +33 -0
  34. package/dist/tui/commands.js +59 -14
  35. package/dist/tui/commands.js.map +1 -1
  36. package/dist/tui/file-completion.d.ts +13 -0
  37. package/dist/tui/file-completion.js +57 -0
  38. package/dist/tui/file-completion.js.map +1 -0
  39. package/docs/strategy-research.md +16 -3
  40. package/package.json +1 -1
  41. package/python/desic_strategy/context.py +23 -5
  42. package/python/desic_strategy/engine.py +4 -1
  43. package/python/desic_strategy/live.py +1 -1
  44. package/python/desic_strategy/policy.py +51 -0
  45. package/python/desic_strategy/runner.py +36 -9
  46. package/python/desic_strategy/timeframe.py +17 -0
  47. package/skills/okx-strategy-research/SKILL.md +55 -1
  48. package/skills/okx-strategy-research/agents/openai.yaml +1 -1
  49. package/skills/okx-strategy-research/references/python-api.md +7 -0
  50. package/skills/okx-strategy-research/references/tools-and-data.md +20 -0
@@ -39,7 +39,7 @@ export const COMMANDS = [
39
39
  name: "help",
40
40
  summary: "cmdHelp",
41
41
  usage: "/help [command]",
42
- args: [{ name: "command", description: "argHelpCommand", required: false }]
42
+ args: [{ name: "command", description: "argHelpCommand", required: false, completes: "command" }]
43
43
  },
44
44
  {
45
45
  name: "data",
@@ -53,7 +53,7 @@ export const COMMANDS = [
53
53
  usage: "/download <instrument> [days | range]",
54
54
  detail: "cmdDownloadDetail",
55
55
  args: [
56
- { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP" },
56
+ { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP", completes: "instrument" },
57
57
  { name: "days | range", description: "argWindow30", default: "30" }
58
58
  ]
59
59
  },
@@ -72,7 +72,7 @@ export const COMMANDS = [
72
72
  summary: "cmdValidate",
73
73
  usage: "/validate <file.py>",
74
74
  detail: "cmdValidateDetail",
75
- args: [{ name: "file.py", description: "argStrategyToCheck", required: true }]
75
+ args: [{ name: "file.py", description: "argStrategyToCheck", required: true, completes: "strategy-file" }]
76
76
  },
77
77
  {
78
78
  name: "backtest",
@@ -80,8 +80,8 @@ export const COMMANDS = [
80
80
  usage: "/backtest <file.py | setting> [instrument] [days | range]",
81
81
  detail: "cmdBacktestDetail",
82
82
  args: [
83
- { name: "file.py | setting", description: "argStrategyOrSetting", required: true },
84
- { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP" },
83
+ { name: "file.py | setting", description: "argStrategyOrSetting", required: true, completes: "strategy-file" },
84
+ { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP", completes: "instrument" },
85
85
  { name: "days | range", description: "argWindow30", default: "30" }
86
86
  ]
87
87
  },
@@ -91,8 +91,8 @@ export const COMMANDS = [
91
91
  usage: "/optimize <file.py | report> [instrument] [days | range] [space.json] [budget]",
92
92
  detail: "cmdOptimizeDetail",
93
93
  args: [
94
- { name: "file.py | report", description: "argStrategyOrReport", required: true },
95
- { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP" },
94
+ { name: "file.py | report", description: "argStrategyOrReport", required: true, completes: "strategy-file" },
95
+ { name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP", completes: "instrument" },
96
96
  { name: "days | range", description: "argWindow90", default: "90" },
97
97
  { name: "space.json", description: "argSpaceFile", default: "space.json" },
98
98
  { name: "budget", description: "argBudget", default: "100" }
@@ -104,7 +104,7 @@ export const COMMANDS = [
104
104
  usage: "/compare <runId> <runId> [runId...] [--no-open]",
105
105
  detail: "cmdCompareDetail",
106
106
  args: [
107
- { name: "runId runId ...", description: "argRunsToCompare", required: true },
107
+ { name: "runId runId ...", description: "argRunsToCompare", required: true, completes: "run" },
108
108
  { name: "--no-open", description: "argNoOpen", required: false }
109
109
  ]
110
110
  },
@@ -123,7 +123,7 @@ export const COMMANDS = [
123
123
  summary: "cmdMarket",
124
124
  usage: "/market [demo|live]",
125
125
  detail: "cmdMarketDetail",
126
- args: [{ name: "demo | live", description: "argMarketEnv", required: false }]
126
+ args: [{ name: "demo | live", description: "argMarketEnv", required: false, completes: "market-environment" }]
127
127
  },
128
128
  {
129
129
  name: "settings",
@@ -135,14 +135,14 @@ export const COMMANDS = [
135
135
  name: "coverage",
136
136
  summary: "cmdCoverage",
137
137
  usage: "/coverage <instrument>",
138
- args: [{ name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP" }],
138
+ args: [{ name: "instrument", description: "argInstrument", default: "BTC-USDT-SWAP", completes: "instrument" }],
139
139
  detail: "cmdCoverageDetail"
140
140
  },
141
141
  {
142
142
  name: "delete",
143
143
  summary: "cmdDelete",
144
144
  usage: "/delete <runId>",
145
- args: [{ name: "runId", description: "argRunToDelete", required: true }],
145
+ args: [{ name: "runId", description: "argRunToDelete", required: true, completes: "run" }],
146
146
  detail: "cmdDeleteDetail"
147
147
  },
148
148
  {
@@ -156,7 +156,7 @@ export const COMMANDS = [
156
156
  summary: "cmdReport",
157
157
  usage: "/report <runId>",
158
158
  args: [
159
- { name: "runId", description: "argRunToOpen", required: true },
159
+ { name: "runId", description: "argRunToOpen", required: true, completes: "run" },
160
160
  { name: "--no-open", description: "argNoOpen", required: false }
161
161
  ]
162
162
  },
@@ -164,7 +164,7 @@ export const COMMANDS = [
164
164
  name: "cancel",
165
165
  summary: "cmdCancel",
166
166
  usage: "/cancel <runId>",
167
- args: [{ name: "runId", description: "argRunToCancel", required: true }]
167
+ args: [{ name: "runId", description: "argRunToCancel", required: true, completes: "run" }]
168
168
  },
169
169
  {
170
170
  name: "env",
@@ -182,7 +182,7 @@ export const COMMANDS = [
182
182
  summary: "cmdLang",
183
183
  usage: "/lang [en|zh]",
184
184
  detail: "cmdLangDetail",
185
- args: [{ name: "locale", description: "argLocale", required: false }]
185
+ args: [{ name: "locale", description: "argLocale", required: false, completes: "locale" }]
186
186
  },
187
187
  {
188
188
  name: "clear",
@@ -267,6 +267,51 @@ export function argumentIndex(input) {
267
267
  return -1;
268
268
  return /\s$/.test(input) ? parts.length - 1 : parts.length - 2;
269
269
  }
270
+ /**
271
+ * Whether the argument being typed has a completable value, and what to match on.
272
+ *
273
+ * Returns the request rather than the candidates: the shell holds the runtime client
274
+ * and this stays a pure function of the input, testable without a terminal or a
275
+ * running runtime.
276
+ */
277
+ export function valueCompletion(input) {
278
+ const parsed = parseCommand(input);
279
+ if (!parsed?.known)
280
+ return null;
281
+ const spec = commandByName(parsed.name);
282
+ if (!spec?.args?.length)
283
+ return null;
284
+ if (!/\s/.test(input))
285
+ return null;
286
+ const active = argumentIndex(input);
287
+ const argument = active >= 0 ? spec.args[active] : undefined;
288
+ // A trailing space means this argument has not been started, so everything matches.
289
+ const started = !/\s$/.test(input);
290
+ const prefix = started ? (parsed.args[active] ?? "") : "";
291
+ const head = started ? input.slice(0, input.length - prefix.length) : input;
292
+ const source = parsed.name === "compare" && active >= 0 && !prefix.startsWith("-")
293
+ ? "run"
294
+ : parsed.name === "optimize" &&
295
+ active === 1 &&
296
+ parsed.args[0]?.toLowerCase() === "report" &&
297
+ !prefix.startsWith("-")
298
+ ? "run"
299
+ : argument?.completes;
300
+ return source ? { source, prefix, head } : null;
301
+ }
302
+ /**
303
+ * Narrows candidate values to those matching a partial argument.
304
+ *
305
+ * Case-insensitive and anchored: typing `BT` offers `BTC-USDT-SWAP`, and matching
306
+ * anywhere in the name would put `ETH-BTC-SWAP` above it for no reason a user typing
307
+ * a prefix would expect.
308
+ */
309
+ export function matchValues(candidates, prefix) {
310
+ if (!prefix)
311
+ return [...candidates];
312
+ const lower = prefix.toLowerCase();
313
+ return candidates.filter((candidate) => candidate.toLowerCase().startsWith(lower));
314
+ }
270
315
  /**
271
316
  * Inline hint for a recognized command.
272
317
  *
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/tui/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/tui/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface FileDiscoveryOptions {
2
+ maxDepth?: number;
3
+ maxDirectories?: number;
4
+ maxFiles?: number;
5
+ }
6
+ /**
7
+ * Finds strategy-shaped Python files below a working directory.
8
+ *
9
+ * The walk is deliberately bounded and does not follow symlinks. Completion runs
10
+ * while the user is typing, so a large checkout or a symlink cycle must not turn a
11
+ * convenience into an unbounded filesystem crawl.
12
+ */
13
+ export declare function discoverPythonFiles(root?: string, options?: FileDiscoveryOptions): Promise<string[]>;
@@ -0,0 +1,57 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const IGNORED_DIRECTORIES = new Set([
4
+ ".git",
5
+ ".hg",
6
+ ".svn",
7
+ ".tox",
8
+ ".venv",
9
+ "__pycache__",
10
+ "build",
11
+ "dist",
12
+ "node_modules",
13
+ "target",
14
+ "venv"
15
+ ]);
16
+ /**
17
+ * Finds strategy-shaped Python files below a working directory.
18
+ *
19
+ * The walk is deliberately bounded and does not follow symlinks. Completion runs
20
+ * while the user is typing, so a large checkout or a symlink cycle must not turn a
21
+ * convenience into an unbounded filesystem crawl.
22
+ */
23
+ export async function discoverPythonFiles(root = process.cwd(), options = {}) {
24
+ const maxDepth = options.maxDepth ?? 5;
25
+ const maxDirectories = options.maxDirectories ?? 500;
26
+ const maxFiles = options.maxFiles ?? 500;
27
+ const pending = [{ absolute: path.resolve(root), depth: 0 }];
28
+ const files = [];
29
+ let visitedDirectories = 0;
30
+ while (pending.length > 0 && visitedDirectories < maxDirectories && files.length < maxFiles) {
31
+ const current = pending.shift();
32
+ visitedDirectories += 1;
33
+ const entries = await readdir(current.absolute, { withFileTypes: true }).catch(() => []);
34
+ entries.sort((left, right) => left.name.localeCompare(right.name));
35
+ for (const entry of entries) {
36
+ if (files.length >= maxFiles)
37
+ break;
38
+ if (entry.isSymbolicLink())
39
+ continue;
40
+ const absolute = path.join(current.absolute, entry.name);
41
+ if (entry.isDirectory()) {
42
+ if (current.depth >= maxDepth || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name))
43
+ continue;
44
+ pending.push({ absolute, depth: current.depth + 1 });
45
+ continue;
46
+ }
47
+ if (!entry.isFile() || !entry.name.toLowerCase().endsWith(".py"))
48
+ continue;
49
+ const relative = path.relative(root, absolute).split(path.sep).join("/");
50
+ // The TUI parser is whitespace-delimited and does not yet implement quoting.
51
+ if (relative && !/\s/.test(relative))
52
+ files.push(relative);
53
+ }
54
+ }
55
+ return files.sort((left, right) => left.localeCompare(right));
56
+ }
57
+ //# sourceMappingURL=file-completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-completion.js","sourceRoot":"","sources":["../../src/tui/file-completion.ts"],"names":[],"mappings":"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"}
@@ -199,9 +199,7 @@ desic-okx strategy validate --file ema.py
199
199
 
200
200
  ### 多周期
201
201
 
202
- ```bash
203
- desic-okx strategy backtest --file s.py --inst BTC-USDT-SWAP --intervals 30m,1H
204
- ```
202
+ **直接写就行,不需要声明。** 引擎会读你的源码,把 `ctx.market.bars(..., "30m")` 里出现的周期自动加进来:
205
203
 
206
204
  ```python
207
205
  buckets = ctx.market.bars(ctx.instrument_id, "30m", lookback=2)
@@ -209,6 +207,19 @@ if not buckets[-1].confirmed:
209
207
  return ctx.no_action("等 30m 收线")
210
208
  ```
211
209
 
210
+ ```bash
211
+ desic-okx strategy backtest --file s.py --inst BTC-USDT-SWAP # 30m 自动派生
212
+ ```
213
+
214
+ 报告的 `assumptions.intervals` 记录的是**实际派生的**那些,不是你请求的 —— 所以你能核对引擎理解得对不对。
215
+
216
+ `--intervals` 仍然保留,用于**周期名是算出来的**情况 —— 那种源码里读不出来:
217
+
218
+ ```python
219
+ chosen = ctx.params.get("tf", "15m") # 读不出来
220
+ ctx.market.bars(ctx.instrument_id, chosen) # 需要 --intervals 15m
221
+ ```
222
+
212
223
  注意:`ctx.indicators` 只接受 `1m`。高周期的当前桶在确认前还可能被修正,用它做增量指标状态,缓存值会悄悄依赖于"第一次算的时间点"。
213
224
 
214
225
  ### 只要尾部就一定传 `lookback`
@@ -520,6 +531,8 @@ MCP 工具(`desic-okx setup` 会自动为 Codex 和 Claude Code 装好):
520
531
  | `strategy_run_optimize` | 参数搜索,入队 |
521
532
  | `strategy_get_optimization` | 排名后的候选表,含训练/验证指标 |
522
533
  | `strategy_compare_runs` | 多运行对比,含差异参数与警告 |
534
+ | `strategy_open_report` | 生成单次运行的 HTML 报告并在浏览器打开 |
535
+ | `strategy_open_comparison` | 同上,多运行对比,叠加权益曲线 |
523
536
  | `strategy_get_run` | 状态、进度、汇总指标 |
524
537
  | `strategy_get_run_equity` / `_trades` / `_actions` | 分页读明细 |
525
538
  | `strategy_settings` / `_update` | 读写回测参数 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "desic-okx-agent",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Independent Desic runtime, MCP server, CLI, and agent skills for OKX",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,19 +24,24 @@ class ContextError(Exception):
24
24
  class MarketView:
25
25
  """Point-in-time K-line access across derived timeframes."""
26
26
 
27
- __slots__ = ("_aggregates", "_instrument_id", "_minutes", "_visible")
27
+ __slots__ = ("_aggregates", "_aggregators", "_instrument_id", "_minutes", "_visible")
28
28
 
29
29
  def __init__(
30
30
  self,
31
31
  instrument_id: str,
32
32
  minutes: list[Bar],
33
33
  visible: int,
34
- aggregates: Mapping[str, tuple[Bar, ...]],
34
+ aggregates: Mapping[str, tuple[Bar, ...]] | None = None,
35
+ aggregators: Mapping[str, TimeframeAggregator] | None = None,
35
36
  ) -> None:
36
37
  self._instrument_id = instrument_id
37
38
  self._minutes = minutes
38
39
  self._visible = visible
39
- self._aggregates = aggregates
40
+ # Either form works. `aggregators` applies a lookback before the tuple is built,
41
+ # which is the cheap path; `aggregates` keeps a caller that already holds
42
+ # snapshots working unchanged.
43
+ self._aggregates = aggregates or {}
44
+ self._aggregators = aggregators or {}
40
45
 
41
46
  def bars(self, instrument_id: str, interval: str = "1m", lookback: int | None = None) -> tuple[Bar, ...]:
42
47
  if instrument_id != self._instrument_id:
@@ -57,11 +62,14 @@ class MarketView:
57
62
  stop = self._visible
58
63
  start = 0 if lookback is None else max(0, stop - lookback)
59
64
  return tuple(self._minutes[start:stop])
65
+ # The aggregator path slices before building the tuple, so a lookback costs the
66
+ # window rather than every bucket accumulated so far.
67
+ aggregator = self._aggregators.get(interval)
68
+ if aggregator is not None:
69
+ return aggregator.tail(lookback)
60
70
  found = self._aggregates.get(interval)
61
71
  if found is None:
62
72
  raise ContextError(f"Series '{interval}' is not available in this run")
63
- # Aggregates are already immutable tuples ending at the cutoff, so slicing one
64
- # copies only what was asked for.
65
73
  return found if lookback is None else found[-lookback:]
66
74
 
67
75
 
@@ -169,3 +177,13 @@ class SeriesSet:
169
177
 
170
178
  def snapshot(self) -> dict[str, tuple[Bar, ...]]:
171
179
  return {interval: agg.snapshot() for interval, agg in self._aggregators.items()}
180
+
181
+ @property
182
+ def aggregators(self) -> Mapping[str, TimeframeAggregator]:
183
+ """The live aggregators, for a reader that wants only a tail.
184
+
185
+ Handed over instead of a snapshot so the slice happens before the tuple is
186
+ built. Materializing every bucket on every bar is the cost this avoids; the
187
+ aggregators are only read through `tail`, which returns a new tuple.
188
+ """
189
+ return self._aggregators
@@ -236,7 +236,10 @@ class Engine:
236
236
 
237
237
  def _context(self, bar: Bar, visible: int, bars: list[Bar], series: SeriesSet) -> StrategyContext:
238
238
  instrument = self._config.instrument
239
- market = MarketView(instrument.inst_id, bars, visible, series.snapshot())
239
+ # Aggregators rather than snapshots: this runs once per bar, and materializing
240
+ # every derived bucket here cost 14.5 us/bar at 4,000 buckets against 1.9 us/bar
241
+ # for the tail a strategy actually reads.
242
+ market = MarketView(instrument.inst_id, bars, visible, aggregators=series.aggregators)
240
243
  return StrategyContext(
241
244
  kind="bar",
242
245
  as_of_ms=bar.close_time_ms,
@@ -133,7 +133,7 @@ class LiveSession:
133
133
  instrument_id=self._instrument_id,
134
134
  interval="1m",
135
135
  bar=bar,
136
- market=MarketView(self._instrument_id, self._bars, len(self._bars), self._series.snapshot()),
136
+ market=MarketView(self._instrument_id, self._bars, len(self._bars), aggregators=self._series.aggregators),
137
137
  portfolio=portfolio,
138
138
  params=self._params,
139
139
  indicators=IndicatorView(self._series.indicators, self._instrument_id, len(self._bars)),
@@ -191,3 +191,54 @@ def _check_handlers(tree: ast.Module) -> list[PolicyViolation]:
191
191
  )
192
192
  )
193
193
  return found
194
+
195
+
196
+ def discover_intervals(source: str) -> tuple[list[str], bool]:
197
+ """Finds the higher timeframes a strategy reads, from the source alone.
198
+
199
+ Higher timeframes are aggregated incrementally: an aggregator has to see every
200
+ one-minute bar from the start, so one cannot be created partway through a run.
201
+ Declaring them was therefore a real requirement — but the declaration duplicated
202
+ something the source already states, and getting it wrong failed at bar one with
203
+ "Series '15m' is not available in this run".
204
+
205
+ Returns the intervals found as literals, and whether any call could not be read
206
+ statically. A `bars(id, chosen)` where `chosen` is computed cannot be resolved
207
+ here, so the caller keeps the explicit list as the way to cover that.
208
+
209
+ Deliberately syntactic. It matches `.bars(...)` by attribute name and takes only
210
+ string literals in the interval position, so it never runs strategy code and
211
+ cannot be tricked into reporting an interval that will not be requested. Over-
212
+ reporting is harmless (an unused aggregator costs one pass over the bars);
213
+ under-reporting is what the returned flag warns about.
214
+ """
215
+ try:
216
+ tree = ast.parse(source)
217
+ except SyntaxError:
218
+ return [], False
219
+
220
+ found: set[str] = set()
221
+ dynamic = False
222
+ for node in ast.walk(tree):
223
+ if not isinstance(node, ast.Call):
224
+ continue
225
+ function = node.func
226
+ if not isinstance(function, ast.Attribute) or function.attr != "bars":
227
+ continue
228
+ argument = _interval_argument(node)
229
+ if argument is None:
230
+ continue
231
+ if isinstance(argument, ast.Constant) and isinstance(argument.value, str):
232
+ found.add(argument.value)
233
+ else:
234
+ dynamic = True
235
+ return sorted(item for item in found if item != "1m"), dynamic
236
+
237
+
238
+ def _interval_argument(node: ast.Call) -> ast.expr | None:
239
+ """The interval argument of a `bars` call, positional or by keyword."""
240
+ for keyword in node.keywords:
241
+ if keyword.arg == "interval":
242
+ return keyword.value
243
+ # bars(instrument_id, interval, ...) — the instrument is first.
244
+ return node.args[1] if len(node.args) > 1 else None
@@ -21,7 +21,7 @@ from .actions import StrategyError
21
21
  from .engine import Costs, Engine, Instrument, RunConfig, Sizing
22
22
  from .indicators import IndicatorError
23
23
  from .live import LiveSession, parse_portfolio
24
- from .policy import validate_source
24
+ from .policy import discover_intervals, validate_source
25
25
  from .report import build_report, calculate_metrics
26
26
  from .timeframe import Bar, DataContractError, ONE_MINUTE_MS, interval_ms
27
27
 
@@ -170,7 +170,7 @@ def _backtest(request: dict[str, Any]) -> dict[str, Any]:
170
170
  bars = _parse_bars(request.get("bars"))
171
171
  config = _parse_config(request)
172
172
  params = dict(request.get("params") or {})
173
- intervals = _parse_intervals(request.get("intervals"))
173
+ intervals = _parse_intervals(request.get("intervals"), source)
174
174
  handlers = _load_handlers(source)
175
175
 
176
176
  total = len(bars)
@@ -182,6 +182,10 @@ def _backtest(request: dict[str, Any]) -> dict[str, Any]:
182
182
  "protocol": PROTOCOL_VERSION,
183
183
  "barCount": total,
184
184
  "preloadBars": config.preload_bars,
185
+ # Reported because the engine resolves this, not the caller: intervals read from
186
+ # the source are added to whatever was requested, so the request is no longer
187
+ # what the run used. A report naming the request would state the wrong thing.
188
+ "intervals": intervals,
185
189
  "report": report,
186
190
  }
187
191
 
@@ -224,7 +228,7 @@ def _live(request: dict[str, Any]) -> int:
224
228
  _emit({"ok": False, "error": {"code": "bad_request", "message": "instrument.instId is required"}})
225
229
  return 2
226
230
  instrument_id = str(instrument_raw["instId"])
227
- intervals = _parse_intervals(request.get("intervals"))
231
+ intervals = _parse_intervals(request.get("intervals"), source)
228
232
  handlers = _load_handlers(source)
229
233
  session = LiveSession(instrument_id, handlers, dict(request.get("params") or {}), intervals)
230
234
 
@@ -309,7 +313,7 @@ def _optimize(request: dict[str, Any]) -> dict[str, Any]:
309
313
 
310
314
  bars = _parse_bars(request.get("bars"))
311
315
  base_config = _parse_config(request)
312
- intervals = _parse_intervals(request.get("intervals"))
316
+ intervals = _parse_intervals(request.get("intervals"), source)
313
317
  handlers = _load_handlers(source)
314
318
  segments = _parse_segments(request.get("segments"), len(bars))
315
319
  candidates = _parse_candidates(request.get("candidates"))
@@ -470,17 +474,40 @@ def _parse_bars(value: Any) -> list[Bar]:
470
474
  return bars
471
475
 
472
476
 
473
- def _parse_intervals(value: Any) -> list[str]:
474
- if value is None:
475
- return ["1m"]
476
- if not isinstance(value, list):
477
+ def _parse_intervals(value: Any, source: str | None = None) -> list[str]:
478
+ """Resolves which timeframes to aggregate for a run.
479
+
480
+ Anything the request names is honoured, and anything the source visibly reads is
481
+ added to it. Requiring the declaration meant a strategy calling
482
+ `ctx.market.bars(id, "15m")` failed on its first bar over a fact its own source
483
+ already stated. Reading it instead removes a step that could only be got wrong.
484
+
485
+ The request still matters. A timeframe reached through a computed name cannot be
486
+ found by reading the source, so naming it explicitly remains the way to cover
487
+ that; and an interval named but never used costs only one pass over the bars.
488
+ """
489
+ if value is not None and not isinstance(value, list):
477
490
  raise DataContractError("'intervals' must be an array of interval names")
478
491
  intervals = ["1m"]
479
- for item in value:
492
+ for item in value or []:
480
493
  name = str(item)
481
494
  interval_ms(name)
482
495
  if name not in intervals:
483
496
  intervals.append(name)
497
+ if source is not None:
498
+ discovered, _ = discover_intervals(source)
499
+ for name in discovered:
500
+ # Validated like a declared one, but named as read from the source: the
501
+ # strategy would reach that line and fail anyway, so failing now with the
502
+ # reason is strictly better than failing on bar one without it.
503
+ try:
504
+ interval_ms(name)
505
+ except DataContractError as error:
506
+ raise DataContractError(
507
+ f"The strategy reads interval '{name}', which cannot be aggregated. {error}"
508
+ ) from error
509
+ if name not in intervals:
510
+ intervals.append(name)
484
511
  return intervals
485
512
 
486
513
 
@@ -139,6 +139,23 @@ class TimeframeAggregator:
139
139
  return tuple(self._completed)
140
140
  return (*self._completed, self._current)
141
141
 
142
+ def tail(self, lookback: int | None) -> tuple[Bar, ...]:
143
+ """The last `lookback` buckets, or all of them when it is None.
144
+
145
+ Sliced before the tuple is built. `snapshot()` copies every accumulated bucket,
146
+ and it is called once per one-minute bar, so a 180-day run over 15m and 1H
147
+ rebuilt ~21,600 elements 260,000 times. Measured at 4,000 buckets: 14.5 us/bar
148
+ for the full snapshot against 1.9 us/bar for a 96-bucket tail.
149
+ """
150
+ if lookback is None:
151
+ return self.snapshot()
152
+ if self._current is None:
153
+ return tuple(self._completed[-lookback:])
154
+ # The forming bucket occupies one slot of the requested window.
155
+ if lookback <= 1:
156
+ return (self._current,)
157
+ return (*self._completed[-(lookback - 1):], self._current)
158
+
142
159
  def latest(self) -> Bar | None:
143
160
  return self._current
144
161