@solncebro/market-data-feeder-lib 0.1.0

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 (115) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +60 -0
  3. package/dist/client/dataStaleness.d.ts +18 -0
  4. package/dist/client/dataStaleness.d.ts.map +1 -0
  5. package/dist/client/dataStaleness.js +23 -0
  6. package/dist/client/dataStaleness.js.map +1 -0
  7. package/dist/client/marketDataClient.d.ts +47 -0
  8. package/dist/client/marketDataClient.d.ts.map +1 -0
  9. package/dist/client/marketDataClient.js +262 -0
  10. package/dist/client/marketDataClient.js.map +1 -0
  11. package/dist/client/marketDataClient.types.d.ts +15 -0
  12. package/dist/client/marketDataClient.types.d.ts.map +1 -0
  13. package/dist/client/marketDataClient.types.js +2 -0
  14. package/dist/client/marketDataClient.types.js.map +1 -0
  15. package/dist/client/marketDataSource.types.d.ts +27 -0
  16. package/dist/client/marketDataSource.types.d.ts.map +1 -0
  17. package/dist/client/marketDataSource.types.js +2 -0
  18. package/dist/client/marketDataSource.types.js.map +1 -0
  19. package/dist/client/mirrorStore.d.ts +29 -0
  20. package/dist/client/mirrorStore.d.ts.map +1 -0
  21. package/dist/client/mirrorStore.js +119 -0
  22. package/dist/client/mirrorStore.js.map +1 -0
  23. package/dist/client/mirrorStore.types.d.ts +20 -0
  24. package/dist/client/mirrorStore.types.d.ts.map +1 -0
  25. package/dist/client/mirrorStore.types.js +2 -0
  26. package/dist/client/mirrorStore.types.js.map +1 -0
  27. package/dist/domain/constants.d.ts +12 -0
  28. package/dist/domain/constants.d.ts.map +1 -0
  29. package/dist/domain/constants.js +47 -0
  30. package/dist/domain/constants.js.map +1 -0
  31. package/dist/domain/events.types.d.ts +14 -0
  32. package/dist/domain/events.types.d.ts.map +1 -0
  33. package/dist/domain/events.types.js +2 -0
  34. package/dist/domain/events.types.js.map +1 -0
  35. package/dist/domain/feederSource.types.d.ts +44 -0
  36. package/dist/domain/feederSource.types.d.ts.map +1 -0
  37. package/dist/domain/feederSource.types.js +2 -0
  38. package/dist/domain/feederSource.types.js.map +1 -0
  39. package/dist/domain/managedSource.types.d.ts +13 -0
  40. package/dist/domain/managedSource.types.d.ts.map +1 -0
  41. package/dist/domain/managedSource.types.js +2 -0
  42. package/dist/domain/managedSource.types.js.map +1 -0
  43. package/dist/domain/marketData.types.d.ts +29 -0
  44. package/dist/domain/marketData.types.d.ts.map +1 -0
  45. package/dist/domain/marketData.types.js +2 -0
  46. package/dist/domain/marketData.types.js.map +1 -0
  47. package/dist/domain/snapshot.types.d.ts +10 -0
  48. package/dist/domain/snapshot.types.d.ts.map +1 -0
  49. package/dist/domain/snapshot.types.js +2 -0
  50. package/dist/domain/snapshot.types.js.map +1 -0
  51. package/dist/domain/subscription.types.d.ts +11 -0
  52. package/dist/domain/subscription.types.d.ts.map +1 -0
  53. package/dist/domain/subscription.types.js +2 -0
  54. package/dist/domain/subscription.types.js.map +1 -0
  55. package/dist/embedded/embeddedMarketDataSource.d.ts +29 -0
  56. package/dist/embedded/embeddedMarketDataSource.d.ts.map +1 -0
  57. package/dist/embedded/embeddedMarketDataSource.js +121 -0
  58. package/dist/embedded/embeddedMarketDataSource.js.map +1 -0
  59. package/dist/embedded/embeddedMarketDataSource.types.d.ts +17 -0
  60. package/dist/embedded/embeddedMarketDataSource.types.d.ts.map +1 -0
  61. package/dist/embedded/embeddedMarketDataSource.types.js +2 -0
  62. package/dist/embedded/embeddedMarketDataSource.types.js.map +1 -0
  63. package/dist/index.d.ts +28 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +30 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/protocol/clientMessageValidation.d.ts +3 -0
  68. package/dist/protocol/clientMessageValidation.d.ts.map +1 -0
  69. package/dist/protocol/clientMessageValidation.js +41 -0
  70. package/dist/protocol/clientMessageValidation.js.map +1 -0
  71. package/dist/protocol/codec.d.ts +5 -0
  72. package/dist/protocol/codec.d.ts.map +1 -0
  73. package/dist/protocol/codec.js +40 -0
  74. package/dist/protocol/codec.js.map +1 -0
  75. package/dist/protocol/messages.types.d.ts +65 -0
  76. package/dist/protocol/messages.types.d.ts.map +1 -0
  77. package/dist/protocol/messages.types.js +2 -0
  78. package/dist/protocol/messages.types.js.map +1 -0
  79. package/dist/source/gapRepair.d.ts +15 -0
  80. package/dist/source/gapRepair.d.ts.map +1 -0
  81. package/dist/source/gapRepair.js +40 -0
  82. package/dist/source/gapRepair.js.map +1 -0
  83. package/dist/source/indicators.d.ts +5 -0
  84. package/dist/source/indicators.d.ts.map +1 -0
  85. package/dist/source/indicators.js +21 -0
  86. package/dist/source/indicators.js.map +1 -0
  87. package/dist/source/marketDataManager.d.ts +94 -0
  88. package/dist/source/marketDataManager.d.ts.map +1 -0
  89. package/dist/source/marketDataManager.js +930 -0
  90. package/dist/source/marketDataManager.js.map +1 -0
  91. package/dist/source/massStale.d.ts +10 -0
  92. package/dist/source/massStale.d.ts.map +1 -0
  93. package/dist/source/massStale.js +8 -0
  94. package/dist/source/massStale.js.map +1 -0
  95. package/dist/source/symbolListDelta.d.ts +4 -0
  96. package/dist/source/symbolListDelta.d.ts.map +1 -0
  97. package/dist/source/symbolListDelta.js +9 -0
  98. package/dist/source/symbolListDelta.js.map +1 -0
  99. package/dist/source/symbolListDelta.types.d.ts +10 -0
  100. package/dist/source/symbolListDelta.types.d.ts.map +1 -0
  101. package/dist/source/symbolListDelta.types.js +2 -0
  102. package/dist/source/symbolListDelta.types.js.map +1 -0
  103. package/dist/source/symbolRemovalGuard.d.ts +14 -0
  104. package/dist/source/symbolRemovalGuard.d.ts.map +1 -0
  105. package/dist/source/symbolRemovalGuard.js +19 -0
  106. package/dist/source/symbolRemovalGuard.js.map +1 -0
  107. package/dist/utils/intervalScheduler.d.ts +16 -0
  108. package/dist/utils/intervalScheduler.d.ts.map +1 -0
  109. package/dist/utils/intervalScheduler.js +42 -0
  110. package/dist/utils/intervalScheduler.js.map +1 -0
  111. package/dist/utils/timeout.d.ts +3 -0
  112. package/dist/utils/timeout.d.ts.map +1 -0
  113. package/dist/utils/timeout.js +18 -0
  114. package/dist/utils/timeout.js.map +1 -0
  115. package/package.json +37 -0
@@ -0,0 +1,119 @@
1
+ const ZERO_MA = { ma25: 0, ma50: 0, ma100: 0, ma200: 0 };
2
+ class MirrorStore {
3
+ maxBufferSize;
4
+ klineListBySymbol = new Map();
5
+ maValuesBySymbol = new Map();
6
+ currentKlineBySymbol = new Map();
7
+ volume24hBySymbol = new Map();
8
+ constructor(maxBufferSize) {
9
+ this.maxBufferSize = maxBufferSize;
10
+ }
11
+ applySnapshot(args) {
12
+ for (const entry of args.entryList) {
13
+ this.seedSymbol(entry);
14
+ }
15
+ }
16
+ applySymbolAdded(entry) {
17
+ this.seedSymbol(entry);
18
+ }
19
+ applySymbolRemoved(symbol) {
20
+ this.klineListBySymbol.delete(symbol);
21
+ this.maValuesBySymbol.delete(symbol);
22
+ this.currentKlineBySymbol.delete(symbol);
23
+ this.volume24hBySymbol.delete(symbol);
24
+ }
25
+ retainSymbols(symbolSet) {
26
+ for (const symbol of this.klineListBySymbol.keys()) {
27
+ if (!symbolSet.has(symbol)) {
28
+ this.applySymbolRemoved(symbol);
29
+ }
30
+ }
31
+ }
32
+ applyKlineClosed(args) {
33
+ const didApply = this.applyKlineToBuffer(args.symbol, args.kline);
34
+ if (!didApply) {
35
+ return;
36
+ }
37
+ this.maValuesBySymbol.set(args.symbol, args.maValues);
38
+ this.currentKlineBySymbol.delete(args.symbol);
39
+ }
40
+ applyKlineUpdated(args) {
41
+ const didApply = this.applyKlineToBuffer(args.symbol, args.kline);
42
+ if (!didApply) {
43
+ return;
44
+ }
45
+ this.maValuesBySymbol.set(args.symbol, args.maValues);
46
+ this.currentKlineBySymbol.set(args.symbol, args.kline);
47
+ }
48
+ applyKlineTick(args) {
49
+ const didApply = this.applyKlineToBuffer(args.symbol, args.kline);
50
+ if (!didApply) {
51
+ return;
52
+ }
53
+ this.currentKlineBySymbol.set(args.symbol, args.kline);
54
+ }
55
+ applyVolume24h(args) {
56
+ this.volume24hBySymbol.set(args.symbol, args.volume24hUsdt);
57
+ }
58
+ getKlineList(symbol) {
59
+ return this.klineListBySymbol.get(symbol) ?? [];
60
+ }
61
+ getMaValues(symbol) {
62
+ return this.maValuesBySymbol.get(symbol) ?? ZERO_MA;
63
+ }
64
+ getCurrentKline(symbol) {
65
+ return this.currentKlineBySymbol.get(symbol);
66
+ }
67
+ getSymbolList() {
68
+ return Array.from(this.klineListBySymbol.keys());
69
+ }
70
+ getLastKlineOpenTimestamp(symbol) {
71
+ const klineList = this.klineListBySymbol.get(symbol);
72
+ if (klineList === undefined || klineList.length === 0) {
73
+ return undefined;
74
+ }
75
+ return klineList[klineList.length - 1].openTimestamp;
76
+ }
77
+ getVolume24h(symbol) {
78
+ return this.volume24hBySymbol.get(symbol) ?? Number.POSITIVE_INFINITY;
79
+ }
80
+ seedSymbol(entry) {
81
+ this.klineListBySymbol.set(entry.symbol, entry.klineList.slice(-this.maxBufferSize));
82
+ this.maValuesBySymbol.set(entry.symbol, entry.maValues);
83
+ if (entry.currentKline !== null) {
84
+ this.currentKlineBySymbol.set(entry.symbol, entry.currentKline);
85
+ }
86
+ else {
87
+ this.currentKlineBySymbol.delete(entry.symbol);
88
+ }
89
+ if (entry.volume24hUsdt !== null) {
90
+ this.volume24hBySymbol.set(entry.symbol, entry.volume24hUsdt);
91
+ }
92
+ }
93
+ applyKlineToBuffer(symbol, kline) {
94
+ const existingList = this.klineListBySymbol.get(symbol);
95
+ const klineList = existingList ?? [];
96
+ if (existingList === undefined) {
97
+ this.klineListBySymbol.set(symbol, klineList);
98
+ }
99
+ if (klineList.length === 0) {
100
+ klineList.push(kline);
101
+ return true;
102
+ }
103
+ const lastKline = klineList[klineList.length - 1];
104
+ if (kline.openTimestamp < lastKline.openTimestamp) {
105
+ return false;
106
+ }
107
+ if (kline.openTimestamp === lastKline.openTimestamp) {
108
+ klineList[klineList.length - 1] = kline;
109
+ return true;
110
+ }
111
+ klineList.push(kline);
112
+ if (klineList.length > this.maxBufferSize) {
113
+ klineList.shift();
114
+ }
115
+ return true;
116
+ }
117
+ }
118
+ export { MirrorStore };
119
+ //# sourceMappingURL=mirrorStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirrorStore.js","sourceRoot":"","sources":["../../src/client/mirrorStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Kline, MaValues } from '../domain/marketData.types.js';
2
+ import type { MarketDataSnapshotEntry } from '../domain/snapshot.types.js';
3
+ interface ApplySnapshotArgs {
4
+ entryList: MarketDataSnapshotEntry[];
5
+ }
6
+ interface ApplyKlineWithMaArgs {
7
+ symbol: string;
8
+ kline: Kline;
9
+ maValues: MaValues;
10
+ }
11
+ interface ApplyKlineArgs {
12
+ symbol: string;
13
+ kline: Kline;
14
+ }
15
+ interface ApplyVolume24hArgs {
16
+ symbol: string;
17
+ volume24hUsdt: number;
18
+ }
19
+ export type { ApplyKlineArgs, ApplyKlineWithMaArgs, ApplySnapshotArgs, ApplyVolume24hArgs };
20
+ //# sourceMappingURL=mirrorStore.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirrorStore.types.d.ts","sourceRoot":"","sources":["../../src/client/mirrorStore.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAE3E,UAAU,iBAAiB;IACzB,SAAS,EAAE,uBAAuB,EAAE,CAAC;CACtC;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;CACd;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mirrorStore.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirrorStore.types.js","sourceRoot":"","sources":["../../src/client/mirrorStore.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { ExchangeNameEnum } from '@solncebro/trade-engine';
2
+ import type { KlineInterval } from './marketData.types.js';
3
+ declare const KLINE_BUFFER_SIZE = 499;
4
+ declare const STALENESS_THRESHOLD_MULTIPLIER = 2;
5
+ declare const SYMBOL_LIST_SYNC_INTERVAL_MS = 3600000;
6
+ declare const KLINE_WATCHDOG_GRACE_MS = 180000;
7
+ declare const KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS = 300000;
8
+ declare function resolveIntervalMs(interval: KlineInterval): number;
9
+ declare function resolveBackfillRequestsPerSecond(exchangeName: ExchangeNameEnum): number;
10
+ declare function isKnownInterval(value: string): value is KlineInterval;
11
+ export { KLINE_BUFFER_SIZE, KLINE_WATCHDOG_GRACE_MS, KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS, STALENESS_THRESHOLD_MULTIPLIER, SYMBOL_LIST_SYNC_INTERVAL_MS, isKnownInterval, resolveIntervalMs, resolveBackfillRequestsPerSecond };
12
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/domain/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,QAAA,MAAM,iBAAiB,MAAM,CAAC;AAE9B,QAAA,MAAM,8BAA8B,IAAI,CAAC;AAIzC,QAAA,MAAM,4BAA4B,UAAY,CAAC;AAC/C,QAAA,MAAM,uBAAuB,SAAU,CAAC;AACxC,QAAA,MAAM,mCAAmC,SAAU,CAAC;AA6BpD,iBAAS,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAE1D;AAED,iBAAS,gCAAgC,CAAC,YAAY,EAAE,gBAAgB,GAAG,MAAM,CAIhF;AAED,iBAAS,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE9D;AAED,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,mCAAmC,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,eAAe,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { ExchangeNameEnum } from '@solncebro/trade-engine';
2
+ const KLINE_BUFFER_SIZE = 499;
3
+ const DEFAULT_INTERVAL_MS = 1_800_000;
4
+ const STALENESS_THRESHOLD_MULTIPLIER = 2;
5
+ // Shared by the standalone FeederServer and the embedded adapter: one listing/delisting discovery
6
+ // cadence and one exchange-stream watchdog tuning regardless of the hosting topology.
7
+ const SYMBOL_LIST_SYNC_INTERVAL_MS = 3_600_000;
8
+ const KLINE_WATCHDOG_GRACE_MS = 180_000;
9
+ const KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS = 300_000;
10
+ // Backfill request rate is per-exchange because the two exchanges enforce REST limits differently.
11
+ // Binance USD-M futures uses a per-IP weight budget: REQUEST_WEIGHT 2400/min (live fapi/v1/exchangeInfo),
12
+ // and a klines call at limit=499 costs weight 2 -> the hard ceiling is 2400/60/2 = 20 req/s. We run 16
13
+ // (16*2*60 = 1920 weight/min) to leave headroom for the 30s ticker poll (~160/min), exchangeInfo and
14
+ // watchdog refetches that share the same per-IP budget. Bybit uses per-endpoint IP limits (not a weight
15
+ // budget), where the proven value is 80 req/s.
16
+ const KLINE_BACKFILL_REQUESTS_PER_SECOND_BINANCE = 16;
17
+ const KLINE_BACKFILL_REQUESTS_PER_SECOND_BYBIT = 80;
18
+ const INTERVAL_MS_BY_KEY = {
19
+ '1s': 1_000,
20
+ '1m': 60_000,
21
+ '3m': 180_000,
22
+ '5m': 300_000,
23
+ '15m': 900_000,
24
+ '30m': 1_800_000,
25
+ '1h': 3_600_000,
26
+ '2h': 7_200_000,
27
+ '4h': 14_400_000,
28
+ '6h': 21_600_000,
29
+ '12h': 43_200_000,
30
+ '1d': 86_400_000,
31
+ '3d': 259_200_000,
32
+ '1w': 604_800_000,
33
+ '1M': 2_592_000_000,
34
+ };
35
+ function resolveIntervalMs(interval) {
36
+ return INTERVAL_MS_BY_KEY[interval] ?? DEFAULT_INTERVAL_MS;
37
+ }
38
+ function resolveBackfillRequestsPerSecond(exchangeName) {
39
+ return exchangeName === ExchangeNameEnum.Binance
40
+ ? KLINE_BACKFILL_REQUESTS_PER_SECOND_BINANCE
41
+ : KLINE_BACKFILL_REQUESTS_PER_SECOND_BYBIT;
42
+ }
43
+ function isKnownInterval(value) {
44
+ return Object.prototype.hasOwnProperty.call(INTERVAL_MS_BY_KEY, value);
45
+ }
46
+ export { KLINE_BUFFER_SIZE, KLINE_WATCHDOG_GRACE_MS, KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS, STALENESS_THRESHOLD_MULTIPLIER, SYMBOL_LIST_SYNC_INTERVAL_MS, isKnownInterval, resolveIntervalMs, resolveBackfillRequestsPerSecond };
47
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/domain/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI3D,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,mBAAmB,GAAG,SAAS,CAAC;AACtC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEzC,kGAAkG;AAClG,sFAAsF;AACtF,MAAM,4BAA4B,GAAG,SAAS,CAAC;AAC/C,MAAM,uBAAuB,GAAG,OAAO,CAAC;AACxC,MAAM,mCAAmC,GAAG,OAAO,CAAC;AAEpD,mGAAmG;AACnG,0GAA0G;AAC1G,uGAAuG;AACvG,qGAAqG;AACrG,wGAAwG;AACxG,+CAA+C;AAC/C,MAAM,0CAA0C,GAAG,EAAE,CAAC;AACtD,MAAM,wCAAwC,GAAG,EAAE,CAAC;AAEpD,MAAM,kBAAkB,GAAkC;IACxD,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,aAAa;CACpB,CAAC;AAEF,SAAS,iBAAiB,CAAC,QAAuB;IAChD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,IAAI,mBAAmB,CAAC;AAC7D,CAAC;AAED,SAAS,gCAAgC,CAAC,YAA8B;IACtE,OAAO,YAAY,KAAK,gBAAgB,CAAC,OAAO;QAC9C,CAAC,CAAC,0CAA0C;QAC5C,CAAC,CAAC,wCAAwC,CAAC;AAC/C,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,mCAAmC,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,eAAe,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Kline, MaValues } from './marketData.types.js';
2
+ type KlineWithMaListener = (symbol: string, kline: Kline, maValues: MaValues) => void;
3
+ type KlineTickListener = (symbol: string, kline: Kline) => void;
4
+ type SymbolNameListener = (symbol: string) => void;
5
+ type Volume24hListener = (symbol: string, volume24hUsdt: number) => void;
6
+ type StreamSilenceListener = (silenceMs: number) => void;
7
+ type SourceMassStaleListener = (staleCount: number, symbolCount: number) => void;
8
+ type SymbolSyncAnomalyListener = (deferredCount: number, symbolCount: number) => void;
9
+ type SourceLifecycleListener = () => void;
10
+ type IntervalLoadListener = (symbolCount: number) => void;
11
+ type ConnectionLostListener = (reason: string) => void;
12
+ type ConnectionRestoredListener = () => void;
13
+ export type { ConnectionLostListener, ConnectionRestoredListener, IntervalLoadListener, KlineTickListener, KlineWithMaListener, SourceLifecycleListener, SourceMassStaleListener, StreamSilenceListener, SymbolNameListener, SymbolSyncAnomalyListener, Volume24hListener };
14
+ //# sourceMappingURL=events.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.types.d.ts","sourceRoot":"","sources":["../../src/domain/events.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,KAAK,mBAAmB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AACtF,KAAK,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAChE,KAAK,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AACnD,KAAK,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;AACzE,KAAK,qBAAqB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AACzD,KAAK,uBAAuB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AACjF,KAAK,yBAAyB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AACtF,KAAK,uBAAuB,GAAG,MAAM,IAAI,CAAC;AAC1C,KAAK,oBAAoB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAC1D,KAAK,sBAAsB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AACvD,KAAK,0BAA0B,GAAG,MAAM,IAAI,CAAC;AAE7C,YAAY,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=events.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.types.js","sourceRoot":"","sources":["../../src/domain/events.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import type { Kline, MaValues, StaleSymbolInfo } from './marketData.types.js';
2
+ import type { IntervalLoadListener, KlineTickListener, KlineWithMaListener, SourceLifecycleListener, SourceMassStaleListener, StreamSilenceListener, SymbolNameListener, SymbolSyncAnomalyListener, Volume24hListener } from './events.types.js';
3
+ import type { ManagedSource } from './managedSource.types.js';
4
+ interface StreamLiveness {
5
+ lastInboundAtMs: number;
6
+ silenceMs: number;
7
+ isStreamSilent: boolean;
8
+ }
9
+ interface FeederSource extends ManagedSource {
10
+ getSymbolList: () => string[];
11
+ getKlineList: (symbol: string) => Kline[];
12
+ getMaValues: (symbol: string) => MaValues;
13
+ getCurrentKline: (symbol: string) => Kline | undefined;
14
+ getVolume24h: (symbol: string) => number;
15
+ getIntervalMs: () => number;
16
+ getKlineCount: () => number;
17
+ getSubscriptionCount: () => number;
18
+ getStaleSymbolList: () => StaleSymbolInfo[];
19
+ getLastKlineOpenTimestamp: (symbol: string) => number | undefined;
20
+ getLastUpdateTimestamp: (symbol: string) => number | undefined;
21
+ getStreamLiveness: () => StreamLiveness;
22
+ getFreshSymbolCount: () => number;
23
+ getPersistentStaleCount: () => number;
24
+ on(eventName: 'klineClosed' | 'klineUpdated', listener: KlineWithMaListener): this;
25
+ on(eventName: 'klineUpdatedTick', listener: KlineTickListener): this;
26
+ on(eventName: 'symbolAdded' | 'symbolRemoved' | 'symbolReseeded' | 'symbolReleased' | 'persistentStaleSymbol' | 'persistentStaleRecovered' | 'symbolLoadCompleted' | 'symbolLoadFailed' | 'symbolBackfillStuck' | 'symbolBackfillRecovered', listener: SymbolNameListener): this;
27
+ on(eventName: 'sourceShutdown', listener: SourceLifecycleListener): this;
28
+ on(eventName: 'volume24h', listener: Volume24hListener): this;
29
+ on(eventName: 'streamSilent' | 'streamResumed', listener: StreamSilenceListener): this;
30
+ on(eventName: 'sourceMassStale' | 'sourceMassStaleRecovered', listener: SourceMassStaleListener): this;
31
+ on(eventName: 'symbolSyncAnomaly', listener: SymbolSyncAnomalyListener): this;
32
+ on(eventName: 'intervalLoadStarted' | 'intervalLoadCompleted', listener: IntervalLoadListener): this;
33
+ off(eventName: 'klineClosed' | 'klineUpdated', listener: KlineWithMaListener): this;
34
+ off(eventName: 'klineUpdatedTick', listener: KlineTickListener): this;
35
+ off(eventName: 'symbolAdded' | 'symbolRemoved' | 'symbolReseeded' | 'symbolReleased' | 'persistentStaleSymbol' | 'persistentStaleRecovered' | 'symbolLoadCompleted' | 'symbolLoadFailed' | 'symbolBackfillStuck' | 'symbolBackfillRecovered', listener: SymbolNameListener): this;
36
+ off(eventName: 'sourceShutdown', listener: SourceLifecycleListener): this;
37
+ off(eventName: 'volume24h', listener: Volume24hListener): this;
38
+ off(eventName: 'streamSilent' | 'streamResumed', listener: StreamSilenceListener): this;
39
+ off(eventName: 'sourceMassStale' | 'sourceMassStaleRecovered', listener: SourceMassStaleListener): this;
40
+ off(eventName: 'symbolSyncAnomaly', listener: SymbolSyncAnomalyListener): this;
41
+ off(eventName: 'intervalLoadStarted' | 'intervalLoadCompleted', listener: IntervalLoadListener): this;
42
+ }
43
+ export type { FeederSource, StreamLiveness };
44
+ //# sourceMappingURL=feederSource.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feederSource.types.d.ts","sourceRoot":"","sources":["../../src/domain/feederSource.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=feederSource.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feederSource.types.js","sourceRoot":"","sources":["../../src/domain/feederSource.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { KlineInterval } from './marketData.types.js';
2
+ type SymbolLoadOutcome = 'loaded' | 'alreadyLoaded' | 'notOnExchange' | 'noHistory' | 'aborted';
3
+ interface ManagedSource {
4
+ start: () => void;
5
+ loadAllSymbols: () => Promise<void>;
6
+ ensureSymbolLoaded: (symbol: string) => Promise<SymbolLoadOutcome>;
7
+ releaseSymbol: (symbol: string) => void;
8
+ syncAllSymbols: () => Promise<void>;
9
+ shutdown: () => Promise<void>;
10
+ getInterval: () => KlineInterval;
11
+ }
12
+ export type { ManagedSource, SymbolLoadOutcome };
13
+ //# sourceMappingURL=managedSource.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managedSource.types.d.ts","sourceRoot":"","sources":["../../src/domain/managedSource.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAQ3D,KAAK,iBAAiB,GAAG,QAAQ,GAAG,eAAe,GAAG,eAAe,GAAG,WAAW,GAAG,SAAS,CAAC;AAEhG,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,aAAa,CAAC;CAClC;AAED,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=managedSource.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managedSource.types.js","sourceRoot":"","sources":["../../src/domain/managedSource.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ type KlineInterval = '1s' | '1m' | '3m' | '5m' | '15m' | '30m' | '1h' | '2h' | '4h' | '6h' | '12h' | '1d' | '3d' | '1w' | '1M';
2
+ interface Kline {
3
+ openTimestamp: number;
4
+ openPrice: number;
5
+ highPrice: number;
6
+ lowPrice: number;
7
+ closePrice: number;
8
+ volume: number;
9
+ closeTimestamp: number;
10
+ quoteAssetVolume: number;
11
+ numberOfTrades: number;
12
+ takerBuyBaseAssetVolume: number;
13
+ takerBuyQuoteAssetVolume: number;
14
+ isClosed?: boolean;
15
+ }
16
+ interface MaValues {
17
+ ma25: number;
18
+ ma50: number;
19
+ ma100: number;
20
+ ma200: number;
21
+ ma99?: number | null;
22
+ ma1000?: number | null;
23
+ }
24
+ interface StaleSymbolInfo {
25
+ symbol: string;
26
+ ageMs: number;
27
+ }
28
+ export type { Kline, KlineInterval, MaValues, StaleSymbolInfo };
29
+ //# sourceMappingURL=marketData.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketData.types.d.ts","sourceRoot":"","sources":["../../src/domain/marketData.types.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GACd,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,CAAC;AAET,UAAU,KAAK;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=marketData.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketData.types.js","sourceRoot":"","sources":["../../src/domain/marketData.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { Kline, MaValues } from './marketData.types.js';
2
+ interface MarketDataSnapshotEntry {
3
+ symbol: string;
4
+ klineList: Kline[];
5
+ maValues: MaValues;
6
+ currentKline: Kline | null;
7
+ volume24hUsdt: number | null;
8
+ }
9
+ export type { MarketDataSnapshotEntry };
10
+ //# sourceMappingURL=snapshot.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.types.d.ts","sourceRoot":"","sources":["../../src/domain/snapshot.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,UAAU,uBAAuB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,KAAK,EAAE,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,YAAY,EAAE,uBAAuB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snapshot.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.types.js","sourceRoot":"","sources":["../../src/domain/snapshot.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ interface SubscriptionScopeAll {
2
+ kind: 'all';
3
+ }
4
+ interface SubscriptionScopeSymbols {
5
+ kind: 'symbols';
6
+ symbolList: string[];
7
+ }
8
+ type SubscriptionScope = SubscriptionScopeAll | SubscriptionScopeSymbols;
9
+ type FeedEventName = 'klineClosed' | 'klineUpdated' | 'klineUpdatedTick';
10
+ export type { FeedEventName, SubscriptionScope, SubscriptionScopeAll, SubscriptionScopeSymbols };
11
+ //# sourceMappingURL=subscription.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.types.d.ts","sourceRoot":"","sources":["../../src/domain/subscription.types.ts"],"names":[],"mappings":"AAAA,UAAU,oBAAoB;IAC5B,IAAI,EAAE,KAAK,CAAC;CACb;AAED,UAAU,wBAAwB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,KAAK,iBAAiB,GAAG,oBAAoB,GAAG,wBAAwB,CAAC;AAEzE,KAAK,aAAa,GAAG,aAAa,GAAG,cAAc,GAAG,kBAAkB,CAAC;AAEzE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=subscription.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.types.js","sourceRoot":"","sources":["../../src/domain/subscription.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { Kline, KlineInterval, MaValues, StaleSymbolInfo } from '../domain/marketData.types.js';
3
+ import type { MarketDataSource } from '../client/marketDataSource.types.js';
4
+ import type { CreateEmbeddedMarketDataSourceArgs, EmbeddedMarketDataSourceArgs } from './embeddedMarketDataSource.types.js';
5
+ declare class EmbeddedMarketDataSource extends EventEmitter implements MarketDataSource {
6
+ private readonly source;
7
+ private readonly onNotify;
8
+ private readonly teardownConnection;
9
+ private symbolSyncSchedulerHandle;
10
+ private isShutDown;
11
+ constructor(args: EmbeddedMarketDataSourceArgs);
12
+ waitUntilReady(timeoutMs: number): Promise<void>;
13
+ shutdown(): Promise<void>;
14
+ isStale(): boolean;
15
+ getInterval(): KlineInterval;
16
+ getIntervalMs(): number;
17
+ getMaValues(symbol: string): MaValues;
18
+ getKlineList(symbol: string): Kline[];
19
+ getCurrentKline(symbol: string): Kline | undefined;
20
+ getSymbolList(): string[];
21
+ getLastKlineOpenTimestamp(symbol: string): number | undefined;
22
+ getLastUpdateTimestamp(symbol: string): number | undefined;
23
+ getVolume24h(symbol: string): number;
24
+ getStaleSymbolList(): StaleSymbolInfo[];
25
+ private forwardSourceEvents;
26
+ }
27
+ declare function createEmbeddedMarketDataSource(args: CreateEmbeddedMarketDataSourceArgs): Promise<EmbeddedMarketDataSource>;
28
+ export { EmbeddedMarketDataSource, createEmbeddedMarketDataSource };
29
+ //# sourceMappingURL=embeddedMarketDataSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddedMarketDataSource.d.ts","sourceRoot":"","sources":["../../src/embedded/embeddedMarketDataSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAO5E,OAAO,KAAK,EAAE,kCAAkC,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAK5H,cAAM,wBAAyB,SAAQ,YAAa,YAAW,gBAAgB;IAC7E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAChE,OAAO,CAAC,yBAAyB,CAAwC;IACzE,OAAO,CAAC,UAAU,CAAkB;gBAExB,IAAI,EAAE,4BAA4B;IAQxC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB/B,OAAO,IAAI,OAAO;IAIlB,WAAW,IAAI,aAAa;IAI5B,aAAa,IAAI,MAAM;IAIvB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIrC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE;IAIrC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIlD,aAAa,IAAI,MAAM,EAAE;IAIzB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7D,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI1D,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIpC,kBAAkB,IAAI,eAAe,EAAE;IAIvC,OAAO,CAAC,mBAAmB;CAoB5B;AAED,iBAAe,8BAA8B,CAAC,IAAI,EAAE,kCAAkC,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA6BzH;AAED,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { ExchangeConnector, RateLimitedRequestQueue, logger } from '@solncebro/trade-engine';
3
+ import { KLINE_WATCHDOG_GRACE_MS, KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS, SYMBOL_LIST_SYNC_INTERVAL_MS, resolveBackfillRequestsPerSecond } from '../domain/constants.js';
4
+ import { MarketDataManager } from '../source/marketDataManager.js';
5
+ import { startIntervalScheduler } from '../utils/intervalScheduler.js';
6
+ import { withTimeout } from '../utils/timeout.js';
7
+ // In-process replacement for MarketDataClient: the same MarketDataSource contract served straight
8
+ // from the feeder core, so a single-app host skips the second process, the WS/JSON hop and the
9
+ // client-side mirror copy of every kline buffer.
10
+ class EmbeddedMarketDataSource extends EventEmitter {
11
+ source;
12
+ onNotify;
13
+ teardownConnection;
14
+ symbolSyncSchedulerHandle = null;
15
+ isShutDown = false;
16
+ constructor(args) {
17
+ super();
18
+ this.source = args.source;
19
+ this.onNotify = args.onNotify ?? (() => undefined);
20
+ this.teardownConnection = args.teardownConnection ?? (() => undefined);
21
+ this.forwardSourceEvents();
22
+ }
23
+ async waitUntilReady(timeoutMs) {
24
+ this.source.start();
25
+ await withTimeout(this.source.loadAllSymbols(), timeoutMs, `Embedded market data source failed to load within ${timeoutMs}ms`);
26
+ // The hourly listing/delisting sync lives in FeederServer for the standalone process; embedded,
27
+ // the adapter drives it — otherwise the universe would freeze at its startup composition.
28
+ this.symbolSyncSchedulerHandle = startIntervalScheduler({
29
+ tickHandler: () => this.source.syncAllSymbols(),
30
+ intervalMs: SYMBOL_LIST_SYNC_INTERVAL_MS,
31
+ contextLabel: '[EmbeddedMarketData] symbol list sync failed',
32
+ });
33
+ }
34
+ async shutdown() {
35
+ if (this.isShutDown) {
36
+ return;
37
+ }
38
+ this.isShutDown = true;
39
+ if (this.symbolSyncSchedulerHandle !== null) {
40
+ this.symbolSyncSchedulerHandle.stop();
41
+ this.symbolSyncSchedulerHandle = null;
42
+ }
43
+ await this.source.shutdown();
44
+ await this.teardownConnection();
45
+ this.removeAllListeners();
46
+ }
47
+ isStale() {
48
+ return this.source.getStreamLiveness().isStreamSilent;
49
+ }
50
+ getInterval() {
51
+ return this.source.getInterval();
52
+ }
53
+ getIntervalMs() {
54
+ return this.source.getIntervalMs();
55
+ }
56
+ getMaValues(symbol) {
57
+ return this.source.getMaValues(symbol);
58
+ }
59
+ getKlineList(symbol) {
60
+ return this.source.getKlineList(symbol);
61
+ }
62
+ getCurrentKline(symbol) {
63
+ return this.source.getCurrentKline(symbol);
64
+ }
65
+ getSymbolList() {
66
+ return this.source.getSymbolList();
67
+ }
68
+ getLastKlineOpenTimestamp(symbol) {
69
+ return this.source.getLastKlineOpenTimestamp(symbol);
70
+ }
71
+ getLastUpdateTimestamp(symbol) {
72
+ return this.source.getLastUpdateTimestamp(symbol);
73
+ }
74
+ getVolume24h(symbol) {
75
+ return this.source.getVolume24h(symbol);
76
+ }
77
+ getStaleSymbolList() {
78
+ return this.source.getStaleSymbolList();
79
+ }
80
+ forwardSourceEvents() {
81
+ this.source.on('klineClosed', (symbol, kline, maValues) => this.emit('klineClosed', symbol, kline, maValues));
82
+ this.source.on('klineUpdated', (symbol, kline, maValues) => this.emit('klineUpdated', symbol, kline, maValues));
83
+ this.source.on('klineUpdatedTick', (symbol, kline) => this.emit('klineUpdatedTick', symbol, kline));
84
+ this.source.on('symbolAdded', (symbol) => this.emit('symbolAdded', symbol));
85
+ this.source.on('symbolRemoved', (symbol) => this.emit('symbolRemoved', symbol));
86
+ // Silence of the exchange kline stream is the embedded counterpart of losing the feeder socket:
87
+ // both mean "no market data is flowing", and the shared connectionLost contract lets the host's
88
+ // FeederConnectionGuard freeze trading without knowing which transport it sits on.
89
+ this.source.on('streamSilent', (silenceMs) => this.emit('connectionLost', `exchange kline stream silent for ${Math.round(silenceMs / 1000)}s`));
90
+ this.source.on('streamResumed', () => this.emit('connectionRestored'));
91
+ // Whole-source degradations reach the operator directly (the standalone feeder routes them to
92
+ // its health monitor + Telegram); per-symbol issues stay in the core's own logs — hundreds of
93
+ // symbols would spam the notify channel without the monitor's dedup/batching.
94
+ this.source.on('sourceMassStale', (staleCount, symbolCount) => this.onNotify(`Embedded market data: MASS STALE — ${staleCount}/${symbolCount} symbols without fresh klines`));
95
+ this.source.on('sourceMassStaleRecovered', (staleCount, symbolCount) => this.onNotify(`Embedded market data: mass stale recovered (${staleCount}/${symbolCount} still stale)`));
96
+ this.source.on('symbolSyncAnomaly', (deferredCount, symbolCount) => this.onNotify(`Embedded market data: symbol sync anomaly — exchange list dropped ${deferredCount}/${symbolCount} symbols, removals deferred`));
97
+ }
98
+ }
99
+ async function createEmbeddedMarketDataSource(args) {
100
+ const exchangeConnector = new ExchangeConnector(args.exchangeName, { apiKey: args.exchangeApiKey, secret: args.exchangeSecret }, (message) => logger.warn({ message }, `[EmbeddedMarketData] transport notify: ${message}`), undefined, {
101
+ graceMs: KLINE_WATCHDOG_GRACE_MS,
102
+ recoveryCooldownMs: KLINE_WATCHDOG_RECOVERY_COOLDOWN_MS,
103
+ onStreamStale: (event) => logger.warn({ event }, `[EmbeddedMarketData] kline stream stale [${args.interval}]`),
104
+ onStreamRecovered: (event) => logger.info({ event }, `[EmbeddedMarketData] kline stream recovered [${args.interval}]`),
105
+ onStreamRecoveryFailed: (event) => logger.error({ event }, `[EmbeddedMarketData] kline stream recovery failed [${args.interval}]`),
106
+ });
107
+ await exchangeConnector.initialize();
108
+ const backfillQueue = new RateLimitedRequestQueue({
109
+ rateLimit: resolveBackfillRequestsPerSecond(args.exchangeName),
110
+ intervalMs: 1000,
111
+ loggerLabel: '[EmbeddedMarketData:backfill]',
112
+ });
113
+ const source = new MarketDataManager(exchangeConnector, args.interval, backfillQueue);
114
+ return new EmbeddedMarketDataSource({
115
+ source,
116
+ onNotify: args.onNotify,
117
+ teardownConnection: () => exchangeConnector.disconnect(),
118
+ });
119
+ }
120
+ export { EmbeddedMarketDataSource, createEmbeddedMarketDataSource };
121
+ //# sourceMappingURL=embeddedMarketDataSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddedMarketDataSource.js","sourceRoot":"","sources":["../../src/embedded/embeddedMarketDataSource.ts"],"names":[],"mappings":"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"}