07.4.4.1.10.3 — Telegram Diagnostic Screen
This commit is contained in:
@@ -110,6 +110,9 @@ class TrendStrategy:
|
||||
if len(prices) > self._window_size:
|
||||
prices.pop(0)
|
||||
|
||||
market_phase = self._normalized_market_phase(market)
|
||||
market_phase_direction = self._normalized_market_phase_direction(market)
|
||||
|
||||
base_payload = {
|
||||
"strategy": self.name,
|
||||
"symbol": symbol,
|
||||
@@ -125,8 +128,8 @@ class TrendStrategy:
|
||||
"market_analysis": market.payload,
|
||||
"market_trend_strength": market.trend_strength.value,
|
||||
"market_trend_quality": market.trend_quality.value,
|
||||
"market_phase": market.market_phase.value,
|
||||
"market_phase_direction": market.phase_direction.value,
|
||||
"market_phase": market_phase,
|
||||
"market_phase_direction": market_phase_direction,
|
||||
"market_phase_change_percent": market.phase_change_percent,
|
||||
"market_phase_direction_consistency": market.payload.get("market_phase_direction_consistency"),
|
||||
"market_phase_reason": market.phase_reason,
|
||||
@@ -305,7 +308,10 @@ class TrendStrategy:
|
||||
momentum_direction = getattr(market, "momentum_direction", TrendDirection.UNKNOWN)
|
||||
momentum_strength = float(getattr(market, "momentum_strength", 0.0) or 0.0)
|
||||
|
||||
if momentum_state == MomentumState.BREAKOUT_UP:
|
||||
if (
|
||||
momentum_state == MomentumState.BREAKOUT_UP
|
||||
and market.state == MarketState.TREND_UP
|
||||
):
|
||||
return SignalResult(
|
||||
signal=SignalType.BUY,
|
||||
reason="BREAKOUT_UP подтверждён momentum/breakout semantic layer.",
|
||||
@@ -319,7 +325,10 @@ class TrendStrategy:
|
||||
},
|
||||
)
|
||||
|
||||
if momentum_state == MomentumState.BREAKOUT_DOWN:
|
||||
if (
|
||||
momentum_state == MomentumState.BREAKOUT_DOWN
|
||||
and market.state == MarketState.TREND_DOWN
|
||||
):
|
||||
return SignalResult(
|
||||
signal=SignalType.SELL,
|
||||
reason="BREAKOUT_DOWN подтверждён momentum/breakout semantic layer.",
|
||||
@@ -333,6 +342,37 @@ class TrendStrategy:
|
||||
},
|
||||
)
|
||||
|
||||
if (
|
||||
momentum_state == MomentumState.BREAKOUT_DOWN
|
||||
and market.state == MarketState.TREND_UP
|
||||
):
|
||||
return SignalResult(
|
||||
signal=SignalType.HOLD,
|
||||
reason="Пробой вниз против TREND_UP считается коррекцией, вход в SHORT запрещён.",
|
||||
confidence=0.0,
|
||||
payload={
|
||||
**base_payload,
|
||||
"entry_block_reason": "COUNTER_TREND_BREAKOUT",
|
||||
"entry_block_message": "пробой против тренда",
|
||||
"expected_direction": "BUY",
|
||||
},
|
||||
)
|
||||
|
||||
if (
|
||||
momentum_state == MomentumState.BREAKOUT_UP
|
||||
and market.state == MarketState.TREND_DOWN
|
||||
):
|
||||
return SignalResult(
|
||||
signal=SignalType.HOLD,
|
||||
reason="Пробой вверх против TREND_DOWN считается откатом, вход в LONG запрещён.",
|
||||
confidence=0.0,
|
||||
payload={
|
||||
**base_payload,
|
||||
"entry_block_reason": "COUNTER_TREND_BREAKOUT",
|
||||
"entry_block_message": "пробой против тренда",
|
||||
"expected_direction": "SELL",
|
||||
},
|
||||
)
|
||||
return None
|
||||
|
||||
def _calculate_breakout_confidence(self, momentum_strength: float) -> float:
|
||||
@@ -384,6 +424,31 @@ class TrendStrategy:
|
||||
|
||||
return down_moves / total_moves
|
||||
|
||||
def _normalized_market_phase(self, market) -> str:
|
||||
phase = market.market_phase.value
|
||||
momentum_state = market.momentum_state.value
|
||||
|
||||
active_momentum_states = {
|
||||
"MOMENTUM_UP",
|
||||
"MOMENTUM_DOWN",
|
||||
"BREAKOUT_UP",
|
||||
"BREAKOUT_DOWN",
|
||||
}
|
||||
|
||||
if phase == "IMPULSE" and momentum_state not in active_momentum_states:
|
||||
return "UNKNOWN"
|
||||
|
||||
return phase
|
||||
|
||||
|
||||
def _normalized_market_phase_direction(self, market) -> str:
|
||||
phase = self._normalized_market_phase(market)
|
||||
|
||||
if phase == "UNKNOWN":
|
||||
return "UNKNOWN"
|
||||
|
||||
return market.phase_direction.value
|
||||
|
||||
def _calculate_confidence(
|
||||
self,
|
||||
change_percent: float,
|
||||
|
||||
Reference in New Issue
Block a user