@quantform/core 0.3.221 → 0.3.229

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 (69) hide show
  1. package/dist/adapter/adapter.event.js +2 -1
  2. package/dist/adapter/adapter.event.js.map +1 -1
  3. package/dist/adapter/backtester/backtester-adapter.js +0 -2
  4. package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
  5. package/dist/adapter/backtester/backtester-cursor.d.ts +1 -1
  6. package/dist/adapter/backtester/backtester-cursor.js +5 -1
  7. package/dist/adapter/backtester/backtester-cursor.js.map +1 -1
  8. package/dist/adapter/backtester/backtester-cursor.spec.js +5 -5
  9. package/dist/adapter/backtester/backtester-cursor.spec.js.map +1 -1
  10. package/dist/adapter/backtester/backtester-streamer.spec.d.ts +1 -0
  11. package/dist/adapter/backtester/backtester-streamer.spec.js +45 -0
  12. package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -0
  13. package/dist/bin.d.ts +2 -2
  14. package/dist/bin.js +5 -2
  15. package/dist/bin.js.map +1 -1
  16. package/dist/session/session.d.ts +8 -4
  17. package/dist/session/session.js +16 -9
  18. package/dist/session/session.js.map +1 -1
  19. package/dist/storage/feed.d.ts +7 -4
  20. package/dist/storage/feed.js +21 -0
  21. package/dist/storage/feed.js.map +1 -1
  22. package/dist/storage/index.d.ts +1 -2
  23. package/dist/storage/index.js +1 -2
  24. package/dist/storage/index.js.map +1 -1
  25. package/dist/storage/measurement.d.ts +7 -9
  26. package/dist/storage/measurement.js +25 -0
  27. package/dist/storage/measurement.js.map +1 -1
  28. package/dist/storage/storage.d.ts +23 -0
  29. package/dist/storage/storage.js +48 -0
  30. package/dist/storage/storage.js.map +1 -0
  31. package/dist/store/event/store-candle.event.d.ts +1 -1
  32. package/dist/store/event/store-candle.event.js +31 -3
  33. package/dist/store/event/store-candle.event.js.map +1 -1
  34. package/dist/store/event/store-candle.event.spec.d.ts +1 -0
  35. package/dist/store/event/store-candle.event.spec.js +24 -0
  36. package/dist/store/event/store-candle.event.spec.js.map +1 -0
  37. package/dist/store/event/store-trade.event.spec.js +1 -1
  38. package/dist/store/event/store-trade.event.spec.js.map +1 -1
  39. package/dist/store/store.d.ts +1 -1
  40. package/dist/store/store.state.js.map +1 -1
  41. package/dist/tests/backtester-adapter.spec.js +2 -2
  42. package/dist/tests/backtester-adapter.spec.js.map +1 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/jestconfig.unit.json +2 -1
  45. package/package.json +1 -1
  46. package/src/adapter/backtester/backtester-adapter.ts +0 -2
  47. package/src/adapter/backtester/backtester-cursor.spec.ts +8 -8
  48. package/src/adapter/backtester/backtester-cursor.ts +6 -2
  49. package/src/adapter/backtester/backtester-streamer.spec.ts +53 -0
  50. package/src/bin.ts +7 -3
  51. package/src/session/session-descriptor.ts +3 -10
  52. package/src/session/session.ts +31 -14
  53. package/src/storage/feed.ts +32 -7
  54. package/src/storage/index.ts +1 -2
  55. package/src/storage/measurement.ts +28 -15
  56. package/src/storage/storage.ts +76 -0
  57. package/src/store/event/store-candle.event.spec.ts +32 -0
  58. package/src/store/event/store-candle.event.ts +25 -1
  59. package/src/store/event/store-trade.event.spec.ts +1 -1
  60. package/src/store/store.state.ts +1 -0
  61. package/src/tests/backtester-adapter.spec.ts +3 -3
  62. package/dist/storage/feed.interceptor.d.ts +0 -14
  63. package/dist/storage/feed.interceptor.js +0 -52
  64. package/dist/storage/feed.interceptor.js.map +0 -1
  65. package/dist/storage/in-memory.feed.d.ts +0 -10
  66. package/dist/storage/in-memory.feed.js +0 -30
  67. package/dist/storage/in-memory.feed.js.map +0 -1
  68. package/src/storage/feed.interceptor.ts +0 -92
  69. package/src/storage/in-memory.feed.ts +0 -38
package/src/bin.ts CHANGED
@@ -10,6 +10,7 @@ import { Store } from './store';
10
10
  import { instrumentOf } from './domain';
11
11
  import { Topic, event, handler } from './common/topic';
12
12
  import minimist = require('minimist');
13
+ import { Logger } from './common';
13
14
 
14
15
  export interface IpcCommand {
15
16
  type;
@@ -86,7 +87,7 @@ class ExecutionHandler extends Topic<{ type: string }, ExecutionAccessor> {
86
87
  @handler(IpcBacktestModeCommand)
87
88
  onBacktestMode(command: IpcBacktestModeCommand, accessor: ExecutionAccessor) {
88
89
  return new Promise<void>(async resolve => {
89
- accessor.session = backtest(this.descriptor, {
90
+ const [session, streamer] = backtest(this.descriptor, {
90
91
  from: command.from,
91
92
  to: command.to,
92
93
  balance: command.balance,
@@ -110,9 +111,12 @@ class ExecutionHandler extends Topic<{ type: string }, ExecutionAccessor> {
110
111
  }
111
112
  });
112
113
 
114
+ accessor.session = session;
115
+
113
116
  this.notify({ type: 'backtest:started' });
114
117
 
115
118
  await accessor.session.awake();
119
+ await streamer.tryContinue().catch(it => Logger.error(it));
116
120
  });
117
121
  }
118
122
 
@@ -197,7 +201,7 @@ export async function run(
197
201
  export function backtest(
198
202
  descriptor: SessionDescriptor,
199
203
  options: BacktesterOptions
200
- ): Session {
204
+ ): [Session, BacktesterStreamer] {
201
205
  const store = new Store();
202
206
 
203
207
  const streamer = new BacktesterStreamer(store, descriptor.feed, options);
@@ -208,7 +212,7 @@ export function backtest(
208
212
  )
209
213
  );
210
214
 
211
- return new Session(store, aggregate, descriptor);
215
+ return [new Session(store, aggregate, descriptor), streamer];
212
216
  }
213
217
 
214
218
  export function paper(descriptor: SessionDescriptor, options: PaperOptions): Session {
@@ -8,20 +8,13 @@ import { Observable } from 'rxjs';
8
8
  export interface SessionDescriptor {
9
9
  id: number;
10
10
 
11
- /**
12
- * defines supported adapters by this strategy.
13
- */
11
+ // provides trading adapters.
14
12
  adapter: Adapter[];
15
13
 
16
- /**
17
- * defines input and output feed for backtesting purposes.
18
- */
19
-
14
+ // provides input and output feed for backtesting purposes.
20
15
  feed?: Feed;
21
16
 
22
- /**
23
- * defines measurement storage.
24
- */
17
+ // defines measurement storage.
25
18
  measurement?: Measurement;
26
19
 
27
20
  behaviour?: Behaviour | Behaviour[] | ((session: Session) => Observable<any>);
@@ -3,6 +3,7 @@ import {
3
3
  filter,
4
4
  map,
5
5
  mergeMap,
6
+ share,
6
7
  shareReplay,
7
8
  startWith,
8
9
  switchMap,
@@ -20,13 +21,12 @@ import {
20
21
  OrderState
21
22
  } from '../domain';
22
23
  import { Store } from '../store';
23
- import { from, Observable, Subscription } from 'rxjs';
24
+ import { concat, from, Observable, Subject, Subscription } from 'rxjs';
24
25
  import { Behaviour, CombinedBehaviour, FunctionBehaviour } from '../behaviour';
25
26
  import { AdapterAggregate } from '../adapter/adapter-aggregate';
26
27
  import { Worker } from '../common';
27
28
  import { Trade } from '../domain/trade';
28
29
  import { SessionDescriptor } from './session-descriptor';
29
- import { Measure } from '../storage/measurement';
30
30
  import {
31
31
  AdapterHistoryQuery,
32
32
  AdapterOrderCancelCommand,
@@ -34,12 +34,18 @@ import {
34
34
  AdapterSubscribeCommand
35
35
  } from '../adapter';
36
36
 
37
+ type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
38
+
37
39
  export class Session {
38
40
  private initialized = false;
39
41
  private subscription: Subscription;
40
42
  private behaviour: Behaviour;
41
43
  private worker = new Worker();
42
44
 
45
+ get timestamp(): number {
46
+ return this.store.snapshot.timestamp;
47
+ }
48
+
43
49
  constructor(
44
50
  readonly store: Store,
45
51
  readonly aggregate: AdapterAggregate,
@@ -91,30 +97,41 @@ export class Session {
91
97
  this.behaviour.statement(output);
92
98
  }
93
99
 
94
- useMeasure<T extends Measure>(
95
- params: { key: string; timestamp?: number },
100
+ useMeasure<T extends { timestamp: number }>(
101
+ params: { kind: string; timestamp?: number },
96
102
  defaultValue: T = undefined
97
- ): [Observable<T>, (value: T) => void] {
98
- const query$ = from(
103
+ ): [Observable<T>, (value: Optional<T, 'timestamp'>) => void] {
104
+ const stored$ = from(
99
105
  this.descriptor.measurement.query(this.descriptor.id, {
100
- type: params.key,
101
- timestamp: params.timestamp ?? this.store.snapshot.timestamp,
102
- limit: 1,
103
- direction: 'BACKWARD'
106
+ to: params.timestamp ?? this.timestamp,
107
+ kind: params.kind,
108
+ count: 1
104
109
  })
105
- ).pipe(map(it => (it.length ? (it[0] as T) : defaultValue)));
110
+ ).pipe(
111
+ map(it =>
112
+ it.length ? { timestamp: it[0].timestamp, ...it[0].payload } : defaultValue
113
+ ),
114
+ share()
115
+ );
116
+
117
+ const subject$ = new Subject<T>();
106
118
 
107
119
  const setter = (value: T) => {
120
+ const timestamp = value.timestamp ?? this.timestamp;
121
+ const measure = { timestamp, kind: params.kind, payload: value };
122
+
108
123
  this.worker.enqueue(() =>
109
- this.descriptor.measurement.save(this.descriptor.id, [value])
124
+ this.descriptor.measurement.save(this.descriptor.id, [measure])
110
125
  );
126
+
127
+ subject$.next({ ...value, timestamp });
111
128
  };
112
129
 
113
- return [query$, setter];
130
+ return [concat(stored$, subject$.asObservable()), setter];
114
131
  }
115
132
 
116
133
  useOptimizer(path: string): any {
117
- return 0;
134
+ return undefined;
118
135
  }
119
136
 
120
137
  async subscribe(instrument: Array<InstrumentSelector>): Promise<void> {
@@ -1,13 +1,38 @@
1
1
  import { StoreEvent } from '../store/event';
2
2
  import { InstrumentSelector } from '../domain';
3
- import { timestamp } from '../common';
3
+ import { Storage, StorageQueryOptions } from './storage';
4
4
 
5
- export interface Feed {
6
- read(
5
+ export class Feed {
6
+ constructor(private readonly storage: Storage) {}
7
+
8
+ index(): Promise<Array<string>> {
9
+ return this.storage.index();
10
+ }
11
+
12
+ save(instrument: InstrumentSelector, events: StoreEvent[]): Promise<void> {
13
+ return this.storage.save(
14
+ instrument.toString(),
15
+ events.map(it => ({
16
+ timestamp: it.timestamp,
17
+ kind: it.type,
18
+ json: JSON.stringify(it, (key, value) =>
19
+ key != 'timestamp' && key != 'type' && key != 'instrument' ? value : undefined
20
+ )
21
+ }))
22
+ );
23
+ }
24
+
25
+ async query(
7
26
  instrument: InstrumentSelector,
8
- from: timestamp,
9
- to: timestamp
10
- ): Promise<StoreEvent[]>;
27
+ options: StorageQueryOptions
28
+ ): Promise<StoreEvent[]> {
29
+ const rows = await this.storage.query(instrument.toString(), options);
11
30
 
12
- write(instrument: InstrumentSelector, events: StoreEvent[]): Promise<void>;
31
+ return rows.map(it => ({
32
+ timestamp: it.timestamp,
33
+ type: it.kind,
34
+ instrument,
35
+ ...JSON.parse(it.json)
36
+ }));
37
+ }
13
38
  }
@@ -1,4 +1,3 @@
1
1
  export * from './feed';
2
- export * from './in-memory.feed';
3
- export * from './feed.interceptor';
2
+ export * from './storage';
4
3
  export * from './measurement';
@@ -1,24 +1,37 @@
1
1
  import { timestamp } from '../common';
2
+ import { Storage, StorageQueryOptions } from './storage';
2
3
 
3
4
  export interface Measure {
4
5
  timestamp: timestamp;
5
- type: string;
6
-
7
- [key: string]: any;
6
+ kind: string;
7
+ payload: any;
8
8
  }
9
9
 
10
- export interface Measurement {
11
- index(): Promise<Array<number>>;
10
+ export class Measurement {
11
+ constructor(private readonly storage: Storage) {}
12
+
13
+ async index(): Promise<Array<number>> {
14
+ return (await this.storage.index()).map(it => Number(it));
15
+ }
16
+
17
+ save(session: number, measurements: Measure[]): Promise<void> {
18
+ return this.storage.save(
19
+ session.toString(),
20
+ measurements.map(it => ({
21
+ timestamp: it.timestamp,
22
+ kind: it.kind,
23
+ json: JSON.stringify(it.payload)
24
+ }))
25
+ );
26
+ }
12
27
 
13
- query(
14
- session: number,
15
- options: {
16
- timestamp: timestamp;
17
- type?: string;
18
- limit: number;
19
- direction: 'FORWARD' | 'BACKWARD';
20
- }
21
- ): Promise<Measure[]>;
28
+ async query(session: number, options: StorageQueryOptions): Promise<Measure[]> {
29
+ const rows = await this.storage.query(session.toString(), options);
22
30
 
23
- save(session: number, measurements: Measure[]): Promise<void>;
31
+ return rows.map(it => ({
32
+ timestamp: it.timestamp,
33
+ kind: it.kind,
34
+ payload: JSON.parse(it.json)
35
+ }));
36
+ }
24
37
  }
@@ -0,0 +1,76 @@
1
+ export type StorageDocument = {
2
+ timestamp: number;
3
+ kind: string;
4
+ json: string;
5
+ };
6
+
7
+ export type StorageQueryOptions = {
8
+ from?: number;
9
+ to?: number;
10
+ kind?: string;
11
+ count: number;
12
+ };
13
+
14
+ export interface Storage {
15
+ index(): Promise<Array<string>>;
16
+
17
+ save(library: string, documents: StorageDocument[]): Promise<void>;
18
+
19
+ query(library: string, options: StorageQueryOptions): Promise<StorageDocument[]>;
20
+ }
21
+
22
+ export class InMemoryStorage implements Storage {
23
+ private tables: Record<string, StorageDocument[]> = {};
24
+
25
+ async index(): Promise<Array<string>> {
26
+ return Object.keys(this.tables);
27
+ }
28
+
29
+ async query(library: string, options: StorageQueryOptions): Promise<StorageDocument[]> {
30
+ if (!this.tables[library]) {
31
+ return [];
32
+ }
33
+
34
+ let query = this.tables[library];
35
+
36
+ if (options.from) {
37
+ query = query.filter(it => it.timestamp > options.from);
38
+ }
39
+
40
+ if (options.to) {
41
+ query = query.filter(it => it.timestamp < options.to);
42
+ }
43
+
44
+ if (options.kind) {
45
+ query = query.filter(it => it.kind == options.kind);
46
+ }
47
+
48
+ if (options.from == undefined && options.to) {
49
+ query = query.reverse();
50
+ }
51
+
52
+ if (options.count) {
53
+ query = query.slice(0, options.count);
54
+ }
55
+
56
+ return query;
57
+ }
58
+
59
+ async save(library: string, documents: StorageDocument[]): Promise<void> {
60
+ if (!this.tables[library]) {
61
+ this.tables[library] = [];
62
+ }
63
+
64
+ const buffer = this.tables[library];
65
+
66
+ for (const document of documents) {
67
+ buffer.push(document);
68
+ }
69
+
70
+ buffer.sort((lhs, rhs) => lhs.timestamp - rhs.timestamp);
71
+ }
72
+
73
+ clear() {
74
+ this.tables = {};
75
+ }
76
+ }
@@ -0,0 +1,32 @@
1
+ import { Asset, Instrument } from '../../domain';
2
+ import { CandleEvent, CandleEventHandler } from '.';
3
+ import { State } from '../store.state';
4
+ import { now } from '../../common';
5
+
6
+ const instrument = new Instrument(
7
+ new Asset('btc', 'binance', 8),
8
+ new Asset('usdt', 'binance', 2),
9
+ 'binance:btc-usdt'
10
+ );
11
+
12
+ describe('candle patch event tests', () => {
13
+ test('should patch trade object', () => {
14
+ const timestamp = now();
15
+ const state = new State();
16
+
17
+ state.universe.instrument[instrument.toString()] = instrument;
18
+ state.subscription.instrument[instrument.toString()] = instrument;
19
+
20
+ const event = new CandleEvent(instrument, 1, 1, 1, 1, 1, 1, timestamp);
21
+
22
+ CandleEventHandler(event, state);
23
+
24
+ const trade = state.trade[instrument.toString()];
25
+
26
+ expect(trade.timestamp).toEqual(timestamp);
27
+ expect(trade.instrument.toString()).toEqual(instrument.toString());
28
+ expect(trade.rate).toEqual(1);
29
+ expect(trade.quantity).toEqual(1);
30
+ expect(state.timestamp).toEqual(timestamp);
31
+ });
32
+ });
@@ -1,9 +1,12 @@
1
1
  import { TradePatchEventHandler } from './store-trade.event';
2
+ import { OrderbookPatchEventHandler } from './store-orderbook.event';
2
3
  import { timestamp } from '../../common/datetime';
3
4
  import { InstrumentSelector } from '../../domain';
4
5
  import { State } from '../store.state';
5
6
  import { StoreEvent } from './store.event';
7
+ import { event } from '../../common/topic';
6
8
 
9
+ @event
7
10
  export class CandleEvent implements StoreEvent {
8
11
  type = 'candle';
9
12
 
@@ -20,7 +23,10 @@ export class CandleEvent implements StoreEvent {
20
23
  }
21
24
 
22
25
  export function CandleEventHandler(event: CandleEvent, state: State) {
23
- return TradePatchEventHandler(
26
+ const instrument = state.universe.instrument[event.instrument.toString()];
27
+
28
+ // patch trade object
29
+ const trade = TradePatchEventHandler(
24
30
  {
25
31
  type: 'trade-patch',
26
32
  instrument: event.instrument,
@@ -30,4 +36,22 @@ export function CandleEventHandler(event: CandleEvent, state: State) {
30
36
  },
31
37
  state
32
38
  );
39
+
40
+ // patch orderbook by assuming candle close price is mid orderbook price
41
+ const orderbook = OrderbookPatchEventHandler(
42
+ {
43
+ type: 'orderbook-patch',
44
+ instrument: event.instrument,
45
+ bestAskQuantity: event.volume * 0.5,
46
+ bestAskRate: event.close + instrument.quote.tickSize,
47
+ bestBidQuantity: event.volume * 0.5,
48
+ bestBidRate: event.close - instrument.quote.tickSize,
49
+ timestamp: event.timestamp
50
+ },
51
+ state
52
+ );
53
+
54
+ state.timestamp = event.timestamp;
55
+
56
+ return [trade, orderbook];
33
57
  }
@@ -44,7 +44,7 @@ describe('trade patch event tests', () => {
44
44
  TradePatchEventHandler(new TradePatchEvent(instrument, 2000, 0.2, timestamp), state);
45
45
 
46
46
  expect(trade.timestamp).toEqual(timestamp);
47
- expect(trade.instrument.toString()).toEqual(trade.instrument.toString());
47
+ expect(trade.instrument.toString()).toEqual(instrument.toString());
48
48
  expect(trade.rate).toEqual(2000);
49
49
  expect(trade.quantity).toEqual(0.2);
50
50
  expect(state.timestamp).toEqual(timestamp);
@@ -13,6 +13,7 @@ import {
13
13
  export class State {
14
14
  timestamp: timestamp;
15
15
 
16
+ // all available trasing assets and instruments
16
17
  universe: {
17
18
  asset: Record<string, Asset>;
18
19
  instrument: Record<string, Instrument>;
@@ -1,7 +1,7 @@
1
1
  import { AdapterAwakeCommand } from '../adapter';
2
2
  import { AdapterSubscribeCommand } from '../adapter';
3
3
  import { Asset, Commision, instrumentOf } from '../domain';
4
- import { InMemoryFeed } from '../storage';
4
+ import { InMemoryStorage, Feed } from '../storage';
5
5
  import { Store } from '../store';
6
6
  import { InstrumentPatchEvent, TradePatchEvent } from '../store/event';
7
7
  import { Adapter, AdapterContext } from '../adapter/adapter';
@@ -43,7 +43,7 @@ class DefaultAdapter extends Adapter {
43
43
  const instrument = instrumentOf('binance:btc-usdt');
44
44
  const adapter = new DefaultAdapter();
45
45
  const store = new Store();
46
- const feed = new InMemoryFeed();
46
+ const feed = new Feed(new InMemoryStorage());
47
47
 
48
48
  describe('backtester adapter tests', () => {
49
49
  test('should return proper adapter name and timestamp', () => {
@@ -78,7 +78,7 @@ describe('backtester adapter tests', () => {
78
78
  }
79
79
  });
80
80
 
81
- feed.write(instrument, [new TradePatchEvent(instrument, 100, 10, 1)]);
81
+ feed.save(instrument, [new TradePatchEvent(instrument, 100, 10, 1)]);
82
82
 
83
83
  const sut = new BacktesterAdapter(adapter, streamer);
84
84
 
@@ -1,14 +0,0 @@
1
- import { InstrumentSelector } from '../domain';
2
- import { StoreEvent } from '../store/event';
3
- import { Feed } from './feed';
4
- export declare abstract class FeedInterceptor implements Feed {
5
- private readonly feed;
6
- constructor(feed: Feed);
7
- abstract intercept(instrument: InstrumentSelector, event: StoreEvent): StoreEvent | StoreEvent[];
8
- read(instrument: InstrumentSelector, from: number, to: number): Promise<StoreEvent[]>;
9
- write(instrument: InstrumentSelector, events: StoreEvent[]): Promise<void>;
10
- }
11
- export declare function fromCandle(feed: Feed, options: {
12
- orderbook: boolean;
13
- trade: boolean;
14
- }): Feed;
@@ -1,52 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fromCandle = exports.FeedInterceptor = void 0;
4
- const event_1 = require("../store/event");
5
- class FeedInterceptor {
6
- constructor(feed) {
7
- this.feed = feed;
8
- }
9
- async read(instrument, from, to) {
10
- const output = new Array();
11
- for (const event of await this.feed.read(instrument, from, to)) {
12
- const intercepted = this.intercept(instrument, event);
13
- if (!intercepted) {
14
- continue;
15
- }
16
- if (Array.isArray(intercepted)) {
17
- output.push(...intercepted);
18
- }
19
- else {
20
- output.push(intercepted);
21
- }
22
- }
23
- return output;
24
- }
25
- write(instrument, events) {
26
- return this.feed.write(instrument, events);
27
- }
28
- }
29
- exports.FeedInterceptor = FeedInterceptor;
30
- class FeedCandleInterceptor extends FeedInterceptor {
31
- constructor(feed, options) {
32
- super(feed);
33
- this.options = options;
34
- }
35
- intercept(instrument, event) {
36
- const output = [];
37
- if (event.type == 'candle') {
38
- if (this.options.orderbook) {
39
- output.push(new event_1.OrderbookPatchEvent(instrument, event.close, 0, event.close, 0, event.timestamp));
40
- }
41
- if (this.options.trade) {
42
- output.push(new event_1.TradePatchEvent(event.instrument, event.close, 0, event.timestamp));
43
- }
44
- return output;
45
- }
46
- }
47
- }
48
- function fromCandle(feed, options) {
49
- return new FeedCandleInterceptor(feed, options);
50
- }
51
- exports.fromCandle = fromCandle;
52
- //# sourceMappingURL=feed.interceptor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"feed.interceptor.js","sourceRoot":"","sources":["../../src/storage/feed.interceptor.ts"],"names":[],"mappings":";;;AACA,0CAAkF;AAGlF,MAAsB,eAAe;IACnC,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAG,CAAC;IAO3C,KAAK,CAAC,IAAI,CACR,UAA8B,EAC9B,IAAY,EACZ,EAAU;QAEV,MAAM,MAAM,GAAG,IAAI,KAAK,EAAc,CAAC;QAEvC,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE;YAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAEtD,IAAI,CAAC,WAAW,EAAE;gBAChB,SAAS;aACV;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;gBAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;aAC7B;iBAAM;gBACL,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAC1B;SACF;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,UAA8B,EAAE,MAAoB;QACxD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;CACF;AAnCD,0CAmCC;AAED,MAAM,qBAAsB,SAAQ,eAAe;IACjD,YACE,IAAU,EACO,OAGhB;QAED,KAAK,CAAC,IAAI,CAAC,CAAC;QALK,YAAO,GAAP,OAAO,CAGvB;IAGH,CAAC;IAED,SAAS,CACP,UAA8B,EAC9B,KAAuB;QAEvB,MAAM,MAAM,GAAG,EAAE,CAAC;QAElB,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE;YAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;gBAC1B,MAAM,CAAC,IAAI,CACT,IAAI,2BAAmB,CACrB,UAAU,EACV,KAAK,CAAC,KAAK,EACX,CAAC,EACD,KAAK,CAAC,KAAK,EACX,CAAC,EACD,KAAK,CAAC,SAAS,CAChB,CACF,CAAC;aACH;YAED,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBACtB,MAAM,CAAC,IAAI,CACT,IAAI,uBAAe,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CACvE,CAAC;aACH;YAED,OAAO,MAAM,CAAC;SACf;IACH,CAAC;CACF;AAED,SAAgB,UAAU,CACxB,IAAU,EACV,OAGC;IAED,OAAO,IAAI,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AARD,gCAQC"}
@@ -1,10 +0,0 @@
1
- import { timestamp } from '../common';
2
- import { InstrumentSelector } from '../domain';
3
- import { StoreEvent } from '../store/event';
4
- import { Feed } from '.';
5
- export declare class InMemoryFeed implements Feed {
6
- private data;
7
- read(instrument: InstrumentSelector, from: timestamp, to: timestamp): Promise<StoreEvent[]>;
8
- write(instrument: InstrumentSelector, events: StoreEvent[]): Promise<void>;
9
- clear(): void;
10
- }
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InMemoryFeed = void 0;
4
- class InMemoryFeed {
5
- constructor() {
6
- this.data = {};
7
- }
8
- async read(instrument, from, to) {
9
- if (!this.data[instrument.toString()]) {
10
- return [];
11
- }
12
- return this.data[instrument.toString()]
13
- .filter(it => it.timestamp > from && it.timestamp <= to)
14
- .sort((lhs, rhs) => lhs.timestamp - rhs.timestamp);
15
- }
16
- async write(instrument, events) {
17
- if (!this.data[instrument.toString()]) {
18
- this.data[instrument.toString()] = [];
19
- }
20
- const buffer = this.data[instrument.toString()];
21
- for (const event of events) {
22
- buffer.push(event);
23
- }
24
- }
25
- clear() {
26
- this.data = {};
27
- }
28
- }
29
- exports.InMemoryFeed = InMemoryFeed;
30
- //# sourceMappingURL=in-memory.feed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"in-memory.feed.js","sourceRoot":"","sources":["../../src/storage/in-memory.feed.ts"],"names":[],"mappings":";;;AAKA,MAAa,YAAY;IAAzB;QACU,SAAI,GAAiC,EAAE,CAAC;IA+BlD,CAAC;IA7BC,KAAK,CAAC,IAAI,CACR,UAA8B,EAC9B,IAAe,EACf,EAAa;QAEb,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE;YACrC,OAAO,EAAE,CAAC;SACX;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;aACpC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;aACvD,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,UAA8B,EAAE,MAAoB;QAC9D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE;YACrC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC;SACvC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEhD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACpB;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,CAAC;CACF;AAhCD,oCAgCC"}