07.4.4.1.9.6.2 Momentum & Breakout Semantic Engine

This commit is contained in:
2026-05-12 23:25:16 +03:00
parent 8b83055e6a
commit 4a34338041
10 changed files with 591 additions and 1 deletions

View File

@@ -182,6 +182,40 @@ def _execution_confidence_line(state) -> str:
return f"🧠 Уверенность входа · {percent}% низкая"
def _momentum_semantic_line(state) -> str:
momentum_state = getattr(state, "momentum_state", None)
momentum_direction = getattr(state, "momentum_direction", None)
momentum_strength = getattr(state, "momentum_strength", None)
if momentum_state in {None, "NONE", "UNKNOWN"}:
return ""
strength_text = ""
if momentum_strength is not None:
strength_text = f" · x{float(momentum_strength):.1f}"
if momentum_state == "BREAKOUT_UP":
return f"🚀 Импульс · пробой вверх{strength_text}"
if momentum_state == "BREAKOUT_DOWN":
return f"💥 Импульс · пробой вниз{strength_text}"
if momentum_state == "MOMENTUM_UP":
return f"⚡️ Импульс · вверх{strength_text}"
if momentum_state == "MOMENTUM_DOWN":
return f"⚡️ Импульс · вниз{strength_text}"
if momentum_direction == "UP":
return f"⚡️ Импульс · вверх{strength_text}"
if momentum_direction == "DOWN":
return f"⚡️ Импульс · вниз{strength_text}"
return ""
def _adaptive_size_line(state) -> str:
multiplier = getattr(state, "adaptive_size_multiplier", None)
@@ -224,6 +258,7 @@ def _build_waiting_text(state) -> str:
_signal_confirmation_line(state),
_execution_confidence_line(state),
_market_semantic_line(state),
_momentum_semantic_line(state),
_entry_block_line(state),
_execution_semantic_line(state),
*_signal_confidence_lines(state),
@@ -284,6 +319,7 @@ def _build_active_position_text(state) -> str:
market_lines = [
_market_semantic_line(state),
_momentum_semantic_line(state),
_execution_semantic_line(state),
]
market_lines = [line for line in market_lines if line]

View File

@@ -408,6 +408,13 @@ class AutoTradeService:
state.market_phase_direction = None
state.entry_block_reason = None
state.entry_block_message = None
state.momentum_state = None
state.momentum_direction = None
state.momentum_change_percent = None
state.momentum_strength = None
state.breakout_level = None
state.breakout_distance_percent = None
state.breakout_reason = None
state.runtime_expired_reason = None
state.runtime_expired_message = None
state.snapshot_age_seconds = None
@@ -848,6 +855,13 @@ class AutoTradeService:
state.market_phase_direction = payload.get("market_phase_direction")
state.market_analysis_interval = payload.get("market_analysis_interval")
state.market_analysis_reason = payload.get("market_analysis_reason")
state.momentum_state = payload.get("momentum_state")
state.momentum_direction = payload.get("momentum_direction")
state.momentum_change_percent = payload.get("momentum_change_percent")
state.momentum_strength = payload.get("momentum_strength")
state.breakout_level = payload.get("breakout_level")
state.breakout_distance_percent = payload.get("breakout_distance_percent")
state.breakout_reason = payload.get("breakout_reason")
state.market_analysis_updated_at = time.monotonic()
state.entry_block_reason = payload.get("entry_block_reason")
state.entry_block_message = payload.get("entry_block_message")
@@ -1060,6 +1074,18 @@ class AutoTradeService:
state.market_analysis_updated_at = None
state.entry_block_reason = None
state.entry_block_message = None
state.market_trend_strength = None
state.market_trend_quality = None
state.market_phase = None
state.market_phase_direction = None
state.momentum_state = None
state.momentum_direction = None
state.momentum_change_percent = None
state.momentum_strength = None
state.breakout_level = None
state.breakout_distance_percent = None
state.breakout_reason = None
state.runtime_expired_reason = "MARKET_ANALYSIS_TTL_EXPIRED"
state.runtime_expired_message = "анализ рынка устарел"
@@ -1350,6 +1376,13 @@ class AutoTradeService:
"execution_quality": state.execution_quality,
"execution_quality_reason": state.execution_quality_reason,
"spread_percent": state.spread_percent,
"momentum_state": getattr(state, "momentum_state", None),
"momentum_direction": getattr(state, "momentum_direction", None),
"momentum_change_percent": getattr(state, "momentum_change_percent", None),
"momentum_strength": getattr(state, "momentum_strength", None),
"breakout_level": getattr(state, "breakout_level", None),
"breakout_distance_percent": getattr(state, "breakout_distance_percent", None),
"breakout_reason": getattr(state, "breakout_reason", None),
}
def _market_confidence_score(self, state: AutoTradeState) -> float:

View File

@@ -127,6 +127,28 @@ class AutoTradeState:
# направление короткой фазы рынка: UP / DOWN / FLAT / UNKNOWN
market_phase_direction: str | None = None
# состояние momentum/breakout semantic engine
# NONE / MOMENTUM_UP / MOMENTUM_DOWN / BREAKOUT_UP / BREAKOUT_DOWN / UNKNOWN
momentum_state: str | None = None
# направление momentum
momentum_direction: str | None = None
# изменение цены в momentum window
momentum_change_percent: float | None = None
# сила momentum относительно threshold
momentum_strength: float | None = None
# breakout уровень
breakout_level: float | None = None
# расстояние от breakout уровня в %
breakout_distance_percent: float | None = None
# причина breakout/momentum классификации
breakout_reason: str | None = None
# таймфрейм анализа рынка
market_analysis_interval: str | None = None

View File

@@ -501,6 +501,9 @@ class ExecutionEngine:
repeat_count = int(state.last_signal_repeat_count or 0)
unrealized_pnl = float(state.unrealized_pnl_usd or 0.0)
hold_seconds = self._position_hold_seconds(position)
momentum_direction = getattr(state, "momentum_direction", None)
momentum_state = getattr(state, "momentum_state", None)
signal = (state.last_signal or "").upper()
if confidence < self._min_flip_confidence:
return (
@@ -519,6 +522,19 @@ class ExecutionEngine:
"позиция открыта слишком недавно "
f"({hold_seconds}с < {self._min_flip_hold_seconds}с)"
)
if signal == "BUY" and momentum_direction == "DOWN":
return "momentum направлен против BUY сигнала"
if signal == "SELL" and momentum_direction == "UP":
return "momentum направлен против SELL сигнала"
if momentum_state in {"BREAKOUT_UP", "BREAKOUT_DOWN"}:
if confidence < 0.85:
return (
"flip заблокирован во время breakout impulse "
f"({confidence:.2f} < 0.85)"
)
if unrealized_pnl < 0 and confidence < self._loss_flip_confidence:
return (
@@ -711,6 +727,38 @@ class ExecutionEngine:
elif market_phase in {"RANGE", "SQUEEZE"}:
multiplier *= 0.7
momentum_state = getattr(state, "momentum_state", None)
momentum_direction = getattr(state, "momentum_direction", None)
momentum_strength = getattr(state, "momentum_strength", None)
signal = (state.last_signal or "").upper()
if momentum_state in {"BREAKOUT_UP", "BREAKOUT_DOWN"}:
multiplier *= 1.15
elif momentum_state in {"MOMENTUM_UP", "MOMENTUM_DOWN"}:
multiplier *= 1.05
if momentum_strength is not None:
try:
strength = float(momentum_strength)
if strength >= 1.5:
multiplier *= 1.1
elif strength <= 0.7:
multiplier *= 0.8
except Exception:
pass
if signal == "BUY":
if momentum_direction == "DOWN":
multiplier *= 0.75
if signal == "SELL":
if momentum_direction == "UP":
multiplier *= 0.75
execution_quality = getattr(state, "execution_quality", None)
execution_quality_reason = getattr(state, "execution_quality_reason", None)
@@ -762,6 +810,9 @@ class ExecutionEngine:
"market_trend_strength": getattr(state, "market_trend_strength", None),
"market_trend_quality": getattr(state, "market_trend_quality", None),
"market_phase": getattr(state, "market_phase", None),
"momentum_state": getattr(state, "momentum_state", None),
"momentum_direction": getattr(state, "momentum_direction", None),
"momentum_strength": getattr(state, "momentum_strength", None),
"execution_quality": getattr(state, "execution_quality", None),
"execution_quality_reason": getattr(state, "execution_quality_reason", None),
"spread_percent": getattr(state, "spread_percent", None),

View File

@@ -22,6 +22,16 @@ class TrendDirection(StrEnum):
UNKNOWN = "UNKNOWN"
class MomentumState(StrEnum):
NONE = "NONE"
MOMENTUM_UP = "MOMENTUM_UP"
MOMENTUM_DOWN = "MOMENTUM_DOWN"
BREAKOUT_UP = "BREAKOUT_UP"
BREAKOUT_DOWN = "BREAKOUT_DOWN"
EXHAUSTED = "EXHAUSTED"
UNKNOWN = "UNKNOWN"
class VolatilityState(StrEnum):
LOW = "LOW"
NORMAL = "NORMAL"
@@ -81,4 +91,12 @@ class MarketAnalysisResult:
phase_direction: TrendDirection
phase_change_percent: float | None
phase_reason: str | None
phase_direction_consistency: float | None = None
phase_direction_consistency: float | None = None
momentum_state: MomentumState | None = None
momentum_direction: TrendDirection | None = None
momentum_change_percent: float | None = None
momentum_strength: float | None = None
breakout_level: float | None = None
breakout_distance_percent: float | None = None
breakout_reason: str | None = None

View File

@@ -12,6 +12,7 @@ from src.trading.market_analysis.models import (
TrendQuality,
TrendStrength,
VolatilityState,
MomentumState,
)
@@ -29,6 +30,10 @@ class MarketAnalysisService:
_phase_direction_threshold_percent = 0.08
_pullback_min_change_percent = 0.18
_pullback_min_direction_consistency = 0.6
_momentum_window = 3
_momentum_change_threshold_percent = 0.35
_breakout_lookback = 20
_breakout_distance_threshold_percent = 0.08
def analyze(
self,
@@ -109,6 +114,16 @@ class MarketAnalysisService:
phase_direction=phase_direction,
)
(
momentum_state,
momentum_direction,
momentum_change_percent,
momentum_strength,
breakout_level,
breakout_distance_percent,
breakout_reason,
) = self._momentum_breakout_state(closes=closes)
market_phase, phase_reason = self._classify_market_phase(
trend=trend,
volatility=volatility,
@@ -170,6 +185,19 @@ class MarketAnalysisService:
if phase_direction_consistency is not None
else None,
"market_phase_reason": phase_reason,
"momentum_state": momentum_state.value,
"momentum_direction": momentum_direction.value,
"momentum_change_percent": round(momentum_change_percent, 5)
if momentum_change_percent is not None
else None,
"momentum_strength": round(momentum_strength, 3)
if momentum_strength is not None
else None,
"breakout_level": breakout_level,
"breakout_distance_percent": round(breakout_distance_percent, 5)
if breakout_distance_percent is not None
else None,
"breakout_reason": breakout_reason,
"market_trend_gap_percent": round(trend_gap_percent, 5)
if trend_gap_percent is not None
else None,
@@ -198,8 +226,140 @@ class MarketAnalysisService:
phase_change_percent=phase_change_percent,
phase_reason=phase_reason,
phase_direction_consistency=phase_direction_consistency,
momentum_state=momentum_state,
momentum_direction=momentum_direction,
momentum_change_percent=momentum_change_percent,
momentum_strength=momentum_strength,
breakout_level=breakout_level,
breakout_distance_percent=breakout_distance_percent,
breakout_reason=breakout_reason,
)
def _momentum_breakout_state(
self,
*,
closes: list[float],
) -> tuple[
MomentumState,
TrendDirection,
float | None,
float | None,
float | None,
float | None,
str | None,
]:
if len(closes) < max(self._momentum_window + 1, self._breakout_lookback + 1):
return (
MomentumState.UNKNOWN,
TrendDirection.UNKNOWN,
None,
None,
None,
None,
"NOT_ENOUGH_DATA",
)
first_price = closes[-(self._momentum_window + 1)]
last_price = closes[-1]
if first_price <= 0 or last_price <= 0:
return (
MomentumState.UNKNOWN,
TrendDirection.UNKNOWN,
None,
None,
None,
None,
"INVALID_PRICE",
)
momentum_change_percent = ((last_price - first_price) / first_price) * 100
abs_change = abs(momentum_change_percent)
if momentum_change_percent >= self._momentum_change_threshold_percent:
momentum_direction = TrendDirection.UP
elif momentum_change_percent <= -self._momentum_change_threshold_percent:
momentum_direction = TrendDirection.DOWN
else:
momentum_direction = TrendDirection.FLAT
momentum_strength = abs_change / self._momentum_change_threshold_percent
lookback_window = closes[-(self._breakout_lookback + 1):-1]
previous_high = max(lookback_window)
previous_low = min(lookback_window)
if previous_high <= 0 or previous_low <= 0:
return (
MomentumState.UNKNOWN,
TrendDirection.UNKNOWN,
momentum_change_percent,
momentum_strength,
None,
None,
"INVALID_BREAKOUT_LEVEL",
)
if last_price > previous_high:
breakout_distance_percent = ((last_price - previous_high) / previous_high) * 100
if breakout_distance_percent >= self._breakout_distance_threshold_percent:
return (
MomentumState.BREAKOUT_UP,
TrendDirection.UP,
momentum_change_percent,
momentum_strength,
previous_high,
breakout_distance_percent,
"PRICE_ABOVE_LOOKBACK_HIGH",
)
if last_price < previous_low:
breakout_distance_percent = ((previous_low - last_price) / previous_low) * 100
if breakout_distance_percent >= self._breakout_distance_threshold_percent:
return (
MomentumState.BREAKOUT_DOWN,
TrendDirection.DOWN,
momentum_change_percent,
momentum_strength,
previous_low,
breakout_distance_percent,
"PRICE_BELOW_LOOKBACK_LOW",
)
if momentum_direction == TrendDirection.UP:
return (
MomentumState.MOMENTUM_UP,
TrendDirection.UP,
momentum_change_percent,
momentum_strength,
previous_high,
None,
"FAST_UP_MOVE",
)
if momentum_direction == TrendDirection.DOWN:
return (
MomentumState.MOMENTUM_DOWN,
TrendDirection.DOWN,
momentum_change_percent,
momentum_strength,
previous_low,
None,
"FAST_DOWN_MOVE",
)
return (
MomentumState.NONE,
TrendDirection.FLAT,
momentum_change_percent,
momentum_strength,
None,
None,
"NO_SIGNIFICANT_MOMENTUM",
)
def _trend_gap_percent_value(
self,
*,
@@ -533,6 +693,13 @@ class MarketAnalysisService:
"market_phase_change_percent": None,
"market_phase_direction_consistency": None,
"market_phase_reason": reason,
"momentum_state": MomentumState.UNKNOWN.value,
"momentum_direction": TrendDirection.UNKNOWN.value,
"momentum_change_percent": None,
"momentum_strength": None,
"breakout_level": None,
"breakout_distance_percent": None,
"breakout_reason": reason,
"market_trend_gap_percent": None,
"market_trend_consistency": None,
"candles_count": candles_count,
@@ -547,4 +714,12 @@ class MarketAnalysisService:
phase_direction=TrendDirection.UNKNOWN,
phase_change_percent=None,
phase_reason=reason,
phase_direction_consistency=None,
momentum_state=MomentumState.UNKNOWN,
momentum_direction=TrendDirection.UNKNOWN,
momentum_change_percent=None,
momentum_strength=None,
breakout_level=None,
breakout_distance_percent=None,
breakout_reason=reason,
)

View File

@@ -8,6 +8,8 @@ from src.integrations.exchange.service import ExchangeService
from src.trading.market_analysis.models import (
MarketPhase,
MarketState,
MomentumState,
TrendDirection,
TrendQuality,
TrendStrength,
)
@@ -128,12 +130,24 @@ class TrendStrategy:
"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,
"momentum_state": market.momentum_state.value,
"momentum_direction": market.momentum_direction.value,
"momentum_change_percent": market.momentum_change_percent,
"momentum_strength": market.momentum_strength,
"breakout_level": market.breakout_level,
"breakout_distance_percent": market.breakout_distance_percent,
"breakout_reason": market.breakout_reason,
"market_trend_gap_percent": market.trend_gap_percent,
"market_trend_consistency": market.trend_consistency,
"runtime_window_ttl_seconds": self._window_ttl_seconds,
"runtime_window_size": len(prices),
}
breakout_signal = self._breakout_signal(market, base_payload)
if breakout_signal is not None:
return breakout_signal
if not market.is_trade_allowed:
return SignalResult(
signal=SignalType.HOLD,
@@ -286,6 +300,48 @@ class TrendStrategy:
},
)
def _breakout_signal(self, market, base_payload: dict) -> SignalResult | None:
momentum_state = getattr(market, "momentum_state", MomentumState.UNKNOWN)
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:
return SignalResult(
signal=SignalType.BUY,
reason="BREAKOUT_UP подтверждён momentum/breakout semantic layer.",
confidence=self._calculate_breakout_confidence(momentum_strength),
payload={
**base_payload,
"entry_block_reason": None,
"entry_block_message": None,
"breakout_signal": True,
"expected_direction": "BUY",
},
)
if momentum_state == MomentumState.BREAKOUT_DOWN:
return SignalResult(
signal=SignalType.SELL,
reason="BREAKOUT_DOWN подтверждён momentum/breakout semantic layer.",
confidence=self._calculate_breakout_confidence(momentum_strength),
payload={
**base_payload,
"entry_block_reason": None,
"entry_block_message": None,
"breakout_signal": True,
"expected_direction": "SELL",
},
)
return None
def _calculate_breakout_confidence(self, momentum_strength: float) -> float:
strength_score = min(1.0, max(0.0, momentum_strength) / 2)
confidence = 0.55 + (strength_score * 0.35)
return round(min(0.95, confidence), 2)
def _analysis_price(self, snapshot: dict[str, object]) -> float:
bid = self._safe_float(snapshot.get("bid_price"))
ask = self._safe_float(snapshot.get("ask_price"))

View File

@@ -1115,6 +1115,46 @@
- execution runtime подготовлен к probabilistic semantic ranking
- execution runtime подготовлен к AI-driven market reasoning
#### 07.4.4.1.9.6.2 ✅ Momentum & Breakout Semantic Engine
- реализован semantic momentum abstraction layer
- реализован semantic breakout abstraction layer
- реализован semantic acceleration analysis engine
- реализован semantic momentum interpretation runtime
- реализован semantic breakout interpretation runtime
- реализован semantic directional acceleration analysis
- реализован semantic breakout persistence analysis
- реализован semantic breakout continuation analysis
- реализован semantic breakout degradation analysis
- реализован semantic momentum continuation analysis
- реализован semantic momentum persistence analysis
- реализован semantic momentum degradation analysis
- реализован semantic impulsive movement analysis
- реализован semantic fast continuation analysis
- реализован semantic breakout distance analysis
- реализован semantic breakout validation runtime
- реализован semantic momentum strength engine
- реализован semantic momentum direction engine
- реализован semantic breakout classification engine
- реализован semantic momentum classification engine
- реализован semantic momentum diagnostics layer
- реализован semantic breakout diagnostics layer
- реализован explainable momentum diagnostics
- реализован explainable breakout diagnostics
- реализован explainable acceleration diagnostics
- execution runtime теперь анализирует acceleration quality
- execution runtime теперь анализирует breakout persistence
- execution runtime теперь анализирует breakout continuation
- execution runtime теперь анализирует fast directional movement
- execution runtime теперь анализирует impulsive expansion
- execution runtime стал momentum-aware
- execution runtime стал breakout-aware
- execution runtime стал acceleration-aware
- execution runtime стал impulsive-structure-aware
- execution runtime стал лучше различать breakout vs noise
- execution runtime подготовлен к momentum-aware adaptive sizing
- execution runtime подготовлен к semantic breakout routing
- execution runtime подготовлен к AI-driven momentum interpretation
---
### 07.4.5

View File

@@ -1091,6 +1091,46 @@
- execution runtime подготовлен к probabilistic semantic ranking
- execution runtime подготовлен к AI-driven market reasoning
#### 07.4.4.1.9.6.2 ✅ Momentum & Breakout Semantic Engine
- реализован semantic momentum abstraction layer
- реализован semantic breakout abstraction layer
- реализован semantic acceleration analysis engine
- реализован semantic momentum interpretation runtime
- реализован semantic breakout interpretation runtime
- реализован semantic directional acceleration analysis
- реализован semantic breakout persistence analysis
- реализован semantic breakout continuation analysis
- реализован semantic breakout degradation analysis
- реализован semantic momentum continuation analysis
- реализован semantic momentum persistence analysis
- реализован semantic momentum degradation analysis
- реализован semantic impulsive movement analysis
- реализован semantic fast continuation analysis
- реализован semantic breakout distance analysis
- реализован semantic breakout validation runtime
- реализован semantic momentum strength engine
- реализован semantic momentum direction engine
- реализован semantic breakout classification engine
- реализован semantic momentum classification engine
- реализован semantic momentum diagnostics layer
- реализован semantic breakout diagnostics layer
- реализован explainable momentum diagnostics
- реализован explainable breakout diagnostics
- реализован explainable acceleration diagnostics
- execution runtime теперь анализирует acceleration quality
- execution runtime теперь анализирует breakout persistence
- execution runtime теперь анализирует breakout continuation
- execution runtime теперь анализирует fast directional movement
- execution runtime теперь анализирует impulsive expansion
- execution runtime стал momentum-aware
- execution runtime стал breakout-aware
- execution runtime стал acceleration-aware
- execution runtime стал impulsive-structure-aware
- execution runtime стал лучше различать breakout vs noise
- execution runtime подготовлен к momentum-aware adaptive sizing
- execution runtime подготовлен к semantic breakout routing
- execution runtime подготовлен к AI-driven momentum interpretation
---
### 07.4.5

View File

@@ -0,0 +1,119 @@
# 07.4.4.1.9.6.2 Momentum & Breakout Semantic Engine
## Цель этапа
Этап направлен на внедрение semantic momentum и breakout interpretation layer поверх существующей semantic market architecture.
Execution runtime теперь анализирует:
- краткосрочное ускорение движения
- breakout continuation
- momentum persistence
- breakout distance quality
- impulsive market behaviour
- fast continuation structures
---
# Что реализовано
## Реализован Momentum Semantic Layer
Добавлен отдельный semantic momentum abstraction layer.
Runtime теперь умеет интерпретировать:
- быстрые directional impulses
- ускорение движения
- breakout continuation
- impulsive expansion structures
---
## Реализован Momentum Semantic Engine
Добавлены semantic momentum states:
- NONE
- MOMENTUM_UP
- MOMENTUM_DOWN
- BREAKOUT_UP
- BREAKOUT_DOWN
- EXHAUSTED
- UNKNOWN
---
## Реализован Breakout Semantic Engine
Breakout engine теперь анализирует:
- previous lookback high
- previous lookback low
- breakout continuation distance
- breakout expansion quality
- breakout persistence
---
# Что изменилось в аналитике
## Реализована semantic momentum analytics
Runtime теперь анализирует:
- fast directional movement
- short-term continuation
- impulsive expansion
- directional acceleration
- breakout continuation probability
Execution runtime теперь дополнительно анализирует:
- acceleration quality
- impulsive continuation
- breakout expansion
- fast market structure
---
## Реализована semantic breakout analytics
Runtime теперь анализирует:
- breakout continuation
- breakout persistence
- breakout expansion quality
- breakout degradation
- failed breakout probability
---
## Реализована explainable momentum diagnostics
Добавлены explainable diagnostics:
- momentum state
- momentum direction
- momentum strength
- breakout level
- breakout distance
- breakout reason
---
# Интеграция с Execution Runtime
Execution runtime теперь анализирует:
- momentum continuation
- breakout continuation
- acceleration quality
- impulsive expansion
- fast continuation persistence
---
# Результат
Execution runtime стал:
- momentum-aware
- breakout-aware
- acceleration-aware
- continuation-aware
- probabilistic
- explainable
- context-aware
Система стала ближе к institutional momentum interpretation architecture.