@tradejs/strategies 2.0.1 → 2.0.2
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/index.js +347 -54
- package/dist/index.mjs +347 -54
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -16516,7 +16516,7 @@ AdaptiveMomentumRibbon addon:
|
|
|
16516
16516
|
- \`quality=4\` additionally allows two narrower continuation pockets: oscillatorStrength >= 1.2 with coin bias conflict, structuralRewardRiskRatio >= 2.2 and volumeRel20 <= 1.2, or Europe-session oscillatorStrength >= 1.5 with effortVsResult <= 120.
|
|
16517
16517
|
- If signal candle range is available, \`signalRangeAtrRatio\` must be >= 1.05 for live approval; weaker signal candles stay in watch mode.
|
|
16518
16518
|
- The local deterministic gate approves LONG by default. SHORT stays in watch mode except for separately calibrated market-breadth shock pockets.
|
|
16519
|
-
- SHORT
|
|
16519
|
+
- SHORT watch-mode approvals use three calibrated pockets: BTC-favored breadth shock, neutral shared-context breadth exhaustion with marketBreadth.advancers <= 0 and effortVsResult <= 800, or low-CMC benchmark OI contraction with BTC net flow <= 0.
|
|
16520
16520
|
- A reference-derivatives rotation pocket can approve q4 when XRP 15m OI 4h change >= 1.6 and TRX 15m OI 4h change <= -0.2. It may override weak signal range and the default SHORT watch mode, but never hard signal invalidation.
|
|
16521
16521
|
- Non-derivatives approvals are demoted when stopDistanceAtr > 4.5 and breakoutBodyAtr > 2.25, because that combination behaves like a chase entry.
|
|
16522
16522
|
- All live approvals require a calibrated market-regime floor: tpDistanceAtr >= 2.9, trendAdx >= 15, and benchmarkRelativeStrength1d <= 4 when available.
|
|
@@ -16528,11 +16528,14 @@ AdaptiveMomentumRibbon addon:
|
|
|
16528
16528
|
`;
|
|
16529
16529
|
var ADAPTIVE_MOMENTUM_RIBBON_PAYLOAD_PROMPT = `
|
|
16530
16530
|
- \`payload.additionalIndicators.adaptiveMomentumRibbonContext\` contains a compact signal summary:
|
|
16531
|
-
signalOsc / oscillatorStrength / signalRangeAtrRatio / stopDistanceAtr / tpDistanceAtr / breakoutBodyAtr / trendAdx / benchmarkRelativeStrength1d / chaseRiskBlocked / approvalRegimeAllowed / approvalRegimeBlockReasons / channelState / channelExtensionPct / invalidationDistancePct / structuralRewardRiskRatio / coinBiasAligned / btcBiasAligned / targetVsBtcAlpha1h / targetVsBtcAlpha4h / spreadBps / cmcAltLiquidityRegime / cmcFearGreedValueChange7d / cmcBtcDominanceChange24hPct / baseDecisionApproveBias / marketBreadthAdvancers / marketBreadthAdvanceDeclineRatio / marketBreadthReturn / shortBreadthShockPocket / shortBreadthNeutralPocket / referenceDerivativesRotationPocket / referenceXrpOiChangePct4h15m / referenceTrxOiChangePct4h15m / q4TargetAlpha1Allowed / q4ContinuationAllowed / q4ContinuationBlockReasons / q4ContinuationRecoveryAllowed / derivativesDirectionAligned / derivativesRiskFlags / derivativesFundingZScore / deterministicQuality / approvalAllowedNow / approvalBlockReasons / riskAnnotations.
|
|
16531
|
+
signalOsc / oscillatorStrength / signalRangeAtrRatio / stopDistanceAtr / tpDistanceAtr / breakoutBodyAtr / trendAdx / benchmarkRelativeStrength1d / chaseRiskBlocked / approvalRegimeAllowed / approvalRegimeBlockReasons / channelState / channelExtensionPct / invalidationDistancePct / structuralRewardRiskRatio / coinBiasAligned / btcBiasAligned / targetVsBtcAlpha1h / targetVsBtcAlpha4h / spreadBps / cmcAltLiquidityRegime / cmcTotalMarketCapUsd / cmcFearGreedValueChange7d / cmcBtcDominanceChange24hPct / benchmarkOiChangePct24h1h / btcReferenceTradeFlowNetBaseDelta / baseDecisionApproveBias / marketBreadthAdvancers / marketBreadthAdvanceDeclineRatio / marketBreadthReturn / shortBreadthShockPocket / shortBreadthNeutralPocket / shortCmcBenchmarkContractionPocket / referenceDerivativesRotationPocket / referenceXrpOiChangePct4h15m / referenceTrxOiChangePct4h15m / q4TargetAlpha1Allowed / q4ContinuationAllowed / q4ContinuationBlockReasons / q4ContinuationRecoveryAllowed / derivativesDirectionAligned / derivativesRiskFlags / derivativesFundingZScore / deterministicQuality / approvalAllowedNow / approvalBlockReasons / riskAnnotations.
|
|
16532
16532
|
- Use this context as the primary strategy-specific interpretation instead of re-deriving it only from generic series.
|
|
16533
16533
|
`;
|
|
16534
16534
|
var SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX = -0.01;
|
|
16535
16535
|
var SHORT_BREADTH_NEUTRAL_EFFORT_VS_RESULT_MAX = 800;
|
|
16536
|
+
var SHORT_CMC_TOTAL_MARKET_CAP_USD_MAX = 229e10;
|
|
16537
|
+
var SHORT_BENCHMARK_OI_CHANGE_PCT_24H_1H_MAX = -4;
|
|
16538
|
+
var SHORT_BTC_REFERENCE_TRADE_FLOW_NET_BASE_DELTA_MAX = 0;
|
|
16536
16539
|
var Q4_TARGET_VS_BTC_ALPHA_1H_MAX = 2.4;
|
|
16537
16540
|
var REFERENCE_XRP_OI_CHANGE_PCT_4H_15M_MIN = 1.6;
|
|
16538
16541
|
var REFERENCE_TRX_OI_CHANGE_PCT_4H_15M_MAX = -0.2;
|
|
@@ -16745,7 +16748,7 @@ var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
|
|
|
16745
16748
|
return 3;
|
|
16746
16749
|
}
|
|
16747
16750
|
if (context.signalDirection === "SHORT") {
|
|
16748
|
-
return context.shortBreadthShockPocket || context.shortBreadthNeutralPocket || context.referenceDerivativesRotationPocket ? 4 : 3;
|
|
16751
|
+
return context.shortBreadthShockPocket || context.shortBreadthNeutralPocket || context.shortCmcBenchmarkContractionPocket || context.referenceDerivativesRotationPocket ? 4 : 3;
|
|
16749
16752
|
}
|
|
16750
16753
|
if (context.signalDirection === "LONG" && context.cmcAltLiquidityRegime === "btc_favored") {
|
|
16751
16754
|
return 3;
|
|
@@ -16756,12 +16759,12 @@ var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
|
|
|
16756
16759
|
if (causalMomentumLowEffortPocket) {
|
|
16757
16760
|
return 5;
|
|
16758
16761
|
}
|
|
16762
|
+
if (context.signalDirection === "LONG" && !context.q4TargetAlpha1Allowed) {
|
|
16763
|
+
return 3;
|
|
16764
|
+
}
|
|
16759
16765
|
if (context.referenceDerivativesRotationPocket) {
|
|
16760
16766
|
return 4;
|
|
16761
16767
|
}
|
|
16762
|
-
if (!context.q4TargetAlpha1Allowed) {
|
|
16763
|
-
return 3;
|
|
16764
|
-
}
|
|
16765
16768
|
if (context.q4ContinuationRecoveryAllowed) {
|
|
16766
16769
|
return 4;
|
|
16767
16770
|
}
|
|
@@ -16871,6 +16874,8 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
16871
16874
|
const gateFeaturesRelative = getRecord(gateFeatures?.relative);
|
|
16872
16875
|
const gateFeaturesDecisionHints = getRecord(gateFeatures?.decisionHints);
|
|
16873
16876
|
const baseDerivativesContext = getRecord(baseContext?.derivatives);
|
|
16877
|
+
const baseDerivativesIntervals = getRecord(baseDerivativesContext?.intervals);
|
|
16878
|
+
const baseDerivatives1h = getRecord(baseDerivativesIntervals?.["1h"]);
|
|
16874
16879
|
const referenceDerivativeContexts = getRecord(
|
|
16875
16880
|
baseDerivativesContext?.referenceContexts
|
|
16876
16881
|
);
|
|
@@ -16884,6 +16889,11 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
16884
16889
|
const targetVsBtc = getRecord(relative?.targetVsBtc);
|
|
16885
16890
|
const cmcGlobal = getRecord(relative?.cmcGlobal);
|
|
16886
16891
|
const cmcFearGreed = getRecord(relative?.cmcFearGreed);
|
|
16892
|
+
const referenceTradeFlow = getRecord(relative?.referenceTradeFlow);
|
|
16893
|
+
const referenceTradeFlowBySymbol = getRecord(
|
|
16894
|
+
referenceTradeFlow?.tradeFlowBySymbol
|
|
16895
|
+
);
|
|
16896
|
+
const btcReferenceTradeFlow = getRecord(referenceTradeFlowBySymbol?.BTCUSDT);
|
|
16887
16897
|
const baseMarketBreadth = getRecord(relative?.marketBreadth);
|
|
16888
16898
|
const structureAcceptance = getRecord(structure?.acceptance);
|
|
16889
16899
|
const marketContext = getRecord(additional?.marketContext);
|
|
@@ -16934,12 +16944,21 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
16934
16944
|
);
|
|
16935
16945
|
const referenceDerivativesRotationPocket = referenceXrpOiChangePct4h15m != null && referenceXrpOiChangePct4h15m >= REFERENCE_XRP_OI_CHANGE_PCT_4H_15M_MIN && referenceTrxOiChangePct4h15m != null && referenceTrxOiChangePct4h15m <= REFERENCE_TRX_OI_CHANGE_PCT_4H_15M_MAX;
|
|
16936
16946
|
const cmcAltLiquidityRegime = typeof cmcGlobal?.altLiquidityRegime === "string" && cmcGlobal.altLiquidityRegime.trim().length > 0 ? cmcGlobal.altLiquidityRegime : null;
|
|
16947
|
+
const cmcTotalMarketCapUsd = toFiniteNumberOrNull(
|
|
16948
|
+
cmcGlobal?.totalMarketCapUsd
|
|
16949
|
+
);
|
|
16937
16950
|
const cmcFearGreedValueChange7d = toFiniteNumberOrNull(
|
|
16938
16951
|
cmcFearGreed?.valueChange7d
|
|
16939
16952
|
);
|
|
16940
16953
|
const cmcBtcDominanceChange24hPct = toFiniteNumberOrNull(
|
|
16941
16954
|
cmcGlobal?.btcDominanceChange24hPct
|
|
16942
16955
|
);
|
|
16956
|
+
const benchmarkOiChangePct24h1h = toFiniteNumberOrNull(
|
|
16957
|
+
baseDerivatives1h?.oiChangePct24h
|
|
16958
|
+
);
|
|
16959
|
+
const btcReferenceTradeFlowNetBaseDelta = toFiniteNumberOrNull(
|
|
16960
|
+
btcReferenceTradeFlow?.netBaseDelta
|
|
16961
|
+
);
|
|
16943
16962
|
const baseDecisionApproveBias = gateFeaturesDecisionHints?.approveBias === "support" || gateFeaturesDecisionHints?.approveBias === "neutral" || gateFeaturesDecisionHints?.approveBias === "reject" ? gateFeaturesDecisionHints.approveBias : null;
|
|
16944
16963
|
const marketBreadthAdvanceDeclineRatio = toFiniteNumberOrNull(
|
|
16945
16964
|
marketBreadth?.advanceDeclineRatio
|
|
@@ -16948,6 +16967,7 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
16948
16967
|
const marketBreadthReturn = toFiniteNumberOrNull(gateFeaturesRelative?.marketBreadthReturn) ?? toFiniteNumberOrNull(marketBreadth?.equalWeightedReturn);
|
|
16949
16968
|
const shortBreadthShockPocket = signalDirection === "SHORT" && cmcAltLiquidityRegime === "btc_favored" && marketBreadthAdvanceDeclineRatio != null && marketBreadthAdvanceDeclineRatio <= 0 && marketBreadthReturn != null && marketBreadthReturn <= SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX;
|
|
16950
16969
|
const shortBreadthNeutralPocket = signalDirection === "SHORT" && baseDecisionApproveBias === "neutral" && marketBreadthAdvancers != null && marketBreadthAdvancers <= 0 && marketBreadthReturn != null && marketBreadthReturn <= 0 && isInRange(effortVsResult, 0, SHORT_BREADTH_NEUTRAL_EFFORT_VS_RESULT_MAX);
|
|
16970
|
+
const shortCmcBenchmarkContractionPocket = signalDirection === "SHORT" && cmcTotalMarketCapUsd != null && cmcTotalMarketCapUsd <= SHORT_CMC_TOTAL_MARKET_CAP_USD_MAX && benchmarkOiChangePct24h1h != null && benchmarkOiChangePct24h1h <= SHORT_BENCHMARK_OI_CHANGE_PCT_24H_1H_MAX && btcReferenceTradeFlowNetBaseDelta != null && btcReferenceTradeFlowNetBaseDelta <= SHORT_BTC_REFERENCE_TRADE_FLOW_NET_BASE_DELTA_MAX;
|
|
16951
16971
|
const q4TargetAlpha1Allowed = targetVsBtcAlpha1h == null || targetVsBtcAlpha1h <= Q4_TARGET_VS_BTC_ALPHA_1H_MAX;
|
|
16952
16972
|
const q4ContinuationBlockReasons = getQ4ContinuationBlockReasons({
|
|
16953
16973
|
targetVsBtcAlpha4h,
|
|
@@ -17019,7 +17039,7 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
17019
17039
|
if (signalDirection === "LONG" && derivativesPressure === "crowded_long" || signalDirection === "SHORT" && derivativesPressure === "crowded_short") {
|
|
17020
17040
|
riskAnnotations.push("derivatives_pressure_conflict");
|
|
17021
17041
|
}
|
|
17022
|
-
if (signalDirection === "SHORT" && !(shortBreadthShockPocket || shortBreadthNeutralPocket || referenceDerivativesRotationPocket)) {
|
|
17042
|
+
if (signalDirection === "SHORT" && !(shortBreadthShockPocket || shortBreadthNeutralPocket || shortCmcBenchmarkContractionPocket || referenceDerivativesRotationPocket)) {
|
|
17023
17043
|
approvalBlockReasons.push("short_disabled");
|
|
17024
17044
|
}
|
|
17025
17045
|
if (signalDirection === "LONG" && cmcAltLiquidityRegime === "btc_favored") {
|
|
@@ -17081,14 +17101,18 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
17081
17101
|
spreadBias,
|
|
17082
17102
|
spreadSeverity,
|
|
17083
17103
|
cmcAltLiquidityRegime,
|
|
17104
|
+
cmcTotalMarketCapUsd,
|
|
17084
17105
|
cmcFearGreedValueChange7d,
|
|
17085
17106
|
cmcBtcDominanceChange24hPct,
|
|
17107
|
+
benchmarkOiChangePct24h1h,
|
|
17108
|
+
btcReferenceTradeFlowNetBaseDelta,
|
|
17086
17109
|
baseDecisionApproveBias,
|
|
17087
17110
|
marketBreadthAdvancers,
|
|
17088
17111
|
marketBreadthAdvanceDeclineRatio,
|
|
17089
17112
|
marketBreadthReturn,
|
|
17090
17113
|
shortBreadthShockPocket,
|
|
17091
17114
|
shortBreadthNeutralPocket,
|
|
17115
|
+
shortCmcBenchmarkContractionPocket,
|
|
17092
17116
|
referenceDerivativesRotationPocket,
|
|
17093
17117
|
referenceXrpOiChangePct4h15m,
|
|
17094
17118
|
referenceTrxOiChangePct4h15m,
|
|
@@ -17159,14 +17183,18 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
|
|
|
17159
17183
|
spreadBias,
|
|
17160
17184
|
spreadSeverity,
|
|
17161
17185
|
cmcAltLiquidityRegime,
|
|
17186
|
+
cmcTotalMarketCapUsd,
|
|
17162
17187
|
cmcFearGreedValueChange7d,
|
|
17163
17188
|
cmcBtcDominanceChange24hPct,
|
|
17189
|
+
benchmarkOiChangePct24h1h,
|
|
17190
|
+
btcReferenceTradeFlowNetBaseDelta,
|
|
17164
17191
|
baseDecisionApproveBias,
|
|
17165
17192
|
marketBreadthAdvancers,
|
|
17166
17193
|
marketBreadthAdvanceDeclineRatio,
|
|
17167
17194
|
marketBreadthReturn,
|
|
17168
17195
|
shortBreadthShockPocket,
|
|
17169
17196
|
shortBreadthNeutralPocket,
|
|
17197
|
+
shortCmcBenchmarkContractionPocket,
|
|
17170
17198
|
referenceDerivativesRotationPocket,
|
|
17171
17199
|
referenceXrpOiChangePct4h15m,
|
|
17172
17200
|
referenceTrxOiChangePct4h15m,
|
|
@@ -17305,14 +17333,18 @@ Additional AdaptiveMomentumRibbon context:
|
|
|
17305
17333
|
- spreadBias=${context.spreadBias ?? "n/a"}
|
|
17306
17334
|
- spreadSeverity=${context.spreadSeverity ?? "n/a"}
|
|
17307
17335
|
- cmcAltLiquidityRegime=${context.cmcAltLiquidityRegime ?? "n/a"}
|
|
17336
|
+
- cmcTotalMarketCapUsd=${context.cmcTotalMarketCapUsd?.toFixed?.(0) ?? "n/a"}
|
|
17308
17337
|
- cmcFearGreedValueChange7d=${context.cmcFearGreedValueChange7d?.toFixed?.(3) ?? "n/a"}
|
|
17309
17338
|
- cmcBtcDominanceChange24hPct=${context.cmcBtcDominanceChange24hPct?.toFixed?.(3) ?? "n/a"}
|
|
17339
|
+
- benchmarkOiChangePct24h1h=${context.benchmarkOiChangePct24h1h?.toFixed?.(3) ?? "n/a"}
|
|
17340
|
+
- btcReferenceTradeFlowNetBaseDelta=${context.btcReferenceTradeFlowNetBaseDelta?.toFixed?.(3) ?? "n/a"}
|
|
17310
17341
|
- baseDecisionApproveBias=${context.baseDecisionApproveBias ?? "n/a"}
|
|
17311
17342
|
- marketBreadthAdvancers=${context.marketBreadthAdvancers?.toFixed?.(0) ?? "n/a"}
|
|
17312
17343
|
- marketBreadthAdvanceDeclineRatio=${context.marketBreadthAdvanceDeclineRatio?.toFixed?.(3) ?? "n/a"}
|
|
17313
17344
|
- marketBreadthReturn=${context.marketBreadthReturn?.toFixed?.(5) ?? "n/a"}
|
|
17314
17345
|
- shortBreadthShockPocket=${context.shortBreadthShockPocket}
|
|
17315
17346
|
- shortBreadthNeutralPocket=${context.shortBreadthNeutralPocket}
|
|
17347
|
+
- shortCmcBenchmarkContractionPocket=${context.shortCmcBenchmarkContractionPocket}
|
|
17316
17348
|
- referenceDerivativesRotationPocket=${context.referenceDerivativesRotationPocket}
|
|
17317
17349
|
- referenceXrpOiChangePct4h15m=${context.referenceXrpOiChangePct4h15m?.toFixed?.(3) ?? "n/a"}
|
|
17318
17350
|
- referenceTrxOiChangePct4h15m=${context.referenceTrxOiChangePct4h15m?.toFixed?.(3) ?? "n/a"}
|
|
@@ -17380,6 +17412,9 @@ var MAX_REFERENCE_SHORT_RECOVERY_ETH_LIQ_IMBALANCE_1H = -0.99;
|
|
|
17380
17412
|
var MAX_XRP_SHORT_RECOVERY_BTC_VS_ALT_RETURN_24H = -0.03;
|
|
17381
17413
|
var MAX_XRP_SHORT_RECOVERY_FUNDING_Z_SCORE_1H = -1.8;
|
|
17382
17414
|
var MIN_XRP_OI_REJECT_BIAS_BLOCK_15M = 25e7;
|
|
17415
|
+
var MAX_XRP_OI_RECOVERY_BTC_DOMINANCE_PCT = 58.45;
|
|
17416
|
+
var MIN_XRP_OI_RECOVERY_MARKET_BREADTH_SYMBOLS = 27;
|
|
17417
|
+
var MIN_XRP_OI_RECOVERY_BNB_FUNDING_CHANGE_1H = 0;
|
|
17383
17418
|
var MAX_APPROVAL_RSI = 75;
|
|
17384
17419
|
var MIN_APPROVAL_BB_WIDTH_RANK_100 = 50;
|
|
17385
17420
|
var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
@@ -17388,6 +17423,7 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
|
17388
17423
|
}) => {
|
|
17389
17424
|
const targetDerivatives1h = baseContext?.derivatives?.intervals?.["1h"];
|
|
17390
17425
|
const ethDerivatives1h = baseContext?.derivatives?.referenceContexts?.["ETHUSDT"]?.intervals?.["1h"];
|
|
17426
|
+
const bnbDerivativesSummary = baseContext?.derivatives?.referenceContexts?.["BNBUSDT"]?.summary;
|
|
17391
17427
|
const xrpDerivatives15m = baseContext?.derivatives?.referenceContexts?.["XRPUSDT"]?.intervals?.["15m"];
|
|
17392
17428
|
const xrpDerivatives1h = baseContext?.derivatives?.referenceContexts?.["XRPUSDT"]?.intervals?.["1h"];
|
|
17393
17429
|
const targetDerivatives1hStale = targetDerivatives1h?.stale === true;
|
|
@@ -17405,10 +17441,17 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
|
17405
17441
|
baseContext?.regime?.volatility?.percentiles?.bbWidthRank100
|
|
17406
17442
|
);
|
|
17407
17443
|
const trendFollowState = baseContext?.regime?.trend?.trendFollow?.state ?? null;
|
|
17444
|
+
const volatilityState = baseContext?.regime?.volatility?.state ?? null;
|
|
17408
17445
|
const h4VolatilityState = baseContext?.mtf?.summary?.h4VolatilityState ?? null;
|
|
17409
17446
|
const benchmarkTrendAlignment = baseContext?.relative?.benchmark?.trendAlignment ?? null;
|
|
17410
17447
|
const cmcExchangeLiquidityAligned = typeof baseContext?.gateFeatures?.relative?.cmcExchangeLiquidityAligned === "boolean" ? baseContext.gateFeatures.relative.cmcExchangeLiquidityAligned : null;
|
|
17411
17448
|
const cmcExchangeLiquidityStale = typeof baseContext?.gateFeatures?.relative?.cmcExchangeLiquidityStale === "boolean" ? baseContext.gateFeatures.relative.cmcExchangeLiquidityStale : null;
|
|
17449
|
+
const cmcBtcDominancePct = asFiniteNumber(
|
|
17450
|
+
baseContext?.relative?.cmcGlobal?.btcDominancePct
|
|
17451
|
+
);
|
|
17452
|
+
const marketBreadthSymbolsCount = asFiniteNumber(
|
|
17453
|
+
baseContext?.relative?.marketBreadth?.symbolsCount
|
|
17454
|
+
);
|
|
17412
17455
|
const baseApproveBias = baseContext?.gateFeatures?.decisionHints?.approveBias ?? null;
|
|
17413
17456
|
const targetLiqImbalance1h = asFiniteNumber(
|
|
17414
17457
|
targetDerivatives1h?.liqImbalance
|
|
@@ -17419,6 +17462,9 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
|
17419
17462
|
const targetLiqTotal1h = asFiniteNumber(targetDerivatives1h?.liqTotal);
|
|
17420
17463
|
const ethLiqImbalance1h = asFiniteNumber(ethDerivatives1h?.liqImbalance);
|
|
17421
17464
|
const ethFundingRate1h = asFiniteNumber(ethDerivatives1h?.fundingRate);
|
|
17465
|
+
const bnbFundingChange1h = asFiniteNumber(
|
|
17466
|
+
bnbDerivativesSummary?.fundingChange1h
|
|
17467
|
+
);
|
|
17422
17468
|
const xrpOpenInterest15m = asFiniteNumber(xrpDerivatives15m?.openInterest);
|
|
17423
17469
|
const xrpPriceOiDivergenceType = baseContext?.derivatives?.referenceContexts?.["XRPUSDT"]?.summary?.priceOiDivergenceType ?? null;
|
|
17424
17470
|
const xrpFundingZScore1h = asFiniteNumber(xrpDerivatives1h?.fundingZScore);
|
|
@@ -17456,10 +17502,11 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
|
17456
17502
|
const xrpBtcShortRecoverySetup = direction === "SHORT" && xrpDerivatives1hStale !== true && xrpPriceOiDivergenceType === "price_down_oi_up" && btcVsAltReturn24h != null && btcVsAltReturn24h <= MAX_XRP_SHORT_RECOVERY_BTC_VS_ALT_RETURN_24H && xrpFundingZScore1h != null && xrpFundingZScore1h <= MAX_XRP_SHORT_RECOVERY_FUNDING_Z_SCORE_1H;
|
|
17457
17503
|
const xrpEthShortRecoverySetup = direction === "SHORT" && xrpDerivatives1hStale !== true && ethDerivatives1hStale !== true && xrpPriceOiDivergenceType === "price_down_oi_up" && xrpFundingZScore1h != null && xrpFundingZScore1h <= MAX_XRP_SHORT_RECOVERY_FUNDING_Z_SCORE_1H && ethLiqImbalance1h != null && ethLiqImbalance1h <= MAX_REFERENCE_SHORT_RECOVERY_ETH_LIQ_IMBALANCE_1H;
|
|
17458
17504
|
const xrpShortRecoverySetup = xrpBtcShortRecoverySetup || xrpEthShortRecoverySetup;
|
|
17459
|
-
|
|
17505
|
+
const xrpOiReferenceRecoverySetup = xrpOpenInterest15m != null && xrpOpenInterest15m >= MIN_XRP_OI_REJECT_BIAS_BLOCK_15M && baseApproveBias === "reject" && volatilityState === "expanded" && cmcBtcDominancePct != null && cmcBtcDominancePct <= MAX_XRP_OI_RECOVERY_BTC_DOMINANCE_PCT && marketBreadthSymbolsCount != null && marketBreadthSymbolsCount >= MIN_XRP_OI_RECOVERY_MARKET_BREADTH_SYMBOLS && bnbFundingChange1h != null && bnbFundingChange1h >= MIN_XRP_OI_RECOVERY_BNB_FUNDING_CHANGE_1H;
|
|
17506
|
+
if (xrpOpenInterest15m != null && xrpOpenInterest15m >= MIN_XRP_OI_REJECT_BIAS_BLOCK_15M && baseApproveBias === "reject" && !xrpShortRecoverySetup && !xrpOiReferenceRecoverySetup) {
|
|
17460
17507
|
hardBlockReasons.push("xrp_oi_reject_bias");
|
|
17461
17508
|
}
|
|
17462
|
-
const approvalSetup = longApprovalSetup || xrpShortRecoverySetup;
|
|
17509
|
+
const approvalSetup = longApprovalSetup || xrpShortRecoverySetup || xrpOiReferenceRecoverySetup;
|
|
17463
17510
|
const highConfidenceSetup = longApprovalSetup && breakoutDistancePct >= MIN_HIGH_CONFIDENCE_BREAKOUT_DISTANCE_PCT && channelWidthPct >= MIN_HIGH_CONFIDENCE_CHANNEL_WIDTH_PCT;
|
|
17464
17511
|
let deterministicQuality = 3;
|
|
17465
17512
|
if (hardBlockReasons.length > 0) {
|
|
@@ -17517,15 +17564,19 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
|
|
|
17517
17564
|
rsi,
|
|
17518
17565
|
bbWidthRank100,
|
|
17519
17566
|
trendFollowState,
|
|
17567
|
+
volatilityState,
|
|
17520
17568
|
h4VolatilityState,
|
|
17521
17569
|
benchmarkTrendAlignment,
|
|
17522
17570
|
cmcExchangeLiquidityAligned,
|
|
17523
17571
|
cmcExchangeLiquidityStale,
|
|
17572
|
+
cmcBtcDominancePct,
|
|
17573
|
+
marketBreadthSymbolsCount,
|
|
17524
17574
|
targetLiqImbalance1h,
|
|
17525
17575
|
targetLiqSpikeRatio1h,
|
|
17526
17576
|
targetLiqTotal1h,
|
|
17527
17577
|
ethLiqImbalance1h,
|
|
17528
17578
|
ethFundingRate1h,
|
|
17579
|
+
bnbFundingChange1h,
|
|
17529
17580
|
xrpOpenInterest15m,
|
|
17530
17581
|
xrpPriceOiDivergenceType,
|
|
17531
17582
|
xrpFundingZScore1h,
|
|
@@ -17601,13 +17652,17 @@ Additional AdaptiveTrendChannel context:
|
|
|
17601
17652
|
- rsi=${String(context.rsi ?? "n/a")}
|
|
17602
17653
|
- bbWidthRank100=${String(context.bbWidthRank100 ?? "n/a")}
|
|
17603
17654
|
- trendFollowState=${context.trendFollowState ?? "n/a"}
|
|
17655
|
+
- volatilityState=${context.volatilityState ?? "n/a"}
|
|
17604
17656
|
- h4VolatilityState=${context.h4VolatilityState ?? "n/a"}
|
|
17605
17657
|
- benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
|
|
17658
|
+
- cmcBtcDominancePct=${String(context.cmcBtcDominancePct ?? "n/a")}
|
|
17659
|
+
- marketBreadthSymbolsCount=${String(context.marketBreadthSymbolsCount ?? "n/a")}
|
|
17606
17660
|
- targetLiqImbalance1h=${String(context.targetLiqImbalance1h ?? "n/a")}
|
|
17607
17661
|
- targetLiqSpikeRatio1h=${String(context.targetLiqSpikeRatio1h ?? "n/a")}
|
|
17608
17662
|
- targetLiqTotal1h=${String(context.targetLiqTotal1h ?? "n/a")}
|
|
17609
17663
|
- ethLiqImbalance1h=${String(context.ethLiqImbalance1h ?? "n/a")}
|
|
17610
17664
|
- ethFundingRate1h=${String(context.ethFundingRate1h ?? "n/a")}
|
|
17665
|
+
- bnbFundingChange1h=${String(context.bnbFundingChange1h ?? "n/a")}
|
|
17611
17666
|
- xrpOpenInterest15m=${String(context.xrpOpenInterest15m ?? "n/a")}
|
|
17612
17667
|
- xrpPriceOiDivergenceType=${context.xrpPriceOiDivergenceType ?? "n/a"}
|
|
17613
17668
|
- xrpFundingZScore1h=${String(context.xrpFundingZScore1h ?? "n/a")}
|
|
@@ -17625,7 +17680,7 @@ Interpretation rules for AdaptiveTrendChannel:
|
|
|
17625
17680
|
- The centerline is the adaptive rail; floor/roof are volatility-scaled invalidation bands.
|
|
17626
17681
|
- Prefer flips with reasonable distance from the centerline and confirmation from shared market context.
|
|
17627
17682
|
- Thin participation, missing shared-context confirmation, or missing liquidation-shock recovery evidence should downgrade the setup.
|
|
17628
|
-
- A high-XRP-OI reject bias should remain blocked unless a narrow XRP reference SHORT recovery setup is present.
|
|
17683
|
+
- A high-XRP-OI reject bias should remain blocked unless a narrow XRP reference SHORT recovery setup or expanded CMC/BNB/breadth recovery setup is present.
|
|
17629
17684
|
- Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
|
|
17630
17685
|
`.trim();
|
|
17631
17686
|
},
|
|
@@ -17842,6 +17897,7 @@ var buildEntryStopTargetFigures = ({
|
|
|
17842
17897
|
var MFR_CALIBRATED_LONG_TARGET_VS_BTC_RATIO_RETURN_24H_MAX = -3.3;
|
|
17843
17898
|
var MFR_CALIBRATED_LONG_ETH_VS_BTC_VOLUME_RATIO_MIN = 0.54;
|
|
17844
17899
|
var MFR_CALIBRATED_LONG_H1_RANGE_POSITION_MAX = 0.08;
|
|
17900
|
+
var MFR_AI_LONG_STOP_DISTANCE_ATR_MIN = 24;
|
|
17845
17901
|
var getMarketFlushReversalLongReboundPocketFeatures = (baseContext) => ({
|
|
17846
17902
|
targetVsBtcRatioReturn24h: toFiniteNumberOrNull2(
|
|
17847
17903
|
baseContext?.relative?.targetVsBtc?.ratioReturn24h
|
|
@@ -17859,6 +17915,21 @@ var isMarketFlushReversalCalibratedLongReboundPocket = ({
|
|
|
17859
17915
|
ethVsBtcVolumeRatio,
|
|
17860
17916
|
h1RangePosition
|
|
17861
17917
|
}) => direction === "LONG" && targetVsBtcRatioReturn24h != null && targetVsBtcRatioReturn24h <= MFR_CALIBRATED_LONG_TARGET_VS_BTC_RATIO_RETURN_24H_MAX && (ethVsBtcVolumeRatio != null && ethVsBtcVolumeRatio >= MFR_CALIBRATED_LONG_ETH_VS_BTC_VOLUME_RATIO_MIN || h1RangePosition != null && h1RangePosition <= MFR_CALIBRATED_LONG_H1_RANGE_POSITION_MAX);
|
|
17918
|
+
var getMarketFlushReversalAiLongPocketFeatures = (baseContext) => ({
|
|
17919
|
+
stopDistanceAtr: toFiniteNumberOrNull2(
|
|
17920
|
+
baseContext?.gateFeatures?.setup?.stopDistanceAtr
|
|
17921
|
+
),
|
|
17922
|
+
cmcIndexRegime: baseContext?.relative?.cmcIndexes?.indexRegime ?? null,
|
|
17923
|
+
cmcIndexStale: typeof baseContext?.relative?.cmcIndexes?.stale === "boolean" ? baseContext.relative.cmcIndexes.stale : null,
|
|
17924
|
+
rsiState: baseContext?.regime?.momentum?.rsiState ?? null
|
|
17925
|
+
});
|
|
17926
|
+
var isMarketFlushReversalValidatedAiLongPocket = ({
|
|
17927
|
+
direction,
|
|
17928
|
+
stopDistanceAtr,
|
|
17929
|
+
cmcIndexRegime,
|
|
17930
|
+
cmcIndexStale,
|
|
17931
|
+
rsiState
|
|
17932
|
+
}) => direction === "LONG" && stopDistanceAtr != null && stopDistanceAtr >= MFR_AI_LONG_STOP_DISTANCE_ATR_MIN && cmcIndexRegime === "risk_off" && cmcIndexStale === false && rsiState === "oversold";
|
|
17862
17933
|
|
|
17863
17934
|
// src/MarketFlushReversal/guardrails.ts
|
|
17864
17935
|
var toFiniteNumberOrNull3 = (value) => {
|
|
@@ -17948,6 +18019,12 @@ var buildMarketFlushReversalGuardrailContext = ({
|
|
|
17948
18019
|
direction
|
|
17949
18020
|
});
|
|
17950
18021
|
const { targetVsBtcRatioReturn24h, ethVsBtcVolumeRatio, h1RangePosition } = longReboundPocketFeatures;
|
|
18022
|
+
const aiLongPocketFeatures = getMarketFlushReversalAiLongPocketFeatures(baseContext);
|
|
18023
|
+
const validatedAiLongPocket = isMarketFlushReversalValidatedAiLongPocket({
|
|
18024
|
+
...aiLongPocketFeatures,
|
|
18025
|
+
direction
|
|
18026
|
+
});
|
|
18027
|
+
const { stopDistanceAtr, cmcIndexRegime, cmcIndexStale, rsiState } = aiLongPocketFeatures;
|
|
17951
18028
|
const approvalBlockReasons = [];
|
|
17952
18029
|
const riskAnnotations = [];
|
|
17953
18030
|
if (direction == null) approvalBlockReasons.push("missing_direction");
|
|
@@ -17958,22 +18035,22 @@ var buildMarketFlushReversalGuardrailContext = ({
|
|
|
17958
18035
|
approvalBlockReasons.push("local_participation_not_confirmed");
|
|
17959
18036
|
}
|
|
17960
18037
|
if (!marketContextAvailable) {
|
|
17961
|
-
|
|
18038
|
+
riskAnnotations.push("missing_broad_market_derivatives");
|
|
17962
18039
|
}
|
|
17963
18040
|
if (marketRiskFlags.includes("stale_derivatives")) {
|
|
17964
|
-
|
|
18041
|
+
riskAnnotations.push("stale_broad_market_derivatives");
|
|
17965
18042
|
}
|
|
17966
18043
|
if (marketContextAvailable && broadMarketFlushDirection == null) {
|
|
17967
|
-
|
|
18044
|
+
riskAnnotations.push("no_broad_market_flush");
|
|
17968
18045
|
}
|
|
17969
18046
|
if (direction != null && broadMarketFlushDirection != null && broadMarketFlushDirection !== direction) {
|
|
17970
|
-
|
|
18047
|
+
riskAnnotations.push("broad_market_flush_direction_mismatch");
|
|
17971
18048
|
}
|
|
17972
18049
|
if (direction === "SHORT") {
|
|
17973
18050
|
approvalBlockReasons.push("short_flush_rebound_pocket_not_validated");
|
|
17974
18051
|
}
|
|
17975
|
-
if (direction === "LONG" && !
|
|
17976
|
-
approvalBlockReasons.push("
|
|
18052
|
+
if (direction === "LONG" && !validatedAiLongPocket) {
|
|
18053
|
+
approvalBlockReasons.push("validated_long_ai_pocket_missing");
|
|
17977
18054
|
}
|
|
17978
18055
|
if (signalContext.marketFlushConfirmed !== true) {
|
|
17979
18056
|
riskAnnotations.push("market_flush_not_available_at_core_time");
|
|
@@ -17997,7 +18074,12 @@ var buildMarketFlushReversalGuardrailContext = ({
|
|
|
17997
18074
|
targetVsBtcRatioReturn24h,
|
|
17998
18075
|
ethVsBtcVolumeRatio,
|
|
17999
18076
|
h1RangePosition,
|
|
18000
|
-
calibratedLongRebound
|
|
18077
|
+
calibratedLongRebound,
|
|
18078
|
+
stopDistanceAtr,
|
|
18079
|
+
cmcIndexRegime,
|
|
18080
|
+
cmcIndexStale,
|
|
18081
|
+
rsiState,
|
|
18082
|
+
validatedAiLongPocket
|
|
18001
18083
|
};
|
|
18002
18084
|
return {
|
|
18003
18085
|
...signalContext,
|
|
@@ -18096,6 +18178,11 @@ Additional Market Flush Reversal context:
|
|
|
18096
18178
|
- ethVsBtcVolumeRatio=${String(context.marketFlushReversalGateFeatures.ethVsBtcVolumeRatio ?? "n/a")}
|
|
18097
18179
|
- h1RangePosition=${String(context.marketFlushReversalGateFeatures.h1RangePosition ?? "n/a")}
|
|
18098
18180
|
- calibratedLongRebound=${String(context.marketFlushReversalGateFeatures.calibratedLongRebound)}
|
|
18181
|
+
- stopDistanceAtr=${String(context.marketFlushReversalGateFeatures.stopDistanceAtr ?? "n/a")}
|
|
18182
|
+
- cmcIndexRegime=${context.marketFlushReversalGateFeatures.cmcIndexRegime ?? "n/a"}
|
|
18183
|
+
- cmcIndexStale=${String(context.marketFlushReversalGateFeatures.cmcIndexStale ?? "n/a")}
|
|
18184
|
+
- rsiState=${context.marketFlushReversalGateFeatures.rsiState ?? "n/a"}
|
|
18185
|
+
- validatedAiLongPocket=${String(context.marketFlushReversalGateFeatures.validatedAiLongPocket)}
|
|
18099
18186
|
- approvalAllowedNow=${String(context.approvalAllowedNow)}
|
|
18100
18187
|
- deterministicQuality=${String(context.deterministicQuality)}
|
|
18101
18188
|
- approvalBlockReasons=${context.approvalBlockReasons.join(",") || "none"}
|
|
@@ -18208,6 +18295,7 @@ var buildDoubleTapGateFeatures = ({
|
|
|
18208
18295
|
defaultApprovalAllowed,
|
|
18209
18296
|
q4AltDispersionOk,
|
|
18210
18297
|
q4DerivativesCmcRiskOk,
|
|
18298
|
+
q4DerivativesDirectionSessionOk,
|
|
18211
18299
|
strictMomentumApproved,
|
|
18212
18300
|
strictMomentumRoc1dOk
|
|
18213
18301
|
}) => {
|
|
@@ -18230,6 +18318,7 @@ var buildDoubleTapGateFeatures = ({
|
|
|
18230
18318
|
q4AltDispersionOk,
|
|
18231
18319
|
q4DerivativesPocket,
|
|
18232
18320
|
q4DerivativesCmcRiskOk,
|
|
18321
|
+
q4DerivativesDirectionSessionOk,
|
|
18233
18322
|
strictMomentumApproved,
|
|
18234
18323
|
strictMomentumRoc1dOk
|
|
18235
18324
|
};
|
|
@@ -18408,7 +18497,8 @@ var buildDoubleTapAiContext = (payload) => {
|
|
|
18408
18497
|
const q4CmcApproval = legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && baseIndicatorCandidate && cmcBtcDominanceChange24hPct != null && cmcBtcDominanceChange24hPct > Q4_CMC_BTC_DOMINANCE_CHANGE_MIN && cmcBtcDominanceChange24hPct <= Q4_CMC_BTC_DOMINANCE_CHANGE_MAX && altDispersion24h != null && altDispersion24h < Q4_ALT_DISPERSION_24H_MAX;
|
|
18409
18498
|
const q4DerivativesBadCmcPocket = btcVsAltReturn24h != null && cmc20ToCmc100RatioChange24hPct != null && btcVsAltReturn24h <= Q4_DERIVATIVES_BAD_BTC_VS_ALT_RETURN_24H_MAX && cmc20ToCmc100RatioChange24hPct <= Q4_DERIVATIVES_BAD_CMC20_TO_CMC100_CHANGE_24H_MAX;
|
|
18410
18499
|
const q4DerivativesPocket = baseContextAvailable && btcVsAltReturn24h != null && ethCrowdingPersistenceBars != null && solFundingZScore15m != null && btcVsAltReturn24h <= Q4_DERIVATIVES_BTC_VS_ALT_RETURN_24H_MAX && ethCrowdingPersistenceBars >= Q4_DERIVATIVES_ETH_CROWDING_PERSISTENCE_MIN && solFundingZScore15m <= Q4_DERIVATIVES_SOL_FUNDING_Z_SCORE_15M_MAX;
|
|
18411
|
-
const
|
|
18500
|
+
const q4DerivativesDirectionSessionOk = q4DerivativesPocket ? signalDirection === "LONG" ? primarySession === "europe" : signalDirection === "SHORT" ? true : false : null;
|
|
18501
|
+
const q4DerivativesApproval = q4DerivativesPocket && q4DerivativesDirectionSessionOk === true && !q4DerivativesBadCmcPocket;
|
|
18412
18502
|
const softBlockReasons = [
|
|
18413
18503
|
...legacyShapeCandidate && sessionWindowPhase !== "active" ? ["inactive_session_window"] : [],
|
|
18414
18504
|
...legacyShapeCandidate && (executionScore == null || executionScore < MIN_EXECUTION_SCORE_FOR_AI_GATE) ? ["low_or_missing_execution_score"] : [],
|
|
@@ -18421,7 +18511,9 @@ var buildDoubleTapAiContext = (payload) => {
|
|
|
18421
18511
|
...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct != null && (cmcBtcDominanceChange24hPct <= Q4_CMC_BTC_DOMINANCE_CHANGE_MIN || cmcBtcDominanceChange24hPct > Q4_CMC_BTC_DOMINANCE_CHANGE_MAX) ? ["cmc_btc_dominance_change_outside_band"] : [],
|
|
18422
18512
|
...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct != null && cmcBtcDominanceChange24hPct > Q4_CMC_BTC_DOMINANCE_CHANGE_MIN && cmcBtcDominanceChange24hPct <= Q4_CMC_BTC_DOMINANCE_CHANGE_MAX && altDispersion24h == null ? ["missing_alt_dispersion_24h_for_q4"] : [],
|
|
18423
18513
|
...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && altDispersion24h != null && altDispersion24h >= Q4_ALT_DISPERSION_24H_MAX ? ["alt_dispersion_24h_too_high_for_q4"] : [],
|
|
18424
|
-
...q4CmcApproval ? ["legacy_q4_structural_observation_only"] : []
|
|
18514
|
+
...q4CmcApproval ? ["legacy_q4_structural_observation_only"] : [],
|
|
18515
|
+
...q4DerivativesPocket && signalDirection === "LONG" && q4DerivativesDirectionSessionOk === false ? ["long_q4_derivatives_outside_europe_session"] : [],
|
|
18516
|
+
...q4DerivativesPocket && signalDirection == null ? ["missing_signal_direction_for_q4_derivatives"] : []
|
|
18425
18517
|
];
|
|
18426
18518
|
const highPrecisionApprovalBlocked = legacyHighPrecisionShapeCandidate && !highPrecisionCmcApproval && !q4DerivativesApproval;
|
|
18427
18519
|
const q4DerivativesApprovalBlocked = q4DerivativesPocket && !q4DerivativesApproval && !highPrecisionCmcApproval;
|
|
@@ -18457,6 +18549,7 @@ var buildDoubleTapAiContext = (payload) => {
|
|
|
18457
18549
|
defaultApprovalAllowed,
|
|
18458
18550
|
q4AltDispersionOk: altDispersion24h == null ? null : altDispersion24h < Q4_ALT_DISPERSION_24H_MAX,
|
|
18459
18551
|
q4DerivativesCmcRiskOk: btcVsAltReturn24h == null || cmc20ToCmc100RatioChange24hPct == null ? null : !q4DerivativesBadCmcPocket,
|
|
18552
|
+
q4DerivativesDirectionSessionOk,
|
|
18460
18553
|
strictMomentumApproved: strictMomentumApprovalAllowedNow,
|
|
18461
18554
|
strictMomentumRoc1dOk
|
|
18462
18555
|
});
|
|
@@ -18490,6 +18583,7 @@ var buildDoubleTapAiContext = (payload) => {
|
|
|
18490
18583
|
ethCrowdingPersistenceBars,
|
|
18491
18584
|
solFundingZScore15m,
|
|
18492
18585
|
altDispersion24h,
|
|
18586
|
+
q4DerivativesDirectionSessionOk,
|
|
18493
18587
|
doubleTapGateFeatures,
|
|
18494
18588
|
structuralHardBlockReasons,
|
|
18495
18589
|
softBlockReasons,
|
|
@@ -18594,6 +18688,7 @@ Additional DoubleTap context:
|
|
|
18594
18688
|
- doubleTapGateQ4AltDispersionOk=${String(context.doubleTapGateFeatures.q4AltDispersionOk ?? "n/a")}
|
|
18595
18689
|
- doubleTapGateQ4DerivativesPocket=${String(context.doubleTapGateFeatures.q4DerivativesPocket)}
|
|
18596
18690
|
- doubleTapGateQ4DerivativesCmcRiskOk=${String(context.doubleTapGateFeatures.q4DerivativesCmcRiskOk ?? "n/a")}
|
|
18691
|
+
- doubleTapGateQ4DerivativesDirectionSessionOk=${String(context.doubleTapGateFeatures.q4DerivativesDirectionSessionOk ?? "n/a")}
|
|
18597
18692
|
- doubleTapGateStrictMomentumApproved=${String(context.doubleTapGateFeatures.strictMomentumApproved)}
|
|
18598
18693
|
- doubleTapGateStrictMomentumRoc1dOk=${String(context.doubleTapGateFeatures.strictMomentumRoc1dOk ?? "n/a")}
|
|
18599
18694
|
- deterministicQuality=${String(context.deterministicQuality)}
|
|
@@ -18611,7 +18706,7 @@ Interpretation rules for DoubleTap:
|
|
|
18611
18706
|
- Treat deterministicQuality and approvalAllowedNow as the normalized local gate result.
|
|
18612
18707
|
- Local q5 approval needs the high-precision pocket plus active session window, execution score >= 35, lowTouchCount20 >= 1, aligned volume structure, no benchmark conflict, and CMC alt volume change <= 0.5.
|
|
18613
18708
|
- The legacy structural q4 CMC pocket is retained only as observation context and should not be treated as local approval.
|
|
18614
|
-
- Local q4 approval comes from the derivatives reference pocket: BTC underperforms alts by at least 0.9%, ETH crowding persistence >= 140, SOL 15m funding z-score <= 0.2, unless BTC underperforms alts by at least 1.4% while CMC20/CMC100 ratio change <= -0.0007.
|
|
18709
|
+
- Local q4 approval comes from the derivatives reference pocket: BTC underperforms alts by at least 0.9%, ETH crowding persistence >= 140, SOL 15m funding z-score <= 0.2, unless BTC underperforms alts by at least 1.4% while CMC20/CMC100 ratio change <= -0.0007; LONG q4 derivatives approval additionally requires the Europe session, while SHORT q4 derivatives approval has no session-side restriction.
|
|
18615
18710
|
- Main local approval additionally needs strict momentum confirmation with ROC1D >= -5.25 for q5 approval; the derivatives reference q4 pocket is already momentum/positioning filtered and does not require that ROC gate.
|
|
18616
18711
|
- A good long has two comparable lows and a clean close above the neckline.
|
|
18617
18712
|
- A good short has two comparable highs and a clean close below the neckline.
|
|
@@ -18695,6 +18790,8 @@ var MAX_APPROVAL_PRICE_DISTANCE_TO_MA_SLOW_ATR = 1.2;
|
|
|
18695
18790
|
var MIN_APPROVAL_ACTIVE_LIQUIDITY_ZONES = 1;
|
|
18696
18791
|
var MAX_DERIVATIVES_RISK_OFF_ALT_BASKET_RETURN_24H = -0.035;
|
|
18697
18792
|
var MAX_DERIVATIVES_RISK_OFF_TRX_OI_CHANGE_PCT_4H = -1.8;
|
|
18793
|
+
var MIN_BENCHMARK_FLOW_BUY_PRESSURE_PCT = 0.61;
|
|
18794
|
+
var MIN_BENCHMARK_OI_ACCELERATION = 0.55;
|
|
18698
18795
|
var Q4_APPROVAL_ATR_RANK_BUCKETS = /* @__PURE__ */ new Set(["high", "extreme"]);
|
|
18699
18796
|
var buildLiquidityTailsGateFeatures = ({
|
|
18700
18797
|
signalContext,
|
|
@@ -18799,10 +18896,17 @@ var buildLiquidityTailsGuardrailContext = ({
|
|
|
18799
18896
|
const flushSupport = direction === "LONG" ? derivativesRiskFlags.includes("short_liquidation_spike") || derivativesPressure === "short_flush" : direction === "SHORT" ? derivativesRiskFlags.includes("long_liquidation_spike") || derivativesPressure === "long_flush" : false;
|
|
18800
18897
|
const directionalCrowding = direction === "LONG" ? derivativesRiskFlags.includes("crowded_long") : direction === "SHORT" ? derivativesRiskFlags.includes("crowded_short") : false;
|
|
18801
18898
|
const derivativesRiskOffLongRecoveryPocket = direction === "LONG" && cmcFearGreedValue != null && cmcFearGreedValue <= MAX_APPROVAL_CMC_FEAR_GREED_VALUE && altBasketReturn24h != null && altBasketReturn24h <= MAX_DERIVATIVES_RISK_OFF_ALT_BASKET_RETURN_24H && referenceTrx1hStale === false && referenceTrx1hOiChangePct4h != null && referenceTrx1hOiChangePct4h <= MAX_DERIVATIVES_RISK_OFF_TRX_OI_CHANGE_PCT_4H;
|
|
18802
|
-
|
|
18899
|
+
const referenceTradeFlowBuyPressurePct = asFiniteNumber2(
|
|
18900
|
+
baseContext?.gateFeatures?.participation?.referenceTradeFlowBuyPressurePct
|
|
18901
|
+
);
|
|
18902
|
+
const benchmarkOiAcceleration = asFiniteNumber2(
|
|
18903
|
+
derivativesSummary?.oiAcceleration
|
|
18904
|
+
);
|
|
18905
|
+
const benchmarkFlowOiExpansionRecoveryPocket = (direction === "LONG" || direction === "SHORT") && q4AtrRankEligible && referenceTradeFlowBuyPressurePct != null && referenceTradeFlowBuyPressurePct >= MIN_BENCHMARK_FLOW_BUY_PRESSURE_PCT && benchmarkOiAcceleration != null && benchmarkOiAcceleration >= MIN_BENCHMARK_OI_ACCELERATION;
|
|
18906
|
+
if (derivativesDirectionAligned === true && !flushSupport && !derivativesRiskOffLongRecoveryPocket && !benchmarkFlowOiExpansionRecoveryPocket) {
|
|
18803
18907
|
hardBlockReasons.push("derivatives_reversal_aligned");
|
|
18804
18908
|
}
|
|
18805
|
-
if (derivativesDirectionAligned === false && !flushSupport && !derivativesRiskOffLongRecoveryPocket) {
|
|
18909
|
+
if (derivativesDirectionAligned === false && !flushSupport && !derivativesRiskOffLongRecoveryPocket && !benchmarkFlowOiExpansionRecoveryPocket) {
|
|
18806
18910
|
hardBlockReasons.push("derivatives_reversal_conflict");
|
|
18807
18911
|
}
|
|
18808
18912
|
if (volumeRel20 != null && volumeRel20 < 0.75) {
|
|
@@ -18892,6 +18996,9 @@ var buildLiquidityTailsGuardrailContext = ({
|
|
|
18892
18996
|
softBlockReasons.push(...approvalContextReasons);
|
|
18893
18997
|
}
|
|
18894
18998
|
}
|
|
18999
|
+
if (deterministicQuality < 4 && hardBlockReasons.length === 0 && benchmarkFlowOiExpansionRecoveryPocket) {
|
|
19000
|
+
deterministicQuality = 4;
|
|
19001
|
+
}
|
|
18895
19002
|
return {
|
|
18896
19003
|
...signalContext,
|
|
18897
19004
|
baseContextAvailable: Boolean(baseContext),
|
|
@@ -18922,6 +19029,7 @@ var buildLiquidityTailsGuardrailContext = ({
|
|
|
18922
19029
|
derivativesRiskFlags,
|
|
18923
19030
|
cadenceUpgradePocket,
|
|
18924
19031
|
derivativesRiskOffLongRecoveryPocket,
|
|
19032
|
+
benchmarkFlowOiExpansionRecoveryPocket,
|
|
18925
19033
|
liquidityTailsGateFeatures,
|
|
18926
19034
|
hardBlockReasons,
|
|
18927
19035
|
softBlockReasons,
|
|
@@ -19092,6 +19200,9 @@ var isDirectionalPriceAboveLevel = ({
|
|
|
19092
19200
|
price,
|
|
19093
19201
|
level
|
|
19094
19202
|
}) => direction === "LONG" ? price != null && level != null && price > level : direction === "SHORT" ? price != null && level != null && price < level : null;
|
|
19203
|
+
var TRANSITION_LOW_TOUCH_COUNT_MAX = 2;
|
|
19204
|
+
var ETH_REFERENCE_WEAK_NON_STRESS_OI_CHANGE_PCT_24H_MAX = -2.5;
|
|
19205
|
+
var LONG_DIRECT_INDICATOR_SUPPORT_MIN = 2;
|
|
19095
19206
|
var buildLiquidityZonesGuardrailContext = ({
|
|
19096
19207
|
signalContext,
|
|
19097
19208
|
baseContext
|
|
@@ -19252,12 +19363,15 @@ var buildLiquidityZonesGuardrailContext = ({
|
|
|
19252
19363
|
const isContinuationBreakoutRetest = direction === "LONG" ? breakoutState === "above_high_level" || entryLocation === "breakout" : direction === "SHORT" ? breakoutState === "below_low_level" || entryLocation === "breakdown" : false;
|
|
19253
19364
|
const hasBaseRetestConfirmation = filterMetric >= 3 && hitCount >= 2 && reactionCloseDistancePct >= 0.08 && retestPenetrationPct <= 90;
|
|
19254
19365
|
const ethReferenceOiWeakPocket = ethReferenceOiChangePct4h != null && ethReferenceOiChangePct4h <= -0.8;
|
|
19255
|
-
const transitionStructureExpansionPocket = hasBaseRetestConfirmation && structureZoneState === "transition" && structureScore != null && structureScore >= 17 && adaptiveChannelFlipDown === false && !directionalCrowding && !ethReferenceOiWeakPocket;
|
|
19256
19366
|
const ethReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && ethReferenceOiChangePct24h != null && ethReferenceOiChangePct24h <= -5.8 && ethReferenceFundingZScore != null && ethReferenceFundingZScore <= -1.05;
|
|
19367
|
+
const transitionStructureExpansionPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= TRANSITION_LOW_TOUCH_COUNT_MAX && structureZoneState === "transition" && structureScore != null && structureScore >= 17 && adaptiveChannelFlipDown === false && !directionalCrowding && !ethReferenceOiWeakPocket;
|
|
19257
19368
|
const solReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && solReferenceOiChangePct24h != null && solReferenceOiChangePct24h <= -4.2 && solReferenceFundingZScore != null && solReferenceFundingZScore <= -1.2;
|
|
19258
19369
|
const calibratedExpansionPocket = transitionStructureExpansionPocket || ethReferenceStressPocket || solReferenceStressPocket;
|
|
19370
|
+
const ethReferenceWeakNonStressPocket = ethReferenceOiChangePct24h != null && ethReferenceOiChangePct24h <= ETH_REFERENCE_WEAK_NON_STRESS_OI_CHANGE_PCT_24H_MAX && !ethReferenceStressPocket;
|
|
19371
|
+
const longDirectIndicatorSupportConfirmed = direction === "LONG" ? directIndicatorSupportCount != null && directIndicatorSupportCount >= LONG_DIRECT_INDICATOR_SUPPORT_MIN : null;
|
|
19259
19372
|
const longRequiresCalibratedExpansion = direction === "LONG" && !calibratedExpansionPocket;
|
|
19260
|
-
const
|
|
19373
|
+
const longDirectIndicatorSupportMissing = longDirectIndicatorSupportConfirmed === false;
|
|
19374
|
+
const approvalDisqualifiedByCalibration = !calibratedExpansionPocket && (longRequiresCalibratedExpansion || isContinuationBreakoutRetest || hasOverextendedVolumeConfirmation || hasIsolatedIndicatorSupport) || ethReferenceWeakNonStressPocket || longDirectIndicatorSupportMissing;
|
|
19261
19375
|
if (longRequiresCalibratedExpansion) {
|
|
19262
19376
|
softBlockReasons.push("long_liquidity_retest_requires_recalibration");
|
|
19263
19377
|
}
|
|
@@ -19270,6 +19384,12 @@ var buildLiquidityZonesGuardrailContext = ({
|
|
|
19270
19384
|
if (hasIsolatedIndicatorSupport) {
|
|
19271
19385
|
softBlockReasons.push("isolated_indicator_support");
|
|
19272
19386
|
}
|
|
19387
|
+
if (ethReferenceWeakNonStressPocket) {
|
|
19388
|
+
softBlockReasons.push("eth_reference_oi_weak_without_stress");
|
|
19389
|
+
}
|
|
19390
|
+
if (longDirectIndicatorSupportMissing) {
|
|
19391
|
+
softBlockReasons.push("long_direct_indicator_support_missing");
|
|
19392
|
+
}
|
|
19273
19393
|
const hasLongBreakoutConfirmation = direction === "LONG" && (breakoutState === "below_low_level" || breakoutState === "above_high_level") && reactionCloseDistancePct >= 1 && volumeRel20 != null && volumeRel20 >= 2 && venueSpreadZScore != null && venueSpreadZScore >= 0;
|
|
19274
19394
|
const hasShortContinuationConfirmation = direction === "SHORT" && hasVolumeConfirmation;
|
|
19275
19395
|
let deterministicQuality = 3;
|
|
@@ -19336,6 +19456,8 @@ var buildLiquidityZonesGuardrailContext = ({
|
|
|
19336
19456
|
transitionStructureExpansionPocket,
|
|
19337
19457
|
ethReferenceStressPocket,
|
|
19338
19458
|
solReferenceStressPocket,
|
|
19459
|
+
ethReferenceWeakNonStressPocket,
|
|
19460
|
+
longDirectIndicatorSupportConfirmed,
|
|
19339
19461
|
hardBlockReasons,
|
|
19340
19462
|
softBlockReasons,
|
|
19341
19463
|
deterministicQuality,
|
|
@@ -19429,6 +19551,7 @@ Additional Liquidity Zones context:
|
|
|
19429
19551
|
- obvLevelAligned=${String(context.obvLevelAligned ?? "n/a")}
|
|
19430
19552
|
- obvSlopeAligned=${String(context.obvSlopeAligned ?? "n/a")}
|
|
19431
19553
|
- directIndicatorSupportCount=${String(context.directIndicatorSupportCount ?? "n/a")}
|
|
19554
|
+
- longDirectIndicatorSupportConfirmed=${String(context.longDirectIndicatorSupportConfirmed ?? "n/a")}
|
|
19432
19555
|
- venueSpreadZScore=${String(context.venueSpreadZScore ?? "n/a")}
|
|
19433
19556
|
- benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
|
|
19434
19557
|
- btcCorrelation=${String(context.btcCorrelation ?? "n/a")}
|
|
@@ -19447,6 +19570,7 @@ Additional Liquidity Zones context:
|
|
|
19447
19570
|
- transitionStructureExpansionPocket=${String(context.transitionStructureExpansionPocket)}
|
|
19448
19571
|
- ethReferenceStressPocket=${String(context.ethReferenceStressPocket)}
|
|
19449
19572
|
- solReferenceStressPocket=${String(context.solReferenceStressPocket)}
|
|
19573
|
+
- ethReferenceWeakNonStressPocket=${String(context.ethReferenceWeakNonStressPocket)}
|
|
19450
19574
|
- deterministicQuality=${context.deterministicQuality}
|
|
19451
19575
|
- approvalAllowedNow=${String(context.approvalAllowedNow)}
|
|
19452
19576
|
- hardBlockReasons=${JSON.stringify(context.hardBlockReasons)}
|
|
@@ -19462,6 +19586,8 @@ Interpretation rules for Liquidity Zones:
|
|
|
19462
19586
|
- Top-level derivatives context is BTC benchmark evidence; target-symbol derivatives require targetContext/targetDerived.
|
|
19463
19587
|
- Do not treat derivatives points, rows, or loaded-history size as approval evidence.
|
|
19464
19588
|
- A calibrated transition-structure pocket, ETH reference stress pocket, or SOL reference stress pocket can approve a structurally valid retest.
|
|
19589
|
+
- LONG approvals need at least two direct MA/MACD/OBV alignments after calibration.
|
|
19590
|
+
- Moderate ETH reference OI weakness blocks approval unless the deeper ETH reference stress pocket is active.
|
|
19465
19591
|
- Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
|
|
19466
19592
|
`.trim();
|
|
19467
19593
|
},
|
|
@@ -19927,6 +20053,16 @@ var getNestedString2 = (value, path) => {
|
|
|
19927
20053
|
}
|
|
19928
20054
|
return typeof current === "string" ? current : null;
|
|
19929
20055
|
};
|
|
20056
|
+
var getNestedBoolean2 = (value, path) => {
|
|
20057
|
+
let current = value;
|
|
20058
|
+
for (const segment of path) {
|
|
20059
|
+
if (!isRecord2(current)) {
|
|
20060
|
+
return null;
|
|
20061
|
+
}
|
|
20062
|
+
current = current[segment];
|
|
20063
|
+
}
|
|
20064
|
+
return typeof current === "boolean" ? current : null;
|
|
20065
|
+
};
|
|
19930
20066
|
var isShortBtcOnlyRecoveryLane = (context, baseContext) => {
|
|
19931
20067
|
const riskFlags = getNestedRecord2(baseContext, [
|
|
19932
20068
|
"derivatives",
|
|
@@ -19951,23 +20087,59 @@ var isShortBtcOnlyRecoveryLane = (context, baseContext) => {
|
|
|
19951
20087
|
const biasConflictState = getReverseTrendlineBiasConflictState(context);
|
|
19952
20088
|
return context.signalDirection === "SHORT" && context.entryTiming === "ready_rejection" && biasConflictState === "btc_only" && context.deterministicRejectionScore != null && context.deterministicRejectionScore >= 6 && context.distance != null && context.distance >= 61 && !hasMissingDerivatives && (derivativesPressure === "long_flush" || derivativesPressure === "short_flush" || derivativesPressure === "crowded_long") && volumeRel20 != null && volumeRel20 >= 1.5 && rangePosition20 != null && rangePosition20 >= 0.2 && rangePosition20 <= 0.7;
|
|
19953
20089
|
};
|
|
20090
|
+
var hasMissingDerivativesRisk = (baseContext) => {
|
|
20091
|
+
const riskFlags = getNestedRecord2(baseContext, [
|
|
20092
|
+
"derivatives",
|
|
20093
|
+
"summary"
|
|
20094
|
+
])?.riskFlags;
|
|
20095
|
+
return Array.isArray(riskFlags) && riskFlags.includes("missing_derivatives");
|
|
20096
|
+
};
|
|
20097
|
+
var isExtremeVolatilityRecoveryLane = (context, baseContext) => {
|
|
20098
|
+
if (context.hardBlockReasons.length > 0) {
|
|
20099
|
+
return false;
|
|
20100
|
+
}
|
|
20101
|
+
const primaryIssue = getNestedString2(baseContext, [
|
|
20102
|
+
"gateFeatures",
|
|
20103
|
+
"decisionHints",
|
|
20104
|
+
"primaryIssue"
|
|
20105
|
+
]);
|
|
20106
|
+
const approveBias = getNestedString2(baseContext, [
|
|
20107
|
+
"gateFeatures",
|
|
20108
|
+
"decisionHints",
|
|
20109
|
+
"approveBias"
|
|
20110
|
+
]);
|
|
20111
|
+
const upCloseStreak = getNestedNumber2(baseContext, [
|
|
20112
|
+
"regime",
|
|
20113
|
+
"momentum",
|
|
20114
|
+
"upCloseStreak"
|
|
20115
|
+
]);
|
|
20116
|
+
const adaptiveChannelFlipUp = getNestedBoolean2(baseContext, [
|
|
20117
|
+
"regime",
|
|
20118
|
+
"trend",
|
|
20119
|
+
"adaptiveChannel",
|
|
20120
|
+
"flipUp"
|
|
20121
|
+
]);
|
|
20122
|
+
const atrPctRank100 = getNestedNumber2(baseContext, [
|
|
20123
|
+
"regime",
|
|
20124
|
+
"volatility",
|
|
20125
|
+
"percentiles",
|
|
20126
|
+
"atrPctRank100"
|
|
20127
|
+
]);
|
|
20128
|
+
return primaryIssue === "extreme_volatility" && approveBias === "reject" && upCloseStreak != null && upCloseStreak <= 2 && adaptiveChannelFlipUp === false && atrPctRank100 != null && atrPctRank100 <= 99 && !hasMissingDerivativesRisk(baseContext);
|
|
20129
|
+
};
|
|
19954
20130
|
var getBaseContextQualityPromotion = (context, signal) => {
|
|
19955
20131
|
const baseContext = isRecord2(signal.additionalIndicators?.baseContext) ? signal.additionalIndicators.baseContext : null;
|
|
19956
20132
|
if (!baseContext) {
|
|
19957
20133
|
return null;
|
|
19958
20134
|
}
|
|
19959
|
-
return isShortBtcOnlyRecoveryLane(context, baseContext) ? 4 : null;
|
|
20135
|
+
return isShortBtcOnlyRecoveryLane(context, baseContext) || isExtremeVolatilityRecoveryLane(context, baseContext) ? 4 : null;
|
|
19960
20136
|
};
|
|
19961
20137
|
var getBaseContextApprovalBlockReasons = (context, signal) => {
|
|
19962
20138
|
const baseContext = isRecord2(signal.additionalIndicators?.baseContext) ? signal.additionalIndicators.baseContext : null;
|
|
19963
20139
|
if (!baseContext) {
|
|
19964
20140
|
return [];
|
|
19965
20141
|
}
|
|
19966
|
-
const
|
|
19967
|
-
"derivatives",
|
|
19968
|
-
"summary"
|
|
19969
|
-
])?.riskFlags;
|
|
19970
|
-
const hasMissingDerivatives = Array.isArray(riskFlags) && riskFlags.includes("missing_derivatives");
|
|
20142
|
+
const hasMissingDerivatives = hasMissingDerivativesRisk(baseContext);
|
|
19971
20143
|
const volumeRel20 = getNestedNumber2(baseContext, [
|
|
19972
20144
|
"participation",
|
|
19973
20145
|
"volume",
|
|
@@ -20003,6 +20175,10 @@ var getBaseContextApprovalBlockReasons = (context, signal) => {
|
|
|
20003
20175
|
context,
|
|
20004
20176
|
baseContext
|
|
20005
20177
|
);
|
|
20178
|
+
const extremeVolatilityRecoveryLane = isExtremeVolatilityRecoveryLane(
|
|
20179
|
+
context,
|
|
20180
|
+
baseContext
|
|
20181
|
+
);
|
|
20006
20182
|
const reasons = [];
|
|
20007
20183
|
if (hasMissingDerivatives) {
|
|
20008
20184
|
reasons.push("missing_derivatives");
|
|
@@ -20022,7 +20198,7 @@ var getBaseContextApprovalBlockReasons = (context, signal) => {
|
|
|
20022
20198
|
if (context.signalDirection === "SHORT" && biasConflictState === "btc_only" && context.distance != null && context.distance <= 60) {
|
|
20023
20199
|
reasons.push("short_btc_conflict_too_shallow");
|
|
20024
20200
|
}
|
|
20025
|
-
if (context.signalDirection === "SHORT" && atrPctZScore != null && atrPctZScore >= 2 && !shortBtcOnlyRecoveryLane) {
|
|
20201
|
+
if (context.signalDirection === "SHORT" && atrPctZScore != null && atrPctZScore >= 2 && !shortBtcOnlyRecoveryLane && !extremeVolatilityRecoveryLane) {
|
|
20026
20202
|
reasons.push("short_extreme_volatility");
|
|
20027
20203
|
}
|
|
20028
20204
|
if (context.signalDirection === "SHORT" && rangePosition20 != null && rangePosition20 < 0.2) {
|
|
@@ -20043,7 +20219,9 @@ var buildReverseTrendLineGateFeatures = ({
|
|
|
20043
20219
|
context,
|
|
20044
20220
|
signal,
|
|
20045
20221
|
approvalBlockReasons,
|
|
20046
|
-
deterministicRejectionScore
|
|
20222
|
+
deterministicRejectionScore,
|
|
20223
|
+
approvalLane,
|
|
20224
|
+
extremeVolatilityRecoveryPocket
|
|
20047
20225
|
}) => {
|
|
20048
20226
|
const baseContext = isRecord2(signal.additionalIndicators?.baseContext) ? signal.additionalIndicators.baseContext : null;
|
|
20049
20227
|
const volumeRel20 = getNestedNumber2(baseContext, [
|
|
@@ -20077,6 +20255,8 @@ var buildReverseTrendLineGateFeatures = ({
|
|
|
20077
20255
|
volatilityState,
|
|
20078
20256
|
rangePositionState,
|
|
20079
20257
|
highQualityBouncePocket: context.deterministicQuality >= 4 && approvalBlockReasons.length === 0 && (bounceAcceptance === "rejection" || bounceAcceptance === "follow_through"),
|
|
20258
|
+
extremeVolatilityRecoveryPocket,
|
|
20259
|
+
approvalLane,
|
|
20080
20260
|
deterministicRejectionScore
|
|
20081
20261
|
};
|
|
20082
20262
|
};
|
|
@@ -20201,7 +20381,14 @@ var buildReverseTrendlineAiContext = (signal) => {
|
|
|
20201
20381
|
},
|
|
20202
20382
|
signal
|
|
20203
20383
|
);
|
|
20204
|
-
const
|
|
20384
|
+
const baseContext = isRecord2(signal.additionalIndicators?.baseContext) ? signal.additionalIndicators.baseContext : null;
|
|
20385
|
+
const extremeVolatilityRecoveryPocket = baseContext != null ? isExtremeVolatilityRecoveryLane(
|
|
20386
|
+
{
|
|
20387
|
+
hardBlockReasons
|
|
20388
|
+
},
|
|
20389
|
+
baseContext
|
|
20390
|
+
) : false;
|
|
20391
|
+
const baseReverseTrendLineGateFeatures = buildReverseTrendLineGateFeatures({
|
|
20205
20392
|
context: {
|
|
20206
20393
|
...structural,
|
|
20207
20394
|
...timing,
|
|
@@ -20210,17 +20397,28 @@ var buildReverseTrendlineAiContext = (signal) => {
|
|
|
20210
20397
|
},
|
|
20211
20398
|
signal,
|
|
20212
20399
|
approvalBlockReasons,
|
|
20213
|
-
deterministicRejectionScore
|
|
20400
|
+
deterministicRejectionScore,
|
|
20401
|
+
approvalLane: "watch",
|
|
20402
|
+
extremeVolatilityRecoveryPocket
|
|
20214
20403
|
});
|
|
20404
|
+
const highScoreBouncePocket = baseReverseTrendLineGateFeatures.highQualityBouncePocket && deterministicRejectionScore != null && deterministicRejectionScore >= 7;
|
|
20405
|
+
const approvalLane = highScoreBouncePocket ? "high_score_bounce" : extremeVolatilityRecoveryPocket ? "extreme_volatility_recovery" : "watch";
|
|
20406
|
+
const approvalAllowedNow = approvalLane !== "watch";
|
|
20407
|
+
const finalApprovalBlockReasons = !approvalAllowedNow && promotedDeterministicQuality >= 4 && approvalBlockReasons.length === 0 ? [...approvalBlockReasons, "rejection_score_below_gate"] : approvalBlockReasons;
|
|
20408
|
+
const finalDeterministicQuality = approvalAllowedNow ? Math.max(promotedDeterministicQuality, 4) : promotedDeterministicQuality;
|
|
20409
|
+
const reverseTrendLineGateFeatures = {
|
|
20410
|
+
...baseReverseTrendLineGateFeatures,
|
|
20411
|
+
approvalLane
|
|
20412
|
+
};
|
|
20215
20413
|
return {
|
|
20216
20414
|
...structural,
|
|
20217
20415
|
...timing,
|
|
20218
20416
|
reverseTrendLineGateFeatures,
|
|
20219
|
-
deterministicQuality:
|
|
20417
|
+
deterministicQuality: finalDeterministicQuality,
|
|
20220
20418
|
deterministicRejectionScore,
|
|
20221
|
-
approvalAllowedNow
|
|
20419
|
+
approvalAllowedNow,
|
|
20222
20420
|
hardBlockReasons,
|
|
20223
|
-
approvalBlockReasons
|
|
20421
|
+
approvalBlockReasons: finalApprovalBlockReasons
|
|
20224
20422
|
};
|
|
20225
20423
|
};
|
|
20226
20424
|
var withReverseTrendLineGateFeatures = ({
|
|
@@ -20265,6 +20463,8 @@ var getHardBlockReasonText2 = (reason) => {
|
|
|
20265
20463
|
return "LONG bounce distance sits in a weak mid-distance pocket";
|
|
20266
20464
|
case "short_follow_through_overrated":
|
|
20267
20465
|
return "SHORT follow-through bounce is not reliable enough for quality 5";
|
|
20466
|
+
case "rejection_score_below_gate":
|
|
20467
|
+
return "deterministic rejection score is below the current strict gate";
|
|
20268
20468
|
default:
|
|
20269
20469
|
return reason;
|
|
20270
20470
|
}
|
|
@@ -20349,6 +20549,8 @@ Additional ReverseTrendLine context:
|
|
|
20349
20549
|
- reverseTrendLineGateVolatilityState=${context.reverseTrendLineGateFeatures.volatilityState}
|
|
20350
20550
|
- reverseTrendLineGateRangePositionState=${context.reverseTrendLineGateFeatures.rangePositionState}
|
|
20351
20551
|
- reverseTrendLineGateHighQualityBouncePocket=${String(context.reverseTrendLineGateFeatures.highQualityBouncePocket)}
|
|
20552
|
+
- reverseTrendLineGateExtremeVolatilityRecoveryPocket=${String(context.reverseTrendLineGateFeatures.extremeVolatilityRecoveryPocket)}
|
|
20553
|
+
- reverseTrendLineGateApprovalLane=${context.reverseTrendLineGateFeatures.approvalLane}
|
|
20352
20554
|
- approvalAllowedNow=${context.approvalAllowedNow}
|
|
20353
20555
|
- hardBlockReasons=${context.hardBlockReasons.join(", ") || "none"}
|
|
20354
20556
|
- approvalBlockReasons=${context.approvalBlockReasons.join(", ") || "none"}
|
|
@@ -20766,6 +20968,7 @@ var buildTrendFollowGateFeatures = ({
|
|
|
20766
20968
|
const referenceDerivativesLossBlock = direction === "SHORT" && referenceXrp15mOpenInterest != null && referenceXrp15mOpenInterest >= TREND_FOLLOW_REF_LOSS_XRP_OI_MIN && referenceEthCrowdingPersistenceBars != null && referenceEthCrowdingPersistenceBars >= TREND_FOLLOW_REF_LOSS_ETH_CROWDING_MIN && referenceSol15mFundingZScore != null && referenceSol15mFundingZScore <= TREND_FOLLOW_REF_LOSS_SOL_FUNDING_Z_MAX;
|
|
20767
20969
|
const referenceDerivativesCadencePocket = !referenceDerivativesLossBlock && (legacyCadencePocket || referenceDerivativesOiCompressionPocket || referenceDerivativesXrpFundingPocket || referenceDerivativesSolFlushPocket);
|
|
20768
20970
|
const referenceDerivativesOpeningPocket = direction === "SHORT" && minutesFromSessionOpen != null && minutesFromSessionOpen <= TREND_FOLLOW_OPENING_SESSION_MAX_MINUTES_FROM_OPEN && referenceXrp15mOpenInterest != null && referenceXrp15mOpenInterest <= TREND_FOLLOW_OPENING_REF_XRP_OI_MAX && referenceXrp1hOiChangePct1h != null && referenceXrp1hOiChangePct1h >= TREND_FOLLOW_OPENING_REF_XRP_OI_CHANGE_1H_MIN && referenceBnb15mOpenInterest != null && referenceBnb15mOpenInterest >= TREND_FOLLOW_OPENING_REF_BNB_OI_MIN;
|
|
20971
|
+
const referenceDerivativesCleanCadencePocket = referenceDerivativesCadencePocket && !derivativesShortFlushOiPocket;
|
|
20769
20972
|
const normalVolatilityCadencePocket = marketVolatilityState === TREND_FOLLOW_ALLOWED_VOLATILITY_STATE;
|
|
20770
20973
|
return {
|
|
20771
20974
|
setupStopDistanceAtr,
|
|
@@ -20808,9 +21011,10 @@ var buildTrendFollowGateFeatures = ({
|
|
|
20808
21011
|
referenceDerivativesSolFlushPocket,
|
|
20809
21012
|
referenceDerivativesLossBlock,
|
|
20810
21013
|
referenceDerivativesCadencePocket,
|
|
21014
|
+
referenceDerivativesCleanCadencePocket,
|
|
20811
21015
|
referenceDerivativesOpeningPocket,
|
|
20812
21016
|
normalVolatilityCadencePocket,
|
|
20813
|
-
highQualityCadencePocket: normalVolatilityCadencePocket &&
|
|
21017
|
+
highQualityCadencePocket: normalVolatilityCadencePocket && referenceDerivativesCleanCadencePocket
|
|
20814
21018
|
};
|
|
20815
21019
|
};
|
|
20816
21020
|
var buildTrendFollowGuardrailContext = ({
|
|
@@ -21070,6 +21274,7 @@ Additional TrendFollow context:
|
|
|
21070
21274
|
- trendFollowGateReferenceDerivativesSolFlushPocket=${String(context.trendFollowGateFeatures.referenceDerivativesSolFlushPocket)}
|
|
21071
21275
|
- trendFollowGateReferenceDerivativesLossBlock=${String(context.trendFollowGateFeatures.referenceDerivativesLossBlock)}
|
|
21072
21276
|
- trendFollowGateReferenceDerivativesCadencePocket=${String(context.trendFollowGateFeatures.referenceDerivativesCadencePocket)}
|
|
21277
|
+
- trendFollowGateReferenceDerivativesCleanCadencePocket=${String(context.trendFollowGateFeatures.referenceDerivativesCleanCadencePocket)}
|
|
21073
21278
|
- trendFollowGateReferenceDerivativesOpeningPocket=${String(context.trendFollowGateFeatures.referenceDerivativesOpeningPocket)}
|
|
21074
21279
|
- trendFollowGateNormalVolatilityCadencePocket=${String(context.trendFollowGateFeatures.normalVolatilityCadencePocket)}
|
|
21075
21280
|
- trendFollowGateHighQualityCadencePocket=${String(context.trendFollowGateFeatures.highQualityCadencePocket)}
|
|
@@ -21089,7 +21294,7 @@ Interpretation rules for TrendFollow:
|
|
|
21089
21294
|
- The ATR trailing stop is the structural invalidation line and also updates while a position is open.
|
|
21090
21295
|
- Prefer breakouts aligned with shared market context and backed by participation.
|
|
21091
21296
|
- Late, thin, crowded, inside-range, adverse-delta, weak-momentum, or weak-volume-structure breakouts should be downgraded even if the pivot cross is valid.
|
|
21092
|
-
- Live approval is reserved for calibrated SHORT derivatives pockets in normal volatility
|
|
21297
|
+
- Live approval is reserved for calibrated SHORT extra-reference derivatives pockets in normal volatility when the BTC benchmark short-flush/OI pocket is not active; legacy BTC benchmark flush and opening-session recovery remain watch mode.
|
|
21093
21298
|
- Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
|
|
21094
21299
|
`.trim();
|
|
21095
21300
|
},
|
|
@@ -21126,6 +21331,8 @@ var LONG_BROAD_MARKET_SHORT_FLUSH_PCT_ABOVE_MA20_MIN = 0.95;
|
|
|
21126
21331
|
var LONG_BROAD_MARKET_SHORT_FLUSH_BTC_VS_ALT_RETURN_24H_MIN = 0;
|
|
21127
21332
|
var SHORT_ASIA_LONG_FLUSH_LOW_CMC_FEAR_GREED_MAX = 18;
|
|
21128
21333
|
var SHORT_ASIA_LONG_FLUSH_ADVANCERS_MAX = 2;
|
|
21334
|
+
var BNB_REFERENCE_OI_CHANGE_PCT_4H_RISK_MIN = 0;
|
|
21335
|
+
var DERIVATIVES_DATA_UNAVAILABLE_STRESS_CMC_FEAR_GREED_MAX = 25;
|
|
21129
21336
|
var toMtfAlignmentForTrendShift = ({
|
|
21130
21337
|
direction,
|
|
21131
21338
|
mtfAlignment
|
|
@@ -21393,9 +21600,14 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21393
21600
|
gateRelative?.cmcFearGreedValueChange24h ?? baseCmcFearGreed?.valueChange24h
|
|
21394
21601
|
);
|
|
21395
21602
|
const cmcFearGreedStale = gateRelative?.cmcFearGreedStale === true || baseCmcFearGreed?.stale === true;
|
|
21603
|
+
const derivativesDataUnavailable = derivativesRiskFlags.includes("missing_derivatives") || derivativesRiskFlags.includes("stale_derivatives");
|
|
21604
|
+
const derivativesDataUnavailableStressRisk = derivativesDataUnavailable && cmcFearGreedStale !== true && cmcFearGreedValue != null && cmcFearGreedValue <= DERIVATIVES_DATA_UNAVAILABLE_STRESS_CMC_FEAR_GREED_MAX;
|
|
21396
21605
|
const derivatives1hLiqShort = asFiniteNumber6(
|
|
21397
21606
|
baseContext?.derivatives?.intervals?.["1h"]?.liqShort
|
|
21398
21607
|
);
|
|
21608
|
+
const bnbReferenceOiChangePct4h = asFiniteNumber6(
|
|
21609
|
+
baseContext?.derivatives?.referenceContexts?.BNBUSDT?.intervals?.["1h"]?.oiChangePct4h
|
|
21610
|
+
);
|
|
21399
21611
|
const btcAltRegime = typeof gateRelative?.btcAltRegime === "string" ? gateRelative.btcAltRegime : null;
|
|
21400
21612
|
const btcAltRegimeStale = gateRelative?.btcAltRegimeStale === true;
|
|
21401
21613
|
const cmcExchangeLiquidityVolumeChange24hPct = asFiniteNumber6(
|
|
@@ -21420,8 +21632,8 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21420
21632
|
const q4LongBreakoutCandidate = signalContext.signalDirection === "LONG" && breakoutState === "above_high_level" && volumeRel20 != null && volumeRel20 >= 1.2 && atrPctZScore != null && atrPctZScore >= 0 && relativeStrength1h != null && relativeStrength1h > -1 && derivativesPressure === "short_flush";
|
|
21421
21633
|
const q4ShortBreakoutCandidate = signalContext.signalDirection === "SHORT" && breakoutState === "below_low_level" && volumeRel20 != null && volumeRel20 >= 1.2 && atrPctZScore != null && atrPctZScore >= 0 && relativeStrength1h != null && relativeStrength1h < 1 && derivativesPressure === "long_flush";
|
|
21422
21634
|
const q4ShortAsiaFlushCandidate = signalContext.signalDirection === "SHORT" && derivativesPressure === "neutral" && derivativesFlushSupport && sessionPrimary === "asia" && !sessionIsOverlap && distanceAtrRatio < 0.7 && slopeAbs >= 0.08 && closeVsAvgPctAbs >= 0.12;
|
|
21423
|
-
const selectiveNeutralQ4Candidate = hasDerivativesSummary && derivativesPressure === "neutral" && !sessionIsOverlap && (signalContext.signalDirection === "LONG" && sessionPrimary === "europe" && (breakoutState === "above_high_level" || breakoutState === "failed_high_breakout") || signalContext.signalDirection === "SHORT" && (sessionPrimary === "off_hours" || sessionPrimary === "asia") && breakoutState === "below_low_level");
|
|
21424
|
-
const shortNeutralBearChannelBreakdownCandidate = signalContext.signalDirection === "SHORT" && breakoutState === "below_low_level" && derivativesPressure === "neutral" && atrPctZScore != null && atrPctZScore >= 0 && atrPctZScore < 1 && adaptiveChannelDirection === "bear";
|
|
21635
|
+
const selectiveNeutralQ4Candidate = hasDerivativesSummary && derivativesPressure === "neutral" && !derivativesDataUnavailableStressRisk && !sessionIsOverlap && (signalContext.signalDirection === "LONG" && sessionPrimary === "europe" && (breakoutState === "above_high_level" || breakoutState === "failed_high_breakout") || signalContext.signalDirection === "SHORT" && (sessionPrimary === "off_hours" || sessionPrimary === "asia") && breakoutState === "below_low_level");
|
|
21636
|
+
const shortNeutralBearChannelBreakdownCandidate = signalContext.signalDirection === "SHORT" && breakoutState === "below_low_level" && derivativesPressure === "neutral" && !derivativesDataUnavailableStressRisk && atrPctZScore != null && atrPctZScore >= 0 && atrPctZScore < 1 && adaptiveChannelDirection === "bear";
|
|
21425
21637
|
let deterministicQuality = 3;
|
|
21426
21638
|
if (hardBlockReasons.length > 0) {
|
|
21427
21639
|
deterministicQuality = signalContext.confirmedFlip ? 2 : 1;
|
|
@@ -21489,6 +21701,10 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21489
21701
|
hardBlockReasons.push("us_short_oi_not_expanding");
|
|
21490
21702
|
}
|
|
21491
21703
|
}
|
|
21704
|
+
if (deterministicQuality >= 5 && derivativesDataUnavailableStressRisk) {
|
|
21705
|
+
deterministicQuality = 4;
|
|
21706
|
+
hardBlockReasons.push("derivatives_data_unavailable_stress");
|
|
21707
|
+
}
|
|
21492
21708
|
if (deterministicQuality >= 5 && hasDerivativesSummary && !selectiveNeutralQ4Candidate && !shortNeutralBearChannelBreakdownCandidate && derivativesPressure === "neutral" && !derivativesFlushSupport) {
|
|
21493
21709
|
deterministicQuality = 4;
|
|
21494
21710
|
hardBlockReasons.push("neutral_derivatives_pressure");
|
|
@@ -21511,6 +21727,7 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21511
21727
|
const shortAsiaLongFlushLowCmcBreadthRisk = signalContext.signalDirection === "SHORT" && sessionPrimary === "asia" && derivativesPressure === "long_flush" && cmcFearGreedStale !== true && marketBreadthStale !== true && cmcFearGreedValue != null && cmcFearGreedValue <= SHORT_ASIA_LONG_FLUSH_LOW_CMC_FEAR_GREED_MAX && marketBreadthAdvancers != null && marketBreadthAdvancers <= SHORT_ASIA_LONG_FLUSH_ADVANCERS_MAX;
|
|
21512
21728
|
const lowRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility < 0.25;
|
|
21513
21729
|
const defensiveRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility >= 0.25 && rewardToVolatility < 8;
|
|
21730
|
+
const bnbReferenceOiExpansionRisk = bnbReferenceOiChangePct4h != null && bnbReferenceOiChangePct4h >= BNB_REFERENCE_OI_CHANGE_PCT_4H_RISK_MIN;
|
|
21514
21731
|
const longBtcAltRegimeRisk = signalContext.signalDirection === "LONG" && btcAltRegimeStale !== true && (btcAltRegime === "btc_lead" || btcAltRegime === "risk_off");
|
|
21515
21732
|
const longBroadMarketShortFlushRisk = signalContext.signalDirection === "LONG" && derivativesPressure === "short_flush" && marketBreadthAdvancers != null && marketBreadthAdvancers >= LONG_BROAD_MARKET_SHORT_FLUSH_ADVANCERS_MIN && marketBreadthPctAboveMa20 != null && marketBreadthPctAboveMa20 >= LONG_BROAD_MARKET_SHORT_FLUSH_PCT_ABOVE_MA20_MIN && btcVsAltReturn24h != null && btcVsAltReturn24h >= LONG_BROAD_MARKET_SHORT_FLUSH_BTC_VS_ALT_RETURN_24H_MIN;
|
|
21516
21733
|
const cmcExchangeLiquidityVolumeChangeRisk = cmcExchangeLiquidityStale !== true && cmcExchangeLiquidityVolumeChange24hPct != null && (cmcExchangeLiquidityVolumeChange24hPct > -0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0 || cmcExchangeLiquidityVolumeChange24hPct >= 0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0.3);
|
|
@@ -21562,6 +21779,10 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21562
21779
|
deterministicQuality = 4;
|
|
21563
21780
|
hardBlockReasons.push("reward_to_volatility_below_defensive_threshold");
|
|
21564
21781
|
}
|
|
21782
|
+
if (deterministicQuality >= 5 && bnbReferenceOiExpansionRisk) {
|
|
21783
|
+
deterministicQuality = 4;
|
|
21784
|
+
hardBlockReasons.push("bnb_reference_1h_oi4h_expansion_risk");
|
|
21785
|
+
}
|
|
21565
21786
|
if (deterministicQuality >= 4 && longBtcAltRegimeRisk) {
|
|
21566
21787
|
deterministicQuality = 4;
|
|
21567
21788
|
hardBlockReasons.push("long_btc_alt_regime_risk");
|
|
@@ -21588,7 +21809,7 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21588
21809
|
const q4UsClosingOiConfirmationRecoveryCandidate = deterministicQuality === 4 && signalContext.confirmedFlip === true && signalContext.flipDistanceOk === true && sessionPrimary === "us" && sessionWindowPhase === "closing" && hardBlockReasons.length > 0 && hardBlockReasons.every(
|
|
21589
21810
|
(reason) => q4UsClosingOiConfirmationRecoveryAllowedReasons.includes(reason)
|
|
21590
21811
|
);
|
|
21591
|
-
const q4ShortBreadthShockLiquidationRecoveryCandidate = deterministicQuality === 4 && signalContext.signalDirection === "SHORT" && signalContext.confirmedFlip === true && signalContext.flipDistanceOk === true && marketBreadthReturn != null && marketBreadthReturn <= SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX2 && derivatives1hLiqShort != null && derivatives1hLiqShort <= SHORT_BREADTH_SHOCK_1H_LIQ_SHORT_MAX;
|
|
21812
|
+
const q4ShortBreadthShockLiquidationRecoveryCandidate = deterministicQuality === 4 && signalContext.signalDirection === "SHORT" && signalContext.confirmedFlip === true && signalContext.flipDistanceOk === true && hardBlockReasons.length === 0 && !derivativesDataUnavailableStressRisk && marketBreadthReturn != null && marketBreadthReturn <= SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX2 && derivatives1hLiqShort != null && derivatives1hLiqShort <= SHORT_BREADTH_SHOCK_1H_LIQ_SHORT_MAX;
|
|
21592
21813
|
const q4LongAltLeadershipRecoveryAllowedReasons = [
|
|
21593
21814
|
"flat_or_mixed_oi",
|
|
21594
21815
|
"neutral_derivatives_pressure",
|
|
@@ -21636,8 +21857,10 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21636
21857
|
shortBullSwingStructureRisk,
|
|
21637
21858
|
shortLowBollingerWidthRisk,
|
|
21638
21859
|
shortAsiaLongFlushLowCmcBreadthRisk,
|
|
21860
|
+
derivativesDataUnavailableStressRisk,
|
|
21639
21861
|
lowRewardToVolatilityRisk,
|
|
21640
21862
|
defensiveRewardToVolatilityRisk,
|
|
21863
|
+
bnbReferenceOiExpansionRisk,
|
|
21641
21864
|
longBtcAltRegimeRisk,
|
|
21642
21865
|
longBroadMarketShortFlushRisk,
|
|
21643
21866
|
cmcExchangeLiquidityVolumeChangeRisk,
|
|
@@ -21662,6 +21885,7 @@ var buildTrendShiftGuardrailContext = ({
|
|
|
21662
21885
|
cmcFearGreedValue,
|
|
21663
21886
|
cmcFearGreedValueChange24h,
|
|
21664
21887
|
derivatives1hLiqShort,
|
|
21888
|
+
bnbReferenceOiChangePct4h,
|
|
21665
21889
|
btcAltRegime,
|
|
21666
21890
|
cmcExchangeLiquidityVolumeChange24hPct,
|
|
21667
21891
|
trendShiftGateFeatures,
|
|
@@ -21729,10 +21953,14 @@ var getTrendShiftGuardrailReasonText = (reason) => {
|
|
|
21729
21953
|
return "the SHORT flip is in a narrow Bollinger-width compression pocket that has been less reliable, so keep it in watch mode";
|
|
21730
21954
|
case "short_asia_long_flush_low_cmc_breadth":
|
|
21731
21955
|
return "the SHORT flip is selling an Asia-session long flush while CMC fear/greed and market breadth are already in capitulation, so keep it in watch mode";
|
|
21956
|
+
case "derivatives_data_unavailable_stress":
|
|
21957
|
+
return "benchmark derivatives data is missing or stale during CMC stress, so keep the flip in watch mode instead of treating neutral derivatives as confirmation";
|
|
21732
21958
|
case "low_reward_to_volatility":
|
|
21733
21959
|
return "the expected reward is too small relative to current volatility after costs, so keep the flip in watch mode";
|
|
21734
21960
|
case "reward_to_volatility_below_defensive_threshold":
|
|
21735
21961
|
return "the expected reward is not large enough relative to current volatility for the defensive TrendShift gate after costs";
|
|
21962
|
+
case "bnb_reference_1h_oi4h_expansion_risk":
|
|
21963
|
+
return "BNB reference 1h open interest is expanding over 4h, a historically fragile cross-market state for TrendShift approvals";
|
|
21736
21964
|
case "long_btc_alt_regime_risk":
|
|
21737
21965
|
return "the LONG flip is fighting a BTC-led or risk-off alt regime, so keep it in watch mode";
|
|
21738
21966
|
case "long_broad_market_short_flush_risk":
|
|
@@ -21885,8 +22113,11 @@ Additional TrendShift context:
|
|
|
21885
22113
|
- defensiveRewardToVolatilityRisk=${String(context.defensiveRewardToVolatilityRisk)}
|
|
21886
22114
|
- shortBullSwingStructureRisk=${String(context.shortBullSwingStructureRisk)}
|
|
21887
22115
|
- shortAsiaLongFlushLowCmcBreadthRisk=${String(context.shortAsiaLongFlushLowCmcBreadthRisk)}
|
|
22116
|
+
- derivativesDataUnavailableStressRisk=${String(context.derivativesDataUnavailableStressRisk)}
|
|
21888
22117
|
- longBtcAltRegimeRisk=${String(context.longBtcAltRegimeRisk)}
|
|
21889
22118
|
- longBroadMarketShortFlushRisk=${String(context.longBroadMarketShortFlushRisk)}
|
|
22119
|
+
- bnbReferenceOiChangePct4h=${String(context.bnbReferenceOiChangePct4h ?? "n/a")}
|
|
22120
|
+
- bnbReferenceOiExpansionRisk=${String(context.bnbReferenceOiExpansionRisk)}
|
|
21890
22121
|
- cmcExchangeLiquidityVolumeChangeRisk=${String(context.cmcExchangeLiquidityVolumeChangeRisk)}
|
|
21891
22122
|
- q4TrendShiftGateFeaturesRecoveryCandidate=${String(context.q4TrendShiftGateFeaturesRecoveryCandidate)}
|
|
21892
22123
|
- q4UsClosingOiConfirmationRecoveryCandidate=${String(context.q4UsClosingOiConfirmationRecoveryCandidate)}
|
|
@@ -21924,12 +22155,14 @@ Interpretation rules for TrendShift:
|
|
|
21924
22155
|
- For SHORT, a bullish swing structure is a watch-only warning even when the immediate flip geometry looks q5-strong.
|
|
21925
22156
|
- For SHORT, a narrow Bollinger-width compression pocket is watch-only even if another q4 recovery condition is present.
|
|
21926
22157
|
- For SHORT, Asia-session long-flush setups are watch-only when CMC fear/greed and market breadth are already in capitulation.
|
|
22158
|
+
- If benchmark derivatives data is missing or stale while CMC fear/greed is in stress mode, keep the flip in watch mode; neutral/unknown derivatives are not confirmation in that state.
|
|
21927
22159
|
- The defensive live gate requires rewardToVolatility >= 8 when that field is available.
|
|
22160
|
+
- If BNB reference 1h open interest is expanding over the last 4h, keep TrendShift flips in watch mode; this is a defensive cross-market risk cut, not target-symbol evidence.
|
|
21928
22161
|
- For LONG, BTC-led or risk-off BTC/alt regime is watch-only even when flip geometry is q5-strong.
|
|
21929
22162
|
- For LONG, broad-market squeeze clusters are watch-only when breadth is already extreme, BTC is leading alts, and benchmark derivatives show a short flush.
|
|
21930
22163
|
- If CMC major-exchange liquidity 24h change is in the historically choppy bands (-0.1, 0) or [0.1, 0.3), keep the flip in watch mode.
|
|
21931
22164
|
- A narrow q4 recovery is allowed during the US closing window only when the sole blocker is missing OI expansion on an otherwise liquidation-supported US-session flush.
|
|
21932
|
-
- A narrow SHORT q4 recovery may pass during a market breadth shock only when marketBreadthReturn <= -0.0112952 and 1h liqShort <= 0.208; this does not override the low-Bollinger-width defensive cut.
|
|
22165
|
+
- A narrow SHORT q4 recovery may pass during a market breadth shock only when marketBreadthReturn <= -0.0112952 and 1h liqShort <= 0.208; this does not override existing hard blockers or the low-Bollinger-width defensive cut.
|
|
21933
22166
|
- A narrow LONG q4 recovery may pass only when alt leadership is clear (btcVsAltReturn24h <= -0.00503054 and btcVsAltReturn1h <= -0.00581403), fear/greed is not falling hard, and the only blockers are the tested OI/benchmark-derivatives or defensive reward-to-volatility blockers.
|
|
21934
22167
|
- If hardBlockReasons is not empty, explain exactly what is still missing for confirmation.
|
|
21935
22168
|
`.trim();
|
|
@@ -22245,6 +22478,9 @@ var TRENDLINE_PAYLOAD_PROMPT = `
|
|
|
22245
22478
|
- It also includes 'atrPct / breakVsAtrRatio / coinMaSpreadPct / btcMaSpreadPct / aggressivePreBreakPressure / strongNearBreakPressure / weakCleanBreak / compressedCleanBreak / weakBtcLedBreak / weakLongFarBreak'.
|
|
22246
22479
|
- If 'payload.additionalIndicators.baseContext.derivatives' exists, it contains Coinalyze-derived open interest, funding, and liquidation fields for the signal moment; do not treat 'stale' or 'missing_derivatives' as confirmation or conflict.
|
|
22247
22480
|
`;
|
|
22481
|
+
var MARKET_CONTEXT_PRIMARY_ISSUE = "market_context_against";
|
|
22482
|
+
var MARKET_CONTEXT_TOTAL_MARKET_CAP_USD_MIN = 233e10;
|
|
22483
|
+
var MARKET_CONTEXT_TREND_PERSISTENCE_MAX = 0.77;
|
|
22248
22484
|
var getRecord2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
22249
22485
|
var getNestedRecord3 = (source, path) => {
|
|
22250
22486
|
let current = source;
|
|
@@ -22320,6 +22556,22 @@ var buildTrendlineContext = (signal) => {
|
|
|
22320
22556
|
const volumeStructurePocIndex = toFiniteNumberOrNull5(
|
|
22321
22557
|
participationVolumeStructure?.pocIndex
|
|
22322
22558
|
);
|
|
22559
|
+
const gateDecisionHints = getNestedRecord3(baseContext, [
|
|
22560
|
+
"gateFeatures",
|
|
22561
|
+
"decisionHints"
|
|
22562
|
+
]);
|
|
22563
|
+
const gatePrimaryIssue = typeof gateDecisionHints?.primaryIssue === "string" ? gateDecisionHints.primaryIssue : null;
|
|
22564
|
+
const cmcGlobalContext = getNestedRecord3(baseContext, [
|
|
22565
|
+
"relative",
|
|
22566
|
+
"cmcGlobal"
|
|
22567
|
+
]);
|
|
22568
|
+
const cmcTotalMarketCapUsd = toFiniteNumberOrNull5(
|
|
22569
|
+
cmcGlobalContext?.totalMarketCapUsd
|
|
22570
|
+
);
|
|
22571
|
+
const trendRegimeContext = getNestedRecord3(baseContext, ["regime", "trend"]);
|
|
22572
|
+
const trendPersistence = toFiniteNumberOrNull5(
|
|
22573
|
+
trendRegimeContext?.persistence
|
|
22574
|
+
);
|
|
22323
22575
|
const benchmarkTrendAlignment = typeof benchmarkContext?.trendAlignment === "string" ? benchmarkContext.trendAlignment : null;
|
|
22324
22576
|
const executionContext = getNestedRecord3(baseContext, [
|
|
22325
22577
|
"relative",
|
|
@@ -22371,7 +22623,7 @@ var buildTrendlineContext = (signal) => {
|
|
|
22371
22623
|
if (structural.signalDirection === "SHORT" && (entryTiming === "ready_follow_through" || entryTiming === "ready_retest") && (sessionPrimary === "off_hours" || sessionIsOverlap) && !hardBlockReasons.includes("short_session_risk")) {
|
|
22372
22624
|
hardBlockReasons.push("short_session_risk");
|
|
22373
22625
|
}
|
|
22374
|
-
const
|
|
22626
|
+
const baseDeterministicQuality = getDeterministicTrendlineQuality({
|
|
22375
22627
|
signalDirection: structural.signalDirection,
|
|
22376
22628
|
clearBreak: structural.clearBreak,
|
|
22377
22629
|
nearLineNoise: structural.nearLineNoise,
|
|
@@ -22386,16 +22638,18 @@ var buildTrendlineContext = (signal) => {
|
|
|
22386
22638
|
entryTiming,
|
|
22387
22639
|
coinMaSpreadPct
|
|
22388
22640
|
});
|
|
22641
|
+
const marketContextApprovalPocket = gatePrimaryIssue === MARKET_CONTEXT_PRIMARY_ISSUE && cmcTotalMarketCapUsd != null && cmcTotalMarketCapUsd >= MARKET_CONTEXT_TOTAL_MARKET_CAP_USD_MIN && trendPersistence != null && trendPersistence <= MARKET_CONTEXT_TREND_PERSISTENCE_MAX;
|
|
22642
|
+
const deterministicQuality = marketContextApprovalPocket ? 4 : baseDeterministicQuality;
|
|
22389
22643
|
const maxAllowedQuality = deterministicQuality;
|
|
22390
22644
|
const longUsLowVolumeCrowdedShortSqueeze = structural.signalDirection === "LONG" && sessionPrimary === "us" && volumeRel20 != null && volumeRel20 < 0.8 && derivativesRiskFlags.includes("crowded_short") && benchmarkTrendAlignment !== "against_benchmark";
|
|
22391
22645
|
const longHistoricalApprovalPocket = venueSpreadZScore != null && venueSpreadZScore <= -1 || longUsLowVolumeCrowdedShortSqueeze || sessionPrimary !== "europe" && !derivativesRiskFlags.includes("missing_derivatives") && !(structural.breakVsAtrRatio != null && structural.breakVsAtrRatio >= 0.8 && structural.breakVsAtrRatio < 1.2) && volumeRel20 != null && volumeRel20 >= 0.8 && benchmarkTrendAlignment !== "against_benchmark";
|
|
22392
|
-
const longHighQualitySessionApproval =
|
|
22646
|
+
const longHighQualitySessionApproval = baseDeterministicQuality >= 5 && sessionPrimary !== "asia";
|
|
22393
22647
|
const longStrongDerivativesAlignedApproval = volumeRel20 != null && volumeRel20 >= 1.5 && derivativesDirectionAligned === true;
|
|
22394
|
-
const longModerateRetestLiquidSessionApproval = structural.signalDirection === "LONG" &&
|
|
22648
|
+
const longModerateRetestLiquidSessionApproval = structural.signalDirection === "LONG" && baseDeterministicQuality === 4 && entryTiming === "ready_retest" && (sessionPrimary === "us" || sessionPrimary === "europe") && volumeRel20 != null && volumeRel20 >= 0.8 && volumeRel20 < 1.5 && benchmarkTrendAlignment !== "against_benchmark" && derivativesDirectionAligned == null && derivativesRiskFlags.length > 0 && !oiNotConfirming;
|
|
22395
22649
|
const longBaseContextApprovalPocket = structural.signalDirection !== "LONG" || longModerateRetestLiquidSessionApproval || longHistoricalApprovalPocket && (longHighQualitySessionApproval || longStrongDerivativesAlignedApproval);
|
|
22396
22650
|
const shortThinNeutralBenchmarkRisk = structural.signalDirection === "SHORT" && volumeRel20 != null && volumeRel20 < 0.8 && benchmarkTrendAlignment === "neutral";
|
|
22397
|
-
const q4ReferenceOiPocApproval =
|
|
22398
|
-
const approvalAllowedNow =
|
|
22651
|
+
const q4ReferenceOiPocApproval = baseDeterministicQuality === 4 && volumeStructurePocIndex != null && volumeStructurePocIndex >= 5 && ethReferenceOiAcceleration != null && ethReferenceOiAcceleration <= -0.5906;
|
|
22652
|
+
const approvalAllowedNow = marketContextApprovalPocket;
|
|
22399
22653
|
const trendLineGateFeatures = buildTrendLineGateFeatures({
|
|
22400
22654
|
structural,
|
|
22401
22655
|
entryTiming,
|
|
@@ -22431,6 +22685,11 @@ var buildTrendlineContext = (signal) => {
|
|
|
22431
22685
|
derivativesRiskFlags,
|
|
22432
22686
|
ethReferenceOiAcceleration,
|
|
22433
22687
|
oiNotConfirming,
|
|
22688
|
+
gatePrimaryIssue,
|
|
22689
|
+
cmcTotalMarketCapUsd,
|
|
22690
|
+
trendPersistence,
|
|
22691
|
+
marketContextApprovalPocket,
|
|
22692
|
+
baseDeterministicQuality,
|
|
22434
22693
|
longUsLowVolumeCrowdedShortSqueeze,
|
|
22435
22694
|
longHighQualitySessionApproval,
|
|
22436
22695
|
longStrongDerivativesAlignedApproval,
|
|
@@ -22680,6 +22939,11 @@ Additional TrendLine context:
|
|
|
22680
22939
|
- trendline.volumeStructurePocIndex=${formatPromptNumber(trendlineContext.volumeStructurePocIndex, 0)}
|
|
22681
22940
|
- trendline.ethReferenceOiAcceleration=${formatPromptNumber(trendlineContext.ethReferenceOiAcceleration, 3)}
|
|
22682
22941
|
- trendline.q4ReferenceOiPocApproval=${String(trendlineContext.q4ReferenceOiPocApproval)}
|
|
22942
|
+
- trendline.gatePrimaryIssue=${trendlineContext.gatePrimaryIssue ?? "n/a"}
|
|
22943
|
+
- trendline.cmcTotalMarketCapUsd=${formatPromptNumber(trendlineContext.cmcTotalMarketCapUsd, 0)}
|
|
22944
|
+
- trendline.trendPersistence=${formatPromptNumber(trendlineContext.trendPersistence, 3)}
|
|
22945
|
+
- trendline.marketContextApprovalPocket=${String(trendlineContext.marketContextApprovalPocket)}
|
|
22946
|
+
- trendline.baseDeterministicQuality=${String(trendlineContext.baseDeterministicQuality)}
|
|
22683
22947
|
- trendline.weakCleanBreak=${String(trendlineContext.weakCleanBreak)}
|
|
22684
22948
|
- trendline.compressedCleanBreak=${String(trendlineContext.compressedCleanBreak)}
|
|
22685
22949
|
- trendline.weakBtcLedBreak=${String(trendlineContext.weakBtcLedBreak)}
|
|
@@ -22958,10 +23222,13 @@ VolumeDivergence addon:
|
|
|
22958
23222
|
`;
|
|
22959
23223
|
var VOLUME_DIVERGENCE_PAYLOAD_PROMPT = `
|
|
22960
23224
|
- \`payload.additionalIndicators.volumeDivergenceContext\` contains a compact divergence-strength summary:
|
|
22961
|
-
divergenceKind / confirmationPrice / confirmationReady / structureAdvanced / reboundFromPivotPct / confirmationDistancePct / priceDisplacementPct / divergenceAmplitudeAtrRatio / reclaimPct / confirmationCandleQuality / volumeDivergenceStrength / deltaAligned / coinBiasAligned / btcBiasAligned / derivativesDirectionAligned / derivativesRiskFlags / derivativesLiqSpikeRatio / venueSpreadZScore / volumeRel20 / rangePosition20 / deterministicQuality / approvalAllowedNow / structuralHardBlockReasons / maxAllowedQuality.
|
|
23225
|
+
divergenceKind / confirmationPrice / confirmationReady / structureAdvanced / reboundFromPivotPct / confirmationDistancePct / priceDisplacementPct / divergenceAmplitudeAtrRatio / reclaimPct / confirmationCandleQuality / volumeDivergenceStrength / deltaAligned / coinBiasAligned / btcBiasAligned / derivativesDirectionAligned / derivativesRiskFlags / derivativesLiqSpikeRatio / venueSpreadZScore / volumeRel20 / rangePosition20 / btcOiChangePct1h15m / solOpenInterest15m / xrpFundingZScore15m / derivativesRegimePocket / deterministicQuality / approvalAllowedNow / structuralHardBlockReasons / maxAllowedQuality.
|
|
22962
23226
|
- Use this context as the explicit strategy-specific summary instead of trying to derive the same conclusion again only from generic candles.
|
|
22963
23227
|
- If \`payload.additionalIndicators.baseContext.derivatives\` exists, it is a Coinalyze-derived summary of derivatives state at signal time; \`stale\` or \`missing_derivatives\` means that Coinalyze context must not be used.
|
|
22964
23228
|
`;
|
|
23229
|
+
var BTC_OI_CHANGE_PCT_1H_15M_MAX = -0.32;
|
|
23230
|
+
var SOL_OPEN_INTEREST_15M_MIN = 101e5;
|
|
23231
|
+
var XRP_FUNDING_Z_SCORE_15M_MAX = -1.2;
|
|
22965
23232
|
var toFiniteNumberOrNull6 = (value) => {
|
|
22966
23233
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
22967
23234
|
return value;
|
|
@@ -23328,6 +23595,23 @@ var getVolumeDivergenceContext = (signal) => {
|
|
|
23328
23595
|
const derivativesRiskFlags = getStringArray3(derivativesSummary?.riskFlags);
|
|
23329
23596
|
const derivativesFundingZScore = toFiniteNumberOrNull6(derivatives15m?.fundingZScore) ?? toFiniteNumberOrNull6(derivatives1h?.fundingZScore);
|
|
23330
23597
|
const derivativesLiqSpikeRatio = toFiniteNumberOrNull6(derivatives15m?.liqSpikeRatio) ?? toFiniteNumberOrNull6(derivatives1h?.liqSpikeRatio);
|
|
23598
|
+
const btcOiChangePct1h15m = toFiniteNumberOrNull6(
|
|
23599
|
+
derivatives15m?.oiChangePct1h
|
|
23600
|
+
);
|
|
23601
|
+
const solOpenInterest15m = getNestedNumber3(derivativesContext, [
|
|
23602
|
+
"referenceContexts",
|
|
23603
|
+
"SOLUSDT",
|
|
23604
|
+
"intervals",
|
|
23605
|
+
"15m",
|
|
23606
|
+
"openInterest"
|
|
23607
|
+
]);
|
|
23608
|
+
const xrpFundingZScore15m = getNestedNumber3(derivativesContext, [
|
|
23609
|
+
"referenceContexts",
|
|
23610
|
+
"XRPUSDT",
|
|
23611
|
+
"intervals",
|
|
23612
|
+
"15m",
|
|
23613
|
+
"fundingZScore"
|
|
23614
|
+
]);
|
|
23331
23615
|
const marketContext = getRecord3(additional?.marketContext);
|
|
23332
23616
|
const venueSpreadZScore = getNestedNumber3(marketContext, [
|
|
23333
23617
|
"execution",
|
|
@@ -23427,9 +23711,9 @@ var getVolumeDivergenceContext = (signal) => {
|
|
|
23427
23711
|
entryThresholds,
|
|
23428
23712
|
aiThresholds
|
|
23429
23713
|
}) : hardBlockReasons.length > 0 ? 2 : 3;
|
|
23430
|
-
const
|
|
23431
|
-
const
|
|
23432
|
-
const approvalAllowedNow = hardBlockReasons.length === 0 &&
|
|
23714
|
+
const derivativesRegimePocket = isAtMost(btcOiChangePct1h15m, BTC_OI_CHANGE_PCT_1H_15M_MAX) && isAtLeast2(solOpenInterest15m, SOL_OPEN_INTEREST_15M_MIN) && isAtMost(xrpFundingZScore15m, XRP_FUNDING_Z_SCORE_15M_MAX);
|
|
23715
|
+
const maxAllowedQuality = derivativesRegimePocket ? Math.max(deterministicQuality, 4) : deterministicQuality;
|
|
23716
|
+
const approvalAllowedNow = hardBlockReasons.length === 0 && confirmationReady && derivativesRegimePocket && maxAllowedQuality >= 4;
|
|
23433
23717
|
return {
|
|
23434
23718
|
signalDirection,
|
|
23435
23719
|
divergenceKind,
|
|
@@ -23462,12 +23746,16 @@ var getVolumeDivergenceContext = (signal) => {
|
|
|
23462
23746
|
venueSpreadZScore,
|
|
23463
23747
|
volumeRel20,
|
|
23464
23748
|
rangePosition20,
|
|
23749
|
+
btcOiChangePct1h15m,
|
|
23750
|
+
solOpenInterest15m,
|
|
23751
|
+
xrpFundingZScore15m,
|
|
23752
|
+
derivativesRegimePocket,
|
|
23465
23753
|
sessionPhase,
|
|
23466
23754
|
hardBlockReasons,
|
|
23467
23755
|
structuralHardBlockReasons: [...hardBlockReasons],
|
|
23468
23756
|
deterministicQuality,
|
|
23469
23757
|
approvalAllowedNow,
|
|
23470
|
-
maxAllowedQuality
|
|
23758
|
+
maxAllowedQuality
|
|
23471
23759
|
};
|
|
23472
23760
|
};
|
|
23473
23761
|
var getVolumeDivergenceContextFromPayload = (payload, signal) => {
|
|
@@ -23518,6 +23806,7 @@ var postProcessAnalysis2 = ({
|
|
|
23518
23806
|
);
|
|
23519
23807
|
const needRetest = finalDirection == null;
|
|
23520
23808
|
const retestPrice = needRetest ? context.confirmationPrice : null;
|
|
23809
|
+
const approvedQuality = finalDirection != null && context.maxAllowedQuality >= 4 ? Math.max(finalQuality, 4) : finalQuality;
|
|
23521
23810
|
if (finalDirection == null) {
|
|
23522
23811
|
return {
|
|
23523
23812
|
...analysis,
|
|
@@ -23535,7 +23824,7 @@ var postProcessAnalysis2 = ({
|
|
|
23535
23824
|
return {
|
|
23536
23825
|
...analysis,
|
|
23537
23826
|
direction: finalDirection,
|
|
23538
|
-
quality:
|
|
23827
|
+
quality: approvedQuality,
|
|
23539
23828
|
needRetest,
|
|
23540
23829
|
retestPrice,
|
|
23541
23830
|
takeProfitPrice: signal.prices?.takeProfitPrice ?? null,
|
|
@@ -23581,6 +23870,10 @@ Additional VolumeDivergence context:
|
|
|
23581
23870
|
- venueSpreadZScore=${context.venueSpreadZScore?.toFixed?.(3) ?? "n/a"}
|
|
23582
23871
|
- volumeRel20=${context.volumeRel20?.toFixed?.(3) ?? "n/a"}
|
|
23583
23872
|
- rangePosition20=${context.rangePosition20?.toFixed?.(3) ?? "n/a"}
|
|
23873
|
+
- btcOiChangePct1h15m=${context.btcOiChangePct1h15m?.toFixed?.(3) ?? "n/a"}
|
|
23874
|
+
- solOpenInterest15m=${context.solOpenInterest15m?.toFixed?.(0) ?? "n/a"}
|
|
23875
|
+
- xrpFundingZScore15m=${context.xrpFundingZScore15m?.toFixed?.(3) ?? "n/a"}
|
|
23876
|
+
- derivativesRegimePocket=${context.derivativesRegimePocket}
|
|
23584
23877
|
- barsSincePivot=${context.barsSincePivot ?? "n/a"}
|
|
23585
23878
|
- barsBetweenPivotConfirmations=${context.barsBetweenPivotConfirmations ?? "n/a"}
|
|
23586
23879
|
- entryTiming=${context.entryTiming ?? "n/a"}
|