@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,39 +1,36 @@
1
- import { from } from 'rxjs';
1
+ import { from, map } from 'rxjs';
2
2
 
3
- import { crossover, crossunder } from './cross';
3
+ import { d } from '../shared';
4
+ import { crossOver, crossUnder } from './cross';
4
5
 
5
- describe('crossunder', () => {
6
- test('should crossunder uptrend once', done => {
6
+ describe('crossUnder', () => {
7
+ test('should crossUnder uptrend once', done => {
7
8
  from([1, 2, 3, 4, 5])
8
9
  .pipe(
9
- crossunder(
10
- () => 3,
11
- it => it
12
- )
10
+ map(it => d(it)),
11
+ crossUnder(d(3), it => it)
13
12
  )
14
13
  .subscribe({
15
- next: it => expect(it).toBe(4),
14
+ next: it => expect(it).toEqual(d(4)),
16
15
  complete: done()
17
16
  });
18
17
  });
19
18
 
20
- test('should crossunder uptrend twice', done => {
19
+ test('should crossUnder uptrend twice', done => {
21
20
  let crosses = 0;
22
21
 
23
22
  from([1, 2, 3, 4, 5, 4, 2, 3, 3, 3, 4, 5])
24
23
  .pipe(
25
- crossunder(
26
- () => 3,
27
- it => it
28
- )
24
+ map(it => d(it)),
25
+ crossUnder(d(3), it => it)
29
26
  )
30
27
  .subscribe({
31
28
  next: it => {
32
- expect(it).toBe(4);
29
+ expect(it).toEqual(d(4));
33
30
  crosses++;
34
31
  },
35
32
  complete: () => {
36
- expect(crosses).toBe(2);
33
+ expect(crosses).toEqual(2);
37
34
  done();
38
35
  }
39
36
  });
@@ -44,18 +41,16 @@ describe('crossunder', () => {
44
41
 
45
42
  from([1, 2, 3, 4, 5, 4, 3, 3, 4, 5])
46
43
  .pipe(
47
- crossunder(
48
- () => 3,
49
- it => it
50
- )
44
+ map(it => d(it)),
45
+ crossUnder(d(3), it => it)
51
46
  )
52
47
  .subscribe({
53
48
  next: it => {
54
- expect(it).toBe(4);
49
+ expect(it).toEqual(d(4));
55
50
  crosses++;
56
51
  },
57
52
  complete: () => {
58
- expect(crosses).toBe(1);
53
+ expect(crosses).toEqual(1);
59
54
  done();
60
55
  }
61
56
  });
@@ -64,10 +59,8 @@ describe('crossunder', () => {
64
59
  test('should not cross downtrend', done => {
65
60
  from([5, 4, 3, 2, 1])
66
61
  .pipe(
67
- crossunder(
68
- () => 3,
69
- it => it
70
- )
62
+ map(it => d(it)),
63
+ crossUnder(d(3), it => it)
71
64
  )
72
65
  .subscribe({
73
66
  next: () => fail(),
@@ -80,13 +73,11 @@ describe('crossover', () => {
80
73
  test('should crossover downtrend once', done => {
81
74
  from([5, 4, 3, 2, 1])
82
75
  .pipe(
83
- crossover(
84
- () => 3,
85
- it => it
86
- )
76
+ map(it => d(it)),
77
+ crossOver(d(3), it => it)
87
78
  )
88
79
  .subscribe({
89
- next: it => expect(it).toBe(2),
80
+ next: it => expect(it).toEqual(d(2)),
90
81
  complete: done()
91
82
  });
92
83
  });
@@ -96,18 +87,16 @@ describe('crossover', () => {
96
87
 
97
88
  from([5, 4, 3, 2, 1, 2, 2, 3, 4, 4, 2, 3])
98
89
  .pipe(
99
- crossover(
100
- () => 3,
101
- it => it
102
- )
90
+ map(it => d(it)),
91
+ crossOver(d(3), it => it)
103
92
  )
104
93
  .subscribe({
105
94
  next: it => {
106
- expect(it).toBe(2);
95
+ expect(it).toEqual(d(2));
107
96
  crosses++;
108
97
  },
109
98
  complete: () => {
110
- expect(crosses).toBe(2);
99
+ expect(crosses).toEqual(2);
111
100
  done();
112
101
  }
113
102
  });
@@ -118,18 +107,16 @@ describe('crossover', () => {
118
107
 
119
108
  from([5, 4, 3, 2, 1, 2, 3, 3, 4, 5])
120
109
  .pipe(
121
- crossover(
122
- () => 3,
123
- it => it
124
- )
110
+ map(it => d(it)),
111
+ crossOver(d(3), it => it)
125
112
  )
126
113
  .subscribe({
127
114
  next: it => {
128
- expect(it).toBe(2);
115
+ expect(it).toEqual(d(2));
129
116
  crosses++;
130
117
  },
131
118
  complete: () => {
132
- expect(crosses).toBe(1);
119
+ expect(crosses).toEqual(1);
133
120
  done();
134
121
  }
135
122
  });
@@ -138,10 +125,8 @@ describe('crossover', () => {
138
125
  test('should not cross uptrend', done => {
139
126
  from([1, 2, 3, 4, 5])
140
127
  .pipe(
141
- crossover(
142
- () => 3,
143
- it => it
144
- )
128
+ map(it => d(it)),
129
+ crossOver(d(3), it => it)
145
130
  )
146
131
  .subscribe({
147
132
  next: () => fail(),
@@ -1,19 +1,24 @@
1
1
  import { filter, Observable } from 'rxjs';
2
2
 
3
- export function crossunder<T>(limitFn: (it: T) => number, currentFn: (it: T) => number) {
3
+ import { decimal } from '../shared';
4
+
5
+ export function crossUnder<T>(
6
+ trigger: decimal | ((it: T) => decimal),
7
+ value: (it: T) => decimal
8
+ ) {
4
9
  return function (source: Observable<T>): Observable<T> {
5
10
  let triggered = false;
6
11
 
7
12
  return source.pipe(
8
13
  filter(it => {
9
- const limit = limitFn(it);
10
- const current = currentFn(it);
14
+ const limit = typeof trigger == 'function' ? trigger(it) : trigger;
15
+ const current = value(it);
11
16
 
12
- if (current < limit) {
17
+ if (current.lessThan(limit)) {
13
18
  triggered = true;
14
19
  }
15
20
 
16
- if (triggered && current > limit) {
21
+ if (triggered && current.greaterThan(limit)) {
17
22
  triggered = false;
18
23
 
19
24
  return true;
@@ -25,20 +30,23 @@ export function crossunder<T>(limitFn: (it: T) => number, currentFn: (it: T) =>
25
30
  };
26
31
  }
27
32
 
28
- export function crossover<T>(limitFn: (it: T) => number, currentFn: (it: T) => number) {
33
+ export function crossOver<T>(
34
+ trigger: decimal | ((it: T) => decimal),
35
+ value: (it: T) => decimal
36
+ ) {
29
37
  return function (source: Observable<T>): Observable<T> {
30
38
  let triggered = false;
31
39
 
32
40
  return source.pipe(
33
41
  filter(it => {
34
- const limit = limitFn(it);
35
- const current = currentFn(it);
42
+ const limit = typeof trigger == 'function' ? trigger(it) : trigger;
43
+ const current = value(it);
36
44
 
37
- if (current > limit) {
45
+ if (current.greaterThan(limit)) {
38
46
  triggered = true;
39
47
  }
40
48
 
41
- if (triggered && current < limit) {
49
+ if (triggered && current.lessThan(limit)) {
42
50
  triggered = false;
43
51
 
44
52
  return true;
@@ -1,6 +1,7 @@
1
1
  import { map, Observable, share, withLatestFrom } from 'rxjs';
2
2
 
3
3
  import { Candle } from '../domain';
4
+ import { decimal } from '../shared';
4
5
  import { minMax } from './min-max';
5
6
 
6
7
  export function donchian<T>(length: number, fn: (it: T) => Candle) {
@@ -8,8 +9,8 @@ export function donchian<T>(length: number, fn: (it: T) => Candle) {
8
9
  [
9
10
  T,
10
11
  {
11
- upper: number;
12
- lower: number;
12
+ upper: decimal;
13
+ lower: decimal;
13
14
  }
14
15
  ]
15
16
  > {
@@ -24,8 +25,8 @@ export function donchian<T>(length: number, fn: (it: T) => Candle) {
24
25
  const tuple: [
25
26
  T,
26
27
  {
27
- upper: number;
28
- lower: number;
28
+ upper: decimal;
29
+ lower: decimal;
29
30
  }
30
31
  ] = [it, { lower: low[1].min, upper: high[1].max }];
31
32
 
@@ -1,9 +1,11 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
- export function drawdown<T>(fn: (it: T) => number) {
4
- return function (source: Observable<T>): Observable<number> {
5
- let rate;
6
- let max = 0;
3
+ import { d, decimal } from '../shared';
4
+
5
+ export function drawdown<T>(fn: (it: T) => decimal) {
6
+ return function (source: Observable<T>): Observable<decimal> {
7
+ let rate: decimal;
8
+ let max = d.Zero;
7
9
 
8
10
  return source.pipe(
9
11
  map(it => {
@@ -15,7 +17,7 @@ export function drawdown<T>(fn: (it: T) => number) {
15
17
  if (value > rate) {
16
18
  rate = value;
17
19
  } else if (value < rate) {
18
- max = Math.min(max, value / rate - 1);
20
+ max = decimal.min(max, value.div(rate).minus(1));
19
21
  }
20
22
  }
21
23
 
@@ -1,21 +1,22 @@
1
1
  import { from } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { ema } from './ema';
4
5
 
5
6
  describe('ema', () => {
6
7
  test('should return expected value', done => {
7
- let value;
8
+ let value: decimal;
8
9
 
9
10
  from([
10
11
  212.8, 214.06, 213.89, 214.66, 213.95, 213.95, 214.55, 214.02, 214.51, 213.75,
11
12
  214.22, 213.43, 214.21, 213.66, 215.03, 216.89, 216.66, 216.32, 214.98, 214.96,
12
13
  215.05, 215.19
13
14
  ])
14
- .pipe(ema(20, it => it))
15
+ .pipe(ema(20, it => d(it)))
15
16
  .subscribe({
16
17
  next: ([, it]) => (value = it),
17
18
  complete: () => {
18
- expect(parseFloat(value.toFixed(4))).toBe(214.6336);
19
+ expect(value.toDecimalPlaces(4)).toEqual(d(214.6336));
19
20
  done();
20
21
  }
21
22
  });
@@ -1,11 +1,12 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { sma } from './sma';
4
5
 
5
- export function ema<T>(length: number, fn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<[T, number]> {
7
- const alpha = 2.0 / (length + 1);
8
- let value: number = null;
6
+ export function ema<T>(length: number, fn: (it: T) => decimal) {
7
+ return function (source: Observable<T>): Observable<[T, decimal]> {
8
+ const alpha = d(2.0).div(d(length + 1));
9
+ let value: decimal = null;
9
10
 
10
11
  return source.pipe(
11
12
  sma(length, fn),
@@ -13,10 +14,10 @@ export function ema<T>(length: number, fn: (it: T) => number) {
13
14
  if (!value) {
14
15
  value = sma;
15
16
  } else {
16
- value = alpha * fn(it) + (1.0 - alpha) * value;
17
+ value = alpha.mul(fn(it)).plus(d(1.0).minus(alpha).mul(value));
17
18
  }
18
19
 
19
- const tuple: [T, number] = [it, value];
20
+ const tuple: [T, decimal] = [it, value];
20
21
 
21
22
  return tuple;
22
23
  }),
@@ -1,17 +1,22 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
+ import { decimal } from '../shared';
3
4
  import { sma } from './sma';
4
5
 
5
- export function envelope<T>(length: number, percent: number, valueFn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<{ min: number; max: number }> {
6
+ export function envelope<T>(
7
+ length: number,
8
+ percent: number,
9
+ valueFn: (it: T) => decimal
10
+ ) {
11
+ return function (source: Observable<T>): Observable<{ min: decimal; max: decimal }> {
7
12
  return source.pipe(
8
13
  sma(length, valueFn),
9
- map(([it, sma]) => {
10
- const offset = (sma * percent) / 100;
14
+ map(([, sma]) => {
15
+ const offset = sma.mul(percent).div(100);
11
16
 
12
17
  return {
13
- min: sma - offset,
14
- max: sma + offset
18
+ min: sma.minus(offset),
19
+ max: sma.add(offset)
15
20
  };
16
21
  }),
17
22
  share()
@@ -12,6 +12,6 @@ export * from './sma';
12
12
  export * from './swma';
13
13
  export * from './tma';
14
14
  export * from './trailing';
15
- export * from './truerange';
15
+ export * from './true-range';
16
16
  export * from './window';
17
17
  export * from './wma';
@@ -1,20 +1,21 @@
1
1
  import { map, Observable, share, withLatestFrom } from 'rxjs';
2
2
 
3
+ import { decimal } from '../shared';
3
4
  import { ema } from './ema';
4
5
 
5
6
  export function macd<T>(
6
7
  fast: number,
7
8
  slow: number,
8
9
  length: number,
9
- fn: (it: T) => number
10
+ fn: (it: T) => decimal
10
11
  ) {
11
- return function (source: Observable<T>): Observable<number> {
12
+ return function (source: Observable<T>): Observable<decimal> {
12
13
  source = source.pipe(share());
13
14
 
14
15
  return source.pipe(
15
16
  withLatestFrom(source.pipe(ema(fast, fn)), source.pipe(ema(slow, fn))),
16
- ema(length, it => it[1][1] - it[2][1]),
17
- map(([it, macd]) => macd),
17
+ ema(length, it => it[1][1].minus(it[2][1])),
18
+ map(([, macd]) => macd),
18
19
  share()
19
20
  );
20
21
  };
@@ -1,21 +1,24 @@
1
1
  import { filter, map, Observable, share } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { window } from './window';
4
5
 
5
- export function minMax<T>(length: number, fn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<[T, { min: number; max: number }]> {
6
+ export function minMax<T>(length: number, fn: (it: T) => decimal) {
7
+ return function (
8
+ source: Observable<T>
9
+ ): Observable<[T, { min: decimal; max: decimal }]> {
7
10
  return source.pipe(
8
11
  window(length, fn),
9
12
  filter(([, buffer]) => buffer.isFull),
10
13
  map(([it, buffer]) => {
11
- let min = 0;
12
- let max = 0;
14
+ let min = d.Zero;
15
+ let max = d.Zero;
13
16
 
14
17
  buffer.forEach(it => {
15
- min = Math.min(it, min);
16
- max = Math.max(it, max);
18
+ min = decimal.min(it, min);
19
+ max = decimal.max(it, max);
17
20
  });
18
- const tuple: [T, { min: number; max: number }] = [it, { min, max }];
21
+ const tuple: [T, { min: decimal; max: decimal }] = [it, { min, max }];
19
22
 
20
23
  return tuple;
21
24
  }),
@@ -1,11 +1,12 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { sma } from '.';
4
5
 
5
- export function rma<T>(length: number, fn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<[T, number]> {
7
- const alpha = 1.0 / length;
8
- let value: number = null;
6
+ export function rma<T>(length: number, fn: (it: T) => decimal) {
7
+ return function (source: Observable<T>): Observable<[T, decimal]> {
8
+ const alpha = d(1.0).div(length);
9
+ let value: decimal = null;
9
10
 
10
11
  return source.pipe(
11
12
  sma(length, fn),
@@ -13,10 +14,10 @@ export function rma<T>(length: number, fn: (it: T) => number) {
13
14
  if (!value) {
14
15
  value = sma;
15
16
  } else {
16
- value = alpha * fn(it) + (1.0 - alpha) * value;
17
+ value = alpha.mul(fn(it)).plus(d(1.0).minus(alpha).mul(value));
17
18
  }
18
19
 
19
- const tuple: [T, number] = [it, value];
20
+ const tuple: [T, decimal] = [it, value];
20
21
  return tuple;
21
22
  }),
22
23
  share()
@@ -1,18 +1,19 @@
1
1
  import { from } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { sma } from './sma';
4
5
 
5
6
  describe('sma', () => {
6
7
  test('should return expected value', done => {
7
- let value;
8
+ let value: decimal;
8
9
 
9
10
  //12 Dec 2020 00:00
10
11
  from([18136.17, 18092.15, 18082.39, 18065.4, 18046.47])
11
- .pipe(sma(5, it => it))
12
+ .pipe(sma(5, it => d(it)))
12
13
  .subscribe({
13
14
  next: ([, it]) => (value = it),
14
15
  complete: () => {
15
- expect(parseFloat(value.toFixed(2))).toBe(18084.52);
16
+ expect(value.toDecimalPlaces(2)).toEqual(d(18084.52));
16
17
  done();
17
18
  }
18
19
  });
@@ -1,20 +1,21 @@
1
1
  import { filter, map, Observable, share, tap } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { window } from './window';
4
5
 
5
- export function sma<T>(length: number, fn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<[T, number]> {
7
- let accumulated = 0;
6
+ export function sma<T>(length: number, fn: (it: T) => decimal) {
7
+ return function (source: Observable<T>): Observable<[T, decimal]> {
8
+ let accumulated = d.Zero;
8
9
 
9
10
  return source.pipe(
10
11
  window(length, fn),
11
- tap(([, , added, removed]) => {
12
- accumulated += added;
13
- accumulated -= removed;
14
- }),
12
+ tap(
13
+ ([, , added, removed]) =>
14
+ (accumulated = accumulated.add(added).minus(removed ?? 0))
15
+ ),
15
16
  filter(([, buffer]) => buffer.isFull),
16
17
  map(([it, buffer]) => {
17
- const tuple: [T, number] = [it, accumulated / buffer.size];
18
+ const tuple: [T, decimal] = [it, accumulated.div(buffer.size)];
18
19
 
19
20
  return tuple;
20
21
  }),
@@ -1,9 +1,10 @@
1
1
  import { filter, map, Observable, share } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { window } from './window';
4
5
 
5
- export function swma<T>(fn: (it: T) => number) {
6
- return function (source: Observable<T>): Observable<[T, number]> {
6
+ export function swma<T>(fn: (it: T) => decimal) {
7
+ return function (source: Observable<T>): Observable<[T, decimal]> {
7
8
  return source.pipe(
8
9
  window(4, fn),
9
10
  filter(([, buffer]) => buffer.isFull),
@@ -13,9 +14,12 @@ export function swma<T>(fn: (it: T) => number) {
13
14
  const x1 = buffer.at(buffer.capacity - (1 + 1));
14
15
  const x0 = buffer.at(buffer.capacity - (0 + 1));
15
16
 
16
- const value = (x3 * 1) / 6 + (x2 * 2) / 6 + (x1 * 2) / 6 + (x0 * 1) / 6;
17
+ const value = d.Zero.plus(x3.mul(1).div(6))
18
+ .plus(x2.mul(2).div(6))
19
+ .plus(x1.mul(2).div(6))
20
+ .plus(x0.mul(1).div(6));
17
21
 
18
- const tuple: [T, number] = [it, value];
22
+ const tuple: [T, decimal] = [it, value];
19
23
  return tuple;
20
24
  }),
21
25
  share()
@@ -1,18 +1,19 @@
1
1
  import { from } from 'rxjs';
2
2
 
3
+ import { d, decimal } from '../shared';
3
4
  import { tma } from './tma';
4
5
 
5
6
  describe('tma', () => {
6
7
  test('should return expected value', done => {
7
- let value;
8
+ let value: decimal;
8
9
 
9
10
  //12 Dec 2020 00:00
10
11
  from([18086.36, 18116.15, 18127.81, 18136.17, 18092.15, 18082.39, 18065.4, 18046.47])
11
- .pipe(tma(4, it => it))
12
+ .pipe(tma(4, it => d(it)))
12
13
  .subscribe({
13
14
  next: ([, it]) => (value = it),
14
15
  complete: () => {
15
- expect(parseFloat(value.toFixed(2))).toBe(18090.98);
16
+ expect(value.toDecimalPlaces(2)).toEqual(d(18090.98));
16
17
  done();
17
18
  }
18
19
  });
@@ -1,15 +1,16 @@
1
1
  import { map, Observable, share } from 'rxjs';
2
2
 
3
+ import { decimal } from '../shared';
3
4
  import { swma } from './swma';
4
5
  import { wma } from './wma';
5
6
 
6
- export function tma<T>(length: number, fn: (it: T) => number) {
7
- return function (source: Observable<T>): Observable<[T, number]> {
7
+ export function tma<T>(length: number, fn: (it: T) => decimal) {
8
+ return function (source: Observable<T>): Observable<[T, decimal]> {
8
9
  return source.pipe(
9
10
  wma(length, fn),
10
11
  swma(([, it]) => it),
11
12
  map(([[it], swma]) => {
12
- const tuple: [T, number] = [it, swma];
13
+ const tuple: [T, decimal] = [it, swma];
13
14
 
14
15
  return tuple;
15
16
  }),