openalgo-script 0.2.0 → 0.4.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 (276) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +65 -31
  3. package/dist/adapters/charts/surfaces.d.ts +17 -0
  4. package/dist/adapters/charts/surfaces.d.ts.map +1 -1
  5. package/dist/adapters/charts/tables.js +82 -0
  6. package/dist/adapters/charts/tables.js.map +1 -1
  7. package/dist/adapters/codemirror/commands.d.ts +14 -0
  8. package/dist/adapters/codemirror/commands.d.ts.map +1 -0
  9. package/dist/adapters/codemirror/commands.js +52 -0
  10. package/dist/adapters/codemirror/commands.js.map +1 -0
  11. package/dist/adapters/codemirror/completion.d.ts +15 -0
  12. package/dist/adapters/codemirror/completion.d.ts.map +1 -0
  13. package/dist/adapters/codemirror/completion.js +64 -0
  14. package/dist/adapters/codemirror/completion.js.map +1 -0
  15. package/dist/adapters/codemirror/contract.d.ts +156 -0
  16. package/dist/adapters/codemirror/contract.d.ts.map +1 -0
  17. package/dist/adapters/codemirror/contract.js +42 -0
  18. package/dist/adapters/codemirror/contract.js.map +1 -0
  19. package/dist/adapters/codemirror/index.d.ts +43 -0
  20. package/dist/adapters/codemirror/index.d.ts.map +1 -0
  21. package/dist/adapters/codemirror/index.js +8 -0
  22. package/dist/adapters/codemirror/index.js.map +1 -0
  23. package/dist/adapters/codemirror/lint.d.ts +17 -0
  24. package/dist/adapters/codemirror/lint.d.ts.map +1 -0
  25. package/dist/adapters/codemirror/lint.js +62 -0
  26. package/dist/adapters/codemirror/lint.js.map +1 -0
  27. package/dist/adapters/codemirror/positions.d.ts +16 -0
  28. package/dist/adapters/codemirror/positions.d.ts.map +1 -0
  29. package/dist/adapters/codemirror/positions.js +65 -0
  30. package/dist/adapters/codemirror/positions.js.map +1 -0
  31. package/dist/adapters/codemirror/stream.d.ts +23 -0
  32. package/dist/adapters/codemirror/stream.d.ts.map +1 -0
  33. package/dist/adapters/codemirror/stream.js +70 -0
  34. package/dist/adapters/codemirror/stream.js.map +1 -0
  35. package/dist/adapters/codemirror/tokens.d.ts +44 -0
  36. package/dist/adapters/codemirror/tokens.d.ts.map +1 -0
  37. package/dist/adapters/codemirror/tokens.js +34 -0
  38. package/dist/adapters/codemirror/tokens.js.map +1 -0
  39. package/dist/adapters/codemirror/tooltips.d.ts +35 -0
  40. package/dist/adapters/codemirror/tooltips.d.ts.map +1 -0
  41. package/dist/adapters/codemirror/tooltips.js +108 -0
  42. package/dist/adapters/codemirror/tooltips.js.map +1 -0
  43. package/dist/core/accounting/charges.d.ts +136 -0
  44. package/dist/core/accounting/charges.d.ts.map +1 -0
  45. package/dist/core/accounting/charges.js +362 -0
  46. package/dist/core/accounting/charges.js.map +1 -0
  47. package/dist/core/accounting/equity.d.ts +158 -0
  48. package/dist/core/accounting/equity.d.ts.map +1 -0
  49. package/dist/core/accounting/equity.js +155 -0
  50. package/dist/core/accounting/equity.js.map +1 -0
  51. package/dist/core/accounting/index.d.ts +44 -0
  52. package/dist/core/accounting/index.d.ts.map +1 -0
  53. package/dist/core/accounting/index.js +36 -0
  54. package/dist/core/accounting/index.js.map +1 -0
  55. package/dist/core/accounting/markers.d.ts +43 -0
  56. package/dist/core/accounting/markers.d.ts.map +1 -0
  57. package/dist/core/accounting/markers.js +64 -0
  58. package/dist/core/accounting/markers.js.map +1 -0
  59. package/dist/core/accounting/monthly.d.ts +52 -0
  60. package/dist/core/accounting/monthly.d.ts.map +1 -0
  61. package/dist/core/accounting/monthly.js +99 -0
  62. package/dist/core/accounting/monthly.js.map +1 -0
  63. package/dist/core/accounting/report.d.ts +38 -0
  64. package/dist/core/accounting/report.d.ts.map +1 -0
  65. package/dist/core/accounting/report.js +63 -0
  66. package/dist/core/accounting/report.js.map +1 -0
  67. package/dist/core/accounting/shapes.d.ts +70 -0
  68. package/dist/core/accounting/shapes.d.ts.map +1 -0
  69. package/dist/core/accounting/shapes.js +21 -0
  70. package/dist/core/accounting/shapes.js.map +1 -0
  71. package/dist/core/accounting/statistics.d.ts +75 -0
  72. package/dist/core/accounting/statistics.d.ts.map +1 -0
  73. package/dist/core/accounting/statistics.js +246 -0
  74. package/dist/core/accounting/statistics.js.map +1 -0
  75. package/dist/core/accounting/trades.d.ts +118 -0
  76. package/dist/core/accounting/trades.d.ts.map +1 -0
  77. package/dist/core/accounting/trades.js +186 -0
  78. package/dist/core/accounting/trades.js.map +1 -0
  79. package/dist/core/backtest/compare.d.ts +38 -0
  80. package/dist/core/backtest/compare.d.ts.map +1 -0
  81. package/dist/core/backtest/compare.js +189 -0
  82. package/dist/core/backtest/compare.js.map +1 -0
  83. package/dist/core/backtest/declaration.d.ts +52 -0
  84. package/dist/core/backtest/declaration.d.ts.map +1 -0
  85. package/dist/core/backtest/declaration.js +48 -0
  86. package/dist/core/backtest/declaration.js.map +1 -0
  87. package/dist/core/backtest/drive.d.ts +29 -0
  88. package/dist/core/backtest/drive.d.ts.map +1 -0
  89. package/dist/core/backtest/drive.js +262 -0
  90. package/dist/core/backtest/drive.js.map +1 -0
  91. package/dist/core/backtest/index.d.ts +46 -0
  92. package/dist/core/backtest/index.d.ts.map +1 -0
  93. package/dist/core/backtest/index.js +36 -0
  94. package/dist/core/backtest/index.js.map +1 -0
  95. package/dist/core/backtest/range.d.ts +84 -0
  96. package/dist/core/backtest/range.d.ts.map +1 -0
  97. package/dist/core/backtest/range.js +90 -0
  98. package/dist/core/backtest/range.js.map +1 -0
  99. package/dist/core/backtest/record.d.ts +238 -0
  100. package/dist/core/backtest/record.d.ts.map +1 -0
  101. package/dist/core/backtest/record.js +176 -0
  102. package/dist/core/backtest/record.js.map +1 -0
  103. package/dist/core/backtest/replay.d.ts +48 -0
  104. package/dist/core/backtest/replay.d.ts.map +1 -0
  105. package/dist/core/backtest/replay.js +127 -0
  106. package/dist/core/backtest/replay.js.map +1 -0
  107. package/dist/core/backtest/resting.d.ts +62 -0
  108. package/dist/core/backtest/resting.d.ts.map +1 -0
  109. package/dist/core/backtest/resting.js +59 -0
  110. package/dist/core/backtest/resting.js.map +1 -0
  111. package/dist/core/backtest/settings.d.ts +117 -0
  112. package/dist/core/backtest/settings.d.ts.map +1 -0
  113. package/dist/core/backtest/settings.js +207 -0
  114. package/dist/core/backtest/settings.js.map +1 -0
  115. package/dist/core/backtest/simulate.d.ts +146 -0
  116. package/dist/core/backtest/simulate.d.ts.map +1 -0
  117. package/dist/core/backtest/simulate.js +217 -0
  118. package/dist/core/backtest/simulate.js.map +1 -0
  119. package/dist/core/catalogue/catalogue.generated.d.ts +66 -0
  120. package/dist/core/catalogue/catalogue.generated.d.ts.map +1 -1
  121. package/dist/core/catalogue/catalogue.generated.js +6 -0
  122. package/dist/core/catalogue/catalogue.generated.js.map +1 -1
  123. package/dist/core/catalogue/values.generated.d.ts +24 -0
  124. package/dist/core/catalogue/values.generated.d.ts.map +1 -1
  125. package/dist/core/check/index.d.ts +2 -1
  126. package/dist/core/check/index.d.ts.map +1 -1
  127. package/dist/core/check/index.js +1 -1
  128. package/dist/core/check/index.js.map +1 -1
  129. package/dist/core/check/library-prose.generated.d.ts +16 -0
  130. package/dist/core/check/library-prose.generated.d.ts.map +1 -0
  131. package/dist/core/check/library-prose.generated.js +353 -0
  132. package/dist/core/check/library-prose.generated.js.map +1 -0
  133. package/dist/core/check/surface.d.ts +24 -0
  134. package/dist/core/check/surface.d.ts.map +1 -1
  135. package/dist/core/check/surface.js +29 -0
  136. package/dist/core/check/surface.js.map +1 -1
  137. package/dist/core/emit/defaults.d.ts +35 -16
  138. package/dist/core/emit/defaults.d.ts.map +1 -1
  139. package/dist/core/emit/defaults.js +66 -0
  140. package/dist/core/emit/defaults.js.map +1 -1
  141. package/dist/core/emit/index.d.ts +2 -0
  142. package/dist/core/emit/index.d.ts.map +1 -1
  143. package/dist/core/emit/index.js +2 -0
  144. package/dist/core/emit/index.js.map +1 -1
  145. package/dist/core/engine/index.d.ts +1 -1
  146. package/dist/core/engine/index.d.ts.map +1 -1
  147. package/dist/core/engine/index.js +1 -1
  148. package/dist/core/engine/index.js.map +1 -1
  149. package/dist/core/engine/load.d.ts +15 -1
  150. package/dist/core/engine/load.d.ts.map +1 -1
  151. package/dist/core/engine/load.js +1 -0
  152. package/dist/core/engine/load.js.map +1 -1
  153. package/dist/core/index.d.ts +37 -3
  154. package/dist/core/index.d.ts.map +1 -1
  155. package/dist/core/index.js +17 -1
  156. package/dist/core/index.js.map +1 -1
  157. package/dist/core/version/version.generated.d.ts +1 -1
  158. package/dist/core/version/version.generated.js +1 -1
  159. package/dist/editor/complete.d.ts +40 -0
  160. package/dist/editor/complete.d.ts.map +1 -0
  161. package/dist/editor/complete.js +206 -0
  162. package/dist/editor/complete.js.map +1 -0
  163. package/dist/editor/diagnose.d.ts +18 -0
  164. package/dist/editor/diagnose.d.ts.map +1 -0
  165. package/dist/editor/diagnose.js +70 -0
  166. package/dist/editor/diagnose.js.map +1 -0
  167. package/dist/editor/format.d.ts +11 -0
  168. package/dist/editor/format.d.ts.map +1 -0
  169. package/dist/editor/format.js +50 -0
  170. package/dist/editor/format.js.map +1 -0
  171. package/dist/editor/highlight.d.ts +28 -0
  172. package/dist/editor/highlight.d.ts.map +1 -0
  173. package/dist/editor/highlight.js +65 -0
  174. package/dist/editor/highlight.js.map +1 -0
  175. package/dist/editor/hover.d.ts +40 -0
  176. package/dist/editor/hover.d.ts.map +1 -0
  177. package/dist/editor/hover.js +147 -0
  178. package/dist/editor/hover.js.map +1 -0
  179. package/dist/editor/index.d.ts +60 -0
  180. package/dist/editor/index.d.ts.map +1 -0
  181. package/dist/editor/index.js +7 -0
  182. package/dist/editor/index.js.map +1 -0
  183. package/dist/editor/kinds.d.ts +27 -0
  184. package/dist/editor/kinds.d.ts.map +1 -0
  185. package/dist/editor/kinds.js +118 -0
  186. package/dist/editor/kinds.js.map +1 -0
  187. package/dist/editor/layout.d.ts +47 -0
  188. package/dist/editor/layout.d.ts.map +1 -0
  189. package/dist/editor/layout.js +135 -0
  190. package/dist/editor/layout.js.map +1 -0
  191. package/dist/editor/manifest.d.ts +47 -0
  192. package/dist/editor/manifest.d.ts.map +1 -0
  193. package/dist/editor/manifest.js +93 -0
  194. package/dist/editor/manifest.js.map +1 -0
  195. package/dist/editor/reading.d.ts +41 -0
  196. package/dist/editor/reading.d.ts.map +1 -0
  197. package/dist/editor/reading.js +51 -0
  198. package/dist/editor/reading.js.map +1 -0
  199. package/dist/editor/scan.d.ts +26 -0
  200. package/dist/editor/scan.d.ts.map +1 -0
  201. package/dist/editor/scan.js +139 -0
  202. package/dist/editor/scan.js.map +1 -0
  203. package/dist/editor/scope.d.ts +19 -0
  204. package/dist/editor/scope.d.ts.map +1 -0
  205. package/dist/editor/scope.js +99 -0
  206. package/dist/editor/scope.js.map +1 -0
  207. package/dist/editor/signature.d.ts +38 -0
  208. package/dist/editor/signature.d.ts.map +1 -0
  209. package/dist/editor/signature.js +112 -0
  210. package/dist/editor/signature.js.map +1 -0
  211. package/dist/editor/site.d.ts +46 -0
  212. package/dist/editor/site.d.ts.map +1 -0
  213. package/dist/editor/site.js +184 -0
  214. package/dist/editor/site.js.map +1 -0
  215. package/dist/editor/spacing.d.ts +29 -0
  216. package/dist/editor/spacing.d.ts.map +1 -0
  217. package/dist/editor/spacing.js +116 -0
  218. package/dist/editor/spacing.js.map +1 -0
  219. package/package.json +30 -3
  220. package/spec/errors.json +140 -0
  221. package/src/adapters/charts/surfaces.ts +17 -0
  222. package/src/adapters/charts/tables.ts +88 -0
  223. package/src/adapters/codemirror/commands.ts +53 -0
  224. package/src/adapters/codemirror/completion.ts +74 -0
  225. package/src/adapters/codemirror/contract.ts +156 -0
  226. package/src/adapters/codemirror/index.ts +66 -0
  227. package/src/adapters/codemirror/lint.ts +66 -0
  228. package/src/adapters/codemirror/positions.ts +79 -0
  229. package/src/adapters/codemirror/stream.ts +87 -0
  230. package/src/adapters/codemirror/tokens.ts +64 -0
  231. package/src/adapters/codemirror/tooltips.ts +113 -0
  232. package/src/core/accounting/charges.ts +452 -0
  233. package/src/core/accounting/equity.ts +276 -0
  234. package/src/core/accounting/index.ts +49 -0
  235. package/src/core/accounting/markers.ts +95 -0
  236. package/src/core/accounting/monthly.ts +137 -0
  237. package/src/core/accounting/report.ts +89 -0
  238. package/src/core/accounting/shapes.ts +73 -0
  239. package/src/core/accounting/statistics.ts +350 -0
  240. package/src/core/accounting/trades.ts +313 -0
  241. package/src/core/backtest/compare.ts +244 -0
  242. package/src/core/backtest/declaration.ts +97 -0
  243. package/src/core/backtest/drive.ts +364 -0
  244. package/src/core/backtest/index.ts +52 -0
  245. package/src/core/backtest/range.ts +137 -0
  246. package/src/core/backtest/record.ts +341 -0
  247. package/src/core/backtest/replay.ts +158 -0
  248. package/src/core/backtest/resting.ts +125 -0
  249. package/src/core/backtest/settings.ts +280 -0
  250. package/src/core/backtest/simulate.ts +304 -0
  251. package/src/core/catalogue/catalogue.generated.ts +6 -0
  252. package/src/core/catalogue/values.generated.ts +6 -0
  253. package/src/core/check/index.ts +3 -0
  254. package/src/core/check/library-prose.generated.ts +367 -0
  255. package/src/core/check/surface.ts +34 -0
  256. package/src/core/emit/defaults.ts +70 -0
  257. package/src/core/emit/index.ts +2 -0
  258. package/src/core/engine/index.ts +1 -1
  259. package/src/core/engine/load.ts +16 -2
  260. package/src/core/index.ts +85 -1
  261. package/src/core/version/version.generated.ts +1 -1
  262. package/src/editor/complete.ts +266 -0
  263. package/src/editor/diagnose.ts +71 -0
  264. package/src/editor/format.ts +85 -0
  265. package/src/editor/highlight.ts +110 -0
  266. package/src/editor/hover.ts +199 -0
  267. package/src/editor/index.ts +65 -0
  268. package/src/editor/kinds.ts +157 -0
  269. package/src/editor/layout.ts +189 -0
  270. package/src/editor/manifest.ts +119 -0
  271. package/src/editor/reading.ts +69 -0
  272. package/src/editor/scan.ts +162 -0
  273. package/src/editor/scope.ts +122 -0
  274. package/src/editor/signature.ts +150 -0
  275. package/src/editor/site.ts +233 -0
  276. package/src/editor/spacing.ts +132 -0
@@ -0,0 +1,186 @@
1
+ /**
2
+ * The round trips a run's fills make up, in the order they opened.
3
+ *
4
+ * `charges[index]` is the money `fills[index]` was charged, rounded once by
5
+ * whoever computed it, so the two travel as one thing and nothing here rounds
6
+ * anything a second time. A caller with no cost model supplies no charges at
7
+ * all and every trade's charges are zero.
8
+ *
9
+ * The fills are read in `seq` order whatever order they are handed in, because
10
+ * `seq` is the order the engine folded them and a report that depended on the
11
+ * order a caller happened to be holding them in would not be reproducible. The
12
+ * marks are read in bar order for the same reason, and a bar is marked after
13
+ * every fill up to it has been folded, because a fill happens during its bar
14
+ * and the close comes after.
15
+ */
16
+ export function tradesOf(fills, charges, marks, contract) {
17
+ const settled = inSeqOrder(fills, charges);
18
+ const built = [];
19
+ const live = [];
20
+ let next = 0;
21
+ for (const bar of inBarOrder(marks)) {
22
+ while (next < settled.length) {
23
+ const one = settled[next];
24
+ if (one === undefined || one.fill.barIndex > bar.barIndex)
25
+ break;
26
+ fold(one, built, live);
27
+ next += 1;
28
+ }
29
+ // A bar with no close is not a price anything can be marked at. It marks
30
+ // nothing rather than marking zero, which would read as a total loss.
31
+ if (bar.close !== null)
32
+ markTo(live, bar.close, contract.pointValue);
33
+ }
34
+ for (; next < settled.length; next += 1) {
35
+ const one = settled[next];
36
+ if (one !== undefined)
37
+ fold(one, built, live);
38
+ }
39
+ return built.map((trade) => finish(trade, contract));
40
+ }
41
+ function inSeqOrder(fills, charges) {
42
+ const paired = fills.map((fill, index) => ({ fill, charge: charges[index] ?? 0 }));
43
+ return paired.sort((a, b) => a.fill.seq - b.fill.seq);
44
+ }
45
+ function inBarOrder(marks) {
46
+ return marks.slice().sort((a, b) => a.barIndex - b.barIndex);
47
+ }
48
+ /**
49
+ * How much of a move from one size to another closed what was held.
50
+ *
51
+ * Exported to the module and not through its door: `markers.ts` asks the same
52
+ * question of the same fills, and the rule for what a move closed and what it
53
+ * opened is one rule. Two folds may read a fill differently and produce a
54
+ * marker for an entry the trade list calls an exit, so they read it here.
55
+ *
56
+ * A move to the other side of zero closed all of it, which is the case a
57
+ * destination that overfilled produces and the one this has to get right.
58
+ */
59
+ export function closedBy(before, after) {
60
+ if (before === 0)
61
+ return 0;
62
+ const same = Math.sign(after) === Math.sign(before);
63
+ return same ? Math.max(0, Math.abs(before) - Math.abs(after)) : Math.abs(before);
64
+ }
65
+ /** And how much of it opened something, which is the rest of the same move. */
66
+ export function openedBy(before, after) {
67
+ if (after === 0)
68
+ return 0;
69
+ if (before === 0 || Math.sign(after) !== Math.sign(before))
70
+ return Math.abs(after);
71
+ return Math.max(0, Math.abs(after) - Math.abs(before));
72
+ }
73
+ /** One fill against the trades its reference holds. */
74
+ function fold(one, built, live) {
75
+ const fill = one.fill;
76
+ const closing = closedBy(fill.refSizeBefore, fill.refSizeAfter);
77
+ const opening = openedBy(fill.refSizeBefore, fill.refSizeAfter);
78
+ const at = live.findIndex((trade) => trade.positionRef === fill.positionRef);
79
+ const held = at < 0 ? null : (live[at] ?? null);
80
+ let paid = false;
81
+ if (held !== null && closing > 0) {
82
+ held.exitUnits += closing;
83
+ held.exitCost += closing * fill.price;
84
+ held.exits += 1;
85
+ held.charges += one.charge;
86
+ paid = true;
87
+ // What the reference left this trade holding: nothing at all when the fill
88
+ // carried it through zero, since the other side of zero is the next trade.
89
+ held.size = opening > 0 ? 0 : fill.refSizeAfter;
90
+ if (held.size === 0) {
91
+ held.closedOnBar = fill.barIndex;
92
+ held.closedAt = fill.barTime;
93
+ live.splice(at, 1);
94
+ }
95
+ }
96
+ if (opening > 0) {
97
+ // A fill that closed something opens a trade of its own rather than adding
98
+ // to the one it just finished.
99
+ const adding = closing > 0 ? null : held;
100
+ if (adding === null) {
101
+ const fresh = begin(fill, opening, built.length + 1);
102
+ built.push(fresh);
103
+ live.push(fresh);
104
+ if (!paid)
105
+ fresh.charges += one.charge;
106
+ }
107
+ else {
108
+ adding.entryUnits += opening;
109
+ adding.entryCost += opening * fill.price;
110
+ adding.entries += 1;
111
+ adding.size = fill.refSizeAfter;
112
+ if (!paid)
113
+ adding.charges += one.charge;
114
+ }
115
+ return;
116
+ }
117
+ // A fill that moved nothing still cost something, and it cost it on account
118
+ // of the trade its reference is holding.
119
+ if (!paid && held !== null)
120
+ held.charges += one.charge;
121
+ }
122
+ function begin(fill, units, index) {
123
+ return {
124
+ index,
125
+ positionRef: fill.positionRef,
126
+ side: fill.refSizeAfter > 0 ? 'long' : 'short',
127
+ openedOnBar: fill.barIndex,
128
+ openedAt: fill.barTime,
129
+ closedOnBar: null,
130
+ closedAt: null,
131
+ entryUnits: units,
132
+ entryCost: units * fill.price,
133
+ exitUnits: 0,
134
+ exitCost: 0,
135
+ entries: 1,
136
+ exits: 0,
137
+ charges: 0,
138
+ size: fill.refSizeAfter,
139
+ maxFavourable: 0,
140
+ maxAdverse: 0,
141
+ };
142
+ }
143
+ /** Every open trade against one bar's close. */
144
+ function markTo(live, close, pointValue) {
145
+ for (const trade of live) {
146
+ const entry = averageOf(trade.entryCost, trade.entryUnits);
147
+ const excursion = (close - entry) * trade.size * pointValue;
148
+ if (excursion > trade.maxFavourable)
149
+ trade.maxFavourable = excursion;
150
+ if (excursion < trade.maxAdverse)
151
+ trade.maxAdverse = excursion;
152
+ }
153
+ }
154
+ function averageOf(cost, units) {
155
+ return units === 0 ? 0 : cost / units;
156
+ }
157
+ function finish(trade, contract) {
158
+ const entryPrice = averageOf(trade.entryCost, trade.entryUnits);
159
+ const exitPrice = trade.exitUnits === 0 ? null : trade.exitCost / trade.exitUnits;
160
+ const way = trade.side === 'long' ? 1 : -1;
161
+ const gross = exitPrice === null
162
+ ? 0
163
+ : (exitPrice - entryPrice) * trade.exitUnits * contract.pointValue * way;
164
+ return {
165
+ index: trade.index,
166
+ positionRef: trade.positionRef,
167
+ side: trade.side,
168
+ openedOnBar: trade.openedOnBar,
169
+ openedAt: trade.openedAt,
170
+ closedOnBar: trade.closedOnBar,
171
+ closedAt: trade.closedAt,
172
+ barsHeld: trade.closedOnBar === null ? null : trade.closedOnBar - trade.openedOnBar,
173
+ units: trade.entryUnits,
174
+ entryPrice,
175
+ exitPrice,
176
+ entries: trade.entries,
177
+ exits: trade.exits,
178
+ grossProfit: gross,
179
+ charges: trade.charges,
180
+ netProfit: gross - trade.charges,
181
+ maxFavourable: trade.maxFavourable,
182
+ maxAdverse: trade.maxAdverse,
183
+ isOpen: trade.closedOnBar === null,
184
+ };
185
+ }
186
+ //# sourceMappingURL=trades.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trades.js","sourceRoot":"","sources":["../../../src/core/accounting/trades.ts"],"names":[],"mappings":"AAyFA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CACtB,KAA8B,EAC9B,OAAyB,EACzB,KAAyB,EACzB,QAAkB;IAElB,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAe,EAAE,CAAC;IAE5B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ;gBAAE,MAAM;YACjE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACvB,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;QACD,yEAAyE;QACzE,sEAAsE;QACtE,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI;YAAE,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,KAAK,SAAS;YAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AACvD,CAAC;AA8BD,SAAS,UAAU,CACjB,KAA8B,EAC9B,OAAyB;IAEzB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,UAAU,CAAC,KAAyB;IAC3C,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,KAAa;IACpD,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACnF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,KAAa;IACpD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1B,IAAI,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,uDAAuD;AACvD,SAAS,IAAI,CAAC,GAAY,EAAE,KAAiB,EAAE,IAAgB;IAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;IAChD,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC;QAC1B,IAAI,CAAC,QAAQ,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QACtC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;QAC3B,IAAI,GAAG,IAAI,CAAC;QACZ,2EAA2E;QAC3E,2EAA2E;QAC3E,IAAI,CAAC,IAAI,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QAChD,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC;YACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,2EAA2E;QAC3E,+BAA+B;QAC/B,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,CAAC,IAAI;gBAAE,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,UAAU,IAAI,OAAO,CAAC;YAC7B,MAAM,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;YACzC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;YACpB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;YAChC,IAAI,CAAC,IAAI;gBAAE,MAAM,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1C,CAAC;QACD,OAAO;IACT,CAAC;IAED,4EAA4E;IAC5E,yCAAyC;IACzC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI;QAAE,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;AACzD,CAAC;AAED,SAAS,KAAK,CAAC,IAAkB,EAAE,KAAa,EAAE,KAAa;IAC7D,OAAO;QACL,KAAK;QACL,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,IAAI,EAAE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;QAC9C,WAAW,EAAE,IAAI,CAAC,QAAQ;QAC1B,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;QACd,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC,KAAK;QAC7B,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,IAAI,CAAC,YAAY;QACvB,aAAa,EAAE,CAAC;QAChB,UAAU,EAAE,CAAC;KACd,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,SAAS,MAAM,CAAC,IAAyB,EAAE,KAAa,EAAE,UAAkB;IAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;QAC5D,IAAI,SAAS,GAAG,KAAK,CAAC,aAAa;YAAE,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC;QACrE,IAAI,SAAS,GAAG,KAAK,CAAC,UAAU;YAAE,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa;IAC5C,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;AACxC,CAAC;AAED,SAAS,MAAM,CAAC,KAAe,EAAE,QAAkB;IACjD,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC;IAClF,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,KAAK,GACT,SAAS,KAAK,IAAI;QAChB,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC;IAC7E,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW;QACnF,KAAK,EAAE,KAAK,CAAC,UAAU;QACvB,UAAU;QACV,SAAS;QACT,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC,OAAO;QAChC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { RunRecord } from './record.js';
2
+ /** What two runs came to, beside each other. */
3
+ export interface RunComparison {
4
+ /** False when the bars hash or the contract differ. */
5
+ readonly comparable: boolean;
6
+ readonly differences: readonly {
7
+ readonly what: 'bars' | 'contract' | 'costs' | 'fill' | 'inputs' | 'program' | 'range';
8
+ readonly detail: string;
9
+ }[];
10
+ readonly deltas: readonly {
11
+ /** A field of Summary. */
12
+ readonly name: string;
13
+ readonly before: number;
14
+ readonly after: number;
15
+ readonly delta: number;
16
+ }[];
17
+ /** (expectancyB - expectancyA) / sqrt(seA^2 + seB^2). */
18
+ readonly separation: number | null;
19
+ /** Trades opening on the same bar with the same side in both. */
20
+ readonly sharedTrades: number;
21
+ }
22
+ /**
23
+ * Two runs, side by side, and whether the gap between them is a result.
24
+ *
25
+ * **Comparable is about the inputs, not about the outputs.** Two runs over
26
+ * different bars, or on different contracts, are two studies: the money in one
27
+ * is not the money in the other, and subtracting them is arithmetic with no
28
+ * meaning behind it. A different program over the same bars is the opposite of
29
+ * that. It is the comparison somebody actually wants, so a differing program is
30
+ * reported as a difference and does not make the pair incomparable.
31
+ *
32
+ * **Every difference is named even when the pair is comparable**, because the
33
+ * reason a run improved is as often a setting somebody forgot they had changed
34
+ * as it is the change they meant to test. A comparison reporting only the money
35
+ * would let that through, and it would read as a result.
36
+ */
37
+ export declare function compareRuns(before: RunRecord, after: RunRecord): RunComparison;
38
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/core/backtest/compare.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,SAAS;QAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;QACvF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,EAAE,CAAC;IACJ,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,0BAA0B;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;KACxB,EAAE,CAAC;IACJ,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAuCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,aAAa,CAa9E"}
@@ -0,0 +1,189 @@
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
+ 'averageBarsHeld',
32
+ 'barsInMarket',
33
+ 'barCount',
34
+ ];
35
+ /**
36
+ * Two runs, side by side, and whether the gap between them is a result.
37
+ *
38
+ * **Comparable is about the inputs, not about the outputs.** Two runs over
39
+ * different bars, or on different contracts, are two studies: the money in one
40
+ * is not the money in the other, and subtracting them is arithmetic with no
41
+ * meaning behind it. A different program over the same bars is the opposite of
42
+ * that. It is the comparison somebody actually wants, so a differing program is
43
+ * reported as a difference and does not make the pair incomparable.
44
+ *
45
+ * **Every difference is named even when the pair is comparable**, because the
46
+ * reason a run improved is as often a setting somebody forgot they had changed
47
+ * as it is the change they meant to test. A comparison reporting only the money
48
+ * would let that through, and it would read as a result.
49
+ */
50
+ export function compareRuns(before, after) {
51
+ const differences = differencesBetween(before, after);
52
+ const blocking = differences.some((one) => one.what === 'bars' || one.what === 'contract');
53
+ return {
54
+ comparable: !blocking,
55
+ differences,
56
+ deltas: deltasBetween(before.report.summary, after.report.summary),
57
+ // Withheld rather than computed on an incomparable pair. A separation
58
+ // between two runs over different bars is a number, and it means nothing.
59
+ separation: blocking ? null : separationBetween(before.report.summary, after.report.summary),
60
+ sharedTrades: sharedTradesBetween(before.report.trades, after.report.trades),
61
+ };
62
+ }
63
+ /**
64
+ * What differs between two runs' inputs, in a fixed order.
65
+ *
66
+ * Compared through the repository's one canonical writer rather than field by
67
+ * field, so a settings shape that grows a field is compared on that field
68
+ * without this function being edited. Field by field is how a comparison
69
+ * quietly stops covering whatever was added to the settings last.
70
+ */
71
+ function differencesBetween(before, after) {
72
+ const found = [];
73
+ if (before.bars.hash !== after.bars.hash) {
74
+ found.push({
75
+ what: 'bars',
76
+ detail: `different bars: ${before.bars.count} rows hashing ${before.bars.hash}, against ${after.bars.count} hashing ${after.bars.hash}`,
77
+ });
78
+ }
79
+ if (canonicalise(before.settings.contract) !== canonicalise(after.settings.contract)) {
80
+ found.push({ what: 'contract', detail: 'the two runs are on different contracts' });
81
+ }
82
+ if (before.programHash !== after.programHash) {
83
+ found.push({
84
+ what: 'program',
85
+ detail: `different program: ${before.programHash}, against ${after.programHash}`,
86
+ });
87
+ }
88
+ if (canonicalise(before.settings.range) !== canonicalise(after.settings.range)) {
89
+ found.push({ what: 'range', detail: 'the two runs cover different date ranges' });
90
+ }
91
+ if (canonicalise(before.settings.costs) !== canonicalise(after.settings.costs)) {
92
+ found.push({ what: 'costs', detail: 'the two runs were charged under different cost models' });
93
+ }
94
+ if (canonicalise(before.settings.fill) !== canonicalise(after.settings.fill)) {
95
+ found.push({ what: 'fill', detail: 'the two runs were filled under different policies' });
96
+ }
97
+ if (canonicalise(before.settings.inputs) !== canonicalise(after.settings.inputs)) {
98
+ found.push({ what: 'inputs', detail: 'the two scripts ran with different input values' });
99
+ }
100
+ return found;
101
+ }
102
+ /**
103
+ * Every compared figure, before and after.
104
+ *
105
+ * A summary carries null where a figure has no meaning: no win rate until a
106
+ * trade closes, no profit factor without a loss. Null on one side and a number
107
+ * on the other is a real thing to report, and a delta between them is not, so
108
+ * the row appears with both values and a delta of zero. Subtracting from null
109
+ * would invent a movement out of a figure that was never there.
110
+ */
111
+ function deltasBetween(before, after) {
112
+ // Widened once, here. COMPARED is a list of names and a summary is a closed
113
+ // shape, so the lookup is by string either way; doing it in one place keeps
114
+ // the rest of this file reading the real type.
115
+ const a0 = before;
116
+ const b0 = after;
117
+ const deltas = [];
118
+ for (const name of COMPARED) {
119
+ const a = numberOf(a0[name]);
120
+ const b = numberOf(b0[name]);
121
+ // Neither side holds a figure: a field of no summary, which is nothing to
122
+ // report rather than a row of three zeroes.
123
+ if (a === null && b === null)
124
+ continue;
125
+ deltas.push({
126
+ name,
127
+ before: a ?? 0,
128
+ after: b ?? 0,
129
+ delta: a === null || b === null ? 0 : (b ?? 0) - (a ?? 0),
130
+ });
131
+ }
132
+ return deltas;
133
+ }
134
+ /** A figure, or none where the summary carries null or a string for it. */
135
+ function numberOf(value) {
136
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
137
+ }
138
+ /**
139
+ * How many standard errors apart the two expectancies are.
140
+ *
141
+ * Analytic, with no resampling and no random number generator, so two runs of
142
+ * this comparison over the same pair give the same figure for ever and a
143
+ * decision taken on it is one anybody can reproduce.
144
+ *
145
+ * **Null rather than a large number where there is no noise to measure.** A run
146
+ * with fewer than two closed trades has a standard error of zero, because one
147
+ * trade has no spread, and where both are zero the ratio divides by it.
148
+ * Returning infinity there would read as infinite confidence, which is the
149
+ * exact opposite of what one trade tells anybody. Null says the question cannot
150
+ * be answered from these two runs, which is the truth about them.
151
+ */
152
+ function separationBetween(before, after) {
153
+ const noise = Math.sqrt(before.expectancyStandardError * before.expectancyStandardError +
154
+ after.expectancyStandardError * after.expectancyStandardError);
155
+ if (!Number.isFinite(noise) || noise === 0)
156
+ return null;
157
+ const gap = after.expectancy - before.expectancy;
158
+ return Number.isFinite(gap) ? gap / noise : null;
159
+ }
160
+ /**
161
+ * How many trades the two runs took alike.
162
+ *
163
+ * Alike means opened on the same bar on the same side, which is the coarsest
164
+ * thing two runs can agree about and the only one that survives a change to
165
+ * sizing or to costs. It is what says whether a change moved the money by
166
+ * trading differently or by trading the same and paying differently, and those
167
+ * are not the same result however alike the two totals look.
168
+ *
169
+ * Counted as a multiset, so two long trades opening on one bar in one run
170
+ * against one in the other share one trade rather than two.
171
+ */
172
+ function sharedTradesBetween(before, after) {
173
+ const counts = new Map();
174
+ for (const trade of before) {
175
+ const key = `${trade.openedOnBar}:${trade.side}`;
176
+ counts.set(key, (counts.get(key) ?? 0) + 1);
177
+ }
178
+ let shared = 0;
179
+ for (const trade of after) {
180
+ const key = `${trade.openedOnBar}:${trade.side}`;
181
+ const left = counts.get(key) ?? 0;
182
+ if (left > 0) {
183
+ counts.set(key, left - 1);
184
+ shared += 1;
185
+ }
186
+ }
187
+ return shared;
188
+ }
189
+ //# 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,29 @@
1
+ import type { Diagnostic } from '../diagnostics/index.js';
2
+ import type { CompiledProgram } from '../emit/index.js';
3
+ import type { RecordedBar, RunRecord } from './record.js';
4
+ import type { BacktestSettings } from './settings.js';
5
+ /** What a run came to, or why it could not be carried out at all. */
6
+ export type BacktestResult = {
7
+ readonly ok: true;
8
+ readonly record: RunRecord;
9
+ } | {
10
+ readonly ok: false;
11
+ readonly diagnostic: Diagnostic;
12
+ };
13
+ /** The few choices a driver has that are not settings of the run itself. */
14
+ export interface DriveOptions {
15
+ /** Whether the bars travel in the record. Inline is the conformance form. */
16
+ readonly form?: 'inline' | 'referenced';
17
+ }
18
+ /**
19
+ * One run, from a compiled program to a record of it.
20
+ *
21
+ * A refusal before the first bar comes back as a refusal and not as a record:
22
+ * a program that would not load, a setting that cannot be applied and a window
23
+ * holding no bars are all runs that did not happen, and a record of one would
24
+ * be a document asserting figures nothing computed. A failure during a bar is
25
+ * the other way round: the run happened, it stopped, and the record carries
26
+ * both what it did and the diagnostic that stopped it.
27
+ */
28
+ export declare function backtest(program: CompiledProgram, bars: readonly RecordedBar[], settings: BacktestSettings, options?: DriveOptions): BacktestResult;
29
+ //# sourceMappingURL=drive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../../src/core/backtest/drive.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAiBxD,OAAO,KAAK,EACV,WAAW,EAIX,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,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;CACzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,GAAE,YAAiB,GACzB,cAAc,CAgDhB"}