@quantform/core 0.5.13 → 0.5.23

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 (499) hide show
  1. package/dist/adapter/adapter-aggregate.d.ts +8 -5
  2. package/dist/adapter/adapter-aggregate.js +18 -20
  3. package/dist/adapter/adapter-aggregate.js.map +1 -1
  4. package/dist/adapter/adapter.d.ts +20 -32
  5. package/dist/adapter/adapter.js +8 -43
  6. package/dist/adapter/adapter.js.map +1 -1
  7. package/dist/adapter/backtester/backtester-adapter.d.ts +11 -9
  8. package/dist/adapter/backtester/backtester-adapter.js +17 -16
  9. package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
  10. package/dist/{tests → adapter/backtester}/backtester-adapter.spec.d.ts +0 -0
  11. package/dist/adapter/backtester/backtester-adapter.spec.js +83 -0
  12. package/dist/adapter/backtester/backtester-adapter.spec.js.map +1 -0
  13. package/dist/adapter/backtester/backtester-cursor.d.ts +3 -4
  14. package/dist/adapter/backtester/backtester-cursor.js +2 -1
  15. package/dist/adapter/backtester/backtester-cursor.js.map +1 -1
  16. package/dist/adapter/backtester/backtester-cursor.spec.js +19 -18
  17. package/dist/adapter/backtester/backtester-cursor.spec.js.map +1 -1
  18. package/dist/adapter/backtester/backtester-streamer.d.ts +3 -1
  19. package/dist/adapter/backtester/backtester-streamer.js +25 -14
  20. package/dist/adapter/backtester/backtester-streamer.js.map +1 -1
  21. package/dist/adapter/backtester/backtester-streamer.spec.js +17 -16
  22. package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -1
  23. package/dist/adapter/error.d.ts +2 -0
  24. package/dist/adapter/error.js +12 -0
  25. package/dist/adapter/error.js.map +1 -0
  26. package/dist/adapter/paper/engine/paper-engine.d.ts +11 -0
  27. package/dist/adapter/paper/engine/paper-engine.js +104 -0
  28. package/dist/adapter/paper/engine/paper-engine.js.map +1 -0
  29. package/dist/adapter/paper/{simulator/paper-spot-simulator.spec.d.ts → engine/paper-engine.spec.d.ts} +0 -0
  30. package/dist/adapter/paper/engine/paper-engine.spec.js +54 -0
  31. package/dist/adapter/paper/engine/paper-engine.spec.js.map +1 -0
  32. package/dist/adapter/paper/index.d.ts +1 -2
  33. package/dist/adapter/paper/index.js +1 -2
  34. package/dist/adapter/paper/index.js.map +1 -1
  35. package/dist/adapter/paper/paper-adapter.d.ts +10 -9
  36. package/dist/adapter/paper/paper-adapter.js +26 -23
  37. package/dist/adapter/paper/paper-adapter.js.map +1 -1
  38. package/dist/adapter/paper/paper-adapter.spec.js +36 -17
  39. package/dist/adapter/paper/paper-adapter.spec.js.map +1 -1
  40. package/dist/bootstrap.js +11 -10
  41. package/dist/bootstrap.js.map +1 -1
  42. package/dist/cli/pull.js +8 -11
  43. package/dist/cli/pull.js.map +1 -1
  44. package/dist/cli/test.js +5 -1
  45. package/dist/cli/test.js.map +1 -1
  46. package/dist/domain/asset.d.ts +10 -9
  47. package/dist/domain/asset.js +26 -23
  48. package/dist/domain/asset.js.map +1 -1
  49. package/dist/domain/asset.spec.js +36 -36
  50. package/dist/domain/asset.spec.js.map +1 -1
  51. package/dist/domain/balance.d.ts +13 -13
  52. package/dist/domain/balance.js +38 -32
  53. package/dist/domain/balance.js.map +1 -1
  54. package/dist/domain/balance.operator.d.ts +6 -0
  55. package/dist/domain/balance.operator.js +10 -0
  56. package/dist/domain/balance.operator.js.map +1 -0
  57. package/dist/{indicator/truerange.spec.d.ts → domain/balance.operator.spec.d.ts} +0 -0
  58. package/dist/domain/balance.operator.spec.js +23 -0
  59. package/dist/domain/balance.operator.spec.js.map +1 -0
  60. package/dist/domain/balance.spec.js +73 -12
  61. package/dist/domain/balance.spec.js.map +1 -1
  62. package/dist/domain/candle.d.ts +8 -23
  63. package/dist/domain/candle.js +6 -72
  64. package/dist/domain/candle.js.map +1 -1
  65. package/dist/domain/candle.operator.d.ts +10 -0
  66. package/dist/domain/candle.operator.js +64 -0
  67. package/dist/domain/candle.operator.js.map +1 -0
  68. package/dist/{shared/policy.spec.d.ts → domain/candle.operator.spec.d.ts} +0 -0
  69. package/dist/domain/candle.operator.spec.js +112 -0
  70. package/dist/domain/candle.operator.spec.js.map +1 -0
  71. package/dist/domain/candle.spec.js +16 -58
  72. package/dist/domain/candle.spec.js.map +1 -1
  73. package/dist/domain/commission.d.ts +12 -8
  74. package/dist/domain/commission.js +6 -6
  75. package/dist/domain/commission.js.map +1 -1
  76. package/dist/{shared/topic.spec.d.ts → domain/commission.spec.d.ts} +0 -0
  77. package/dist/domain/commission.spec.js +31 -0
  78. package/dist/domain/commission.spec.js.map +1 -0
  79. package/dist/domain/component.d.ts +1 -0
  80. package/dist/domain/error.d.ts +6 -0
  81. package/dist/domain/error.js +24 -0
  82. package/dist/domain/error.js.map +1 -0
  83. package/dist/domain/index.d.ts +8 -1
  84. package/dist/domain/index.js +8 -1
  85. package/dist/domain/index.js.map +1 -1
  86. package/dist/domain/instrument.d.ts +3 -2
  87. package/dist/domain/instrument.js +17 -9
  88. package/dist/domain/instrument.js.map +1 -1
  89. package/dist/domain/instrument.operator.d.ts +6 -0
  90. package/dist/domain/instrument.operator.js +14 -0
  91. package/dist/domain/instrument.operator.js.map +1 -0
  92. package/dist/{store/event/store-balance.event.spec.d.ts → domain/instrument.operator.spec.d.ts} +0 -0
  93. package/dist/domain/instrument.operator.spec.js +24 -0
  94. package/dist/domain/instrument.operator.spec.js.map +1 -0
  95. package/dist/domain/instrument.spec.js +22 -30
  96. package/dist/domain/instrument.spec.js.map +1 -1
  97. package/dist/domain/order.d.ts +16 -18
  98. package/dist/domain/order.js +39 -27
  99. package/dist/domain/order.js.map +1 -1
  100. package/dist/domain/order.operator.d.ts +7 -0
  101. package/dist/domain/order.operator.js +14 -0
  102. package/dist/domain/order.operator.js.map +1 -0
  103. package/dist/{store/event/store-candle.event.spec.d.ts → domain/order.operator.spec.d.ts} +0 -0
  104. package/dist/domain/order.operator.spec.js +65 -0
  105. package/dist/domain/order.operator.spec.js.map +1 -0
  106. package/dist/{store/event/store-instrument.event.spec.d.ts → domain/order.spec.d.ts} +0 -0
  107. package/dist/domain/order.spec.js +34 -0
  108. package/dist/domain/order.spec.js.map +1 -0
  109. package/dist/domain/orderbook.d.ts +19 -6
  110. package/dist/domain/orderbook.js +6 -4
  111. package/dist/domain/orderbook.js.map +1 -1
  112. package/dist/domain/orderbook.operator.d.ts +6 -0
  113. package/dist/domain/orderbook.operator.js +10 -0
  114. package/dist/domain/orderbook.operator.js.map +1 -0
  115. package/dist/{store/event/store-order.event.spec.d.ts → domain/orderbook.operator.spec.d.ts} +0 -0
  116. package/dist/domain/orderbook.operator.spec.js +22 -0
  117. package/dist/domain/orderbook.operator.spec.js.map +1 -0
  118. package/dist/{store/event/store-trade.event.spec.d.ts → domain/orderbook.spec.d.ts} +0 -0
  119. package/dist/domain/orderbook.spec.js +13 -0
  120. package/dist/domain/orderbook.spec.js.map +1 -0
  121. package/dist/domain/position.d.ts +9 -14
  122. package/dist/domain/position.js +9 -31
  123. package/dist/domain/position.js.map +1 -1
  124. package/dist/domain/position.operator.d.ts +11 -0
  125. package/dist/domain/position.operator.js +38 -0
  126. package/dist/domain/position.operator.js.map +1 -0
  127. package/dist/domain/position.operator.spec.d.ts +1 -0
  128. package/dist/domain/position.operator.spec.js +49 -0
  129. package/dist/domain/position.operator.spec.js.map +1 -0
  130. package/dist/domain/position.spec.js +22 -17
  131. package/dist/domain/position.spec.js.map +1 -1
  132. package/dist/domain/session.d.ts +15 -18
  133. package/dist/domain/session.js +21 -31
  134. package/dist/domain/session.js.map +1 -1
  135. package/dist/domain/session.spec.js +2 -2
  136. package/dist/domain/session.spec.js.map +1 -1
  137. package/dist/domain/trade.d.ts +4 -3
  138. package/dist/domain/trade.js +1 -0
  139. package/dist/domain/trade.js.map +1 -1
  140. package/dist/domain/trade.operator.d.ts +6 -0
  141. package/dist/domain/trade.operator.js +10 -0
  142. package/dist/domain/trade.operator.js.map +1 -0
  143. package/dist/domain/trade.operator.spec.d.ts +1 -0
  144. package/dist/domain/trade.operator.spec.js +24 -0
  145. package/dist/domain/trade.operator.spec.js.map +1 -0
  146. package/dist/domain/trade.spec.d.ts +1 -0
  147. package/dist/domain/trade.spec.js +13 -0
  148. package/dist/domain/trade.spec.js.map +1 -0
  149. package/dist/indicator/atr.d.ts +2 -1
  150. package/dist/indicator/atr.js +3 -3
  151. package/dist/indicator/atr.js.map +1 -1
  152. package/dist/indicator/cross.d.ts +3 -2
  153. package/dist/indicator/cross.js +13 -13
  154. package/dist/indicator/cross.js.map +1 -1
  155. package/dist/indicator/cross.spec.js +23 -22
  156. package/dist/indicator/cross.spec.js.map +1 -1
  157. package/dist/indicator/donchian.d.ts +3 -2
  158. package/dist/indicator/donchian.js.map +1 -1
  159. package/dist/indicator/drawdown.d.ts +2 -1
  160. package/dist/indicator/drawdown.js +3 -2
  161. package/dist/indicator/drawdown.js.map +1 -1
  162. package/dist/indicator/ema.d.ts +2 -1
  163. package/dist/indicator/ema.js +3 -2
  164. package/dist/indicator/ema.js.map +1 -1
  165. package/dist/indicator/ema.spec.js +4 -3
  166. package/dist/indicator/ema.spec.js.map +1 -1
  167. package/dist/indicator/envelope.d.ts +4 -3
  168. package/dist/indicator/envelope.js +4 -4
  169. package/dist/indicator/envelope.js.map +1 -1
  170. package/dist/indicator/index.d.ts +1 -1
  171. package/dist/indicator/index.js +1 -1
  172. package/dist/indicator/index.js.map +1 -1
  173. package/dist/indicator/macd.d.ts +2 -1
  174. package/dist/indicator/macd.js +1 -1
  175. package/dist/indicator/macd.js.map +1 -1
  176. package/dist/indicator/min-max.d.ts +4 -3
  177. package/dist/indicator/min-max.js +5 -4
  178. package/dist/indicator/min-max.js.map +1 -1
  179. package/dist/indicator/rma.d.ts +2 -1
  180. package/dist/indicator/rma.js +3 -2
  181. package/dist/indicator/rma.js.map +1 -1
  182. package/dist/indicator/sma.d.ts +2 -1
  183. package/dist/indicator/sma.js +4 -6
  184. package/dist/indicator/sma.js.map +1 -1
  185. package/dist/indicator/sma.spec.js +4 -3
  186. package/dist/indicator/sma.spec.js.map +1 -1
  187. package/dist/indicator/swma.d.ts +2 -1
  188. package/dist/indicator/swma.js +5 -1
  189. package/dist/indicator/swma.js.map +1 -1
  190. package/dist/indicator/tma.d.ts +2 -1
  191. package/dist/indicator/tma.js.map +1 -1
  192. package/dist/indicator/tma.spec.js +4 -3
  193. package/dist/indicator/tma.spec.js.map +1 -1
  194. package/dist/indicator/trailing.d.ts +8 -7
  195. package/dist/indicator/trailing.js +12 -11
  196. package/dist/indicator/trailing.js.map +1 -1
  197. package/dist/indicator/trailing.spec.js +15 -14
  198. package/dist/indicator/trailing.spec.js.map +1 -1
  199. package/dist/indicator/true-range.d.ts +4 -0
  200. package/dist/indicator/true-range.js +20 -0
  201. package/dist/indicator/true-range.js.map +1 -0
  202. package/dist/indicator/true-range.spec.d.ts +1 -0
  203. package/dist/indicator/true-range.spec.js +28 -0
  204. package/dist/indicator/true-range.spec.js.map +1 -0
  205. package/dist/indicator/window.d.ts +1 -1
  206. package/dist/indicator/window.js +1 -1
  207. package/dist/indicator/window.js.map +1 -1
  208. package/dist/indicator/wma.d.ts +2 -1
  209. package/dist/indicator/wma.js +6 -5
  210. package/dist/indicator/wma.js.map +1 -1
  211. package/dist/indicator/wma.spec.js +4 -3
  212. package/dist/indicator/wma.spec.js.map +1 -1
  213. package/dist/shared/collections.d.ts +26 -0
  214. package/dist/shared/collections.js +115 -0
  215. package/dist/shared/collections.js.map +1 -0
  216. package/dist/shared/collections.spec.d.ts +1 -0
  217. package/dist/shared/collections.spec.js +28 -0
  218. package/dist/shared/collections.spec.js.map +1 -0
  219. package/dist/shared/datetime.d.ts +0 -1
  220. package/dist/shared/datetime.js +1 -12
  221. package/dist/shared/datetime.js.map +1 -1
  222. package/dist/shared/decimals.d.ts +15 -6
  223. package/dist/shared/decimals.js +22 -36
  224. package/dist/shared/decimals.js.map +1 -1
  225. package/dist/shared/decimals.spec.js +18 -22
  226. package/dist/shared/decimals.spec.js.map +1 -1
  227. package/dist/shared/index.d.ts +2 -1
  228. package/dist/shared/index.js +2 -1
  229. package/dist/shared/index.js.map +1 -1
  230. package/dist/shared/io.js.map +1 -1
  231. package/dist/shared/pipe.d.ts +4 -0
  232. package/dist/shared/pipe.js +9 -0
  233. package/dist/shared/pipe.js.map +1 -0
  234. package/dist/shared/policy.d.ts +0 -1
  235. package/dist/shared/policy.js +1 -11
  236. package/dist/shared/policy.js.map +1 -1
  237. package/dist/storage/cache.js +1 -1
  238. package/dist/storage/cache.js.map +1 -1
  239. package/dist/storage/cache.spec.d.ts +1 -0
  240. package/dist/storage/cache.spec.js +18 -0
  241. package/dist/storage/cache.spec.js.map +1 -0
  242. package/dist/storage/feed.d.ts +7 -4
  243. package/dist/storage/feed.js +55 -8
  244. package/dist/storage/feed.js.map +1 -1
  245. package/dist/storage/storage.d.ts +2 -7
  246. package/dist/storage/storage.js +6 -11
  247. package/dist/storage/storage.js.map +1 -1
  248. package/dist/store/index.d.ts +8 -2
  249. package/dist/store/index.js +8 -2
  250. package/dist/store/index.js.map +1 -1
  251. package/dist/store/store-balance.event.d.ts +33 -0
  252. package/dist/store/store-balance.event.js +90 -0
  253. package/dist/store/store-balance.event.js.map +1 -0
  254. package/dist/store/store-balance.event.spec.d.ts +1 -0
  255. package/dist/store/{event/store-balance.event.spec.js → store-balance.event.spec.js} +10 -10
  256. package/dist/store/store-balance.event.spec.js.map +1 -0
  257. package/dist/store/{event/store-instrument.event.d.ts → store-instrument.event.d.ts} +5 -8
  258. package/dist/store/store-instrument.event.js +52 -0
  259. package/dist/store/store-instrument.event.js.map +1 -0
  260. package/dist/store/store-instrument.event.spec.d.ts +1 -0
  261. package/dist/store/store-instrument.event.spec.js +22 -0
  262. package/dist/store/store-instrument.event.spec.js.map +1 -0
  263. package/dist/store/store-order.event.d.ts +59 -0
  264. package/dist/store/store-order.event.js +181 -0
  265. package/dist/store/store-order.event.js.map +1 -0
  266. package/dist/store/store-order.event.spec.d.ts +1 -0
  267. package/dist/store/{event/store-order.event.spec.js → store-order.event.spec.js} +8 -8
  268. package/dist/store/store-order.event.spec.js.map +1 -0
  269. package/dist/store/store-orderbook.event.d.ts +12 -0
  270. package/dist/store/store-orderbook.event.js +42 -0
  271. package/dist/store/store-orderbook.event.js.map +1 -0
  272. package/dist/store/store-orderbook.event.spec.d.ts +1 -0
  273. package/dist/store/store-orderbook.event.spec.js +28 -0
  274. package/dist/store/store-orderbook.event.spec.js.map +1 -0
  275. package/dist/store/store-position.event.d.ts +21 -0
  276. package/dist/store/store-position.event.js +89 -0
  277. package/dist/store/store-position.event.js.map +1 -0
  278. package/dist/store/store-state.d.ts +27 -0
  279. package/dist/store/store-state.js +29 -0
  280. package/dist/store/store-state.js.map +1 -0
  281. package/dist/store/store-trade.event.d.ts +12 -0
  282. package/dist/store/store-trade.event.js +25 -0
  283. package/dist/store/store-trade.event.js.map +1 -0
  284. package/dist/store/store-trade.event.spec.d.ts +1 -0
  285. package/dist/store/store-trade.event.spec.js +44 -0
  286. package/dist/store/store-trade.event.spec.js.map +1 -0
  287. package/dist/store/store.d.ts +4 -25
  288. package/dist/store/store.event.d.ts +6 -0
  289. package/dist/store/{event/store.event.js → store.event.js} +0 -0
  290. package/dist/store/store.event.js.map +1 -0
  291. package/dist/store/store.js +7 -195
  292. package/dist/store/store.js.map +1 -1
  293. package/dist/store/store.spec.d.ts +1 -0
  294. package/dist/store/store.spec.js +119 -0
  295. package/dist/store/store.spec.js.map +1 -0
  296. package/dist/tsconfig.tsbuildinfo +1 -1
  297. package/{jestconfig.unit.json → jestconfig.json} +2 -2
  298. package/package.json +4 -6
  299. package/src/adapter/adapter-aggregate.ts +39 -38
  300. package/src/adapter/adapter.ts +39 -71
  301. package/src/adapter/backtester/backtester-adapter.spec.ts +133 -0
  302. package/src/adapter/backtester/backtester-adapter.ts +41 -21
  303. package/src/adapter/backtester/backtester-cursor.spec.ts +19 -18
  304. package/src/adapter/backtester/backtester-cursor.ts +7 -7
  305. package/src/adapter/backtester/backtester-streamer.spec.ts +23 -22
  306. package/src/adapter/backtester/backtester-streamer.ts +28 -15
  307. package/src/adapter/error.ts +9 -0
  308. package/src/adapter/paper/engine/paper-engine.spec.ts +99 -0
  309. package/src/adapter/paper/engine/paper-engine.ts +142 -0
  310. package/src/adapter/paper/index.ts +1 -2
  311. package/src/adapter/paper/paper-adapter.spec.ts +65 -20
  312. package/src/adapter/paper/paper-adapter.ts +42 -27
  313. package/src/bootstrap.ts +26 -19
  314. package/src/cli/pull.ts +11 -6
  315. package/src/cli/test.ts +5 -2
  316. package/src/domain/asset.spec.ts +37 -33
  317. package/src/domain/asset.ts +33 -34
  318. package/src/domain/balance.operator.spec.ts +25 -0
  319. package/src/domain/balance.operator.ts +15 -0
  320. package/src/domain/balance.spec.ts +101 -12
  321. package/src/domain/balance.ts +57 -51
  322. package/src/domain/candle.operator.spec.ts +126 -0
  323. package/src/domain/candle.operator.ts +107 -0
  324. package/src/domain/candle.spec.ts +18 -73
  325. package/src/domain/candle.ts +9 -121
  326. package/src/domain/commission.spec.ts +34 -0
  327. package/src/domain/commission.ts +13 -11
  328. package/src/domain/component.ts +1 -0
  329. package/src/domain/error.ts +27 -0
  330. package/src/domain/index.ts +8 -1
  331. package/src/domain/instrument.operator.spec.ts +28 -0
  332. package/src/domain/instrument.operator.ts +25 -0
  333. package/src/domain/instrument.spec.ts +22 -30
  334. package/src/domain/instrument.ts +20 -11
  335. package/src/domain/order.operator.spec.ts +82 -0
  336. package/src/domain/order.operator.ts +23 -0
  337. package/src/domain/order.spec.ts +44 -0
  338. package/src/domain/order.ts +55 -55
  339. package/src/domain/orderbook.operator.spec.ts +28 -0
  340. package/src/domain/orderbook.operator.ts +15 -0
  341. package/src/domain/orderbook.spec.ts +17 -0
  342. package/src/domain/orderbook.ts +18 -9
  343. package/src/domain/position.operator.spec.ts +59 -0
  344. package/src/domain/position.operator.ts +64 -0
  345. package/src/domain/position.spec.ts +28 -23
  346. package/src/domain/position.ts +17 -49
  347. package/src/domain/session.spec.ts +4 -4
  348. package/src/domain/session.ts +42 -134
  349. package/src/domain/trade.operator.spec.ts +31 -0
  350. package/src/domain/trade.operator.ts +15 -0
  351. package/src/domain/trade.spec.ts +17 -0
  352. package/src/domain/trade.ts +7 -4
  353. package/src/indicator/atr.ts +6 -5
  354. package/src/indicator/cross.spec.ts +33 -48
  355. package/src/indicator/cross.ts +18 -10
  356. package/src/indicator/donchian.ts +5 -4
  357. package/src/indicator/drawdown.ts +7 -5
  358. package/src/indicator/ema.spec.ts +5 -4
  359. package/src/indicator/ema.ts +7 -6
  360. package/src/indicator/envelope.ts +11 -6
  361. package/src/indicator/index.ts +1 -1
  362. package/src/indicator/macd.ts +5 -4
  363. package/src/indicator/min-max.ts +10 -7
  364. package/src/indicator/rma.ts +7 -6
  365. package/src/indicator/sma.spec.ts +5 -4
  366. package/src/indicator/sma.ts +9 -8
  367. package/src/indicator/swma.ts +8 -4
  368. package/src/indicator/tma.spec.ts +5 -4
  369. package/src/indicator/tma.ts +4 -3
  370. package/src/indicator/trailing.spec.ts +29 -16
  371. package/src/indicator/trailing.ts +22 -16
  372. package/src/indicator/true-range.spec.ts +32 -0
  373. package/src/indicator/true-range.ts +32 -0
  374. package/src/indicator/window.ts +3 -3
  375. package/src/indicator/wma.spec.ts +5 -4
  376. package/src/indicator/wma.ts +8 -7
  377. package/src/shared/collections.spec.ts +30 -0
  378. package/src/shared/collections.ts +141 -0
  379. package/src/shared/datetime.ts +0 -12
  380. package/src/shared/decimals.spec.ts +19 -24
  381. package/src/shared/decimals.ts +22 -55
  382. package/src/shared/index.ts +2 -1
  383. package/src/shared/io.ts +0 -2
  384. package/src/shared/pipe.ts +12 -0
  385. package/src/shared/policy.ts +0 -13
  386. package/src/storage/cache.spec.ts +18 -0
  387. package/src/storage/cache.ts +1 -1
  388. package/src/storage/feed.ts +88 -23
  389. package/src/storage/storage.ts +9 -13
  390. package/src/store/index.ts +8 -2
  391. package/src/store/{event/store-balance.event.spec.ts → store-balance.event.spec.ts} +10 -10
  392. package/src/store/store-balance.event.ts +124 -0
  393. package/src/store/store-instrument.event.spec.ts +25 -0
  394. package/src/store/store-instrument.event.ts +72 -0
  395. package/src/store/store-order.event.spec.ts +28 -0
  396. package/src/store/store-order.event.ts +214 -0
  397. package/src/store/store-orderbook.event.spec.ts +37 -0
  398. package/src/store/store-orderbook.event.ts +54 -0
  399. package/src/store/store-position.event.ts +114 -0
  400. package/src/store/store-state.ts +48 -0
  401. package/src/store/store-trade.event.spec.ts +60 -0
  402. package/src/store/store-trade.event.ts +36 -0
  403. package/src/store/store.event.ts +8 -0
  404. package/src/store/store.spec.ts +180 -0
  405. package/src/store/store.ts +10 -208
  406. package/dist/adapter/paper/simulator/paper-margin-simulator.d.ts +0 -10
  407. package/dist/adapter/paper/simulator/paper-margin-simulator.js +0 -69
  408. package/dist/adapter/paper/simulator/paper-margin-simulator.js.map +0 -1
  409. package/dist/adapter/paper/simulator/paper-simulator.d.ts +0 -16
  410. package/dist/adapter/paper/simulator/paper-simulator.js +0 -93
  411. package/dist/adapter/paper/simulator/paper-simulator.js.map +0 -1
  412. package/dist/adapter/paper/simulator/paper-spot-simulator.d.ts +0 -13
  413. package/dist/adapter/paper/simulator/paper-spot-simulator.js +0 -81
  414. package/dist/adapter/paper/simulator/paper-spot-simulator.js.map +0 -1
  415. package/dist/adapter/paper/simulator/paper-spot-simulator.spec.js +0 -49
  416. package/dist/adapter/paper/simulator/paper-spot-simulator.spec.js.map +0 -1
  417. package/dist/domain/statement.d.ts +0 -4
  418. package/dist/domain/statement.js +0 -87
  419. package/dist/domain/statement.js.map +0 -1
  420. package/dist/indicator/truerange.d.ts +0 -3
  421. package/dist/indicator/truerange.js +0 -19
  422. package/dist/indicator/truerange.js.map +0 -1
  423. package/dist/indicator/truerange.spec.js +0 -28
  424. package/dist/indicator/truerange.spec.js.map +0 -1
  425. package/dist/shared/policy.spec.js +0 -22
  426. package/dist/shared/policy.spec.js.map +0 -1
  427. package/dist/shared/topic.d.ts +0 -14
  428. package/dist/shared/topic.js +0 -40
  429. package/dist/shared/topic.js.map +0 -1
  430. package/dist/shared/topic.spec.js +0 -43
  431. package/dist/shared/topic.spec.js.map +0 -1
  432. package/dist/store/event/index.d.ts +0 -8
  433. package/dist/store/event/index.js +0 -25
  434. package/dist/store/event/index.js.map +0 -1
  435. package/dist/store/event/store-balance.event.d.ts +0 -37
  436. package/dist/store/event/store-balance.event.js +0 -119
  437. package/dist/store/event/store-balance.event.js.map +0 -1
  438. package/dist/store/event/store-balance.event.spec.js.map +0 -1
  439. package/dist/store/event/store-candle.event.d.ts +0 -18
  440. package/dist/store/event/store-candle.event.js +0 -63
  441. package/dist/store/event/store-candle.event.js.map +0 -1
  442. package/dist/store/event/store-candle.event.spec.js +0 -23
  443. package/dist/store/event/store-candle.event.spec.js.map +0 -1
  444. package/dist/store/event/store-instrument.event.js +0 -78
  445. package/dist/store/event/store-instrument.event.js.map +0 -1
  446. package/dist/store/event/store-instrument.event.spec.js +0 -21
  447. package/dist/store/event/store-instrument.event.spec.js.map +0 -1
  448. package/dist/store/event/store-order.event.d.ts +0 -61
  449. package/dist/store/event/store-order.event.js +0 -205
  450. package/dist/store/event/store-order.event.js.map +0 -1
  451. package/dist/store/event/store-order.event.spec.js.map +0 -1
  452. package/dist/store/event/store-orderbook.event.d.ts +0 -15
  453. package/dist/store/event/store-orderbook.event.js +0 -65
  454. package/dist/store/event/store-orderbook.event.js.map +0 -1
  455. package/dist/store/event/store-position.event.d.ts +0 -23
  456. package/dist/store/event/store-position.event.js +0 -97
  457. package/dist/store/event/store-position.event.js.map +0 -1
  458. package/dist/store/event/store-trade.event.d.ts +0 -13
  459. package/dist/store/event/store-trade.event.js +0 -47
  460. package/dist/store/event/store-trade.event.js.map +0 -1
  461. package/dist/store/event/store-trade.event.spec.js +0 -44
  462. package/dist/store/event/store-trade.event.spec.js.map +0 -1
  463. package/dist/store/event/store.event.d.ts +0 -5
  464. package/dist/store/event/store.event.js.map +0 -1
  465. package/dist/store/store.state.d.ts +0 -21
  466. package/dist/store/store.state.js +0 -21
  467. package/dist/store/store.state.js.map +0 -1
  468. package/dist/tests/backtester-adapter.spec.js +0 -61
  469. package/dist/tests/backtester-adapter.spec.js.map +0 -1
  470. package/dist/tests/session.spec.d.ts +0 -0
  471. package/dist/tests/session.spec.js +0 -1
  472. package/dist/tests/session.spec.js.map +0 -1
  473. package/jestconfig.integration.json +0 -12
  474. package/src/adapter/paper/simulator/paper-margin-simulator.ts +0 -108
  475. package/src/adapter/paper/simulator/paper-simulator.ts +0 -121
  476. package/src/adapter/paper/simulator/paper-spot-simulator.spec.ts +0 -87
  477. package/src/adapter/paper/simulator/paper-spot-simulator.ts +0 -134
  478. package/src/domain/statement.ts +0 -119
  479. package/src/indicator/truerange.spec.ts +0 -32
  480. package/src/indicator/truerange.ts +0 -31
  481. package/src/shared/policy.spec.ts +0 -25
  482. package/src/shared/topic.spec.ts +0 -34
  483. package/src/shared/topic.ts +0 -43
  484. package/src/store/event/index.ts +0 -8
  485. package/src/store/event/store-balance.event.ts +0 -161
  486. package/src/store/event/store-candle.event.spec.ts +0 -30
  487. package/src/store/event/store-candle.event.ts +0 -71
  488. package/src/store/event/store-instrument.event.spec.ts +0 -25
  489. package/src/store/event/store-instrument.event.ts +0 -84
  490. package/src/store/event/store-order.event.spec.ts +0 -28
  491. package/src/store/event/store-order.event.ts +0 -218
  492. package/src/store/event/store-orderbook.event.ts +0 -70
  493. package/src/store/event/store-position.event.ts +0 -109
  494. package/src/store/event/store-trade.event.spec.ts +0 -60
  495. package/src/store/event/store-trade.event.ts +0 -52
  496. package/src/store/event/store.event.ts +0 -6
  497. package/src/store/store.state.ts +0 -43
  498. package/src/tests/backtester-adapter.spec.ts +0 -88
  499. package/src/tests/session.spec.ts +0 -121
@@ -1,79 +1,46 @@
1
- /**
2
- * calculate the number of decimal places of a number
3
- * @param value
4
- * @returns a precision number of the value
5
- */
6
- export function precision(value: number) {
7
- if (!isFinite(value)) {
8
- return 0;
9
- }
10
-
11
- let e = 1;
12
- let p = 0;
1
+ import { Decimal } from 'decimal.js';
13
2
 
14
- while (Math.round(value * e) / e !== value) {
15
- e *= 10;
16
- p++;
3
+ declare module 'decimal.js' {
4
+ interface Decimal {
5
+ toFloor(decimalPlaces: number): Decimal;
6
+ toCeil(decimalPlaces: number): Decimal;
17
7
  }
18
-
19
- return p;
20
8
  }
21
9
 
22
- /**
23
- * round down the number to the given precision
24
- * @param number
25
- * @param precision
26
- * @returns rounded down number
27
- */
28
- export function floor(number: number, precision: number): number {
29
- const fixed = Math.pow(10, precision);
10
+ Decimal.prototype.toFloor = function (decimalPlaces: number) {
11
+ return this.toDecimalPlaces(decimalPlaces, Decimal.ROUND_FLOOR);
12
+ };
30
13
 
31
- return Math.floor(number * fixed) / fixed;
32
- }
14
+ Decimal.prototype.toCeil = function (decimalPlaces: number) {
15
+ return this.toDecimalPlaces(decimalPlaces, Decimal.ROUND_CEIL);
16
+ };
33
17
 
34
- /**
35
- * round up the number to the given precision
36
- * @param number
37
- * @param precision
38
- * @returns rounded up number
39
- */
40
- export function ceil(number: number, precision: number): number {
41
- const fixed = Math.pow(10, precision);
18
+ export class decimal extends Decimal {}
42
19
 
43
- return Math.ceil(number * fixed) / fixed;
20
+ export function d(value: Decimal.Value) {
21
+ return new decimal(value);
44
22
  }
45
23
 
46
- /**
47
- * round the number to the given precision
48
- * @param number
49
- * @param precision
50
- * @returns rounded number
51
- */
52
- export function fixed(number: number, precision: number): number {
53
- return floor(number, precision);
54
- }
24
+ d.Zero = new decimal(0);
55
25
 
56
- export function weightedMean(values: number[], weights: number[]) {
26
+ export function weightedMean(values: decimal[], weights: decimal[]): decimal {
57
27
  const result = values
58
28
  .map((value, i) => {
59
29
  const weight = weights[i];
60
- const sum = value * weight;
30
+ const sum = value.mul(weight);
61
31
  return [sum, weight];
62
32
  })
63
- .reduce((p, c) => [p[0] + c[0], p[1] + c[1]], [0, 0]);
33
+ .reduce((p, c) => [p[0].add(c[0]), p[1].add(c[1])], [d.Zero, d.Zero]);
64
34
 
65
35
  if (!result[1]) {
66
- return 0;
36
+ return d.Zero;
67
37
  }
68
38
 
69
- return result[0] / result[1];
39
+ return result[0].div(result[1]);
70
40
  }
71
41
 
72
- export function pnl(entryRate: number, exitRate: number, size: number) {
73
- const cost = size * entryRate;
74
- const unrealized = size * exitRate;
75
-
76
- return unrealized - cost;
42
+ export function pnl(entryRate: decimal, exitRate: decimal, amount: decimal) {
43
+ return exitRate.div(entryRate).minus(1).mul(amount);
77
44
  }
78
45
 
79
46
  /**
@@ -3,4 +3,5 @@ export * from './decimals';
3
3
  export * from './io';
4
4
  export * from './logger';
5
5
  export * from './policy';
6
- export * from './topic';
6
+ export * from './collections';
7
+ export * from './pipe';
package/src/shared/io.ts CHANGED
@@ -1,5 +1,3 @@
1
- import fs = require('fs');
2
-
3
1
  export function workingDirectory() {
4
2
  return './.quantform/';
5
3
  }
@@ -0,0 +1,12 @@
1
+ import { filter, map, Observable } from 'rxjs';
2
+
3
+ // tslint:disable-next-line: no-any
4
+ type Constructor<T> = new (...args: any[]) => T;
5
+
6
+ export function ofType<T extends K, K>(type: Constructor<T>) {
7
+ return (input: Observable<K>) =>
8
+ input.pipe(
9
+ filter(it => it instanceof type),
10
+ map(it => it as T)
11
+ );
12
+ }
@@ -1,18 +1,5 @@
1
- import * as hash from 'object-hash';
2
1
  import { retryAsync } from 'ts-retry';
3
2
 
4
3
  export function retry<T>(fn: () => Promise<T>): Promise<T> {
5
4
  return retryAsync(fn, { delay: 1000, maxTry: 3 });
6
5
  }
7
-
8
- const inMemoryCache: Record<string, any> = {};
9
-
10
- export async function cache<T>(key: any, fn: () => Promise<T>): Promise<T> {
11
- const hashed = hash(key);
12
-
13
- if (inMemoryCache[hashed]) {
14
- return inMemoryCache[hashed];
15
- }
16
-
17
- return (inMemoryCache[hashed] = await fn());
18
- }
@@ -0,0 +1,18 @@
1
+ import { Cache } from './cache';
2
+ import { InMemoryStorage } from './storage';
3
+
4
+ describe('Cache', () => {
5
+ test('should return cached value', async () => {
6
+ const cache = new Cache(new InMemoryStorage());
7
+
8
+ const value1 = await cache.tryGet(() => Promise.resolve('quantform-1'), {
9
+ key: 'test'
10
+ });
11
+ const value2 = await cache.tryGet(() => Promise.resolve('quantform-2'), {
12
+ key: 'test'
13
+ });
14
+
15
+ expect(value1).toEqual('quantform-1');
16
+ expect(value2).toEqual('quantform-1');
17
+ });
18
+ });
@@ -13,7 +13,7 @@ export class Cache {
13
13
  const payload = await this.storage.query(options.key, {
14
14
  kind: 'cache',
15
15
  count: 1,
16
- to: time
16
+ to: time + 1
17
17
  });
18
18
 
19
19
  if ((!payload.length || payload[0].timestamp < time - options.ttl) ?? 60 * 60 * 24) {
@@ -1,6 +1,9 @@
1
1
  import { InstrumentSelector } from '../domain';
2
- import { StoreEvent } from '../store';
3
- import { Storage, StorageQueryOptions } from './storage';
2
+ import { d } from '../shared';
3
+ import { OrderbookPatchEvent, TradePatchEvent } from '../store';
4
+ import { Storage, StorageDocument, StorageQueryOptions } from './storage';
5
+
6
+ export type StorageEvent = TradePatchEvent | OrderbookPatchEvent;
4
7
 
5
8
  /**
6
9
  * Represents a storage supposed to store historical data.
@@ -18,21 +21,29 @@ export class Feed {
18
21
 
19
22
  /**
20
23
  *
21
- * @param instrument
22
24
  * @param events
23
25
  * @returns
24
26
  */
25
- save(instrument: InstrumentSelector, events: StoreEvent[]): Promise<void> {
26
- return this.storage.save(
27
- instrument.toString(),
28
- events.map(it => ({
29
- timestamp: it.timestamp,
30
- kind: it.type,
31
- json: JSON.stringify(it, (key, value) =>
32
- key != 'timestamp' && key != 'type' && key != 'instrument' ? value : undefined
33
- )
34
- }))
35
- );
27
+ async save(events: StorageEvent[]): Promise<void> {
28
+ const grouped = events.reduce((aggregate, it) => {
29
+ const document = this.serializeEvent(it);
30
+
31
+ if (!document) {
32
+ return aggregate;
33
+ }
34
+
35
+ if (aggregate[it.instrument.id]) {
36
+ aggregate[it.instrument.id].push(document);
37
+ } else {
38
+ aggregate[it.instrument.id] = [document];
39
+ }
40
+
41
+ return aggregate;
42
+ }, {} as Record<string, StorageDocument[]>);
43
+
44
+ for (const instrument in grouped) {
45
+ await this.storage.save(instrument, grouped[instrument]);
46
+ }
36
47
  }
37
48
 
38
49
  /**
@@ -44,14 +55,68 @@ export class Feed {
44
55
  async query(
45
56
  instrument: InstrumentSelector,
46
57
  options: StorageQueryOptions
47
- ): Promise<StoreEvent[]> {
48
- const rows = await this.storage.query(instrument.toString(), options);
49
-
50
- return rows.map(it => ({
51
- timestamp: it.timestamp,
52
- type: it.kind,
53
- instrument,
54
- ...JSON.parse(it.json)
55
- }));
58
+ ): Promise<StorageEvent[]> {
59
+ const documents = await this.storage.query(instrument.id, options);
60
+
61
+ return documents.map(it => this.deserializeEvent(it, instrument));
62
+ }
63
+
64
+ /**
65
+ * Converts a StorageEvent to a persisted StorageDocument.
66
+ */
67
+ protected serializeEvent(event: StorageEvent): StorageDocument | undefined {
68
+ if (event instanceof OrderbookPatchEvent) {
69
+ return {
70
+ timestamp: event.timestamp,
71
+ kind: 'orderbook',
72
+ json: JSON.stringify({
73
+ ar: event.ask.rate.toString(),
74
+ ab: event.ask.quantity.toString(),
75
+ br: event.bid.rate.toString(),
76
+ bb: event.bid.quantity.toString()
77
+ })
78
+ };
79
+ }
80
+
81
+ if (event instanceof TradePatchEvent) {
82
+ return {
83
+ timestamp: event.timestamp,
84
+ kind: 'trade',
85
+ json: JSON.stringify({
86
+ r: event.rate.toString(),
87
+ q: event.quantity.toString()
88
+ })
89
+ };
90
+ }
91
+
92
+ return undefined;
93
+ }
94
+
95
+ /**
96
+ * Converts a persisted StorageDocument to a StorageEvent.
97
+ */
98
+ protected deserializeEvent(
99
+ document: StorageDocument,
100
+ instrument: InstrumentSelector
101
+ ): StorageEvent {
102
+ const payload = JSON.parse(document.json);
103
+
104
+ if (document.kind === 'trade') {
105
+ return new TradePatchEvent(
106
+ instrument,
107
+ d(payload.r),
108
+ d(payload.q),
109
+ document.timestamp
110
+ );
111
+ }
112
+
113
+ if (document.kind === 'orderbook') {
114
+ return new OrderbookPatchEvent(
115
+ instrument,
116
+ { rate: d(payload.ar), quantity: d(payload.aq), next: undefined },
117
+ { rate: d(payload.bb), quantity: d(payload.bq), next: undefined },
118
+ document.timestamp
119
+ );
120
+ }
56
121
  }
57
122
  }
@@ -11,6 +11,11 @@ export type StorageQueryOptions = {
11
11
  count: number;
12
12
  };
13
13
 
14
+ /**
15
+ *
16
+ */
17
+ export type StorageFactory = (type: string) => Storage;
18
+
14
19
  /**
15
20
  *
16
21
  */
@@ -35,11 +40,10 @@ export interface Storage {
35
40
  query(library: string, options: StorageQueryOptions): Promise<StorageDocument[]>;
36
41
  }
37
42
 
38
- /**
39
- *
40
- */
41
- export interface StorageFactory {
42
- create(type: string): Storage;
43
+ export function inMemoryStorageFactory(): StorageFactory {
44
+ const storage: Record<string, Storage> = {};
45
+
46
+ return (type: string) => storage[type] ?? (storage[type] = new InMemoryStorage());
43
47
  }
44
48
 
45
49
  /**
@@ -118,11 +122,3 @@ export class InMemoryStorage implements Storage {
118
122
  this.tables = {};
119
123
  }
120
124
  }
121
-
122
- export class InMemoryStorageFactory implements StorageFactory {
123
- private readonly storage: Record<string, Storage> = {};
124
-
125
- create(type: string): Storage {
126
- return this.storage[type] ?? (this.storage[type] = new InMemoryStorage());
127
- }
128
- }
@@ -1,3 +1,9 @@
1
- export * from './event';
2
1
  export * from './store';
3
- export * from './store.state';
2
+ export * from './store-state';
3
+ export * from './store-balance.event';
4
+ export * from './store-instrument.event';
5
+ export * from './store-order.event';
6
+ export * from './store-orderbook.event';
7
+ export * from './store-position.event';
8
+ export * from './store-trade.event';
9
+ export * from './store.event';
@@ -1,10 +1,10 @@
1
- import { Asset, Commission } from '../../domain';
2
- import { now } from '../../shared';
3
- import { Store } from '..';
4
- import { BalancePatchEvent } from '.';
1
+ import { Asset, Commission } from '../domain';
2
+ import { d, now } from '../shared';
3
+ import { Store } from '.';
4
+ import { BalancePatchEvent } from './store-balance.event';
5
5
  import { InstrumentPatchEvent } from './store-instrument.event';
6
6
 
7
- describe('balance event tests', () => {
7
+ describe('BalancePatchEvent', () => {
8
8
  test('should patch a store', () => {
9
9
  const base = new Asset('de30', 'cex', 2);
10
10
  const quote = new Asset('usd', 'cex', 2);
@@ -15,15 +15,15 @@ describe('balance event tests', () => {
15
15
  store.changes$.subscribe(it => (component = it));
16
16
 
17
17
  store.dispatch(
18
- new InstrumentPatchEvent(timestamp, base, quote, new Commission(0, 0), '')
18
+ new InstrumentPatchEvent(timestamp, base, quote, new Commission(d.Zero, d.Zero), '')
19
19
  );
20
- store.dispatch(new BalancePatchEvent(base, 100, 0, timestamp));
20
+ store.dispatch(new BalancePatchEvent(base, d(100), d.Zero, timestamp));
21
21
 
22
- const balance = store.snapshot.balance[base.toString()];
22
+ const balance = store.snapshot.balance.get(base.id);
23
23
 
24
24
  expect(balance).toEqual(component);
25
- expect(balance.free).toEqual(100);
26
- expect(balance.locked).toEqual(0);
25
+ expect(balance.free).toEqual(d(100));
26
+ expect(balance.locked).toEqual(d.Zero);
27
27
  expect(balance.timestamp).toEqual(timestamp);
28
28
  expect(store.snapshot.timestamp).toEqual(timestamp);
29
29
  });
@@ -0,0 +1,124 @@
1
+ import { AssetSelector, Balance, InstrumentSelector } from '../domain';
2
+ import { decimal, timestamp } from '../shared';
3
+ import { StoreEvent } from './store.event';
4
+ import { State, StateChangeTracker } from './store-state';
5
+
6
+ /**
7
+ * Updates the free and freezed balance of the given asset.
8
+ */
9
+ export class BalancePatchEvent implements StoreEvent {
10
+ constructor(
11
+ readonly asset: AssetSelector,
12
+ readonly free: decimal,
13
+ readonly freezed: decimal,
14
+ readonly timestamp: timestamp
15
+ ) {}
16
+
17
+ handle(state: State, changes: StateChangeTracker) {
18
+ // you can have not tradeable assets in wallet, skip them.
19
+ const asset = state.universe.asset.get(this.asset.id);
20
+ if (!asset) {
21
+ return;
22
+ }
23
+
24
+ const balance = state.balance.tryGetOrSet(this.asset.id, () => new Balance(asset));
25
+
26
+ balance.timestamp = this.timestamp;
27
+ balance.set(this.free, this.freezed);
28
+
29
+ state.timestamp = this.timestamp;
30
+
31
+ changes.commit(balance);
32
+ }
33
+ }
34
+ /**
35
+ *
36
+ */
37
+ export class BalanceTransactEvent implements StoreEvent {
38
+ constructor(
39
+ readonly asset: AssetSelector,
40
+ readonly amount: decimal,
41
+ readonly timestamp: timestamp
42
+ ) {}
43
+
44
+ handle(state: State, changes: StateChangeTracker) {
45
+ const balance = state.balance.tryGetOrSet(this.asset.id, () => {
46
+ const asset = state.universe.asset.get(this.asset.id);
47
+
48
+ return new Balance(asset);
49
+ });
50
+
51
+ balance.timestamp = this.timestamp;
52
+ balance.account(this.amount);
53
+
54
+ state.timestamp = this.timestamp;
55
+
56
+ changes.commit(balance);
57
+ }
58
+ }
59
+
60
+ /**
61
+ *
62
+ */
63
+ export class BalanceLockOrderEvent implements StoreEvent {
64
+ constructor(
65
+ readonly orderId: string,
66
+ readonly instrument: InstrumentSelector,
67
+ readonly timestamp: timestamp
68
+ ) {}
69
+
70
+ handle(state: State, changes: StateChangeTracker) {
71
+ const order = state.order.get(this.instrument.id).get(this.orderId);
72
+ const base = state.balance.get(order.instrument.base.id);
73
+ const quote = state.balance.get(order.instrument.quote.id);
74
+
75
+ const balanceToLock = order.calculateBalanceToLock(base, quote);
76
+
77
+ state.timestamp = this.timestamp;
78
+
79
+ if (balanceToLock.base.greaterThan(0)) {
80
+ base.timestamp = this.timestamp;
81
+ base.lock(this.orderId, balanceToLock.base);
82
+
83
+ changes.commit(base);
84
+ }
85
+
86
+ if (balanceToLock.quote.greaterThan(0)) {
87
+ quote.timestamp = this.timestamp;
88
+ quote.lock(this.orderId, balanceToLock.quote);
89
+
90
+ changes.commit(quote);
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ *
97
+ */
98
+ export class BalanceUnlockOrderEvent implements StoreEvent {
99
+ constructor(
100
+ readonly orderId: string,
101
+ readonly instrument: InstrumentSelector,
102
+ readonly timestamp: timestamp
103
+ ) {}
104
+
105
+ handle(state: State, changes: StateChangeTracker) {
106
+ const order = state.order.get(this.instrument.id).get(this.orderId);
107
+ const base = state.balance.get(order.instrument.base.id);
108
+ const quote = state.balance.get(order.instrument.quote.id);
109
+
110
+ state.timestamp = this.timestamp;
111
+
112
+ if (base.tryUnlock(this.orderId)) {
113
+ base.timestamp = this.timestamp;
114
+
115
+ changes.commit(base);
116
+ }
117
+
118
+ if (quote.tryUnlock(this.orderId)) {
119
+ quote.timestamp = this.timestamp;
120
+
121
+ changes.commit(quote);
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,25 @@
1
+ import { Store } from '..';
2
+ import { Asset, Commission } from '../domain';
3
+ import { d, now } from '../shared';
4
+ import { InstrumentPatchEvent } from './store-instrument.event';
5
+
6
+ describe('InstrumentPatchEvent', () => {
7
+ test('should patch a store', () => {
8
+ const timestamp = now();
9
+ const store = new Store();
10
+ const base = new Asset('de30', 'cex', 2);
11
+ const quote = new Asset('usd', 'cex', 2);
12
+
13
+ store.dispatch(
14
+ new InstrumentPatchEvent(timestamp, base, quote, new Commission(d.Zero, d.Zero), '')
15
+ );
16
+
17
+ const { universe } = store.snapshot;
18
+
19
+ expect(universe.instrument.get('cex:de30-usd').base).toEqual(base);
20
+ expect(universe.instrument.get('cex:de30-usd').quote).toEqual(quote);
21
+ expect(universe.instrument.get('cex:de30-usd').timestamp).toEqual(timestamp);
22
+ expect(universe.instrument.asReadonlyArray().length).toEqual(1);
23
+ expect(universe.asset.asReadonlyArray().length).toEqual(2);
24
+ });
25
+ });
@@ -0,0 +1,72 @@
1
+ import { Asset, Commission, Instrument, InstrumentSelector } from '../domain';
2
+ import { timestamp } from '../shared';
3
+ import { State, StateChangeTracker } from '../store';
4
+ import { StoreEvent } from './store.event';
5
+ import { InnerSet } from './store-state';
6
+
7
+ export class InstrumentPatchEvent implements StoreEvent {
8
+ constructor(
9
+ readonly timestamp: timestamp,
10
+ readonly base: Asset,
11
+ readonly quote: Asset,
12
+ readonly commission: Commission,
13
+ readonly raw: string,
14
+ readonly leverage?: number
15
+ ) {}
16
+
17
+ handle(state: State, changes: StateChangeTracker): void {
18
+ const selector = new InstrumentSelector(
19
+ this.base.name,
20
+ this.quote.name,
21
+ this.base.adapterName
22
+ );
23
+
24
+ const instrument = state.universe.instrument.tryGetOrSet(selector.id, () => {
25
+ state.universe.asset.tryGetOrSet(
26
+ this.base.id,
27
+ () => new Asset(this.base.name, this.base.adapterName, 8)
28
+ );
29
+
30
+ state.universe.asset.tryGetOrSet(
31
+ this.quote.id,
32
+ () => new Asset(this.quote.name, this.quote.adapterName, 8)
33
+ );
34
+
35
+ state.order.tryGetOrSet(selector.id, () => new InnerSet(selector.id));
36
+
37
+ return new Instrument(this.base, this.quote, this.raw);
38
+ });
39
+
40
+ instrument.timestamp = this.timestamp;
41
+ instrument.commission = this.commission;
42
+
43
+ if (this.leverage) {
44
+ instrument.leverage = this.leverage;
45
+ }
46
+
47
+ changes.commit(instrument);
48
+ }
49
+ }
50
+
51
+ export class InstrumentSubscriptionEvent implements StoreEvent {
52
+ constructor(
53
+ readonly timestamp: timestamp,
54
+ readonly instrument: InstrumentSelector,
55
+ readonly subscribed: boolean
56
+ ) {}
57
+
58
+ handle(state: State, changes: StateChangeTracker): void {
59
+ const instrument = state.universe.instrument.get(this.instrument.id);
60
+ if (!instrument) {
61
+ throw new Error('invalid instrument');
62
+ }
63
+
64
+ if (this.subscribed) {
65
+ state.subscription.instrument.upsert(instrument);
66
+ state.subscription.asset.upsert(state.universe.asset.get(instrument.base.id));
67
+ state.subscription.asset.upsert(state.universe.asset.get(instrument.quote.id));
68
+ }
69
+
70
+ changes.commit(instrument);
71
+ }
72
+ }
@@ -0,0 +1,28 @@
1
+ import { Asset, Instrument, Order } from '../domain';
2
+ import { d, now } from '../shared';
3
+ import { Store } from '../store';
4
+ import { OrderLoadEvent } from './store-order.event';
5
+
6
+ const instrument = new Instrument(
7
+ new Asset('btc', 'binance', 8),
8
+ new Asset('usdt', 'binance', 2),
9
+ 'binance:btc-usdt'
10
+ );
11
+
12
+ describe('OrderLoadEvent', () => {
13
+ test('should load order to store', () => {
14
+ const timestamp = now();
15
+ const store = new Store();
16
+ const order = Order.market(instrument, d(1.0));
17
+
18
+ order.state = 'PENDING';
19
+
20
+ store.snapshot.universe.instrument.upsert(instrument);
21
+ store.snapshot.subscription.instrument.upsert(instrument);
22
+
23
+ store.dispatch(new OrderLoadEvent(order, timestamp));
24
+
25
+ expect(store.snapshot.order.asReadonlyArray().length).toEqual(1);
26
+ expect(store.snapshot.order.get(instrument.id).get(order.id)).toEqual(order);
27
+ });
28
+ });