@tradejs/strategies 1.0.12 → 2.0.1

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 CHANGED
@@ -16519,6 +16519,7 @@ AdaptiveMomentumRibbon addon:
16519
16519
  - SHORT breadth-shock approvals use two calibrated pockets: BTC-favored breadth shock, or a neutral shared-context breadth exhaustion pocket with marketBreadth.advancers <= 0 and effortVsResult <= 800.
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
+ - All live approvals require a calibrated market-regime floor: tpDistanceAtr >= 2.9, trendAdx >= 15, and benchmarkRelativeStrength1d <= 4 when available.
16522
16523
  - LONG approvals require cmcAltLiquidityRegime to be anything except \`btc_favored\` when that CMC field is available.
16523
16524
  - Non-q5 LONG approvals require targetVsBtcAlpha1h <= 2.4 when that field is available, to avoid chase entries after target already outran BTC.
16524
16525
  - \`quality=4\` continuation approvals require targetVsBtcAlpha4h >= 1, spreadBps >= -10, and cmcFearGreedValueChange7d >= -15 when those fields are available. \`quality=5\` is not capped by this q4-only continuation guard.
@@ -16527,7 +16528,7 @@ AdaptiveMomentumRibbon addon:
16527
16528
  `;
16528
16529
  var ADAPTIVE_MOMENTUM_RIBBON_PAYLOAD_PROMPT = `
16529
16530
  - \`payload.additionalIndicators.adaptiveMomentumRibbonContext\` contains a compact signal summary:
16530
- signalOsc / oscillatorStrength / signalRangeAtrRatio / stopDistanceAtr / breakoutBodyAtr / chaseRiskBlocked / 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 / cmcFearGreedValueChange7d / cmcBtcDominanceChange24hPct / baseDecisionApproveBias / marketBreadthAdvancers / marketBreadthAdvanceDeclineRatio / marketBreadthReturn / shortBreadthShockPocket / shortBreadthNeutralPocket / referenceDerivativesRotationPocket / referenceXrpOiChangePct4h15m / referenceTrxOiChangePct4h15m / q4TargetAlpha1Allowed / q4ContinuationAllowed / q4ContinuationBlockReasons / q4ContinuationRecoveryAllowed / derivativesDirectionAligned / derivativesRiskFlags / derivativesFundingZScore / deterministicQuality / approvalAllowedNow / approvalBlockReasons / riskAnnotations.
16531
16532
  - Use this context as the primary strategy-specific interpretation instead of re-deriving it only from generic series.
16532
16533
  `;
16533
16534
  var SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX = -0.01;
@@ -16537,6 +16538,9 @@ var REFERENCE_XRP_OI_CHANGE_PCT_4H_15M_MIN = 1.6;
16537
16538
  var REFERENCE_TRX_OI_CHANGE_PCT_4H_15M_MAX = -0.2;
16538
16539
  var CHASE_STOP_DISTANCE_ATR_MAX = 4.5;
16539
16540
  var CHASE_BREAKOUT_BODY_ATR_MAX = 2.25;
16541
+ var MIN_APPROVAL_TP_DISTANCE_ATR = 2.9;
16542
+ var MIN_APPROVAL_TREND_ADX = 15;
16543
+ var MAX_APPROVAL_BENCHMARK_RELATIVE_STRENGTH_1D = 4;
16540
16544
  var toFiniteNumberOrNull = (value) => {
16541
16545
  if (typeof value === "number" && Number.isFinite(value)) {
16542
16546
  return value;
@@ -16711,6 +16715,19 @@ var getQ4ContinuationBlockReasons = (context) => {
16711
16715
  return reasons;
16712
16716
  };
16713
16717
  var getQ4ContinuationRecoveryAllowed = (context) => context.q4TargetAlpha1Allowed && !context.q4ContinuationAllowed && isInRange(context.effortVsResult, 0, 60) && context.cmcBtcDominanceChange24hPct != null && context.cmcBtcDominanceChange24hPct <= 0;
16718
+ var getApprovalRegimeBlockReasons = (context) => {
16719
+ const reasons = [];
16720
+ if (context.tpDistanceAtr == null || context.tpDistanceAtr < MIN_APPROVAL_TP_DISTANCE_ATR) {
16721
+ reasons.push("low_tp_distance_atr");
16722
+ }
16723
+ if (context.trendAdx == null || context.trendAdx < MIN_APPROVAL_TREND_ADX) {
16724
+ reasons.push("weak_trend_adx");
16725
+ }
16726
+ if (context.benchmarkRelativeStrength1d != null && context.benchmarkRelativeStrength1d > MAX_APPROVAL_BENCHMARK_RELATIVE_STRENGTH_1D) {
16727
+ reasons.push("benchmark_1d_chase_risk");
16728
+ }
16729
+ return reasons;
16730
+ };
16714
16731
  var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
16715
16732
  if (context.hardBlockReasons.length > 0) {
16716
16733
  return 2;
@@ -16724,6 +16741,9 @@ var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
16724
16741
  if (context.chaseRiskBlocked && !context.referenceDerivativesRotationPocket) {
16725
16742
  return 3;
16726
16743
  }
16744
+ if (!context.approvalRegimeAllowed) {
16745
+ return 3;
16746
+ }
16727
16747
  if (context.signalDirection === "SHORT") {
16728
16748
  return context.shortBreadthShockPocket || context.shortBreadthNeutralPocket || context.referenceDerivativesRotationPocket ? 4 : 3;
16729
16749
  }
@@ -16838,6 +16858,8 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16838
16858
  const candle = getRecord(baseContext?.candle);
16839
16859
  const raw = getRecord(baseContext?.raw);
16840
16860
  const regime = getRecord(baseContext?.regime);
16861
+ const regimeTrend = getRecord(regime?.trend);
16862
+ const regimeTrendAdx = getRecord(regimeTrend?.adx);
16841
16863
  const regimeSession = getRecord(regime?.session);
16842
16864
  const structure = getRecord(baseContext?.structure);
16843
16865
  const localRange = getRecord(structure?.localRange);
@@ -16877,6 +16899,9 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16877
16899
  const benchmarkRelativeStrength1h = toFiniteNumberOrNull(
16878
16900
  benchmark?.relativeStrength1h
16879
16901
  );
16902
+ const benchmarkRelativeStrength1d = toFiniteNumberOrNull(
16903
+ benchmark?.relativeStrength1d
16904
+ );
16880
16905
  const benchmarkTrendAlignment = typeof benchmark?.trendAlignment === "string" ? benchmark.trendAlignment : null;
16881
16906
  const targetVsBtcAlpha1h = toFiniteNumberOrNull(targetVsBtc?.alphaVsBtc1h);
16882
16907
  const targetVsBtcAlpha4h = toFiniteNumberOrNull(targetVsBtc?.alphaVsBtc4h);
@@ -16895,6 +16920,8 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16895
16920
  const stopDistanceAtr = toFiniteNumberOrNull(
16896
16921
  gateFeaturesSetup?.stopDistanceAtr
16897
16922
  );
16923
+ const tpDistanceAtr = toFiniteNumberOrNull(gateFeaturesSetup?.tpDistanceAtr);
16924
+ const trendAdx = toFiniteNumberOrNull(regimeTrendAdx?.adx);
16898
16925
  const breakoutBodyAtr = toFiniteNumberOrNull(
16899
16926
  structureAcceptance?.breakoutBodyAtr
16900
16927
  );
@@ -16934,6 +16961,12 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16934
16961
  effortVsResult,
16935
16962
  cmcBtcDominanceChange24hPct
16936
16963
  });
16964
+ const approvalRegimeBlockReasons = baseContextAvailable ? getApprovalRegimeBlockReasons({
16965
+ tpDistanceAtr,
16966
+ trendAdx,
16967
+ benchmarkRelativeStrength1d
16968
+ }) : [];
16969
+ const approvalRegimeAllowed = approvalRegimeBlockReasons.length === 0;
16937
16970
  const hardBlockReasons = [];
16938
16971
  if (invalidated) {
16939
16972
  hardBlockReasons.push("invalidated");
@@ -16973,6 +17006,7 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16973
17006
  if (chaseRiskBlocked && !referenceDerivativesRotationPocket) {
16974
17007
  approvalBlockReasons.push("chase_entry_risk");
16975
17008
  }
17009
+ approvalBlockReasons.push(...approvalRegimeBlockReasons);
16976
17010
  if (breakoutRetestQuality != null && breakoutRetestQuality < 0.25) {
16977
17011
  riskAnnotations.push("weak_retest_quality");
16978
17012
  }
@@ -17004,8 +17038,13 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
17004
17038
  oscillatorStrength,
17005
17039
  signalRangeAtrRatio,
17006
17040
  stopDistanceAtr,
17041
+ tpDistanceAtr,
17007
17042
  breakoutBodyAtr,
17043
+ trendAdx,
17044
+ benchmarkRelativeStrength1d,
17008
17045
  chaseRiskBlocked,
17046
+ approvalRegimeAllowed,
17047
+ approvalRegimeBlockReasons,
17009
17048
  kcMidline,
17010
17049
  kcUpper,
17011
17050
  kcLower,
@@ -17077,8 +17116,13 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
17077
17116
  oscillatorStrength,
17078
17117
  signalRangeAtrRatio,
17079
17118
  stopDistanceAtr,
17119
+ tpDistanceAtr,
17080
17120
  breakoutBodyAtr,
17121
+ trendAdx,
17122
+ benchmarkRelativeStrength1d,
17081
17123
  chaseRiskBlocked,
17124
+ approvalRegimeAllowed,
17125
+ approvalRegimeBlockReasons,
17082
17126
  kcMidline,
17083
17127
  kcUpper,
17084
17128
  kcLower,
@@ -17225,8 +17269,13 @@ Additional AdaptiveMomentumRibbon context:
17225
17269
  - oscillatorStrength=${context.oscillatorStrength?.toFixed?.(3) ?? "n/a"}
17226
17270
  - signalRangeAtrRatio=${context.signalRangeAtrRatio?.toFixed?.(3) ?? "n/a"}
17227
17271
  - stopDistanceAtr=${context.stopDistanceAtr?.toFixed?.(3) ?? "n/a"}
17272
+ - tpDistanceAtr=${context.tpDistanceAtr?.toFixed?.(3) ?? "n/a"}
17228
17273
  - breakoutBodyAtr=${context.breakoutBodyAtr?.toFixed?.(3) ?? "n/a"}
17274
+ - trendAdx=${context.trendAdx?.toFixed?.(3) ?? "n/a"}
17275
+ - benchmarkRelativeStrength1d=${context.benchmarkRelativeStrength1d?.toFixed?.(3) ?? "n/a"}
17229
17276
  - chaseRiskBlocked=${context.chaseRiskBlocked}
17277
+ - approvalRegimeAllowed=${context.approvalRegimeAllowed}
17278
+ - approvalRegimeBlockReasons=${context.approvalRegimeBlockReasons.join(", ") || "none"}
17230
17279
  - channelState=${context.channelState}
17231
17280
  - channelBiasAligned=${context.channelBiasAligned}
17232
17281
  - channelExtensionPct=${context.channelExtensionPct?.toFixed?.(3) ?? "n/a"}%
@@ -17327,9 +17376,7 @@ var MIN_APPROVAL_CHANNEL_WIDTH_PCT = 2;
17327
17376
  var MIN_HIGH_CONFIDENCE_CHANNEL_WIDTH_PCT = 2;
17328
17377
  var MIN_APPROVAL_VOLUME_REL20 = 10;
17329
17378
  var MIN_SHORT_APPROVAL_VOLUME_REL20 = 7;
17330
- var MAX_SHORT_RECOVERY_TARGET_LIQ_IMBALANCE_1H = -0.97;
17331
- var MIN_SHORT_RECOVERY_TARGET_LIQ_SPIKE_RATIO_1H = 5.7;
17332
- var MAX_SHORT_RECOVERY_ETH_FUNDING_RATE_1H = 37e-4;
17379
+ var MAX_REFERENCE_SHORT_RECOVERY_ETH_LIQ_IMBALANCE_1H = -0.99;
17333
17380
  var MAX_XRP_SHORT_RECOVERY_BTC_VS_ALT_RETURN_24H = -0.03;
17334
17381
  var MAX_XRP_SHORT_RECOVERY_FUNDING_Z_SCORE_1H = -1.8;
17335
17382
  var MIN_XRP_OI_REJECT_BIAS_BLOCK_15M = 25e7;
@@ -17370,6 +17417,7 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17370
17417
  targetDerivatives1h?.liqSpikeRatio
17371
17418
  );
17372
17419
  const targetLiqTotal1h = asFiniteNumber(targetDerivatives1h?.liqTotal);
17420
+ const ethLiqImbalance1h = asFiniteNumber(ethDerivatives1h?.liqImbalance);
17373
17421
  const ethFundingRate1h = asFiniteNumber(ethDerivatives1h?.fundingRate);
17374
17422
  const xrpOpenInterest15m = asFiniteNumber(xrpDerivatives15m?.openInterest);
17375
17423
  const xrpPriceOiDivergenceType = baseContext?.derivatives?.referenceContexts?.["XRPUSDT"]?.summary?.priceOiDivergenceType ?? null;
@@ -17405,12 +17453,13 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17405
17453
  const cmcExchangeLiquiditySupportsApproval = direction === "LONG" && cmcExchangeLiquidityAligned === true && cmcExchangeLiquidityStale !== true;
17406
17454
  const trendFollowSupportsApproval = direction === "LONG" && trendFollowState === "bull";
17407
17455
  const longApprovalSetup = direction === "LONG" && breakoutAligned && h4VolatilityState === "expanded" && cmcExchangeLiquiditySupportsApproval && trendFollowSupportsApproval && breakoutDistancePct >= minApprovalBreakoutDistancePct && channelWidthPct >= MIN_APPROVAL_CHANNEL_WIDTH_PCT && (volumeRel20 ?? 0) >= minApprovalVolumeRel20 && (rsi ?? Number.POSITIVE_INFINITY) <= MAX_APPROVAL_RSI && (bbWidthRank100 ?? 0) >= MIN_APPROVAL_BB_WIDTH_RANK_100;
17408
- const shortRecoverySetup = direction === "SHORT" && targetDerivatives1hStale !== true && ethDerivatives1hStale !== true && targetLiqImbalance1h != null && targetLiqSpikeRatio1h != null && ethFundingRate1h != null && targetLiqImbalance1h <= MAX_SHORT_RECOVERY_TARGET_LIQ_IMBALANCE_1H && targetLiqSpikeRatio1h >= MIN_SHORT_RECOVERY_TARGET_LIQ_SPIKE_RATIO_1H && ethFundingRate1h <= MAX_SHORT_RECOVERY_ETH_FUNDING_RATE_1H;
17409
- const xrpShortRecoverySetup = 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;
17456
+ 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
+ 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
+ const xrpShortRecoverySetup = xrpBtcShortRecoverySetup || xrpEthShortRecoverySetup;
17410
17459
  if (xrpOpenInterest15m != null && xrpOpenInterest15m >= MIN_XRP_OI_REJECT_BIAS_BLOCK_15M && baseApproveBias === "reject" && !xrpShortRecoverySetup) {
17411
17460
  hardBlockReasons.push("xrp_oi_reject_bias");
17412
17461
  }
17413
- const approvalSetup = longApprovalSetup || shortRecoverySetup || xrpShortRecoverySetup;
17462
+ const approvalSetup = longApprovalSetup || xrpShortRecoverySetup;
17414
17463
  const highConfidenceSetup = longApprovalSetup && breakoutDistancePct >= MIN_HIGH_CONFIDENCE_BREAKOUT_DISTANCE_PCT && channelWidthPct >= MIN_HIGH_CONFIDENCE_CHANNEL_WIDTH_PCT;
17415
17464
  let deterministicQuality = 3;
17416
17465
  if (hardBlockReasons.length > 0) {
@@ -17475,6 +17524,7 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17475
17524
  targetLiqImbalance1h,
17476
17525
  targetLiqSpikeRatio1h,
17477
17526
  targetLiqTotal1h,
17527
+ ethLiqImbalance1h,
17478
17528
  ethFundingRate1h,
17479
17529
  xrpOpenInterest15m,
17480
17530
  xrpPriceOiDivergenceType,
@@ -17556,6 +17606,7 @@ Additional AdaptiveTrendChannel context:
17556
17606
  - targetLiqImbalance1h=${String(context.targetLiqImbalance1h ?? "n/a")}
17557
17607
  - targetLiqSpikeRatio1h=${String(context.targetLiqSpikeRatio1h ?? "n/a")}
17558
17608
  - targetLiqTotal1h=${String(context.targetLiqTotal1h ?? "n/a")}
17609
+ - ethLiqImbalance1h=${String(context.ethLiqImbalance1h ?? "n/a")}
17559
17610
  - ethFundingRate1h=${String(context.ethFundingRate1h ?? "n/a")}
17560
17611
  - xrpOpenInterest15m=${String(context.xrpOpenInterest15m ?? "n/a")}
17561
17612
  - xrpPriceOiDivergenceType=${context.xrpPriceOiDivergenceType ?? "n/a"}
@@ -18369,12 +18420,13 @@ var buildDoubleTapAiContext = (payload) => {
18369
18420
  ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct == null ? ["missing_cmc_btc_dominance_change"] : [],
18370
18421
  ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct != null && (cmcBtcDominanceChange24hPct <= Q4_CMC_BTC_DOMINANCE_CHANGE_MIN || cmcBtcDominanceChange24hPct > Q4_CMC_BTC_DOMINANCE_CHANGE_MAX) ? ["cmc_btc_dominance_change_outside_band"] : [],
18371
18422
  ...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"] : [],
18372
- ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && altDispersion24h != null && altDispersion24h >= Q4_ALT_DISPERSION_24H_MAX ? ["alt_dispersion_24h_too_high_for_q4"] : []
18423
+ ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && altDispersion24h != null && altDispersion24h >= Q4_ALT_DISPERSION_24H_MAX ? ["alt_dispersion_24h_too_high_for_q4"] : [],
18424
+ ...q4CmcApproval ? ["legacy_q4_structural_observation_only"] : []
18373
18425
  ];
18374
18426
  const highPrecisionApprovalBlocked = legacyHighPrecisionShapeCandidate && !highPrecisionCmcApproval && !q4DerivativesApproval;
18375
- const q4DerivativesApprovalBlocked = q4DerivativesPocket && !q4DerivativesApproval && !highPrecisionCmcApproval && !q4CmcApproval;
18376
- const q4ApprovalBlocked = legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && !q4CmcApproval && !q4DerivativesApproval;
18377
- const approvalSourceAllowed = highPrecisionCmcApproval || q4CmcApproval || q4DerivativesApproval;
18427
+ const q4DerivativesApprovalBlocked = q4DerivativesPocket && !q4DerivativesApproval && !highPrecisionCmcApproval;
18428
+ const q4ApprovalBlocked = legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && !q4DerivativesApproval;
18429
+ const approvalSourceAllowed = highPrecisionCmcApproval || q4DerivativesApproval;
18378
18430
  const approvalBlocked = !approvalSourceAllowed && (highPrecisionApprovalBlocked || q4ApprovalBlocked || q4DerivativesApprovalBlocked);
18379
18431
  const defaultApprovalAllowed = structuralHardBlockReasons.length === 0 && approvalSourceAllowed && !approvalBlocked;
18380
18432
  const strictMomentumRoc1dOk = roc1d == null ? null : roc1d >= STRICT_MOMENTUM_ROC1D_MIN;
@@ -18408,7 +18460,7 @@ var buildDoubleTapAiContext = (payload) => {
18408
18460
  strictMomentumApproved: strictMomentumApprovalAllowedNow,
18409
18461
  strictMomentumRoc1dOk
18410
18462
  });
18411
- const deterministicQuality = structuralHardBlockReasons.length > 0 ? Math.min(geometryQuality, 2) : highPrecisionCmcApproval ? 5 : q4CmcApproval || q4DerivativesApproval ? 4 : Math.min(geometryQuality, 3);
18463
+ const deterministicQuality = structuralHardBlockReasons.length > 0 ? Math.min(geometryQuality, 2) : highPrecisionCmcApproval ? 5 : q4DerivativesApproval ? 4 : Math.min(geometryQuality, 3);
18412
18464
  return {
18413
18465
  ...context,
18414
18466
  baseContextAvailable,
@@ -18558,9 +18610,9 @@ Interpretation rules for DoubleTap:
18558
18610
  - Extremely tiny breaks can still be early noise; live approval needs support from baseContext.
18559
18611
  - Treat deterministicQuality and approvalAllowedNow as the normalized local gate result.
18560
18612
  - 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.
18561
- - Local q4 approval can come from the structural approval pocket plus active session window, execution score >= 35, lowTouchCount20 >= 1, -0.3 < CMC BTC dominance change <= -0.05, and BTC/alt dispersion 24h < 0.06.
18562
- - Local q4 approval can also come 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.
18563
- - Main local approval additionally needs strict momentum confirmation with ROC1D >= -5.25 for structural q4/q5 approvals; the derivatives reference q4 pocket is already momentum/positioning filtered and does not require that ROC gate.
18613
+ - 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.
18615
+ - 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.
18564
18616
  - A good long has two comparable lows and a clean close above the neckline.
18565
18617
  - A good short has two comparable highs and a clean close below the neckline.
18566
18618
  - Venue spread, trend bias, body strength, and reward-to-volatility are diagnostics for this gate, not strict local blockers.
@@ -18630,6 +18682,7 @@ var asFiniteNumber2 = (value) => {
18630
18682
  const parsed = Number(value);
18631
18683
  return Number.isFinite(parsed) ? parsed : null;
18632
18684
  };
18685
+ var asNullableFiniteNumber = (value) => value == null ? null : asFiniteNumber2(value);
18633
18686
  var asStringArray2 = (value) => Array.isArray(value) ? value.filter(
18634
18687
  (entry) => typeof entry === "string" && entry.trim().length > 0
18635
18688
  ) : [];
@@ -18638,6 +18691,8 @@ var MIN_Q3_UPGRADE_REACTION_CLOSE_DISTANCE_PCT = 1.5;
18638
18691
  var MIN_Q3_UPGRADE_BODY_STRENGTH = 0.65;
18639
18692
  var MIN_Q3_UPGRADE_VOLUME_REL20 = 1;
18640
18693
  var MAX_APPROVAL_CMC_FEAR_GREED_VALUE = 39;
18694
+ var MAX_APPROVAL_PRICE_DISTANCE_TO_MA_SLOW_ATR = 1.2;
18695
+ var MIN_APPROVAL_ACTIVE_LIQUIDITY_ZONES = 1;
18641
18696
  var MAX_DERIVATIVES_RISK_OFF_ALT_BASKET_RETURN_24H = -0.035;
18642
18697
  var MAX_DERIVATIVES_RISK_OFF_TRX_OI_CHANGE_PCT_4H = -1.8;
18643
18698
  var Q4_APPROVAL_ATR_RANK_BUCKETS = /* @__PURE__ */ new Set(["high", "extreme"]);
@@ -18701,6 +18756,12 @@ var buildLiquidityTailsGuardrailContext = ({
18701
18756
  const roc1h = asFiniteNumber2(baseContext?.regime?.momentum?.roc1h);
18702
18757
  const roc4h = asFiniteNumber2(baseContext?.regime?.momentum?.roc4h);
18703
18758
  const benchmarkTrendAlignment = baseContext?.relative?.benchmark?.trendAlignment ?? null;
18759
+ const priceDistanceToMaSlowAtr = asNullableFiniteNumber(
18760
+ baseContext?.regime?.trend?.priceDistanceToMaSlowAtr
18761
+ );
18762
+ const liquidityZonesActiveCount = asNullableFiniteNumber(
18763
+ baseContext?.structure?.liquidityZones?.activeCount
18764
+ );
18704
18765
  const atrPctRankBucket = typeof baseContext?.gateFeatures?.volatility?.atrPctRankBucket === "string" ? baseContext.gateFeatures.volatility.atrPctRankBucket : null;
18705
18766
  const q4AtrRankEligible = atrPctRankBucket != null && Q4_APPROVAL_ATR_RANK_BUCKETS.has(atrPctRankBucket);
18706
18767
  const liquidityRisk = typeof baseContext?.gateFeatures?.risk?.liquidityRisk === "string" ? baseContext.gateFeatures.risk.liquidityRisk : null;
@@ -18816,6 +18877,21 @@ var buildLiquidityTailsGuardrailContext = ({
18816
18877
  if (deterministicQuality === 3 && hardBlockReasons.length === 0 && derivativesRiskOffLongRecoveryPocket) {
18817
18878
  deterministicQuality = 4;
18818
18879
  }
18880
+ if (deterministicQuality >= 4) {
18881
+ const approvalContextReasons = [];
18882
+ if (priceDistanceToMaSlowAtr == null) {
18883
+ approvalContextReasons.push("price_distance_to_ma_slow_unavailable");
18884
+ } else if (priceDistanceToMaSlowAtr > MAX_APPROVAL_PRICE_DISTANCE_TO_MA_SLOW_ATR) {
18885
+ approvalContextReasons.push("price_overextended_from_ma_slow");
18886
+ }
18887
+ if (liquidityZonesActiveCount == null || liquidityZonesActiveCount < MIN_APPROVAL_ACTIVE_LIQUIDITY_ZONES) {
18888
+ approvalContextReasons.push("liquidity_zone_confirmation_missing");
18889
+ }
18890
+ if (approvalContextReasons.length > 0) {
18891
+ deterministicQuality = 3;
18892
+ softBlockReasons.push(...approvalContextReasons);
18893
+ }
18894
+ }
18819
18895
  return {
18820
18896
  ...signalContext,
18821
18897
  baseContextAvailable: Boolean(baseContext),
@@ -18830,6 +18906,8 @@ var buildLiquidityTailsGuardrailContext = ({
18830
18906
  roc1h,
18831
18907
  roc4h,
18832
18908
  benchmarkTrendAlignment,
18909
+ priceDistanceToMaSlowAtr,
18910
+ liquidityZonesActiveCount,
18833
18911
  atrPctRankBucket,
18834
18912
  q4AtrRankEligible,
18835
18913
  liquidityRisk,
@@ -18938,6 +19016,8 @@ Additional Liquidity Tails context:
18938
19016
  - roc1h=${String(context.roc1h ?? "n/a")}
18939
19017
  - roc4h=${String(context.roc4h ?? "n/a")}
18940
19018
  - benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
19019
+ - priceDistanceToMaSlowAtr=${String(context.priceDistanceToMaSlowAtr ?? "n/a")}
19020
+ - liquidityZonesActiveCount=${String(context.liquidityZonesActiveCount ?? "n/a")}
18941
19021
  - atrPctRankBucket=${context.atrPctRankBucket ?? "n/a"}
18942
19022
  - q4AtrRankEligible=${String(context.q4AtrRankEligible)}
18943
19023
  - liquidityRisk=${context.liquidityRisk ?? "n/a"}
@@ -19065,8 +19145,15 @@ var buildLiquidityZonesGuardrailContext = ({
19065
19145
  const lowTouchCount20 = asPresentFiniteNumber(
19066
19146
  baseContext?.structure?.levels?.lowTouchCount20
19067
19147
  );
19148
+ const ethReferenceDerivatives15m = baseContext?.derivatives?.referenceContexts?.ETHUSDT?.intervals?.["15m"];
19068
19149
  const ethReferenceOiChangePct4h = asPresentFiniteNumber(
19069
- baseContext?.derivatives?.referenceContexts?.ETHUSDT?.intervals?.["15m"]?.oiChangePct4h
19150
+ ethReferenceDerivatives15m?.oiChangePct4h
19151
+ );
19152
+ const ethReferenceOiChangePct24h = asPresentFiniteNumber(
19153
+ ethReferenceDerivatives15m?.oiChangePct24h
19154
+ );
19155
+ const ethReferenceFundingZScore = asPresentFiniteNumber(
19156
+ ethReferenceDerivatives15m?.fundingZScore
19070
19157
  );
19071
19158
  const solReferenceOiChangePct24h = asPresentFiniteNumber(
19072
19159
  baseContext?.derivatives?.referenceContexts?.SOLUSDT?.intervals?.["15m"]?.oiChangePct24h
@@ -19166,8 +19253,9 @@ var buildLiquidityZonesGuardrailContext = ({
19166
19253
  const hasBaseRetestConfirmation = filterMetric >= 3 && hitCount >= 2 && reactionCloseDistancePct >= 0.08 && retestPenetrationPct <= 90;
19167
19254
  const ethReferenceOiWeakPocket = ethReferenceOiChangePct4h != null && ethReferenceOiChangePct4h <= -0.8;
19168
19255
  const transitionStructureExpansionPocket = hasBaseRetestConfirmation && structureZoneState === "transition" && structureScore != null && structureScore >= 17 && adaptiveChannelFlipDown === false && !directionalCrowding && !ethReferenceOiWeakPocket;
19256
+ const ethReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && ethReferenceOiChangePct24h != null && ethReferenceOiChangePct24h <= -5.8 && ethReferenceFundingZScore != null && ethReferenceFundingZScore <= -1.05;
19169
19257
  const solReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && solReferenceOiChangePct24h != null && solReferenceOiChangePct24h <= -4.2 && solReferenceFundingZScore != null && solReferenceFundingZScore <= -1.2;
19170
- const calibratedExpansionPocket = transitionStructureExpansionPocket || solReferenceStressPocket;
19258
+ const calibratedExpansionPocket = transitionStructureExpansionPocket || ethReferenceStressPocket || solReferenceStressPocket;
19171
19259
  const longRequiresCalibratedExpansion = direction === "LONG" && !calibratedExpansionPocket;
19172
19260
  const approvalDisqualifiedByCalibration = !calibratedExpansionPocket && (longRequiresCalibratedExpansion || isContinuationBreakoutRetest || hasOverextendedVolumeConfirmation || hasIsolatedIndicatorSupport);
19173
19261
  if (longRequiresCalibratedExpansion) {
@@ -19241,9 +19329,12 @@ var buildLiquidityZonesGuardrailContext = ({
19241
19329
  adaptiveChannelFlipDown,
19242
19330
  lowTouchCount20,
19243
19331
  ethReferenceOiChangePct4h,
19332
+ ethReferenceOiChangePct24h,
19333
+ ethReferenceFundingZScore,
19244
19334
  solReferenceOiChangePct24h,
19245
19335
  solReferenceFundingZScore,
19246
19336
  transitionStructureExpansionPocket,
19337
+ ethReferenceStressPocket,
19247
19338
  solReferenceStressPocket,
19248
19339
  hardBlockReasons,
19249
19340
  softBlockReasons,
@@ -19349,9 +19440,12 @@ Additional Liquidity Zones context:
19349
19440
  - adaptiveChannelFlipDown=${String(context.adaptiveChannelFlipDown ?? "n/a")}
19350
19441
  - lowTouchCount20=${String(context.lowTouchCount20 ?? "n/a")}
19351
19442
  - ethReferenceOiChangePct4h=${String(context.ethReferenceOiChangePct4h ?? "n/a")}
19443
+ - ethReferenceOiChangePct24h=${String(context.ethReferenceOiChangePct24h ?? "n/a")}
19444
+ - ethReferenceFundingZScore=${String(context.ethReferenceFundingZScore ?? "n/a")}
19352
19445
  - solReferenceOiChangePct24h=${String(context.solReferenceOiChangePct24h ?? "n/a")}
19353
19446
  - solReferenceFundingZScore=${String(context.solReferenceFundingZScore ?? "n/a")}
19354
19447
  - transitionStructureExpansionPocket=${String(context.transitionStructureExpansionPocket)}
19448
+ - ethReferenceStressPocket=${String(context.ethReferenceStressPocket)}
19355
19449
  - solReferenceStressPocket=${String(context.solReferenceStressPocket)}
19356
19450
  - deterministicQuality=${context.deterministicQuality}
19357
19451
  - approvalAllowedNow=${String(context.approvalAllowedNow)}
@@ -19367,7 +19461,7 @@ Interpretation rules for Liquidity Zones:
19367
19461
  - A close fully through the level marks the zone crossed; crossed zones are not live-entry candidates.
19368
19462
  - Top-level derivatives context is BTC benchmark evidence; target-symbol derivatives require targetContext/targetDerived.
19369
19463
  - Do not treat derivatives points, rows, or loaded-history size as approval evidence.
19370
- - A calibrated transition-structure pocket or SOL reference stress pocket can approve a structurally valid retest.
19464
+ - A calibrated transition-structure pocket, ETH reference stress pocket, or SOL reference stress pocket can approve a structurally valid retest.
19371
19465
  - Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
19372
19466
  `.trim();
19373
19467
  },
@@ -20508,6 +20602,7 @@ var TREND_FOLLOW_OPENING_SESSION_MAX_MINUTES_FROM_OPEN = 75;
20508
20602
  var TREND_FOLLOW_OPENING_REF_XRP_OI_MAX = 324e6;
20509
20603
  var TREND_FOLLOW_OPENING_REF_XRP_OI_CHANGE_1H_MIN = 0.4;
20510
20604
  var TREND_FOLLOW_OPENING_REF_BNB_OI_MIN = 56e4;
20605
+ var TREND_FOLLOW_ALLOWED_VOLATILITY_STATE = "normal";
20511
20606
  var asFiniteNumber5 = (value) => {
20512
20607
  const parsed = Number(value);
20513
20608
  return Number.isFinite(parsed) ? parsed : null;
@@ -20619,6 +20714,7 @@ var buildTrendFollowGateFeatures = ({
20619
20714
  );
20620
20715
  const marketBreadthAligned = marketBreadthReturn == null || marketBreadth?.stale ? null : direction === "LONG" ? marketBreadthReturn >= 0 : direction === "SHORT" ? marketBreadthReturn <= 0 : null;
20621
20716
  const marketBreadthContinuation = marketBreadth?.stale === true ? "stale" : marketBreadthAligned === true ? "aligned" : marketBreadthAligned === false ? "against" : "unknown";
20717
+ const marketVolatilityState = typeof baseContext?.regime?.volatility?.state === "string" ? baseContext.regime.volatility.state : null;
20622
20718
  const targetVsBtcBeta20 = asFiniteNumber5(
20623
20719
  baseContext?.relative?.targetVsBtc?.betaToBtc20
20624
20720
  );
@@ -20670,6 +20766,7 @@ var buildTrendFollowGateFeatures = ({
20670
20766
  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;
20671
20767
  const referenceDerivativesCadencePocket = !referenceDerivativesLossBlock && (legacyCadencePocket || referenceDerivativesOiCompressionPocket || referenceDerivativesXrpFundingPocket || referenceDerivativesSolFlushPocket);
20672
20768
  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;
20769
+ const normalVolatilityCadencePocket = marketVolatilityState === TREND_FOLLOW_ALLOWED_VOLATILITY_STATE;
20673
20770
  return {
20674
20771
  setupStopDistanceAtr,
20675
20772
  setupTpDistanceAtr,
@@ -20684,6 +20781,7 @@ var buildTrendFollowGateFeatures = ({
20684
20781
  relativeContinuation,
20685
20782
  marketBreadthContinuation,
20686
20783
  marketBreadthDispersion: asFiniteNumber5(marketBreadth?.dispersion),
20784
+ marketVolatilityState,
20687
20785
  targetVsBtcBeta20,
20688
20786
  btcAltRegimeBtcTurnoverShare24h,
20689
20787
  btcAltRegimeAltBasketReturn24h,
@@ -20711,7 +20809,8 @@ var buildTrendFollowGateFeatures = ({
20711
20809
  referenceDerivativesLossBlock,
20712
20810
  referenceDerivativesCadencePocket,
20713
20811
  referenceDerivativesOpeningPocket,
20714
- highQualityCadencePocket: referenceDerivativesCadencePocket || referenceDerivativesOpeningPocket
20812
+ normalVolatilityCadencePocket,
20813
+ highQualityCadencePocket: normalVolatilityCadencePocket && (referenceDerivativesCadencePocket || referenceDerivativesOpeningPocket)
20715
20814
  };
20716
20815
  };
20717
20816
  var buildTrendFollowGuardrailContext = ({
@@ -20944,6 +21043,7 @@ Additional TrendFollow context:
20944
21043
  - trendFollowGateRelativeContinuation=${context.trendFollowGateFeatures.relativeContinuation}
20945
21044
  - trendFollowGateMarketBreadthContinuation=${context.trendFollowGateFeatures.marketBreadthContinuation}
20946
21045
  - trendFollowGateMarketBreadthDispersion=${String(context.trendFollowGateFeatures.marketBreadthDispersion ?? "n/a")}
21046
+ - trendFollowGateMarketVolatilityState=${String(context.trendFollowGateFeatures.marketVolatilityState ?? "n/a")}
20947
21047
  - trendFollowGateTargetVsBtcBeta20=${String(context.trendFollowGateFeatures.targetVsBtcBeta20 ?? "n/a")}
20948
21048
  - trendFollowGateBtcAltRegimeBtcTurnoverShare24h=${String(context.trendFollowGateFeatures.btcAltRegimeBtcTurnoverShare24h ?? "n/a")}
20949
21049
  - trendFollowGateBtcAltRegimeAltBasketReturn24h=${String(context.trendFollowGateFeatures.btcAltRegimeAltBasketReturn24h ?? "n/a")}
@@ -20971,6 +21071,7 @@ Additional TrendFollow context:
20971
21071
  - trendFollowGateReferenceDerivativesLossBlock=${String(context.trendFollowGateFeatures.referenceDerivativesLossBlock)}
20972
21072
  - trendFollowGateReferenceDerivativesCadencePocket=${String(context.trendFollowGateFeatures.referenceDerivativesCadencePocket)}
20973
21073
  - trendFollowGateReferenceDerivativesOpeningPocket=${String(context.trendFollowGateFeatures.referenceDerivativesOpeningPocket)}
21074
+ - trendFollowGateNormalVolatilityCadencePocket=${String(context.trendFollowGateFeatures.normalVolatilityCadencePocket)}
20974
21075
  - trendFollowGateHighQualityCadencePocket=${String(context.trendFollowGateFeatures.highQualityCadencePocket)}
20975
21076
  - benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
20976
21077
  - derivativesPressure=${context.derivativesPressure ?? "n/a"}
@@ -20988,7 +21089,7 @@ Interpretation rules for TrendFollow:
20988
21089
  - The ATR trailing stop is the structural invalidation line and also updates while a position is open.
20989
21090
  - Prefer breakouts aligned with shared market context and backed by participation.
20990
21091
  - Late, thin, crowded, inside-range, adverse-delta, weak-momentum, or weak-volume-structure breakouts should be downgraded even if the pivot cross is valid.
20991
- - Live approval is reserved for calibrated SHORT derivatives pockets: the legacy BTC benchmark long-liquidation flush, guarded extra-reference XRP/SOL/BNB/TRX continuation pockets, or the narrow opening-session XRP/BNB reference pocket; other structurally valid breakouts remain watch mode.
21092
+ - Live approval is reserved for calibrated SHORT derivatives pockets in normal volatility: the legacy BTC benchmark long-liquidation flush, guarded extra-reference XRP/SOL/BNB/TRX continuation pockets, or the narrow opening-session XRP/BNB reference pocket; other structurally valid breakouts remain watch mode.
20992
21093
  - Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
20993
21094
  `.trim();
20994
21095
  },
@@ -21020,6 +21121,11 @@ var SHORT_BREADTH_SHOCK_1H_LIQ_SHORT_MAX = 0.208;
21020
21121
  var LONG_ALT_LEADERSHIP_BTC_VS_ALT_RETURN_24H_MAX = -503054e-8;
21021
21122
  var LONG_ALT_LEADERSHIP_BTC_VS_ALT_RETURN_1H_MAX = -581403e-8;
21022
21123
  var LONG_ALT_LEADERSHIP_FEAR_GREED_CHANGE_24H_MIN = -1;
21124
+ var LONG_BROAD_MARKET_SHORT_FLUSH_ADVANCERS_MIN = 27;
21125
+ var LONG_BROAD_MARKET_SHORT_FLUSH_PCT_ABOVE_MA20_MIN = 0.95;
21126
+ var LONG_BROAD_MARKET_SHORT_FLUSH_BTC_VS_ALT_RETURN_24H_MIN = 0;
21127
+ var SHORT_ASIA_LONG_FLUSH_LOW_CMC_FEAR_GREED_MAX = 18;
21128
+ var SHORT_ASIA_LONG_FLUSH_ADVANCERS_MAX = 2;
21023
21129
  var toMtfAlignmentForTrendShift = ({
21024
21130
  direction,
21025
21131
  mtfAlignment
@@ -21268,12 +21374,21 @@ var buildTrendShiftGuardrailContext = ({
21268
21374
  );
21269
21375
  const gateVolatility = baseContext?.gateFeatures?.volatility;
21270
21376
  const gateRelative = baseContext?.gateFeatures?.relative;
21377
+ const baseMarketBreadth = baseContext?.relative?.marketBreadth;
21271
21378
  const baseBtcAltRegime = baseContext?.relative?.btcAltRegime;
21272
21379
  const baseCmcFearGreed = baseContext?.relative?.cmcFearGreed;
21273
21380
  const bbWidthPct = asFiniteNumber6(volatility?.bbWidthPct);
21274
21381
  const marketBreadthReturn = asFiniteNumber6(gateRelative?.marketBreadthReturn);
21382
+ const marketBreadthAdvancers = asFiniteNumber6(baseMarketBreadth?.advancers);
21383
+ const marketBreadthPctAboveMa20 = asFiniteNumber6(
21384
+ baseMarketBreadth?.pctAboveMa20
21385
+ );
21386
+ const marketBreadthStale = gateRelative?.marketBreadthStale === true || baseMarketBreadth?.stale === true;
21275
21387
  const btcVsAltReturn24h = asFiniteNumber6(gateRelative?.btcVsAltReturn24h);
21276
21388
  const btcVsAltReturn1h = asFiniteNumber6(baseBtcAltRegime?.btcVsAltReturn1h);
21389
+ const cmcFearGreedValue = asFiniteNumber6(
21390
+ gateRelative?.cmcFearGreedValue ?? baseCmcFearGreed?.value
21391
+ );
21277
21392
  const cmcFearGreedValueChange24h = asFiniteNumber6(
21278
21393
  gateRelative?.cmcFearGreedValueChange24h ?? baseCmcFearGreed?.valueChange24h
21279
21394
  );
@@ -21393,9 +21508,11 @@ var buildTrendShiftGuardrailContext = ({
21393
21508
  const shortExtremeAtrHighBbRisk = signalContext.signalDirection === "SHORT" && gateVolatility?.state === "normal" && gateVolatility.atrPctRankBucket === "extreme" && gateVolatility.bbWidthRankBucket === "high";
21394
21509
  const shortBullSwingStructureRisk = signalContext.signalDirection === "SHORT" && swingBias === "bull";
21395
21510
  const shortLowBollingerWidthRisk = signalContext.signalDirection === "SHORT" && bbWidthPct != null && bbWidthPct <= SHORT_LOW_BB_WIDTH_PCT_MAX;
21511
+ 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;
21396
21512
  const lowRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility < 0.25;
21397
21513
  const defensiveRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility >= 0.25 && rewardToVolatility < 8;
21398
21514
  const longBtcAltRegimeRisk = signalContext.signalDirection === "LONG" && btcAltRegimeStale !== true && (btcAltRegime === "btc_lead" || btcAltRegime === "risk_off");
21515
+ 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;
21399
21516
  const cmcExchangeLiquidityVolumeChangeRisk = cmcExchangeLiquidityStale !== true && cmcExchangeLiquidityVolumeChange24hPct != null && (cmcExchangeLiquidityVolumeChange24hPct > -0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0 || cmcExchangeLiquidityVolumeChange24hPct >= 0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0.3);
21400
21517
  if (deterministicQuality >= 5 && longRelativeStrengthOverextended) {
21401
21518
  deterministicQuality = 4;
@@ -21433,6 +21550,10 @@ var buildTrendShiftGuardrailContext = ({
21433
21550
  deterministicQuality = 4;
21434
21551
  hardBlockReasons.push("short_bull_swing_structure");
21435
21552
  }
21553
+ if (deterministicQuality >= 5 && shortAsiaLongFlushLowCmcBreadthRisk) {
21554
+ deterministicQuality = 4;
21555
+ hardBlockReasons.push("short_asia_long_flush_low_cmc_breadth");
21556
+ }
21436
21557
  if (deterministicQuality >= 4 && lowRewardToVolatilityRisk) {
21437
21558
  deterministicQuality = 4;
21438
21559
  hardBlockReasons.push("low_reward_to_volatility");
@@ -21445,6 +21566,10 @@ var buildTrendShiftGuardrailContext = ({
21445
21566
  deterministicQuality = 4;
21446
21567
  hardBlockReasons.push("long_btc_alt_regime_risk");
21447
21568
  }
21569
+ if (deterministicQuality >= 5 && longBroadMarketShortFlushRisk) {
21570
+ deterministicQuality = 4;
21571
+ hardBlockReasons.push("long_broad_market_short_flush_risk");
21572
+ }
21448
21573
  if (deterministicQuality >= 4 && cmcExchangeLiquidityVolumeChangeRisk) {
21449
21574
  deterministicQuality = 4;
21450
21575
  hardBlockReasons.push("cmc_exchange_liquidity_volume_change_risk");
@@ -21510,9 +21635,11 @@ var buildTrendShiftGuardrailContext = ({
21510
21635
  shortExtremeAtrHighBbRisk,
21511
21636
  shortBullSwingStructureRisk,
21512
21637
  shortLowBollingerWidthRisk,
21638
+ shortAsiaLongFlushLowCmcBreadthRisk,
21513
21639
  lowRewardToVolatilityRisk,
21514
21640
  defensiveRewardToVolatilityRisk,
21515
21641
  longBtcAltRegimeRisk,
21642
+ longBroadMarketShortFlushRisk,
21516
21643
  cmcExchangeLiquidityVolumeChangeRisk,
21517
21644
  q4TrendShiftGateFeaturesRecoveryCandidate,
21518
21645
  q4UsClosingOiConfirmationRecoveryCandidate,
@@ -21528,8 +21655,11 @@ var buildTrendShiftGuardrailContext = ({
21528
21655
  nearPointOfControl,
21529
21656
  relativeStrength1h,
21530
21657
  marketBreadthReturn,
21658
+ marketBreadthAdvancers,
21659
+ marketBreadthPctAboveMa20,
21531
21660
  btcVsAltReturn24h,
21532
21661
  btcVsAltReturn1h,
21662
+ cmcFearGreedValue,
21533
21663
  cmcFearGreedValueChange24h,
21534
21664
  derivatives1hLiqShort,
21535
21665
  btcAltRegime,
@@ -21597,12 +21727,16 @@ var getTrendShiftGuardrailReasonText = (reason) => {
21597
21727
  return "the SHORT flip is still fighting a bullish swing structure, so keep it in watch mode";
21598
21728
  case "short_low_bollinger_width":
21599
21729
  return "the SHORT flip is in a narrow Bollinger-width compression pocket that has been less reliable, so keep it in watch mode";
21730
+ case "short_asia_long_flush_low_cmc_breadth":
21731
+ 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";
21600
21732
  case "low_reward_to_volatility":
21601
21733
  return "the expected reward is too small relative to current volatility after costs, so keep the flip in watch mode";
21602
21734
  case "reward_to_volatility_below_defensive_threshold":
21603
21735
  return "the expected reward is not large enough relative to current volatility for the defensive TrendShift gate after costs";
21604
21736
  case "long_btc_alt_regime_risk":
21605
21737
  return "the LONG flip is fighting a BTC-led or risk-off alt regime, so keep it in watch mode";
21738
+ case "long_broad_market_short_flush_risk":
21739
+ return "the LONG flip is chasing a broad-market squeeze while BTC is leading alts and benchmark derivatives show a short flush, so keep it in watch mode";
21606
21740
  case "cmc_exchange_liquidity_volume_change_risk":
21607
21741
  return "major-exchange liquidity change is in a historically choppy CMC band, so keep the flip in watch mode";
21608
21742
  default:
@@ -21717,8 +21851,11 @@ Additional TrendShift context:
21717
21851
  - nearPointOfControl=${String(context.nearPointOfControl ?? "n/a")}
21718
21852
  - relativeStrength1h=${String(context.relativeStrength1h ?? "n/a")}
21719
21853
  - marketBreadthReturn=${String(context.marketBreadthReturn ?? "n/a")}
21854
+ - marketBreadthAdvancers=${String(context.marketBreadthAdvancers ?? "n/a")}
21855
+ - marketBreadthPctAboveMa20=${String(context.marketBreadthPctAboveMa20 ?? "n/a")}
21720
21856
  - btcVsAltReturn24h=${String(context.btcVsAltReturn24h ?? "n/a")}
21721
21857
  - btcVsAltReturn1h=${String(context.btcVsAltReturn1h ?? "n/a")}
21858
+ - cmcFearGreedValue=${String(context.cmcFearGreedValue ?? "n/a")}
21722
21859
  - cmcFearGreedValueChange24h=${String(context.cmcFearGreedValueChange24h ?? "n/a")}
21723
21860
  - derivatives1hLiqShort=${String(context.derivatives1hLiqShort ?? "n/a")}
21724
21861
  - btcAltRegime=${context.btcAltRegime ?? "n/a"}
@@ -21747,7 +21884,9 @@ Additional TrendShift context:
21747
21884
  - shortLowBollingerWidthRisk=${String(context.shortLowBollingerWidthRisk)}
21748
21885
  - defensiveRewardToVolatilityRisk=${String(context.defensiveRewardToVolatilityRisk)}
21749
21886
  - shortBullSwingStructureRisk=${String(context.shortBullSwingStructureRisk)}
21887
+ - shortAsiaLongFlushLowCmcBreadthRisk=${String(context.shortAsiaLongFlushLowCmcBreadthRisk)}
21750
21888
  - longBtcAltRegimeRisk=${String(context.longBtcAltRegimeRisk)}
21889
+ - longBroadMarketShortFlushRisk=${String(context.longBroadMarketShortFlushRisk)}
21751
21890
  - cmcExchangeLiquidityVolumeChangeRisk=${String(context.cmcExchangeLiquidityVolumeChangeRisk)}
21752
21891
  - q4TrendShiftGateFeaturesRecoveryCandidate=${String(context.q4TrendShiftGateFeaturesRecoveryCandidate)}
21753
21892
  - q4UsClosingOiConfirmationRecoveryCandidate=${String(context.q4UsClosingOiConfirmationRecoveryCandidate)}
@@ -21784,8 +21923,10 @@ Interpretation rules for TrendShift:
21784
21923
  - For SHORT, being near the price-volume point of control is a watch-only warning; LONG near-POC flips are not blocked by this rule.
21785
21924
  - For SHORT, a bullish swing structure is a watch-only warning even when the immediate flip geometry looks q5-strong.
21786
21925
  - For SHORT, a narrow Bollinger-width compression pocket is watch-only even if another q4 recovery condition is present.
21926
+ - For SHORT, Asia-session long-flush setups are watch-only when CMC fear/greed and market breadth are already in capitulation.
21787
21927
  - The defensive live gate requires rewardToVolatility >= 8 when that field is available.
21788
21928
  - For LONG, BTC-led or risk-off BTC/alt regime is watch-only even when flip geometry is q5-strong.
21929
+ - 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.
21789
21930
  - 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.
21790
21931
  - 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.
21791
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.