@quantform/core 0.3.267 → 0.4.5

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 (246) hide show
  1. package/dist/adapter/adapter-aggregate.d.ts +2 -2
  2. package/dist/adapter/adapter-aggregate.js.map +1 -1
  3. package/dist/adapter/adapter.d.ts +4 -5
  4. package/dist/adapter/adapter.js.map +1 -1
  5. package/dist/adapter/backtester/backtester-adapter.d.ts +5 -5
  6. package/dist/adapter/backtester/backtester-adapter.js +3 -7
  7. package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
  8. package/dist/adapter/backtester/backtester-cursor.d.ts +2 -2
  9. package/dist/adapter/backtester/backtester-cursor.spec.js +9 -9
  10. package/dist/adapter/backtester/backtester-cursor.spec.js.map +1 -1
  11. package/dist/adapter/backtester/backtester-streamer.d.ts +6 -4
  12. package/dist/adapter/backtester/backtester-streamer.js +5 -5
  13. package/dist/adapter/backtester/backtester-streamer.js.map +1 -1
  14. package/dist/adapter/backtester/backtester-streamer.spec.js +9 -11
  15. package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -1
  16. package/dist/adapter/index.d.ts +2 -0
  17. package/dist/adapter/index.js +2 -0
  18. package/dist/adapter/index.js.map +1 -1
  19. package/dist/adapter/paper/index.d.ts +1 -1
  20. package/dist/adapter/paper/index.js +1 -1
  21. package/dist/adapter/paper/index.js.map +1 -1
  22. package/dist/adapter/paper/paper-adapter.d.ts +3 -3
  23. package/dist/adapter/paper/paper-adapter.js +4 -7
  24. package/dist/adapter/paper/paper-adapter.js.map +1 -1
  25. package/dist/adapter/paper/paper-adapter.spec.js +3 -5
  26. package/dist/adapter/paper/paper-adapter.spec.js.map +1 -1
  27. package/dist/adapter/paper/simulator/paper-margin-simulator.d.ts +1 -1
  28. package/dist/adapter/paper/simulator/paper-margin-simulator.js +6 -6
  29. package/dist/adapter/paper/simulator/paper-margin-simulator.js.map +1 -1
  30. package/dist/adapter/paper/simulator/paper-simulator.d.ts +1 -1
  31. package/dist/adapter/paper/simulator/paper-simulator.js +3 -3
  32. package/dist/adapter/paper/simulator/paper-simulator.js.map +1 -1
  33. package/dist/adapter/paper/simulator/paper-spot-simulator.d.ts +2 -2
  34. package/dist/adapter/paper/simulator/paper-spot-simulator.js +12 -12
  35. package/dist/adapter/paper/simulator/paper-spot-simulator.js.map +1 -1
  36. package/dist/adapter/paper/simulator/paper-spot-simulator.spec.js +8 -9
  37. package/dist/adapter/paper/simulator/paper-spot-simulator.spec.js.map +1 -1
  38. package/dist/bootstrap.d.ts +1 -1
  39. package/dist/bootstrap.js +3 -5
  40. package/dist/bootstrap.js.map +1 -1
  41. package/dist/domain/balance.d.ts +1 -1
  42. package/dist/domain/candle.d.ts +14 -0
  43. package/dist/domain/candle.js +65 -1
  44. package/dist/domain/candle.js.map +1 -1
  45. package/dist/domain/candle.spec.js +11 -13
  46. package/dist/domain/candle.spec.js.map +1 -1
  47. package/dist/domain/index.d.ts +6 -8
  48. package/dist/domain/index.js +6 -8
  49. package/dist/domain/index.js.map +1 -1
  50. package/dist/domain/order.d.ts +1 -1
  51. package/dist/domain/order.js.map +1 -1
  52. package/dist/domain/orderbook.d.ts +1 -1
  53. package/dist/domain/position.d.ts +2 -2
  54. package/dist/domain/position.js +3 -3
  55. package/dist/domain/position.js.map +1 -1
  56. package/dist/domain/session.d.ts +14 -3
  57. package/dist/domain/session.js +17 -18
  58. package/dist/domain/session.js.map +1 -1
  59. package/dist/domain/session.spec.js +3 -3
  60. package/dist/domain/session.spec.js.map +1 -1
  61. package/dist/domain/statement.d.ts +1 -2
  62. package/dist/domain/statement.js.map +1 -1
  63. package/dist/domain/trade.d.ts +1 -1
  64. package/dist/index.d.ts +4 -7
  65. package/dist/index.js +4 -7
  66. package/dist/index.js.map +1 -1
  67. package/dist/indicator/atr.js +3 -3
  68. package/dist/indicator/atr.js.map +1 -1
  69. package/dist/indicator/cross.js +3 -3
  70. package/dist/indicator/cross.js.map +1 -1
  71. package/dist/indicator/donchian.js +3 -4
  72. package/dist/indicator/donchian.js.map +1 -1
  73. package/dist/indicator/drawdown.js +3 -3
  74. package/dist/indicator/drawdown.js.map +1 -1
  75. package/dist/indicator/ema.js +3 -3
  76. package/dist/indicator/ema.js.map +1 -1
  77. package/dist/indicator/envelope.js +3 -3
  78. package/dist/indicator/envelope.js.map +1 -1
  79. package/dist/indicator/index.d.ts +3 -3
  80. package/dist/indicator/index.js +3 -3
  81. package/dist/indicator/index.js.map +1 -1
  82. package/dist/indicator/macd.js +2 -3
  83. package/dist/indicator/macd.js.map +1 -1
  84. package/dist/indicator/min-max.js +3 -3
  85. package/dist/indicator/min-max.js.map +1 -1
  86. package/dist/indicator/rma.js +3 -3
  87. package/dist/indicator/rma.js.map +1 -1
  88. package/dist/indicator/sma.js +2 -3
  89. package/dist/indicator/sma.js.map +1 -1
  90. package/dist/indicator/swma.js +3 -3
  91. package/dist/indicator/swma.js.map +1 -1
  92. package/dist/indicator/tma.js +3 -3
  93. package/dist/indicator/tma.js.map +1 -1
  94. package/dist/indicator/trailing.js +3 -3
  95. package/dist/indicator/trailing.js.map +1 -1
  96. package/dist/indicator/truerange.js +3 -3
  97. package/dist/indicator/truerange.js.map +1 -1
  98. package/dist/indicator/truerange.spec.js +2 -2
  99. package/dist/indicator/truerange.spec.js.map +1 -1
  100. package/dist/indicator/wma.js +3 -3
  101. package/dist/indicator/wma.js.map +1 -1
  102. package/dist/ipc.d.ts +1 -1
  103. package/dist/ipc.js +3 -3
  104. package/dist/ipc.js.map +1 -1
  105. package/dist/ipc.spec.js +3 -4
  106. package/dist/ipc.spec.js.map +1 -1
  107. package/dist/shared/index.d.ts +4 -4
  108. package/dist/shared/index.js +4 -4
  109. package/dist/shared/index.js.map +1 -1
  110. package/dist/shared/policy.js +1 -1
  111. package/dist/shared/policy.js.map +1 -1
  112. package/dist/storage/feed.d.ts +1 -1
  113. package/dist/storage/feed.js.map +1 -1
  114. package/dist/storage/index.d.ts +1 -1
  115. package/dist/storage/index.js +1 -1
  116. package/dist/storage/index.js.map +1 -1
  117. package/dist/storage/measurement.js.map +1 -1
  118. package/dist/storage/storage.js.map +1 -1
  119. package/dist/store/event/index.d.ts +4 -4
  120. package/dist/store/event/index.js +4 -4
  121. package/dist/store/event/index.js.map +1 -1
  122. package/dist/store/event/store-balance.event.d.ts +1 -1
  123. package/dist/store/event/store-balance.event.js +1 -1
  124. package/dist/store/event/store-balance.event.js.map +1 -1
  125. package/dist/store/event/store-balance.event.spec.js +3 -3
  126. package/dist/store/event/store-balance.event.spec.js.map +1 -1
  127. package/dist/store/event/store-candle.event.d.ts +2 -2
  128. package/dist/store/event/store-candle.event.js +2 -2
  129. package/dist/store/event/store-candle.event.js.map +1 -1
  130. package/dist/store/event/store-candle.event.spec.js +1 -1
  131. package/dist/store/event/store-candle.event.spec.js.map +1 -1
  132. package/dist/store/event/store-instrument.event.d.ts +1 -1
  133. package/dist/store/event/store-instrument.event.js +1 -1
  134. package/dist/store/event/store-instrument.event.js.map +1 -1
  135. package/dist/store/event/store-instrument.event.spec.js +1 -1
  136. package/dist/store/event/store-instrument.event.spec.js.map +1 -1
  137. package/dist/store/event/store-order.event.d.ts +1 -1
  138. package/dist/store/event/store-order.event.js +1 -1
  139. package/dist/store/event/store-order.event.js.map +1 -1
  140. package/dist/store/event/store-order.event.spec.js +2 -2
  141. package/dist/store/event/store-order.event.spec.js.map +1 -1
  142. package/dist/store/event/store-orderbook.event.d.ts +1 -1
  143. package/dist/store/event/store-orderbook.event.js +1 -1
  144. package/dist/store/event/store-orderbook.event.js.map +1 -1
  145. package/dist/store/event/store-position.event.d.ts +1 -1
  146. package/dist/store/event/store-position.event.js +1 -1
  147. package/dist/store/event/store-position.event.js.map +1 -1
  148. package/dist/store/event/store-trade.event.d.ts +1 -1
  149. package/dist/store/event/store-trade.event.js +1 -1
  150. package/dist/store/event/store-trade.event.js.map +1 -1
  151. package/dist/store/event/store-trade.event.spec.js +2 -2
  152. package/dist/store/event/store-trade.event.spec.js.map +1 -1
  153. package/dist/store/index.d.ts +1 -0
  154. package/dist/store/index.js +1 -0
  155. package/dist/store/index.js.map +1 -1
  156. package/dist/store/store.d.ts +2 -5
  157. package/dist/store/store.js +4 -8
  158. package/dist/store/store.js.map +1 -1
  159. package/dist/store/store.state.d.ts +1 -1
  160. package/dist/tests/backtester-adapter.spec.js +6 -13
  161. package/dist/tests/backtester-adapter.spec.js.map +1 -1
  162. package/dist/tests/session.spec.d.ts +0 -1
  163. package/dist/tests/session.spec.js +0 -2
  164. package/dist/tsconfig.tsbuildinfo +1 -1
  165. package/package.json +1 -1
  166. package/src/adapter/adapter-aggregate.ts +2 -3
  167. package/src/adapter/adapter.ts +4 -5
  168. package/src/adapter/backtester/backtester-adapter.ts +6 -6
  169. package/src/adapter/backtester/backtester-cursor.spec.ts +1 -1
  170. package/src/adapter/backtester/backtester-cursor.ts +2 -2
  171. package/src/adapter/backtester/backtester-streamer.spec.ts +1 -3
  172. package/src/adapter/backtester/backtester-streamer.ts +7 -8
  173. package/src/adapter/index.ts +2 -0
  174. package/src/adapter/paper/index.ts +1 -1
  175. package/src/adapter/paper/paper-adapter.spec.ts +3 -5
  176. package/src/adapter/paper/paper-adapter.ts +3 -5
  177. package/src/adapter/paper/simulator/paper-margin-simulator.ts +3 -3
  178. package/src/adapter/paper/simulator/paper-simulator.ts +3 -3
  179. package/src/adapter/paper/simulator/paper-spot-simulator.spec.ts +12 -13
  180. package/src/adapter/paper/simulator/paper-spot-simulator.ts +4 -4
  181. package/src/bootstrap.ts +4 -4
  182. package/src/domain/balance.ts +1 -1
  183. package/src/domain/candle.spec.ts +3 -5
  184. package/src/domain/candle.ts +103 -0
  185. package/src/domain/index.ts +6 -8
  186. package/src/domain/order.ts +2 -2
  187. package/src/domain/orderbook.ts +1 -1
  188. package/src/domain/position.ts +2 -3
  189. package/src/domain/session.spec.ts +3 -3
  190. package/src/domain/session.ts +61 -8
  191. package/src/domain/statement.ts +1 -2
  192. package/src/domain/trade.ts +1 -1
  193. package/src/index.ts +4 -7
  194. package/src/indicator/atr.ts +1 -2
  195. package/src/indicator/cross.ts +3 -4
  196. package/src/indicator/donchian.ts +2 -3
  197. package/src/indicator/drawdown.ts +2 -3
  198. package/src/indicator/ema.ts +1 -2
  199. package/src/indicator/envelope.ts +1 -2
  200. package/src/indicator/index.ts +3 -3
  201. package/src/indicator/macd.ts +1 -2
  202. package/src/indicator/min-max.ts +1 -2
  203. package/src/indicator/rma.ts +1 -2
  204. package/src/indicator/sma.ts +1 -2
  205. package/src/indicator/swma.ts +1 -2
  206. package/src/indicator/tma.ts +1 -2
  207. package/src/indicator/trailing.ts +3 -4
  208. package/src/indicator/truerange.spec.ts +2 -2
  209. package/src/indicator/truerange.ts +1 -2
  210. package/src/indicator/window.ts +1 -1
  211. package/src/indicator/wma.ts +1 -2
  212. package/src/ipc.spec.ts +3 -4
  213. package/src/ipc.ts +6 -6
  214. package/src/shared/index.ts +4 -4
  215. package/src/shared/policy.ts +1 -1
  216. package/src/shared/topic.spec.ts +1 -1
  217. package/src/storage/feed.ts +20 -1
  218. package/src/storage/index.ts +1 -1
  219. package/src/storage/measurement.ts +19 -0
  220. package/src/storage/storage.ts +37 -0
  221. package/src/store/event/index.ts +4 -4
  222. package/src/store/event/store-balance.event.spec.ts +3 -3
  223. package/src/store/event/store-balance.event.ts +2 -2
  224. package/src/store/event/store-candle.event.spec.ts +1 -1
  225. package/src/store/event/store-candle.event.ts +5 -5
  226. package/src/store/event/store-instrument.event.spec.ts +1 -1
  227. package/src/store/event/store-instrument.event.ts +2 -2
  228. package/src/store/event/store-order.event.spec.ts +2 -2
  229. package/src/store/event/store-order.event.ts +2 -2
  230. package/src/store/event/store-orderbook.event.ts +2 -2
  231. package/src/store/event/store-position.event.ts +2 -2
  232. package/src/store/event/store-trade.event.spec.ts +2 -2
  233. package/src/store/event/store-trade.event.ts +2 -2
  234. package/src/store/index.ts +1 -0
  235. package/src/store/store.state.ts +7 -7
  236. package/src/store/store.ts +6 -9
  237. package/src/tests/backtester-adapter.spec.ts +6 -13
  238. package/src/tests/session.spec.ts +0 -3
  239. package/dist/domain/candle-builder.d.ts +0 -16
  240. package/dist/domain/candle-builder.js +0 -70
  241. package/dist/domain/candle-builder.js.map +0 -1
  242. package/dist/domain/session-descriptor.d.ts +0 -15
  243. package/dist/domain/session-descriptor.js +0 -3
  244. package/dist/domain/session-descriptor.js.map +0 -1
  245. package/src/domain/candle-builder.ts +0 -104
  246. package/src/domain/session-descriptor.ts +0 -53
@@ -1,12 +1,10 @@
1
1
  import { PaperSpotSimulator } from '.';
2
2
  import { AdapterContext } from '..';
3
- import { Store } from '../../store';
3
+ import { InstrumentPatchEvent, Store } from '../../store';
4
4
  import { Adapter } from '../adapter';
5
- import { PaperSimulator } from './simulator/paper-simulator';
5
+ import { Asset, Commission, instrumentOf, Order } from './../../domain';
6
6
  import { PaperAdapter } from './paper-adapter';
7
- import { Order, Asset, Commission, assetOf } from './../../domain';
8
- import { instrumentOf } from './../../domain/instrument';
9
- import { BalancePatchEvent, InstrumentPatchEvent } from '../../store/event';
7
+ import { PaperSimulator } from './simulator/paper-simulator';
10
8
 
11
9
  class DefaultAdapter extends Adapter {
12
10
  name = 'default';
@@ -1,12 +1,10 @@
1
1
  import { Adapter, AdapterContext } from '..';
2
- import { Store } from '../../store';
3
- import { PaperSimulator } from './simulator/paper-simulator';
4
2
  import { assetOf, Candle, InstrumentSelector, Order } from '../../domain';
5
- import { BalancePatchEvent } from '../../store/event';
6
- import { Feed } from 'src/storage';
3
+ import { BalancePatchEvent, Store } from '../../store';
7
4
  import { FeedQuery, HistoryQuery } from '../adapter';
5
+ import { PaperSimulator } from './simulator/paper-simulator';
8
6
 
9
- export class PaperOptions {
7
+ export interface PaperOptions {
10
8
  balance: { [key: string]: number };
11
9
  }
12
10
 
@@ -1,5 +1,6 @@
1
- import { pnl, weightedMean } from '../../../shared';
1
+ import { PaperAdapter } from '..';
2
2
  import { Order } from '../../../domain';
3
+ import { pnl, weightedMean } from '../../../shared';
3
4
  import {
4
5
  BalanceTransactEvent,
5
6
  OrderCanceledEvent,
@@ -8,8 +9,7 @@ import {
8
9
  OrderNewEvent,
9
10
  OrderPendingEvent,
10
11
  PositionPatchEvent
11
- } from '../../../store/event';
12
- import { PaperAdapter } from '..';
12
+ } from '../../../store';
13
13
  import { PaperSimulator } from './paper-simulator';
14
14
 
15
15
  export class PaperMarginSimulator extends PaperSimulator {
@@ -1,7 +1,7 @@
1
- import { tap } from 'rxjs/operators';
2
- import { Component, InstrumentSelector, Order, Orderbook, Trade } from '../../../domain';
3
- import { PaperAdapter } from '..';
1
+ import { tap } from 'rxjs';
4
2
  import { Set } from 'typescript-collections';
3
+ import { PaperAdapter } from '..';
4
+ import { Component, InstrumentSelector, Order, Orderbook, Trade } from '../../../domain';
5
5
 
6
6
  export abstract class PaperSimulator {
7
7
  private readonly pending: Record<string, Set<Order>> = {};
@@ -1,23 +1,22 @@
1
- import { Adapter, AdapterContext } from './../../adapter';
1
+ import { PaperAdapter } from '../paper-adapter';
2
+ import {
3
+ Asset,
4
+ assetOf,
5
+ Commission,
6
+ commissionPercentOf,
7
+ instrumentOf,
8
+ Order
9
+ } from './../../../domain';
2
10
  import {
3
11
  BalancePatchEvent,
4
12
  InstrumentPatchEvent,
5
13
  InstrumentSubscriptionEvent,
6
- OrderbookPatchEvent,
14
+ Store,
7
15
  TradePatchEvent
8
- } from './../../../store/event';
9
- import { Store } from './../../../store';
16
+ } from './../../../store';
17
+ import { Adapter, AdapterContext } from './../../adapter';
10
18
  import { PaperSimulator } from './paper-simulator';
11
- import { PaperAdapter } from '../paper-adapter';
12
19
  import { PaperSpotSimulator } from './paper-spot-simulator';
13
- import {
14
- Asset,
15
- Commission,
16
- Order,
17
- instrumentOf,
18
- assetOf,
19
- commissionPercentOf
20
- } from './../../../domain';
21
20
 
22
21
  class DefaultAdapter extends Adapter {
23
22
  name = 'default';
@@ -1,4 +1,6 @@
1
- import { Order, Orderbook } from '../../../domain';
1
+ import { PaperAdapter } from '..';
2
+ import { Order } from '../../../domain';
3
+ import { timestamp } from '../../../shared';
2
4
  import {
3
5
  BalanceFreezEvent,
4
6
  BalanceTransactEvent,
@@ -8,10 +10,8 @@ import {
8
10
  OrderFilledEvent,
9
11
  OrderNewEvent,
10
12
  OrderPendingEvent
11
- } from '../../../store/event';
12
- import { PaperAdapter } from '..';
13
+ } from '../../../store';
13
14
  import { PaperSimulator } from './paper-simulator';
14
- import { timestamp } from '../../../shared';
15
15
 
16
16
  export class PaperSpotSimulator extends PaperSimulator {
17
17
  constructor(readonly adapter: PaperAdapter) {
package/src/bootstrap.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
+ AdapterAggregate,
2
3
  BacktesterAdapter,
3
4
  BacktesterListener,
4
- BacktesterStreamer
5
- } from './adapter/backtester';
6
- import { AdapterAggregate } from './adapter';
7
- import { PaperAdapter } from './adapter/paper';
5
+ BacktesterStreamer,
6
+ PaperAdapter
7
+ } from './adapter';
8
8
  import { Session, SessionDescriptor } from './domain';
9
9
  import { Store } from './store';
10
10
 
@@ -1,7 +1,7 @@
1
1
  import { timestamp } from '../shared';
2
2
  import { Asset } from './';
3
- import { Position, PositionMode } from './position';
4
3
  import { Component } from './component';
4
+ import { Position, PositionMode } from './position';
5
5
 
6
6
  /**
7
7
  * Represents single asset balance in your wallet.
@@ -1,9 +1,7 @@
1
- import { from } from 'rxjs';
2
- import { map } from 'rxjs/operators';
3
- import { TradePatchEvent } from '../store/event';
1
+ import { from, map } from 'rxjs';
4
2
  import { now } from '../shared';
5
- import { Candle } from './candle';
6
- import { mergeCandle } from './candle-builder';
3
+ import { TradePatchEvent } from '../store';
4
+ import { Candle, mergeCandle } from './candle';
7
5
  import { instrumentOf } from './instrument';
8
6
  import { Timeframe } from './timeframe';
9
7
 
@@ -1,4 +1,16 @@
1
+ import {
2
+ concat,
3
+ filter,
4
+ last,
5
+ map,
6
+ mergeMap,
7
+ Observable,
8
+ share,
9
+ skipLast,
10
+ withLatestFrom
11
+ } from 'rxjs';
1
12
  import { timestamp } from '../shared';
13
+ import { tf } from './timeframe';
2
14
 
3
15
  export class Candle {
4
16
  constructor(
@@ -15,3 +27,94 @@ export class Candle {
15
27
  this.close = value;
16
28
  }
17
29
  }
30
+
31
+ export class CandleBuilder {
32
+ private _candle: Candle;
33
+
34
+ get candle(): Candle {
35
+ return this._candle;
36
+ }
37
+
38
+ constructor(readonly timeframe: number) {}
39
+
40
+ append(value: number, timestamp: timestamp): Candle {
41
+ const frame = tf(timestamp, this.timeframe);
42
+
43
+ if (!this._candle) {
44
+ this._candle = new Candle(frame, value, value, value, value);
45
+
46
+ return null;
47
+ }
48
+
49
+ if (this.candle.timestamp == frame) {
50
+ this.candle.apply(value);
51
+
52
+ return null;
53
+ }
54
+
55
+ const previous = this._candle;
56
+
57
+ this._candle = new Candle(frame, value, value, value, value);
58
+ return previous;
59
+ }
60
+ }
61
+
62
+ export function candle<T extends { timestamp: number }>(
63
+ timeframe: number,
64
+ fn: (x: T) => number
65
+ ) {
66
+ return function (source: Observable<T>): Observable<Candle> {
67
+ const builder = new CandleBuilder(timeframe);
68
+ let candle: Candle;
69
+
70
+ return source.pipe(
71
+ filter(it => {
72
+ return (candle = builder.append(fn(it), it.timestamp)) != null;
73
+ }),
74
+ map(_ => candle),
75
+ share()
76
+ );
77
+ };
78
+ }
79
+
80
+ export function mergeCandle<T extends { timestamp: number }>(
81
+ timeframe: number,
82
+ fn: (x: T) => number,
83
+ history$: Observable<Candle>
84
+ ) {
85
+ return function (source$: Observable<T>): Observable<Candle> {
86
+ const builder = new CandleBuilder(timeframe);
87
+ let hasMergedHistory = false;
88
+
89
+ return concat(
90
+ history$.pipe(skipLast(1)),
91
+ source$.pipe(
92
+ withLatestFrom(history$.pipe(last())),
93
+ mergeMap(([it, history]) => {
94
+ const completed = builder.append(fn(it), it.timestamp);
95
+
96
+ if (completed) {
97
+ if (completed.timestamp == history.timestamp) {
98
+ completed.open = history.open;
99
+ completed.high = Math.max(completed.high, history.high);
100
+ completed.low = Math.min(completed.low, history.low);
101
+
102
+ hasMergedHistory = true;
103
+ } else if (completed.timestamp > history.timestamp) {
104
+ if (!hasMergedHistory) {
105
+ hasMergedHistory = true;
106
+ return [history, completed];
107
+ }
108
+ } else if (completed.timestamp < history.timestamp) {
109
+ throw new Error('invalid candle sequence, input data is to old.');
110
+ }
111
+
112
+ return [completed];
113
+ }
114
+
115
+ return [];
116
+ })
117
+ )
118
+ );
119
+ };
120
+ }
@@ -1,15 +1,13 @@
1
1
  export * from './asset';
2
- export * from './instrument';
3
2
  export * from './balance';
4
- export * from './order';
5
- export * from './orderbook';
3
+ export * from './candle';
6
4
  export * from './commission';
7
5
  export * from './component';
8
- export * from './candle';
9
- export * from './candle-builder';
10
- export * from './timeframe';
6
+ export * from './instrument';
7
+ export * from './order';
8
+ export * from './orderbook';
11
9
  export * from './position';
12
- export * from './trade';
13
10
  export * from './session';
14
- export * from './session-descriptor';
15
11
  export * from './statement';
12
+ export * from './timeframe';
13
+ export * from './trade';
@@ -1,7 +1,7 @@
1
- import { Component } from './component';
2
1
  import { v4 } from 'uuid';
3
- import { InstrumentSelector } from './instrument';
4
2
  import { timestamp } from '../shared';
3
+ import { Component } from './component';
4
+ import { InstrumentSelector } from './instrument';
5
5
 
6
6
  export type OrderSide = 'SELL' | 'BUY';
7
7
  export type OrderType = 'MARKET' | 'LIMIT' | 'STOP-MARKET' | 'STOP-LIMIT';
@@ -1,5 +1,5 @@
1
- import { timestamp } from '../shared';
2
1
  import { Instrument } from '../domain';
2
+ import { timestamp } from '../shared';
3
3
  import { Component } from './component';
4
4
 
5
5
  /**
@@ -1,8 +1,7 @@
1
+ import { map, Observable, share } from 'rxjs';
1
2
  import { Instrument } from '../domain';
2
- import { Component } from './component';
3
3
  import { pnl, timestamp, weightedMean } from '../shared';
4
- import { Observable } from 'rxjs';
5
- import { map, share } from 'rxjs/operators';
4
+ import { Component } from './component';
6
5
 
7
6
  export type PositionMode = 'CROSS' | 'ISOLATED';
8
7
 
@@ -1,8 +1,8 @@
1
- import { InstrumentPatchEvent } from '../store/event';
1
+ import { Bootstrap } from '../bootstrap';
2
2
  import { Asset, Commission } from '../domain';
3
3
  import { now } from '../shared';
4
- import { SessionDescriptor } from './session-descriptor';
5
- import { Bootstrap } from '../bootstrap';
4
+ import { InstrumentPatchEvent } from '../store';
5
+ import { SessionDescriptor } from './session';
6
6
 
7
7
  describe('session tests', () => {
8
8
  const descriptor: SessionDescriptor = {
@@ -1,14 +1,21 @@
1
1
  import {
2
+ concat,
2
3
  distinctUntilChanged,
3
4
  filter,
5
+ from,
4
6
  map,
5
7
  mergeMap,
8
+ Observable,
6
9
  share,
7
10
  shareReplay,
8
11
  startWith,
12
+ Subject,
13
+ Subscription,
9
14
  switchMap,
10
15
  take
11
- } from 'rxjs/operators';
16
+ } from 'rxjs';
17
+ import { Adapter, BacktesterOptions, PaperOptions } from '../adapter';
18
+ import { AdapterAggregate } from '../adapter/adapter-aggregate';
12
19
  import {
13
20
  AssetSelector,
14
21
  Balance,
@@ -16,19 +23,65 @@ import {
16
23
  Instrument,
17
24
  InstrumentSelector,
18
25
  Order,
19
- Position,
20
26
  Orderbook,
21
- OrderState
27
+ OrderState,
28
+ Position
22
29
  } from '../domain';
23
- import { Store } from '../store';
24
- import { concat, from, Observable, Subject, Subscription } from 'rxjs';
25
- import { AdapterAggregate } from '../adapter/adapter-aggregate';
26
- import { Worker, now } from '../shared';
27
30
  import { Trade } from '../domain/trade';
28
- import { SessionDescriptor } from './session-descriptor';
31
+ import { now, Worker } from '../shared';
32
+ import { Feed, Measurement } from '../storage';
33
+ import { Store } from '../store';
29
34
 
30
35
  type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
31
36
 
37
+ /**
38
+ * Describes a single session.
39
+ * You can use @run function to start a new session managed by CLI.
40
+ * To start managed session you should install @quantform/cli package and run
41
+ * specific command:
42
+ * - qf paper (to paper trade strategy)
43
+ * - qf backtest (to backtest strategy based on provided feed)
44
+ * - qf live (to live trade strategy)
45
+ * or run on your own in code:
46
+ * - paper(descriptor, options)
47
+ * - backtest(descriptor, options)
48
+ * - live(descriptor)
49
+ */
50
+ export interface SessionDescriptor {
51
+ /**
52
+ * Unique session identifier, used to identify session in the storage.
53
+ * You can generate new id every time you start the new session or provide
54
+ * session id explicitly to resume previous session (in code or via CLI).
55
+ * If you don't provide session id, it will generate new one based on time.
56
+ */
57
+ id?: number;
58
+
59
+ /**
60
+ * Collection of adapters used to connect to the exchanges.
61
+ */
62
+ adapter: Adapter[];
63
+
64
+ /**
65
+ * Provides historical data for backtest, it's not required for live and paper
66
+ * sessions.
67
+ */
68
+ feed?: Feed;
69
+
70
+ /**
71
+ * Stores session variables i.e. indicators, orders, or any other type of time
72
+ * series data. You can install @quantform/editor to render this data in your browser.
73
+ */
74
+ measurement?: Measurement;
75
+
76
+ /**
77
+ * Session additional options.
78
+ */
79
+ options?: {
80
+ backtester?: BacktesterOptions;
81
+ paper?: PaperOptions;
82
+ };
83
+ }
84
+
32
85
  export class Session {
33
86
  private initialized = false;
34
87
  private subscription: Subscription;
@@ -1,6 +1,5 @@
1
- import { Session } from '.';
2
- import { InstrumentSelector } from '.';
3
1
  import { combineLatest, finalize, map, take, tap } from 'rxjs';
2
+ import { InstrumentSelector, Session } from '.';
4
3
  import { drawdown } from '../indicator';
5
4
  import { floor, precision } from '../shared';
6
5
 
@@ -1,5 +1,5 @@
1
- import { timestamp } from '../shared';
2
1
  import { Instrument } from '.';
2
+ import { timestamp } from '../shared';
3
3
  import { Component } from './component';
4
4
 
5
5
  /**
package/src/index.ts CHANGED
@@ -1,11 +1,8 @@
1
- export * from './shared';
2
- export * from './domain';
3
1
  export * from './adapter';
4
- export * from './adapter/backtester';
5
- export * from './adapter/paper';
2
+ export * from './bootstrap';
3
+ export * from './domain';
6
4
  export * from './indicator';
5
+ export * from './ipc';
6
+ export * from './shared';
7
7
  export * from './storage';
8
8
  export * from './store';
9
- export * from './store/event';
10
- export * from './bootstrap';
11
- export * from './ipc';
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { share, map } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { Candle } from '../domain';
4
3
  import { rma } from './rma';
5
4
  import { truerange } from './truerange';
@@ -1,8 +1,7 @@
1
- import { Observable } from 'rxjs';
2
- import { filter } from 'rxjs/operators';
1
+ import { filter, Observable } from 'rxjs';
3
2
 
4
3
  export function crossunder<T>(limitFn: (it: T) => number, currentFn: (it: T) => number) {
5
- return function(source: Observable<T>): Observable<T> {
4
+ return function (source: Observable<T>): Observable<T> {
6
5
  let triggered = false;
7
6
 
8
7
  return source.pipe(
@@ -27,7 +26,7 @@ export function crossunder<T>(limitFn: (it: T) => number, currentFn: (it: T) =>
27
26
  }
28
27
 
29
28
  export function crossover<T>(limitFn: (it: T) => number, currentFn: (it: T) => number) {
30
- return function(source: Observable<T>): Observable<T> {
29
+ return function (source: Observable<T>): Observable<T> {
31
30
  let triggered = false;
32
31
 
33
32
  return source.pipe(
@@ -1,7 +1,6 @@
1
- import { Observable, withLatestFrom } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
3
- import { minMax } from './min-max';
1
+ import { map, Observable, share, withLatestFrom } from 'rxjs';
4
2
  import { Candle } from '../domain';
3
+ import { minMax } from './min-max';
5
4
 
6
5
  export function donchian<T>(length: number, fn: (it: T) => Candle) {
7
6
  return function (source: Observable<T>): Observable<
@@ -1,8 +1,7 @@
1
- import { Observable } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
 
4
3
  export function drawdown<T>(fn: (it: T) => number) {
5
- return function(source: Observable<T>): Observable<number> {
4
+ return function (source: Observable<T>): Observable<number> {
6
5
  let rate;
7
6
  let max = 0;
8
7
 
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { sma } from './sma';
4
3
 
5
4
  export function ema<T>(length: number, fn: (it: T) => number) {
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { sma } from './sma';
4
3
 
5
4
  export function envelope<T>(length: number, percent: number, valueFn: (it: T) => number) {
@@ -1,4 +1,7 @@
1
+ export * from './atr';
1
2
  export * from './cross';
3
+ export * from './donchian';
4
+ export * from './drawdown';
2
5
  export * from './ema';
3
6
  export * from './envelope';
4
7
  export * from './macd';
@@ -12,6 +15,3 @@ export * from './trailing';
12
15
  export * from './truerange';
13
16
  export * from './window';
14
17
  export * from './wma';
15
- export * from './donchian';
16
- export * from './atr';
17
- export * from './drawdown';
@@ -1,5 +1,4 @@
1
- import { Observable, withLatestFrom } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share, withLatestFrom } from 'rxjs';
3
2
  import { ema } from './ema';
4
3
 
5
4
  export function macd<T>(
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { filter, map, share } from 'rxjs/operators';
1
+ import { filter, map, Observable, share } from 'rxjs';
3
2
  import { window } from './window';
4
3
 
5
4
  export function minMax<T>(length: number, fn: (it: T) => number) {
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { sma } from '.';
4
3
 
5
4
  export function rma<T>(length: number, fn: (it: T) => number) {
@@ -1,5 +1,4 @@
1
- import { Observable, tap } from 'rxjs';
2
- import { filter, map, share } from 'rxjs/operators';
1
+ import { filter, map, Observable, share, tap } from 'rxjs';
3
2
  import { window } from './window';
4
3
 
5
4
  export function sma<T>(length: number, fn: (it: T) => number) {
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { filter, map, share } from 'rxjs/operators';
1
+ import { filter, map, Observable, share } from 'rxjs';
3
2
  import { window } from './window';
4
3
 
5
4
  export function swma<T>(fn: (it: T) => number) {
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { share, map } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { swma } from './swma';
4
3
  import { wma } from './wma';
5
4
 
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { filter } from 'rxjs/operators';
1
+ import { filter, Observable } from 'rxjs';
3
2
 
4
3
  export class Trailing {
5
4
  private triggered = false;
@@ -56,7 +55,7 @@ export class Trailing {
56
55
  }
57
56
 
58
57
  export function trailingup<T>(trigger: number, buffer: number, value: (it: T) => number) {
59
- return function(source: Observable<T>): Observable<T> {
58
+ return function (source: Observable<T>): Observable<T> {
60
59
  const trailing = new Trailing(trigger, buffer);
61
60
 
62
61
  return source.pipe(filter(it => trailing.up(value(it))));
@@ -68,7 +67,7 @@ export function trailingdown<T>(
68
67
  buffer: number,
69
68
  value: (it: T) => number
70
69
  ) {
71
- return function(source: Observable<T>): Observable<T> {
70
+ return function (source: Observable<T>): Observable<T> {
72
71
  const trailing = new Trailing(trigger, buffer);
73
72
 
74
73
  return source.pipe(filter(it => trailing.down(value(it))));
@@ -1,8 +1,8 @@
1
1
  import { from } from 'rxjs';
2
2
  import { Candle } from '../domain';
3
- import { truerange } from './truerange';
4
- import { sma } from './sma';
5
3
  import { now } from '../shared';
4
+ import { sma } from './sma';
5
+ import { truerange } from './truerange';
6
6
 
7
7
  describe('truerange atr tests', () => {
8
8
  test('should return expected value', done => {
@@ -1,5 +1,4 @@
1
- import { Observable } from 'rxjs';
2
- import { map, share } from 'rxjs/operators';
1
+ import { map, Observable, share } from 'rxjs';
3
2
  import { Candle } from '../domain';
4
3
 
5
4
  export function truerange<T>(fn: (it: T) => Candle) {
@@ -1,4 +1,4 @@
1
- import { Observable, share, map } from 'rxjs';
1
+ import { map, Observable, share } from 'rxjs';
2
2
  import { RingBuffer } from './ring-buffer';
3
3
 
4
4
  export function window<T, Y>(length: number, fn: (value: T) => Y) {