@quantform/core 0.5.15 → 0.6.4

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 (562) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/adapter/adapter-aggregate.d.ts +41 -5
  3. package/dist/adapter/adapter-aggregate.d.ts.map +1 -0
  4. package/dist/adapter/adapter-aggregate.js +114 -54
  5. package/dist/adapter/adapter.d.ts +29 -15
  6. package/dist/adapter/adapter.d.ts.map +1 -0
  7. package/dist/adapter/adapter.js +4 -1
  8. package/dist/adapter/backtester/backtester-adapter.d.ts +4 -3
  9. package/dist/adapter/backtester/backtester-adapter.d.ts.map +1 -0
  10. package/dist/adapter/backtester/backtester-adapter.js +28 -15
  11. package/dist/adapter/backtester/backtester-cursor.d.ts +5 -4
  12. package/dist/adapter/backtester/backtester-cursor.d.ts.map +1 -0
  13. package/dist/adapter/backtester/backtester-cursor.js +24 -14
  14. package/dist/adapter/backtester/backtester-streamer.d.ts +20 -2
  15. package/dist/adapter/backtester/backtester-streamer.d.ts.map +1 -0
  16. package/dist/adapter/backtester/backtester-streamer.js +54 -40
  17. package/dist/adapter/backtester/error.d.ts +3 -0
  18. package/dist/adapter/backtester/error.d.ts.map +1 -0
  19. package/dist/adapter/backtester/error.js +11 -0
  20. package/dist/adapter/backtester/index.d.ts +1 -0
  21. package/dist/adapter/backtester/index.d.ts.map +1 -0
  22. package/dist/adapter/backtester/index.js +0 -1
  23. package/dist/adapter/error.d.ts +2 -0
  24. package/dist/adapter/error.d.ts.map +1 -0
  25. package/dist/adapter/error.js +5 -2
  26. package/dist/adapter/index.d.ts +1 -0
  27. package/dist/adapter/index.d.ts.map +1 -0
  28. package/dist/adapter/index.js +0 -1
  29. package/dist/adapter/paper/engine/paper-engine.d.ts +1 -0
  30. package/dist/adapter/paper/engine/paper-engine.d.ts.map +1 -0
  31. package/dist/adapter/paper/engine/paper-engine.js +38 -32
  32. package/dist/adapter/paper/index.d.ts +1 -0
  33. package/dist/adapter/paper/index.d.ts.map +1 -0
  34. package/dist/adapter/paper/index.js +0 -1
  35. package/dist/adapter/paper/paper-adapter.d.ts +7 -5
  36. package/dist/adapter/paper/paper-adapter.d.ts.map +1 -0
  37. package/dist/adapter/paper/paper-adapter.js +49 -25
  38. package/dist/cli/build.d.ts +1 -0
  39. package/dist/cli/build.d.ts.map +1 -0
  40. package/dist/cli/build.js +18 -8
  41. package/dist/cli/dev.d.ts +1 -0
  42. package/dist/cli/dev.d.ts.map +1 -0
  43. package/dist/cli/dev.js +52 -12
  44. package/dist/cli/error.d.ts +2 -0
  45. package/dist/cli/error.d.ts.map +1 -0
  46. package/dist/cli/error.js +7 -0
  47. package/dist/cli/index.d.ts +1 -0
  48. package/dist/cli/index.d.ts.map +1 -0
  49. package/dist/cli/index.js +21 -10
  50. package/dist/cli/internal/workspace.d.ts +1 -7
  51. package/dist/cli/internal/workspace.d.ts.map +1 -0
  52. package/dist/cli/internal/workspace.js +1 -6
  53. package/dist/cli/pull.d.ts +1 -0
  54. package/dist/cli/pull.d.ts.map +1 -0
  55. package/dist/cli/pull.js +65 -40
  56. package/dist/cli/run.d.ts +2 -1
  57. package/dist/cli/run.d.ts.map +1 -0
  58. package/dist/cli/run.js +52 -14
  59. package/dist/cli/test.d.ts +2 -1
  60. package/dist/cli/test.d.ts.map +1 -0
  61. package/dist/cli/test.js +59 -34
  62. package/dist/domain/asset.d.ts +24 -4
  63. package/dist/domain/asset.d.ts.map +1 -0
  64. package/dist/domain/asset.js +23 -8
  65. package/dist/domain/{balance.operator.d.ts → balance-operator.d.ts} +1 -0
  66. package/dist/domain/balance-operator.d.ts.map +1 -0
  67. package/dist/domain/{balance.operator.js → balance-operator.js} +0 -1
  68. package/dist/domain/balance.d.ts +35 -11
  69. package/dist/domain/balance.d.ts.map +1 -0
  70. package/dist/domain/balance.js +46 -17
  71. package/dist/domain/candle-operator.d.ts +11 -0
  72. package/dist/domain/candle-operator.d.ts.map +1 -0
  73. package/dist/domain/{candle.operator.js → candle-operator.js} +11 -5
  74. package/dist/domain/candle.d.ts +9 -8
  75. package/dist/domain/candle.d.ts.map +1 -0
  76. package/dist/domain/candle.js +3 -3
  77. package/dist/domain/commission.d.ts +12 -9
  78. package/dist/domain/commission.d.ts.map +1 -0
  79. package/dist/domain/commission.js +7 -6
  80. package/dist/domain/component.d.ts +1 -0
  81. package/dist/domain/component.d.ts.map +1 -0
  82. package/dist/domain/component.js +0 -1
  83. package/dist/domain/error.d.ts +6 -4
  84. package/dist/domain/error.d.ts.map +1 -0
  85. package/dist/domain/error.js +4 -5
  86. package/dist/domain/index.d.ts +9 -7
  87. package/dist/domain/index.d.ts.map +1 -0
  88. package/dist/domain/index.js +8 -8
  89. package/dist/domain/{instrument.operator.d.ts → instrument-operator.d.ts} +1 -0
  90. package/dist/domain/instrument-operator.d.ts.map +1 -0
  91. package/dist/domain/{instrument.operator.js → instrument-operator.js} +0 -1
  92. package/dist/domain/instrument.d.ts +9 -6
  93. package/dist/domain/instrument.d.ts.map +1 -0
  94. package/dist/domain/instrument.js +7 -3
  95. package/dist/domain/{order.operator.d.ts → order-operator.d.ts} +1 -0
  96. package/dist/domain/order-operator.d.ts.map +1 -0
  97. package/dist/domain/order-operator.js +16 -0
  98. package/dist/domain/order.d.ts +17 -22
  99. package/dist/domain/order.d.ts.map +1 -0
  100. package/dist/domain/order.js +23 -34
  101. package/dist/domain/{orderbook.operator.d.ts → orderbook-operator.d.ts} +1 -0
  102. package/dist/domain/orderbook-operator.d.ts.map +1 -0
  103. package/dist/domain/{orderbook.operator.js → orderbook-operator.js} +0 -1
  104. package/dist/domain/orderbook.d.ts +26 -10
  105. package/dist/domain/orderbook.d.ts.map +1 -0
  106. package/dist/domain/orderbook.js +12 -6
  107. package/dist/domain/{position.operator.d.ts → position-operator.d.ts} +7 -4
  108. package/dist/domain/position-operator.d.ts.map +1 -0
  109. package/dist/domain/{position.operator.js → position-operator.js} +13 -6
  110. package/dist/domain/position.d.ts +10 -9
  111. package/dist/domain/position.d.ts.map +1 -0
  112. package/dist/domain/position.js +4 -4
  113. package/dist/domain/session-builder.d.ts +54 -0
  114. package/dist/domain/session-builder.d.ts.map +1 -0
  115. package/dist/domain/session-builder.js +105 -0
  116. package/dist/domain/session.d.ts +54 -13
  117. package/dist/domain/session.d.ts.map +1 -0
  118. package/dist/domain/session.js +104 -40
  119. package/dist/domain/timeframe.d.ts +1 -0
  120. package/dist/domain/timeframe.d.ts.map +1 -0
  121. package/dist/domain/timeframe.js +0 -1
  122. package/dist/domain/{trade.operator.d.ts → trade-operator.d.ts} +1 -0
  123. package/dist/domain/trade-operator.d.ts.map +1 -0
  124. package/dist/domain/{trade.operator.js → trade-operator.js} +0 -1
  125. package/dist/domain/trade.d.ts +12 -7
  126. package/dist/domain/trade.d.ts.map +1 -0
  127. package/dist/domain/trade.js +8 -2
  128. package/dist/index.d.ts +2 -2
  129. package/dist/index.d.ts.map +1 -0
  130. package/dist/index.js +1 -3
  131. package/dist/shared/collections.d.ts +20 -1
  132. package/dist/shared/collections.d.ts.map +1 -0
  133. package/dist/shared/collections.js +98 -8
  134. package/dist/shared/datetime.d.ts +1 -0
  135. package/dist/shared/datetime.d.ts.map +1 -0
  136. package/dist/shared/datetime.js +0 -1
  137. package/dist/shared/decimals.d.ts +28 -6
  138. package/dist/shared/decimals.d.ts.map +1 -0
  139. package/dist/shared/decimals.js +33 -35
  140. package/dist/shared/environment.d.ts +3 -0
  141. package/dist/shared/environment.d.ts.map +1 -0
  142. package/dist/shared/environment.js +15 -0
  143. package/dist/shared/index.d.ts +3 -1
  144. package/dist/shared/index.d.ts.map +1 -0
  145. package/dist/shared/index.js +2 -2
  146. package/dist/shared/logger.d.ts +5 -7
  147. package/dist/shared/logger.d.ts.map +1 -0
  148. package/dist/shared/logger.js +24 -8
  149. package/dist/shared/pipe.d.ts +5 -0
  150. package/dist/shared/pipe.d.ts.map +1 -0
  151. package/dist/shared/pipe.js +8 -0
  152. package/dist/shared/policy.d.ts +1 -0
  153. package/dist/shared/policy.d.ts.map +1 -0
  154. package/dist/shared/policy.js +0 -1
  155. package/dist/storage/cache.d.ts +1 -0
  156. package/dist/storage/cache.d.ts.map +1 -0
  157. package/dist/storage/cache.js +30 -19
  158. package/dist/storage/feed.d.ts +33 -4
  159. package/dist/storage/feed.d.ts.map +1 -0
  160. package/dist/storage/feed.js +93 -19
  161. package/dist/storage/index.d.ts +1 -0
  162. package/dist/storage/index.d.ts.map +1 -0
  163. package/dist/storage/index.js +0 -1
  164. package/dist/storage/measurement.d.ts +20 -0
  165. package/dist/storage/measurement.d.ts.map +1 -0
  166. package/dist/storage/measurement.js +41 -10
  167. package/dist/storage/storage.d.ts +41 -0
  168. package/dist/storage/storage.d.ts.map +1 -0
  169. package/dist/storage/storage.js +69 -33
  170. package/dist/store/error.d.ts +9 -0
  171. package/dist/store/error.d.ts.map +1 -0
  172. package/dist/store/error.js +31 -0
  173. package/dist/store/index.d.ts +8 -7
  174. package/dist/store/index.d.ts.map +1 -0
  175. package/dist/store/index.js +7 -8
  176. package/dist/store/{store-balance.event.d.ts → store-balance-event.d.ts} +20 -7
  177. package/dist/store/store-balance-event.d.ts.map +1 -0
  178. package/dist/store/{store-balance.event.js → store-balance-event.js} +54 -10
  179. package/dist/store/{store.event.d.ts → store-event.d.ts} +1 -0
  180. package/dist/store/store-event.d.ts.map +1 -0
  181. package/dist/store/{store.event.js → store-event.js} +0 -1
  182. package/dist/store/{store-instrument.event.d.ts → store-instrument-event.d.ts} +5 -4
  183. package/dist/store/store-instrument-event.d.ts.map +1 -0
  184. package/dist/store/{store-instrument.event.js → store-instrument-event.js} +13 -5
  185. package/dist/store/{store-order.event.d.ts → store-order-event.d.ts} +10 -5
  186. package/dist/store/store-order-event.d.ts.map +1 -0
  187. package/dist/store/{store-order.event.js → store-order-event.js} +24 -20
  188. package/dist/store/store-orderbook-event.d.ts +13 -0
  189. package/dist/store/store-orderbook-event.d.ts.map +1 -0
  190. package/dist/store/store-orderbook-event.js +43 -0
  191. package/dist/store/{store-position.event.d.ts → store-position-event.d.ts} +7 -6
  192. package/dist/store/store-position-event.d.ts.map +1 -0
  193. package/dist/store/{store-position.event.js → store-position-event.js} +36 -17
  194. package/dist/store/store-state.d.ts +3 -2
  195. package/dist/store/store-state.d.ts.map +1 -0
  196. package/dist/store/store-state.js +1 -1
  197. package/dist/store/store-trade-event.d.ts +17 -0
  198. package/dist/store/store-trade-event.d.ts.map +1 -0
  199. package/dist/store/{store-trade.event.js → store-trade-event.js} +14 -5
  200. package/dist/store/store.d.ts +2 -1
  201. package/dist/store/store.d.ts.map +1 -0
  202. package/dist/store/store.js +0 -1
  203. package/dist/strategy.d.ts +8 -0
  204. package/dist/strategy.d.ts.map +1 -0
  205. package/dist/strategy.js +44 -0
  206. package/jest.config.ts +13 -0
  207. package/package.json +19 -30
  208. package/src/adapter/adapter-aggregate.ts +57 -25
  209. package/src/adapter/adapter.ts +15 -18
  210. package/src/adapter/backtester/backtester-adapter.ts +14 -7
  211. package/src/adapter/backtester/backtester-cursor.spec.ts +20 -18
  212. package/src/adapter/backtester/backtester-cursor.ts +6 -6
  213. package/src/adapter/backtester/backtester-streamer.spec.ts +18 -15
  214. package/src/adapter/backtester/backtester-streamer.ts +21 -30
  215. package/src/adapter/backtester/error.ts +7 -0
  216. package/src/adapter/error.ts +4 -0
  217. package/src/adapter/paper/engine/paper-engine.spec.ts +54 -30
  218. package/src/adapter/paper/engine/paper-engine.ts +62 -46
  219. package/src/adapter/paper/paper-adapter.ts +30 -9
  220. package/src/cli/build.ts +1 -1
  221. package/src/cli/dev.ts +15 -7
  222. package/src/cli/error.ts +5 -0
  223. package/src/cli/internal/workspace.ts +0 -11
  224. package/src/cli/pull.ts +28 -36
  225. package/src/cli/run.ts +14 -11
  226. package/src/cli/test.ts +24 -37
  227. package/src/domain/asset.spec.ts +4 -4
  228. package/src/domain/asset.ts +8 -15
  229. package/src/domain/{balance.operator.spec.ts → balance-operator.spec.ts} +4 -3
  230. package/src/domain/{balance.operator.ts → balance-operator.ts} +0 -0
  231. package/src/domain/balance.spec.ts +51 -47
  232. package/src/domain/balance.ts +32 -31
  233. package/src/domain/candle-operator.spec.ts +126 -0
  234. package/src/domain/{candle.operator.ts → candle-operator.ts} +24 -7
  235. package/src/domain/candle.spec.ts +13 -12
  236. package/src/domain/candle.ts +9 -9
  237. package/src/domain/commission.spec.ts +13 -12
  238. package/src/domain/commission.ts +15 -11
  239. package/src/domain/error.ts +8 -6
  240. package/src/domain/index.ts +8 -7
  241. package/src/domain/{instrument.operator.spec.ts → instrument-operator.spec.ts} +9 -2
  242. package/src/domain/{instrument.operator.ts → instrument-operator.ts} +0 -0
  243. package/src/domain/instrument.spec.ts +8 -1
  244. package/src/domain/instrument.ts +11 -8
  245. package/src/domain/{order.operator.spec.ts → order-operator.spec.ts} +11 -7
  246. package/src/domain/{order.operator.ts → order-operator.ts} +2 -2
  247. package/src/domain/order.spec.ts +15 -15
  248. package/src/domain/order.ts +34 -61
  249. package/src/domain/{orderbook.operator.spec.ts → orderbook-operator.spec.ts} +15 -3
  250. package/src/domain/{orderbook.operator.ts → orderbook-operator.ts} +0 -0
  251. package/src/domain/orderbook.spec.ts +11 -2
  252. package/src/domain/orderbook.ts +20 -13
  253. package/src/domain/{position.operator.spec.ts → position-operator.spec.ts} +13 -7
  254. package/src/domain/{position.operator.ts → position-operator.ts} +21 -11
  255. package/src/domain/position.spec.ts +14 -10
  256. package/src/domain/position.ts +10 -10
  257. package/src/domain/session-builder.ts +158 -0
  258. package/src/domain/session.spec.ts +5 -12
  259. package/src/domain/session.ts +85 -72
  260. package/src/domain/{trade.operator.spec.ts → trade-operator.spec.ts} +7 -3
  261. package/src/domain/{trade.operator.ts → trade-operator.ts} +0 -0
  262. package/src/domain/trade.spec.ts +6 -2
  263. package/src/domain/trade.ts +9 -7
  264. package/src/index.ts +1 -2
  265. package/src/shared/collections.spec.ts +34 -0
  266. package/src/shared/collections.ts +125 -6
  267. package/src/shared/decimals.spec.ts +18 -24
  268. package/src/shared/decimals.ts +22 -55
  269. package/src/shared/environment.ts +13 -0
  270. package/src/shared/index.ts +2 -1
  271. package/src/shared/logger.ts +35 -7
  272. package/src/shared/pipe.ts +12 -0
  273. package/src/storage/cache.ts +3 -1
  274. package/src/storage/feed.ts +91 -34
  275. package/src/storage/storage.ts +10 -8
  276. package/src/store/error.ts +36 -0
  277. package/src/store/index.ts +7 -7
  278. package/src/store/{store-balance.event.spec.ts → store-balance-event.spec.ts} +8 -8
  279. package/src/store/{store-balance.event.ts → store-balance-event.ts} +58 -15
  280. package/src/store/{store.event.ts → store-event.ts} +0 -0
  281. package/src/store/{store-instrument.event.spec.ts → store-instrument-event.spec.ts} +8 -7
  282. package/src/store/{store-instrument.event.ts → store-instrument-event.ts} +18 -7
  283. package/src/store/store-order-event.spec.ts +32 -0
  284. package/src/store/{store-order.event.ts → store-order-event.ts} +27 -22
  285. package/src/store/store-orderbook-event.spec.ts +39 -0
  286. package/src/store/store-orderbook-event.ts +56 -0
  287. package/src/store/{store-position.event.ts → store-position-event.ts} +41 -22
  288. package/src/store/store-state.ts +3 -3
  289. package/src/store/{store-trade.event.spec.ts → store-trade-event.spec.ts} +16 -14
  290. package/src/store/{store-trade.event.ts → store-trade-event.ts} +14 -8
  291. package/src/store/store.spec.ts +22 -20
  292. package/src/store/store.ts +1 -1
  293. package/src/strategy.ts +47 -0
  294. package/tsconfig.json +12 -5
  295. package/dist/adapter/adapter-aggregate.js.map +0 -1
  296. package/dist/adapter/adapter.js.map +0 -1
  297. package/dist/adapter/backtester/backtester-adapter.js.map +0 -1
  298. package/dist/adapter/backtester/backtester-adapter.spec.d.ts +0 -1
  299. package/dist/adapter/backtester/backtester-adapter.spec.js +0 -82
  300. package/dist/adapter/backtester/backtester-adapter.spec.js.map +0 -1
  301. package/dist/adapter/backtester/backtester-cursor.js.map +0 -1
  302. package/dist/adapter/backtester/backtester-cursor.spec.d.ts +0 -1
  303. package/dist/adapter/backtester/backtester-cursor.spec.js +0 -37
  304. package/dist/adapter/backtester/backtester-cursor.spec.js.map +0 -1
  305. package/dist/adapter/backtester/backtester-streamer.js.map +0 -1
  306. package/dist/adapter/backtester/backtester-streamer.spec.d.ts +0 -1
  307. package/dist/adapter/backtester/backtester-streamer.spec.js +0 -44
  308. package/dist/adapter/backtester/backtester-streamer.spec.js.map +0 -1
  309. package/dist/adapter/backtester/index.js.map +0 -1
  310. package/dist/adapter/error.js.map +0 -1
  311. package/dist/adapter/index.js.map +0 -1
  312. package/dist/adapter/paper/engine/paper-engine.js.map +0 -1
  313. package/dist/adapter/paper/engine/paper-engine.spec.d.ts +0 -1
  314. package/dist/adapter/paper/engine/paper-engine.spec.js +0 -54
  315. package/dist/adapter/paper/engine/paper-engine.spec.js.map +0 -1
  316. package/dist/adapter/paper/index.js.map +0 -1
  317. package/dist/adapter/paper/paper-adapter.js.map +0 -1
  318. package/dist/adapter/paper/paper-adapter.spec.d.ts +0 -1
  319. package/dist/adapter/paper/paper-adapter.spec.js +0 -69
  320. package/dist/adapter/paper/paper-adapter.spec.js.map +0 -1
  321. package/dist/bootstrap.d.ts +0 -11
  322. package/dist/bootstrap.js +0 -73
  323. package/dist/bootstrap.js.map +0 -1
  324. package/dist/cli/build.js.map +0 -1
  325. package/dist/cli/dev.js.map +0 -1
  326. package/dist/cli/index.js.map +0 -1
  327. package/dist/cli/internal/workspace.js.map +0 -1
  328. package/dist/cli/pull.js.map +0 -1
  329. package/dist/cli/run.js.map +0 -1
  330. package/dist/cli/test.js.map +0 -1
  331. package/dist/domain/asset.js.map +0 -1
  332. package/dist/domain/asset.spec.d.ts +0 -1
  333. package/dist/domain/asset.spec.js +0 -55
  334. package/dist/domain/asset.spec.js.map +0 -1
  335. package/dist/domain/balance.js.map +0 -1
  336. package/dist/domain/balance.operator.js.map +0 -1
  337. package/dist/domain/balance.operator.spec.d.ts +0 -1
  338. package/dist/domain/balance.operator.spec.js +0 -23
  339. package/dist/domain/balance.operator.spec.js.map +0 -1
  340. package/dist/domain/balance.spec.d.ts +0 -1
  341. package/dist/domain/balance.spec.js +0 -82
  342. package/dist/domain/balance.spec.js.map +0 -1
  343. package/dist/domain/candle.js.map +0 -1
  344. package/dist/domain/candle.operator.d.ts +0 -9
  345. package/dist/domain/candle.operator.js.map +0 -1
  346. package/dist/domain/candle.operator.spec.d.ts +0 -1
  347. package/dist/domain/candle.operator.spec.js +0 -111
  348. package/dist/domain/candle.operator.spec.js.map +0 -1
  349. package/dist/domain/candle.spec.d.ts +0 -1
  350. package/dist/domain/candle.spec.js +0 -26
  351. package/dist/domain/candle.spec.js.map +0 -1
  352. package/dist/domain/commission.js.map +0 -1
  353. package/dist/domain/commission.spec.d.ts +0 -1
  354. package/dist/domain/commission.spec.js +0 -30
  355. package/dist/domain/commission.spec.js.map +0 -1
  356. package/dist/domain/component.js.map +0 -1
  357. package/dist/domain/error.js.map +0 -1
  358. package/dist/domain/index.js.map +0 -1
  359. package/dist/domain/instrument.js.map +0 -1
  360. package/dist/domain/instrument.operator.js.map +0 -1
  361. package/dist/domain/instrument.operator.spec.d.ts +0 -1
  362. package/dist/domain/instrument.operator.spec.js +0 -24
  363. package/dist/domain/instrument.operator.spec.js.map +0 -1
  364. package/dist/domain/instrument.spec.d.ts +0 -1
  365. package/dist/domain/instrument.spec.js +0 -49
  366. package/dist/domain/instrument.spec.js.map +0 -1
  367. package/dist/domain/order.js.map +0 -1
  368. package/dist/domain/order.operator.js +0 -14
  369. package/dist/domain/order.operator.js.map +0 -1
  370. package/dist/domain/order.operator.spec.d.ts +0 -1
  371. package/dist/domain/order.operator.spec.js +0 -64
  372. package/dist/domain/order.operator.spec.js.map +0 -1
  373. package/dist/domain/order.spec.d.ts +0 -1
  374. package/dist/domain/order.spec.js +0 -33
  375. package/dist/domain/order.spec.js.map +0 -1
  376. package/dist/domain/orderbook.js.map +0 -1
  377. package/dist/domain/orderbook.operator.js.map +0 -1
  378. package/dist/domain/orderbook.operator.spec.d.ts +0 -1
  379. package/dist/domain/orderbook.operator.spec.js +0 -22
  380. package/dist/domain/orderbook.operator.spec.js.map +0 -1
  381. package/dist/domain/orderbook.spec.d.ts +0 -1
  382. package/dist/domain/orderbook.spec.js +0 -13
  383. package/dist/domain/orderbook.spec.js.map +0 -1
  384. package/dist/domain/position.js.map +0 -1
  385. package/dist/domain/position.operator.js.map +0 -1
  386. package/dist/domain/position.operator.spec.d.ts +0 -1
  387. package/dist/domain/position.operator.spec.js +0 -48
  388. package/dist/domain/position.operator.spec.js.map +0 -1
  389. package/dist/domain/position.spec.d.ts +0 -1
  390. package/dist/domain/position.spec.js +0 -30
  391. package/dist/domain/position.spec.js.map +0 -1
  392. package/dist/domain/session.js.map +0 -1
  393. package/dist/domain/session.spec.d.ts +0 -1
  394. package/dist/domain/session.spec.js +0 -23
  395. package/dist/domain/session.spec.js.map +0 -1
  396. package/dist/domain/timeframe.js.map +0 -1
  397. package/dist/domain/trade.js.map +0 -1
  398. package/dist/domain/trade.operator.js.map +0 -1
  399. package/dist/domain/trade.operator.spec.d.ts +0 -1
  400. package/dist/domain/trade.operator.spec.js +0 -24
  401. package/dist/domain/trade.operator.spec.js.map +0 -1
  402. package/dist/domain/trade.spec.d.ts +0 -1
  403. package/dist/domain/trade.spec.js +0 -13
  404. package/dist/domain/trade.spec.js.map +0 -1
  405. package/dist/index.js.map +0 -1
  406. package/dist/indicator/atr.d.ts +0 -3
  407. package/dist/indicator/atr.js +0 -16
  408. package/dist/indicator/atr.js.map +0 -1
  409. package/dist/indicator/cross.d.ts +0 -3
  410. package/dist/indicator/cross.js +0 -41
  411. package/dist/indicator/cross.js.map +0 -1
  412. package/dist/indicator/cross.spec.d.ts +0 -1
  413. package/dist/indicator/cross.spec.js +0 -101
  414. package/dist/indicator/cross.spec.js.map +0 -1
  415. package/dist/indicator/donchian.d.ts +0 -9
  416. package/dist/indicator/donchian.js +0 -16
  417. package/dist/indicator/donchian.js.map +0 -1
  418. package/dist/indicator/drawdown.d.ts +0 -2
  419. package/dist/indicator/drawdown.js +0 -27
  420. package/dist/indicator/drawdown.js.map +0 -1
  421. package/dist/indicator/ema.d.ts +0 -2
  422. package/dist/indicator/ema.js +0 -23
  423. package/dist/indicator/ema.js.map +0 -1
  424. package/dist/indicator/ema.spec.d.ts +0 -1
  425. package/dist/indicator/ema.spec.js +0 -23
  426. package/dist/indicator/ema.spec.js.map +0 -1
  427. package/dist/indicator/envelope.d.ts +0 -5
  428. package/dist/indicator/envelope.js +0 -18
  429. package/dist/indicator/envelope.js.map +0 -1
  430. package/dist/indicator/index.d.ts +0 -17
  431. package/dist/indicator/index.js +0 -34
  432. package/dist/indicator/index.js.map +0 -1
  433. package/dist/indicator/macd.d.ts +0 -2
  434. package/dist/indicator/macd.js +0 -13
  435. package/dist/indicator/macd.js.map +0 -1
  436. package/dist/indicator/min-max.d.ts +0 -5
  437. package/dist/indicator/min-max.js +0 -21
  438. package/dist/indicator/min-max.js.map +0 -1
  439. package/dist/indicator/ring-buffer.d.ts +0 -16
  440. package/dist/indicator/ring-buffer.js +0 -56
  441. package/dist/indicator/ring-buffer.js.map +0 -1
  442. package/dist/indicator/rma.d.ts +0 -2
  443. package/dist/indicator/rma.js +0 -23
  444. package/dist/indicator/rma.js.map +0 -1
  445. package/dist/indicator/sma.d.ts +0 -2
  446. package/dist/indicator/sma.js +0 -19
  447. package/dist/indicator/sma.js.map +0 -1
  448. package/dist/indicator/sma.spec.d.ts +0 -1
  449. package/dist/indicator/sma.spec.js +0 -19
  450. package/dist/indicator/sma.spec.js.map +0 -1
  451. package/dist/indicator/swma.d.ts +0 -2
  452. package/dist/indicator/swma.js +0 -20
  453. package/dist/indicator/swma.js.map +0 -1
  454. package/dist/indicator/tma.d.ts +0 -2
  455. package/dist/indicator/tma.js +0 -16
  456. package/dist/indicator/tma.js.map +0 -1
  457. package/dist/indicator/tma.spec.d.ts +0 -1
  458. package/dist/indicator/tma.spec.js +0 -19
  459. package/dist/indicator/tma.spec.js.map +0 -1
  460. package/dist/indicator/trailing.d.ts +0 -13
  461. package/dist/indicator/trailing.js +0 -67
  462. package/dist/indicator/trailing.js.map +0 -1
  463. package/dist/indicator/trailing.spec.d.ts +0 -1
  464. package/dist/indicator/trailing.spec.js +0 -69
  465. package/dist/indicator/trailing.spec.js.map +0 -1
  466. package/dist/indicator/truerange.d.ts +0 -3
  467. package/dist/indicator/truerange.js +0 -19
  468. package/dist/indicator/truerange.js.map +0 -1
  469. package/dist/indicator/truerange.spec.d.ts +0 -1
  470. package/dist/indicator/truerange.spec.js +0 -28
  471. package/dist/indicator/truerange.spec.js.map +0 -1
  472. package/dist/indicator/window.d.ts +0 -3
  473. package/dist/indicator/window.js +0 -22
  474. package/dist/indicator/window.js.map +0 -1
  475. package/dist/indicator/wma.d.ts +0 -2
  476. package/dist/indicator/wma.js +0 -22
  477. package/dist/indicator/wma.js.map +0 -1
  478. package/dist/indicator/wma.spec.d.ts +0 -1
  479. package/dist/indicator/wma.spec.js +0 -19
  480. package/dist/indicator/wma.spec.js.map +0 -1
  481. package/dist/shared/collections.js.map +0 -1
  482. package/dist/shared/datetime.js.map +0 -1
  483. package/dist/shared/decimals.js.map +0 -1
  484. package/dist/shared/decimals.spec.d.ts +0 -1
  485. package/dist/shared/decimals.spec.js +0 -34
  486. package/dist/shared/decimals.spec.js.map +0 -1
  487. package/dist/shared/index.js.map +0 -1
  488. package/dist/shared/io.d.ts +0 -1
  489. package/dist/shared/io.js +0 -8
  490. package/dist/shared/io.js.map +0 -1
  491. package/dist/shared/logger.js.map +0 -1
  492. package/dist/shared/policy.js.map +0 -1
  493. package/dist/storage/cache.js.map +0 -1
  494. package/dist/storage/cache.spec.d.ts +0 -1
  495. package/dist/storage/cache.spec.js +0 -18
  496. package/dist/storage/cache.spec.js.map +0 -1
  497. package/dist/storage/feed.js.map +0 -1
  498. package/dist/storage/index.js.map +0 -1
  499. package/dist/storage/measurement.js.map +0 -1
  500. package/dist/storage/storage.js.map +0 -1
  501. package/dist/store/index.js.map +0 -1
  502. package/dist/store/store-balance.event.js.map +0 -1
  503. package/dist/store/store-balance.event.spec.d.ts +0 -1
  504. package/dist/store/store-balance.event.spec.js +0 -26
  505. package/dist/store/store-balance.event.spec.js.map +0 -1
  506. package/dist/store/store-instrument.event.js.map +0 -1
  507. package/dist/store/store-instrument.event.spec.d.ts +0 -1
  508. package/dist/store/store-instrument.event.spec.js +0 -22
  509. package/dist/store/store-instrument.event.spec.js.map +0 -1
  510. package/dist/store/store-order.event.js.map +0 -1
  511. package/dist/store/store-order.event.spec.d.ts +0 -1
  512. package/dist/store/store-order.event.spec.js +0 -21
  513. package/dist/store/store-order.event.spec.js.map +0 -1
  514. package/dist/store/store-orderbook.event.d.ts +0 -14
  515. package/dist/store/store-orderbook.event.js +0 -42
  516. package/dist/store/store-orderbook.event.js.map +0 -1
  517. package/dist/store/store-position.event.js.map +0 -1
  518. package/dist/store/store-state.js.map +0 -1
  519. package/dist/store/store-trade.event.d.ts +0 -12
  520. package/dist/store/store-trade.event.js.map +0 -1
  521. package/dist/store/store-trade.event.spec.d.ts +0 -1
  522. package/dist/store/store-trade.event.spec.js +0 -44
  523. package/dist/store/store-trade.event.spec.js.map +0 -1
  524. package/dist/store/store.event.js.map +0 -1
  525. package/dist/store/store.js.map +0 -1
  526. package/dist/store/store.spec.d.ts +0 -1
  527. package/dist/store/store.spec.js +0 -119
  528. package/dist/store/store.spec.js.map +0 -1
  529. package/dist/tsconfig.tsbuildinfo +0 -1
  530. package/jestconfig.json +0 -12
  531. package/src/adapter/backtester/backtester-adapter.spec.ts +0 -124
  532. package/src/adapter/paper/paper-adapter.spec.ts +0 -105
  533. package/src/bootstrap.ts +0 -139
  534. package/src/domain/candle.operator.spec.ts +0 -125
  535. package/src/indicator/atr.ts +0 -20
  536. package/src/indicator/cross.spec.ts +0 -151
  537. package/src/indicator/cross.ts +0 -51
  538. package/src/indicator/donchian.ts +0 -37
  539. package/src/indicator/drawdown.ts +0 -27
  540. package/src/indicator/ema.spec.ts +0 -38
  541. package/src/indicator/ema.ts +0 -26
  542. package/src/indicator/envelope.ts +0 -20
  543. package/src/indicator/index.ts +0 -17
  544. package/src/indicator/macd.ts +0 -21
  545. package/src/indicator/min-max.ts +0 -25
  546. package/src/indicator/ring-buffer.ts +0 -63
  547. package/src/indicator/rma.ts +0 -25
  548. package/src/indicator/sma.spec.ts +0 -20
  549. package/src/indicator/sma.ts +0 -24
  550. package/src/indicator/swma.ts +0 -24
  551. package/src/indicator/tma.spec.ts +0 -20
  552. package/src/indicator/tma.ts +0 -19
  553. package/src/indicator/trailing.spec.ts +0 -75
  554. package/src/indicator/trailing.ts +0 -75
  555. package/src/indicator/truerange.spec.ts +0 -32
  556. package/src/indicator/truerange.ts +0 -31
  557. package/src/indicator/window.ts +0 -28
  558. package/src/indicator/wma.spec.ts +0 -19
  559. package/src/indicator/wma.ts +0 -28
  560. package/src/shared/io.ts +0 -3
  561. package/src/store/store-order.event.spec.ts +0 -28
  562. package/src/store/store-orderbook.event.ts +0 -54
@@ -1,25 +1,32 @@
1
1
  import { filter, map, Observable, share, startWith } from 'rxjs';
2
2
 
3
- import { weightedMean } from '../shared';
3
+ import { d, decimal, weightedMean } from '../shared';
4
4
  import { State } from '../store';
5
+ import { Component } from './component';
6
+ import { invalidInstrumentSelectorError } from './error';
5
7
  import { InstrumentSelector } from './instrument';
6
8
  import { Position } from './position';
7
9
 
8
10
  export function position(selector: InstrumentSelector) {
9
- return (source: Observable<Position>) =>
11
+ return (source: Observable<Component>) =>
10
12
  source.pipe(
11
- filter(it => it.kind == 'position' && it.instrument.id == selector.id),
13
+ filter(it => it instanceof Position && it.instrument.id == selector.id),
12
14
  map(it => it as Readonly<Position>)
13
15
  );
14
16
  }
15
17
 
16
18
  export function positions(selector: InstrumentSelector, state: State) {
19
+ const balance = state.balance.get(selector.quote.id);
20
+ if (!balance) {
21
+ throw invalidInstrumentSelectorError(selector.id);
22
+ }
23
+
17
24
  const getter = () =>
18
- Object.values(state.balance.get(selector.quote.id).position).filter(
19
- it => it.instrument.id == selector.id
20
- );
25
+ Object.values(balance.position)
26
+ .filter(it => it.instrument.id == selector.id)
27
+ .map(it => it as Readonly<Position>);
21
28
 
22
- return (source: Observable<Position>) =>
29
+ return (source: Observable<Component>) =>
23
30
  source.pipe(
24
31
  position(selector),
25
32
  map(() => getter()),
@@ -30,12 +37,15 @@ export function positions(selector: InstrumentSelector, state: State) {
30
37
  export function flatten() {
31
38
  return function (
32
39
  source: Observable<Position[]>
33
- ): Observable<{ size: number; rate: number }> {
40
+ ): Observable<{ size: decimal; rate: decimal }> {
34
41
  return source.pipe(
35
42
  map(it => {
36
43
  if (it.length > 1) {
37
44
  return {
38
- size: it.reduce((aggregate, position) => aggregate + position.size, 0),
45
+ size: it.reduce(
46
+ (aggregate, position) => aggregate.add(position.size),
47
+ d.Zero
48
+ ),
39
49
  rate: weightedMean(
40
50
  it.map(x => x.averageExecutionRate),
41
51
  it.map(x => x.size)
@@ -51,8 +61,8 @@ export function flatten() {
51
61
  }
52
62
 
53
63
  return {
54
- size: 0,
55
- rate: 0
64
+ size: d.Zero,
65
+ rate: d.Zero
56
66
  };
57
67
  }),
58
68
  share()
@@ -1,39 +1,43 @@
1
+ import { d } from '../shared';
1
2
  import { Asset } from './asset';
3
+ import { Commission } from './commission';
2
4
  import { Instrument } from './instrument';
3
5
  import { Position } from './position';
4
6
 
5
7
  describe('Position', () => {
6
8
  const instrument = new Instrument(
9
+ 0,
7
10
  new Asset('abc', 'xyz', 4),
8
11
  new Asset('def', 'xyz', 4),
9
- 'abc-def'
12
+ 'abc-def',
13
+ Commission.Zero
10
14
  );
11
15
 
12
16
  test('should construct a position', () => {
13
- const sut = new Position('1', instrument, 'CROSS', 10, 2, 3);
17
+ const sut = new Position(0, '1', instrument, 'CROSS', d(10), d(2), 3);
14
18
 
15
19
  expect(sut.id).toEqual('1');
16
20
  expect(sut.mode).toEqual('CROSS');
17
- expect(sut.averageExecutionRate).toEqual(10);
18
- expect(sut.size).toEqual(2);
21
+ expect(sut.averageExecutionRate).toEqual(d(10));
22
+ expect(sut.size).toEqual(d(2));
19
23
  expect(sut.leverage).toEqual(3);
20
24
  expect(sut.estimatedUnrealizedPnL).toEqual(undefined);
21
25
  expect(sut.id).toEqual('1');
22
26
  });
23
27
 
24
28
  test('should calculate correct margin', () => {
25
- const sut = new Position('1', instrument, 'CROSS', 2511.81, 10.31, 20);
29
+ const sut = new Position(0, '1', instrument, 'CROSS', d(2511.81), d(10.31), 20);
26
30
 
27
- expect(sut.margin).toEqual(0.5155);
31
+ expect(sut.margin).toEqual(d(0.5155));
28
32
  expect(sut.estimatedUnrealizedPnL).toEqual(undefined);
29
33
  });
30
34
 
31
35
  test('should calculate correct unrealized pnl', () => {
32
- const sut = new Position('1', instrument, 'CROSS', 2511.81, 10.31, 20);
36
+ const sut = new Position(0, '1', instrument, 'CROSS', d(2511.81), d(10.31), 20);
33
37
 
34
- const pnl = sut.calculateEstimatedUnrealizedPnL(2576.44);
38
+ const pnl = sut.calculateEstimatedUnrealizedPnL(d(2576.44));
35
39
 
36
- expect(pnl).toEqual(0.2652);
37
- expect(sut.estimatedUnrealizedPnL).toEqual(0.2652);
40
+ expect(pnl).toEqual(d(0.2652));
41
+ expect(sut.estimatedUnrealizedPnL).toEqual(d(0.2652));
38
42
  });
39
43
  });
@@ -1,29 +1,29 @@
1
1
  import { Instrument } from '../domain';
2
- import { pnl, timestamp } from '../shared';
2
+ import { decimal, pnl } from '../shared';
3
3
  import { Component } from './component';
4
4
 
5
5
  export type PositionMode = 'CROSS' | 'ISOLATED';
6
6
 
7
7
  export class Position implements Component {
8
- kind = 'position';
9
- timestamp: timestamp;
10
- estimatedUnrealizedPnL?: number;
8
+ readonly kind = 'position';
9
+ estimatedUnrealizedPnL?: decimal;
11
10
 
12
- get margin(): number {
13
- return this.instrument.quote.fixed(Math.abs(this.size) / this.leverage);
11
+ get margin(): decimal {
12
+ return this.instrument.quote.floor(this.size.abs().div(this.leverage));
14
13
  }
15
14
 
16
15
  constructor(
16
+ public timestamp: number,
17
17
  readonly id: string,
18
18
  readonly instrument: Instrument,
19
19
  readonly mode: PositionMode,
20
- public averageExecutionRate: number,
21
- public size: number,
20
+ public averageExecutionRate: decimal,
21
+ public size: decimal,
22
22
  public leverage: number
23
23
  ) {}
24
24
 
25
- calculateEstimatedUnrealizedPnL(rate: number): number {
26
- this.estimatedUnrealizedPnL = this.instrument.quote.fixed(
25
+ calculateEstimatedUnrealizedPnL(rate: decimal): decimal {
26
+ this.estimatedUnrealizedPnL = this.instrument.quote.floor(
27
27
  pnl(this.averageExecutionRate, rate, this.size)
28
28
  );
29
29
 
@@ -0,0 +1,158 @@
1
+ import {
2
+ AdapterAggregate,
3
+ AdapterFactory,
4
+ BacktesterListener,
5
+ BacktesterStreamer,
6
+ createBacktesterAdapterFactory,
7
+ createPaperAdapterFactory,
8
+ DefaultTimeProvider
9
+ } from '../adapter';
10
+ import { decimal, now } from '../shared';
11
+ import {
12
+ Cache,
13
+ Feed,
14
+ inMemoryStorageFactory,
15
+ Measurement,
16
+ StorageFactory
17
+ } from '../storage';
18
+ import { Store } from '../store';
19
+ import { AssetSelector } from './asset';
20
+ import { Session } from './session';
21
+
22
+ export type SessionFeature = (builder: SessionBuilder) => void;
23
+
24
+ export function deposit(selector: AssetSelector, amount: decimal): SessionFeature {
25
+ return (builder: SessionBuilder) => {
26
+ builder.useBalance(selector, amount);
27
+ };
28
+ }
29
+
30
+ export function period(from: Date, to: Date): SessionFeature {
31
+ return (builder: SessionBuilder) => {
32
+ builder.usePeriod(from.getTime(), to.getTime());
33
+ };
34
+ }
35
+
36
+ export class SessionBuilder {
37
+ public id: number = now();
38
+ public adapter = new Array<AdapterFactory>();
39
+ public storage: StorageFactory = inMemoryStorageFactory();
40
+ public balance: Record<string, decimal> = {};
41
+ public period = {
42
+ from: 0,
43
+ to: Number.MAX_VALUE
44
+ };
45
+
46
+ /**
47
+ * Unique session identifier, used to identify session in the storage.
48
+ * You can generate new id every time you start the new session or provide
49
+ * session id explicitly to resume previous session (in code or via CLI).
50
+ * If you don't provide session id, it will generate new one based on time.
51
+ */
52
+ useSessionId(id: number): SessionBuilder {
53
+ this.id = id;
54
+
55
+ return this;
56
+ }
57
+
58
+ /**
59
+ * Collection of adapters used to connect to the exchanges.
60
+ */
61
+ useAdapter(adapter: AdapterFactory): SessionBuilder {
62
+ this.adapter.push(adapter);
63
+
64
+ return this;
65
+ }
66
+
67
+ /**
68
+ * Provides historical data for backtest, it's not required for live and paper
69
+ * sessions. Stores session variables i.e. indicators, orders, or any other type of time
70
+ * series data. You can install @quantform/editor to render this data in your browser.
71
+ */
72
+ useStorage(storage: StorageFactory): SessionBuilder {
73
+ this.storage = storage;
74
+
75
+ return this;
76
+ }
77
+
78
+ useBalance(selector: AssetSelector, amount: decimal): SessionBuilder {
79
+ this.balance[selector.toString()] = amount;
80
+
81
+ return this;
82
+ }
83
+
84
+ usePeriod(from: number, to: number): SessionBuilder {
85
+ this.period.from = from;
86
+ this.period.to = to;
87
+
88
+ return this;
89
+ }
90
+
91
+ /**
92
+ * Starts a new backtest session.
93
+ * @param listener backtest event listener.
94
+ * @returns new session object.
95
+ */
96
+ backtest(listener?: BacktesterListener): [Session, BacktesterStreamer] {
97
+ const store = new Store();
98
+ const feed = new Feed(this.storage('feed'));
99
+ const cache = new Cache(this.storage('cache'));
100
+ const measurement = new Measurement(this.storage('measurement'));
101
+
102
+ const streamer = new BacktesterStreamer(store, feed, this.period, listener);
103
+
104
+ const aggregate = new AdapterAggregate(
105
+ this.adapter.map(it =>
106
+ createBacktesterAdapterFactory(
107
+ createPaperAdapterFactory(it, { balance: this.balance }),
108
+ streamer
109
+ )
110
+ ),
111
+ streamer.getTimeProvider(),
112
+ store,
113
+ cache
114
+ );
115
+
116
+ const session = new Session(this.id, store, aggregate, measurement);
117
+
118
+ return [session, streamer];
119
+ }
120
+
121
+ /**
122
+ * Starts a new paper session.
123
+ * @returns new session object.
124
+ */
125
+ paper(): Session {
126
+ const store = new Store();
127
+ const cache = new Cache(this.storage('cache'));
128
+ const measurement = new Measurement(this.storage('measurement'));
129
+
130
+ const aggregate = new AdapterAggregate(
131
+ this.adapter.map(it => createPaperAdapterFactory(it, { balance: this.balance })),
132
+ DefaultTimeProvider,
133
+ store,
134
+ cache
135
+ );
136
+
137
+ return new Session(this.id, store, aggregate, measurement);
138
+ }
139
+
140
+ /**
141
+ * Starts a new live session.
142
+ * @returns new session object.
143
+ */
144
+ live(): Session {
145
+ const store = new Store();
146
+ const cache = new Cache(this.storage('cache'));
147
+ const measurement = new Measurement(this.storage('measurement'));
148
+
149
+ const aggregate = new AdapterAggregate(
150
+ this.adapter,
151
+ DefaultTimeProvider,
152
+ store,
153
+ cache
154
+ );
155
+
156
+ return new Session(this.id, store, aggregate, measurement);
157
+ }
158
+ }
@@ -1,17 +1,10 @@
1
- import { Bootstrap } from '../bootstrap';
2
- import { Asset, Commission } from '../domain';
3
- import { now } from '../shared';
1
+ import { Asset, Commission, SessionBuilder } from '../domain';
2
+ import { d, now } from '../shared';
4
3
  import { InstrumentPatchEvent } from '../store';
5
- import { SessionDescriptor } from './session';
6
4
 
7
5
  describe('Session', () => {
8
- const descriptor: SessionDescriptor = {
9
- id: now(),
10
- adapter: []
11
- };
12
-
13
6
  test('should trigger once', done => {
14
- const session = new Bootstrap(descriptor).paper();
7
+ const session = new SessionBuilder().paper();
15
8
 
16
9
  session.instruments().subscribe({
17
10
  next: it => {
@@ -25,14 +18,14 @@ describe('Session', () => {
25
18
  now(),
26
19
  new Asset('de30', 'cex', 2),
27
20
  new Asset('usd', 'cex', 2),
28
- new Commission(0, 0),
21
+ new Commission(d.Zero, d.Zero),
29
22
  ''
30
23
  ),
31
24
  new InstrumentPatchEvent(
32
25
  now(),
33
26
  new Asset('wig20', 'cex', 2),
34
27
  new Asset('pln', 'cex', 2),
35
- new Commission(0, 0),
28
+ new Commission(d.Zero, d.Zero),
36
29
  ''
37
30
  )
38
31
  );
@@ -1,19 +1,21 @@
1
1
  import {
2
+ concat,
2
3
  defer,
3
4
  filter,
4
- finalize,
5
5
  from,
6
6
  map,
7
7
  mergeMap,
8
8
  Observable,
9
+ of,
10
+ ReplaySubject,
11
+ share,
9
12
  shareReplay,
10
13
  startWith,
11
- Subscription,
12
14
  switchMap,
13
15
  take
14
16
  } from 'rxjs';
17
+ import { v4 } from 'uuid';
15
18
 
16
- import { AdapterFactory, BacktesterOptions, PaperOptions } from '../adapter';
17
19
  import { AdapterAggregate } from '../adapter/adapter-aggregate';
18
20
  import {
19
21
  AssetSelector,
@@ -21,71 +23,39 @@ import {
21
23
  Candle,
22
24
  Instrument,
23
25
  InstrumentSelector,
26
+ invalidInstrumentSelectorError,
24
27
  Order,
25
28
  Orderbook,
26
29
  Position,
27
30
  Trade
28
31
  } from '../domain';
29
- import { now } from '../shared';
30
- import { StorageFactory } from '../storage';
32
+ import { decimal } from '../shared';
33
+ import { Measurement } from '../storage';
31
34
  import { Store } from '../store';
32
- import { balance } from './balance.operator';
33
- import { instrument, instruments } from './instrument.operator';
34
- import { order, orders } from './order.operator';
35
- import { orderbook } from './orderbook.operator';
36
- import { position, positions } from './position.operator';
37
- import { trade } from './trade.operator';
38
-
39
- /**
40
- * Describes a single session.
41
- */
42
- export interface SessionDescriptor {
43
- /**
44
- * Unique session identifier, used to identify session in the storage.
45
- * You can generate new id every time you start the new session or provide
46
- * session id explicitly to resume previous session (in code or via CLI).
47
- * If you don't provide session id, it will generate new one based on time.
48
- */
49
- id?: number;
50
-
51
- /**
52
- * Collection of adapters used to connect to the exchanges.
53
- */
54
- adapter: AdapterFactory[];
35
+ import { balance } from './balance-operator';
36
+ import { instrument, instruments } from './instrument-operator';
37
+ import { order, orders } from './order-operator';
38
+ import { orderbook } from './orderbook-operator';
39
+ import { position, positions } from './position-operator';
40
+ import { trade } from './trade-operator';
55
41
 
56
- /**
57
- * Provides historical data for backtest, it's not required for live and paper
58
- * sessions. Stores session variables i.e. indicators, orders, or any other type of time
59
- * series data. You can install @quantform/editor to render this data in your browser.
60
- */
61
- storage?: StorageFactory;
62
-
63
- /**
64
- * Session additional options.
65
- */
66
- simulation?: PaperOptions & BacktesterOptions;
67
- }
42
+ type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
68
43
 
69
44
  export class Session {
70
45
  private initialized = false;
71
- private subscription: Subscription;
72
46
 
73
47
  get timestamp(): number {
74
48
  return this.store.snapshot.timestamp;
75
49
  }
76
50
 
77
51
  constructor(
52
+ readonly id: number,
78
53
  readonly store: Store,
79
54
  readonly aggregate: AdapterAggregate,
80
- readonly descriptor?: SessionDescriptor
81
- ) {
82
- // generate session id based on time if not provided.
83
- if (descriptor && !descriptor.id) {
84
- descriptor.id = now();
85
- }
86
- }
55
+ readonly measurement: Measurement | undefined
56
+ ) { }
87
57
 
88
- async awake(describe: (session: Session) => Observable<any>): Promise<void> {
58
+ async awake(): Promise<void> {
89
59
  if (this.initialized) {
90
60
  return;
91
61
  }
@@ -94,12 +64,6 @@ export class Session {
94
64
 
95
65
  // awake all adapters and synchronize trading accounts with store.
96
66
  await this.aggregate.awake();
97
-
98
- if (describe) {
99
- this.subscription = describe(this)
100
- .pipe(finalize(() => this.dispose()))
101
- .subscribe();
102
- }
103
67
  }
104
68
 
105
69
  async dispose(): Promise<void> {
@@ -107,11 +71,6 @@ export class Session {
107
71
  return;
108
72
  }
109
73
 
110
- if (this.subscription) {
111
- this.subscription.unsubscribe();
112
- this.subscription = undefined;
113
- }
114
-
115
74
  this.store.dispose();
116
75
 
117
76
  await this.aggregate.dispose();
@@ -129,12 +88,31 @@ export class Session {
129
88
 
130
89
  /**
131
90
  * Opens a new order.
132
- * Example of buy order:
133
- * session.open(Order.market(instrument, 100));
134
91
  */
135
- open(order: Order): Observable<Readonly<Order>> {
136
- return from(this.aggregate.open(order)).pipe(
137
- switchMap(() => this.order(order.instrument).pipe(filter(it => it.id == order.id)))
92
+ open(order: {
93
+ instrument: InstrumentSelector;
94
+ quantity: decimal;
95
+ rate?: decimal;
96
+ }): Observable<Readonly<Order>> {
97
+ const instrument = this.store.snapshot.universe.instrument.get(order.instrument.id);
98
+ if (!instrument) {
99
+ throw invalidInstrumentSelectorError(order.instrument.id);
100
+ }
101
+
102
+ const newOrder = new Order(
103
+ this.timestamp,
104
+ v4(),
105
+ instrument,
106
+ order.quantity,
107
+ this.timestamp,
108
+ order.rate
109
+ );
110
+
111
+ return of(newOrder).pipe(
112
+ switchMap(() => this.aggregate.open(newOrder)),
113
+ switchMap(() =>
114
+ this.order(order.instrument).pipe(filter(it => it.id == newOrder.id))
115
+ )
138
116
  );
139
117
  }
140
118
 
@@ -143,10 +121,7 @@ export class Session {
143
121
  */
144
122
  cancel(order: Order): Observable<Readonly<Order>> {
145
123
  return defer(() => from(this.aggregate.cancel(order))).pipe(
146
- switchMap(() =>
147
- this.store.changes$.pipe(filter(it => it instanceof Order && order.id == it.id))
148
- ),
149
- map(it => it as Order)
124
+ switchMap(() => this.order(order.instrument).pipe(filter(it => it.id == order.id)))
150
125
  );
151
126
  }
152
127
 
@@ -232,12 +207,50 @@ export class Session {
232
207
  return this.store.changes$.pipe(
233
208
  startWith(this.store.snapshot.universe.instrument.get(selector.id)),
234
209
  filter(it => it instanceof Instrument && it.id == selector.id),
235
- switchMap(() =>
236
- from(this.aggregate.history({ instrument: selector, timeframe, length }))
237
- ),
210
+ switchMap(() => from(this.aggregate.history(selector, timeframe, length))),
238
211
  take(1),
239
212
  shareReplay(),
240
213
  mergeMap(it => it)
241
214
  );
242
215
  }
216
+
217
+ measure<T extends { timestamp: number }>(
218
+ spec: {
219
+ kind: string;
220
+ timestamp?: number;
221
+ },
222
+ defaultValue?: Optional<T, 'timestamp'>
223
+ ): [Observable<T>, (value: T) => void] {
224
+ if (!this.measurement) {
225
+ throw new Error();
226
+ }
227
+
228
+ const changes$ = new ReplaySubject<Optional<T, 'timestamp'>>();
229
+ const persisted$ = from(
230
+ this.measurement.query(this.id, {
231
+ to: spec.timestamp ?? this.timestamp,
232
+ kind: spec.kind,
233
+ count: 1
234
+ })
235
+ ).pipe(
236
+ map(it =>
237
+ it.length ? { timestamp: it[0].timestamp, ...it[0].payload } : defaultValue
238
+ ),
239
+ share()
240
+ );
241
+
242
+ const setter = (value: Optional<T, 'timestamp'>) => {
243
+ const timestamp = value.timestamp ?? this.timestamp;
244
+ const measure = { timestamp, kind: spec.kind, payload: value };
245
+
246
+ this.measurement?.save(this.id, [measure]);
247
+
248
+ changes$.next({ ...value, timestamp });
249
+ };
250
+
251
+ return [
252
+ concat(persisted$, changes$.asObservable()).pipe(filter(it => it !== undefined)),
253
+ setter
254
+ ];
255
+ }
243
256
  }
@@ -1,23 +1,27 @@
1
1
  import { Subject } from 'rxjs';
2
2
 
3
+ import { d } from '../shared';
3
4
  import { State } from '../store';
4
5
  import { Asset } from './asset';
6
+ import { Commission } from './commission';
5
7
  import { Component } from './component';
6
8
  import { Instrument } from './instrument';
7
9
  import { Trade } from './trade';
8
- import { trade } from './trade.operator';
10
+ import { trade } from './trade-operator';
9
11
 
10
12
  describe('trade', () => {
11
13
  const instrument = new Instrument(
14
+ 0,
12
15
  new Asset('abc', 'xyz', 4),
13
16
  new Asset('def', 'xyz', 4),
14
- 'abc-def'
17
+ 'abc-def',
18
+ Commission.Zero
15
19
  );
16
20
 
17
21
  const state = new State();
18
22
 
19
23
  beforeEach(() => {
20
- state.trade.upsert(new Trade(instrument));
24
+ state.trade.upsert(new Trade(0, instrument, d.Zero, d.Zero));
21
25
  });
22
26
 
23
27
  test('should pipe an orderbook on subscription', done => {
@@ -1,16 +1,20 @@
1
+ import { d } from '../shared';
1
2
  import { Asset } from './asset';
3
+ import { Commission } from './commission';
2
4
  import { Instrument } from './instrument';
3
5
  import { Trade } from './trade';
4
6
 
5
7
  describe('Trade', () => {
6
8
  const instrument = new Instrument(
9
+ 0,
7
10
  new Asset('abc', 'xyz', 4),
8
11
  new Asset('def', 'xyz', 4),
9
- 'abc-def'
12
+ 'abc-def',
13
+ Commission.Zero
10
14
  );
11
15
 
12
16
  test('should construct an empty trade', () => {
13
- const sut = new Trade(instrument);
17
+ const sut = new Trade(0, instrument, d.Zero, d.Zero);
14
18
 
15
19
  expect(sut.id).toEqual(instrument.id);
16
20
  });
@@ -1,4 +1,4 @@
1
- import { timestamp } from '../shared';
1
+ import { decimal } from '../shared';
2
2
  import { Instrument } from '.';
3
3
  import { Component } from './component';
4
4
 
@@ -7,13 +7,15 @@ import { Component } from './component';
7
7
  * and seller of the same asset.
8
8
  */
9
9
  export class Trade implements Component {
10
- id: string;
11
- kind = 'trade';
12
- timestamp: timestamp;
13
- rate: number;
14
- quantity: number;
10
+ readonly id: string;
11
+ readonly kind = 'trade';
15
12
 
16
- constructor(public readonly instrument: Instrument) {
13
+ constructor(
14
+ public timestamp: number,
15
+ public readonly instrument: Instrument,
16
+ public rate: decimal,
17
+ public quantity: decimal
18
+ ) {
17
19
  this.id = instrument.id;
18
20
  }
19
21
 
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from './adapter';
2
- export * from './bootstrap';
3
2
  export * from './domain';
4
- export * from './indicator';
5
3
  export * from './shared';
6
4
  export * from './storage';
7
5
  export * from './store';
6
+ export * from './strategy';