@tradejs/core 2.0.15 → 2.0.17
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.
- package/dist/{chunk-HVCNGDPT.mjs → chunk-NN7Z3GIK.mjs} +437 -391
- package/dist/{indicators-Da_i06-8.d.mts → indicators-C4AaiFrs.d.mts} +1 -0
- package/dist/{indicators-Da_i06-8.d.ts → indicators-C4AaiFrs.d.ts} +1 -0
- package/dist/indicators.d.mts +1 -1
- package/dist/indicators.d.ts +1 -1
- package/dist/indicators.js +437 -391
- package/dist/indicators.mjs +1 -1
- package/dist/strategies.d.mts +1 -1
- package/dist/strategies.d.ts +1 -1
- package/dist/strategies.js +481 -504
- package/dist/strategies.mjs +47 -126
- package/package.json +2 -2
package/dist/strategies.js
CHANGED
|
@@ -7982,19 +7982,9 @@ var buildBaseContextSnapshot = ({
|
|
|
7982
7982
|
const btcCloseSeries = fullBtcCloseSeries.slice(-BASE_CONTEXT_CANDLE_WINDOW);
|
|
7983
7983
|
const atr2 = toNullable(baseResult.atr);
|
|
7984
7984
|
const bbWidthPct = baseResult.bbUpper != null && baseResult.bbLower != null && baseResult.bbMiddle != null && baseResult.bbMiddle !== 0 ? (baseResult.bbUpper - baseResult.bbLower) / baseResult.bbMiddle * 100 : null;
|
|
7985
|
-
const atrPctSeries = materializeNumericHistory(
|
|
7986
|
-
indicatorHistory.atrPct ?? createNumericHistoryBuffer()
|
|
7987
|
-
);
|
|
7988
|
-
const macdHistogramSeries = materializeNumericHistory(
|
|
7989
|
-
indicatorHistory.macdHistogram ?? createNumericHistoryBuffer()
|
|
7990
|
-
);
|
|
7991
|
-
const spreadSeries = materializeNumericHistory(
|
|
7992
|
-
indicatorHistory.spread ?? createNumericHistoryBuffer()
|
|
7993
|
-
);
|
|
7994
7985
|
const recent20 = candlesHistory.slice(-20);
|
|
7995
7986
|
const prior20 = candlesHistory.slice(-21, -1);
|
|
7996
7987
|
const structureWindow = candlesHistory.slice(-STRUCTURE_LOOKBACK);
|
|
7997
|
-
const session = buildSessionContext(candle.timestamp);
|
|
7998
7988
|
const recent20High = recent20.length > 0 ? Math.max(...recent20.map((item) => item.high)) : null;
|
|
7999
7989
|
const recent20Low = recent20.length > 0 ? Math.min(...recent20.map((item) => item.low)) : null;
|
|
8000
7990
|
const avgVolume20 = recent20.length > 0 ? recent20.reduce((sum2, item) => sum2 + item.volume, 0) / recent20.length : null;
|
|
@@ -8023,38 +8013,7 @@ var buildBaseContextSnapshot = ({
|
|
|
8023
8013
|
);
|
|
8024
8014
|
const maStackScore = baseResult.maFast == null || baseResult.maMedium == null || baseResult.maSlow == null ? null : Math.sign(baseResult.maFast - baseResult.maMedium) + Math.sign(baseResult.maMedium - baseResult.maSlow);
|
|
8025
8015
|
const trendBias = maStackScore == null ? "neutral" : maStackScore > 0 ? "bull" : maStackScore < 0 ? "bear" : "neutral";
|
|
8026
|
-
const persistenceWindow = closeSeries.slice(-10);
|
|
8027
|
-
const directionalMoves = persistenceWindow.slice(1).map((value, index) => value - persistenceWindow[index]);
|
|
8028
|
-
const persistence = directionalMoves.length === 0 ? null : directionalMoves.filter(
|
|
8029
|
-
(delta) => trendBias === "bull" ? delta > 0 : trendBias === "bear" ? delta < 0 : delta === 0
|
|
8030
|
-
).length / directionalMoves.length;
|
|
8031
|
-
const atrPctZScore = calculateZScore(
|
|
8032
|
-
atrPctSeries,
|
|
8033
|
-
toNullable(baseResult.atrPct)
|
|
8034
|
-
);
|
|
8035
|
-
const atrSlope = calculateLineSlope(atrPctSeries, 5);
|
|
8036
|
-
const compressionScore = safeDivide(
|
|
8037
|
-
toNullable(baseResult.atrPct),
|
|
8038
|
-
getLastFiniteValue(atrPctSeries.slice(0, -1))
|
|
8039
|
-
);
|
|
8040
|
-
const expansionScore = compressionScore == null || compressionScore === 0 ? null : 1 / compressionScore;
|
|
8041
|
-
const bbWidthPctSeries = calculateRecentBbWidthPctSeries(closeSeries, 100);
|
|
8042
|
-
const rawAtrPctSeries = calculateRecentAtrPctSeries(candlesHistory, 100);
|
|
8043
|
-
const rawAtrPct = safeDivide(atr2, candle.close);
|
|
8044
|
-
const realizedVolatility = calculateRealizedVolatility(closeSeries);
|
|
8045
|
-
const realizedVolatilitySeries = calculateRecentRealizedVolatilitySeries(
|
|
8046
|
-
closeSeries,
|
|
8047
|
-
100
|
|
8048
|
-
);
|
|
8049
|
-
const rangeExpansionSeries = calculateRecentRangeExpansionSeries(
|
|
8050
|
-
candlesHistory,
|
|
8051
|
-
20
|
|
8052
|
-
);
|
|
8053
|
-
const rangeExpansion = rangeExpansionSeries[rangeExpansionSeries.length - 1] ?? null;
|
|
8054
|
-
const volatilityState = compressionScore == null ? "unknown" : compressionScore <= 0.9 ? "compressed" : compressionScore >= 1.1 ? "expanded" : "normal";
|
|
8055
8016
|
const highLowRange = candle.high - candle.low;
|
|
8056
|
-
const bodyStrength = highLowRange > 0 ? Math.abs(candle.close - candle.open) / highLowRange : null;
|
|
8057
|
-
const closeLocationInRange = highLowRange > 0 ? (candle.close - candle.low) / highLowRange : null;
|
|
8058
8017
|
const breakoutState = baseResult.highLevel == null || baseResult.lowLevel == null ? "unknown" : candle.close > baseResult.highLevel ? prevCandle != null && prevCandle.close <= baseResult.highLevel ? "above_high_level" : "failed_high_breakout" : candle.close < baseResult.lowLevel ? prevCandle != null && prevCandle.close >= baseResult.lowLevel ? "below_low_level" : "failed_low_breakout" : "inside_range";
|
|
8059
8018
|
const touchTolerance = atr2 != null && Number.isFinite(atr2) && atr2 > 0 ? atr2 * 0.15 : null;
|
|
8060
8019
|
const highLevel = baseResult.highLevel;
|
|
@@ -8087,253 +8046,347 @@ var buildBaseContextSnapshot = ({
|
|
|
8087
8046
|
distanceScore * 0.45 + wickSupport * 0.25 + closeAcceptance * 0.3
|
|
8088
8047
|
);
|
|
8089
8048
|
})();
|
|
8090
|
-
const recentFalseBreakoutDensity = highLevel == null || lowLevel == null || recent20.length < 2 ? null : recent20.reduce((count, item, index) => {
|
|
8091
|
-
if (index === 0) {
|
|
8092
|
-
return count;
|
|
8093
|
-
}
|
|
8094
|
-
const prevItem = recent20[index - 1];
|
|
8095
|
-
if (!prevItem) {
|
|
8096
|
-
return count;
|
|
8097
|
-
}
|
|
8098
|
-
if (prevItem.close > highLevel && item.close <= highLevel) {
|
|
8099
|
-
return count + 1;
|
|
8100
|
-
}
|
|
8101
|
-
if (prevItem.close < lowLevel && item.close >= lowLevel) {
|
|
8102
|
-
return count + 1;
|
|
8103
|
-
}
|
|
8104
|
-
return count;
|
|
8105
|
-
}, 0) / (recent20.length - 1);
|
|
8106
8049
|
const rejectionWickScore = trendBias === "bull" ? lowerWick : trendBias === "bear" ? upperWick : Math.max(upperWick ?? 0, lowerWick ?? 0);
|
|
8107
|
-
const adxContext = buildAdxContext(adxValue) ?? calculateAdxContext(candlesHistory);
|
|
8108
|
-
const rsiContext = buildRsiContext(rsiValue) ?? calculateRsiContext(closeSeries);
|
|
8109
|
-
const benchmarkMaFast = averageLastN(btcCloseSeries, indicatorPeriods.maFast);
|
|
8110
|
-
const benchmarkMaSlow = averageLastN(btcCloseSeries, indicatorPeriods.maSlow);
|
|
8111
|
-
const coin1h = coinResampledCandles.h1;
|
|
8112
|
-
const btc1h = btcResampledCandles.h1;
|
|
8113
|
-
const btc4h = btcResampledCandles.h4;
|
|
8114
|
-
const btc1d = btcResampledCandles.d1;
|
|
8115
|
-
const eth1h = ethResampledCandles?.h1 ?? [];
|
|
8116
|
-
const eth4h = ethResampledCandles?.h4 ?? [];
|
|
8117
|
-
const eth1d = ethResampledCandles?.d1 ?? [];
|
|
8118
8050
|
const coin4h = coinResampledCandles.h4;
|
|
8119
8051
|
const coin1d = coinResampledCandles.d1;
|
|
8120
|
-
const
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
)
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
totalStructureVolume
|
|
8211
|
-
);
|
|
8212
|
-
const supportVolumeShare = safeDivide(
|
|
8213
|
-
nearestSupport?.volume ?? null,
|
|
8214
|
-
totalStructureVolume
|
|
8215
|
-
);
|
|
8216
|
-
const sweepState = nearestResistance == null && nearestSupport == null ? "unknown" : nearestResistance != null && candle.high > nearestResistance.upper && candle.close < nearestResistance.level ? "swept_high" : nearestSupport != null && candle.low < nearestSupport.lower && candle.close > nearestSupport.level ? "swept_low" : nearestResistance != null && candle.close > nearestResistance.upper ? "broken_high" : nearestSupport != null && candle.close < nearestSupport.lower ? "broken_low" : "none";
|
|
8217
|
-
const liquiditySide = sweepState === "swept_high" || sweepState === "broken_high" ? "high" : sweepState === "swept_low" || sweepState === "broken_low" ? "low" : null;
|
|
8218
|
-
const referenceZoneSide = liquiditySide === "high" ? "resistance" : liquiditySide === "low" ? "support" : null;
|
|
8219
|
-
const prior20High = prior20.length > 0 ? Math.max(...prior20.map((item) => item.high)) : null;
|
|
8220
|
-
const prior20Low = prior20.length > 0 ? Math.min(...prior20.map((item) => item.low)) : null;
|
|
8221
|
-
const sweepHigh20 = prior20High == null ? null : candle.high > prior20High && candle.close < prior20High;
|
|
8222
|
-
const sweepLow20 = prior20Low == null ? null : candle.low < prior20Low && candle.close > prior20Low;
|
|
8223
|
-
const closeBackInsideRange = sweepHigh20 == null && sweepLow20 == null ? null : Boolean(sweepHigh20 || sweepLow20);
|
|
8224
|
-
const stopRunDirection = sweepHigh20 ? "up" : sweepLow20 ? "down" : null;
|
|
8225
|
-
const sweepWickPct = stopRunDirection === "up" ? upperWick : stopRunDirection === "down" ? lowerWick : null;
|
|
8226
|
-
const recent3 = candlesHistory.slice(-3);
|
|
8227
|
-
const recent5 = candlesHistory.slice(-5);
|
|
8228
|
-
const closesAboveHighLevel3 = highLevel == null ? null : recent3.filter((item) => item.close > highLevel).length;
|
|
8229
|
-
const closesBelowLowLevel3 = lowLevel == null ? null : recent3.filter((item) => item.close < lowLevel).length;
|
|
8230
|
-
const failedAcceptanceBars = highLevel == null || lowLevel == null ? null : recent5.filter(
|
|
8231
|
-
(item) => item.high > highLevel && item.close <= highLevel || item.low < lowLevel && item.close >= lowLevel
|
|
8232
|
-
).length;
|
|
8233
|
-
const acceptanceScore = closesAboveHighLevel3 == null || closesBelowLowLevel3 == null ? null : (closesAboveHighLevel3 - closesBelowLowLevel3) / Math.max(1, recent3.length);
|
|
8234
|
-
const breakoutBodyAtr = safeDivide(Math.abs(candle.close - candle.open), atr2);
|
|
8235
|
-
const priceVolumeProfile = buildPriceVolumeProfileContext(
|
|
8236
|
-
structureWindow,
|
|
8237
|
-
candle.close,
|
|
8238
|
-
atr2
|
|
8239
|
-
);
|
|
8240
|
-
const volumeStructure = buildVolumeStructureContext(
|
|
8241
|
-
candlesHistory,
|
|
8242
|
-
candle.close,
|
|
8243
|
-
atr2
|
|
8244
|
-
);
|
|
8245
|
-
const srZones = buildSrZonesContext(
|
|
8246
|
-
structureWindow,
|
|
8247
|
-
candle.close,
|
|
8248
|
-
prevCandle?.close ?? null,
|
|
8249
|
-
atr2
|
|
8250
|
-
);
|
|
8251
|
-
const liquidityZones = buildLiquidityZonesContext(
|
|
8252
|
-
candlesHistory.slice(-180),
|
|
8253
|
-
candle.close,
|
|
8254
|
-
prevCandle?.close ?? null,
|
|
8255
|
-
atr2
|
|
8256
|
-
);
|
|
8257
|
-
const liquidityTails = buildLiquidityTailsContext(
|
|
8258
|
-
candlesHistory.slice(-180),
|
|
8259
|
-
candle.close,
|
|
8260
|
-
atr2
|
|
8261
|
-
);
|
|
8262
|
-
const trendFollow = buildTrendFollowContext(
|
|
8263
|
-
candlesHistory.slice(-220),
|
|
8264
|
-
candle.close,
|
|
8265
|
-
atr2
|
|
8266
|
-
);
|
|
8267
|
-
const structureZonesContext = buildStructureZonesContext(
|
|
8268
|
-
swingContext,
|
|
8269
|
-
pivotContext,
|
|
8270
|
-
candle.close,
|
|
8271
|
-
atr2,
|
|
8272
|
-
structureWindow
|
|
8273
|
-
);
|
|
8274
|
-
const hl2Series = precomputedMaLayers === void 0 ? candlesHistory.map((item) => (item.high + item.low) / 2) : [];
|
|
8275
|
-
const maLayers = buildMaLayersContext(hl2Series, precomputedMaLayers);
|
|
8276
|
-
const contextMa = buildContextMaContext(
|
|
8277
|
-
closeSeries,
|
|
8278
|
-
candle.close,
|
|
8279
|
-
atr2,
|
|
8280
|
-
precomputedContextMa
|
|
8281
|
-
);
|
|
8282
|
-
const adaptiveChannel = buildAdaptiveChannelContext(
|
|
8283
|
-
candlesHistory,
|
|
8284
|
-
candle.close,
|
|
8285
|
-
atr2,
|
|
8286
|
-
precomputedAdaptiveChannel
|
|
8287
|
-
);
|
|
8288
|
-
const deltaContext = buildDeltaContext(structureWindow);
|
|
8289
|
-
const snapshot = {
|
|
8290
|
-
candle,
|
|
8291
|
-
prevCandle,
|
|
8292
|
-
raw: {
|
|
8293
|
-
trend: {
|
|
8294
|
-
maFast: baseResult.maFast,
|
|
8295
|
-
maMedium: baseResult.maMedium,
|
|
8296
|
-
maSlow: baseResult.maSlow
|
|
8052
|
+
const buildRelativeSnapshot = () => {
|
|
8053
|
+
const spreadSeries = materializeNumericHistory(
|
|
8054
|
+
indicatorHistory.spread ?? createNumericHistoryBuffer()
|
|
8055
|
+
);
|
|
8056
|
+
const benchmarkMaFast = averageLastN(
|
|
8057
|
+
btcCloseSeries,
|
|
8058
|
+
indicatorPeriods.maFast
|
|
8059
|
+
);
|
|
8060
|
+
const benchmarkMaSlow = averageLastN(
|
|
8061
|
+
btcCloseSeries,
|
|
8062
|
+
indicatorPeriods.maSlow
|
|
8063
|
+
);
|
|
8064
|
+
const coin1h = coinResampledCandles.h1;
|
|
8065
|
+
const btc1h = btcResampledCandles.h1;
|
|
8066
|
+
const btc4h = btcResampledCandles.h4;
|
|
8067
|
+
const btc1d = btcResampledCandles.d1;
|
|
8068
|
+
const eth1h = ethResampledCandles?.h1 ?? [];
|
|
8069
|
+
const eth4h = ethResampledCandles?.h4 ?? [];
|
|
8070
|
+
const eth1d = ethResampledCandles?.d1 ?? [];
|
|
8071
|
+
const targetVsBtc = buildTargetVsBtcContext({
|
|
8072
|
+
coin1h,
|
|
8073
|
+
btc1h,
|
|
8074
|
+
coin4h,
|
|
8075
|
+
btc4h,
|
|
8076
|
+
coin1d,
|
|
8077
|
+
btc1d,
|
|
8078
|
+
coinCandles: candlesHistory,
|
|
8079
|
+
btcCandles: btcCandlesHistory
|
|
8080
|
+
});
|
|
8081
|
+
const targetVsEth = ethCandlesHistory.length >= 2 ? buildTargetVsEthContext({
|
|
8082
|
+
coin1h,
|
|
8083
|
+
eth1h,
|
|
8084
|
+
coin4h,
|
|
8085
|
+
eth4h,
|
|
8086
|
+
coin1d,
|
|
8087
|
+
eth1d,
|
|
8088
|
+
coinCandles: candlesHistory,
|
|
8089
|
+
ethCandles: ethCandlesHistory
|
|
8090
|
+
}) : null;
|
|
8091
|
+
const btcPsychologicalLevels = buildPsychologicalLevelAssetContext(
|
|
8092
|
+
btcCandlesHistory,
|
|
8093
|
+
1e3
|
|
8094
|
+
);
|
|
8095
|
+
const ethPsychologicalLevels = buildPsychologicalLevelAssetContext(
|
|
8096
|
+
ethCandlesHistory,
|
|
8097
|
+
100
|
|
8098
|
+
);
|
|
8099
|
+
const referencePsychologicalLevels = btcPsychologicalLevels != null || ethPsychologicalLevels != null ? {
|
|
8100
|
+
...btcPsychologicalLevels != null ? { BTCUSDT: btcPsychologicalLevels } : {},
|
|
8101
|
+
...ethPsychologicalLevels != null ? { ETHUSDT: ethPsychologicalLevels } : {}
|
|
8102
|
+
} : null;
|
|
8103
|
+
const relativeStrength1h = getRelativeChange(
|
|
8104
|
+
baseResult.price1hPcnt,
|
|
8105
|
+
btc1h.length >= 2 ? percentChange(
|
|
8106
|
+
btc1h[btc1h.length - 1].close,
|
|
8107
|
+
btc1h[Math.max(0, btc1h.length - 2)].close
|
|
8108
|
+
) : null
|
|
8109
|
+
);
|
|
8110
|
+
const relativeStrength4h = getRelativeChange(
|
|
8111
|
+
coin4h.length >= 2 ? percentChange(
|
|
8112
|
+
coin4h[coin4h.length - 1].close,
|
|
8113
|
+
coin4h[coin4h.length - 2].close
|
|
8114
|
+
) : null,
|
|
8115
|
+
btc4h.length >= 2 ? percentChange(
|
|
8116
|
+
btc4h[btc4h.length - 1].close,
|
|
8117
|
+
btc4h[btc4h.length - 2].close
|
|
8118
|
+
) : null
|
|
8119
|
+
);
|
|
8120
|
+
const relativeStrength1d = getRelativeChange(
|
|
8121
|
+
coin1d.length >= 2 ? percentChange(
|
|
8122
|
+
coin1d[coin1d.length - 1].close,
|
|
8123
|
+
coin1d[coin1d.length - 2].close
|
|
8124
|
+
) : null,
|
|
8125
|
+
btc1d.length >= 2 ? percentChange(
|
|
8126
|
+
btc1d[btc1d.length - 1].close,
|
|
8127
|
+
btc1d[btc1d.length - 2].close
|
|
8128
|
+
) : null
|
|
8129
|
+
);
|
|
8130
|
+
const benchmarkBias = btc1h.length >= 2 ? btc1h[btc1h.length - 1].close > btc1h[btc1h.length - 2].close ? "bull" : btc1h[btc1h.length - 1].close < btc1h[btc1h.length - 2].close ? "bear" : "neutral" : "neutral";
|
|
8131
|
+
const trendAlignment = trendBias === "neutral" || benchmarkBias === "neutral" ? "neutral" : trendBias === benchmarkBias ? trendBias === "bull" ? "aligned_bull" : "aligned_bear" : "against_benchmark";
|
|
8132
|
+
const benchmarkTrendBias = benchmarkMaFast == null || benchmarkMaSlow == null ? "neutral" : benchmarkMaFast > benchmarkMaSlow ? "bull" : benchmarkMaFast < benchmarkMaSlow ? "bear" : "neutral";
|
|
8133
|
+
return {
|
|
8134
|
+
benchmark: {
|
|
8135
|
+
maFast: benchmarkMaFast,
|
|
8136
|
+
maSlow: benchmarkMaSlow,
|
|
8137
|
+
bias: benchmarkTrendBias,
|
|
8138
|
+
relativeStrength1h,
|
|
8139
|
+
relativeStrength4h,
|
|
8140
|
+
relativeStrength1d,
|
|
8141
|
+
trendAlignment
|
|
8297
8142
|
},
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
bbWidthPct
|
|
8143
|
+
execution: {
|
|
8144
|
+
venueSpread: baseResult.spread,
|
|
8145
|
+
venueSpreadZScore: calculateZScore(
|
|
8146
|
+
spreadSeries,
|
|
8147
|
+
toNullable(baseResult.spread)
|
|
8148
|
+
)
|
|
8305
8149
|
},
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8150
|
+
targetVsBtc,
|
|
8151
|
+
...targetVsEth != null ? { targetVsEth } : {},
|
|
8152
|
+
...referencePsychologicalLevels != null ? { referencePsychologicalLevels } : {}
|
|
8153
|
+
};
|
|
8154
|
+
};
|
|
8155
|
+
const buildStructureSnapshot = () => {
|
|
8156
|
+
const structurePivots = detectConfirmedPivots(structureWindow, atr2);
|
|
8157
|
+
const structureZones = buildPriceZones(
|
|
8158
|
+
structureWindow,
|
|
8159
|
+
structurePivots,
|
|
8160
|
+
atr2
|
|
8161
|
+
);
|
|
8162
|
+
const swingContext = buildSwingContext(structurePivots);
|
|
8163
|
+
const pivotContext = buildPivotContext(
|
|
8164
|
+
structurePivots,
|
|
8165
|
+
structureWindow.length,
|
|
8166
|
+
atr2
|
|
8167
|
+
);
|
|
8168
|
+
const nearestSupport = getNearestZone(
|
|
8169
|
+
structureZones,
|
|
8170
|
+
"support",
|
|
8171
|
+
candle.close
|
|
8172
|
+
);
|
|
8173
|
+
const nearestResistance = getNearestZone(
|
|
8174
|
+
structureZones,
|
|
8175
|
+
"resistance",
|
|
8176
|
+
candle.close
|
|
8177
|
+
);
|
|
8178
|
+
const totalStructureVolume = structureWindow.reduce(
|
|
8179
|
+
(sum2, item) => sum2 + item.volume,
|
|
8180
|
+
0
|
|
8181
|
+
);
|
|
8182
|
+
const priceInSupportZone = nearestSupport == null ? null : candle.close >= nearestSupport.lower && candle.close <= nearestSupport.upper;
|
|
8183
|
+
const priceInResistanceZone = nearestResistance == null ? null : candle.close >= nearestResistance.lower && candle.close <= nearestResistance.upper;
|
|
8184
|
+
const activeZoneType = priceInSupportZone ? "support" : priceInResistanceZone ? "resistance" : null;
|
|
8185
|
+
const priceInZone = priceInSupportZone == null && priceInResistanceZone == null ? null : Boolean(priceInSupportZone || priceInResistanceZone);
|
|
8186
|
+
const resistanceVolumeShare = safeDivide(
|
|
8187
|
+
nearestResistance?.volume ?? null,
|
|
8188
|
+
totalStructureVolume
|
|
8189
|
+
);
|
|
8190
|
+
const supportVolumeShare = safeDivide(
|
|
8191
|
+
nearestSupport?.volume ?? null,
|
|
8192
|
+
totalStructureVolume
|
|
8193
|
+
);
|
|
8194
|
+
const sweepState = nearestResistance == null && nearestSupport == null ? "unknown" : nearestResistance != null && candle.high > nearestResistance.upper && candle.close < nearestResistance.level ? "swept_high" : nearestSupport != null && candle.low < nearestSupport.lower && candle.close > nearestSupport.level ? "swept_low" : nearestResistance != null && candle.close > nearestResistance.upper ? "broken_high" : nearestSupport != null && candle.close < nearestSupport.lower ? "broken_low" : "none";
|
|
8195
|
+
const liquiditySide = sweepState === "swept_high" || sweepState === "broken_high" ? "high" : sweepState === "swept_low" || sweepState === "broken_low" ? "low" : null;
|
|
8196
|
+
const referenceZoneSide = liquiditySide === "high" ? "resistance" : liquiditySide === "low" ? "support" : null;
|
|
8197
|
+
const prior20High = prior20.length > 0 ? Math.max(...prior20.map((item) => item.high)) : null;
|
|
8198
|
+
const prior20Low = prior20.length > 0 ? Math.min(...prior20.map((item) => item.low)) : null;
|
|
8199
|
+
const sweepHigh20 = prior20High == null ? null : candle.high > prior20High && candle.close < prior20High;
|
|
8200
|
+
const sweepLow20 = prior20Low == null ? null : candle.low < prior20Low && candle.close > prior20Low;
|
|
8201
|
+
const closeBackInsideRange = sweepHigh20 == null && sweepLow20 == null ? null : Boolean(sweepHigh20 || sweepLow20);
|
|
8202
|
+
const stopRunDirection = sweepHigh20 ? "up" : sweepLow20 ? "down" : null;
|
|
8203
|
+
const sweepWickPct = stopRunDirection === "up" ? upperWick : stopRunDirection === "down" ? lowerWick : null;
|
|
8204
|
+
const recent3 = candlesHistory.slice(-3);
|
|
8205
|
+
const recent5 = candlesHistory.slice(-5);
|
|
8206
|
+
const closesAboveHighLevel3 = highLevel == null ? null : recent3.filter((item) => item.close > highLevel).length;
|
|
8207
|
+
const closesBelowLowLevel3 = lowLevel == null ? null : recent3.filter((item) => item.close < lowLevel).length;
|
|
8208
|
+
const failedAcceptanceBars = highLevel == null || lowLevel == null ? null : recent5.filter(
|
|
8209
|
+
(item) => item.high > highLevel && item.close <= highLevel || item.low < lowLevel && item.close >= lowLevel
|
|
8210
|
+
).length;
|
|
8211
|
+
const acceptanceScore = closesAboveHighLevel3 == null || closesBelowLowLevel3 == null ? null : (closesAboveHighLevel3 - closesBelowLowLevel3) / Math.max(1, recent3.length);
|
|
8212
|
+
const breakoutBodyAtr = safeDivide(
|
|
8213
|
+
Math.abs(candle.close - candle.open),
|
|
8214
|
+
atr2
|
|
8215
|
+
);
|
|
8216
|
+
const srZones = buildSrZonesContext(
|
|
8217
|
+
structureWindow,
|
|
8218
|
+
candle.close,
|
|
8219
|
+
prevCandle?.close ?? null,
|
|
8220
|
+
atr2
|
|
8221
|
+
);
|
|
8222
|
+
const liquidityZones = buildLiquidityZonesContext(
|
|
8223
|
+
candlesHistory.slice(-180),
|
|
8224
|
+
candle.close,
|
|
8225
|
+
prevCandle?.close ?? null,
|
|
8226
|
+
atr2
|
|
8227
|
+
);
|
|
8228
|
+
const liquidityTails = buildLiquidityTailsContext(
|
|
8229
|
+
candlesHistory.slice(-180),
|
|
8230
|
+
candle.close,
|
|
8231
|
+
atr2
|
|
8232
|
+
);
|
|
8233
|
+
const structureZonesContext = buildStructureZonesContext(
|
|
8234
|
+
swingContext,
|
|
8235
|
+
pivotContext,
|
|
8236
|
+
candle.close,
|
|
8237
|
+
atr2,
|
|
8238
|
+
structureWindow
|
|
8239
|
+
);
|
|
8240
|
+
return {
|
|
8241
|
+
swing: swingContext,
|
|
8242
|
+
zones: {
|
|
8243
|
+
support: {
|
|
8244
|
+
level: nearestSupport?.level ?? null,
|
|
8245
|
+
lower: nearestSupport?.lower ?? null,
|
|
8246
|
+
upper: nearestSupport?.upper ?? null,
|
|
8247
|
+
touches: nearestSupport?.touches ?? null,
|
|
8248
|
+
ageBars: nearestSupport?.ageBars ?? null,
|
|
8249
|
+
volumeShare: supportVolumeShare,
|
|
8250
|
+
distanceAtr: safeDivide(
|
|
8251
|
+
nearestSupport == null ? null : candle.close - nearestSupport.level,
|
|
8252
|
+
atr2
|
|
8253
|
+
)
|
|
8254
|
+
},
|
|
8255
|
+
resistance: {
|
|
8256
|
+
level: nearestResistance?.level ?? null,
|
|
8257
|
+
lower: nearestResistance?.lower ?? null,
|
|
8258
|
+
upper: nearestResistance?.upper ?? null,
|
|
8259
|
+
touches: nearestResistance?.touches ?? null,
|
|
8260
|
+
ageBars: nearestResistance?.ageBars ?? null,
|
|
8261
|
+
volumeShare: resistanceVolumeShare,
|
|
8262
|
+
distanceAtr: safeDivide(
|
|
8263
|
+
nearestResistance == null ? null : nearestResistance.level - candle.close,
|
|
8264
|
+
atr2
|
|
8265
|
+
)
|
|
8266
|
+
},
|
|
8267
|
+
active: {
|
|
8268
|
+
side: activeZoneType,
|
|
8269
|
+
priceInZone
|
|
8270
|
+
}
|
|
8310
8271
|
},
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8272
|
+
srZones,
|
|
8273
|
+
liquidity: {
|
|
8274
|
+
sweepState,
|
|
8275
|
+
side: liquiditySide,
|
|
8276
|
+
referenceZoneSide,
|
|
8277
|
+
sweepHigh20,
|
|
8278
|
+
sweepLow20,
|
|
8279
|
+
closeBackInsideRange,
|
|
8280
|
+
stopRunDirection,
|
|
8281
|
+
sweepWickPct
|
|
8318
8282
|
},
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8283
|
+
liquidityZones,
|
|
8284
|
+
liquidityTails,
|
|
8285
|
+
structureZones: structureZonesContext,
|
|
8286
|
+
pivots: pivotContext,
|
|
8287
|
+
acceptance: {
|
|
8288
|
+
closesAboveHighLevel3,
|
|
8289
|
+
closesBelowLowLevel3,
|
|
8290
|
+
failedAcceptanceBars,
|
|
8291
|
+
acceptanceScore,
|
|
8292
|
+
breakoutBodyAtr
|
|
8293
|
+
},
|
|
8294
|
+
localRange: {
|
|
8295
|
+
rangePosition20: calculateRangePosition(
|
|
8296
|
+
candle.close,
|
|
8297
|
+
recent20Low,
|
|
8298
|
+
recent20High
|
|
8299
|
+
),
|
|
8300
|
+
distanceToHighLevelAtr,
|
|
8301
|
+
distanceToLowLevelAtr,
|
|
8302
|
+
breakoutState,
|
|
8303
|
+
barsSinceBreakout: breakoutRuntimeState.barsSinceBreakout,
|
|
8304
|
+
breakoutRetestQuality
|
|
8327
8305
|
},
|
|
8328
8306
|
levels: {
|
|
8329
|
-
|
|
8330
|
-
|
|
8307
|
+
highTouchCount20,
|
|
8308
|
+
lowTouchCount20,
|
|
8309
|
+
dominantTouchCount20
|
|
8331
8310
|
},
|
|
8332
|
-
|
|
8333
|
-
|
|
8311
|
+
candleQuality: {
|
|
8312
|
+
upperWickPct: upperWick,
|
|
8313
|
+
lowerWickPct: lowerWick,
|
|
8314
|
+
rejectionWickScore
|
|
8334
8315
|
}
|
|
8335
|
-
}
|
|
8336
|
-
|
|
8316
|
+
};
|
|
8317
|
+
};
|
|
8318
|
+
const buildRegimeSnapshot = () => {
|
|
8319
|
+
const atrPctSeries = materializeNumericHistory(
|
|
8320
|
+
indicatorHistory.atrPct ?? createNumericHistoryBuffer()
|
|
8321
|
+
);
|
|
8322
|
+
const macdHistogramSeries = materializeNumericHistory(
|
|
8323
|
+
indicatorHistory.macdHistogram ?? createNumericHistoryBuffer()
|
|
8324
|
+
);
|
|
8325
|
+
const persistenceWindow = closeSeries.slice(-10);
|
|
8326
|
+
const directionalMoves = persistenceWindow.slice(1).map((value, index) => value - persistenceWindow[index]);
|
|
8327
|
+
const persistence = directionalMoves.length === 0 ? null : directionalMoves.filter(
|
|
8328
|
+
(delta) => trendBias === "bull" ? delta > 0 : trendBias === "bear" ? delta < 0 : delta === 0
|
|
8329
|
+
).length / directionalMoves.length;
|
|
8330
|
+
const atrPctZScore = calculateZScore(
|
|
8331
|
+
atrPctSeries,
|
|
8332
|
+
toNullable(baseResult.atrPct)
|
|
8333
|
+
);
|
|
8334
|
+
const atrSlope = calculateLineSlope(atrPctSeries, 5);
|
|
8335
|
+
const compressionScore = safeDivide(
|
|
8336
|
+
toNullable(baseResult.atrPct),
|
|
8337
|
+
getLastFiniteValue(atrPctSeries.slice(0, -1))
|
|
8338
|
+
);
|
|
8339
|
+
const expansionScore = compressionScore == null || compressionScore === 0 ? null : 1 / compressionScore;
|
|
8340
|
+
const bbWidthPctSeries = calculateRecentBbWidthPctSeries(closeSeries, 100);
|
|
8341
|
+
const rawAtrPctSeries = calculateRecentAtrPctSeries(candlesHistory, 100);
|
|
8342
|
+
const rawAtrPct = safeDivide(atr2, candle.close);
|
|
8343
|
+
const realizedVolatility = calculateRealizedVolatility(closeSeries);
|
|
8344
|
+
const realizedVolatilitySeries = calculateRecentRealizedVolatilitySeries(
|
|
8345
|
+
closeSeries,
|
|
8346
|
+
100
|
|
8347
|
+
);
|
|
8348
|
+
const rangeExpansionSeries = calculateRecentRangeExpansionSeries(
|
|
8349
|
+
candlesHistory,
|
|
8350
|
+
20
|
|
8351
|
+
);
|
|
8352
|
+
const rangeExpansion = rangeExpansionSeries[rangeExpansionSeries.length - 1] ?? null;
|
|
8353
|
+
const volatilityState = compressionScore == null ? "unknown" : compressionScore <= 0.9 ? "compressed" : compressionScore >= 1.1 ? "expanded" : "normal";
|
|
8354
|
+
const bodyStrength = highLowRange > 0 ? Math.abs(candle.close - candle.open) / highLowRange : null;
|
|
8355
|
+
const closeLocationInRange = highLowRange > 0 ? (candle.close - candle.low) / highLowRange : null;
|
|
8356
|
+
const recentFalseBreakoutDensity = highLevel == null || lowLevel == null || recent20.length < 2 ? null : recent20.reduce((count, item, index) => {
|
|
8357
|
+
if (index === 0) return count;
|
|
8358
|
+
const prevItem = recent20[index - 1];
|
|
8359
|
+
if (!prevItem) return count;
|
|
8360
|
+
if (prevItem.close > highLevel && item.close <= highLevel) {
|
|
8361
|
+
return count + 1;
|
|
8362
|
+
}
|
|
8363
|
+
if (prevItem.close < lowLevel && item.close >= lowLevel) {
|
|
8364
|
+
return count + 1;
|
|
8365
|
+
}
|
|
8366
|
+
return count;
|
|
8367
|
+
}, 0) / (recent20.length - 1);
|
|
8368
|
+
const adxContext = buildAdxContext(adxValue) ?? calculateAdxContext(candlesHistory);
|
|
8369
|
+
const rsiContext = buildRsiContext(rsiValue) ?? calculateRsiContext(closeSeries);
|
|
8370
|
+
const trendFollow = buildTrendFollowContext(
|
|
8371
|
+
candlesHistory.slice(-220),
|
|
8372
|
+
candle.close,
|
|
8373
|
+
atr2
|
|
8374
|
+
);
|
|
8375
|
+
const hl2Series = precomputedMaLayers === void 0 ? candlesHistory.map((item) => (item.high + item.low) / 2) : [];
|
|
8376
|
+
const maLayers = buildMaLayersContext(hl2Series, precomputedMaLayers);
|
|
8377
|
+
const contextMa = buildContextMaContext(
|
|
8378
|
+
closeSeries,
|
|
8379
|
+
candle.close,
|
|
8380
|
+
atr2,
|
|
8381
|
+
precomputedContextMa
|
|
8382
|
+
);
|
|
8383
|
+
const adaptiveChannel = buildAdaptiveChannelContext(
|
|
8384
|
+
candlesHistory,
|
|
8385
|
+
candle.close,
|
|
8386
|
+
atr2,
|
|
8387
|
+
precomputedAdaptiveChannel
|
|
8388
|
+
);
|
|
8389
|
+
return {
|
|
8337
8390
|
trend: {
|
|
8338
8391
|
bias: trendBias,
|
|
8339
8392
|
maStackScore,
|
|
@@ -8406,89 +8459,17 @@ var buildBaseContextSnapshot = ({
|
|
|
8406
8459
|
upCloseStreak: closeStreaks.up,
|
|
8407
8460
|
downCloseStreak: closeStreaks.down
|
|
8408
8461
|
},
|
|
8409
|
-
session,
|
|
8462
|
+
session: buildSessionContext(candle.timestamp),
|
|
8410
8463
|
memory: {
|
|
8411
8464
|
recentFalseBreakoutDensity
|
|
8412
8465
|
}
|
|
8413
|
-
}
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
upper: nearestSupport?.upper ?? null,
|
|
8421
|
-
touches: nearestSupport?.touches ?? null,
|
|
8422
|
-
ageBars: nearestSupport?.ageBars ?? null,
|
|
8423
|
-
volumeShare: supportVolumeShare,
|
|
8424
|
-
distanceAtr: safeDivide(
|
|
8425
|
-
nearestSupport == null ? null : candle.close - nearestSupport.level,
|
|
8426
|
-
atr2
|
|
8427
|
-
)
|
|
8428
|
-
},
|
|
8429
|
-
resistance: {
|
|
8430
|
-
level: nearestResistance?.level ?? null,
|
|
8431
|
-
lower: nearestResistance?.lower ?? null,
|
|
8432
|
-
upper: nearestResistance?.upper ?? null,
|
|
8433
|
-
touches: nearestResistance?.touches ?? null,
|
|
8434
|
-
ageBars: nearestResistance?.ageBars ?? null,
|
|
8435
|
-
volumeShare: resistanceVolumeShare,
|
|
8436
|
-
distanceAtr: safeDivide(
|
|
8437
|
-
nearestResistance == null ? null : nearestResistance.level - candle.close,
|
|
8438
|
-
atr2
|
|
8439
|
-
)
|
|
8440
|
-
},
|
|
8441
|
-
active: {
|
|
8442
|
-
side: activeZoneType,
|
|
8443
|
-
priceInZone
|
|
8444
|
-
}
|
|
8445
|
-
},
|
|
8446
|
-
srZones,
|
|
8447
|
-
liquidity: {
|
|
8448
|
-
sweepState,
|
|
8449
|
-
side: liquiditySide,
|
|
8450
|
-
referenceZoneSide,
|
|
8451
|
-
sweepHigh20,
|
|
8452
|
-
sweepLow20,
|
|
8453
|
-
closeBackInsideRange,
|
|
8454
|
-
stopRunDirection,
|
|
8455
|
-
sweepWickPct
|
|
8456
|
-
},
|
|
8457
|
-
liquidityZones,
|
|
8458
|
-
liquidityTails,
|
|
8459
|
-
structureZones: structureZonesContext,
|
|
8460
|
-
pivots: pivotContext,
|
|
8461
|
-
acceptance: {
|
|
8462
|
-
closesAboveHighLevel3,
|
|
8463
|
-
closesBelowLowLevel3,
|
|
8464
|
-
failedAcceptanceBars,
|
|
8465
|
-
acceptanceScore,
|
|
8466
|
-
breakoutBodyAtr
|
|
8467
|
-
},
|
|
8468
|
-
localRange: {
|
|
8469
|
-
rangePosition20: calculateRangePosition(
|
|
8470
|
-
candle.close,
|
|
8471
|
-
recent20Low,
|
|
8472
|
-
recent20High
|
|
8473
|
-
),
|
|
8474
|
-
distanceToHighLevelAtr,
|
|
8475
|
-
distanceToLowLevelAtr,
|
|
8476
|
-
breakoutState,
|
|
8477
|
-
barsSinceBreakout: breakoutRuntimeState.barsSinceBreakout,
|
|
8478
|
-
breakoutRetestQuality
|
|
8479
|
-
},
|
|
8480
|
-
levels: {
|
|
8481
|
-
highTouchCount20,
|
|
8482
|
-
lowTouchCount20,
|
|
8483
|
-
dominantTouchCount20
|
|
8484
|
-
},
|
|
8485
|
-
candleQuality: {
|
|
8486
|
-
upperWickPct: upperWick,
|
|
8487
|
-
lowerWickPct: lowerWick,
|
|
8488
|
-
rejectionWickScore
|
|
8489
|
-
}
|
|
8490
|
-
},
|
|
8491
|
-
participation: {
|
|
8466
|
+
};
|
|
8467
|
+
};
|
|
8468
|
+
const buildParticipationSnapshot = () => {
|
|
8469
|
+
let cachedPriceVolumeProfile;
|
|
8470
|
+
let cachedVolumeStructure;
|
|
8471
|
+
let cachedDelta;
|
|
8472
|
+
return {
|
|
8492
8473
|
volume: {
|
|
8493
8474
|
volumeRel20,
|
|
8494
8475
|
turnoverRel20,
|
|
@@ -8501,30 +8482,89 @@ var buildBaseContextSnapshot = ({
|
|
|
8501
8482
|
),
|
|
8502
8483
|
effortVsResult
|
|
8503
8484
|
},
|
|
8504
|
-
priceVolumeProfile
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
maFast: benchmarkMaFast,
|
|
8511
|
-
maSlow: benchmarkMaSlow,
|
|
8512
|
-
bias: benchmarkTrendBias,
|
|
8513
|
-
relativeStrength1h,
|
|
8514
|
-
relativeStrength4h,
|
|
8515
|
-
relativeStrength1d,
|
|
8516
|
-
trendAlignment
|
|
8485
|
+
get priceVolumeProfile() {
|
|
8486
|
+
return cachedPriceVolumeProfile ??= buildPriceVolumeProfileContext(
|
|
8487
|
+
structureWindow,
|
|
8488
|
+
candle.close,
|
|
8489
|
+
atr2
|
|
8490
|
+
);
|
|
8517
8491
|
},
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
)
|
|
8492
|
+
get volumeStructure() {
|
|
8493
|
+
return cachedVolumeStructure ??= buildVolumeStructureContext(
|
|
8494
|
+
candlesHistory,
|
|
8495
|
+
candle.close,
|
|
8496
|
+
atr2
|
|
8497
|
+
);
|
|
8524
8498
|
},
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8499
|
+
get delta() {
|
|
8500
|
+
return cachedDelta ??= buildDeltaContext(
|
|
8501
|
+
structureWindow
|
|
8502
|
+
);
|
|
8503
|
+
}
|
|
8504
|
+
};
|
|
8505
|
+
};
|
|
8506
|
+
let cachedStructureSnapshot;
|
|
8507
|
+
let cachedRegimeSnapshot;
|
|
8508
|
+
let cachedParticipationSnapshot;
|
|
8509
|
+
let cachedRelativeSnapshot;
|
|
8510
|
+
const snapshot = {
|
|
8511
|
+
candle,
|
|
8512
|
+
prevCandle,
|
|
8513
|
+
raw: {
|
|
8514
|
+
trend: {
|
|
8515
|
+
maFast: baseResult.maFast,
|
|
8516
|
+
maMedium: baseResult.maMedium,
|
|
8517
|
+
maSlow: baseResult.maSlow
|
|
8518
|
+
},
|
|
8519
|
+
volatility: {
|
|
8520
|
+
atr: atr2,
|
|
8521
|
+
atrPct: toNullable(baseResult.atrPct),
|
|
8522
|
+
bbUpper: baseResult.bbUpper,
|
|
8523
|
+
bbMiddle: baseResult.bbMiddle,
|
|
8524
|
+
bbLower: baseResult.bbLower,
|
|
8525
|
+
bbWidthPct
|
|
8526
|
+
},
|
|
8527
|
+
momentum: {
|
|
8528
|
+
macd: toNullable(baseResult.macd),
|
|
8529
|
+
macdSignal: toNullable(baseResult.macdSignal),
|
|
8530
|
+
macdHistogram: toNullable(baseResult.macdHistogram)
|
|
8531
|
+
},
|
|
8532
|
+
volume: {
|
|
8533
|
+
volume: candle.volume,
|
|
8534
|
+
turnover: candle.turnover,
|
|
8535
|
+
obv: baseResult.obv,
|
|
8536
|
+
obvSma: baseResult.smaObv,
|
|
8537
|
+
volume1h: baseResult.volume1h,
|
|
8538
|
+
volume24h: baseResult.volume24h
|
|
8539
|
+
},
|
|
8540
|
+
price: {
|
|
8541
|
+
prevClose: baseResult.prevClose,
|
|
8542
|
+
price1hPct: baseResult.price1hPcnt,
|
|
8543
|
+
price24hPct: baseResult.price24hPcnt,
|
|
8544
|
+
highPrice1h: baseResult.highPrice1h,
|
|
8545
|
+
lowPrice1h: baseResult.lowPrice1h,
|
|
8546
|
+
highPrice24h: baseResult.highPrice24h,
|
|
8547
|
+
lowPrice24h: baseResult.lowPrice24h
|
|
8548
|
+
},
|
|
8549
|
+
levels: {
|
|
8550
|
+
highLevel: baseResult.highLevel,
|
|
8551
|
+
lowLevel: baseResult.lowLevel
|
|
8552
|
+
},
|
|
8553
|
+
crossAsset: {
|
|
8554
|
+
btcCorrelation: baseResult.correlation
|
|
8555
|
+
}
|
|
8556
|
+
},
|
|
8557
|
+
get regime() {
|
|
8558
|
+
return cachedRegimeSnapshot ??= buildRegimeSnapshot();
|
|
8559
|
+
},
|
|
8560
|
+
get structure() {
|
|
8561
|
+
return cachedStructureSnapshot ??= buildStructureSnapshot();
|
|
8562
|
+
},
|
|
8563
|
+
get participation() {
|
|
8564
|
+
return cachedParticipationSnapshot ??= buildParticipationSnapshot();
|
|
8565
|
+
},
|
|
8566
|
+
get relative() {
|
|
8567
|
+
return cachedRelativeSnapshot ??= buildRelativeSnapshot();
|
|
8528
8568
|
}
|
|
8529
8569
|
};
|
|
8530
8570
|
let cachedMtfSnapshot = null;
|
|
@@ -10599,6 +10639,22 @@ var createIndicators = (data, btcData = [], options = {}) => {
|
|
|
10599
10639
|
const last = value[value.length - 1];
|
|
10600
10640
|
return typeof last === "number" ? last : void 0;
|
|
10601
10641
|
},
|
|
10642
|
+
latestNumbers: (key, count) => {
|
|
10643
|
+
const normalizedCount = Number.isFinite(count) ? Math.max(0, Math.trunc(count)) : 0;
|
|
10644
|
+
if (normalizedCount === 0) return [];
|
|
10645
|
+
const buffer = indicatorHistory[key];
|
|
10646
|
+
if (buffer) {
|
|
10647
|
+
const resultSize = Math.min(normalizedCount, buffer.size);
|
|
10648
|
+
const result = new Array(resultSize);
|
|
10649
|
+
const firstOffset = buffer.size - resultSize;
|
|
10650
|
+
for (let index = 0; index < resultSize; index += 1) {
|
|
10651
|
+
result[index] = buffer.values[(buffer.start + firstOffset + index) % ML_BASE_CANDLES_WINDOW];
|
|
10652
|
+
}
|
|
10653
|
+
return result;
|
|
10654
|
+
}
|
|
10655
|
+
const value = getHistoryResult()[key];
|
|
10656
|
+
return Array.isArray(value) ? value.slice(-normalizedCount).filter((item) => typeof item === "number") : [];
|
|
10657
|
+
},
|
|
10602
10658
|
result: () => {
|
|
10603
10659
|
return cloneHistorySnapshot(
|
|
10604
10660
|
getHistoryResult()
|
|
@@ -10938,7 +10994,8 @@ var createStrategyIndicatorsState = ({
|
|
|
10938
10994
|
ensureInitializedWithCurrentBar: ensureControllerInitialized,
|
|
10939
10995
|
snapshot: (options) => ensureControllerInitialized().snapshot(options),
|
|
10940
10996
|
latestSnapshot: () => ensureControllerInitialized().latestSnapshot(),
|
|
10941
|
-
latestNumber: (key) => ensureControllerInitialized().latestNumber(key)
|
|
10997
|
+
latestNumber: (key) => ensureControllerInitialized().latestNumber(key),
|
|
10998
|
+
latestNumbers: (key, count) => ensureControllerInitialized().latestNumbers(key, count)
|
|
10942
10999
|
};
|
|
10943
11000
|
};
|
|
10944
11001
|
|
|
@@ -11257,19 +11314,6 @@ var toRankBucket = (value) => {
|
|
|
11257
11314
|
if (value <= 20) return "low";
|
|
11258
11315
|
return "normal";
|
|
11259
11316
|
};
|
|
11260
|
-
var toRangePositionBucket = (value) => {
|
|
11261
|
-
if (value == null) return "unknown";
|
|
11262
|
-
if (value <= 0.2) return "low";
|
|
11263
|
-
if (value >= 0.8) return "high";
|
|
11264
|
-
return "middle";
|
|
11265
|
-
};
|
|
11266
|
-
var toVolumeBucket = (value) => {
|
|
11267
|
-
if (value == null) return "unknown";
|
|
11268
|
-
if (value < 0.8) return "thin";
|
|
11269
|
-
if (value < 1.5) return "normal";
|
|
11270
|
-
if (value < 3) return "elevated";
|
|
11271
|
-
return "spike";
|
|
11272
|
-
};
|
|
11273
11317
|
var toVenueSpreadSeverity = (value) => {
|
|
11274
11318
|
if (value == null) return "unknown";
|
|
11275
11319
|
const abs = Math.abs(value);
|
|
@@ -11382,7 +11426,6 @@ var buildBaseContextGateFeatures = ({
|
|
|
11382
11426
|
const atrPctZScore = asFiniteNumberOrNull(volatility?.atrPctZScore);
|
|
11383
11427
|
const breakoutState = localRange?.breakoutState ?? "unknown";
|
|
11384
11428
|
const rangePosition20 = asFiniteNumberOrNull(localRange?.rangePosition20);
|
|
11385
|
-
const rangePositionBucket = toRangePositionBucket(rangePosition20);
|
|
11386
11429
|
const breakoutWithDirection = toDirectionalAlignment({
|
|
11387
11430
|
direction,
|
|
11388
11431
|
bullValue: "above_high_level",
|
|
@@ -11501,22 +11544,12 @@ var buildBaseContextGateFeatures = ({
|
|
|
11501
11544
|
targetVsBtc?.ratioReturn24h
|
|
11502
11545
|
);
|
|
11503
11546
|
const targetVsBtcAlpha24h = asFiniteNumberOrNull(targetVsBtc?.alphaVsBtc24h);
|
|
11504
|
-
const targetVsBtcBeta20 = asFiniteNumberOrNull(targetVsBtc?.betaToBtc20);
|
|
11505
|
-
const targetVsBtcCorrelation20 = asFiniteNumberOrNull(
|
|
11506
|
-
targetVsBtc?.correlationToBtc20
|
|
11507
|
-
);
|
|
11508
|
-
const targetVsBtcRatioTrend = targetVsBtc?.ratioTrend ?? "unknown";
|
|
11509
11547
|
const targetVsBtcDirectionValue = targetVsBtcRatioReturn24h ?? targetVsBtcAlpha24h;
|
|
11510
11548
|
const targetVsBtcAligned = direction == null || targetVsBtcDirectionValue == null ? null : direction === "LONG" ? targetVsBtcDirectionValue >= 0 : targetVsBtcDirectionValue <= 0;
|
|
11511
11549
|
const targetVsEthRatioReturn24h = asFiniteNumberOrNull(
|
|
11512
11550
|
targetVsEth?.ratioReturn24h
|
|
11513
11551
|
);
|
|
11514
11552
|
const targetVsEthAlpha24h = asFiniteNumberOrNull(targetVsEth?.alphaVsEth24h);
|
|
11515
|
-
const targetVsEthBeta20 = asFiniteNumberOrNull(targetVsEth?.betaToEth20);
|
|
11516
|
-
const targetVsEthCorrelation20 = asFiniteNumberOrNull(
|
|
11517
|
-
targetVsEth?.correlationToEth20
|
|
11518
|
-
);
|
|
11519
|
-
const targetVsEthRatioTrend = targetVsEth?.ratioTrend ?? "unknown";
|
|
11520
11553
|
const targetVsEthDirectionValue = targetVsEthRatioReturn24h ?? targetVsEthAlpha24h;
|
|
11521
11554
|
const targetVsEthAligned = direction == null || targetVsEthDirectionValue == null ? null : direction === "LONG" ? targetVsEthDirectionValue >= 0 : targetVsEthDirectionValue <= 0;
|
|
11522
11555
|
const btcAltRegimeValue = btcAltRegime?.regime ?? "unknown";
|
|
@@ -11525,20 +11558,15 @@ var buildBaseContextGateFeatures = ({
|
|
|
11525
11558
|
const btcVsAltReturn24h = asFiniteNumberOrNull(
|
|
11526
11559
|
btcAltRegime?.btcVsAltReturn24h
|
|
11527
11560
|
);
|
|
11528
|
-
const btcTurnoverShare24h = asFiniteNumberOrNull(
|
|
11529
|
-
btcAltRegime?.btcTurnoverShare24h
|
|
11530
|
-
);
|
|
11531
11561
|
const venueSpreadZScore = asFiniteNumberOrNull(execution?.venueSpreadZScore);
|
|
11532
11562
|
const venueSpreadSeverity = toVenueSpreadSeverity(venueSpreadZScore);
|
|
11533
11563
|
const higherTimeframeConflict = mtfAlignmentForDirection === "unknown" ? null : mtfAlignmentForDirection === "against" || mtfAlignmentForDirection === "mixed";
|
|
11534
11564
|
const extremeVolatilityRisk = Math.abs(atrPctZScore ?? 0) >= 2 || atrPctRankBucket === "extreme";
|
|
11535
|
-
const compressionBreakoutSupport = (volatility?.state === "compressed" || bbWidthRankBucket === "low") && breakoutState !== "inside_range" && breakoutState !== "unknown";
|
|
11536
11565
|
const benchmarkConflict = benchmarkAligned === false || relativeStrengthBucket.endsWith("_against");
|
|
11537
11566
|
const derivativesSummary = baseContext.derivatives?.summary;
|
|
11538
11567
|
const derivativesDirectionAligned = typeof derivativesSummary?.directionAligned === "boolean" ? derivativesSummary.directionAligned : null;
|
|
11539
11568
|
const derivativesRiskFlags = Array.isArray(derivativesSummary?.riskFlags) ? derivativesSummary.riskFlags : [];
|
|
11540
11569
|
const derivativesCrowdedForDirection = direction === "LONG" ? derivativesRiskFlags.includes("crowded_long") : direction === "SHORT" ? derivativesRiskFlags.includes("crowded_short") : false;
|
|
11541
|
-
const derivativesCrowdedAny = derivativesRiskFlags.includes("crowded_long") || derivativesRiskFlags.includes("crowded_short");
|
|
11542
11570
|
const atr2 = asFiniteNumberOrNull(baseContext.raw?.volatility?.atr);
|
|
11543
11571
|
const currentPrice = asFiniteNumberOrNull(prices?.currentPrice);
|
|
11544
11572
|
const takeProfitPrice = asFiniteNumberOrNull(prices?.takeProfitPrice);
|
|
@@ -11698,142 +11726,57 @@ var buildBaseContextGateFeatures = ({
|
|
|
11698
11726
|
scores.execution,
|
|
11699
11727
|
scores.derivatives
|
|
11700
11728
|
]);
|
|
11701
|
-
const volatilityRisk = extremeVolatilityRisk ? "high" : atrPctRankBucket === "high" || bbWidthRankBucket === "high" ? "medium" : atrPctRankBucket === "unknown" && bbWidthRankBucket === "unknown" ? "unknown" : "low";
|
|
11702
11729
|
const liquidityRisk = venueSpreadSeverity === "wide" || cmcExchangeLiquidityAligned === false ? "high" : venueSpreadSeverity === "elevated" ? "medium" : venueSpreadSeverity === "unknown" && cmcExchangeLiquidityAligned == null ? "unknown" : "low";
|
|
11703
|
-
const regimeRisk = higherTimeframeConflict === true ? "high" : mtfAlignmentForDirection === "neutral" || mtfAlignmentForDirection === "unknown" ? "medium" : "low";
|
|
11704
|
-
const crowdingRisk = derivativesCrowdedForDirection ? "high" : derivativesCrowdedAny ? "medium" : derivativesSummary ? "low" : "unknown";
|
|
11705
|
-
const chaseRisk = direction === "LONG" && rangePositionBucket === "high" && breakoutWithDirection !== true || direction === "SHORT" && rangePositionBucket === "low" && breakoutWithDirection !== true ? "high" : tpDistanceAtr != null && tpDistanceAtr < 1 || rangePositionBucket === "high" || rangePositionBucket === "low" ? "medium" : rangePositionBucket === "unknown" ? "unknown" : "low";
|
|
11706
11730
|
const primaryIssue = derivativesCrowdedForDirection ? "crowded_derivatives" : higherTimeframeConflict === true ? "mtf_conflict" : venueSpreadSeverity === "wide" || cmcExchangeLiquidityAligned === false ? "bad_execution" : extremeVolatilityRisk ? "extreme_volatility" : benchmarkConflict || marketBreadthAligned === false || cmcAltLiquidityAligned === false || cmcEthBtcAligned === false || cmcFearGreedAligned === false || cmcIndexAligned === false || targetVsBtcAligned === false || targetVsEthAligned === false || btcAltRegimeAligned === false ? "market_context_against" : (scores.participation ?? 100) < 45 ? "weak_participation" : (scores.structure ?? 100) < 45 ? "weak_structure" : "none";
|
|
11707
|
-
const needsExtraConfirmation = conflicts.length > 0 || scores.totalContext != null && scores.totalContext < 60;
|
|
11708
11731
|
const approveBias = conflicts.length >= 3 || primaryIssue === "crowded_derivatives" || primaryIssue === "bad_execution" || primaryIssue === "mtf_conflict" ? "reject" : confirmations.length >= 3 && conflicts.length === 0 ? "support" : "neutral";
|
|
11709
|
-
const maxReasonableQuality = approveBias === "reject" ? 2 : conflicts.length >= 2 || needsExtraConfirmation ? 3 : approveBias === "support" ? 5 : 4;
|
|
11710
11732
|
return {
|
|
11711
|
-
direction,
|
|
11712
11733
|
setup: {
|
|
11713
|
-
riskRatio: asFiniteNumberOrNull(prices?.riskRatio),
|
|
11714
11734
|
rewardToVolatility: tpDistanceAtr,
|
|
11715
11735
|
stopDistanceAtr,
|
|
11716
11736
|
tpDistanceAtr,
|
|
11717
11737
|
entryLocation
|
|
11718
11738
|
},
|
|
11719
|
-
scores
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
|
|
11739
|
+
scores: {
|
|
11740
|
+
structure: scores.structure,
|
|
11741
|
+
participation: scores.participation,
|
|
11742
|
+
execution: scores.execution,
|
|
11743
|
+
totalContext: scores.totalContext
|
|
11723
11744
|
},
|
|
11724
11745
|
conflicts: {
|
|
11725
|
-
count: conflicts.length
|
|
11726
|
-
items: conflicts
|
|
11746
|
+
count: conflicts.length
|
|
11727
11747
|
},
|
|
11728
11748
|
risk: {
|
|
11729
|
-
|
|
11730
|
-
liquidityRisk,
|
|
11731
|
-
volatilityRisk,
|
|
11732
|
-
crowdingRisk,
|
|
11733
|
-
chaseRisk
|
|
11749
|
+
liquidityRisk
|
|
11734
11750
|
},
|
|
11735
11751
|
decisionHints: {
|
|
11736
11752
|
approveBias,
|
|
11737
|
-
maxReasonableQuality,
|
|
11738
|
-
needsExtraConfirmation,
|
|
11739
11753
|
primaryIssue
|
|
11740
11754
|
},
|
|
11741
11755
|
mtf: {
|
|
11742
|
-
|
|
11743
|
-
higherTimeframeConflict,
|
|
11744
|
-
h1TrendBias: mtfSummary?.h1TrendBias ?? "unknown",
|
|
11745
|
-
h4TrendBias: mtfSummary?.h4TrendBias ?? "unknown",
|
|
11746
|
-
d1TrendBias: mtfSummary?.d1TrendBias ?? "unknown",
|
|
11747
|
-
h1RangePosition: asFiniteNumberOrNull(mtfSummary?.h1RangePosition),
|
|
11748
|
-
h4VolatilityState: mtfSummary?.h4VolatilityState ?? "unknown"
|
|
11756
|
+
higherTimeframeConflict
|
|
11749
11757
|
},
|
|
11750
11758
|
volatility: {
|
|
11751
11759
|
state: volatility?.state ?? "unknown",
|
|
11752
|
-
atrPctZScore,
|
|
11753
11760
|
atrPctRankBucket,
|
|
11754
|
-
bbWidthRankBucket
|
|
11755
|
-
extremeVolatilityRisk,
|
|
11756
|
-
compressionBreakoutSupport
|
|
11757
|
-
},
|
|
11758
|
-
structure: {
|
|
11759
|
-
breakoutState,
|
|
11760
|
-
rangePositionBucket,
|
|
11761
|
-
breakoutWithDirection,
|
|
11762
|
-
failedBreakoutForDirection,
|
|
11763
|
-
liquiditySweepForDirection,
|
|
11764
|
-
nearPointOfControl
|
|
11761
|
+
bbWidthRankBucket
|
|
11765
11762
|
},
|
|
11766
11763
|
participation: {
|
|
11767
|
-
volumeRel20,
|
|
11768
|
-
volumeBucket: toVolumeBucket(volumeRel20),
|
|
11769
|
-
deltaBias,
|
|
11770
|
-
deltaAligned,
|
|
11771
|
-
tradeFlowBuyPressurePct,
|
|
11772
|
-
tradeFlowAligned,
|
|
11773
|
-
hyperliquidWhaleBuySharePct,
|
|
11774
|
-
hyperliquidWhaleNetNotionalUsd,
|
|
11775
|
-
hyperliquidWhaleUniqueCount,
|
|
11776
|
-
hyperliquidWhaleCoveredCount,
|
|
11777
|
-
hyperliquidWhaleExpectedCount,
|
|
11778
|
-
hyperliquidWhaleCoveragePct,
|
|
11779
|
-
hyperliquidWhaleCoverageSufficient,
|
|
11780
|
-
hyperliquidWhaleNotionalUsd,
|
|
11781
|
-
hyperliquidWhaleSufficientActivity,
|
|
11782
|
-
hyperliquidWhaleFlowAligned,
|
|
11783
|
-
hyperliquidWhaleFlowStale,
|
|
11784
|
-
referenceTradeFlowBuyPressurePct,
|
|
11785
|
-
referenceTradeFlowAligned,
|
|
11786
11764
|
volumeStructureAligned
|
|
11787
11765
|
},
|
|
11788
11766
|
relative: {
|
|
11789
|
-
benchmarkTrendAlignment,
|
|
11790
|
-
benchmarkAligned,
|
|
11791
11767
|
benchmarkConflict,
|
|
11792
|
-
relativeStrength1h,
|
|
11793
|
-
relativeStrengthBucket,
|
|
11794
11768
|
marketBreadthReturn,
|
|
11795
|
-
marketBreadthAligned,
|
|
11796
11769
|
marketBreadthStale: typeof marketBreadth?.stale === "boolean" ? marketBreadth.stale : null,
|
|
11797
|
-
cmcAltLiquidityRegime,
|
|
11798
|
-
cmcAltLiquidityAligned,
|
|
11799
|
-
cmcAltLiquidityStale,
|
|
11800
|
-
cmcEthBtcReferenceRegime,
|
|
11801
|
-
cmcEthBtcAligned,
|
|
11802
|
-
cmcEthBtcStale,
|
|
11803
|
-
cmcExchangeLiquidityRegime,
|
|
11804
11770
|
cmcExchangeLiquidityAligned,
|
|
11805
11771
|
cmcExchangeLiquidityStale,
|
|
11806
11772
|
cmcExchangeLiquidityVolumeChange24hPct,
|
|
11807
11773
|
cmcFearGreedValue,
|
|
11808
11774
|
cmcFearGreedValueChange24h,
|
|
11809
|
-
cmcFearGreedRegime,
|
|
11810
|
-
cmcFearGreedAligned,
|
|
11811
11775
|
cmcFearGreedStale,
|
|
11812
|
-
cmcIndexRegime,
|
|
11813
|
-
cmcIndexAligned,
|
|
11814
|
-
cmcIndexStale,
|
|
11815
11776
|
cmc20ToCmc100RatioChange24hPct,
|
|
11816
|
-
targetVsBtcRatioReturn24h,
|
|
11817
|
-
targetVsBtcAlpha24h,
|
|
11818
|
-
targetVsBtcBeta20,
|
|
11819
|
-
targetVsBtcCorrelation20,
|
|
11820
|
-
targetVsBtcRatioTrend,
|
|
11821
|
-
targetVsBtcAligned,
|
|
11822
|
-
targetVsEthRatioReturn24h,
|
|
11823
|
-
targetVsEthAlpha24h,
|
|
11824
|
-
targetVsEthBeta20,
|
|
11825
|
-
targetVsEthCorrelation20,
|
|
11826
|
-
targetVsEthRatioTrend,
|
|
11827
|
-
targetVsEthAligned,
|
|
11828
11777
|
btcAltRegime: btcAltRegimeValue,
|
|
11829
|
-
btcAltRegimeAligned,
|
|
11830
11778
|
btcAltRegimeStale,
|
|
11831
|
-
btcVsAltReturn24h
|
|
11832
|
-
btcTurnoverShare24h
|
|
11833
|
-
},
|
|
11834
|
-
execution: {
|
|
11835
|
-
venueSpreadZScore,
|
|
11836
|
-
venueSpreadSeverity
|
|
11779
|
+
btcVsAltReturn24h
|
|
11837
11780
|
}
|
|
11838
11781
|
};
|
|
11839
11782
|
};
|
|
@@ -11841,6 +11784,40 @@ var cloneBaseContextData = (baseContext, direction, prices) => {
|
|
|
11841
11784
|
const clone = cloneSignalPayloadDataProperties(
|
|
11842
11785
|
baseContext
|
|
11843
11786
|
);
|
|
11787
|
+
clone.regime = cloneSignalPayloadDataProperties(
|
|
11788
|
+
baseContext.regime
|
|
11789
|
+
);
|
|
11790
|
+
clone.structure = cloneSignalPayloadDataProperties(
|
|
11791
|
+
baseContext.structure
|
|
11792
|
+
);
|
|
11793
|
+
const participation = baseContext.participation;
|
|
11794
|
+
if (participation) {
|
|
11795
|
+
const participationClone = cloneSignalPayloadDataProperties(
|
|
11796
|
+
participation
|
|
11797
|
+
);
|
|
11798
|
+
const priceVolumeProfile = participation.priceVolumeProfile;
|
|
11799
|
+
const volumeStructure = participation.volumeStructure;
|
|
11800
|
+
const delta = participation.delta;
|
|
11801
|
+
if (priceVolumeProfile != null) {
|
|
11802
|
+
participationClone.priceVolumeProfile = cloneSignalPayloadDataProperties(
|
|
11803
|
+
priceVolumeProfile
|
|
11804
|
+
);
|
|
11805
|
+
}
|
|
11806
|
+
if (volumeStructure != null) {
|
|
11807
|
+
participationClone.volumeStructure = cloneSignalPayloadDataProperties(
|
|
11808
|
+
volumeStructure
|
|
11809
|
+
);
|
|
11810
|
+
}
|
|
11811
|
+
if (delta != null) {
|
|
11812
|
+
participationClone.delta = cloneSignalPayloadDataProperties(
|
|
11813
|
+
delta
|
|
11814
|
+
);
|
|
11815
|
+
}
|
|
11816
|
+
clone.participation = participationClone;
|
|
11817
|
+
}
|
|
11818
|
+
clone.relative = cloneSignalPayloadDataProperties(
|
|
11819
|
+
baseContext.relative
|
|
11820
|
+
);
|
|
11844
11821
|
const compactMtf = cloneCompactMtfContext(baseContext);
|
|
11845
11822
|
if (compactMtf) {
|
|
11846
11823
|
clone.mtf = compactMtf;
|