@quantform/core 0.5.15 → 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 (282) hide show
  1. package/dist/adapter/adapter-aggregate.d.ts +5 -4
  2. package/dist/adapter/adapter-aggregate.js +4 -4
  3. package/dist/adapter/adapter-aggregate.js.map +1 -1
  4. package/dist/adapter/adapter.d.ts +4 -15
  5. package/dist/adapter/adapter.js.map +1 -1
  6. package/dist/adapter/backtester/backtester-adapter.d.ts +3 -3
  7. package/dist/adapter/backtester/backtester-adapter.js +4 -4
  8. package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
  9. package/dist/adapter/backtester/backtester-adapter.spec.js +7 -6
  10. package/dist/adapter/backtester/backtester-adapter.spec.js.map +1 -1
  11. package/dist/adapter/backtester/backtester-cursor.d.ts +4 -4
  12. package/dist/adapter/backtester/backtester-cursor.js.map +1 -1
  13. package/dist/adapter/backtester/backtester-cursor.spec.js +19 -17
  14. package/dist/adapter/backtester/backtester-cursor.spec.js.map +1 -1
  15. package/dist/adapter/backtester/backtester-streamer.d.ts +0 -1
  16. package/dist/adapter/backtester/backtester-streamer.js +4 -14
  17. package/dist/adapter/backtester/backtester-streamer.js.map +1 -1
  18. package/dist/adapter/backtester/backtester-streamer.spec.js +12 -11
  19. package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -1
  20. package/dist/adapter/paper/engine/paper-engine.js +20 -19
  21. package/dist/adapter/paper/engine/paper-engine.js.map +1 -1
  22. package/dist/adapter/paper/engine/paper-engine.spec.js +19 -19
  23. package/dist/adapter/paper/engine/paper-engine.spec.js.map +1 -1
  24. package/dist/adapter/paper/paper-adapter.d.ts +4 -3
  25. package/dist/adapter/paper/paper-adapter.js +8 -7
  26. package/dist/adapter/paper/paper-adapter.js.map +1 -1
  27. package/dist/adapter/paper/paper-adapter.spec.js +5 -4
  28. package/dist/adapter/paper/paper-adapter.spec.js.map +1 -1
  29. package/dist/cli/pull.js +5 -10
  30. package/dist/cli/pull.js.map +1 -1
  31. package/dist/domain/asset.d.ts +4 -4
  32. package/dist/domain/asset.js +4 -7
  33. package/dist/domain/asset.js.map +1 -1
  34. package/dist/domain/asset.spec.js +4 -4
  35. package/dist/domain/asset.spec.js.map +1 -1
  36. package/dist/domain/balance.d.ts +9 -9
  37. package/dist/domain/balance.js +16 -15
  38. package/dist/domain/balance.js.map +1 -1
  39. package/dist/domain/balance.spec.js +37 -36
  40. package/dist/domain/balance.spec.js.map +1 -1
  41. package/dist/domain/candle.d.ts +8 -8
  42. package/dist/domain/candle.js +3 -2
  43. package/dist/domain/candle.js.map +1 -1
  44. package/dist/domain/candle.operator.d.ts +3 -2
  45. package/dist/domain/candle.operator.js.map +1 -1
  46. package/dist/domain/candle.operator.spec.js +43 -42
  47. package/dist/domain/candle.operator.spec.js.map +1 -1
  48. package/dist/domain/candle.spec.js +11 -11
  49. package/dist/domain/candle.spec.js.map +1 -1
  50. package/dist/domain/commission.d.ts +10 -9
  51. package/dist/domain/commission.js +5 -5
  52. package/dist/domain/commission.js.map +1 -1
  53. package/dist/domain/commission.spec.js +13 -12
  54. package/dist/domain/commission.spec.js.map +1 -1
  55. package/dist/domain/error.d.ts +2 -1
  56. package/dist/domain/error.js +1 -1
  57. package/dist/domain/error.js.map +1 -1
  58. package/dist/domain/order.d.ts +13 -13
  59. package/dist/domain/order.js +10 -9
  60. package/dist/domain/order.js.map +1 -1
  61. package/dist/domain/order.operator.spec.js +6 -5
  62. package/dist/domain/order.operator.spec.js.map +1 -1
  63. package/dist/domain/order.spec.js +11 -10
  64. package/dist/domain/order.spec.js.map +1 -1
  65. package/dist/domain/orderbook.d.ts +18 -6
  66. package/dist/domain/orderbook.js +5 -4
  67. package/dist/domain/orderbook.js.map +1 -1
  68. package/dist/domain/position.d.ts +7 -7
  69. package/dist/domain/position.js +2 -2
  70. package/dist/domain/position.js.map +1 -1
  71. package/dist/domain/position.operator.d.ts +3 -2
  72. package/dist/domain/position.operator.js +3 -3
  73. package/dist/domain/position.operator.js.map +1 -1
  74. package/dist/domain/position.operator.spec.js +4 -3
  75. package/dist/domain/position.operator.spec.js.map +1 -1
  76. package/dist/domain/position.spec.js +10 -9
  77. package/dist/domain/position.spec.js.map +1 -1
  78. package/dist/domain/session.js +1 -1
  79. package/dist/domain/session.js.map +1 -1
  80. package/dist/domain/session.spec.js +1 -1
  81. package/dist/domain/session.spec.js.map +1 -1
  82. package/dist/domain/trade.d.ts +3 -3
  83. package/dist/indicator/atr.d.ts +2 -1
  84. package/dist/indicator/atr.js +3 -3
  85. package/dist/indicator/atr.js.map +1 -1
  86. package/dist/indicator/cross.d.ts +3 -2
  87. package/dist/indicator/cross.js +13 -13
  88. package/dist/indicator/cross.js.map +1 -1
  89. package/dist/indicator/cross.spec.js +22 -21
  90. package/dist/indicator/cross.spec.js.map +1 -1
  91. package/dist/indicator/donchian.d.ts +3 -2
  92. package/dist/indicator/donchian.js.map +1 -1
  93. package/dist/indicator/drawdown.d.ts +2 -1
  94. package/dist/indicator/drawdown.js +3 -2
  95. package/dist/indicator/drawdown.js.map +1 -1
  96. package/dist/indicator/ema.d.ts +2 -1
  97. package/dist/indicator/ema.js +3 -2
  98. package/dist/indicator/ema.js.map +1 -1
  99. package/dist/indicator/ema.spec.js +3 -2
  100. package/dist/indicator/ema.spec.js.map +1 -1
  101. package/dist/indicator/envelope.d.ts +4 -3
  102. package/dist/indicator/envelope.js +4 -4
  103. package/dist/indicator/envelope.js.map +1 -1
  104. package/dist/indicator/index.d.ts +1 -1
  105. package/dist/indicator/index.js +1 -1
  106. package/dist/indicator/index.js.map +1 -1
  107. package/dist/indicator/macd.d.ts +2 -1
  108. package/dist/indicator/macd.js +1 -1
  109. package/dist/indicator/macd.js.map +1 -1
  110. package/dist/indicator/min-max.d.ts +4 -3
  111. package/dist/indicator/min-max.js +5 -4
  112. package/dist/indicator/min-max.js.map +1 -1
  113. package/dist/indicator/rma.d.ts +2 -1
  114. package/dist/indicator/rma.js +3 -2
  115. package/dist/indicator/rma.js.map +1 -1
  116. package/dist/indicator/sma.d.ts +2 -1
  117. package/dist/indicator/sma.js +4 -6
  118. package/dist/indicator/sma.js.map +1 -1
  119. package/dist/indicator/sma.spec.js +3 -2
  120. package/dist/indicator/sma.spec.js.map +1 -1
  121. package/dist/indicator/swma.d.ts +2 -1
  122. package/dist/indicator/swma.js +5 -1
  123. package/dist/indicator/swma.js.map +1 -1
  124. package/dist/indicator/tma.d.ts +2 -1
  125. package/dist/indicator/tma.js.map +1 -1
  126. package/dist/indicator/tma.spec.js +3 -2
  127. package/dist/indicator/tma.spec.js.map +1 -1
  128. package/dist/indicator/trailing.d.ts +8 -7
  129. package/dist/indicator/trailing.js +12 -11
  130. package/dist/indicator/trailing.js.map +1 -1
  131. package/dist/indicator/trailing.spec.js +15 -14
  132. package/dist/indicator/trailing.spec.js.map +1 -1
  133. package/dist/indicator/true-range.d.ts +4 -0
  134. package/dist/indicator/true-range.js +20 -0
  135. package/dist/indicator/true-range.js.map +1 -0
  136. package/dist/indicator/{truerange.spec.d.ts → true-range.spec.d.ts} +0 -0
  137. package/dist/indicator/true-range.spec.js +28 -0
  138. package/dist/indicator/true-range.spec.js.map +1 -0
  139. package/dist/indicator/window.d.ts +1 -1
  140. package/dist/indicator/window.js +1 -1
  141. package/dist/indicator/window.js.map +1 -1
  142. package/dist/indicator/wma.d.ts +2 -1
  143. package/dist/indicator/wma.js +6 -5
  144. package/dist/indicator/wma.js.map +1 -1
  145. package/dist/indicator/wma.spec.js +3 -2
  146. package/dist/indicator/wma.spec.js.map +1 -1
  147. package/dist/shared/collections.d.ts +16 -0
  148. package/dist/shared/collections.js +83 -1
  149. package/dist/shared/collections.js.map +1 -1
  150. package/dist/shared/collections.spec.d.ts +1 -0
  151. package/dist/shared/collections.spec.js +28 -0
  152. package/dist/shared/collections.spec.js.map +1 -0
  153. package/dist/shared/decimals.d.ts +15 -6
  154. package/dist/shared/decimals.js +21 -34
  155. package/dist/shared/decimals.js.map +1 -1
  156. package/dist/shared/decimals.spec.js +17 -22
  157. package/dist/shared/decimals.spec.js.map +1 -1
  158. package/dist/shared/index.d.ts +1 -0
  159. package/dist/shared/index.js +1 -0
  160. package/dist/shared/index.js.map +1 -1
  161. package/dist/shared/pipe.d.ts +4 -0
  162. package/dist/shared/pipe.js +9 -0
  163. package/dist/shared/pipe.js.map +1 -0
  164. package/dist/storage/feed.d.ts +8 -4
  165. package/dist/storage/feed.js +55 -18
  166. package/dist/storage/feed.js.map +1 -1
  167. package/dist/store/store-balance.event.d.ts +6 -6
  168. package/dist/store/store-balance.event.js +2 -2
  169. package/dist/store/store-balance.event.js.map +1 -1
  170. package/dist/store/store-balance.event.spec.js +4 -4
  171. package/dist/store/store-balance.event.spec.js.map +1 -1
  172. package/dist/store/store-instrument.event.js.map +1 -1
  173. package/dist/store/store-instrument.event.spec.js +1 -1
  174. package/dist/store/store-instrument.event.spec.js.map +1 -1
  175. package/dist/store/store-order.event.d.ts +3 -3
  176. package/dist/store/store-order.event.js.map +1 -1
  177. package/dist/store/store-order.event.spec.js +1 -1
  178. package/dist/store/store-order.event.spec.js.map +1 -1
  179. package/dist/store/store-orderbook.event.d.ts +4 -6
  180. package/dist/store/store-orderbook.event.js +13 -13
  181. package/dist/store/store-orderbook.event.js.map +1 -1
  182. package/dist/store/store-orderbook.event.spec.d.ts +1 -0
  183. package/dist/store/store-orderbook.event.spec.js +28 -0
  184. package/dist/store/store-orderbook.event.spec.js.map +1 -0
  185. package/dist/store/store-position.event.d.ts +4 -4
  186. package/dist/store/store-position.event.js +23 -11
  187. package/dist/store/store-position.event.js.map +1 -1
  188. package/dist/store/store-trade.event.d.ts +4 -4
  189. package/dist/store/store-trade.event.js +2 -2
  190. package/dist/store/store-trade.event.js.map +1 -1
  191. package/dist/store/store-trade.event.spec.js +8 -8
  192. package/dist/store/store-trade.event.spec.js.map +1 -1
  193. package/dist/store/store.spec.js +15 -15
  194. package/dist/store/store.spec.js.map +1 -1
  195. package/dist/tsconfig.tsbuildinfo +1 -1
  196. package/jestconfig.json +1 -0
  197. package/package.json +3 -1
  198. package/src/adapter/adapter-aggregate.ts +16 -7
  199. package/src/adapter/adapter.ts +15 -18
  200. package/src/adapter/backtester/backtester-adapter.spec.ts +18 -9
  201. package/src/adapter/backtester/backtester-adapter.ts +14 -5
  202. package/src/adapter/backtester/backtester-cursor.spec.ts +20 -18
  203. package/src/adapter/backtester/backtester-cursor.ts +5 -5
  204. package/src/adapter/backtester/backtester-streamer.spec.ts +14 -13
  205. package/src/adapter/backtester/backtester-streamer.ts +5 -22
  206. package/src/adapter/paper/engine/paper-engine.spec.ts +30 -23
  207. package/src/adapter/paper/engine/paper-engine.ts +28 -21
  208. package/src/adapter/paper/paper-adapter.spec.ts +15 -6
  209. package/src/adapter/paper/paper-adapter.ts +20 -8
  210. package/src/cli/pull.ts +6 -5
  211. package/src/domain/asset.spec.ts +4 -4
  212. package/src/domain/asset.ts +7 -14
  213. package/src/domain/balance.spec.ts +37 -36
  214. package/src/domain/balance.ts +29 -29
  215. package/src/domain/candle.operator.spec.ts +43 -42
  216. package/src/domain/candle.operator.ts +4 -3
  217. package/src/domain/candle.spec.ts +13 -12
  218. package/src/domain/candle.ts +9 -9
  219. package/src/domain/commission.spec.ts +13 -12
  220. package/src/domain/commission.ts +13 -11
  221. package/src/domain/error.ts +5 -3
  222. package/src/domain/order.operator.spec.ts +6 -5
  223. package/src/domain/order.spec.ts +11 -10
  224. package/src/domain/order.ts +25 -22
  225. package/src/domain/orderbook.ts +14 -8
  226. package/src/domain/position.operator.spec.ts +5 -4
  227. package/src/domain/position.operator.ts +8 -5
  228. package/src/domain/position.spec.ts +10 -9
  229. package/src/domain/position.ts +8 -8
  230. package/src/domain/session.spec.ts +3 -3
  231. package/src/domain/session.ts +1 -3
  232. package/src/domain/trade.ts +3 -3
  233. package/src/indicator/atr.ts +6 -5
  234. package/src/indicator/cross.spec.ts +32 -47
  235. package/src/indicator/cross.ts +18 -10
  236. package/src/indicator/donchian.ts +5 -4
  237. package/src/indicator/drawdown.ts +7 -5
  238. package/src/indicator/ema.spec.ts +4 -3
  239. package/src/indicator/ema.ts +7 -6
  240. package/src/indicator/envelope.ts +11 -6
  241. package/src/indicator/index.ts +1 -1
  242. package/src/indicator/macd.ts +5 -4
  243. package/src/indicator/min-max.ts +10 -7
  244. package/src/indicator/rma.ts +7 -6
  245. package/src/indicator/sma.spec.ts +4 -3
  246. package/src/indicator/sma.ts +9 -8
  247. package/src/indicator/swma.ts +8 -4
  248. package/src/indicator/tma.spec.ts +4 -3
  249. package/src/indicator/tma.ts +4 -3
  250. package/src/indicator/trailing.spec.ts +29 -16
  251. package/src/indicator/trailing.ts +22 -16
  252. package/src/indicator/true-range.spec.ts +32 -0
  253. package/src/indicator/true-range.ts +32 -0
  254. package/src/indicator/window.ts +3 -3
  255. package/src/indicator/wma.spec.ts +4 -3
  256. package/src/indicator/wma.ts +8 -7
  257. package/src/shared/collections.spec.ts +30 -0
  258. package/src/shared/collections.ts +106 -0
  259. package/src/shared/decimals.spec.ts +18 -24
  260. package/src/shared/decimals.ts +22 -55
  261. package/src/shared/index.ts +1 -0
  262. package/src/shared/pipe.ts +12 -0
  263. package/src/storage/feed.ts +89 -34
  264. package/src/store/store-balance.event.spec.ts +5 -5
  265. package/src/store/store-balance.event.ts +6 -6
  266. package/src/store/store-instrument.event.spec.ts +2 -2
  267. package/src/store/store-instrument.event.ts +2 -2
  268. package/src/store/store-order.event.spec.ts +2 -2
  269. package/src/store/store-order.event.ts +2 -2
  270. package/src/store/store-orderbook.event.spec.ts +37 -0
  271. package/src/store/store-orderbook.event.ts +13 -13
  272. package/src/store/store-position.event.ts +27 -15
  273. package/src/store/store-trade.event.spec.ts +9 -9
  274. package/src/store/store-trade.event.ts +5 -5
  275. package/src/store/store.spec.ts +16 -16
  276. package/dist/indicator/truerange.d.ts +0 -3
  277. package/dist/indicator/truerange.js +0 -19
  278. package/dist/indicator/truerange.js.map +0 -1
  279. package/dist/indicator/truerange.spec.js +0 -28
  280. package/dist/indicator/truerange.spec.js.map +0 -1
  281. package/src/indicator/truerange.spec.ts +0 -32
  282. package/src/indicator/truerange.ts +0 -31
@@ -1,23 +1,25 @@
1
+ import { decimal } from '../shared';
2
+
1
3
  export class Commission {
2
- constructor(readonly makerRate: number, readonly takerRate: number) {}
4
+ constructor(readonly makerRate: decimal, readonly takerRate: decimal) {}
3
5
 
4
- calculateMakerFee(value: number) {
5
- return value * this.makerRate;
6
+ calculateMakerFee(value: decimal) {
7
+ return value.mul(this.makerRate);
6
8
  }
7
9
 
8
- calculateTakerFee(value: number) {
9
- return value * this.takerRate;
10
+ calculateTakerFee(value: decimal) {
11
+ return value.mul(this.takerRate);
10
12
  }
11
13
 
12
- applyMakerFee(value: number): number {
13
- return value - this.calculateMakerFee(value);
14
+ applyMakerFee(value: decimal): decimal {
15
+ return value.minus(this.calculateMakerFee(value));
14
16
  }
15
17
 
16
- applyTakerFee(value: number): number {
17
- return value - this.calculateTakerFee(value);
18
+ applyTakerFee(value: decimal): decimal {
19
+ return value.minus(this.calculateTakerFee(value));
18
20
  }
19
21
  }
20
22
 
21
- export function commissionPercentOf(fees: { maker: number; taker: number }) {
22
- return new Commission(fees.maker / 100.0, fees.taker / 100.0);
23
+ export function commissionPercentOf(fees: { maker: decimal; taker: decimal }) {
24
+ return new Commission(fees.maker.div(100.0), fees.taker.div(100.0));
23
25
  }
@@ -1,10 +1,12 @@
1
+ import { decimal } from '../shared';
2
+
1
3
  export function insufficientFundsError(
2
4
  assetName: string,
3
- requiredAmount: number,
4
- availableAmount: number
5
+ requiredAmount: decimal,
6
+ availableAmount: decimal
5
7
  ) {
6
8
  return new Error(
7
- `insufficient funds of ${assetName} has: ${availableAmount} requires: ${requiredAmount}`
9
+ `insufficient funds of ${assetName} has: ${availableAmount.toString()} requires: ${requiredAmount.toString()}`
8
10
  );
9
11
  }
10
12
 
@@ -1,5 +1,6 @@
1
1
  import { BehaviorSubject, map, Subject } from 'rxjs';
2
2
 
3
+ import { d } from '../shared';
3
4
  import { InnerSet, State } from '../store';
4
5
  import { Asset } from './asset';
5
6
  import { Component } from './component';
@@ -15,12 +16,12 @@ const instrument = new Instrument(
15
16
 
16
17
  describe('order', () => {
17
18
  test('should pipe an order', done => {
18
- new BehaviorSubject<Component>(Order.market(instrument, -100))
19
+ new BehaviorSubject<Component>(Order.market(instrument, d(-100)))
19
20
  .pipe(order(instrument))
20
21
  .subscribe({
21
22
  next: it => {
22
23
  expect(it.instrument).toEqual(instrument);
23
- expect(it.quantity).toEqual(-100);
24
+ expect(it.quantity).toEqual(d(-100));
24
25
  done();
25
26
  }
26
27
  });
@@ -41,9 +42,9 @@ describe('positions', () => {
41
42
  beforeEach(() => {
42
43
  state = new State();
43
44
 
44
- order1 = Order.market(instrument, -100);
45
- order2 = Order.limit(instrument, 100, 10);
46
- order3 = Order.market(instrument, 100);
45
+ order1 = Order.market(instrument, d(-100));
46
+ order2 = Order.limit(instrument, d(100), d(10));
47
+ order3 = Order.market(instrument, d(100));
47
48
 
48
49
  state.order.upsert(new InnerSet<Order>(instrument.id, [order1, order2, order3]));
49
50
  });
@@ -1,3 +1,4 @@
1
+ import { d } from '../shared';
1
2
  import { Asset } from './asset';
2
3
  import { Instrument } from './instrument';
3
4
  import { Order } from './order';
@@ -10,34 +11,34 @@ describe('Order', () => {
10
11
  );
11
12
 
12
13
  test('should construct a market buy order', () => {
13
- const sut = Order.market(instrument, 100);
14
+ const sut = Order.market(instrument, d(100));
14
15
 
15
- expect(sut.quantity).toEqual(100);
16
+ expect(sut.quantity).toEqual(d(100));
16
17
  expect(sut.rate).toEqual(undefined);
17
18
  expect(sut.type).toEqual('MARKET');
18
19
  });
19
20
 
20
21
  test('should construct a market sell order', () => {
21
- const sut = Order.market(instrument, -100);
22
+ const sut = Order.market(instrument, d(-100));
22
23
 
23
- expect(sut.quantity).toEqual(-100);
24
+ expect(sut.quantity).toEqual(d(-100));
24
25
  expect(sut.rate).toEqual(undefined);
25
26
  expect(sut.type).toEqual('MARKET');
26
27
  });
27
28
 
28
29
  test('should construct a limit buy order', () => {
29
- const sut = Order.limit(instrument, 100, 2000);
30
+ const sut = Order.limit(instrument, d(100), d(2000));
30
31
 
31
- expect(sut.quantity).toEqual(100);
32
- expect(sut.rate).toEqual(2000);
32
+ expect(sut.quantity).toEqual(d(100));
33
+ expect(sut.rate).toEqual(d(2000));
33
34
  expect(sut.type).toEqual('LIMIT');
34
35
  });
35
36
 
36
37
  test('should construct a limit sell order', () => {
37
- const sut = Order.limit(instrument, -100, 2000);
38
+ const sut = Order.limit(instrument, d(-100), d(2000));
38
39
 
39
- expect(sut.quantity).toEqual(-100);
40
- expect(sut.rate).toEqual(2000);
40
+ expect(sut.quantity).toEqual(d(-100));
41
+ expect(sut.rate).toEqual(d(2000));
41
42
  expect(sut.type).toEqual('LIMIT');
42
43
  });
43
44
  });
@@ -1,6 +1,6 @@
1
1
  import { v4 } from 'uuid';
2
2
 
3
- import { timestamp } from '../shared';
3
+ import { d, decimal, timestamp } from '../shared';
4
4
  import { Balance } from './balance';
5
5
  import { Component } from './component';
6
6
  import { invalidArgumentError } from './error';
@@ -22,31 +22,31 @@ export class Order implements Component {
22
22
  externalId: string;
23
23
  state: OrderState = 'NEW';
24
24
 
25
- quantityExecuted = 0;
26
- averageExecutionRate: number;
25
+ quantityExecuted = d.Zero;
26
+ averageExecutionRate: decimal;
27
27
  createdAt: timestamp;
28
28
 
29
- static market(instrument: InstrumentSelector, quantity: number): Order {
29
+ static market(instrument: InstrumentSelector, quantity: decimal): Order {
30
30
  return new Order(instrument, 'MARKET', quantity);
31
31
  }
32
32
 
33
- static limit(instrument: InstrumentSelector, quantity: number, rate: number): Order {
33
+ static limit(instrument: InstrumentSelector, quantity: decimal, rate: decimal): Order {
34
34
  return new Order(instrument, 'LIMIT', quantity, rate);
35
35
  }
36
36
 
37
37
  static stopMarket(
38
38
  instrument: InstrumentSelector,
39
- quantity: number,
40
- stopRate: number
39
+ quantity: decimal,
40
+ stopRate: decimal
41
41
  ): Order {
42
42
  return new Order(instrument, 'STOP-MARKET', quantity, undefined, stopRate);
43
43
  }
44
44
 
45
45
  static stopLimit(
46
46
  instrument: InstrumentSelector,
47
- quantity: number,
48
- rate: number,
49
- stopRate: number
47
+ quantity: decimal,
48
+ rate: decimal,
49
+ stopRate: decimal
50
50
  ): Order {
51
51
  return new Order(instrument, 'STOP-LIMIT', quantity, rate, stopRate);
52
52
  }
@@ -54,15 +54,15 @@ export class Order implements Component {
54
54
  constructor(
55
55
  readonly instrument: InstrumentSelector,
56
56
  readonly type: OrderType,
57
- readonly quantity: number,
58
- readonly rate?: number,
59
- readonly stopRate?: number
57
+ readonly quantity: decimal,
58
+ readonly rate?: decimal,
59
+ readonly stopRate?: decimal
60
60
  ) {
61
61
  if (!quantity || Number.isNaN(quantity)) {
62
62
  throw invalidArgumentError(quantity);
63
63
  }
64
64
 
65
- if (rate && (Number.isNaN(rate) || rate <= 0)) {
65
+ if (rate && rate.lessThanOrEqualTo(0)) {
66
66
  throw invalidArgumentError(rate);
67
67
  }
68
68
  }
@@ -71,29 +71,32 @@ export class Order implements Component {
71
71
  return this.id;
72
72
  }
73
73
 
74
- calculateBalanceToLock(base: Balance, quote: Balance): { base: number; quote: number } {
75
- const qty = Math.abs(this.quantity);
74
+ calculateBalanceToLock(
75
+ base: Balance,
76
+ quote: Balance
77
+ ): { base: decimal; quote: decimal } {
78
+ const qty = this.quantity.abs();
76
79
 
77
- if (this.quantity > 0) {
80
+ if (this.quantity.greaterThan(0)) {
78
81
  switch (this.type) {
79
82
  case 'MARKET':
80
83
  return {
81
- base: 0,
84
+ base: d.Zero,
82
85
  quote: quote.free
83
86
  };
84
87
 
85
88
  case 'LIMIT':
86
89
  return {
87
- base: 0,
88
- quote: quote.asset.ceil(this.rate * qty)
90
+ base: d.Zero,
91
+ quote: quote.asset.ceil(this.rate.mul(qty))
89
92
  };
90
93
  }
91
94
  }
92
95
 
93
- if (this.quantity < 0) {
96
+ if (this.quantity.lessThan(0)) {
94
97
  return {
95
98
  base: qty,
96
- quote: 0
99
+ quote: d.Zero
97
100
  };
98
101
  }
99
102
  }
@@ -1,7 +1,18 @@
1
1
  import { Instrument } from '../domain';
2
- import { timestamp } from '../shared';
2
+ import { decimal, timestamp } from '../shared';
3
3
  import { Component } from './component';
4
4
 
5
+ export interface Liquidity {
6
+ rate: decimal;
7
+ quantity: decimal;
8
+ next: this;
9
+ }
10
+
11
+ export const LiquidityAskComparer = (lhs: { rate: decimal }, rhs: { rate: decimal }) =>
12
+ lhs.rate.comparedTo(rhs.rate);
13
+ export const LiquidityBidComparer = (lhs: { rate: decimal }, rhs: { rate: decimal }) =>
14
+ rhs.rate.comparedTo(lhs.rate);
15
+
5
16
  /**
6
17
  * Provides an access to pending buy and sell orders on the specific market.
7
18
  */
@@ -9,14 +20,9 @@ export class Orderbook implements Component {
9
20
  id: string;
10
21
  kind = 'orderbook';
11
22
  timestamp: timestamp;
12
- bestAskRate: number;
13
- bestAskQuantity: number;
14
- bestBidRate: number;
15
- bestBidQuantity: number;
16
23
 
17
- get midRate(): number {
18
- return this.instrument.quote.fixed((this.bestAskRate + this.bestBidRate) / 2);
19
- }
24
+ asks: Liquidity;
25
+ bids: Liquidity;
20
26
 
21
27
  constructor(public readonly instrument: Instrument) {
22
28
  this.id = instrument.id;
@@ -1,5 +1,6 @@
1
- import { BehaviorSubject, map, Subject } from 'rxjs';
1
+ import { BehaviorSubject, Subject } from 'rxjs';
2
2
 
3
+ import { d } from '../shared';
3
4
  import { State } from '../store';
4
5
  import { Asset } from './asset';
5
6
  import { Balance } from './balance';
@@ -16,7 +17,7 @@ const instrument = new Instrument(
16
17
 
17
18
  describe('position', () => {
18
19
  test('should pipe a position', done => {
19
- new BehaviorSubject<Component>(new Position('1', instrument, 'CROSS', 10, 2, 3))
20
+ new BehaviorSubject<Component>(new Position('1', instrument, 'CROSS', d(10), d(2), 3))
20
21
  .pipe(position(instrument))
21
22
  .subscribe({
22
23
  next: it => {
@@ -37,8 +38,8 @@ describe('position', () => {
37
38
  describe('positions', () => {
38
39
  const state = new State();
39
40
  const balance = new Balance(instrument.quote);
40
- const position1 = new Position('1', instrument, 'CROSS', 10, 2, 3);
41
- const position2 = new Position('2', instrument, 'CROSS', 20, 2, 3);
41
+ const position1 = new Position('1', instrument, 'CROSS', d(10), d(2), 3);
42
+ const position2 = new Position('2', instrument, 'CROSS', d(20), d(2), 3);
42
43
 
43
44
  beforeEach(() => {
44
45
  state.balance.upsert(balance);
@@ -1,6 +1,6 @@
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
5
  import { InstrumentSelector } from './instrument';
6
6
  import { Position } from './position';
@@ -30,12 +30,15 @@ export function positions(selector: InstrumentSelector, state: State) {
30
30
  export function flatten() {
31
31
  return function (
32
32
  source: Observable<Position[]>
33
- ): Observable<{ size: number; rate: number }> {
33
+ ): Observable<{ size: decimal; rate: decimal }> {
34
34
  return source.pipe(
35
35
  map(it => {
36
36
  if (it.length > 1) {
37
37
  return {
38
- size: it.reduce((aggregate, position) => aggregate + position.size, 0),
38
+ size: it.reduce(
39
+ (aggregate, position) => aggregate.add(position.size),
40
+ d.Zero
41
+ ),
39
42
  rate: weightedMean(
40
43
  it.map(x => x.averageExecutionRate),
41
44
  it.map(x => x.size)
@@ -51,8 +54,8 @@ export function flatten() {
51
54
  }
52
55
 
53
56
  return {
54
- size: 0,
55
- rate: 0
57
+ size: d.Zero,
58
+ rate: d.Zero
56
59
  };
57
60
  }),
58
61
  share()
@@ -1,3 +1,4 @@
1
+ import { d } from '../shared';
1
2
  import { Asset } from './asset';
2
3
  import { Instrument } from './instrument';
3
4
  import { Position } from './position';
@@ -10,30 +11,30 @@ describe('Position', () => {
10
11
  );
11
12
 
12
13
  test('should construct a position', () => {
13
- const sut = new Position('1', instrument, 'CROSS', 10, 2, 3);
14
+ const sut = new Position('1', instrument, 'CROSS', d(10), d(2), 3);
14
15
 
15
16
  expect(sut.id).toEqual('1');
16
17
  expect(sut.mode).toEqual('CROSS');
17
- expect(sut.averageExecutionRate).toEqual(10);
18
- expect(sut.size).toEqual(2);
18
+ expect(sut.averageExecutionRate).toEqual(d(10));
19
+ expect(sut.size).toEqual(d(2));
19
20
  expect(sut.leverage).toEqual(3);
20
21
  expect(sut.estimatedUnrealizedPnL).toEqual(undefined);
21
22
  expect(sut.id).toEqual('1');
22
23
  });
23
24
 
24
25
  test('should calculate correct margin', () => {
25
- const sut = new Position('1', instrument, 'CROSS', 2511.81, 10.31, 20);
26
+ const sut = new Position('1', instrument, 'CROSS', d(2511.81), d(10.31), 20);
26
27
 
27
- expect(sut.margin).toEqual(0.5155);
28
+ expect(sut.margin).toEqual(d(0.5155));
28
29
  expect(sut.estimatedUnrealizedPnL).toEqual(undefined);
29
30
  });
30
31
 
31
32
  test('should calculate correct unrealized pnl', () => {
32
- const sut = new Position('1', instrument, 'CROSS', 2511.81, 10.31, 20);
33
+ const sut = new Position('1', instrument, 'CROSS', d(2511.81), d(10.31), 20);
33
34
 
34
- const pnl = sut.calculateEstimatedUnrealizedPnL(2576.44);
35
+ const pnl = sut.calculateEstimatedUnrealizedPnL(d(2576.44));
35
36
 
36
- expect(pnl).toEqual(0.2652);
37
- expect(sut.estimatedUnrealizedPnL).toEqual(0.2652);
37
+ expect(pnl).toEqual(d(0.2652));
38
+ expect(sut.estimatedUnrealizedPnL).toEqual(d(0.2652));
38
39
  });
39
40
  });
@@ -1,5 +1,5 @@
1
1
  import { Instrument } from '../domain';
2
- import { pnl, timestamp } from '../shared';
2
+ import { decimal, pnl, timestamp } from '../shared';
3
3
  import { Component } from './component';
4
4
 
5
5
  export type PositionMode = 'CROSS' | 'ISOLATED';
@@ -7,23 +7,23 @@ export type PositionMode = 'CROSS' | 'ISOLATED';
7
7
  export class Position implements Component {
8
8
  kind = 'position';
9
9
  timestamp: timestamp;
10
- estimatedUnrealizedPnL?: number;
10
+ estimatedUnrealizedPnL?: decimal;
11
11
 
12
- get margin(): number {
13
- return this.instrument.quote.fixed(Math.abs(this.size) / this.leverage);
12
+ get margin(): decimal {
13
+ return this.instrument.quote.floor(this.size.abs().div(this.leverage));
14
14
  }
15
15
 
16
16
  constructor(
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
 
@@ -1,6 +1,6 @@
1
1
  import { Bootstrap } from '../bootstrap';
2
2
  import { Asset, Commission } from '../domain';
3
- import { now } from '../shared';
3
+ import { d, now } from '../shared';
4
4
  import { InstrumentPatchEvent } from '../store';
5
5
  import { SessionDescriptor } from './session';
6
6
 
@@ -25,14 +25,14 @@ describe('Session', () => {
25
25
  now(),
26
26
  new Asset('de30', 'cex', 2),
27
27
  new Asset('usd', 'cex', 2),
28
- new Commission(0, 0),
28
+ new Commission(d.Zero, d.Zero),
29
29
  ''
30
30
  ),
31
31
  new InstrumentPatchEvent(
32
32
  now(),
33
33
  new Asset('wig20', 'cex', 2),
34
34
  new Asset('pln', 'cex', 2),
35
- new Commission(0, 0),
35
+ new Commission(d.Zero, d.Zero),
36
36
  ''
37
37
  )
38
38
  );
@@ -232,9 +232,7 @@ export class Session {
232
232
  return this.store.changes$.pipe(
233
233
  startWith(this.store.snapshot.universe.instrument.get(selector.id)),
234
234
  filter(it => it instanceof Instrument && it.id == selector.id),
235
- switchMap(() =>
236
- from(this.aggregate.history({ instrument: selector, timeframe, length }))
237
- ),
235
+ switchMap(() => from(this.aggregate.history(selector, timeframe, length))),
238
236
  take(1),
239
237
  shareReplay(),
240
238
  mergeMap(it => it)
@@ -1,4 +1,4 @@
1
- import { timestamp } from '../shared';
1
+ import { decimal, timestamp } from '../shared';
2
2
  import { Instrument } from '.';
3
3
  import { Component } from './component';
4
4
 
@@ -10,8 +10,8 @@ export class Trade implements Component {
10
10
  id: string;
11
11
  kind = 'trade';
12
12
  timestamp: timestamp;
13
- rate: number;
14
- quantity: number;
13
+ rate: decimal;
14
+ quantity: decimal;
15
15
 
16
16
  constructor(public readonly instrument: Instrument) {
17
17
  this.id = instrument.id;
@@ -1,16 +1,17 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
3
  import { Candle } from '../domain';
4
+ import { decimal } from '../shared';
4
5
  import { rma } from './rma';
5
- import { truerange } from './truerange';
6
+ import { trueRange } from './true-range';
6
7
 
7
8
  export function atr<T>(length: number, fn: (it: T) => Candle) {
8
- return function (source: Observable<T>): Observable<[T, number]> {
9
+ return function (source: Observable<T>): Observable<[T, decimal]> {
9
10
  return source.pipe(
10
- truerange(fn),
11
+ trueRange(fn),
11
12
  rma(length, ([, tr]) => tr),
12
- map(([[it], truerange]) => {
13
- const tuple: [T, number] = [it, truerange];
13
+ map(([[it], tr]) => {
14
+ const tuple: [T, decimal] = [it, tr];
14
15
 
15
16
  return tuple;
16
17
  }),