dexbot 1.6.5 → 1.6.6

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 (155) hide show
  1. package/CHANGELOG.md +36 -4
  2. package/README.md +104 -35
  3. package/analysis/README.md +11 -16
  4. package/analysis/account_resolver.ts +1 -11
  5. package/analysis/bot_usage/kibana_bot_queries.ts +1 -1
  6. package/analysis/chain_pool.ts +1 -1
  7. package/analysis/fills_source.ts +0 -6
  8. package/analysis/grid_correction_check.ts +20 -26
  9. package/analysis/resolve_source.ts +1 -1
  10. package/analysis/trade_profitability.ts +2 -5
  11. package/analysis/trend_detection/README.md +1 -3
  12. package/analysis/trend_detection/package.json +1 -1
  13. package/claw/package.json +1 -1
  14. package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
  15. package/claw/runtimes/openclaw-plugin/package.json +1 -1
  16. package/claw/tests/test_claw_mcp_transport.ts +2 -2
  17. package/dist/analysis/account_resolver.d.ts +1 -4
  18. package/dist/analysis/account_resolver.d.ts.map +1 -1
  19. package/dist/analysis/account_resolver.js +1 -1
  20. package/dist/analysis/account_resolver.js.map +1 -1
  21. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -2
  22. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
  23. package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -1
  24. package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
  25. package/dist/analysis/chain_pool.d.ts +1 -3
  26. package/dist/analysis/chain_pool.d.ts.map +1 -1
  27. package/dist/analysis/chain_pool.js +1 -1
  28. package/dist/analysis/chain_pool.js.map +1 -1
  29. package/dist/analysis/fills_source.d.ts +1 -51
  30. package/dist/analysis/fills_source.d.ts.map +1 -1
  31. package/dist/analysis/fills_source.js +1 -1
  32. package/dist/analysis/fills_source.js.map +1 -1
  33. package/dist/analysis/grid_correction_check.d.ts +2 -3
  34. package/dist/analysis/grid_correction_check.d.ts.map +1 -1
  35. package/dist/analysis/grid_correction_check.js +18 -26
  36. package/dist/analysis/grid_correction_check.js.map +1 -1
  37. package/dist/analysis/resolve_source.d.ts +1 -1
  38. package/dist/analysis/resolve_source.d.ts.map +1 -1
  39. package/dist/analysis/trade_profitability.d.ts.map +1 -1
  40. package/dist/analysis/trade_profitability.js +2 -7
  41. package/dist/analysis/trade_profitability.js.map +1 -1
  42. package/dist/dexbot.d.ts.map +1 -1
  43. package/dist/dexbot.js +60 -74
  44. package/dist/dexbot.js.map +1 -1
  45. package/dist/market_adapter/core/kibana_candles.d.ts +1 -15
  46. package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -1
  47. package/dist/market_adapter/core/kibana_candles.js +1 -1
  48. package/dist/market_adapter/core/kibana_candles.js.map +1 -1
  49. package/dist/market_adapter/inputs/fetch_lp_data.d.ts +1 -35
  50. package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
  51. package/dist/market_adapter/inputs/fetch_lp_data.js +10 -54
  52. package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
  53. package/dist/market_adapter/inputs/kibana_feed_source.d.ts +1 -8
  54. package/dist/market_adapter/inputs/kibana_feed_source.d.ts.map +1 -1
  55. package/dist/market_adapter/inputs/kibana_feed_source.js +1 -1
  56. package/dist/market_adapter/inputs/kibana_feed_source.js.map +1 -1
  57. package/dist/market_adapter/inputs/window_cache.d.ts +2 -63
  58. package/dist/market_adapter/inputs/window_cache.d.ts.map +1 -1
  59. package/dist/market_adapter/inputs/window_cache.js +22 -102
  60. package/dist/market_adapter/inputs/window_cache.js.map +1 -1
  61. package/dist/modules/account_bots.d.ts +16 -2
  62. package/dist/modules/account_bots.d.ts.map +1 -1
  63. package/dist/modules/account_bots.js +107 -44
  64. package/dist/modules/account_bots.js.map +1 -1
  65. package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -1
  66. package/dist/modules/bitshares-native/crypto/ecc.browser.js +0 -31
  67. package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -1
  68. package/dist/modules/credit_runtime.d.ts +0 -2
  69. package/dist/modules/credit_runtime.d.ts.map +1 -1
  70. package/dist/modules/credit_runtime.js +1 -10
  71. package/dist/modules/credit_runtime.js.map +1 -1
  72. package/dist/modules/dexbot_class.d.ts +13 -10
  73. package/dist/modules/dexbot_class.d.ts.map +1 -1
  74. package/dist/modules/dexbot_class.js +0 -9
  75. package/dist/modules/dexbot_class.js.map +1 -1
  76. package/dist/modules/dexbot_cow_runtime.d.ts +13 -0
  77. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  78. package/dist/modules/dexbot_cow_runtime.js +13 -1
  79. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  80. package/dist/modules/order/accounting.d.ts +4 -18
  81. package/dist/modules/order/accounting.d.ts.map +1 -1
  82. package/dist/modules/order/accounting.js +4 -34
  83. package/dist/modules/order/accounting.js.map +1 -1
  84. package/dist/modules/order/export.d.ts +9 -12
  85. package/dist/modules/order/export.d.ts.map +1 -1
  86. package/dist/modules/order/export.js +9 -12
  87. package/dist/modules/order/export.js.map +1 -1
  88. package/dist/modules/order/grid.d.ts +35 -40
  89. package/dist/modules/order/grid.d.ts.map +1 -1
  90. package/dist/modules/order/grid.js +43 -43
  91. package/dist/modules/order/grid.js.map +1 -1
  92. package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
  93. package/dist/modules/order/grid_reconcile.js +111 -20
  94. package/dist/modules/order/grid_reconcile.js.map +1 -1
  95. package/dist/modules/order/grid_reconcile_internal.d.ts +5 -3
  96. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  97. package/dist/modules/order/grid_reconcile_internal.js +18 -3
  98. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  99. package/dist/modules/order/manager.d.ts +0 -8
  100. package/dist/modules/order/manager.d.ts.map +1 -1
  101. package/dist/modules/order/manager.js +0 -10
  102. package/dist/modules/order/manager.js.map +1 -1
  103. package/dist/modules/order/utils/order.d.ts +22 -7
  104. package/dist/modules/order/utils/order.d.ts.map +1 -1
  105. package/dist/modules/order/utils/order.js +103 -21
  106. package/dist/modules/order/utils/order.js.map +1 -1
  107. package/dist/modules/order/utils/withPoolRef.d.ts +12 -0
  108. package/dist/modules/order/utils/withPoolRef.d.ts.map +1 -1
  109. package/dist/modules/order/utils/withPoolRef.js +17 -0
  110. package/dist/modules/order/utils/withPoolRef.js.map +1 -1
  111. package/dist/modules/order/working_grid.d.ts +8 -13
  112. package/dist/modules/order/working_grid.d.ts.map +1 -1
  113. package/dist/modules/order/working_grid.js +8 -29
  114. package/dist/modules/order/working_grid.js.map +1 -1
  115. package/dist/scripts/sync-version.js +0 -22
  116. package/dist/scripts/sync-version.js.map +1 -1
  117. package/dist/scripts/update_dist_freshness.d.ts +12 -0
  118. package/dist/scripts/update_dist_freshness.d.ts.map +1 -1
  119. package/dist/scripts/update_dist_freshness.js +30 -1
  120. package/dist/scripts/update_dist_freshness.js.map +1 -1
  121. package/docs/BITSHARES_ONBOARDING.md +9 -6
  122. package/docs/COW_INVARIANTS.md +1 -0
  123. package/docs/DEXBOT_COMPARISON.md +11 -11
  124. package/docs/EVOLUTION.md +8 -7
  125. package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
  126. package/docs/GRID_PRICE_INVARIANT.md +518 -0
  127. package/docs/GRID_RECALCULATION.md +1 -1
  128. package/docs/GRID_RECONCILE.md +60 -39
  129. package/docs/ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md +556 -0
  130. package/docs/README.md +3 -3
  131. package/docs/WORKFLOW.md +12 -6
  132. package/docs/architecture.md +40 -38
  133. package/docs/developer_guide.md +4 -8
  134. package/market_adapter/README.md +16 -12
  135. package/modules/README.md +1 -1
  136. package/package.json +7 -3
  137. package/scripts/README.md +0 -9
  138. package/scripts/reset-settings.sh +1 -1
  139. package/analysis/ama_fitting/package.json +0 -12
  140. package/analysis/analyze_derivatives.ts +0 -320
  141. package/analysis/derivative_chart_generator.ts +0 -874
  142. package/analysis/trend_detection/SIGNAL_DOCUMENTATION.md +0 -403
  143. package/analysis/trend_detection/derivative_analyzer.ts +0 -1059
  144. package/dist/analysis/analyze_derivatives.d.ts +0 -68
  145. package/dist/analysis/analyze_derivatives.d.ts.map +0 -1
  146. package/dist/analysis/analyze_derivatives.js +0 -287
  147. package/dist/analysis/analyze_derivatives.js.map +0 -1
  148. package/dist/analysis/derivative_chart_generator.d.ts +0 -12
  149. package/dist/analysis/derivative_chart_generator.d.ts.map +0 -1
  150. package/dist/analysis/derivative_chart_generator.js +0 -891
  151. package/dist/analysis/derivative_chart_generator.js.map +0 -1
  152. package/dist/analysis/trend_detection/derivative_analyzer.d.ts +0 -248
  153. package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +0 -1
  154. package/dist/analysis/trend_detection/derivative_analyzer.js +0 -910
  155. package/dist/analysis/trend_detection/derivative_analyzer.js.map +0 -1
@@ -1,910 +0,0 @@
1
- 'use strict';
2
- import { roundTo } from '../../modules/order/utils/math.js';
3
- /**
4
- * Derivative Analyzer
5
- *
6
- * Trend detection from the sign (and magnitude) of the slow SMA derivative.
7
- *
8
- * The analyzer intentionally stays narrow:
9
- * - SMA for direction / regime
10
- * - MACD for momentum
11
- * - RSI for exhaustion and counter-trend filtering
12
- */
13
- // ─── Simple Moving Average ───────────────────────────────────────────────────
14
- class SMA {
15
- period;
16
- values;
17
- constructor(period) {
18
- this.period = period;
19
- this.values = [];
20
- }
21
- update(price) {
22
- this.values.push(price);
23
- if (this.values.length > this.period)
24
- this.values.shift();
25
- if (this.values.length < this.period)
26
- return null;
27
- return this.values.reduce((a, b) => a + b, 0) / this.period;
28
- }
29
- isReady() { return this.values.length >= this.period; }
30
- reset(period) { this.period = period; this.values = []; }
31
- }
32
- // ─── Exponential Moving Average ──────────────────────────────────────────────
33
- class EMA {
34
- period;
35
- multiplier;
36
- value;
37
- count;
38
- _sum;
39
- constructor(period) {
40
- this.period = period;
41
- this.multiplier = 2 / (period + 1);
42
- this.value = null;
43
- this.count = 0;
44
- this._sum = 0;
45
- }
46
- update(price) {
47
- this.count++;
48
- if (this.count < this.period) {
49
- this._sum += price;
50
- return null;
51
- }
52
- if (this.count === this.period) {
53
- this._sum += price;
54
- this.value = this._sum / this.period;
55
- return this.value;
56
- }
57
- this.value = price * this.multiplier + this.value * (1 - this.multiplier);
58
- return this.value;
59
- }
60
- isReady() { return this.count >= this.period; }
61
- reset(period) {
62
- this.period = period ?? this.period;
63
- this.multiplier = 2 / (this.period + 1);
64
- this.value = null;
65
- this.count = 0;
66
- this._sum = 0;
67
- }
68
- }
69
- // ─── MACD ─────────────────────────────────────────────────────────────────────
70
- class MACD {
71
- fastPeriod;
72
- slowPeriod;
73
- signalPeriod;
74
- fastEma;
75
- slowEma;
76
- signalEma;
77
- /**
78
- * Moving Average Convergence Divergence
79
- * macdLine = EMA(fast) - EMA(slow)
80
- * signal = EMA(signalPeriod) of macdLine
81
- * histogram = macdLine - signal
82
- */
83
- constructor(fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
84
- this.fastPeriod = fastPeriod;
85
- this.slowPeriod = slowPeriod;
86
- this.signalPeriod = signalPeriod;
87
- this.fastEma = new EMA(fastPeriod);
88
- this.slowEma = new EMA(slowPeriod);
89
- this.signalEma = new EMA(signalPeriod);
90
- }
91
- update(price) {
92
- const fast = this.fastEma.update(price);
93
- const slow = this.slowEma.update(price);
94
- if (fast === null || slow === null)
95
- return null;
96
- const macdLine = fast - slow;
97
- const signal = this.signalEma.update(macdLine);
98
- if (signal === null)
99
- return null;
100
- return { macd: macdLine, signal, histogram: macdLine - signal };
101
- }
102
- isReady() { return this.slowEma.isReady() && this.signalEma.isReady(); }
103
- reset(fastPeriod, slowPeriod, signalPeriod) {
104
- this.fastPeriod = fastPeriod ?? this.fastPeriod;
105
- this.slowPeriod = slowPeriod ?? this.slowPeriod;
106
- this.signalPeriod = signalPeriod ?? this.signalPeriod;
107
- this.fastEma.reset(this.fastPeriod);
108
- this.slowEma.reset(this.slowPeriod);
109
- this.signalEma.reset(this.signalPeriod);
110
- }
111
- }
112
- // ─── RSI ──────────────────────────────────────────────────────────────────────
113
- class RSI {
114
- period;
115
- count;
116
- prevPrice;
117
- avgGain;
118
- avgLoss;
119
- /**
120
- * Relative Strength Index (Wilder smoothing)
121
- * Overbought > 70, Oversold < 30
122
- */
123
- constructor(period = 14) {
124
- this.period = period;
125
- this.count = 0;
126
- this.prevPrice = null;
127
- this.avgGain = 0;
128
- this.avgLoss = 0;
129
- }
130
- update(price) {
131
- if (this.prevPrice === null) {
132
- this.prevPrice = price;
133
- return null;
134
- }
135
- const change = price - this.prevPrice;
136
- this.prevPrice = price;
137
- const gain = change > 0 ? change : 0;
138
- const loss = change < 0 ? -change : 0;
139
- this.count++;
140
- if (this.count < this.period) {
141
- this.avgGain += gain;
142
- this.avgLoss += loss;
143
- return null;
144
- }
145
- if (this.count === this.period) {
146
- this.avgGain = (this.avgGain + gain) / this.period;
147
- this.avgLoss = (this.avgLoss + loss) / this.period;
148
- }
149
- else {
150
- this.avgGain = (this.avgGain * (this.period - 1) + gain) / this.period;
151
- this.avgLoss = (this.avgLoss * (this.period - 1) + loss) / this.period;
152
- }
153
- if (this.avgLoss === 0)
154
- return 100;
155
- return 100 - (100 / (1 + this.avgGain / this.avgLoss));
156
- }
157
- isReady() { return this.count >= this.period; }
158
- reset(period) {
159
- this.period = period ?? this.period;
160
- this.count = 0;
161
- this.prevPrice = null;
162
- this.avgGain = 0;
163
- this.avgLoss = 0;
164
- }
165
- }
166
- class DerivativeAnalyzer {
167
- minBarsForConfirmation;
168
- slowSmaPeriod;
169
- sma;
170
- fastSmaPeriod;
171
- fastSma;
172
- macdConfig;
173
- macd;
174
- currMacd;
175
- prevMacd;
176
- rsiPeriod;
177
- rsi;
178
- currRsi;
179
- prevRsi;
180
- interpConfirmBars;
181
- interpHoldBars;
182
- rsiOverboughtLevel;
183
- rsiOversoldLevel;
184
- rsiBullThreshold;
185
- rsiBearThreshold;
186
- macdMinHist;
187
- // Resolved threshold for the MACD-line gates: falls back to the historical
188
- // 0.02 default only when unset/NaN, so an explicit 0 (strict sign test)
189
- // stays expressible via the API.
190
- macdLineGateThreshold;
191
- fastSmaCommitmentBars;
192
- trendFilterEnabled;
193
- trendFilterMinBars;
194
- momentumGateEnabled;
195
- momentumGateMinBars;
196
- momentumGateRsiZone;
197
- barsInMacdDivergence;
198
- barsInRsiDivergence;
199
- priceRegimeGateEnabled;
200
- priceRegimeMinDistancePct;
201
- prevRawInterp;
202
- barsInRawInterp;
203
- currInterpretation;
204
- currInterpretationRaw;
205
- pendingInterp;
206
- pendingInterpBars;
207
- entryBias;
208
- isBullWeakEntry;
209
- isBullConfirmation;
210
- isLateBullWithoutWeak;
211
- isBearWeakEntry;
212
- isBearConfirmation;
213
- isLateBearWithoutWeak;
214
- bullEntrySetupActive;
215
- bullEntrySetupConfirmed;
216
- bearEntrySetupActive;
217
- bearEntrySetupConfirmed;
218
- prevSma;
219
- currSma;
220
- prevFastSma;
221
- currFastSma;
222
- prevPrice;
223
- currPrice;
224
- prevRawSmaTrend;
225
- barsInSmaTrend;
226
- prevRawFastSmaTrend;
227
- barsInFastSmaTrend;
228
- barsAboveFastSma;
229
- barsBelowFastSma;
230
- updateCount;
231
- constructor(config = {}) {
232
- this.minBarsForConfirmation = config.minBarsForConfirmation || 3;
233
- // SMA (slow)
234
- this.slowSmaPeriod = config.slowSmaPeriod ?? 500;
235
- this.sma = this.slowSmaPeriod ? new SMA(this.slowSmaPeriod) : null;
236
- // SMA (fast)
237
- this.fastSmaPeriod = config.fastSmaPeriod ?? 100;
238
- this.fastSma = this.fastSmaPeriod ? new SMA(this.fastSmaPeriod) : null;
239
- // MACD
240
- this.macdConfig = {
241
- fastPeriod: config.macdFastPeriod ?? 12,
242
- slowPeriod: config.macdSlowPeriod ?? 26,
243
- signalPeriod: config.macdSignalPeriod ?? 9,
244
- };
245
- this.macd = new MACD(this.macdConfig.fastPeriod, this.macdConfig.slowPeriod, this.macdConfig.signalPeriod);
246
- this.currMacd = null;
247
- this.prevMacd = null;
248
- // RSI
249
- this.rsiPeriod = config.rsiPeriod ?? 14;
250
- this.rsi = new RSI(this.rsiPeriod);
251
- this.currRsi = null;
252
- this.prevRsi = null;
253
- // Interpretation state
254
- this.interpConfirmBars = config.interpConfirmBars ?? 3;
255
- this.interpHoldBars = config.interpHoldBars ?? 0;
256
- this.rsiOverboughtLevel = config.rsiOverboughtLevel ?? 70;
257
- this.rsiOversoldLevel = config.rsiOversoldLevel ?? 30;
258
- this.rsiBullThreshold = config.rsiBullThreshold ?? 55;
259
- this.rsiBearThreshold = config.rsiBearThreshold ?? 45;
260
- this.macdMinHist = config.macdMinHist ?? 0;
261
- // Unset/NaN → historical 0.02 gate default; explicit 0 → strict sign test.
262
- // (`this.macdMinHist || 0.02` at the gates made explicit 0 unreachable.)
263
- this.macdLineGateThreshold = config.macdMinHist != null && Number.isFinite(config.macdMinHist)
264
- ? config.macdMinHist
265
- : 0.02;
266
- this.fastSmaCommitmentBars = config.fastSmaCommitmentBars ?? 2;
267
- this.trendFilterEnabled = config.trendFilterEnabled ?? false;
268
- this.trendFilterMinBars = config.trendFilterMinBars ?? 3;
269
- this.momentumGateEnabled = config.momentumGateEnabled ?? false;
270
- this.momentumGateMinBars = config.momentumGateMinBars ?? 3;
271
- this.momentumGateRsiZone = config.momentumGateRsiZone ?? 35;
272
- this.barsInMacdDivergence = 0;
273
- this.barsInRsiDivergence = 0;
274
- this.priceRegimeGateEnabled = config.priceRegimeGateEnabled ?? true;
275
- this.priceRegimeMinDistancePct = config.priceRegimeMinDistancePct ?? 0.35;
276
- this.prevRawInterp = null;
277
- this.barsInRawInterp = 0;
278
- this.currInterpretation = 'NEUTRAL';
279
- this.currInterpretationRaw = 'NEUTRAL';
280
- this.pendingInterp = null;
281
- this.pendingInterpBars = 0;
282
- this.entryBias = 'NONE';
283
- this.isBullWeakEntry = false;
284
- this.isBullConfirmation = false;
285
- this.isLateBullWithoutWeak = false;
286
- this.isBearWeakEntry = false;
287
- this.isBearConfirmation = false;
288
- this.isLateBearWithoutWeak = false;
289
- this.bullEntrySetupActive = false;
290
- this.bullEntrySetupConfirmed = false;
291
- this.bearEntrySetupActive = false;
292
- this.bearEntrySetupConfirmed = false;
293
- // Previous / current SMA values (for derivative)
294
- this.prevSma = null;
295
- this.currSma = null;
296
- this.prevFastSma = null;
297
- this.currFastSma = null;
298
- this.prevPrice = null;
299
- this.currPrice = null;
300
- // Independent trend states
301
- this.prevRawSmaTrend = null;
302
- this.barsInSmaTrend = 0;
303
- this.prevRawFastSmaTrend = null;
304
- this.barsInFastSmaTrend = 0;
305
- this.barsAboveFastSma = 0;
306
- this.barsBelowFastSma = 0;
307
- this.updateCount = 0;
308
- }
309
- update(price, timestamp = null) {
310
- if (!Number.isFinite(price) || price <= 0) {
311
- throw new Error('price must be a positive finite number');
312
- }
313
- // Update current price at the start of the bar (before interpretation)
314
- this.prevPrice = this.currPrice;
315
- this.currPrice = price;
316
- // SMA (slow)
317
- if (this.sma) {
318
- this.prevSma = this.currSma;
319
- this.currSma = this.sma.update(price);
320
- }
321
- // SMA (fast)
322
- if (this.fastSma) {
323
- this.prevFastSma = this.currFastSma;
324
- this.currFastSma = this.fastSma.update(price);
325
- }
326
- // MACD — normalized as % of price so scale is comparable across all price levels
327
- if (this.macd) {
328
- this.prevMacd = this.currMacd;
329
- const raw = this.macd.update(price);
330
- if (raw !== null && price > 0) {
331
- this.currMacd = {
332
- macd: (raw.macd / price) * 100,
333
- signal: (raw.signal / price) * 100,
334
- histogram: (raw.histogram / price) * 100,
335
- };
336
- }
337
- else {
338
- this.currMacd = null;
339
- }
340
- }
341
- // RSI
342
- if (this.rsi) {
343
- this.prevRsi = this.currRsi;
344
- this.currRsi = this.rsi.update(price);
345
- }
346
- // Advance momentum divergence counters (for Momentum Gate optimization)
347
- this._advanceMomentumDivergence();
348
- // Fast-SMA commitment tracking: price vs fast MA position
349
- this._advancePriceFastSmaPosition();
350
- // Interpretation (computed after MACD + RSI are updated)
351
- if (this.macd || this.rsi) {
352
- const prevInterpretation = this.currInterpretation;
353
- this._resetEntryBias();
354
- let rawInterp = this.trendFilterEnabled
355
- ? this._applyTrendFilter(this._computeInterpretation())
356
- : this._computeInterpretation();
357
- // Opt 13 — Post-filter MACD line gate (bull/bear trap suppression)
358
- // The MACD line is the authoritative momentum regime indicator:
359
- // line > threshold → bullish regime; line < -threshold → bearish regime.
360
- // Any signal that contradicts the confirmed regime is suppressed to NEUTRAL.
361
- // This ignores marginal crossings at ~0 and ensures signals only start when
362
- // momentum is clearly confirmed.
363
- if (this.macd && this.currMacd !== null) {
364
- const threshold = this.macdLineGateThreshold;
365
- if ((rawInterp === 'BEAR' || rawInterp === 'BEAR_WEAK') && this.currMacd.macd > -threshold)
366
- rawInterp = 'NEUTRAL';
367
- if ((rawInterp === 'BULL' || rawInterp === 'BULL_WEAK') && this.currMacd.macd < threshold)
368
- rawInterp = 'NEUTRAL';
369
- }
370
- this.currInterpretationRaw = rawInterp;
371
- // BULL/BEAR require confirmation bars; other states are immediate
372
- if (rawInterp === 'BULL' || rawInterp === 'BEAR') {
373
- // Check if fast-SMA commitment is met (required before counting confirmation)
374
- let fastSmaPassesCommitment = true;
375
- if (this.fastSma && this.currFastSma !== null && this.currPrice !== null) {
376
- if (rawInterp === 'BULL') {
377
- fastSmaPassesCommitment = this.barsAboveFastSma >= this.fastSmaCommitmentBars;
378
- }
379
- else if (rawInterp === 'BEAR') {
380
- fastSmaPassesCommitment = this.barsBelowFastSma >= this.fastSmaCommitmentBars;
381
- }
382
- }
383
- // Only count confirmation bars if the fast-SMA commitment passes
384
- if (fastSmaPassesCommitment) {
385
- if (rawInterp === this.prevRawInterp) {
386
- this.barsInRawInterp++;
387
- }
388
- else {
389
- this.prevRawInterp = rawInterp;
390
- this.barsInRawInterp = 1;
391
- }
392
- }
393
- else {
394
- // Commitment not met — reset confirmation counter
395
- this.prevRawInterp = rawInterp === 'BULL' ? 'BEAR' : 'BULL';
396
- this.barsInRawInterp = 0;
397
- }
398
- const confirmed = this.barsInRawInterp >= this.interpConfirmBars
399
- ? rawInterp : 'NEUTRAL';
400
- this._applyWithHysteresis(confirmed);
401
- }
402
- else {
403
- this.prevRawInterp = rawInterp;
404
- this.barsInRawInterp = 0;
405
- this._applyWithHysteresis(rawInterp);
406
- }
407
- this._advanceEntryBias(prevInterpretation);
408
- }
409
- this.updateCount++;
410
- // Update trend states
411
- const smaRaw = this._rawSmaTrend();
412
- const fastSmaRaw = this._rawFastSmaTrend();
413
- this._advanceTrend(smaRaw, 'Sma');
414
- this._advanceTrend(fastSmaRaw, 'FastSma');
415
- const result = this.getAnalysis();
416
- if (timestamp !== null)
417
- result.timestamp = timestamp;
418
- return result;
419
- }
420
- _advanceTrend(raw, key) {
421
- const prevKey = `prevRaw${key}Trend`;
422
- const barsKey = `barsIn${key}Trend`;
423
- if (raw !== this[prevKey]) {
424
- this[prevKey] = raw;
425
- this[barsKey] = 1;
426
- }
427
- else {
428
- this[barsKey]++;
429
- }
430
- }
431
- // ── Derivative signs ───────────────────────────────────────
432
- _rawSmaTrend() {
433
- if (!this.sma || this.prevSma === null || this.currSma === null)
434
- return 'NEUTRAL';
435
- if (this.currSma > this.prevSma)
436
- return 'UP';
437
- if (this.currSma < this.prevSma)
438
- return 'DOWN';
439
- return 'NEUTRAL';
440
- }
441
- _rawFastSmaTrend() {
442
- if (!this.fastSma || this.prevFastSma === null || this.currFastSma === null)
443
- return 'NEUTRAL';
444
- if (this.currFastSma > this.prevFastSma)
445
- return 'UP';
446
- if (this.currFastSma < this.prevFastSma)
447
- return 'DOWN';
448
- return 'NEUTRAL';
449
- }
450
- _advancePriceFastSmaPosition() {
451
- if (!this.fastSma || this.currFastSma === null || this.currPrice === null) {
452
- this.barsAboveFastSma = 0;
453
- this.barsBelowFastSma = 0;
454
- return;
455
- }
456
- if (this.currPrice > this.currFastSma) {
457
- this.barsAboveFastSma++;
458
- this.barsBelowFastSma = 0;
459
- }
460
- else {
461
- this.barsBelowFastSma++;
462
- this.barsAboveFastSma = 0;
463
- }
464
- }
465
- _advanceMomentumDivergence() {
466
- if (!this.momentumGateEnabled || !this.macd || !this.rsi || !this.sma)
467
- return;
468
- if (this.currMacd === null || this.currRsi === null)
469
- return;
470
- const slowDir = this._rawSmaTrend();
471
- if (slowDir === 'NEUTRAL') {
472
- this.barsInMacdDivergence = 0;
473
- this.barsInRsiDivergence = 0;
474
- return;
475
- }
476
- const macdOpposes = (slowDir === 'UP' && this.currMacd.histogram < -this.macdMinHist) ||
477
- (slowDir === 'DOWN' && this.currMacd.histogram > this.macdMinHist);
478
- const rsiOpposes = (slowDir === 'UP' && this.currRsi < this.momentumGateRsiZone) ||
479
- (slowDir === 'DOWN' && this.currRsi > (100 - this.momentumGateRsiZone));
480
- this.barsInMacdDivergence = macdOpposes ? this.barsInMacdDivergence + 1 : 0;
481
- this.barsInRsiDivergence = rsiOpposes ? this.barsInRsiDivergence + 1 : 0;
482
- }
483
- // ── Trend filter ─────────────────────────────────────────
484
- _applyTrendFilter(interp) {
485
- // OB/OS are exit signals — not suppressed by trend direction
486
- if (interp === 'OVERBOUGHT' || interp === 'OVERSOLD')
487
- return interp;
488
- // Compute fast MA direction and sustained bars count
489
- let fastDir, fastBarsInDir;
490
- if (this.fastSma) {
491
- fastDir = this._rawFastSmaTrend();
492
- fastBarsInDir = (fastDir === this.prevRawFastSmaTrend ? this.barsInFastSmaTrend + 1 : 1);
493
- }
494
- else if (this.sma) {
495
- fastDir = this._rawSmaTrend();
496
- fastBarsInDir = (fastDir === this.prevRawSmaTrend ? this.barsInSmaTrend + 1 : 1);
497
- }
498
- else {
499
- return interp;
500
- }
501
- if (fastDir === 'NEUTRAL')
502
- return interp;
503
- // Primary gate: fast MA sustained in opposite direction → suppress to NEUTRAL
504
- let suppressedByTrendFilter = false;
505
- if (fastBarsInDir >= this.trendFilterMinBars) {
506
- if (fastDir === 'UP' && (interp === 'BEAR' || interp === 'BEAR_WEAK')) {
507
- interp = 'NEUTRAL';
508
- suppressedByTrendFilter = true;
509
- }
510
- if (fastDir === 'DOWN' && (interp === 'BULL' || interp === 'BULL_WEAK')) {
511
- interp = 'NEUTRAL';
512
- suppressedByTrendFilter = true;
513
- }
514
- }
515
- // Momentum Gate (Opt 11): if MACD + RSI both diverge from SMA(500) for
516
- // >= momentumGateMinBars, allow signal through as WEAK instead of suppressing to NEUTRAL.
517
- if (suppressedByTrendFilter && this.momentumGateEnabled && this.sma) {
518
- const slowDir = this._rawSmaTrend();
519
- const macdConf = this.barsInMacdDivergence >= this.momentumGateMinBars;
520
- const rsiConf = this.barsInRsiDivergence >= this.momentumGateMinBars;
521
- if (macdConf && rsiConf && slowDir !== 'NEUTRAL') {
522
- if (slowDir === 'UP' && (this.currMacd?.histogram ?? 0) < -this.macdMinHist) {
523
- interp = 'BEAR_WEAK';
524
- }
525
- if (slowDir === 'DOWN' && (this.currMacd?.histogram ?? 0) > this.macdMinHist) {
526
- interp = 'BULL_WEAK';
527
- }
528
- }
529
- }
530
- // Macro regime gate: when fastSMA and SMA(slow) are both present and disagree,
531
- // cap full BULL/BEAR to WEAK — a short-term dip/bounce against the macro trend
532
- // does not warrant a confirmed directional signal.
533
- if (this._violatesMacroDisagreeGate(interp, fastDir)) {
534
- if (interp === 'BULL')
535
- return 'BULL_WEAK';
536
- if (interp === 'BEAR')
537
- return 'BEAR_WEAK';
538
- }
539
- // Fast-SMA commitment gate — price vs fast MA cross-check (N-bar commitment required)
540
- if (this.fastSma && this.currFastSma !== null && this.currPrice !== null) {
541
- if (interp === 'BULL' && this.barsAboveFastSma < this.fastSmaCommitmentBars)
542
- return 'BULL_WEAK';
543
- if (interp === 'BEAR' && this.barsBelowFastSma < this.fastSmaCommitmentBars)
544
- return 'BEAR_WEAK';
545
- }
546
- // Opt 12 — MACD Line & Histogram regime check
547
- if (this.macd && this.currMacd !== null) {
548
- if (interp === 'BULL' && this.currMacd.macd <= 0)
549
- return 'BULL_WEAK';
550
- if (interp === 'BEAR' && this.currMacd.macd >= 0)
551
- return 'BEAR_WEAK';
552
- if (interp === 'BEAR' && this.currMacd.histogram > 0)
553
- return 'BEAR_WEAK';
554
- }
555
- // Macro price regime gate: require a minimum clearance beyond slow SMA.
556
- if (this._violatesPriceRegimeGate(interp))
557
- return 'NEUTRAL';
558
- return interp;
559
- }
560
- // ── Hysteresis ────────────────────────────────────────────
561
- _applyWithHysteresis(newInterp) {
562
- // OB/OS are exit signals — always immediate, bypass hold
563
- if (newInterp === 'OVERBOUGHT' || newInterp === 'OVERSOLD') {
564
- this.currInterpretation = newInterp;
565
- this.pendingInterp = null;
566
- this.pendingInterpBars = 0;
567
- return;
568
- }
569
- const curr = this.currInterpretation;
570
- const isDowngrade = (curr === 'BULL' && newInterp !== 'BULL')
571
- || (curr === 'BEAR' && newInterp !== 'BEAR');
572
- // Hard regime gates define when a confirmed signal is no longer valid at all.
573
- // In those cases hysteresis must not keep a stale BULL/BEAR alive after invalidation.
574
- const hardInvalidation = this._isHardInvalidation(curr);
575
- if (!isDowngrade || this.interpHoldBars <= 0 || hardInvalidation) {
576
- this.currInterpretation = newInterp;
577
- this.pendingInterp = null;
578
- this.pendingInterpBars = 0;
579
- return;
580
- }
581
- // Debounce the downgrade — must hold for interpHoldBars bars
582
- if (newInterp === this.pendingInterp) {
583
- this.pendingInterpBars++;
584
- if (this.pendingInterpBars >= this.interpHoldBars) {
585
- this.currInterpretation = newInterp;
586
- this.pendingInterp = null;
587
- this.pendingInterpBars = 0;
588
- }
589
- }
590
- else {
591
- this.pendingInterp = newInterp;
592
- this.pendingInterpBars = 1;
593
- }
594
- }
595
- _resetEntryBias() {
596
- this.entryBias = 'NONE';
597
- this.isBullWeakEntry = false;
598
- this.isBullConfirmation = false;
599
- this.isLateBullWithoutWeak = false;
600
- this.isBearWeakEntry = false;
601
- this.isBearConfirmation = false;
602
- this.isLateBearWithoutWeak = false;
603
- }
604
- _advanceEntryBias(prevInterpretation) {
605
- const curr = this.currInterpretation;
606
- const slowDir = this._rawSmaTrend();
607
- const fastDir = this.fastSma ? this._rawFastSmaTrend() : slowDir;
608
- const prevBullish = prevInterpretation === 'BULL' || prevInterpretation === 'BULL_WEAK';
609
- const currBullish = curr === 'BULL' || curr === 'BULL_WEAK';
610
- const prevBearish = prevInterpretation === 'BEAR' || prevInterpretation === 'BEAR_WEAK';
611
- const currBearish = curr === 'BEAR' || curr === 'BEAR_WEAK';
612
- const bullMacroAligned = slowDir === 'UP';
613
- const bearMacroAligned = slowDir === 'DOWN';
614
- const bullEntryAligned = bullMacroAligned && fastDir === 'UP';
615
- const bearEntryAligned = bearMacroAligned && fastDir === 'DOWN';
616
- if (!currBullish) {
617
- this.bullEntrySetupActive = false;
618
- this.bullEntrySetupConfirmed = false;
619
- }
620
- // Keep weak bullish states visible on the chart, but do not emit long
621
- // entry events until both slow and fast SMA trends are aligned up.
622
- if (!bullEntryAligned) {
623
- this.bullEntrySetupActive = false;
624
- this.bullEntrySetupConfirmed = false;
625
- }
626
- else if (curr === 'BULL_WEAK' && (!prevBullish || !this.bullEntrySetupActive)) {
627
- this.bullEntrySetupActive = true;
628
- this.bullEntrySetupConfirmed = false;
629
- this.entryBias = 'EARLY_LONG';
630
- this.isBullWeakEntry = true;
631
- return;
632
- }
633
- if (curr === 'BULL' && prevInterpretation !== 'BULL') {
634
- if (this.bullEntrySetupActive && !this.bullEntrySetupConfirmed) {
635
- this.bullEntrySetupConfirmed = true;
636
- this.entryBias = 'CONFIRM_LONG';
637
- this.isBullConfirmation = true;
638
- }
639
- }
640
- if (!currBearish) {
641
- this.bearEntrySetupActive = false;
642
- this.bearEntrySetupConfirmed = false;
643
- }
644
- // Keep weak bearish states visible on the chart, but do not emit short
645
- // entry events until both slow and fast SMA trends are aligned down.
646
- if (!bearEntryAligned) {
647
- this.bearEntrySetupActive = false;
648
- this.bearEntrySetupConfirmed = false;
649
- return;
650
- }
651
- if (curr === 'BEAR_WEAK' && (!prevBearish || !this.bearEntrySetupActive)) {
652
- this.bearEntrySetupActive = true;
653
- this.bearEntrySetupConfirmed = false;
654
- this.entryBias = 'EARLY_SHORT';
655
- this.isBearWeakEntry = true;
656
- return;
657
- }
658
- if (curr === 'BEAR' && prevInterpretation !== 'BEAR') {
659
- if (this.bearEntrySetupActive && !this.bearEntrySetupConfirmed) {
660
- this.bearEntrySetupConfirmed = true;
661
- this.entryBias = 'CONFIRM_SHORT';
662
- this.isBearConfirmation = true;
663
- }
664
- }
665
- }
666
- _isHardInvalidation(interp) {
667
- if (interp !== 'BULL' && interp !== 'BEAR')
668
- return false;
669
- if (this.macd && this.currMacd !== null) {
670
- const threshold = this.macdLineGateThreshold;
671
- if (interp === 'BULL' && this.currMacd.macd < threshold)
672
- return true;
673
- if (interp === 'BEAR' && this.currMacd.macd > -threshold)
674
- return true;
675
- }
676
- if (this._violatesMacroDisagreeGate(interp))
677
- return true;
678
- if (this._violatesPriceRegimeGate(interp))
679
- return true;
680
- return false;
681
- }
682
- _violatesMacroDisagreeGate(interp, fastDirOverride = null) {
683
- if (!this.trendFilterEnabled || !this.fastSma || !this.sma)
684
- return false;
685
- if (interp !== 'BULL' && interp !== 'BEAR')
686
- return false;
687
- const fastDir = fastDirOverride ?? this._rawFastSmaTrend();
688
- const slowDir = this._rawSmaTrend();
689
- const slowBarsInDir = (slowDir === this.prevRawSmaTrend ? this.barsInSmaTrend + 1 : 1);
690
- if (fastDir === 'NEUTRAL' || slowDir === 'NEUTRAL')
691
- return false;
692
- if (slowBarsInDir < this.trendFilterMinBars)
693
- return false;
694
- if (fastDir === slowDir)
695
- return false;
696
- return fastDir !== slowDir;
697
- }
698
- _violatesPriceRegimeGate(interp) {
699
- if (!this.priceRegimeGateEnabled || !this.sma || this.currSma === null || this.currPrice === null) {
700
- return false;
701
- }
702
- if (!['BULL', 'BULL_WEAK', 'BEAR', 'BEAR_WEAK'].includes(interp))
703
- return false;
704
- const distanceMultiplier = this.priceRegimeMinDistancePct / 100;
705
- const bullFloor = this.currSma * (1 + distanceMultiplier);
706
- const bearCeiling = this.currSma * (1 - distanceMultiplier);
707
- if ((interp === 'BULL' || interp === 'BULL_WEAK') && this.currPrice < bullFloor)
708
- return true;
709
- if ((interp === 'BEAR' || interp === 'BEAR_WEAK') && this.currPrice > bearCeiling)
710
- return true;
711
- return false;
712
- }
713
- // ── Interpretation ────────────────────────────────────────
714
- _computeInterpretation() {
715
- const hist = this.currMacd?.histogram ?? null;
716
- const macdLine = this.currMacd?.macd ?? null;
717
- const prevHist = this.prevMacd?.histogram ?? null;
718
- const prevMacdLine = this.prevMacd?.macd ?? null;
719
- const rsi = this.currRsi;
720
- if (hist === null && rsi === null)
721
- return 'NEUTRAL';
722
- // 1. MACD histogram sign with minimum magnitude filter
723
- const histBull = hist !== null && hist > this.macdMinHist;
724
- const histBear = hist !== null && hist < -this.macdMinHist;
725
- // 2. MACD histogram momentum
726
- const histMom = (hist !== null && prevHist !== null) ? hist - prevHist : null;
727
- const histWeakeningBull = histBull && histMom !== null && histMom < 0;
728
- const histWeakeningBear = histBear && histMom !== null && histMom > 0;
729
- // 3. MACD zero-line position
730
- const macdAboveZero = macdLine !== null && macdLine > 0;
731
- const macdBelowZero = macdLine !== null && macdLine < 0;
732
- // 5. MACD line slope — is the MACD line itself rising or falling?
733
- const macdLineSlope = (macdLine !== null && prevMacdLine !== null) ? macdLine - prevMacdLine : null;
734
- const macdLineRising = macdLineSlope !== null && macdLineSlope > 0;
735
- const macdLineFalling = macdLineSlope !== null && macdLineSlope < 0;
736
- // 6. RSI extremes (highest priority — exit signals)
737
- const rsiOverbought = rsi !== null && rsi > this.rsiOverboughtLevel;
738
- const rsiOversold = rsi !== null && rsi < this.rsiOversoldLevel;
739
- // 7. RSI direction — rising or falling?
740
- const rsiSlope = (rsi !== null && this.prevRsi !== null) ? rsi - this.prevRsi : null;
741
- const rsiRising = rsiSlope !== null && rsiSlope > 0;
742
- const rsiFalling = rsiSlope !== null && rsiSlope < 0;
743
- // 8. RSI counter-trend: in opposing zone AND not recovering (direction confirms divergence)
744
- const rsiCounterBull = rsi !== null && rsi < this.rsiBearThreshold && !rsiRising;
745
- const rsiCounterBear = rsi !== null && rsi > this.rsiBullThreshold && !rsiFalling;
746
- // Base signal driven by MACD histogram (RSI no longer hard-gates)
747
- let raw = 'NEUTRAL';
748
- if (histBull)
749
- raw = 'BULL';
750
- if (histBear)
751
- raw = 'BEAR';
752
- // RSI extreme exit — override immediately
753
- if (raw === 'BULL' && rsiOverbought)
754
- return 'OVERBOUGHT';
755
- if (raw === 'BEAR' && rsiOversold)
756
- return 'OVERSOLD';
757
- // Weak conditions:
758
- // histFading: histogram shrinking AND MACD line not supporting (any zero position)
759
- // dualWeak: histogram positive but MACD line still on wrong side of zero AND not recovering
760
- // rsiCounter: RSI in counter-trend territory AND direction confirms (standalone)
761
- //
762
- // Note: histogram = MACD line − Signal line, so macdBelowSignal is always false when
763
- // histBull is true. Signal line crossover is not a valid structural check here.
764
- const histFadingBull = histWeakeningBull && !macdLineRising;
765
- const histFadingBear = histWeakeningBear && !macdLineFalling;
766
- const dualWeakBull = histBull && macdBelowZero && !macdLineRising;
767
- const dualWeakBear = histBear && macdAboveZero && !macdLineFalling;
768
- const bullWeak = histFadingBull || dualWeakBull || rsiCounterBull;
769
- const bearWeak = histFadingBear || dualWeakBear || rsiCounterBear;
770
- if (raw === 'BULL' && bullWeak)
771
- return 'BULL_WEAK';
772
- if (raw === 'BEAR' && bearWeak)
773
- return 'BEAR_WEAK';
774
- return raw;
775
- }
776
- // ── Analysis ───────────────────────────────────────────────
777
- getAnalysis() {
778
- const warmupNeeded = Math.max(this.sma ? this.slowSmaPeriod : 0, this.fastSma ? this.fastSmaPeriod : 0, this.macd ? this.macdConfig.slowPeriod + this.macdConfig.signalPeriod : 0, this.rsi ? this.rsiPeriod + 1 : 0);
779
- if (this.updateCount < warmupNeeded) {
780
- return {
781
- isReady: false,
782
- reason: `Warming up: ${this.updateCount}/${warmupNeeded} candles`,
783
- trend: 'NEUTRAL', confidence: 0, isConfirmed: false,
784
- ...this._emptySignals(),
785
- price: this.currPrice, updateCount: this.updateCount,
786
- };
787
- }
788
- const smaRaw = this._rawSmaTrend();
789
- const fastSmaRaw = this._rawFastSmaTrend();
790
- const smaConf = this._conf(smaRaw, this.barsInSmaTrend);
791
- const fastSmaConf = this._conf(fastSmaRaw, this.barsInFastSmaTrend);
792
- const smaConfirmed = smaRaw !== 'NEUTRAL' && this.barsInSmaTrend >= this.minBarsForConfirmation;
793
- const fastSmaConfirmed = fastSmaRaw !== 'NEUTRAL' && this.barsInFastSmaTrend >= this.minBarsForConfirmation;
794
- // Primary: fastSMA > SMA
795
- const primary = this.fastSma ? fastSmaRaw : smaRaw;
796
- const primConf = this.fastSma ? fastSmaConf : smaConf;
797
- const primConfirm = this.fastSma ? fastSmaConfirmed : smaConfirmed;
798
- return {
799
- isReady: true,
800
- trend: primConfirm ? primary : 'NEUTRAL',
801
- confidence: primConf,
802
- isConfirmed: primConfirm,
803
- rawTrend: primary,
804
- barsInTrend: this.fastSma ? this.barsInFastSmaTrend : this.barsInSmaTrend,
805
- // SMA (slow)
806
- smaRawTrend: smaRaw,
807
- smaTrend: smaConfirmed ? smaRaw : 'NEUTRAL',
808
- smaBarsInTrend: this.barsInSmaTrend,
809
- smaConfidence: smaConf,
810
- // SMA (fast)
811
- fastSmaRawTrend: fastSmaRaw,
812
- fastSmaTrend: fastSmaConfirmed ? fastSmaRaw : 'NEUTRAL',
813
- fastSmaBarsInTrend: this.barsInFastSmaTrend,
814
- fastSmaConfidence: fastSmaConf,
815
- fastSmaValue: this.currFastSma !== null ? roundTo(this.currFastSma, 1e6) : null,
816
- // MACD
817
- macdLine: this.currMacd ? roundTo(this.currMacd.macd, 1e8) : null,
818
- macdSignal: this.currMacd ? roundTo(this.currMacd.signal, 1e8) : null,
819
- macdHistogram: this.currMacd ? roundTo(this.currMacd.histogram, 1e8) : null,
820
- macdTrend: this.currMacd
821
- ? (this.currMacd.histogram > 0 ? 'BULL' : this.currMacd.histogram < 0 ? 'BEAR' : 'NEUTRAL')
822
- : null,
823
- // RSI
824
- rsi: this.currRsi !== null ? roundTo(this.currRsi, 100) : null,
825
- rsiZone: this.currRsi !== null
826
- ? (this.currRsi > this.rsiOverboughtLevel ? 'OVERBOUGHT' : this.currRsi < this.rsiOversoldLevel ? 'OVERSOLD' : 'NEUTRAL')
827
- : null,
828
- // Combined interpretation
829
- interpretation: this.currInterpretation,
830
- interpretationRaw: this.currInterpretationRaw,
831
- interpretationBars: this.barsInRawInterp,
832
- entryBias: this.entryBias,
833
- isBullWeakEntry: this.isBullWeakEntry,
834
- isBullConfirmation: this.isBullConfirmation,
835
- isLateBullWithoutWeak: this.isLateBullWithoutWeak,
836
- isBearWeakEntry: this.isBearWeakEntry,
837
- isBearConfirmation: this.isBearConfirmation,
838
- isLateBearWithoutWeak: this.isLateBearWithoutWeak,
839
- // Values
840
- price: this.currPrice,
841
- slowSma: this.currSma !== null ? roundTo(this.currSma, 1e6) : null,
842
- updateCount: this.updateCount,
843
- };
844
- }
845
- _conf(raw, bars) {
846
- return raw !== 'NEUTRAL' ? Math.min(100, Math.round((bars / 20) * 100)) : 0;
847
- }
848
- _emptySignals() {
849
- return {
850
- smaRawTrend: 'NEUTRAL', smaTrend: 'NEUTRAL', smaBarsInTrend: 0, smaConfidence: 0,
851
- fastSmaRawTrend: 'NEUTRAL', fastSmaTrend: 'NEUTRAL', fastSmaBarsInTrend: 0, fastSmaConfidence: 0, fastSmaValue: null,
852
- slowSma: null,
853
- macdLine: null, macdSignal: null, macdHistogram: null, macdTrend: null,
854
- rsi: null, rsiZone: null,
855
- interpretation: 'NEUTRAL', interpretationRaw: 'NEUTRAL', interpretationBars: 0,
856
- entryBias: 'NONE',
857
- isBullWeakEntry: false,
858
- isBullConfirmation: false,
859
- isLateBullWithoutWeak: false,
860
- isBearWeakEntry: false,
861
- isBearConfirmation: false,
862
- isLateBearWithoutWeak: false,
863
- };
864
- }
865
- reset() {
866
- if (this.sma)
867
- this.sma.reset(this.slowSmaPeriod);
868
- if (this.fastSma)
869
- this.fastSma.reset(this.fastSmaPeriod);
870
- if (this.macd)
871
- this.macd.reset(this.macdConfig.fastPeriod, this.macdConfig.slowPeriod, this.macdConfig.signalPeriod);
872
- if (this.rsi)
873
- this.rsi.reset(this.rsiPeriod);
874
- this.currMacd = null;
875
- this.prevMacd = null;
876
- this.currRsi = null;
877
- this.prevRawInterp = null;
878
- this.barsInRawInterp = 0;
879
- this.currInterpretation = 'NEUTRAL';
880
- this.currInterpretationRaw = 'NEUTRAL';
881
- this.pendingInterp = null;
882
- this.pendingInterpBars = 0;
883
- this.entryBias = 'NONE';
884
- this.isBullWeakEntry = false;
885
- this.isBullConfirmation = false;
886
- this.isLateBullWithoutWeak = false;
887
- this.isBearWeakEntry = false;
888
- this.isBearConfirmation = false;
889
- this.isLateBearWithoutWeak = false;
890
- this.bullEntrySetupActive = false;
891
- this.bullEntrySetupConfirmed = false;
892
- this.bearEntrySetupActive = false;
893
- this.bearEntrySetupConfirmed = false;
894
- this.prevSma = null;
895
- this.currSma = null;
896
- this.prevFastSma = null;
897
- this.currFastSma = null;
898
- this.currPrice = null;
899
- this.prevRawSmaTrend = null;
900
- this.barsInSmaTrend = 0;
901
- this.prevRawFastSmaTrend = null;
902
- this.barsInFastSmaTrend = 0;
903
- this.barsAboveFastSma = 0;
904
- this.barsBelowFastSma = 0;
905
- this.updateCount = 0;
906
- }
907
- getUpdateCount() { return this.updateCount; }
908
- }
909
- export { DerivativeAnalyzer };
910
- //# sourceMappingURL=derivative_analyzer.js.map