@quantform/core 0.3.214 → 0.3.220

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 (103) hide show
  1. package/dist/adapter/paper/model/paper-margin-model.d.ts +2 -2
  2. package/dist/adapter/paper/model/paper-margin-model.js +2 -2
  3. package/dist/adapter/paper/model/paper-margin-model.js.map +1 -1
  4. package/dist/adapter/paper/model/paper-model.d.ts +4 -4
  5. package/dist/adapter/paper/model/paper-model.js +26 -12
  6. package/dist/adapter/paper/model/paper-model.js.map +1 -1
  7. package/dist/adapter/paper/model/paper-spot-model.d.ts +3 -2
  8. package/dist/adapter/paper/model/paper-spot-model.js +2 -2
  9. package/dist/adapter/paper/model/paper-spot-model.js.map +1 -1
  10. package/dist/indicator/atr.d.ts +1 -2
  11. package/dist/indicator/atr.js +4 -1
  12. package/dist/indicator/atr.js.map +1 -1
  13. package/dist/indicator/donchian.d.ts +7 -6
  14. package/dist/indicator/donchian.js +6 -15
  15. package/dist/indicator/donchian.js.map +1 -1
  16. package/dist/indicator/ema.d.ts +1 -10
  17. package/dist/indicator/ema.js +13 -32
  18. package/dist/indicator/ema.js.map +1 -1
  19. package/dist/indicator/ema.spec.js +4 -23
  20. package/dist/indicator/ema.spec.js.map +1 -1
  21. package/dist/indicator/envelope.js +4 -8
  22. package/dist/indicator/envelope.js.map +1 -1
  23. package/dist/indicator/index.d.ts +1 -1
  24. package/dist/indicator/index.js +1 -1
  25. package/dist/indicator/index.js.map +1 -1
  26. package/dist/indicator/macd.js +3 -12
  27. package/dist/indicator/macd.js.map +1 -1
  28. package/dist/indicator/min-max.d.ts +4 -11
  29. package/dist/indicator/min-max.js +12 -29
  30. package/dist/indicator/min-max.js.map +1 -1
  31. package/dist/indicator/rma.d.ts +1 -10
  32. package/dist/indicator/rma.js +13 -32
  33. package/dist/indicator/rma.js.map +1 -1
  34. package/dist/indicator/sma.d.ts +1 -10
  35. package/dist/indicator/sma.js +11 -22
  36. package/dist/indicator/sma.js.map +1 -1
  37. package/dist/indicator/sma.spec.js +1 -1
  38. package/dist/indicator/sma.spec.js.map +1 -1
  39. package/dist/indicator/swma.d.ts +1 -9
  40. package/dist/indicator/swma.js +11 -26
  41. package/dist/indicator/swma.js.map +1 -1
  42. package/dist/indicator/tma.d.ts +1 -2
  43. package/dist/indicator/tma.js +4 -1
  44. package/dist/indicator/tma.js.map +1 -1
  45. package/dist/indicator/tma.spec.js +1 -1
  46. package/dist/indicator/tma.spec.js.map +1 -1
  47. package/dist/indicator/truerange.d.ts +1 -1
  48. package/dist/indicator/truerange.js +3 -1
  49. package/dist/indicator/truerange.js.map +1 -1
  50. package/dist/indicator/truerange.spec.js +2 -2
  51. package/dist/indicator/truerange.spec.js.map +1 -1
  52. package/dist/indicator/window.d.ts +3 -0
  53. package/dist/indicator/window.js +22 -0
  54. package/dist/indicator/window.js.map +1 -0
  55. package/dist/indicator/wma.d.ts +1 -11
  56. package/dist/indicator/wma.js +13 -33
  57. package/dist/indicator/wma.js.map +1 -1
  58. package/dist/indicator/wma.spec.js +1 -1
  59. package/dist/indicator/wma.spec.js.map +1 -1
  60. package/dist/session/session-descriptor.d.ts +0 -1
  61. package/dist/session/session-optimizer.js.map +1 -1
  62. package/dist/session/session.d.ts +4 -4
  63. package/dist/session/session.js +13 -13
  64. package/dist/session/session.js.map +1 -1
  65. package/dist/store/event/store-candle.event.d.ts +2 -0
  66. package/dist/store/event/store-candle.event.js +12 -1
  67. package/dist/store/event/store-candle.event.js.map +1 -1
  68. package/dist/store/store.d.ts +2 -1
  69. package/dist/store/store.js +9 -0
  70. package/dist/store/store.js.map +1 -1
  71. package/dist/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +1 -1
  73. package/src/adapter/paper/model/paper-margin-model.ts +5 -5
  74. package/src/adapter/paper/model/paper-model.ts +35 -18
  75. package/src/adapter/paper/model/paper-spot-model.ts +5 -5
  76. package/src/indicator/atr.ts +9 -4
  77. package/src/indicator/donchian.ts +26 -26
  78. package/src/indicator/ema.spec.ts +4 -23
  79. package/src/indicator/ema.ts +15 -42
  80. package/src/indicator/envelope.ts +8 -14
  81. package/src/indicator/index.ts +1 -1
  82. package/src/indicator/macd.ts +8 -19
  83. package/src/indicator/min-max.ts +15 -37
  84. package/src/indicator/rma.ts +15 -43
  85. package/src/indicator/sma.spec.ts +1 -1
  86. package/src/indicator/sma.ts +13 -29
  87. package/src/indicator/swma.ts +14 -35
  88. package/src/indicator/tma.spec.ts +1 -1
  89. package/src/indicator/tma.ts +9 -4
  90. package/src/indicator/truerange.spec.ts +2 -2
  91. package/src/indicator/truerange.ts +15 -10
  92. package/src/indicator/window.ts +27 -0
  93. package/src/indicator/wma.spec.ts +1 -1
  94. package/src/indicator/wma.ts +16 -44
  95. package/src/session/session-descriptor.ts +0 -2
  96. package/src/session/session-optimizer.ts +1 -1
  97. package/src/session/session.ts +19 -14
  98. package/src/store/event/store-candle.event.ts +15 -0
  99. package/src/store/store.ts +10 -0
  100. package/dist/indicator/window-indicator.d.ts +0 -10
  101. package/dist/indicator/window-indicator.js +0 -28
  102. package/dist/indicator/window-indicator.js.map +0 -1
  103. package/src/indicator/window-indicator.ts +0 -35
@@ -18,10 +18,10 @@ describe('truerange atr tests', () => {
18
18
  ])
19
19
  .pipe(
20
20
  truerange(it => it),
21
- sma(4, it => it)
21
+ sma(4, ([, it]) => it)
22
22
  )
23
23
  .subscribe({
24
- next: it => (value = it.value),
24
+ next: ([, it]) => (value = it),
25
25
  complete: () => {
26
26
  expect(parseFloat(value.toFixed(2))).toBe(42.41);
27
27
  done();
@@ -3,22 +3,27 @@ import { map, share } from 'rxjs/operators';
3
3
  import { Candle } from '../domain';
4
4
 
5
5
  export function truerange<T>(fn: (it: T) => Candle) {
6
- return function(source: Observable<T>): Observable<number> {
6
+ return function (source: Observable<T>): Observable<[T, number]> {
7
7
  let previous;
8
8
 
9
9
  return source.pipe(
10
10
  map(it => {
11
11
  const current = fn(it);
12
12
 
13
- return previous == null
14
- ? current.high - current.low
15
- : Math.max(
16
- Math.max(
17
- current.high - current.low,
18
- Math.abs(current.high - previous.close)
19
- ),
20
- Math.abs(current.low - previous.close)
21
- );
13
+ const value =
14
+ previous == null
15
+ ? current.high - current.low
16
+ : Math.max(
17
+ Math.max(
18
+ current.high - current.low,
19
+ Math.abs(current.high - previous.close)
20
+ ),
21
+ Math.abs(current.low - previous.close)
22
+ );
23
+
24
+ const tuple: [T, number] = [it, value];
25
+
26
+ return tuple;
22
27
  }),
23
28
  share()
24
29
  );
@@ -0,0 +1,27 @@
1
+ import { Observable, share, map } from 'rxjs';
2
+ import { RingBuffer } from './ring-buffer';
3
+
4
+ export function window<T, Y>(length: number, fn: (value: T) => Y) {
5
+ return function (source: Observable<T>): Observable<[T, RingBuffer<Y>, Y, Y]> {
6
+ const buffer = new RingBuffer<Y>(length);
7
+
8
+ return source.pipe(
9
+ map(it => {
10
+ let removed = null;
11
+
12
+ if (buffer.isFull) {
13
+ removed = buffer.peek();
14
+ }
15
+
16
+ const value = fn(it);
17
+
18
+ buffer.enqueue(value);
19
+
20
+ const tuple: [T, RingBuffer<Y>, Y, Y] = [it, buffer, value, removed];
21
+
22
+ return tuple;
23
+ }),
24
+ share()
25
+ );
26
+ };
27
+ }
@@ -8,7 +8,7 @@ describe('wma tests', () => {
8
8
  from([18136.17, 18092.15, 18082.39, 18065.4, 18046.47])
9
9
  .pipe(wma(5, it => it))
10
10
  .subscribe({
11
- next: it => (value = it.value),
11
+ next: ([, it]) => (value = it),
12
12
  complete: () => {
13
13
  expect(parseFloat(value.toFixed(2))).toBe(18070.77);
14
14
  done();
@@ -1,55 +1,27 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { filter, map, share } from 'rxjs/operators';
3
- import { RingBuffer } from './ring-buffer';
4
- import { SMA } from './sma';
5
- import { WindowIndicator } from './window-indicator';
3
+ import { window } from './window';
6
4
 
7
- export class WMA extends WindowIndicator<number> {
8
- private _k = 0;
9
- private _sma: SMA;
10
- private _value: number;
11
-
12
- get value(): number {
13
- return this._value;
14
- }
15
-
16
- constructor(capacity: number) {
17
- super(capacity);
18
-
19
- this._k = 1.0 / capacity;
20
- this._sma = new SMA(capacity);
21
- }
22
-
23
- calculate(added: number, removed: number, buffer: RingBuffer<number>) {
24
- if (!this.isCompleted) {
25
- return;
26
- }
27
-
28
- let norm = 0.0;
29
- let sum = 0.0;
30
-
31
- for (let i = 0; i < this.capacity; i++) {
32
- const weight = (this.capacity - i) * this.capacity;
33
- norm = norm + weight;
34
-
35
- sum = sum + buffer.at(this.capacity - (i + 1)) * weight;
36
- }
5
+ export function wma<T>(length: number, fn: (it: T) => number) {
6
+ return function (source: Observable<T>): Observable<[T, number]> {
7
+ return source.pipe(
8
+ window(length, fn),
9
+ filter(([, buffer]) => buffer.isFull),
10
+ map(([it, buffer]) => {
11
+ let norm = 0.0;
12
+ let sum = 0.0;
37
13
 
38
- this._value = sum / norm;
39
- }
40
- }
14
+ for (let i = 0; i < buffer.capacity; i++) {
15
+ const weight = (buffer.capacity - i) * buffer.capacity;
41
16
 
42
- export function wma<T>(length: number, fn: (it: T) => number) {
43
- return function(source: Observable<T>): Observable<WMA> {
44
- const indicator = new WMA(length);
17
+ norm = norm + weight;
18
+ sum = sum + buffer.at(buffer.capacity - (i + 1)) * weight;
19
+ }
45
20
 
46
- return source.pipe(
47
- filter(it => {
48
- indicator.append(fn(it));
21
+ const tuple: [T, number] = [it, sum / norm];
49
22
 
50
- return indicator.isCompleted;
23
+ return tuple;
51
24
  }),
52
- map(_ => indicator),
53
25
  share()
54
26
  );
55
27
  };
@@ -24,7 +24,5 @@ export interface SessionDescriptor {
24
24
  */
25
25
  measurement?: Measurement;
26
26
 
27
- template?: string;
28
-
29
27
  behaviour?: Behaviour | Behaviour[] | ((session: Session) => Observable<any>);
30
28
  }
@@ -1,5 +1,5 @@
1
1
  export function fit(key: string, generator?: any[]) {
2
- return function(target: any, propertyKey: string) {
2
+ return function (target: any, propertyKey: string) {
3
3
  let defaultSetterValue;
4
4
 
5
5
  if (generator) {
@@ -83,33 +83,38 @@ export class Session {
83
83
  await this.worker.wait();
84
84
  }
85
85
 
86
- save(...measure: Measure[]) {
87
- if (!this.descriptor?.measurement) {
86
+ statement(output: Record<string, any>) {
87
+ if (!this.behaviour?.statement) {
88
88
  return;
89
89
  }
90
90
 
91
- this.worker.enqueue(() =>
92
- this.descriptor.measurement.save(this.descriptor.id, measure)
93
- );
91
+ this.behaviour.statement(output);
94
92
  }
95
93
 
96
- query(params: { type: string; timestamp?: number }): Observable<Measure> {
97
- return from(
94
+ useMeasure<T extends Measure>(
95
+ params: { type: string; timestamp?: number },
96
+ defaultValue: T = undefined
97
+ ) {
98
+ const query$ = from(
98
99
  this.descriptor.measurement.query(this.descriptor.id, {
99
100
  type: params.type,
100
101
  timestamp: params.timestamp ?? this.store.snapshot.timestamp,
101
102
  limit: 1,
102
103
  direction: 'BACKWARD'
103
104
  })
104
- ).pipe(map(it => it[0]));
105
- }
105
+ ).pipe(map(it => (it.length ? (it[0] as T) : defaultValue)));
106
106
 
107
- statement(output: Record<string, any>) {
108
- if (!this.behaviour?.statement) {
109
- return;
110
- }
107
+ const setter = (value: T) => {
108
+ this.worker.enqueue(() =>
109
+ this.descriptor.measurement.save(this.descriptor.id, [value])
110
+ );
111
+ };
111
112
 
112
- this.behaviour.statement(output);
113
+ return [query$, setter];
114
+ }
115
+
116
+ useOptimizer(path: string): any {
117
+ return 0;
113
118
  }
114
119
 
115
120
  async subscribe(instrument: Array<InstrumentSelector>): Promise<void> {
@@ -1,5 +1,7 @@
1
+ import { TradePatchEventHandler } from './store-trade.event';
1
2
  import { timestamp } from '../../common/datetime';
2
3
  import { InstrumentSelector } from '../../domain';
4
+ import { State } from '../store.state';
3
5
  import { StoreEvent } from './store.event';
4
6
 
5
7
  export class CandleEvent implements StoreEvent {
@@ -16,3 +18,16 @@ export class CandleEvent implements StoreEvent {
16
18
  readonly timestamp: timestamp
17
19
  ) {}
18
20
  }
21
+
22
+ export function CandleEventHandler(event: CandleEvent, state: State) {
23
+ return TradePatchEventHandler(
24
+ {
25
+ type: 'trade-patch',
26
+ instrument: event.instrument,
27
+ quantity: event.volume,
28
+ rate: event.close,
29
+ timestamp: event.timestamp
30
+ },
31
+ state
32
+ );
33
+ }
@@ -14,6 +14,8 @@ import {
14
14
  BalanceTransactEventHandler,
15
15
  BalanceUnfreezEvent,
16
16
  BalanceUnfreezEventHandler,
17
+ CandleEvent,
18
+ CandleEventHandler,
17
19
  InstrumentPatchEvent,
18
20
  InstrumentPatchEventHandler,
19
21
  InstrumentSubscriptionEvent,
@@ -222,4 +224,12 @@ export class Store extends Topic<StoreEvent, any> {
222
224
  onTradePatch(event: TradePatchEvent) {
223
225
  return TradePatchEventHandler(event, this.snapshot);
224
226
  }
227
+
228
+ /**
229
+ * @see CandleEventHandler
230
+ */
231
+ @handler(CandleEvent)
232
+ onCandle(event: CandleEvent) {
233
+ return CandleEventHandler(event, this.snapshot);
234
+ }
225
235
  }
@@ -1,10 +0,0 @@
1
- import { RingBuffer } from './ring-buffer';
2
- export declare abstract class WindowIndicator<T> {
3
- private _buffer;
4
- get capacity(): number;
5
- get size(): number;
6
- get isCompleted(): boolean;
7
- constructor(capacity: number);
8
- abstract calculate(added: T, removed: T, buffer: RingBuffer<T>): any;
9
- append(value: T): void;
10
- }
@@ -1,28 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WindowIndicator = void 0;
4
- const ring_buffer_1 = require("./ring-buffer");
5
- class WindowIndicator {
6
- constructor(capacity) {
7
- this._buffer = new ring_buffer_1.RingBuffer(capacity);
8
- }
9
- get capacity() {
10
- return this._buffer.capacity;
11
- }
12
- get size() {
13
- return this._buffer.size;
14
- }
15
- get isCompleted() {
16
- return this._buffer.isFull;
17
- }
18
- append(value) {
19
- let removed = null;
20
- if (this.isCompleted) {
21
- removed = this._buffer.peek();
22
- }
23
- this._buffer.enqueue(value);
24
- this.calculate(value, removed, this._buffer);
25
- }
26
- }
27
- exports.WindowIndicator = WindowIndicator;
28
- //# sourceMappingURL=window-indicator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"window-indicator.js","sourceRoot":"","sources":["../../src/indicator/window-indicator.ts"],"names":[],"mappings":";;;AAAA,+CAA2C;AAE3C,MAAsB,eAAe;IAenC,YAAY,QAAgB;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,wBAAU,CAAI,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAdD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAQM,MAAM,CAAC,KAAQ;QACpB,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;SAC/B;QAED,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAE5B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;CACF;AAhCD,0CAgCC"}
@@ -1,35 +0,0 @@
1
- import { RingBuffer } from './ring-buffer';
2
-
3
- export abstract class WindowIndicator<T> {
4
- private _buffer: RingBuffer<T>;
5
-
6
- get capacity(): number {
7
- return this._buffer.capacity;
8
- }
9
-
10
- get size(): number {
11
- return this._buffer.size;
12
- }
13
-
14
- get isCompleted(): boolean {
15
- return this._buffer.isFull;
16
- }
17
-
18
- constructor(capacity: number) {
19
- this._buffer = new RingBuffer<T>(capacity);
20
- }
21
-
22
- abstract calculate(added: T, removed: T, buffer: RingBuffer<T>);
23
-
24
- public append(value: T) {
25
- let removed = null;
26
-
27
- if (this.isCompleted) {
28
- removed = this._buffer.peek();
29
- }
30
-
31
- this._buffer.enqueue(value);
32
-
33
- this.calculate(value, removed, this._buffer);
34
- }
35
- }