openalgo-script 0.2.0 → 0.5.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 (357) hide show
  1. package/CHANGELOG.md +1198 -0
  2. package/README.md +127 -40
  3. package/dist/adapters/charts/driving.d.ts +50 -0
  4. package/dist/adapters/charts/driving.d.ts.map +1 -0
  5. package/dist/adapters/charts/driving.js +57 -0
  6. package/dist/adapters/charts/driving.js.map +1 -0
  7. package/dist/adapters/charts/run.d.ts +20 -0
  8. package/dist/adapters/charts/run.d.ts.map +1 -1
  9. package/dist/adapters/charts/run.js +83 -16
  10. package/dist/adapters/charts/run.js.map +1 -1
  11. package/dist/adapters/charts/surfaces.d.ts +17 -0
  12. package/dist/adapters/charts/surfaces.d.ts.map +1 -1
  13. package/dist/adapters/charts/tables.js +82 -0
  14. package/dist/adapters/charts/tables.js.map +1 -1
  15. package/dist/adapters/charts/venue.d.ts +73 -0
  16. package/dist/adapters/charts/venue.d.ts.map +1 -0
  17. package/dist/adapters/charts/venue.js +104 -0
  18. package/dist/adapters/charts/venue.js.map +1 -0
  19. package/dist/adapters/codemirror/commands.d.ts +14 -0
  20. package/dist/adapters/codemirror/commands.d.ts.map +1 -0
  21. package/dist/adapters/codemirror/commands.js +52 -0
  22. package/dist/adapters/codemirror/commands.js.map +1 -0
  23. package/dist/adapters/codemirror/completion.d.ts +15 -0
  24. package/dist/adapters/codemirror/completion.d.ts.map +1 -0
  25. package/dist/adapters/codemirror/completion.js +64 -0
  26. package/dist/adapters/codemirror/completion.js.map +1 -0
  27. package/dist/adapters/codemirror/contract.d.ts +156 -0
  28. package/dist/adapters/codemirror/contract.d.ts.map +1 -0
  29. package/dist/adapters/codemirror/contract.js +42 -0
  30. package/dist/adapters/codemirror/contract.js.map +1 -0
  31. package/dist/adapters/codemirror/index.d.ts +43 -0
  32. package/dist/adapters/codemirror/index.d.ts.map +1 -0
  33. package/dist/adapters/codemirror/index.js +8 -0
  34. package/dist/adapters/codemirror/index.js.map +1 -0
  35. package/dist/adapters/codemirror/lint.d.ts +17 -0
  36. package/dist/adapters/codemirror/lint.d.ts.map +1 -0
  37. package/dist/adapters/codemirror/lint.js +62 -0
  38. package/dist/adapters/codemirror/lint.js.map +1 -0
  39. package/dist/adapters/codemirror/positions.d.ts +16 -0
  40. package/dist/adapters/codemirror/positions.d.ts.map +1 -0
  41. package/dist/adapters/codemirror/positions.js +65 -0
  42. package/dist/adapters/codemirror/positions.js.map +1 -0
  43. package/dist/adapters/codemirror/stream.d.ts +23 -0
  44. package/dist/adapters/codemirror/stream.d.ts.map +1 -0
  45. package/dist/adapters/codemirror/stream.js +70 -0
  46. package/dist/adapters/codemirror/stream.js.map +1 -0
  47. package/dist/adapters/codemirror/tokens.d.ts +44 -0
  48. package/dist/adapters/codemirror/tokens.d.ts.map +1 -0
  49. package/dist/adapters/codemirror/tokens.js +34 -0
  50. package/dist/adapters/codemirror/tokens.js.map +1 -0
  51. package/dist/adapters/codemirror/tooltips.d.ts +35 -0
  52. package/dist/adapters/codemirror/tooltips.d.ts.map +1 -0
  53. package/dist/adapters/codemirror/tooltips.js +108 -0
  54. package/dist/adapters/codemirror/tooltips.js.map +1 -0
  55. package/dist/core/accounting/analysis.d.ts +111 -0
  56. package/dist/core/accounting/analysis.d.ts.map +1 -0
  57. package/dist/core/accounting/analysis.js +123 -0
  58. package/dist/core/accounting/analysis.js.map +1 -0
  59. package/dist/core/accounting/charges.d.ts +136 -0
  60. package/dist/core/accounting/charges.d.ts.map +1 -0
  61. package/dist/core/accounting/charges.js +362 -0
  62. package/dist/core/accounting/charges.js.map +1 -0
  63. package/dist/core/accounting/equity.d.ts +191 -0
  64. package/dist/core/accounting/equity.d.ts.map +1 -0
  65. package/dist/core/accounting/equity.js +167 -0
  66. package/dist/core/accounting/equity.js.map +1 -0
  67. package/dist/core/accounting/index.d.ts +46 -0
  68. package/dist/core/accounting/index.d.ts.map +1 -0
  69. package/dist/core/accounting/index.js +37 -0
  70. package/dist/core/accounting/index.js.map +1 -0
  71. package/dist/core/accounting/markers.d.ts +43 -0
  72. package/dist/core/accounting/markers.d.ts.map +1 -0
  73. package/dist/core/accounting/markers.js +64 -0
  74. package/dist/core/accounting/markers.js.map +1 -0
  75. package/dist/core/accounting/monthly.d.ts +52 -0
  76. package/dist/core/accounting/monthly.d.ts.map +1 -0
  77. package/dist/core/accounting/monthly.js +99 -0
  78. package/dist/core/accounting/monthly.js.map +1 -0
  79. package/dist/core/accounting/report.d.ts +41 -0
  80. package/dist/core/accounting/report.d.ts.map +1 -0
  81. package/dist/core/accounting/report.js +65 -0
  82. package/dist/core/accounting/report.js.map +1 -0
  83. package/dist/core/accounting/shapes.d.ts +70 -0
  84. package/dist/core/accounting/shapes.d.ts.map +1 -0
  85. package/dist/core/accounting/shapes.js +21 -0
  86. package/dist/core/accounting/shapes.js.map +1 -0
  87. package/dist/core/accounting/statistics.d.ts +87 -0
  88. package/dist/core/accounting/statistics.d.ts.map +1 -0
  89. package/dist/core/accounting/statistics.js +268 -0
  90. package/dist/core/accounting/statistics.js.map +1 -0
  91. package/dist/core/accounting/trades.d.ts +118 -0
  92. package/dist/core/accounting/trades.d.ts.map +1 -0
  93. package/dist/core/accounting/trades.js +186 -0
  94. package/dist/core/accounting/trades.js.map +1 -0
  95. package/dist/core/backtest/case.d.ts +60 -0
  96. package/dist/core/backtest/case.d.ts.map +1 -0
  97. package/dist/core/backtest/case.js +319 -0
  98. package/dist/core/backtest/case.js.map +1 -0
  99. package/dist/core/backtest/compare.d.ts +38 -0
  100. package/dist/core/backtest/compare.d.ts.map +1 -0
  101. package/dist/core/backtest/compare.js +191 -0
  102. package/dist/core/backtest/compare.js.map +1 -0
  103. package/dist/core/backtest/declaration.d.ts +52 -0
  104. package/dist/core/backtest/declaration.d.ts.map +1 -0
  105. package/dist/core/backtest/declaration.js +48 -0
  106. package/dist/core/backtest/declaration.js.map +1 -0
  107. package/dist/core/backtest/deliver.d.ts +93 -0
  108. package/dist/core/backtest/deliver.d.ts.map +1 -0
  109. package/dist/core/backtest/deliver.js +94 -0
  110. package/dist/core/backtest/deliver.js.map +1 -0
  111. package/dist/core/backtest/drive.d.ts +87 -0
  112. package/dist/core/backtest/drive.d.ts.map +1 -0
  113. package/dist/core/backtest/drive.js +312 -0
  114. package/dist/core/backtest/drive.js.map +1 -0
  115. package/dist/core/backtest/index.d.ts +58 -0
  116. package/dist/core/backtest/index.d.ts.map +1 -0
  117. package/dist/core/backtest/index.js +47 -0
  118. package/dist/core/backtest/index.js.map +1 -0
  119. package/dist/core/backtest/range.d.ts +84 -0
  120. package/dist/core/backtest/range.d.ts.map +1 -0
  121. package/dist/core/backtest/range.js +90 -0
  122. package/dist/core/backtest/range.js.map +1 -0
  123. package/dist/core/backtest/record.d.ts +299 -0
  124. package/dist/core/backtest/record.d.ts.map +1 -0
  125. package/dist/core/backtest/record.js +243 -0
  126. package/dist/core/backtest/record.js.map +1 -0
  127. package/dist/core/backtest/replay.d.ts +48 -0
  128. package/dist/core/backtest/replay.d.ts.map +1 -0
  129. package/dist/core/backtest/replay.js +137 -0
  130. package/dist/core/backtest/replay.js.map +1 -0
  131. package/dist/core/backtest/resting.d.ts +62 -0
  132. package/dist/core/backtest/resting.d.ts.map +1 -0
  133. package/dist/core/backtest/resting.js +59 -0
  134. package/dist/core/backtest/resting.js.map +1 -0
  135. package/dist/core/backtest/settings.d.ts +117 -0
  136. package/dist/core/backtest/settings.d.ts.map +1 -0
  137. package/dist/core/backtest/settings.js +207 -0
  138. package/dist/core/backtest/settings.js.map +1 -0
  139. package/dist/core/backtest/simulate.d.ts +258 -0
  140. package/dist/core/backtest/simulate.d.ts.map +1 -0
  141. package/dist/core/backtest/simulate.js +335 -0
  142. package/dist/core/backtest/simulate.js.map +1 -0
  143. package/dist/core/catalogue/catalogue.generated.d.ts +66 -0
  144. package/dist/core/catalogue/catalogue.generated.d.ts.map +1 -1
  145. package/dist/core/catalogue/catalogue.generated.js +6 -0
  146. package/dist/core/catalogue/catalogue.generated.js.map +1 -1
  147. package/dist/core/catalogue/values.generated.d.ts +24 -0
  148. package/dist/core/catalogue/values.generated.d.ts.map +1 -1
  149. package/dist/core/check/index.d.ts +2 -1
  150. package/dist/core/check/index.d.ts.map +1 -1
  151. package/dist/core/check/index.js +1 -1
  152. package/dist/core/check/index.js.map +1 -1
  153. package/dist/core/check/library-orders.js +2 -2
  154. package/dist/core/check/library-orders.js.map +1 -1
  155. package/dist/core/check/library-prose.generated.d.ts +16 -0
  156. package/dist/core/check/library-prose.generated.d.ts.map +1 -0
  157. package/dist/core/check/library-prose.generated.js +353 -0
  158. package/dist/core/check/library-prose.generated.js.map +1 -0
  159. package/dist/core/check/surface.d.ts +24 -0
  160. package/dist/core/check/surface.d.ts.map +1 -1
  161. package/dist/core/check/surface.js +29 -0
  162. package/dist/core/check/surface.js.map +1 -1
  163. package/dist/core/emit/canonical.d.ts +22 -8
  164. package/dist/core/emit/canonical.d.ts.map +1 -1
  165. package/dist/core/emit/canonical.js +67 -6
  166. package/dist/core/emit/canonical.js.map +1 -1
  167. package/dist/core/emit/defaults.d.ts +35 -16
  168. package/dist/core/emit/defaults.d.ts.map +1 -1
  169. package/dist/core/emit/defaults.js +66 -0
  170. package/dist/core/emit/defaults.js.map +1 -1
  171. package/dist/core/emit/index.d.ts +2 -0
  172. package/dist/core/emit/index.d.ts.map +1 -1
  173. package/dist/core/emit/index.js +2 -0
  174. package/dist/core/emit/index.js.map +1 -1
  175. package/dist/core/engine/arithmetic.d.ts +6 -25
  176. package/dist/core/engine/arithmetic.d.ts.map +1 -1
  177. package/dist/core/engine/arithmetic.js +48 -3
  178. package/dist/core/engine/arithmetic.js.map +1 -1
  179. package/dist/core/engine/index.d.ts +2 -2
  180. package/dist/core/engine/index.d.ts.map +1 -1
  181. package/dist/core/engine/index.js +2 -2
  182. package/dist/core/engine/index.js.map +1 -1
  183. package/dist/core/engine/library/arrays.d.ts.map +1 -1
  184. package/dist/core/engine/library/arrays.js +8 -2
  185. package/dist/core/engine/library/arrays.js.map +1 -1
  186. package/dist/core/engine/library/code-points.d.ts +40 -0
  187. package/dist/core/engine/library/code-points.d.ts.map +1 -0
  188. package/dist/core/engine/library/code-points.js +74 -0
  189. package/dist/core/engine/library/code-points.js.map +1 -0
  190. package/dist/core/engine/library/index.d.ts +5 -0
  191. package/dist/core/engine/library/index.d.ts.map +1 -1
  192. package/dist/core/engine/library/index.js +5 -0
  193. package/dist/core/engine/library/index.js.map +1 -1
  194. package/dist/core/engine/library/text.d.ts.map +1 -1
  195. package/dist/core/engine/library/text.js +51 -34
  196. package/dist/core/engine/library/text.js.map +1 -1
  197. package/dist/core/engine/load.d.ts +35 -1
  198. package/dist/core/engine/load.d.ts.map +1 -1
  199. package/dist/core/engine/load.js +63 -0
  200. package/dist/core/engine/load.js.map +1 -1
  201. package/dist/core/engine/verify-tables.d.ts.map +1 -1
  202. package/dist/core/engine/verify-tables.js +41 -0
  203. package/dist/core/engine/verify-tables.js.map +1 -1
  204. package/dist/core/index.d.ts +43 -4
  205. package/dist/core/index.d.ts.map +1 -1
  206. package/dist/core/index.js +23 -2
  207. package/dist/core/index.js.map +1 -1
  208. package/dist/core/stdlib/index.d.ts +1 -1
  209. package/dist/core/stdlib/index.d.ts.map +1 -1
  210. package/dist/core/stdlib/index.js +1 -1
  211. package/dist/core/stdlib/index.js.map +1 -1
  212. package/dist/core/stdlib/maths/index.d.ts +1 -1
  213. package/dist/core/stdlib/maths/index.d.ts.map +1 -1
  214. package/dist/core/stdlib/maths/index.js +1 -1
  215. package/dist/core/stdlib/maths/index.js.map +1 -1
  216. package/dist/core/stdlib/maths/rounding.d.ts +5 -0
  217. package/dist/core/stdlib/maths/rounding.d.ts.map +1 -1
  218. package/dist/core/stdlib/maths/rounding.js +19 -1
  219. package/dist/core/stdlib/maths/rounding.js.map +1 -1
  220. package/dist/core/version/version.generated.d.ts +1 -1
  221. package/dist/core/version/version.generated.js +1 -1
  222. package/dist/editor/complete.d.ts +40 -0
  223. package/dist/editor/complete.d.ts.map +1 -0
  224. package/dist/editor/complete.js +206 -0
  225. package/dist/editor/complete.js.map +1 -0
  226. package/dist/editor/diagnose.d.ts +18 -0
  227. package/dist/editor/diagnose.d.ts.map +1 -0
  228. package/dist/editor/diagnose.js +70 -0
  229. package/dist/editor/diagnose.js.map +1 -0
  230. package/dist/editor/format.d.ts +11 -0
  231. package/dist/editor/format.d.ts.map +1 -0
  232. package/dist/editor/format.js +50 -0
  233. package/dist/editor/format.js.map +1 -0
  234. package/dist/editor/highlight.d.ts +28 -0
  235. package/dist/editor/highlight.d.ts.map +1 -0
  236. package/dist/editor/highlight.js +65 -0
  237. package/dist/editor/highlight.js.map +1 -0
  238. package/dist/editor/hover.d.ts +40 -0
  239. package/dist/editor/hover.d.ts.map +1 -0
  240. package/dist/editor/hover.js +147 -0
  241. package/dist/editor/hover.js.map +1 -0
  242. package/dist/editor/index.d.ts +60 -0
  243. package/dist/editor/index.d.ts.map +1 -0
  244. package/dist/editor/index.js +7 -0
  245. package/dist/editor/index.js.map +1 -0
  246. package/dist/editor/kinds.d.ts +27 -0
  247. package/dist/editor/kinds.d.ts.map +1 -0
  248. package/dist/editor/kinds.js +118 -0
  249. package/dist/editor/kinds.js.map +1 -0
  250. package/dist/editor/layout.d.ts +47 -0
  251. package/dist/editor/layout.d.ts.map +1 -0
  252. package/dist/editor/layout.js +135 -0
  253. package/dist/editor/layout.js.map +1 -0
  254. package/dist/editor/manifest.d.ts +47 -0
  255. package/dist/editor/manifest.d.ts.map +1 -0
  256. package/dist/editor/manifest.js +93 -0
  257. package/dist/editor/manifest.js.map +1 -0
  258. package/dist/editor/reading.d.ts +41 -0
  259. package/dist/editor/reading.d.ts.map +1 -0
  260. package/dist/editor/reading.js +51 -0
  261. package/dist/editor/reading.js.map +1 -0
  262. package/dist/editor/scan.d.ts +26 -0
  263. package/dist/editor/scan.d.ts.map +1 -0
  264. package/dist/editor/scan.js +139 -0
  265. package/dist/editor/scan.js.map +1 -0
  266. package/dist/editor/scope.d.ts +19 -0
  267. package/dist/editor/scope.d.ts.map +1 -0
  268. package/dist/editor/scope.js +99 -0
  269. package/dist/editor/scope.js.map +1 -0
  270. package/dist/editor/signature.d.ts +38 -0
  271. package/dist/editor/signature.d.ts.map +1 -0
  272. package/dist/editor/signature.js +112 -0
  273. package/dist/editor/signature.js.map +1 -0
  274. package/dist/editor/site.d.ts +46 -0
  275. package/dist/editor/site.d.ts.map +1 -0
  276. package/dist/editor/site.js +184 -0
  277. package/dist/editor/site.js.map +1 -0
  278. package/dist/editor/spacing.d.ts +29 -0
  279. package/dist/editor/spacing.d.ts.map +1 -0
  280. package/dist/editor/spacing.js +116 -0
  281. package/dist/editor/spacing.js.map +1 -0
  282. package/package.json +42 -3
  283. package/spec/README.md +2 -1
  284. package/spec/errors.json +141 -1
  285. package/src/adapters/charts/driving.ts +109 -0
  286. package/src/adapters/charts/run.ts +120 -28
  287. package/src/adapters/charts/surfaces.ts +17 -0
  288. package/src/adapters/charts/tables.ts +88 -0
  289. package/src/adapters/charts/venue.ts +132 -0
  290. package/src/adapters/codemirror/commands.ts +53 -0
  291. package/src/adapters/codemirror/completion.ts +74 -0
  292. package/src/adapters/codemirror/contract.ts +156 -0
  293. package/src/adapters/codemirror/index.ts +66 -0
  294. package/src/adapters/codemirror/lint.ts +66 -0
  295. package/src/adapters/codemirror/positions.ts +79 -0
  296. package/src/adapters/codemirror/stream.ts +87 -0
  297. package/src/adapters/codemirror/tokens.ts +64 -0
  298. package/src/adapters/codemirror/tooltips.ts +113 -0
  299. package/src/core/accounting/analysis.ts +188 -0
  300. package/src/core/accounting/charges.ts +452 -0
  301. package/src/core/accounting/equity.ts +314 -0
  302. package/src/core/accounting/index.ts +51 -0
  303. package/src/core/accounting/markers.ts +95 -0
  304. package/src/core/accounting/monthly.ts +137 -0
  305. package/src/core/accounting/report.ts +94 -0
  306. package/src/core/accounting/shapes.ts +73 -0
  307. package/src/core/accounting/statistics.ts +387 -0
  308. package/src/core/accounting/trades.ts +313 -0
  309. package/src/core/backtest/case.ts +395 -0
  310. package/src/core/backtest/compare.ts +246 -0
  311. package/src/core/backtest/declaration.ts +97 -0
  312. package/src/core/backtest/deliver.ts +161 -0
  313. package/src/core/backtest/drive.ts +468 -0
  314. package/src/core/backtest/index.ts +64 -0
  315. package/src/core/backtest/range.ts +137 -0
  316. package/src/core/backtest/record.ts +470 -0
  317. package/src/core/backtest/replay.ts +168 -0
  318. package/src/core/backtest/resting.ts +125 -0
  319. package/src/core/backtest/settings.ts +280 -0
  320. package/src/core/backtest/simulate.ts +499 -0
  321. package/src/core/catalogue/catalogue.generated.ts +6 -0
  322. package/src/core/catalogue/values.generated.ts +6 -0
  323. package/src/core/check/index.ts +3 -0
  324. package/src/core/check/library-orders.ts +2 -2
  325. package/src/core/check/library-prose.generated.ts +367 -0
  326. package/src/core/check/surface.ts +34 -0
  327. package/src/core/emit/canonical.ts +67 -9
  328. package/src/core/emit/defaults.ts +70 -0
  329. package/src/core/emit/index.ts +2 -0
  330. package/src/core/engine/arithmetic.ts +23 -3
  331. package/src/core/engine/index.ts +2 -2
  332. package/src/core/engine/library/arrays.ts +8 -2
  333. package/src/core/engine/library/code-points.ts +73 -0
  334. package/src/core/engine/library/index.ts +6 -0
  335. package/src/core/engine/library/text.ts +53 -35
  336. package/src/core/engine/load.ts +84 -2
  337. package/src/core/engine/verify-tables.ts +43 -0
  338. package/src/core/index.ts +100 -2
  339. package/src/core/stdlib/index.ts +1 -0
  340. package/src/core/stdlib/maths/index.ts +1 -0
  341. package/src/core/stdlib/maths/rounding.ts +23 -1
  342. package/src/core/version/version.generated.ts +1 -1
  343. package/src/editor/complete.ts +266 -0
  344. package/src/editor/diagnose.ts +71 -0
  345. package/src/editor/format.ts +85 -0
  346. package/src/editor/highlight.ts +110 -0
  347. package/src/editor/hover.ts +199 -0
  348. package/src/editor/index.ts +65 -0
  349. package/src/editor/kinds.ts +157 -0
  350. package/src/editor/layout.ts +189 -0
  351. package/src/editor/manifest.ts +119 -0
  352. package/src/editor/reading.ts +69 -0
  353. package/src/editor/scan.ts +162 -0
  354. package/src/editor/scope.ts +122 -0
  355. package/src/editor/signature.ts +150 -0
  356. package/src/editor/site.ts +233 -0
  357. package/src/editor/spacing.ts +132 -0
@@ -0,0 +1,191 @@
1
+ import { canonicalise } from '../emit/index.js';
2
+ /**
3
+ * A Summary field worth a delta, in the order a comparison reports them.
4
+ *
5
+ * Written out rather than walked off the object, for two reasons. A key walk
6
+ * would report a delta for `currency`, which is a string, and for `capital`,
7
+ * which is an input rather than a result. And the order a comparison prints its
8
+ * rows in would then be the order a literal happens to be written in, which is
9
+ * a thing somebody reformats without knowing they changed an output.
10
+ */
11
+ const COMPARED = [
12
+ 'netProfit',
13
+ 'returnPercent',
14
+ 'grossProfit',
15
+ 'grossLoss',
16
+ 'charges',
17
+ 'tradeCount',
18
+ 'openTradeCount',
19
+ 'wins',
20
+ 'losses',
21
+ 'scratches',
22
+ 'winRate',
23
+ 'averageWin',
24
+ 'averageLoss',
25
+ 'expectancy',
26
+ 'expectancyStandardError',
27
+ 'profitFactor',
28
+ 'maxDrawdown',
29
+ 'maxDrawdownPercent',
30
+ 'longestDrawdownBars',
31
+ 'maxRunUp',
32
+ 'maxRunUpPercent',
33
+ 'averageBarsHeld',
34
+ 'barsInMarket',
35
+ 'barCount',
36
+ ];
37
+ /**
38
+ * Two runs, side by side, and whether the gap between them is a result.
39
+ *
40
+ * **Comparable is about the inputs, not about the outputs.** Two runs over
41
+ * different bars, or on different contracts, are two studies: the money in one
42
+ * is not the money in the other, and subtracting them is arithmetic with no
43
+ * meaning behind it. A different program over the same bars is the opposite of
44
+ * that. It is the comparison somebody actually wants, so a differing program is
45
+ * reported as a difference and does not make the pair incomparable.
46
+ *
47
+ * **Every difference is named even when the pair is comparable**, because the
48
+ * reason a run improved is as often a setting somebody forgot they had changed
49
+ * as it is the change they meant to test. A comparison reporting only the money
50
+ * would let that through, and it would read as a result.
51
+ */
52
+ export function compareRuns(before, after) {
53
+ const differences = differencesBetween(before, after);
54
+ const blocking = differences.some((one) => one.what === 'bars' || one.what === 'contract');
55
+ return {
56
+ comparable: !blocking,
57
+ differences,
58
+ deltas: deltasBetween(before.report.summary, after.report.summary),
59
+ // Withheld rather than computed on an incomparable pair. A separation
60
+ // between two runs over different bars is a number, and it means nothing.
61
+ separation: blocking ? null : separationBetween(before.report.summary, after.report.summary),
62
+ sharedTrades: sharedTradesBetween(before.report.trades, after.report.trades),
63
+ };
64
+ }
65
+ /**
66
+ * What differs between two runs' inputs, in a fixed order.
67
+ *
68
+ * Compared through the repository's one canonical writer rather than field by
69
+ * field, so a settings shape that grows a field is compared on that field
70
+ * without this function being edited. Field by field is how a comparison
71
+ * quietly stops covering whatever was added to the settings last.
72
+ */
73
+ function differencesBetween(before, after) {
74
+ const found = [];
75
+ if (before.bars.hash !== after.bars.hash) {
76
+ found.push({
77
+ what: 'bars',
78
+ detail: `different bars: ${before.bars.count} rows hashing ${before.bars.hash}, against ${after.bars.count} hashing ${after.bars.hash}`,
79
+ });
80
+ }
81
+ if (canonicalise(before.settings.contract) !== canonicalise(after.settings.contract)) {
82
+ found.push({ what: 'contract', detail: 'the two runs are on different contracts' });
83
+ }
84
+ if (before.programHash !== after.programHash) {
85
+ found.push({
86
+ what: 'program',
87
+ detail: `different program: ${before.programHash}, against ${after.programHash}`,
88
+ });
89
+ }
90
+ if (canonicalise(before.settings.range) !== canonicalise(after.settings.range)) {
91
+ found.push({ what: 'range', detail: 'the two runs cover different date ranges' });
92
+ }
93
+ if (canonicalise(before.settings.costs) !== canonicalise(after.settings.costs)) {
94
+ found.push({ what: 'costs', detail: 'the two runs were charged under different cost models' });
95
+ }
96
+ if (canonicalise(before.settings.fill) !== canonicalise(after.settings.fill)) {
97
+ found.push({ what: 'fill', detail: 'the two runs were filled under different policies' });
98
+ }
99
+ if (canonicalise(before.settings.inputs) !== canonicalise(after.settings.inputs)) {
100
+ found.push({ what: 'inputs', detail: 'the two scripts ran with different input values' });
101
+ }
102
+ return found;
103
+ }
104
+ /**
105
+ * Every compared figure, before and after.
106
+ *
107
+ * A summary carries null where a figure has no meaning: no win rate until a
108
+ * trade closes, no profit factor without a loss. Null on one side and a number
109
+ * on the other is a real thing to report, and a delta between them is not, so
110
+ * the row appears with both values and a delta of zero. Subtracting from null
111
+ * would invent a movement out of a figure that was never there.
112
+ */
113
+ function deltasBetween(before, after) {
114
+ // Widened once, here. COMPARED is a list of names and a summary is a closed
115
+ // shape, so the lookup is by string either way; doing it in one place keeps
116
+ // the rest of this file reading the real type.
117
+ const a0 = before;
118
+ const b0 = after;
119
+ const deltas = [];
120
+ for (const name of COMPARED) {
121
+ const a = numberOf(a0[name]);
122
+ const b = numberOf(b0[name]);
123
+ // Neither side holds a figure: a field of no summary, which is nothing to
124
+ // report rather than a row of three zeroes.
125
+ if (a === null && b === null)
126
+ continue;
127
+ deltas.push({
128
+ name,
129
+ before: a ?? 0,
130
+ after: b ?? 0,
131
+ delta: a === null || b === null ? 0 : (b ?? 0) - (a ?? 0),
132
+ });
133
+ }
134
+ return deltas;
135
+ }
136
+ /** A figure, or none where the summary carries null or a string for it. */
137
+ function numberOf(value) {
138
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
139
+ }
140
+ /**
141
+ * How many standard errors apart the two expectancies are.
142
+ *
143
+ * Analytic, with no resampling and no random number generator, so two runs of
144
+ * this comparison over the same pair give the same figure for ever and a
145
+ * decision taken on it is one anybody can reproduce.
146
+ *
147
+ * **Null rather than a large number where there is no noise to measure.** A run
148
+ * with fewer than two closed trades has a standard error of zero, because one
149
+ * trade has no spread, and where both are zero the ratio divides by it.
150
+ * Returning infinity there would read as infinite confidence, which is the
151
+ * exact opposite of what one trade tells anybody. Null says the question cannot
152
+ * be answered from these two runs, which is the truth about them.
153
+ */
154
+ function separationBetween(before, after) {
155
+ const noise = Math.sqrt(before.expectancyStandardError * before.expectancyStandardError +
156
+ after.expectancyStandardError * after.expectancyStandardError);
157
+ if (!Number.isFinite(noise) || noise === 0)
158
+ return null;
159
+ const gap = after.expectancy - before.expectancy;
160
+ return Number.isFinite(gap) ? gap / noise : null;
161
+ }
162
+ /**
163
+ * How many trades the two runs took alike.
164
+ *
165
+ * Alike means opened on the same bar on the same side, which is the coarsest
166
+ * thing two runs can agree about and the only one that survives a change to
167
+ * sizing or to costs. It is what says whether a change moved the money by
168
+ * trading differently or by trading the same and paying differently, and those
169
+ * are not the same result however alike the two totals look.
170
+ *
171
+ * Counted as a multiset, so two long trades opening on one bar in one run
172
+ * against one in the other share one trade rather than two.
173
+ */
174
+ function sharedTradesBetween(before, after) {
175
+ const counts = new Map();
176
+ for (const trade of before) {
177
+ const key = `${trade.openedOnBar}:${trade.side}`;
178
+ counts.set(key, (counts.get(key) ?? 0) + 1);
179
+ }
180
+ let shared = 0;
181
+ for (const trade of after) {
182
+ const key = `${trade.openedOnBar}:${trade.side}`;
183
+ const left = counts.get(key) ?? 0;
184
+ if (left > 0) {
185
+ counts.set(key, left - 1);
186
+ shared += 1;
187
+ }
188
+ }
189
+ return shared;
190
+ }
191
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../../src/core/backtest/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The declaration's own half of a run, read once and read here.
3
+ *
4
+ * **What the program states is stored once, as the program**, so none of these
5
+ * figures is a setting a host chooses and none of them travels in the record
6
+ * beside the settings. They are read back out of the compiled program every
7
+ * time a run is driven or replayed, which is what makes a replay of a stored
8
+ * record the same run rather than a run under today's defaults.
9
+ *
10
+ * Every field of `meta.strategy` is written into the program with the value it
11
+ * resolved to, defaults included (`compiled-program.md` 2.3), so nothing here
12
+ * carries a table of defaults and a default that changes in a later language
13
+ * version cannot silently change an old program. A field a script wrote with an
14
+ * `input()` is resolved against the run's own settings, by the engine, at load,
15
+ * and `fieldValue` reads what that resolution produced: the rule lives in the
16
+ * engine and is applied here rather than repeated.
17
+ *
18
+ * A study has no strategy declaration at all. It places no order and has no
19
+ * money, and it reads here as the absence it is rather than as a zero capital
20
+ * somebody would divide by.
21
+ */
22
+ import type { CompiledProgram } from '../emit/index.js';
23
+ import type { ResolvedInput } from '../engine/index.js';
24
+ /** The money and the fill the declaration fixed before bar 0. */
25
+ export interface RunDeclaration {
26
+ /** False for a study, which declares none of this. */
27
+ readonly isStrategy: boolean;
28
+ readonly capital: number;
29
+ readonly currency: string;
30
+ /** Where a market order is priced, `language.md` 13.3. */
31
+ readonly fillOn: string;
32
+ readonly slippage: number;
33
+ readonly commission: number;
34
+ readonly commissionType: string;
35
+ /**
36
+ * The unit the declaration's quantity is stated in, `language.md` 13.3.
37
+ *
38
+ * Read here because the destination is the party that has to convert it, and
39
+ * a destination that cannot convert the unit a strategy sizes in has to
40
+ * refuse the run rather than fill a number in the wrong unit.
41
+ */
42
+ readonly qtyType: string;
43
+ }
44
+ /**
45
+ * What one program's declaration says about money, after its inputs.
46
+ *
47
+ * The inputs are the ones the engine resolved at load, handed back by `load`
48
+ * for this reader. A caller with none reads the literals, which is every
49
+ * program that did not write a declaration field with an `input()`.
50
+ */
51
+ export declare function declarationOf(program: CompiledProgram, inputs?: readonly ResolvedInput[]): RunDeclaration;
52
+ //# sourceMappingURL=declaration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../../../src/core/backtest/declaration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAS,MAAM,oBAAoB,CAAC;AAE/D,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EACxB,MAAM,GAAE,SAAS,aAAa,EAAO,GACpC,cAAc,CAwBhB"}
@@ -0,0 +1,48 @@
1
+ import { fieldValue } from '../engine/index.js';
2
+ /**
3
+ * What one program's declaration says about money, after its inputs.
4
+ *
5
+ * The inputs are the ones the engine resolved at load, handed back by `load`
6
+ * for this reader. A caller with none reads the literals, which is every
7
+ * program that did not write a declaration field with an `input()`.
8
+ */
9
+ export function declarationOf(program, inputs = []) {
10
+ const strategy = program.meta.strategy;
11
+ if (strategy === undefined) {
12
+ return {
13
+ isStrategy: false,
14
+ capital: 0,
15
+ currency: '',
16
+ fillOn: '',
17
+ slippage: 0,
18
+ commission: 0,
19
+ commissionType: '',
20
+ qtyType: '',
21
+ };
22
+ }
23
+ return {
24
+ isStrategy: true,
25
+ capital: numberOf(fieldValue(strategy.capital, inputs)),
26
+ currency: stringOf(fieldValue(strategy.currency, inputs)),
27
+ fillOn: stringOf(fieldValue(strategy.fillOn, inputs)),
28
+ slippage: numberOf(fieldValue(strategy.slippage, inputs)),
29
+ commission: numberOf(fieldValue(strategy.commission, inputs)),
30
+ commissionType: stringOf(fieldValue(strategy.commissionType, inputs)),
31
+ qtyType: stringOf(fieldValue(strategy.qtyType, inputs)),
32
+ };
33
+ }
34
+ /**
35
+ * A number the declaration states, or zero where it states something else.
36
+ *
37
+ * Zero rather than absence, and only here: every one of these fields is written
38
+ * into the program with a number, so anything else is a program this engine
39
+ * would already have refused at load. The fallback is what keeps this reader
40
+ * total rather than a second place a malformed program is diagnosed.
41
+ */
42
+ function numberOf(value) {
43
+ return typeof value === 'number' && Number.isFinite(value) ? value : 0;
44
+ }
45
+ function stringOf(value) {
46
+ return typeof value === 'string' ? value : '';
47
+ }
48
+ //# sourceMappingURL=declaration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declaration.js","sourceRoot":"","sources":["../../../src/core/backtest/declaration.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAwBhD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAwB,EACxB,SAAmC,EAAE;IAErC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,cAAc,EAAE,EAAE;YAClB,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;IACD,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzD,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC7D,cAAc,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;KACxD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,KAAY;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * A case's rows and this engine's frames, and the destination between them.
3
+ *
4
+ * Both directions are here because they are one correspondence: a case names an
5
+ * order by an ordinal and an engine knows it by an id, so `Delivery` reads an
6
+ * ordinal into the id of the intent the run placed, and `framedAs` writes an id
7
+ * back out as the ordinal a case file prints. Split between two files, the two
8
+ * halves of it drift, and a suite whose rows say one thing and whose records
9
+ * say another is one nobody can read.
10
+ *
11
+ * `conformance.md` section 3: `frames.csv` supplies order frames the way
12
+ * `bars.csv` supplies bars, so a strategy case asserts the fold against input
13
+ * the engine did not choose. `simulate.ts` is the other destination this module
14
+ * has, the one that reads a bar and works out what a venue would have said.
15
+ * This one works nothing out. It holds the rows a case supplied, hands over the
16
+ * ones each boundary names, and the whole of its behaviour is the mapping
17
+ * between a row and a frame.
18
+ *
19
+ * **An ordinal is what a case can name, and an id is not.** A row names the nth
20
+ * intent the run placed, because no case can know the id an engine minted, so
21
+ * the intents are counted here in the order the run handed them over and the
22
+ * ordinal is read against that count. A row naming an ordinal the run never
23
+ * placed is delivered all the same, carrying an id no run mints: step 1 of
24
+ * `stdlib.md` 17.8 refuses a frame naming no row of the ledger, and that
25
+ * refusal is the ledger's to make. A destination that dropped the row instead
26
+ * would answer nothing at all where section 3 hands an engine a frame about an
27
+ * order its ledger does not hold, and the case would pass by the frame never
28
+ * having arrived.
29
+ *
30
+ * **What a row does not carry, this does not invent.** `host-interface.md` 7.2
31
+ * lets a frame say which instrument and product the destination booked the
32
+ * order under, and the file has no column for either, so neither is stated and
33
+ * the row keeps what its placement put there. The instant is the one the file
34
+ * does carry: a row states one or states `none`, and one that states none
35
+ * leaves `updatedAt` where the placement put it, which is what the fold does
36
+ * with a frame whose destination stated no instant.
37
+ */
38
+ import type { OrderFrame, OrderIntent, RoutedEffect } from '../engine/index.js';
39
+ import type { RecordedFrame } from './record.js';
40
+ /** One frame, the boundary it was handed over at, and the row it came from. */
41
+ export interface Delivered {
42
+ readonly frame: OrderFrame;
43
+ readonly afterBar: number;
44
+ /**
45
+ * The row a case supplied, or null where the run's own destination answered
46
+ * the frame and there is no row until the record is written.
47
+ */
48
+ readonly row: RecordedFrame | null;
49
+ }
50
+ /** Where a run's orders go, and what it is told between two of its bars. */
51
+ export interface Destination {
52
+ /** Step 9: what the strategy decided, on the bar it decided it. */
53
+ route(effect: RoutedEffect, barIndex: number): void;
54
+ /** What this destination hands over at the boundary after `barIndex`. */
55
+ answers(barIndex: number): readonly Delivered[];
56
+ /** Every intent it was handed, in the order it was handed them. */
57
+ readonly intents: readonly OrderIntent[];
58
+ }
59
+ /**
60
+ * A destination holding one case's frames, ready at the boundaries they name.
61
+ *
62
+ * Built before the run rather than during it, because the rows are input: what
63
+ * a boundary hands over was decided by whoever wrote the case and not by
64
+ * anything this run does. The one thing it learns as the run goes is which
65
+ * intent an ordinal names, which only the run can say.
66
+ */
67
+ export declare class Delivery implements Destination {
68
+ readonly intents: OrderIntent[];
69
+ /** The rows of each boundary, in file order, which section 3 fixes as the delivery order. */
70
+ private readonly rows;
71
+ constructor(frames: readonly RecordedFrame[]);
72
+ /** Nothing is decided by an order arriving here: it is counted, and that is all. */
73
+ route(effect: RoutedEffect): void;
74
+ answers(barIndex: number): readonly Delivered[];
75
+ }
76
+ /**
77
+ * The ordinal of every intent, which is how a case names one.
78
+ *
79
+ * One, two, three in the order the run placed them, because no engine can know
80
+ * the id another minted and a case that named one would only ever be readable
81
+ * by the engine that wrote it.
82
+ */
83
+ export declare function ordinalsOf(intents: readonly OrderIntent[]): ReadonlyMap<number, number>;
84
+ /**
85
+ * One delivered frame, in the columns a case file prints.
86
+ *
87
+ * The instant travels with it. `stdlib.md` 17.7 folds `updatedAt` from a
88
+ * frame's `time`, so a driver that dropped the field here wrote a record whose
89
+ * ledger no engine could fold from the record's own frames: it would have
90
+ * nothing to move that field to and would leave it at `placedAt`.
91
+ */
92
+ export declare function framedAs(frame: OrderFrame, afterBar: number, ordinals: ReadonlyMap<number, number>): RecordedFrame;
93
+ //# sourceMappingURL=deliver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../../../src/core/backtest/deliver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD,yEAAyE;IACzE,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,SAAS,EAAE,CAAC;IAChD,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C;AAcD;;;;;;;GAOG;AACH,qBAAa,QAAS,YAAW,WAAW;IAC1C,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAM;IACrC,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsC;gBAE/C,MAAM,EAAE,SAAS,aAAa,EAAE;IAQ5C,oFAAoF;IACpF,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAIjC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,SAAS,EAAE;CAQhD;AAeD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAMvF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,aAAa,CAWf"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * An id no run mints, which a row naming no intent of this run is delivered
3
+ * under.
4
+ *
5
+ * Ids are counted from one by the ledger that mints them, so nothing below one
6
+ * can name a row and the fold refuses the frame by the rule it refuses every
7
+ * other unknown one by. The alternative was an id of a real row chosen by some
8
+ * rule of this file's own, which would fold a case's frame into whichever order
9
+ * happened to be near it.
10
+ */
11
+ const NO_INTENT = -1;
12
+ /**
13
+ * A destination holding one case's frames, ready at the boundaries they name.
14
+ *
15
+ * Built before the run rather than during it, because the rows are input: what
16
+ * a boundary hands over was decided by whoever wrote the case and not by
17
+ * anything this run does. The one thing it learns as the run goes is which
18
+ * intent an ordinal names, which only the run can say.
19
+ */
20
+ export class Delivery {
21
+ intents = [];
22
+ /** The rows of each boundary, in file order, which section 3 fixes as the delivery order. */
23
+ rows = new Map();
24
+ constructor(frames) {
25
+ for (const row of frames) {
26
+ const at = this.rows.get(row.afterBar);
27
+ if (at === undefined)
28
+ this.rows.set(row.afterBar, [row]);
29
+ else
30
+ at.push(row);
31
+ }
32
+ }
33
+ /** Nothing is decided by an order arriving here: it is counted, and that is all. */
34
+ route(effect) {
35
+ for (const intent of effect.intents)
36
+ this.intents.push(intent);
37
+ }
38
+ answers(barIndex) {
39
+ const due = this.rows.get(barIndex) ?? [];
40
+ return due.map((row) => ({
41
+ frame: frameOf(row, this.intents[row.intent - 1]),
42
+ afterBar: barIndex,
43
+ row,
44
+ }));
45
+ }
46
+ }
47
+ /** One row of a case, as the frame `host-interface.md` 7.2 describes. */
48
+ function frameOf(row, intent) {
49
+ return {
50
+ intentId: intent?.intentId ?? NO_INTENT,
51
+ status: row.status,
52
+ filledQty: row.filledQty,
53
+ avgFillPrice: row.avgFillPrice,
54
+ orderRef: row.orderRef,
55
+ text: row.text,
56
+ time: row.time,
57
+ };
58
+ }
59
+ /**
60
+ * The ordinal of every intent, which is how a case names one.
61
+ *
62
+ * One, two, three in the order the run placed them, because no engine can know
63
+ * the id another minted and a case that named one would only ever be readable
64
+ * by the engine that wrote it.
65
+ */
66
+ export function ordinalsOf(intents) {
67
+ const out = new Map();
68
+ for (const intent of intents) {
69
+ if (!out.has(intent.intentId))
70
+ out.set(intent.intentId, out.size + 1);
71
+ }
72
+ return out;
73
+ }
74
+ /**
75
+ * One delivered frame, in the columns a case file prints.
76
+ *
77
+ * The instant travels with it. `stdlib.md` 17.7 folds `updatedAt` from a
78
+ * frame's `time`, so a driver that dropped the field here wrote a record whose
79
+ * ledger no engine could fold from the record's own frames: it would have
80
+ * nothing to move that field to and would leave it at `placedAt`.
81
+ */
82
+ export function framedAs(frame, afterBar, ordinals) {
83
+ return {
84
+ afterBar,
85
+ intent: ordinals.get(frame.intentId) ?? 0,
86
+ status: frame.status,
87
+ filledQty: frame.filledQty,
88
+ avgFillPrice: frame.avgFillPrice ?? null,
89
+ orderRef: frame.orderRef ?? null,
90
+ text: frame.text ?? null,
91
+ time: frame.time ?? null,
92
+ };
93
+ }
94
+ //# sourceMappingURL=deliver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver.js","sourceRoot":"","sources":["../../../src/core/backtest/deliver.ts"],"names":[],"mappings":"AA6DA;;;;;;;;;GASG;AACH,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,OAAO,QAAQ;IACV,OAAO,GAAkB,EAAE,CAAC;IACrC,6FAA6F;IAC5E,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE3D,YAAY,MAAgC;QAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,EAAE,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;;gBACpD,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,oFAAoF;IACpF,KAAK,CAAC,MAAoB;QACxB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,CAAC,QAAgB;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACvB,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjD,QAAQ,EAAE,QAAQ;YAClB,GAAG;SACJ,CAAC,CAAC,CAAC;IACN,CAAC;CACF;AAED,yEAAyE;AACzE,SAAS,OAAO,CAAC,GAAkB,EAAE,MAA+B;IAClE,OAAO;QACL,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,SAAS;QACvC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;KACf,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,OAA+B;IACxD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAiB,EACjB,QAAgB,EAChB,QAAqC;IAErC,OAAO;QACL,QAAQ;QACR,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QACzC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;KACzB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,87 @@
1
+ import type { Diagnostic } from '../diagnostics/index.js';
2
+ import type { CompiledProgram } from '../emit/index.js';
3
+ import type { Instrument } from '../engine/index.js';
4
+ import type { RecordedBar, RecordedFrame, RunRecord } from './record.js';
5
+ import type { BacktestSettings } from './settings.js';
6
+ /** What a run came to, or why it could not be carried out at all. */
7
+ export type BacktestResult = {
8
+ readonly ok: true;
9
+ readonly record: RunRecord;
10
+ } | {
11
+ readonly ok: false;
12
+ readonly diagnostic: Diagnostic;
13
+ };
14
+ /**
15
+ * The facts of `host-interface.md` 4.1 that the contract does not hold.
16
+ *
17
+ * The contract already states six of the twelve, the ones the money is priced
18
+ * under, and a fact stated in two places is a fact that can disagree with
19
+ * itself: a tick size the engine rounds to and a different one the venue
20
+ * worsens a fill by is a run under two instruments. So the other six are
21
+ * stated here and the six the contract holds cannot be, which the compiler
22
+ * enforces rather than a check at run time.
23
+ */
24
+ export type InstrumentFacts = Omit<Instrument, 'symbol' | 'exchange' | 'tickSize' | 'lotSize' | 'pointValue' | 'currency'>;
25
+ /** The few choices a driver has that are not settings of the run itself. */
26
+ export interface DriveOptions {
27
+ /** Whether the bars travel in the record. Inline is the conformance form. */
28
+ readonly form?: 'inline' | 'referenced';
29
+ /**
30
+ * What the host states about the instrument beside the contract, so the
31
+ * record it produces is a conformance case.
32
+ *
33
+ * A case holds `instrument.json`, which `conformance.md` section 2 says is
34
+ * the record of `host-interface.md` 4.1, and that page requires one fact of
35
+ * every host: `hasVolume`, because no derivation recovers it (4.2). The
36
+ * engine reads the record and does not refuse a run without it, so a caller
37
+ * that leaves this out gets a record that replays and reruns like any other
38
+ * and cannot become a case, exactly as one without `sourceText` cannot.
39
+ *
40
+ * A session stated without a timezone is refused at load, OS6012, by the
41
+ * same rule that refuses it for any host.
42
+ */
43
+ readonly instrument?: InstrumentFacts;
44
+ /**
45
+ * The script's own text, so the record it produces is a conformance case.
46
+ *
47
+ * A compiled program identifies its source and cannot reproduce it, and a
48
+ * case has to hold `script.os`. A caller holding only a program leaves this
49
+ * out and gets a record that replays and reruns like any other; the one
50
+ * thing it cannot do is be handed to somebody else's engine as a case.
51
+ *
52
+ * It is checked against the program's own source hash, so text from a
53
+ * different revision than the one that was compiled is refused rather than
54
+ * written into a case that could never make its own expected output.
55
+ */
56
+ readonly sourceText?: string;
57
+ }
58
+ /**
59
+ * One run against a simulated destination, from a compiled program to a record.
60
+ *
61
+ * The frames are the destination's own: it is handed the orders, it reads the
62
+ * bars, and what it answers is what the engine folds. A run whose frames
63
+ * somebody else is supplying is `backtestSupplied` below.
64
+ */
65
+ export declare function backtest(program: CompiledProgram, bars: readonly RecordedBar[], settings: BacktestSettings, options?: DriveOptions): BacktestResult;
66
+ /**
67
+ * One run over the frames somebody else supplied, which this engine does not
68
+ * choose and does not add to.
69
+ *
70
+ * `conformance.md` section 3 gives a case a `frames.csv` that supplies order
71
+ * frames the way `bars.csv` supplies bars, so that a case asserts the fold
72
+ * against input the engine did not choose. Every other argument is `backtest`'s
73
+ * and means there what it means here. A row is delivered at the boundary it
74
+ * names and folded before the next bar, and the record carries the rows it was
75
+ * handed rather than a second spelling of them.
76
+ *
77
+ * **Nothing is invented.** No fill is priced off a bar, no order rests and no
78
+ * schedule is read, so an order the frames say nothing about stays where its
79
+ * placement left it, which is what a case saying nothing about it means.
80
+ *
81
+ * **A record made here is a record of this run and not of a simulated one.**
82
+ * `rerun` puts a record's program back on a simulated destination, because a
83
+ * record does not say which of the two answered it, so a rerun of one of these
84
+ * reproduces it only where that destination would answer these same frames.
85
+ */
86
+ export declare function backtestSupplied(program: CompiledProgram, bars: readonly RecordedBar[], settings: BacktestSettings, frames: readonly RecordedFrame[], options?: DriveOptions): BacktestResult;
87
+ //# sourceMappingURL=drive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../../src/core/backtest/drive.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAIV,UAAU,EAIX,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EACV,WAAW,EAEX,aAAa,EAEb,SAAS,EACV,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,qEAAqE;AACrE,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,UAAU,EACV,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,CAC3E,CAAC;AAEF,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IACxC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,GAAE,YAAiB,GACzB,cAAc,CAahB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,OAAO,GAAE,YAAiB,GACzB,cAAc,CAEhB"}