@quantform/core 0.6.5 → 0.6.7

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 (336) hide show
  1. package/dist/adapter/adapter-aggregate.d.ts +2 -2
  2. package/dist/adapter/adapter-aggregate.d.ts.map +1 -1
  3. package/dist/adapter/adapter-aggregate.js +12 -11
  4. package/dist/adapter/adapter.d.ts +2 -3
  5. package/dist/adapter/adapter.d.ts.map +1 -1
  6. package/dist/adapter/backtester/backtester-adapter.d.ts +1 -5
  7. package/dist/adapter/backtester/backtester-adapter.d.ts.map +1 -1
  8. package/dist/adapter/backtester/backtester-adapter.js +2 -2
  9. package/dist/adapter/backtester/backtester-cursor.d.ts.map +1 -1
  10. package/dist/adapter/backtester/backtester-cursor.js +2 -2
  11. package/dist/adapter/backtester/backtester-cursor.spec.d.ts +2 -0
  12. package/dist/adapter/backtester/backtester-cursor.spec.d.ts.map +1 -0
  13. package/dist/adapter/backtester/backtester-cursor.spec.js +47 -0
  14. package/dist/adapter/backtester/backtester-streamer.d.ts +1 -1
  15. package/dist/adapter/backtester/backtester-streamer.d.ts.map +1 -1
  16. package/dist/adapter/backtester/backtester-streamer.js +4 -5
  17. package/dist/adapter/backtester/backtester-streamer.spec.d.ts +2 -0
  18. package/dist/adapter/backtester/backtester-streamer.spec.d.ts.map +1 -0
  19. package/dist/adapter/backtester/backtester-streamer.spec.js +45 -0
  20. package/dist/adapter/backtester/error.d.ts +6 -2
  21. package/dist/adapter/backtester/error.d.ts.map +1 -1
  22. package/dist/adapter/backtester/error.js +11 -7
  23. package/dist/adapter/backtester/index.d.ts +4 -2
  24. package/dist/adapter/backtester/index.d.ts.map +1 -1
  25. package/dist/adapter/backtester/index.js +4 -2
  26. package/dist/adapter/error.d.ts +9 -3
  27. package/dist/adapter/error.d.ts.map +1 -1
  28. package/dist/adapter/error.js +16 -10
  29. package/dist/adapter/index.d.ts +5 -4
  30. package/dist/adapter/index.d.ts.map +1 -1
  31. package/dist/adapter/index.js +5 -4
  32. package/dist/adapter/paper/engine/paper-engine.d.ts.map +1 -1
  33. package/dist/adapter/paper/engine/paper-engine.js +7 -8
  34. package/dist/adapter/paper/engine/paper-engine.spec.d.ts +2 -0
  35. package/dist/adapter/paper/engine/paper-engine.spec.d.ts.map +1 -0
  36. package/dist/adapter/paper/engine/paper-engine.spec.js +63 -0
  37. package/dist/adapter/paper/index.d.ts +2 -2
  38. package/dist/adapter/paper/index.d.ts.map +1 -1
  39. package/dist/adapter/paper/index.js +2 -2
  40. package/dist/adapter/paper/paper-adapter.d.ts +1 -3
  41. package/dist/adapter/paper/paper-adapter.d.ts.map +1 -1
  42. package/dist/adapter/paper/paper-adapter.js +8 -7
  43. package/dist/cli/build.js +1 -1
  44. package/dist/cli/dev.js +6 -6
  45. package/dist/cli/index.js +5 -5
  46. package/dist/cli/internal/workspace.js +1 -1
  47. package/dist/cli/pull.js +6 -6
  48. package/dist/cli/run.js +6 -6
  49. package/dist/cli/test.d.ts.map +1 -1
  50. package/dist/cli/test.js +9 -8
  51. package/dist/domain/asset.d.ts +5 -1
  52. package/dist/domain/asset.d.ts.map +1 -1
  53. package/dist/domain/asset.js +13 -7
  54. package/dist/domain/asset.spec.d.ts +2 -0
  55. package/dist/domain/asset.spec.d.ts.map +1 -0
  56. package/dist/domain/asset.spec.js +54 -0
  57. package/dist/domain/balance-operator.d.ts +1 -3
  58. package/dist/domain/balance-operator.d.ts.map +1 -1
  59. package/dist/domain/balance-operator.js +2 -2
  60. package/dist/domain/balance-operator.spec.d.ts +2 -0
  61. package/dist/domain/balance-operator.spec.d.ts.map +1 -0
  62. package/dist/domain/balance-operator.spec.js +21 -0
  63. package/dist/domain/balance.d.ts +14 -15
  64. package/dist/domain/balance.d.ts.map +1 -1
  65. package/dist/domain/balance.js +30 -48
  66. package/dist/domain/balance.spec.d.ts +2 -0
  67. package/dist/domain/balance.spec.d.ts.map +1 -0
  68. package/dist/domain/balance.spec.js +32 -0
  69. package/dist/domain/commission.d.ts.map +1 -1
  70. package/dist/domain/commission.spec.d.ts +2 -0
  71. package/dist/domain/commission.spec.d.ts.map +1 -0
  72. package/dist/domain/commission.spec.js +30 -0
  73. package/dist/domain/component.d.ts +2 -2
  74. package/dist/domain/component.d.ts.map +1 -1
  75. package/dist/domain/error.d.ts +15 -5
  76. package/dist/domain/error.d.ts.map +1 -1
  77. package/dist/domain/error.js +26 -16
  78. package/dist/domain/index.d.ts +21 -21
  79. package/dist/domain/index.d.ts.map +1 -1
  80. package/dist/domain/index.js +21 -21
  81. package/dist/domain/instrument-operator.d.ts +1 -2
  82. package/dist/domain/instrument-operator.d.ts.map +1 -1
  83. package/dist/domain/instrument-operator.js +3 -3
  84. package/dist/domain/instrument-operator.spec.d.ts +2 -0
  85. package/dist/domain/instrument-operator.spec.d.ts.map +1 -0
  86. package/dist/domain/instrument-operator.spec.js +21 -0
  87. package/dist/domain/instrument.d.ts +3 -3
  88. package/dist/domain/instrument.d.ts.map +1 -1
  89. package/dist/domain/instrument.js +10 -8
  90. package/dist/domain/instrument.spec.d.ts +2 -0
  91. package/dist/domain/instrument.spec.d.ts.map +1 -0
  92. package/dist/domain/instrument.spec.js +51 -0
  93. package/dist/domain/ohlc-operator.d.ts +1 -1
  94. package/dist/domain/ohlc-operator.d.ts.map +1 -1
  95. package/dist/domain/ohlc-operator.js +4 -5
  96. package/dist/domain/ohlc-operator.spec.d.ts +2 -0
  97. package/dist/domain/ohlc-operator.spec.d.ts.map +1 -0
  98. package/dist/domain/ohlc-operator.spec.js +110 -0
  99. package/dist/domain/ohlc.d.ts.map +1 -1
  100. package/dist/domain/ohlc.spec.d.ts +2 -0
  101. package/dist/domain/ohlc.spec.d.ts.map +1 -0
  102. package/dist/domain/ohlc.spec.js +25 -0
  103. package/dist/domain/order-operator.d.ts +1 -3
  104. package/dist/domain/order-operator.d.ts.map +1 -1
  105. package/dist/domain/order-operator.js +3 -3
  106. package/dist/domain/order-operator.spec.d.ts +2 -0
  107. package/dist/domain/order-operator.spec.d.ts.map +1 -0
  108. package/dist/domain/order-operator.spec.js +61 -0
  109. package/dist/domain/order.d.ts +5 -8
  110. package/dist/domain/order.d.ts.map +1 -1
  111. package/dist/domain/order.js +14 -22
  112. package/dist/domain/order.spec.d.ts +2 -0
  113. package/dist/domain/order.spec.d.ts.map +1 -0
  114. package/dist/domain/order.spec.js +27 -0
  115. package/dist/domain/orderbook-operator.d.ts +1 -3
  116. package/dist/domain/orderbook-operator.d.ts.map +1 -1
  117. package/dist/domain/orderbook-operator.js +2 -2
  118. package/dist/domain/orderbook-operator.spec.d.ts +2 -0
  119. package/dist/domain/orderbook-operator.spec.d.ts.map +1 -0
  120. package/dist/domain/orderbook-operator.spec.js +19 -0
  121. package/dist/domain/orderbook.d.ts +3 -2
  122. package/dist/domain/orderbook.d.ts.map +1 -1
  123. package/dist/domain/orderbook.js +3 -0
  124. package/dist/domain/orderbook.spec.d.ts +2 -0
  125. package/dist/domain/orderbook.spec.d.ts.map +1 -0
  126. package/dist/domain/orderbook.spec.js +11 -0
  127. package/dist/domain/position-operator.d.ts +1 -3
  128. package/dist/domain/position-operator.d.ts.map +1 -1
  129. package/dist/domain/position-operator.js +3 -4
  130. package/dist/domain/position-operator.spec.d.ts +2 -0
  131. package/dist/domain/position-operator.spec.d.ts.map +1 -0
  132. package/dist/domain/position-operator.spec.js +44 -0
  133. package/dist/domain/position.d.ts +3 -2
  134. package/dist/domain/position.d.ts.map +1 -1
  135. package/dist/domain/position.js +2 -0
  136. package/dist/domain/position.spec.d.ts +2 -0
  137. package/dist/domain/position.spec.d.ts.map +1 -0
  138. package/dist/domain/position.spec.js +28 -0
  139. package/dist/domain/session-builder.d.ts +8 -4
  140. package/dist/domain/session-builder.d.ts.map +1 -1
  141. package/dist/domain/session-builder.js +10 -15
  142. package/dist/domain/session.d.ts +1 -1
  143. package/dist/domain/session.d.ts.map +1 -1
  144. package/dist/domain/session.js +11 -17
  145. package/dist/domain/session.spec.d.ts +2 -0
  146. package/dist/domain/session.spec.d.ts.map +1 -0
  147. package/dist/domain/session.spec.js +17 -0
  148. package/dist/domain/trade-operator.d.ts +1 -3
  149. package/dist/domain/trade-operator.d.ts.map +1 -1
  150. package/dist/domain/trade-operator.js +2 -2
  151. package/dist/domain/trade-operator.spec.d.ts +2 -0
  152. package/dist/domain/trade-operator.spec.d.ts.map +1 -0
  153. package/dist/domain/trade-operator.spec.js +21 -0
  154. package/dist/domain/trade.d.ts +3 -2
  155. package/dist/domain/trade.d.ts.map +1 -1
  156. package/dist/domain/trade.js +3 -0
  157. package/dist/domain/trade.spec.d.ts +2 -0
  158. package/dist/domain/trade.spec.d.ts.map +1 -0
  159. package/dist/domain/trade.spec.js +11 -0
  160. package/dist/index.d.ts +2 -2
  161. package/dist/index.d.ts.map +1 -1
  162. package/dist/index.js +9 -8
  163. package/dist/shared/collections.spec.d.ts +2 -0
  164. package/dist/shared/collections.spec.d.ts.map +1 -0
  165. package/dist/shared/collections.spec.js +29 -0
  166. package/dist/shared/decimals.spec.d.ts +2 -0
  167. package/dist/shared/decimals.spec.d.ts.map +1 -0
  168. package/dist/shared/decimals.spec.js +28 -0
  169. package/dist/shared/hash.d.ts +2 -0
  170. package/dist/shared/hash.d.ts.map +1 -0
  171. package/dist/shared/hash.js +12 -0
  172. package/dist/shared/index.d.ts +7 -7
  173. package/dist/shared/index.d.ts.map +1 -1
  174. package/dist/shared/index.js +7 -7
  175. package/dist/shared/logger.d.ts +8 -5
  176. package/dist/shared/logger.d.ts.map +1 -1
  177. package/dist/shared/logger.js +23 -16
  178. package/dist/storage/cache.d.ts +1 -1
  179. package/dist/storage/cache.d.ts.map +1 -1
  180. package/dist/storage/cache.spec.d.ts +2 -0
  181. package/dist/storage/cache.spec.d.ts.map +1 -0
  182. package/dist/storage/cache.spec.js +25 -0
  183. package/dist/storage/feed.d.ts +1 -1
  184. package/dist/storage/feed.d.ts.map +1 -1
  185. package/dist/storage/index.d.ts +4 -4
  186. package/dist/storage/index.d.ts.map +1 -1
  187. package/dist/storage/index.js +4 -4
  188. package/dist/storage/measurement.d.ts +1 -1
  189. package/dist/storage/measurement.d.ts.map +1 -1
  190. package/dist/store/error.d.ts +21 -7
  191. package/dist/store/error.d.ts.map +1 -1
  192. package/dist/store/error.js +36 -22
  193. package/dist/store/index.d.ts +10 -9
  194. package/dist/store/index.d.ts.map +1 -1
  195. package/dist/store/index.js +10 -9
  196. package/dist/store/store-balance-event.d.ts +10 -30
  197. package/dist/store/store-balance-event.d.ts.map +1 -1
  198. package/dist/store/store-balance-event.js +19 -94
  199. package/dist/store/store-balance-event.spec.d.ts +2 -0
  200. package/dist/store/store-balance-event.spec.d.ts.map +1 -0
  201. package/dist/store/store-balance-event.spec.js +24 -0
  202. package/dist/store/store-event.d.ts +1 -1
  203. package/dist/store/store-event.d.ts.map +1 -1
  204. package/dist/store/store-instrument-event.d.ts +1 -2
  205. package/dist/store/store-instrument-event.d.ts.map +1 -1
  206. package/dist/store/store-instrument-event.js +5 -6
  207. package/dist/store/store-instrument-event.spec.d.ts +2 -0
  208. package/dist/store/store-instrument-event.spec.d.ts.map +1 -0
  209. package/dist/store/store-instrument-event.spec.js +22 -0
  210. package/dist/store/store-order-event.d.ts +1 -2
  211. package/dist/store/store-order-event.d.ts.map +1 -1
  212. package/dist/store/store-order-event.js +60 -22
  213. package/dist/store/store-order-event.spec.d.ts +2 -0
  214. package/dist/store/store-order-event.spec.d.ts.map +1 -0
  215. package/dist/store/store-order-event.spec.js +23 -0
  216. package/dist/store/store-orderbook-event.d.ts +1 -2
  217. package/dist/store/store-orderbook-event.d.ts.map +1 -1
  218. package/dist/store/store-orderbook-event.js +3 -3
  219. package/dist/store/store-orderbook-event.spec.d.ts +2 -0
  220. package/dist/store/store-orderbook-event.spec.d.ts.map +1 -0
  221. package/dist/store/store-orderbook-event.spec.js +27 -0
  222. package/dist/store/store-position-event.d.ts +1 -2
  223. package/dist/store/store-position-event.d.ts.map +1 -1
  224. package/dist/store/store-position-event.js +5 -5
  225. package/dist/store/store-state.d.ts.map +1 -1
  226. package/dist/store/store-trade-event.d.ts +1 -2
  227. package/dist/store/store-trade-event.d.ts.map +1 -1
  228. package/dist/store/store-trade-event.js +3 -3
  229. package/dist/store/store-trade-event.spec.d.ts +2 -0
  230. package/dist/store/store-trade-event.spec.d.ts.map +1 -0
  231. package/dist/store/store-trade-event.spec.js +44 -0
  232. package/dist/store/store.d.ts +1 -2
  233. package/dist/store/store.d.ts.map +1 -1
  234. package/dist/store/store.js +5 -2
  235. package/dist/store/store.spec.d.ts +2 -0
  236. package/dist/store/store.spec.d.ts.map +1 -0
  237. package/dist/store/store.spec.js +122 -0
  238. package/jest.config.ts +23 -2
  239. package/package.json +2 -2
  240. package/src/adapter/adapter-aggregate.ts +35 -21
  241. package/src/adapter/adapter.ts +6 -7
  242. package/src/adapter/backtester/backtester-adapter.ts +12 -8
  243. package/src/adapter/backtester/backtester-cursor.spec.ts +6 -6
  244. package/src/adapter/backtester/backtester-cursor.ts +5 -5
  245. package/src/adapter/backtester/backtester-streamer.spec.ts +6 -6
  246. package/src/adapter/backtester/backtester-streamer.ts +12 -9
  247. package/src/adapter/backtester/error.ts +8 -4
  248. package/src/adapter/backtester/index.ts +4 -2
  249. package/src/adapter/error.ts +14 -8
  250. package/src/adapter/index.ts +5 -4
  251. package/src/adapter/paper/engine/paper-engine.spec.ts +6 -12
  252. package/src/adapter/paper/engine/paper-engine.ts +13 -28
  253. package/src/adapter/paper/index.ts +2 -2
  254. package/src/adapter/paper/paper-adapter.ts +18 -11
  255. package/src/cli/build.ts +1 -1
  256. package/src/cli/dev.ts +5 -5
  257. package/src/cli/index.ts +5 -5
  258. package/src/cli/internal/workspace.ts +1 -1
  259. package/src/cli/pull.ts +7 -7
  260. package/src/cli/run.ts +5 -5
  261. package/src/cli/test.ts +8 -7
  262. package/src/domain/asset.spec.ts +4 -4
  263. package/src/domain/asset.ts +13 -6
  264. package/src/domain/balance-operator.spec.ts +3 -6
  265. package/src/domain/balance-operator.ts +5 -6
  266. package/src/domain/balance.spec.ts +7 -77
  267. package/src/domain/balance.ts +51 -64
  268. package/src/domain/commission.spec.ts +3 -3
  269. package/src/domain/commission.ts +1 -1
  270. package/src/domain/component.ts +3 -3
  271. package/src/domain/error.ts +23 -18
  272. package/src/domain/index.ts +21 -21
  273. package/src/domain/instrument-operator.spec.ts +10 -7
  274. package/src/domain/instrument-operator.ts +6 -6
  275. package/src/domain/instrument.spec.ts +11 -6
  276. package/src/domain/instrument.ts +16 -7
  277. package/src/domain/ohlc-operator.spec.ts +5 -6
  278. package/src/domain/ohlc-operator.ts +2 -3
  279. package/src/domain/ohlc.spec.ts +2 -2
  280. package/src/domain/ohlc.ts +2 -2
  281. package/src/domain/order-operator.spec.ts +14 -10
  282. package/src/domain/order-operator.ts +8 -7
  283. package/src/domain/order.spec.ts +3 -6
  284. package/src/domain/order.ts +26 -29
  285. package/src/domain/orderbook-operator.spec.ts +11 -9
  286. package/src/domain/orderbook-operator.ts +5 -6
  287. package/src/domain/orderbook.spec.ts +3 -6
  288. package/src/domain/orderbook.ts +5 -3
  289. package/src/domain/position-operator.spec.ts +14 -11
  290. package/src/domain/position-operator.ts +12 -9
  291. package/src/domain/position.spec.ts +3 -6
  292. package/src/domain/position.ts +5 -3
  293. package/src/domain/session-builder.ts +14 -14
  294. package/src/domain/session.spec.ts +4 -4
  295. package/src/domain/session.ts +20 -15
  296. package/src/domain/trade-operator.spec.ts +4 -9
  297. package/src/domain/trade-operator.ts +5 -6
  298. package/src/domain/trade.spec.ts +3 -6
  299. package/src/domain/trade.ts +5 -3
  300. package/src/index.ts +15 -14
  301. package/src/shared/collections.spec.ts +2 -2
  302. package/src/shared/decimals.spec.ts +1 -1
  303. package/src/shared/hash.ts +10 -0
  304. package/src/shared/index.ts +7 -7
  305. package/src/shared/logger.ts +22 -15
  306. package/src/storage/cache.spec.ts +2 -3
  307. package/src/storage/cache.ts +2 -2
  308. package/src/storage/feed.ts +4 -4
  309. package/src/storage/index.ts +4 -4
  310. package/src/storage/measurement.ts +2 -2
  311. package/src/store/error.ts +33 -22
  312. package/src/store/index.ts +10 -9
  313. package/src/store/store-balance-event.spec.ts +5 -7
  314. package/src/store/store-balance-event.ts +20 -115
  315. package/src/store/store-event.ts +2 -2
  316. package/src/store/store-instrument-event.spec.ts +4 -5
  317. package/src/store/store-instrument-event.ts +13 -9
  318. package/src/store/store-order-event.spec.ts +6 -5
  319. package/src/store/store-order-event.ts +92 -23
  320. package/src/store/store-orderbook-event.spec.ts +4 -5
  321. package/src/store/store-orderbook-event.ts +11 -7
  322. package/src/store/store-position-event.ts +13 -9
  323. package/src/store/store-state.ts +2 -2
  324. package/src/store/store-trade-event.spec.ts +4 -5
  325. package/src/store/store-trade-event.ts +11 -7
  326. package/src/store/store.spec.ts +45 -31
  327. package/src/store/store.ts +6 -3
  328. package/tsconfig.json +7 -4
  329. package/dist/cli/error.d.ts +0 -2
  330. package/dist/cli/error.d.ts.map +0 -1
  331. package/dist/cli/error.js +0 -7
  332. package/dist/shared/pipe.d.ts +0 -5
  333. package/dist/shared/pipe.d.ts.map +0 -1
  334. package/dist/shared/pipe.js +0 -8
  335. package/src/cli/error.ts +0 -5
  336. package/src/shared/pipe.ts +0 -12
@@ -1,24 +1,27 @@
1
- import { d, decimal } from '../shared';
2
- import { Asset } from './';
3
- import { Component } from './component';
4
- import { insufficientFundsError, invalidArgumentError } from './error';
5
- import { Position, PositionMode } from './position';
1
+ import { Asset, Component, Position, PositionMode } from '@lib/domain';
2
+ import { d, decimal, hash } from '@lib/shared';
3
+
4
+ export interface Fundable {
5
+ id: string;
6
+ getFundingAmount(balance: Balance): decimal;
7
+ }
6
8
 
7
9
  /**
8
10
  * Represents single asset balance in your wallet.
9
11
  */
10
12
  export class Balance implements Component {
13
+ static type = hash(Balance.name);
14
+ readonly type = Balance.type;
15
+
11
16
  id: string;
12
17
 
13
- private locker: Record<string, decimal> = {};
14
- private available = d.Zero;
15
- private unavailable = d.Zero;
18
+ private transientFunding: Record<string, Fundable> = {};
16
19
 
17
20
  /**
18
21
  * Returns available amount to trade.
19
22
  */
20
23
  get free(): decimal {
21
- return this.asset.floor(this.available).add(this.getEstimatedUnrealizedPnL('CROSS'));
24
+ return this.available.add(this.getEstimatedUnrealizedPnL('CROSS'));
22
25
  }
23
26
 
24
27
  /**
@@ -33,9 +36,7 @@ export class Balance implements Component {
33
36
  * Represents a sum of free, locked and opened positions.
34
37
  */
35
38
  get total(): decimal {
36
- return this.asset
37
- .floor(this.available.add(this.unavailable))
38
- .add(this.getEstimatedUnrealizedPnL());
39
+ return this.available.plus(this.unavailable).plus(this.getEstimatedUnrealizedPnL());
39
40
  }
40
41
 
41
42
  /**
@@ -43,61 +44,15 @@ export class Balance implements Component {
43
44
  */
44
45
  readonly position: Record<string, Position> = {};
45
46
 
46
- constructor(public timestamp: number, public readonly asset: Asset) {
47
+ constructor(
48
+ public timestamp: number,
49
+ public readonly asset: Asset,
50
+ public available: decimal = d.Zero,
51
+ public unavailable: decimal = d.Zero
52
+ ) {
47
53
  this.id = asset.id;
48
54
  }
49
55
 
50
- account(amount: decimal) {
51
- if (this.available.add(amount).lessThan(0)) {
52
- throw insufficientFundsError(this.id, amount, this.available);
53
- }
54
-
55
- this.available = this.available.add(amount);
56
- }
57
-
58
- set(free: decimal, locked: decimal) {
59
- this.available = free;
60
- this.unavailable = locked;
61
- this.locker = {};
62
- }
63
-
64
- /**
65
- * Lock specific amount of asset.
66
- * If you place new pending order, you will lock your balance to fund order.
67
- */
68
- lock(id: string, amount: decimal) {
69
- if (this.available.lessThan(amount)) {
70
- throw insufficientFundsError(this.id, amount, this.available);
71
- }
72
-
73
- if (this.locker[id]) {
74
- throw invalidArgumentError(id);
75
- }
76
-
77
- this.locker[id] = amount;
78
- this.available = this.available.minus(amount);
79
- this.unavailable = this.unavailable.plus(amount);
80
- }
81
-
82
- tryUnlock(id: string): boolean {
83
- if (!this.locker[id]) {
84
- return false;
85
- }
86
-
87
- const amount = this.locker[id];
88
-
89
- delete this.locker[id];
90
-
91
- if (this.unavailable < amount) {
92
- throw insufficientFundsError(this.id, amount, this.unavailable);
93
- }
94
-
95
- this.available = this.available.add(amount);
96
- this.unavailable = this.unavailable.minus(amount);
97
-
98
- return true;
99
- }
100
-
101
56
  /**
102
57
  * Returns unrealized profit and loss for all positions backed by this balance.
103
58
  */
@@ -120,4 +75,36 @@ export class Balance implements Component {
120
75
  d.Zero
121
76
  );
122
77
  }
78
+
79
+ tryAddTransientFunding(fundable: Fundable) {
80
+ if (fundable.id in this.transientFunding) {
81
+ return false;
82
+ }
83
+
84
+ this.transientFunding[fundable.id] = fundable;
85
+
86
+ const funding = fundable.getFundingAmount(this);
87
+
88
+ this.available = this.available.minus(funding);
89
+ this.unavailable = this.unavailable.plus(funding);
90
+
91
+ return true;
92
+ }
93
+
94
+ tryRemoveTransientFunding(fundable: Fundable) {
95
+ if (!(fundable.id in this.transientFunding)) {
96
+ return false;
97
+ }
98
+
99
+ const funding = fundable.getFundingAmount(this);
100
+
101
+ this.available = this.available.plus(funding);
102
+ this.unavailable = this.unavailable.minus(funding);
103
+
104
+ return true;
105
+ }
106
+
107
+ clearTransientFunding() {
108
+ this.transientFunding = {};
109
+ }
123
110
  }
@@ -1,7 +1,7 @@
1
- import { d } from '../shared';
2
- import { commissionPercentOf } from './commission';
1
+ import { Commission, commissionPercentOf } from '@lib/domain';
2
+ import { d } from '@lib/shared';
3
3
 
4
- describe('Commission', () => {
4
+ describe(Commission.name, () => {
5
5
  test('should construct a Commission', () => {
6
6
  const sut = commissionPercentOf({
7
7
  maker: d(0.1),
@@ -1,4 +1,4 @@
1
- import { d, decimal } from '../shared';
1
+ import { d, decimal } from '@lib/shared';
2
2
 
3
3
  export class Commission {
4
4
  static readonly Zero = commissionPercentOf({ maker: d.Zero, taker: d.Zero });
@@ -1,6 +1,6 @@
1
- import { timestamp } from '../shared';
1
+ import { timestamp } from '@lib/shared';
2
2
 
3
3
  export interface Component {
4
- id: string;
5
- timestamp: timestamp;
4
+ readonly type: number;
5
+ readonly timestamp: timestamp;
6
6
  }
@@ -1,27 +1,32 @@
1
- import { decimal } from '../shared';
1
+ import { decimal } from '@lib/shared';
2
2
 
3
- export function insufficientFundsError(
4
- assetName: string,
5
- requiredAmount: decimal,
6
- availableAmount: decimal
7
- ) {
8
- return new Error(
9
- `insufficient funds of ${assetName} has: ${availableAmount.toString()} requires: ${requiredAmount.toString()}`
10
- );
3
+ export class InsufficientFundsError extends Error {
4
+ constructor(assetName: string, requiredAmount: decimal, availableAmount: decimal) {
5
+ super(
6
+ `insufficient funds of ${assetName} has: ${availableAmount.toString()} requires: ${requiredAmount.toString()}`
7
+ );
8
+ }
11
9
  }
12
10
 
13
- export function invalidArgumentError(value: any) {
14
- return new Error(`invalid argument: ${value}`);
11
+ export class InvalidArgumentsError extends Error {
12
+ constructor(argName: Record<any, unknown>) {
13
+ super(`invalid arguments: ${argName}`);
14
+ }
15
15
  }
16
16
 
17
- export function invalidAssetSelectorError(selector: string) {
18
- return new Error(`invalid asset selector: ${selector}`);
17
+ export class InvalidAssetSelectorError extends Error {
18
+ constructor(selector: string) {
19
+ super(`invalid asset selector: ${selector}`);
20
+ }
19
21
  }
20
-
21
- export function invalidInstrumentSelectorError(selector: string) {
22
- return new Error(`invalid instrument selector: ${selector}`);
22
+ export class InvalidInstrumentSelectorError extends Error {
23
+ constructor(selector: string) {
24
+ super(`invalid instrument selector: ${selector}`);
25
+ }
23
26
  }
24
27
 
25
- export function adapterMismatchError() {
26
- return new Error('adapters must be the same');
28
+ export class AdapterMismatchError extends Error {
29
+ constructor() {
30
+ super('adapters must be the same');
31
+ }
27
32
  }
@@ -1,21 +1,21 @@
1
- export * from './asset';
2
- export * from './balance';
3
- export * from './balance-operator';
4
- export * from './error';
5
- export * from './ohlc';
6
- export * from './ohlc-operator';
7
- export * from './commission';
8
- export * from './component';
9
- export * from './instrument';
10
- export * from './instrument-operator';
11
- export * from './order';
12
- export * from './order-operator';
13
- export * from './orderbook';
14
- export * from './orderbook-operator';
15
- export * from './position';
16
- export * from './position-operator';
17
- export * from './session';
18
- export * from './session-builder';
19
- export * from './timeframe';
20
- export * from './trade';
21
- export * from './trade-operator';
1
+ export * from '@lib/domain/asset';
2
+ export * from '@lib/domain/balance';
3
+ export * from '@lib/domain/balance-operator';
4
+ export * from '@lib/domain/error';
5
+ export * from '@lib/domain/ohlc';
6
+ export * from '@lib/domain/ohlc-operator';
7
+ export * from '@lib/domain/commission';
8
+ export * from '@lib/domain/component';
9
+ export * from '@lib/domain/instrument';
10
+ export * from '@lib/domain/instrument-operator';
11
+ export * from '@lib/domain/order';
12
+ export * from '@lib/domain/order-operator';
13
+ export * from '@lib/domain/orderbook';
14
+ export * from '@lib/domain/orderbook-operator';
15
+ export * from '@lib/domain/position';
16
+ export * from '@lib/domain/position-operator';
17
+ export * from '@lib/domain/session';
18
+ export * from '@lib/domain/session-builder';
19
+ export * from '@lib/domain/timeframe';
20
+ export * from '@lib/domain/trade';
21
+ export * from '@lib/domain/trade-operator';
@@ -1,13 +1,16 @@
1
1
  import { Subject } from 'rxjs';
2
2
 
3
- import { State } from '../store';
4
- import { Asset } from './asset';
5
- import { Commission } from './commission';
6
- import { Component } from './component';
7
- import { Instrument, instrumentOf } from './instrument';
8
- import { instrument } from './instrument-operator';
3
+ import {
4
+ Asset,
5
+ Commission,
6
+ Component,
7
+ Instrument,
8
+ instrument,
9
+ instrumentOf
10
+ } from '@lib/domain';
11
+ import { State } from '@lib/store';
9
12
 
10
- describe('instrument', () => {
13
+ describe(instrument.name, () => {
11
14
  const state = new State();
12
15
 
13
16
  beforeEach(() => {
@@ -1,22 +1,22 @@
1
1
  import { distinctUntilChanged, filter, map, Observable, startWith } from 'rxjs';
2
2
 
3
- import { State } from '../store';
4
- import { Component } from './component';
5
- import { Instrument, InstrumentSelector } from './instrument';
3
+ import { Component, Instrument, InstrumentSelector } from '@lib/domain';
4
+ import { State } from '@lib/store';
6
5
 
7
6
  export function instrument(selector: InstrumentSelector, state: State) {
8
7
  return (source$: Observable<Component>) =>
9
8
  source$.pipe(
10
9
  startWith(state.universe.instrument.get(selector.id)),
11
- filter(it => it instanceof Instrument && it.id == selector.id),
12
- map(it => it as Instrument)
10
+ filter(it => it !== undefined && it.type === Instrument.type),
11
+ map(it => it as Instrument),
12
+ filter(it => it.id == selector.id)
13
13
  );
14
14
  }
15
15
 
16
16
  export function instruments(state: State) {
17
17
  return (source$: Observable<Component>) =>
18
18
  source$.pipe(
19
- filter(it => it instanceof Instrument),
19
+ filter(it => it.type === Instrument.type),
20
20
  map(() => state.universe.instrument.asReadonlyArray()),
21
21
  startWith(state.universe.instrument.asReadonlyArray()),
22
22
  filter(it => it.length > 0),
@@ -1,9 +1,14 @@
1
- import { d } from '../shared';
2
- import { Asset, assetOf } from './asset';
3
- import { commissionPercentOf } from './commission';
4
- import { Instrument, instrumentOf } from './instrument';
1
+ import {
2
+ Asset,
3
+ assetOf,
4
+ commissionPercentOf,
5
+ Instrument,
6
+ instrumentOf,
7
+ InstrumentSelector
8
+ } from '@lib/domain';
9
+ import { d } from '@lib/shared';
5
10
 
6
- describe('Instrument', () => {
11
+ describe(Instrument.name, () => {
7
12
  test('should construct a instrument', () => {
8
13
  const sut = new Instrument(
9
14
  0,
@@ -24,7 +29,7 @@ describe('Instrument', () => {
24
29
  });
25
30
  });
26
31
 
27
- describe('InstrumentSelector', () => {
32
+ describe(InstrumentSelector.name, () => {
28
33
  test('should construct a instrument selector', () => {
29
34
  const sut = instrumentOf('xyz:abc-def');
30
35
 
@@ -1,7 +1,13 @@
1
- import { Asset, AssetSelector, AssetSelectorSeparator } from './asset';
2
- import { Commission } from './commission';
3
- import { Component } from './component';
4
- import { adapterMismatchError, invalidInstrumentSelectorError } from './error';
1
+ import {
2
+ AdapterMismatchError,
3
+ Asset,
4
+ AssetSelector,
5
+ AssetSelectorSeparator,
6
+ Commission,
7
+ Component,
8
+ InvalidInstrumentSelectorError
9
+ } from '@lib/domain';
10
+ import { hash } from '@lib/shared';
5
11
 
6
12
  export const InstrumentSelectorSeparator = '-';
7
13
 
@@ -22,6 +28,9 @@ export class InstrumentSelector {
22
28
  * Represents trading market which is made up by two trading assets (base and quoted).
23
29
  */
24
30
  export class Instrument extends InstrumentSelector implements Component {
31
+ static type = hash(Instrument.name);
32
+ readonly type = Instrument.type;
33
+
25
34
  readonly cross: Instrument | undefined;
26
35
  leverage: number | undefined = undefined;
27
36
 
@@ -35,7 +44,7 @@ export class Instrument extends InstrumentSelector implements Component {
35
44
  super(base.name, quote.name, base.adapterName);
36
45
 
37
46
  if (base.adapterName != quote.adapterName) {
38
- throw adapterMismatchError();
47
+ throw new AdapterMismatchError();
39
48
  }
40
49
  }
41
50
  }
@@ -43,12 +52,12 @@ export class Instrument extends InstrumentSelector implements Component {
43
52
  export function instrumentOf(selector: string): InstrumentSelector {
44
53
  const [adapterName, asset, ...rest] = selector.split(AssetSelectorSeparator);
45
54
  if (!adapterName || !asset || rest.length) {
46
- throw invalidInstrumentSelectorError(selector);
55
+ throw new InvalidInstrumentSelectorError(selector);
47
56
  }
48
57
 
49
58
  const [baseAssetName, quoteAssetName] = asset.split(InstrumentSelectorSeparator);
50
59
  if (!baseAssetName || !quoteAssetName) {
51
- throw invalidInstrumentSelectorError(selector);
60
+ throw new InvalidInstrumentSelectorError(selector);
52
61
  }
53
62
 
54
63
  return new InstrumentSelector(baseAssetName, quoteAssetName, adapterName);
@@ -1,10 +1,9 @@
1
1
  import { from } from 'rxjs';
2
2
 
3
- import { d } from '../shared';
4
- import { Ohlc } from './ohlc';
5
- import { mergeOhlc, ohlc, ohlcCompleted } from './ohlc-operator';
3
+ import { mergeOhlc, Ohlc, ohlc, ohlcCompleted } from '@lib/domain';
4
+ import { d } from '@lib/shared';
6
5
 
7
- describe('ohlc', () => {
6
+ describe(ohlc.name, () => {
8
7
  test('should aggregate and pipe ohlc updates', done => {
9
8
  const input$ = from([
10
9
  { timestamp: 1, rate: d(1) },
@@ -35,7 +34,7 @@ describe('ohlc', () => {
35
34
  });
36
35
  });
37
36
 
38
- describe('ohlcCompleted', () => {
37
+ describe(ohlcCompleted.name, () => {
39
38
  test('should aggregate and pipe distinct completed ohlc', done => {
40
39
  const input$ = from([
41
40
  { timestamp: 1, rate: d(1) },
@@ -60,7 +59,7 @@ describe('ohlcCompleted', () => {
60
59
  });
61
60
  });
62
61
 
63
- describe('mergeOhlc', () => {
62
+ describe(mergeOhlc.name, () => {
64
63
  test('should pipe and merge ohlc from history', done => {
65
64
  const history$ = from([
66
65
  new Ohlc(1, d(1), d(1.5), d(0.5), d(2)),
@@ -11,9 +11,8 @@ import {
11
11
  switchMap
12
12
  } from 'rxjs';
13
13
 
14
- import { decimal } from '../shared';
15
- import { Ohlc } from './ohlc';
16
- import { tf } from './timeframe';
14
+ import { Ohlc, tf } from '@lib/domain';
15
+ import { decimal } from '@lib/shared';
17
16
 
18
17
  function aggregate(
19
18
  candle: Ohlc | undefined,
@@ -1,5 +1,5 @@
1
- import { d, now } from '../shared';
2
- import { Ohlc } from './ohlc';
1
+ import { Ohlc } from '@lib/domain';
2
+ import { d, now } from '@lib/shared';
3
3
 
4
4
  describe('Ohlc', () => {
5
5
  test('should construct a ohlc', () => {
@@ -1,4 +1,4 @@
1
- import { decimal, timestamp } from '../shared';
1
+ import { decimal, timestamp } from '@lib/shared';
2
2
 
3
3
  export class Ohlc {
4
4
  constructor(
@@ -8,7 +8,7 @@ export class Ohlc {
8
8
  public low: decimal,
9
9
  public close: decimal,
10
10
  public volume?: decimal
11
- ) { }
11
+ ) {}
12
12
 
13
13
  apply(value: decimal) {
14
14
  this.high = decimal.max(this.high, value);
@@ -1,13 +1,17 @@
1
1
  import { BehaviorSubject, map, Subject } from 'rxjs';
2
2
 
3
- import { d } from '../shared';
4
- import { InnerSet, State } from '../store';
5
- import { Asset } from './asset';
6
- import { Commission } from './commission';
7
- import { Component } from './component';
8
- import { Instrument } from './instrument';
9
- import { Order } from './order';
10
- import { order, orders } from './order-operator';
3
+ import {
4
+ Asset,
5
+ Commission,
6
+ Component,
7
+ Instrument,
8
+ Order,
9
+ order,
10
+ orders,
11
+ positions
12
+ } from '@lib/domain';
13
+ import { d } from '@lib/shared';
14
+ import { InnerSet, State } from '@lib/store';
11
15
 
12
16
  const instrument = new Instrument(
13
17
  0,
@@ -17,7 +21,7 @@ const instrument = new Instrument(
17
21
  Commission.Zero
18
22
  );
19
23
 
20
- describe('order', () => {
24
+ describe(order.name, () => {
21
25
  test('should pipe an order', done => {
22
26
  new BehaviorSubject<Component>(new Order(0, '1', instrument, d(-100), 0))
23
27
  .pipe(order(instrument))
@@ -38,7 +42,7 @@ describe('order', () => {
38
42
  });
39
43
  });
40
44
 
41
- describe('positions', () => {
45
+ describe(positions.name, () => {
42
46
  let state: State;
43
47
  let order1: Order, order2: Order, order3: Order;
44
48
 
@@ -1,22 +1,23 @@
1
1
  import { filter, map, Observable, startWith } from 'rxjs';
2
2
 
3
- import { State } from '../store';
4
- import { Component } from './component';
5
- import { InstrumentSelector } from './instrument';
6
- import { Order } from './order';
3
+ import { Component, InstrumentSelector, Order } from '@lib/domain';
4
+ import { State } from '@lib/store';
7
5
 
8
6
  export function order(selector: InstrumentSelector) {
9
7
  return (source$: Observable<Component>) =>
10
8
  source$.pipe(
11
- filter(it => it instanceof Order && it.instrument.id == selector.id),
12
- map(it => it as Order)
9
+ filter(it => it !== undefined && it.type === Order.type),
10
+ map(it => it as Order),
11
+ filter(it => it.instrument.id === selector.id)
13
12
  );
14
13
  }
15
14
 
16
15
  export function orders(selector: InstrumentSelector, state: State) {
17
16
  return (source$: Observable<Component>) =>
18
17
  source$.pipe(
19
- filter(it => it instanceof Order && it.instrument.id == selector.id),
18
+ filter(it => it.type === Order.type),
19
+ map(it => it as Order),
20
+ filter(it => it.instrument.id === selector.id),
20
21
  map(() => state.order.get(selector.id)?.asReadonlyArray() ?? []),
21
22
  startWith(state.order.get(selector.id)?.asReadonlyArray() ?? [])
22
23
  );
@@ -1,10 +1,7 @@
1
- import { d } from '../shared';
2
- import { Asset } from './asset';
3
- import { Commission } from './commission';
4
- import { Instrument } from './instrument';
5
- import { Order } from './order';
1
+ import { Asset, Commission, Instrument, Order } from '@lib/domain';
2
+ import { d } from '@lib/shared';
6
3
 
7
- describe('Order', () => {
4
+ describe(Order.name, () => {
8
5
  const instrument = new Instrument(
9
6
  0,
10
7
  new Asset('abc', 'xyz', 4),
@@ -1,8 +1,11 @@
1
- import { d, decimal } from '../shared';
2
- import { Balance } from './balance';
3
- import { Component } from './component';
4
- import { invalidArgumentError } from './error';
5
- import { Instrument } from './instrument';
1
+ import {
2
+ Balance,
3
+ Component,
4
+ Fundable,
5
+ Instrument,
6
+ InvalidArgumentsError
7
+ } from '@lib/domain';
8
+ import { d, decimal, hash } from '@lib/shared';
6
9
 
7
10
  export type OrderState =
8
11
  | 'NEW'
@@ -12,7 +15,10 @@ export type OrderState =
12
15
  | 'CANCELED'
13
16
  | 'REJECTED';
14
17
 
15
- export class Order implements Component {
18
+ export class Order implements Fundable, Component {
19
+ static type = hash(Order.name);
20
+ readonly type = Order.type;
21
+
16
22
  state: OrderState = 'NEW';
17
23
  quantityExecuted = d.Zero;
18
24
  averageExecutionRate?: decimal;
@@ -28,41 +34,32 @@ export class Order implements Component {
28
34
  readonly stopRate?: decimal
29
35
  ) {
30
36
  if (!quantity || Number.isNaN(quantity)) {
31
- throw invalidArgumentError(quantity);
37
+ throw new InvalidArgumentsError({ quantity });
32
38
  }
33
39
 
34
40
  if (rate && rate.lessThanOrEqualTo(0)) {
35
- throw invalidArgumentError(rate);
41
+ throw new InvalidArgumentsError({ rate });
36
42
  }
37
43
  }
38
44
 
39
- calculateBalanceToLock(
40
- base: Balance,
41
- quote: Balance
42
- ): { base?: decimal; quote?: decimal } {
43
- const qty = this.quantity.abs();
45
+ getFundingAmount(balance: Balance): decimal {
46
+ const quantityLeft = this.quantity.abs().minus(this.quantityExecuted);
44
47
 
45
- if (this.quantity.greaterThan(0)) {
48
+ if (
49
+ this.instrument.quote.id === balance.asset.id &&
50
+ this.quantity.greaterThan(d.Zero)
51
+ ) {
46
52
  if (this.rate) {
47
- return {
48
- base: d.Zero,
49
- quote: quote.asset.ceil(this.rate.mul(qty))
50
- };
51
- } else {
52
- return {
53
- base: d.Zero,
54
- quote: quote.free
55
- };
53
+ return quantityLeft.mul(this.rate).abs();
56
54
  }
55
+
56
+ return balance.free;
57
57
  }
58
58
 
59
- if (this.quantity.lessThan(0)) {
60
- return {
61
- base: qty,
62
- quote: d.Zero
63
- };
59
+ if (this.instrument.base.id === balance.asset.id && this.quantity.lessThan(d.Zero)) {
60
+ return quantityLeft;
64
61
  }
65
62
 
66
- return {};
63
+ return d.Zero;
67
64
  }
68
65
  }