@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.mjs CHANGED
@@ -16484,6 +16484,7 @@ AdaptiveMomentumRibbon addon:
16484
16484
  - 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.
16485
16485
  - 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.
16486
16486
  - Non-derivatives approvals are demoted when stopDistanceAtr > 4.5 and breakoutBodyAtr > 2.25, because that combination behaves like a chase entry.
16487
+ - All live approvals require a calibrated market-regime floor: tpDistanceAtr >= 2.9, trendAdx >= 15, and benchmarkRelativeStrength1d <= 4 when available.
16487
16488
  - LONG approvals require cmcAltLiquidityRegime to be anything except \`btc_favored\` when that CMC field is available.
16488
16489
  - Non-q5 LONG approvals require targetVsBtcAlpha1h <= 2.4 when that field is available, to avoid chase entries after target already outran BTC.
16489
16490
  - \`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.
@@ -16492,7 +16493,7 @@ AdaptiveMomentumRibbon addon:
16492
16493
  `;
16493
16494
  var ADAPTIVE_MOMENTUM_RIBBON_PAYLOAD_PROMPT = `
16494
16495
  - \`payload.additionalIndicators.adaptiveMomentumRibbonContext\` contains a compact signal summary:
16495
- 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.
16496
+ 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.
16496
16497
  - Use this context as the primary strategy-specific interpretation instead of re-deriving it only from generic series.
16497
16498
  `;
16498
16499
  var SHORT_BREADTH_SHOCK_MARKET_BREADTH_RETURN_MAX = -0.01;
@@ -16502,6 +16503,9 @@ var REFERENCE_XRP_OI_CHANGE_PCT_4H_15M_MIN = 1.6;
16502
16503
  var REFERENCE_TRX_OI_CHANGE_PCT_4H_15M_MAX = -0.2;
16503
16504
  var CHASE_STOP_DISTANCE_ATR_MAX = 4.5;
16504
16505
  var CHASE_BREAKOUT_BODY_ATR_MAX = 2.25;
16506
+ var MIN_APPROVAL_TP_DISTANCE_ATR = 2.9;
16507
+ var MIN_APPROVAL_TREND_ADX = 15;
16508
+ var MAX_APPROVAL_BENCHMARK_RELATIVE_STRENGTH_1D = 4;
16505
16509
  var toFiniteNumberOrNull = (value) => {
16506
16510
  if (typeof value === "number" && Number.isFinite(value)) {
16507
16511
  return value;
@@ -16676,6 +16680,19 @@ var getQ4ContinuationBlockReasons = (context) => {
16676
16680
  return reasons;
16677
16681
  };
16678
16682
  var getQ4ContinuationRecoveryAllowed = (context) => context.q4TargetAlpha1Allowed && !context.q4ContinuationAllowed && isInRange(context.effortVsResult, 0, 60) && context.cmcBtcDominanceChange24hPct != null && context.cmcBtcDominanceChange24hPct <= 0;
16683
+ var getApprovalRegimeBlockReasons = (context) => {
16684
+ const reasons = [];
16685
+ if (context.tpDistanceAtr == null || context.tpDistanceAtr < MIN_APPROVAL_TP_DISTANCE_ATR) {
16686
+ reasons.push("low_tp_distance_atr");
16687
+ }
16688
+ if (context.trendAdx == null || context.trendAdx < MIN_APPROVAL_TREND_ADX) {
16689
+ reasons.push("weak_trend_adx");
16690
+ }
16691
+ if (context.benchmarkRelativeStrength1d != null && context.benchmarkRelativeStrength1d > MAX_APPROVAL_BENCHMARK_RELATIVE_STRENGTH_1D) {
16692
+ reasons.push("benchmark_1d_chase_risk");
16693
+ }
16694
+ return reasons;
16695
+ };
16679
16696
  var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
16680
16697
  if (context.hardBlockReasons.length > 0) {
16681
16698
  return 2;
@@ -16689,6 +16706,9 @@ var getDeterministicAdaptiveMomentumRibbonQuality = (context) => {
16689
16706
  if (context.chaseRiskBlocked && !context.referenceDerivativesRotationPocket) {
16690
16707
  return 3;
16691
16708
  }
16709
+ if (!context.approvalRegimeAllowed) {
16710
+ return 3;
16711
+ }
16692
16712
  if (context.signalDirection === "SHORT") {
16693
16713
  return context.shortBreadthShockPocket || context.shortBreadthNeutralPocket || context.referenceDerivativesRotationPocket ? 4 : 3;
16694
16714
  }
@@ -16803,6 +16823,8 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16803
16823
  const candle = getRecord(baseContext?.candle);
16804
16824
  const raw = getRecord(baseContext?.raw);
16805
16825
  const regime = getRecord(baseContext?.regime);
16826
+ const regimeTrend = getRecord(regime?.trend);
16827
+ const regimeTrendAdx = getRecord(regimeTrend?.adx);
16806
16828
  const regimeSession = getRecord(regime?.session);
16807
16829
  const structure = getRecord(baseContext?.structure);
16808
16830
  const localRange = getRecord(structure?.localRange);
@@ -16842,6 +16864,9 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16842
16864
  const benchmarkRelativeStrength1h = toFiniteNumberOrNull(
16843
16865
  benchmark?.relativeStrength1h
16844
16866
  );
16867
+ const benchmarkRelativeStrength1d = toFiniteNumberOrNull(
16868
+ benchmark?.relativeStrength1d
16869
+ );
16845
16870
  const benchmarkTrendAlignment = typeof benchmark?.trendAlignment === "string" ? benchmark.trendAlignment : null;
16846
16871
  const targetVsBtcAlpha1h = toFiniteNumberOrNull(targetVsBtc?.alphaVsBtc1h);
16847
16872
  const targetVsBtcAlpha4h = toFiniteNumberOrNull(targetVsBtc?.alphaVsBtc4h);
@@ -16860,6 +16885,8 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16860
16885
  const stopDistanceAtr = toFiniteNumberOrNull(
16861
16886
  gateFeaturesSetup?.stopDistanceAtr
16862
16887
  );
16888
+ const tpDistanceAtr = toFiniteNumberOrNull(gateFeaturesSetup?.tpDistanceAtr);
16889
+ const trendAdx = toFiniteNumberOrNull(regimeTrendAdx?.adx);
16863
16890
  const breakoutBodyAtr = toFiniteNumberOrNull(
16864
16891
  structureAcceptance?.breakoutBodyAtr
16865
16892
  );
@@ -16899,6 +16926,12 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16899
16926
  effortVsResult,
16900
16927
  cmcBtcDominanceChange24hPct
16901
16928
  });
16929
+ const approvalRegimeBlockReasons = baseContextAvailable ? getApprovalRegimeBlockReasons({
16930
+ tpDistanceAtr,
16931
+ trendAdx,
16932
+ benchmarkRelativeStrength1d
16933
+ }) : [];
16934
+ const approvalRegimeAllowed = approvalRegimeBlockReasons.length === 0;
16902
16935
  const hardBlockReasons = [];
16903
16936
  if (invalidated) {
16904
16937
  hardBlockReasons.push("invalidated");
@@ -16938,6 +16971,7 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16938
16971
  if (chaseRiskBlocked && !referenceDerivativesRotationPocket) {
16939
16972
  approvalBlockReasons.push("chase_entry_risk");
16940
16973
  }
16974
+ approvalBlockReasons.push(...approvalRegimeBlockReasons);
16941
16975
  if (breakoutRetestQuality != null && breakoutRetestQuality < 0.25) {
16942
16976
  riskAnnotations.push("weak_retest_quality");
16943
16977
  }
@@ -16969,8 +17003,13 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
16969
17003
  oscillatorStrength,
16970
17004
  signalRangeAtrRatio,
16971
17005
  stopDistanceAtr,
17006
+ tpDistanceAtr,
16972
17007
  breakoutBodyAtr,
17008
+ trendAdx,
17009
+ benchmarkRelativeStrength1d,
16973
17010
  chaseRiskBlocked,
17011
+ approvalRegimeAllowed,
17012
+ approvalRegimeBlockReasons,
16974
17013
  kcMidline,
16975
17014
  kcUpper,
16976
17015
  kcLower,
@@ -17042,8 +17081,13 @@ var buildAdaptiveMomentumRibbonContext = (signal, additionalIndicators) => {
17042
17081
  oscillatorStrength,
17043
17082
  signalRangeAtrRatio,
17044
17083
  stopDistanceAtr,
17084
+ tpDistanceAtr,
17045
17085
  breakoutBodyAtr,
17086
+ trendAdx,
17087
+ benchmarkRelativeStrength1d,
17046
17088
  chaseRiskBlocked,
17089
+ approvalRegimeAllowed,
17090
+ approvalRegimeBlockReasons,
17047
17091
  kcMidline,
17048
17092
  kcUpper,
17049
17093
  kcLower,
@@ -17190,8 +17234,13 @@ Additional AdaptiveMomentumRibbon context:
17190
17234
  - oscillatorStrength=${context.oscillatorStrength?.toFixed?.(3) ?? "n/a"}
17191
17235
  - signalRangeAtrRatio=${context.signalRangeAtrRatio?.toFixed?.(3) ?? "n/a"}
17192
17236
  - stopDistanceAtr=${context.stopDistanceAtr?.toFixed?.(3) ?? "n/a"}
17237
+ - tpDistanceAtr=${context.tpDistanceAtr?.toFixed?.(3) ?? "n/a"}
17193
17238
  - breakoutBodyAtr=${context.breakoutBodyAtr?.toFixed?.(3) ?? "n/a"}
17239
+ - trendAdx=${context.trendAdx?.toFixed?.(3) ?? "n/a"}
17240
+ - benchmarkRelativeStrength1d=${context.benchmarkRelativeStrength1d?.toFixed?.(3) ?? "n/a"}
17194
17241
  - chaseRiskBlocked=${context.chaseRiskBlocked}
17242
+ - approvalRegimeAllowed=${context.approvalRegimeAllowed}
17243
+ - approvalRegimeBlockReasons=${context.approvalRegimeBlockReasons.join(", ") || "none"}
17195
17244
  - channelState=${context.channelState}
17196
17245
  - channelBiasAligned=${context.channelBiasAligned}
17197
17246
  - channelExtensionPct=${context.channelExtensionPct?.toFixed?.(3) ?? "n/a"}%
@@ -17292,9 +17341,7 @@ var MIN_APPROVAL_CHANNEL_WIDTH_PCT = 2;
17292
17341
  var MIN_HIGH_CONFIDENCE_CHANNEL_WIDTH_PCT = 2;
17293
17342
  var MIN_APPROVAL_VOLUME_REL20 = 10;
17294
17343
  var MIN_SHORT_APPROVAL_VOLUME_REL20 = 7;
17295
- var MAX_SHORT_RECOVERY_TARGET_LIQ_IMBALANCE_1H = -0.97;
17296
- var MIN_SHORT_RECOVERY_TARGET_LIQ_SPIKE_RATIO_1H = 5.7;
17297
- var MAX_SHORT_RECOVERY_ETH_FUNDING_RATE_1H = 37e-4;
17344
+ var MAX_REFERENCE_SHORT_RECOVERY_ETH_LIQ_IMBALANCE_1H = -0.99;
17298
17345
  var MAX_XRP_SHORT_RECOVERY_BTC_VS_ALT_RETURN_24H = -0.03;
17299
17346
  var MAX_XRP_SHORT_RECOVERY_FUNDING_Z_SCORE_1H = -1.8;
17300
17347
  var MIN_XRP_OI_REJECT_BIAS_BLOCK_15M = 25e7;
@@ -17335,6 +17382,7 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17335
17382
  targetDerivatives1h?.liqSpikeRatio
17336
17383
  );
17337
17384
  const targetLiqTotal1h = asFiniteNumber(targetDerivatives1h?.liqTotal);
17385
+ const ethLiqImbalance1h = asFiniteNumber(ethDerivatives1h?.liqImbalance);
17338
17386
  const ethFundingRate1h = asFiniteNumber(ethDerivatives1h?.fundingRate);
17339
17387
  const xrpOpenInterest15m = asFiniteNumber(xrpDerivatives15m?.openInterest);
17340
17388
  const xrpPriceOiDivergenceType = baseContext?.derivatives?.referenceContexts?.["XRPUSDT"]?.summary?.priceOiDivergenceType ?? null;
@@ -17370,12 +17418,13 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17370
17418
  const cmcExchangeLiquiditySupportsApproval = direction === "LONG" && cmcExchangeLiquidityAligned === true && cmcExchangeLiquidityStale !== true;
17371
17419
  const trendFollowSupportsApproval = direction === "LONG" && trendFollowState === "bull";
17372
17420
  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;
17373
- 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;
17374
- 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;
17421
+ 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;
17422
+ 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;
17423
+ const xrpShortRecoverySetup = xrpBtcShortRecoverySetup || xrpEthShortRecoverySetup;
17375
17424
  if (xrpOpenInterest15m != null && xrpOpenInterest15m >= MIN_XRP_OI_REJECT_BIAS_BLOCK_15M && baseApproveBias === "reject" && !xrpShortRecoverySetup) {
17376
17425
  hardBlockReasons.push("xrp_oi_reject_bias");
17377
17426
  }
17378
- const approvalSetup = longApprovalSetup || shortRecoverySetup || xrpShortRecoverySetup;
17427
+ const approvalSetup = longApprovalSetup || xrpShortRecoverySetup;
17379
17428
  const highConfidenceSetup = longApprovalSetup && breakoutDistancePct >= MIN_HIGH_CONFIDENCE_BREAKOUT_DISTANCE_PCT && channelWidthPct >= MIN_HIGH_CONFIDENCE_CHANNEL_WIDTH_PCT;
17380
17429
  let deterministicQuality = 3;
17381
17430
  if (hardBlockReasons.length > 0) {
@@ -17440,6 +17489,7 @@ var buildAdaptiveTrendChannelGuardrailContext = ({
17440
17489
  targetLiqImbalance1h,
17441
17490
  targetLiqSpikeRatio1h,
17442
17491
  targetLiqTotal1h,
17492
+ ethLiqImbalance1h,
17443
17493
  ethFundingRate1h,
17444
17494
  xrpOpenInterest15m,
17445
17495
  xrpPriceOiDivergenceType,
@@ -17521,6 +17571,7 @@ Additional AdaptiveTrendChannel context:
17521
17571
  - targetLiqImbalance1h=${String(context.targetLiqImbalance1h ?? "n/a")}
17522
17572
  - targetLiqSpikeRatio1h=${String(context.targetLiqSpikeRatio1h ?? "n/a")}
17523
17573
  - targetLiqTotal1h=${String(context.targetLiqTotal1h ?? "n/a")}
17574
+ - ethLiqImbalance1h=${String(context.ethLiqImbalance1h ?? "n/a")}
17524
17575
  - ethFundingRate1h=${String(context.ethFundingRate1h ?? "n/a")}
17525
17576
  - xrpOpenInterest15m=${String(context.xrpOpenInterest15m ?? "n/a")}
17526
17577
  - xrpPriceOiDivergenceType=${context.xrpPriceOiDivergenceType ?? "n/a"}
@@ -18334,12 +18385,13 @@ var buildDoubleTapAiContext = (payload) => {
18334
18385
  ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct == null ? ["missing_cmc_btc_dominance_change"] : [],
18335
18386
  ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && cmcBtcDominanceChange24hPct != null && (cmcBtcDominanceChange24hPct <= Q4_CMC_BTC_DOMINANCE_CHANGE_MIN || cmcBtcDominanceChange24hPct > Q4_CMC_BTC_DOMINANCE_CHANGE_MAX) ? ["cmc_btc_dominance_change_outside_band"] : [],
18336
18387
  ...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"] : [],
18337
- ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && altDispersion24h != null && altDispersion24h >= Q4_ALT_DISPERSION_24H_MAX ? ["alt_dispersion_24h_too_high_for_q4"] : []
18388
+ ...legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && altDispersion24h != null && altDispersion24h >= Q4_ALT_DISPERSION_24H_MAX ? ["alt_dispersion_24h_too_high_for_q4"] : [],
18389
+ ...q4CmcApproval ? ["legacy_q4_structural_observation_only"] : []
18338
18390
  ];
18339
18391
  const highPrecisionApprovalBlocked = legacyHighPrecisionShapeCandidate && !highPrecisionCmcApproval && !q4DerivativesApproval;
18340
- const q4DerivativesApprovalBlocked = q4DerivativesPocket && !q4DerivativesApproval && !highPrecisionCmcApproval && !q4CmcApproval;
18341
- const q4ApprovalBlocked = legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && !q4CmcApproval && !q4DerivativesApproval;
18342
- const approvalSourceAllowed = highPrecisionCmcApproval || q4CmcApproval || q4DerivativesApproval;
18392
+ const q4DerivativesApprovalBlocked = q4DerivativesPocket && !q4DerivativesApproval && !highPrecisionCmcApproval;
18393
+ const q4ApprovalBlocked = legacyShapeCandidate && !legacyHighPrecisionShapeCandidate && !q4DerivativesApproval;
18394
+ const approvalSourceAllowed = highPrecisionCmcApproval || q4DerivativesApproval;
18343
18395
  const approvalBlocked = !approvalSourceAllowed && (highPrecisionApprovalBlocked || q4ApprovalBlocked || q4DerivativesApprovalBlocked);
18344
18396
  const defaultApprovalAllowed = structuralHardBlockReasons.length === 0 && approvalSourceAllowed && !approvalBlocked;
18345
18397
  const strictMomentumRoc1dOk = roc1d == null ? null : roc1d >= STRICT_MOMENTUM_ROC1D_MIN;
@@ -18373,7 +18425,7 @@ var buildDoubleTapAiContext = (payload) => {
18373
18425
  strictMomentumApproved: strictMomentumApprovalAllowedNow,
18374
18426
  strictMomentumRoc1dOk
18375
18427
  });
18376
- const deterministicQuality = structuralHardBlockReasons.length > 0 ? Math.min(geometryQuality, 2) : highPrecisionCmcApproval ? 5 : q4CmcApproval || q4DerivativesApproval ? 4 : Math.min(geometryQuality, 3);
18428
+ const deterministicQuality = structuralHardBlockReasons.length > 0 ? Math.min(geometryQuality, 2) : highPrecisionCmcApproval ? 5 : q4DerivativesApproval ? 4 : Math.min(geometryQuality, 3);
18377
18429
  return {
18378
18430
  ...context,
18379
18431
  baseContextAvailable,
@@ -18523,9 +18575,9 @@ Interpretation rules for DoubleTap:
18523
18575
  - Extremely tiny breaks can still be early noise; live approval needs support from baseContext.
18524
18576
  - Treat deterministicQuality and approvalAllowedNow as the normalized local gate result.
18525
18577
  - 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.
18526
- - 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.
18527
- - 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.
18528
- - 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.
18578
+ - The legacy structural q4 CMC pocket is retained only as observation context and should not be treated as local approval.
18579
+ - 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.
18580
+ - 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.
18529
18581
  - A good long has two comparable lows and a clean close above the neckline.
18530
18582
  - A good short has two comparable highs and a clean close below the neckline.
18531
18583
  - Venue spread, trend bias, body strength, and reward-to-volatility are diagnostics for this gate, not strict local blockers.
@@ -18595,6 +18647,7 @@ var asFiniteNumber2 = (value) => {
18595
18647
  const parsed = Number(value);
18596
18648
  return Number.isFinite(parsed) ? parsed : null;
18597
18649
  };
18650
+ var asNullableFiniteNumber = (value) => value == null ? null : asFiniteNumber2(value);
18598
18651
  var asStringArray2 = (value) => Array.isArray(value) ? value.filter(
18599
18652
  (entry) => typeof entry === "string" && entry.trim().length > 0
18600
18653
  ) : [];
@@ -18603,6 +18656,8 @@ var MIN_Q3_UPGRADE_REACTION_CLOSE_DISTANCE_PCT = 1.5;
18603
18656
  var MIN_Q3_UPGRADE_BODY_STRENGTH = 0.65;
18604
18657
  var MIN_Q3_UPGRADE_VOLUME_REL20 = 1;
18605
18658
  var MAX_APPROVAL_CMC_FEAR_GREED_VALUE = 39;
18659
+ var MAX_APPROVAL_PRICE_DISTANCE_TO_MA_SLOW_ATR = 1.2;
18660
+ var MIN_APPROVAL_ACTIVE_LIQUIDITY_ZONES = 1;
18606
18661
  var MAX_DERIVATIVES_RISK_OFF_ALT_BASKET_RETURN_24H = -0.035;
18607
18662
  var MAX_DERIVATIVES_RISK_OFF_TRX_OI_CHANGE_PCT_4H = -1.8;
18608
18663
  var Q4_APPROVAL_ATR_RANK_BUCKETS = /* @__PURE__ */ new Set(["high", "extreme"]);
@@ -18666,6 +18721,12 @@ var buildLiquidityTailsGuardrailContext = ({
18666
18721
  const roc1h = asFiniteNumber2(baseContext?.regime?.momentum?.roc1h);
18667
18722
  const roc4h = asFiniteNumber2(baseContext?.regime?.momentum?.roc4h);
18668
18723
  const benchmarkTrendAlignment = baseContext?.relative?.benchmark?.trendAlignment ?? null;
18724
+ const priceDistanceToMaSlowAtr = asNullableFiniteNumber(
18725
+ baseContext?.regime?.trend?.priceDistanceToMaSlowAtr
18726
+ );
18727
+ const liquidityZonesActiveCount = asNullableFiniteNumber(
18728
+ baseContext?.structure?.liquidityZones?.activeCount
18729
+ );
18669
18730
  const atrPctRankBucket = typeof baseContext?.gateFeatures?.volatility?.atrPctRankBucket === "string" ? baseContext.gateFeatures.volatility.atrPctRankBucket : null;
18670
18731
  const q4AtrRankEligible = atrPctRankBucket != null && Q4_APPROVAL_ATR_RANK_BUCKETS.has(atrPctRankBucket);
18671
18732
  const liquidityRisk = typeof baseContext?.gateFeatures?.risk?.liquidityRisk === "string" ? baseContext.gateFeatures.risk.liquidityRisk : null;
@@ -18781,6 +18842,21 @@ var buildLiquidityTailsGuardrailContext = ({
18781
18842
  if (deterministicQuality === 3 && hardBlockReasons.length === 0 && derivativesRiskOffLongRecoveryPocket) {
18782
18843
  deterministicQuality = 4;
18783
18844
  }
18845
+ if (deterministicQuality >= 4) {
18846
+ const approvalContextReasons = [];
18847
+ if (priceDistanceToMaSlowAtr == null) {
18848
+ approvalContextReasons.push("price_distance_to_ma_slow_unavailable");
18849
+ } else if (priceDistanceToMaSlowAtr > MAX_APPROVAL_PRICE_DISTANCE_TO_MA_SLOW_ATR) {
18850
+ approvalContextReasons.push("price_overextended_from_ma_slow");
18851
+ }
18852
+ if (liquidityZonesActiveCount == null || liquidityZonesActiveCount < MIN_APPROVAL_ACTIVE_LIQUIDITY_ZONES) {
18853
+ approvalContextReasons.push("liquidity_zone_confirmation_missing");
18854
+ }
18855
+ if (approvalContextReasons.length > 0) {
18856
+ deterministicQuality = 3;
18857
+ softBlockReasons.push(...approvalContextReasons);
18858
+ }
18859
+ }
18784
18860
  return {
18785
18861
  ...signalContext,
18786
18862
  baseContextAvailable: Boolean(baseContext),
@@ -18795,6 +18871,8 @@ var buildLiquidityTailsGuardrailContext = ({
18795
18871
  roc1h,
18796
18872
  roc4h,
18797
18873
  benchmarkTrendAlignment,
18874
+ priceDistanceToMaSlowAtr,
18875
+ liquidityZonesActiveCount,
18798
18876
  atrPctRankBucket,
18799
18877
  q4AtrRankEligible,
18800
18878
  liquidityRisk,
@@ -18903,6 +18981,8 @@ Additional Liquidity Tails context:
18903
18981
  - roc1h=${String(context.roc1h ?? "n/a")}
18904
18982
  - roc4h=${String(context.roc4h ?? "n/a")}
18905
18983
  - benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
18984
+ - priceDistanceToMaSlowAtr=${String(context.priceDistanceToMaSlowAtr ?? "n/a")}
18985
+ - liquidityZonesActiveCount=${String(context.liquidityZonesActiveCount ?? "n/a")}
18906
18986
  - atrPctRankBucket=${context.atrPctRankBucket ?? "n/a"}
18907
18987
  - q4AtrRankEligible=${String(context.q4AtrRankEligible)}
18908
18988
  - liquidityRisk=${context.liquidityRisk ?? "n/a"}
@@ -19030,8 +19110,15 @@ var buildLiquidityZonesGuardrailContext = ({
19030
19110
  const lowTouchCount20 = asPresentFiniteNumber(
19031
19111
  baseContext?.structure?.levels?.lowTouchCount20
19032
19112
  );
19113
+ const ethReferenceDerivatives15m = baseContext?.derivatives?.referenceContexts?.ETHUSDT?.intervals?.["15m"];
19033
19114
  const ethReferenceOiChangePct4h = asPresentFiniteNumber(
19034
- baseContext?.derivatives?.referenceContexts?.ETHUSDT?.intervals?.["15m"]?.oiChangePct4h
19115
+ ethReferenceDerivatives15m?.oiChangePct4h
19116
+ );
19117
+ const ethReferenceOiChangePct24h = asPresentFiniteNumber(
19118
+ ethReferenceDerivatives15m?.oiChangePct24h
19119
+ );
19120
+ const ethReferenceFundingZScore = asPresentFiniteNumber(
19121
+ ethReferenceDerivatives15m?.fundingZScore
19035
19122
  );
19036
19123
  const solReferenceOiChangePct24h = asPresentFiniteNumber(
19037
19124
  baseContext?.derivatives?.referenceContexts?.SOLUSDT?.intervals?.["15m"]?.oiChangePct24h
@@ -19131,8 +19218,9 @@ var buildLiquidityZonesGuardrailContext = ({
19131
19218
  const hasBaseRetestConfirmation = filterMetric >= 3 && hitCount >= 2 && reactionCloseDistancePct >= 0.08 && retestPenetrationPct <= 90;
19132
19219
  const ethReferenceOiWeakPocket = ethReferenceOiChangePct4h != null && ethReferenceOiChangePct4h <= -0.8;
19133
19220
  const transitionStructureExpansionPocket = hasBaseRetestConfirmation && structureZoneState === "transition" && structureScore != null && structureScore >= 17 && adaptiveChannelFlipDown === false && !directionalCrowding && !ethReferenceOiWeakPocket;
19221
+ const ethReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && ethReferenceOiChangePct24h != null && ethReferenceOiChangePct24h <= -5.8 && ethReferenceFundingZScore != null && ethReferenceFundingZScore <= -1.05;
19134
19222
  const solReferenceStressPocket = hasBaseRetestConfirmation && lowTouchCount20 != null && lowTouchCount20 <= 3 && solReferenceOiChangePct24h != null && solReferenceOiChangePct24h <= -4.2 && solReferenceFundingZScore != null && solReferenceFundingZScore <= -1.2;
19135
- const calibratedExpansionPocket = transitionStructureExpansionPocket || solReferenceStressPocket;
19223
+ const calibratedExpansionPocket = transitionStructureExpansionPocket || ethReferenceStressPocket || solReferenceStressPocket;
19136
19224
  const longRequiresCalibratedExpansion = direction === "LONG" && !calibratedExpansionPocket;
19137
19225
  const approvalDisqualifiedByCalibration = !calibratedExpansionPocket && (longRequiresCalibratedExpansion || isContinuationBreakoutRetest || hasOverextendedVolumeConfirmation || hasIsolatedIndicatorSupport);
19138
19226
  if (longRequiresCalibratedExpansion) {
@@ -19206,9 +19294,12 @@ var buildLiquidityZonesGuardrailContext = ({
19206
19294
  adaptiveChannelFlipDown,
19207
19295
  lowTouchCount20,
19208
19296
  ethReferenceOiChangePct4h,
19297
+ ethReferenceOiChangePct24h,
19298
+ ethReferenceFundingZScore,
19209
19299
  solReferenceOiChangePct24h,
19210
19300
  solReferenceFundingZScore,
19211
19301
  transitionStructureExpansionPocket,
19302
+ ethReferenceStressPocket,
19212
19303
  solReferenceStressPocket,
19213
19304
  hardBlockReasons,
19214
19305
  softBlockReasons,
@@ -19314,9 +19405,12 @@ Additional Liquidity Zones context:
19314
19405
  - adaptiveChannelFlipDown=${String(context.adaptiveChannelFlipDown ?? "n/a")}
19315
19406
  - lowTouchCount20=${String(context.lowTouchCount20 ?? "n/a")}
19316
19407
  - ethReferenceOiChangePct4h=${String(context.ethReferenceOiChangePct4h ?? "n/a")}
19408
+ - ethReferenceOiChangePct24h=${String(context.ethReferenceOiChangePct24h ?? "n/a")}
19409
+ - ethReferenceFundingZScore=${String(context.ethReferenceFundingZScore ?? "n/a")}
19317
19410
  - solReferenceOiChangePct24h=${String(context.solReferenceOiChangePct24h ?? "n/a")}
19318
19411
  - solReferenceFundingZScore=${String(context.solReferenceFundingZScore ?? "n/a")}
19319
19412
  - transitionStructureExpansionPocket=${String(context.transitionStructureExpansionPocket)}
19413
+ - ethReferenceStressPocket=${String(context.ethReferenceStressPocket)}
19320
19414
  - solReferenceStressPocket=${String(context.solReferenceStressPocket)}
19321
19415
  - deterministicQuality=${context.deterministicQuality}
19322
19416
  - approvalAllowedNow=${String(context.approvalAllowedNow)}
@@ -19332,7 +19426,7 @@ Interpretation rules for Liquidity Zones:
19332
19426
  - A close fully through the level marks the zone crossed; crossed zones are not live-entry candidates.
19333
19427
  - Top-level derivatives context is BTC benchmark evidence; target-symbol derivatives require targetContext/targetDerived.
19334
19428
  - Do not treat derivatives points, rows, or loaded-history size as approval evidence.
19335
- - A calibrated transition-structure pocket or SOL reference stress pocket can approve a structurally valid retest.
19429
+ - A calibrated transition-structure pocket, ETH reference stress pocket, or SOL reference stress pocket can approve a structurally valid retest.
19336
19430
  - Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
19337
19431
  `.trim();
19338
19432
  },
@@ -20473,6 +20567,7 @@ var TREND_FOLLOW_OPENING_SESSION_MAX_MINUTES_FROM_OPEN = 75;
20473
20567
  var TREND_FOLLOW_OPENING_REF_XRP_OI_MAX = 324e6;
20474
20568
  var TREND_FOLLOW_OPENING_REF_XRP_OI_CHANGE_1H_MIN = 0.4;
20475
20569
  var TREND_FOLLOW_OPENING_REF_BNB_OI_MIN = 56e4;
20570
+ var TREND_FOLLOW_ALLOWED_VOLATILITY_STATE = "normal";
20476
20571
  var asFiniteNumber5 = (value) => {
20477
20572
  const parsed = Number(value);
20478
20573
  return Number.isFinite(parsed) ? parsed : null;
@@ -20584,6 +20679,7 @@ var buildTrendFollowGateFeatures = ({
20584
20679
  );
20585
20680
  const marketBreadthAligned = marketBreadthReturn == null || marketBreadth?.stale ? null : direction === "LONG" ? marketBreadthReturn >= 0 : direction === "SHORT" ? marketBreadthReturn <= 0 : null;
20586
20681
  const marketBreadthContinuation = marketBreadth?.stale === true ? "stale" : marketBreadthAligned === true ? "aligned" : marketBreadthAligned === false ? "against" : "unknown";
20682
+ const marketVolatilityState = typeof baseContext?.regime?.volatility?.state === "string" ? baseContext.regime.volatility.state : null;
20587
20683
  const targetVsBtcBeta20 = asFiniteNumber5(
20588
20684
  baseContext?.relative?.targetVsBtc?.betaToBtc20
20589
20685
  );
@@ -20635,6 +20731,7 @@ var buildTrendFollowGateFeatures = ({
20635
20731
  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;
20636
20732
  const referenceDerivativesCadencePocket = !referenceDerivativesLossBlock && (legacyCadencePocket || referenceDerivativesOiCompressionPocket || referenceDerivativesXrpFundingPocket || referenceDerivativesSolFlushPocket);
20637
20733
  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;
20734
+ const normalVolatilityCadencePocket = marketVolatilityState === TREND_FOLLOW_ALLOWED_VOLATILITY_STATE;
20638
20735
  return {
20639
20736
  setupStopDistanceAtr,
20640
20737
  setupTpDistanceAtr,
@@ -20649,6 +20746,7 @@ var buildTrendFollowGateFeatures = ({
20649
20746
  relativeContinuation,
20650
20747
  marketBreadthContinuation,
20651
20748
  marketBreadthDispersion: asFiniteNumber5(marketBreadth?.dispersion),
20749
+ marketVolatilityState,
20652
20750
  targetVsBtcBeta20,
20653
20751
  btcAltRegimeBtcTurnoverShare24h,
20654
20752
  btcAltRegimeAltBasketReturn24h,
@@ -20676,7 +20774,8 @@ var buildTrendFollowGateFeatures = ({
20676
20774
  referenceDerivativesLossBlock,
20677
20775
  referenceDerivativesCadencePocket,
20678
20776
  referenceDerivativesOpeningPocket,
20679
- highQualityCadencePocket: referenceDerivativesCadencePocket || referenceDerivativesOpeningPocket
20777
+ normalVolatilityCadencePocket,
20778
+ highQualityCadencePocket: normalVolatilityCadencePocket && (referenceDerivativesCadencePocket || referenceDerivativesOpeningPocket)
20680
20779
  };
20681
20780
  };
20682
20781
  var buildTrendFollowGuardrailContext = ({
@@ -20909,6 +21008,7 @@ Additional TrendFollow context:
20909
21008
  - trendFollowGateRelativeContinuation=${context.trendFollowGateFeatures.relativeContinuation}
20910
21009
  - trendFollowGateMarketBreadthContinuation=${context.trendFollowGateFeatures.marketBreadthContinuation}
20911
21010
  - trendFollowGateMarketBreadthDispersion=${String(context.trendFollowGateFeatures.marketBreadthDispersion ?? "n/a")}
21011
+ - trendFollowGateMarketVolatilityState=${String(context.trendFollowGateFeatures.marketVolatilityState ?? "n/a")}
20912
21012
  - trendFollowGateTargetVsBtcBeta20=${String(context.trendFollowGateFeatures.targetVsBtcBeta20 ?? "n/a")}
20913
21013
  - trendFollowGateBtcAltRegimeBtcTurnoverShare24h=${String(context.trendFollowGateFeatures.btcAltRegimeBtcTurnoverShare24h ?? "n/a")}
20914
21014
  - trendFollowGateBtcAltRegimeAltBasketReturn24h=${String(context.trendFollowGateFeatures.btcAltRegimeAltBasketReturn24h ?? "n/a")}
@@ -20936,6 +21036,7 @@ Additional TrendFollow context:
20936
21036
  - trendFollowGateReferenceDerivativesLossBlock=${String(context.trendFollowGateFeatures.referenceDerivativesLossBlock)}
20937
21037
  - trendFollowGateReferenceDerivativesCadencePocket=${String(context.trendFollowGateFeatures.referenceDerivativesCadencePocket)}
20938
21038
  - trendFollowGateReferenceDerivativesOpeningPocket=${String(context.trendFollowGateFeatures.referenceDerivativesOpeningPocket)}
21039
+ - trendFollowGateNormalVolatilityCadencePocket=${String(context.trendFollowGateFeatures.normalVolatilityCadencePocket)}
20939
21040
  - trendFollowGateHighQualityCadencePocket=${String(context.trendFollowGateFeatures.highQualityCadencePocket)}
20940
21041
  - benchmarkTrendAlignment=${context.benchmarkTrendAlignment ?? "n/a"}
20941
21042
  - derivativesPressure=${context.derivativesPressure ?? "n/a"}
@@ -20953,7 +21054,7 @@ Interpretation rules for TrendFollow:
20953
21054
  - The ATR trailing stop is the structural invalidation line and also updates while a position is open.
20954
21055
  - Prefer breakouts aligned with shared market context and backed by participation.
20955
21056
  - Late, thin, crowded, inside-range, adverse-delta, weak-momentum, or weak-volume-structure breakouts should be downgraded even if the pivot cross is valid.
20956
- - 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.
21057
+ - 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.
20957
21058
  - Treat deterministicQuality and approvalAllowedNow as the local normalized gate result.
20958
21059
  `.trim();
20959
21060
  },
@@ -20985,6 +21086,11 @@ var SHORT_BREADTH_SHOCK_1H_LIQ_SHORT_MAX = 0.208;
20985
21086
  var LONG_ALT_LEADERSHIP_BTC_VS_ALT_RETURN_24H_MAX = -503054e-8;
20986
21087
  var LONG_ALT_LEADERSHIP_BTC_VS_ALT_RETURN_1H_MAX = -581403e-8;
20987
21088
  var LONG_ALT_LEADERSHIP_FEAR_GREED_CHANGE_24H_MIN = -1;
21089
+ var LONG_BROAD_MARKET_SHORT_FLUSH_ADVANCERS_MIN = 27;
21090
+ var LONG_BROAD_MARKET_SHORT_FLUSH_PCT_ABOVE_MA20_MIN = 0.95;
21091
+ var LONG_BROAD_MARKET_SHORT_FLUSH_BTC_VS_ALT_RETURN_24H_MIN = 0;
21092
+ var SHORT_ASIA_LONG_FLUSH_LOW_CMC_FEAR_GREED_MAX = 18;
21093
+ var SHORT_ASIA_LONG_FLUSH_ADVANCERS_MAX = 2;
20988
21094
  var toMtfAlignmentForTrendShift = ({
20989
21095
  direction,
20990
21096
  mtfAlignment
@@ -21233,12 +21339,21 @@ var buildTrendShiftGuardrailContext = ({
21233
21339
  );
21234
21340
  const gateVolatility = baseContext?.gateFeatures?.volatility;
21235
21341
  const gateRelative = baseContext?.gateFeatures?.relative;
21342
+ const baseMarketBreadth = baseContext?.relative?.marketBreadth;
21236
21343
  const baseBtcAltRegime = baseContext?.relative?.btcAltRegime;
21237
21344
  const baseCmcFearGreed = baseContext?.relative?.cmcFearGreed;
21238
21345
  const bbWidthPct = asFiniteNumber6(volatility?.bbWidthPct);
21239
21346
  const marketBreadthReturn = asFiniteNumber6(gateRelative?.marketBreadthReturn);
21347
+ const marketBreadthAdvancers = asFiniteNumber6(baseMarketBreadth?.advancers);
21348
+ const marketBreadthPctAboveMa20 = asFiniteNumber6(
21349
+ baseMarketBreadth?.pctAboveMa20
21350
+ );
21351
+ const marketBreadthStale = gateRelative?.marketBreadthStale === true || baseMarketBreadth?.stale === true;
21240
21352
  const btcVsAltReturn24h = asFiniteNumber6(gateRelative?.btcVsAltReturn24h);
21241
21353
  const btcVsAltReturn1h = asFiniteNumber6(baseBtcAltRegime?.btcVsAltReturn1h);
21354
+ const cmcFearGreedValue = asFiniteNumber6(
21355
+ gateRelative?.cmcFearGreedValue ?? baseCmcFearGreed?.value
21356
+ );
21242
21357
  const cmcFearGreedValueChange24h = asFiniteNumber6(
21243
21358
  gateRelative?.cmcFearGreedValueChange24h ?? baseCmcFearGreed?.valueChange24h
21244
21359
  );
@@ -21358,9 +21473,11 @@ var buildTrendShiftGuardrailContext = ({
21358
21473
  const shortExtremeAtrHighBbRisk = signalContext.signalDirection === "SHORT" && gateVolatility?.state === "normal" && gateVolatility.atrPctRankBucket === "extreme" && gateVolatility.bbWidthRankBucket === "high";
21359
21474
  const shortBullSwingStructureRisk = signalContext.signalDirection === "SHORT" && swingBias === "bull";
21360
21475
  const shortLowBollingerWidthRisk = signalContext.signalDirection === "SHORT" && bbWidthPct != null && bbWidthPct <= SHORT_LOW_BB_WIDTH_PCT_MAX;
21476
+ 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;
21361
21477
  const lowRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility < 0.25;
21362
21478
  const defensiveRewardToVolatilityRisk = rewardToVolatility != null && rewardToVolatility >= 0.25 && rewardToVolatility < 8;
21363
21479
  const longBtcAltRegimeRisk = signalContext.signalDirection === "LONG" && btcAltRegimeStale !== true && (btcAltRegime === "btc_lead" || btcAltRegime === "risk_off");
21480
+ 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;
21364
21481
  const cmcExchangeLiquidityVolumeChangeRisk = cmcExchangeLiquidityStale !== true && cmcExchangeLiquidityVolumeChange24hPct != null && (cmcExchangeLiquidityVolumeChange24hPct > -0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0 || cmcExchangeLiquidityVolumeChange24hPct >= 0.1 && cmcExchangeLiquidityVolumeChange24hPct < 0.3);
21365
21482
  if (deterministicQuality >= 5 && longRelativeStrengthOverextended) {
21366
21483
  deterministicQuality = 4;
@@ -21398,6 +21515,10 @@ var buildTrendShiftGuardrailContext = ({
21398
21515
  deterministicQuality = 4;
21399
21516
  hardBlockReasons.push("short_bull_swing_structure");
21400
21517
  }
21518
+ if (deterministicQuality >= 5 && shortAsiaLongFlushLowCmcBreadthRisk) {
21519
+ deterministicQuality = 4;
21520
+ hardBlockReasons.push("short_asia_long_flush_low_cmc_breadth");
21521
+ }
21401
21522
  if (deterministicQuality >= 4 && lowRewardToVolatilityRisk) {
21402
21523
  deterministicQuality = 4;
21403
21524
  hardBlockReasons.push("low_reward_to_volatility");
@@ -21410,6 +21531,10 @@ var buildTrendShiftGuardrailContext = ({
21410
21531
  deterministicQuality = 4;
21411
21532
  hardBlockReasons.push("long_btc_alt_regime_risk");
21412
21533
  }
21534
+ if (deterministicQuality >= 5 && longBroadMarketShortFlushRisk) {
21535
+ deterministicQuality = 4;
21536
+ hardBlockReasons.push("long_broad_market_short_flush_risk");
21537
+ }
21413
21538
  if (deterministicQuality >= 4 && cmcExchangeLiquidityVolumeChangeRisk) {
21414
21539
  deterministicQuality = 4;
21415
21540
  hardBlockReasons.push("cmc_exchange_liquidity_volume_change_risk");
@@ -21475,9 +21600,11 @@ var buildTrendShiftGuardrailContext = ({
21475
21600
  shortExtremeAtrHighBbRisk,
21476
21601
  shortBullSwingStructureRisk,
21477
21602
  shortLowBollingerWidthRisk,
21603
+ shortAsiaLongFlushLowCmcBreadthRisk,
21478
21604
  lowRewardToVolatilityRisk,
21479
21605
  defensiveRewardToVolatilityRisk,
21480
21606
  longBtcAltRegimeRisk,
21607
+ longBroadMarketShortFlushRisk,
21481
21608
  cmcExchangeLiquidityVolumeChangeRisk,
21482
21609
  q4TrendShiftGateFeaturesRecoveryCandidate,
21483
21610
  q4UsClosingOiConfirmationRecoveryCandidate,
@@ -21493,8 +21620,11 @@ var buildTrendShiftGuardrailContext = ({
21493
21620
  nearPointOfControl,
21494
21621
  relativeStrength1h,
21495
21622
  marketBreadthReturn,
21623
+ marketBreadthAdvancers,
21624
+ marketBreadthPctAboveMa20,
21496
21625
  btcVsAltReturn24h,
21497
21626
  btcVsAltReturn1h,
21627
+ cmcFearGreedValue,
21498
21628
  cmcFearGreedValueChange24h,
21499
21629
  derivatives1hLiqShort,
21500
21630
  btcAltRegime,
@@ -21562,12 +21692,16 @@ var getTrendShiftGuardrailReasonText = (reason) => {
21562
21692
  return "the SHORT flip is still fighting a bullish swing structure, so keep it in watch mode";
21563
21693
  case "short_low_bollinger_width":
21564
21694
  return "the SHORT flip is in a narrow Bollinger-width compression pocket that has been less reliable, so keep it in watch mode";
21695
+ case "short_asia_long_flush_low_cmc_breadth":
21696
+ 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";
21565
21697
  case "low_reward_to_volatility":
21566
21698
  return "the expected reward is too small relative to current volatility after costs, so keep the flip in watch mode";
21567
21699
  case "reward_to_volatility_below_defensive_threshold":
21568
21700
  return "the expected reward is not large enough relative to current volatility for the defensive TrendShift gate after costs";
21569
21701
  case "long_btc_alt_regime_risk":
21570
21702
  return "the LONG flip is fighting a BTC-led or risk-off alt regime, so keep it in watch mode";
21703
+ case "long_broad_market_short_flush_risk":
21704
+ 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";
21571
21705
  case "cmc_exchange_liquidity_volume_change_risk":
21572
21706
  return "major-exchange liquidity change is in a historically choppy CMC band, so keep the flip in watch mode";
21573
21707
  default:
@@ -21682,8 +21816,11 @@ Additional TrendShift context:
21682
21816
  - nearPointOfControl=${String(context.nearPointOfControl ?? "n/a")}
21683
21817
  - relativeStrength1h=${String(context.relativeStrength1h ?? "n/a")}
21684
21818
  - marketBreadthReturn=${String(context.marketBreadthReturn ?? "n/a")}
21819
+ - marketBreadthAdvancers=${String(context.marketBreadthAdvancers ?? "n/a")}
21820
+ - marketBreadthPctAboveMa20=${String(context.marketBreadthPctAboveMa20 ?? "n/a")}
21685
21821
  - btcVsAltReturn24h=${String(context.btcVsAltReturn24h ?? "n/a")}
21686
21822
  - btcVsAltReturn1h=${String(context.btcVsAltReturn1h ?? "n/a")}
21823
+ - cmcFearGreedValue=${String(context.cmcFearGreedValue ?? "n/a")}
21687
21824
  - cmcFearGreedValueChange24h=${String(context.cmcFearGreedValueChange24h ?? "n/a")}
21688
21825
  - derivatives1hLiqShort=${String(context.derivatives1hLiqShort ?? "n/a")}
21689
21826
  - btcAltRegime=${context.btcAltRegime ?? "n/a"}
@@ -21712,7 +21849,9 @@ Additional TrendShift context:
21712
21849
  - shortLowBollingerWidthRisk=${String(context.shortLowBollingerWidthRisk)}
21713
21850
  - defensiveRewardToVolatilityRisk=${String(context.defensiveRewardToVolatilityRisk)}
21714
21851
  - shortBullSwingStructureRisk=${String(context.shortBullSwingStructureRisk)}
21852
+ - shortAsiaLongFlushLowCmcBreadthRisk=${String(context.shortAsiaLongFlushLowCmcBreadthRisk)}
21715
21853
  - longBtcAltRegimeRisk=${String(context.longBtcAltRegimeRisk)}
21854
+ - longBroadMarketShortFlushRisk=${String(context.longBroadMarketShortFlushRisk)}
21716
21855
  - cmcExchangeLiquidityVolumeChangeRisk=${String(context.cmcExchangeLiquidityVolumeChangeRisk)}
21717
21856
  - q4TrendShiftGateFeaturesRecoveryCandidate=${String(context.q4TrendShiftGateFeaturesRecoveryCandidate)}
21718
21857
  - q4UsClosingOiConfirmationRecoveryCandidate=${String(context.q4UsClosingOiConfirmationRecoveryCandidate)}
@@ -21749,8 +21888,10 @@ Interpretation rules for TrendShift:
21749
21888
  - 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.
21750
21889
  - For SHORT, a bullish swing structure is a watch-only warning even when the immediate flip geometry looks q5-strong.
21751
21890
  - For SHORT, a narrow Bollinger-width compression pocket is watch-only even if another q4 recovery condition is present.
21891
+ - For SHORT, Asia-session long-flush setups are watch-only when CMC fear/greed and market breadth are already in capitulation.
21752
21892
  - The defensive live gate requires rewardToVolatility >= 8 when that field is available.
21753
21893
  - For LONG, BTC-led or risk-off BTC/alt regime is watch-only even when flip geometry is q5-strong.
21894
+ - 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.
21754
21895
  - 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.
21755
21896
  - 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.
21756
21897
  - 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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tradejs/strategies",
3
- "version": "1.0.12",
4
- "description": "Built-in strategy plugin catalog for the TradeJS open-source framework.",
3
+ "version": "2.0.1",
4
+ "description": "Built-in strategy plugin catalog for the TradeJS TypeScript framework.",
5
5
  "keywords": [
6
6
  "tradejs",
7
7
  "trading",
@@ -32,10 +32,10 @@
32
32
  }
33
33
  },
34
34
  "dependencies": {
35
- "@tradejs/core": "^1.0.12",
36
- "@tradejs/indicators": "^1.0.12",
37
- "@tradejs/node": "^1.0.12",
38
- "@tradejs/types": "^1.0.12",
35
+ "@tradejs/core": "^2.0.1",
36
+ "@tradejs/indicators": "^2.0.1",
37
+ "@tradejs/node": "^2.0.1",
38
+ "@tradejs/types": "^2.0.1",
39
39
  "technicalindicators": "^3.1.0"
40
40
  },
41
41
  "devDependencies": {
@@ -46,6 +46,6 @@
46
46
  "build": "tsup",
47
47
  "typecheck": "tsc -p ./tsconfig.json --noEmit"
48
48
  },
49
- "license": "MIT",
49
+ "license": "BUSL-1.1",
50
50
  "author": "aleksnick (https://github.com/aleksnick)"
51
51
  }