07.4.4.1.9.6.2 Momentum & Breakout Semantic Engine
This commit is contained in:
@@ -182,6 +182,40 @@ def _execution_confidence_line(state) -> str:
|
|||||||
return f"🧠 Уверенность входа · {percent}% низкая"
|
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:
|
def _adaptive_size_line(state) -> str:
|
||||||
multiplier = getattr(state, "adaptive_size_multiplier", None)
|
multiplier = getattr(state, "adaptive_size_multiplier", None)
|
||||||
|
|
||||||
@@ -224,6 +258,7 @@ def _build_waiting_text(state) -> str:
|
|||||||
_signal_confirmation_line(state),
|
_signal_confirmation_line(state),
|
||||||
_execution_confidence_line(state),
|
_execution_confidence_line(state),
|
||||||
_market_semantic_line(state),
|
_market_semantic_line(state),
|
||||||
|
_momentum_semantic_line(state),
|
||||||
_entry_block_line(state),
|
_entry_block_line(state),
|
||||||
_execution_semantic_line(state),
|
_execution_semantic_line(state),
|
||||||
*_signal_confidence_lines(state),
|
*_signal_confidence_lines(state),
|
||||||
@@ -284,6 +319,7 @@ def _build_active_position_text(state) -> str:
|
|||||||
|
|
||||||
market_lines = [
|
market_lines = [
|
||||||
_market_semantic_line(state),
|
_market_semantic_line(state),
|
||||||
|
_momentum_semantic_line(state),
|
||||||
_execution_semantic_line(state),
|
_execution_semantic_line(state),
|
||||||
]
|
]
|
||||||
market_lines = [line for line in market_lines if line]
|
market_lines = [line for line in market_lines if line]
|
||||||
|
|||||||
@@ -408,6 +408,13 @@ class AutoTradeService:
|
|||||||
state.market_phase_direction = None
|
state.market_phase_direction = None
|
||||||
state.entry_block_reason = None
|
state.entry_block_reason = None
|
||||||
state.entry_block_message = 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_reason = None
|
||||||
state.runtime_expired_message = None
|
state.runtime_expired_message = None
|
||||||
state.snapshot_age_seconds = None
|
state.snapshot_age_seconds = None
|
||||||
@@ -848,6 +855,13 @@ class AutoTradeService:
|
|||||||
state.market_phase_direction = payload.get("market_phase_direction")
|
state.market_phase_direction = payload.get("market_phase_direction")
|
||||||
state.market_analysis_interval = payload.get("market_analysis_interval")
|
state.market_analysis_interval = payload.get("market_analysis_interval")
|
||||||
state.market_analysis_reason = payload.get("market_analysis_reason")
|
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.market_analysis_updated_at = time.monotonic()
|
||||||
state.entry_block_reason = payload.get("entry_block_reason")
|
state.entry_block_reason = payload.get("entry_block_reason")
|
||||||
state.entry_block_message = payload.get("entry_block_message")
|
state.entry_block_message = payload.get("entry_block_message")
|
||||||
@@ -1060,6 +1074,18 @@ class AutoTradeService:
|
|||||||
state.market_analysis_updated_at = None
|
state.market_analysis_updated_at = None
|
||||||
state.entry_block_reason = None
|
state.entry_block_reason = None
|
||||||
state.entry_block_message = 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_reason = "MARKET_ANALYSIS_TTL_EXPIRED"
|
||||||
state.runtime_expired_message = "анализ рынка устарел"
|
state.runtime_expired_message = "анализ рынка устарел"
|
||||||
|
|
||||||
@@ -1350,6 +1376,13 @@ class AutoTradeService:
|
|||||||
"execution_quality": state.execution_quality,
|
"execution_quality": state.execution_quality,
|
||||||
"execution_quality_reason": state.execution_quality_reason,
|
"execution_quality_reason": state.execution_quality_reason,
|
||||||
"spread_percent": state.spread_percent,
|
"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:
|
def _market_confidence_score(self, state: AutoTradeState) -> float:
|
||||||
|
|||||||
@@ -127,6 +127,28 @@ class AutoTradeState:
|
|||||||
# направление короткой фазы рынка: UP / DOWN / FLAT / UNKNOWN
|
# направление короткой фазы рынка: UP / DOWN / FLAT / UNKNOWN
|
||||||
market_phase_direction: str | None = None
|
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
|
market_analysis_interval: str | None = None
|
||||||
|
|
||||||
|
|||||||
@@ -501,6 +501,9 @@ class ExecutionEngine:
|
|||||||
repeat_count = int(state.last_signal_repeat_count or 0)
|
repeat_count = int(state.last_signal_repeat_count or 0)
|
||||||
unrealized_pnl = float(state.unrealized_pnl_usd or 0.0)
|
unrealized_pnl = float(state.unrealized_pnl_usd or 0.0)
|
||||||
hold_seconds = self._position_hold_seconds(position)
|
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:
|
if confidence < self._min_flip_confidence:
|
||||||
return (
|
return (
|
||||||
@@ -519,6 +522,19 @@ class ExecutionEngine:
|
|||||||
"позиция открыта слишком недавно "
|
"позиция открыта слишком недавно "
|
||||||
f"({hold_seconds}с < {self._min_flip_hold_seconds}с)"
|
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:
|
if unrealized_pnl < 0 and confidence < self._loss_flip_confidence:
|
||||||
return (
|
return (
|
||||||
@@ -711,6 +727,38 @@ class ExecutionEngine:
|
|||||||
elif market_phase in {"RANGE", "SQUEEZE"}:
|
elif market_phase in {"RANGE", "SQUEEZE"}:
|
||||||
multiplier *= 0.7
|
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 = getattr(state, "execution_quality", None)
|
||||||
execution_quality_reason = getattr(state, "execution_quality_reason", 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_strength": getattr(state, "market_trend_strength", None),
|
||||||
"market_trend_quality": getattr(state, "market_trend_quality", None),
|
"market_trend_quality": getattr(state, "market_trend_quality", None),
|
||||||
"market_phase": getattr(state, "market_phase", 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": getattr(state, "execution_quality", None),
|
||||||
"execution_quality_reason": getattr(state, "execution_quality_reason", None),
|
"execution_quality_reason": getattr(state, "execution_quality_reason", None),
|
||||||
"spread_percent": getattr(state, "spread_percent", None),
|
"spread_percent": getattr(state, "spread_percent", None),
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ class TrendDirection(StrEnum):
|
|||||||
UNKNOWN = "UNKNOWN"
|
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):
|
class VolatilityState(StrEnum):
|
||||||
LOW = "LOW"
|
LOW = "LOW"
|
||||||
NORMAL = "NORMAL"
|
NORMAL = "NORMAL"
|
||||||
@@ -81,4 +91,12 @@ class MarketAnalysisResult:
|
|||||||
phase_direction: TrendDirection
|
phase_direction: TrendDirection
|
||||||
phase_change_percent: float | None
|
phase_change_percent: float | None
|
||||||
phase_reason: str | 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
|
||||||
@@ -12,6 +12,7 @@ from src.trading.market_analysis.models import (
|
|||||||
TrendQuality,
|
TrendQuality,
|
||||||
TrendStrength,
|
TrendStrength,
|
||||||
VolatilityState,
|
VolatilityState,
|
||||||
|
MomentumState,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +30,10 @@ class MarketAnalysisService:
|
|||||||
_phase_direction_threshold_percent = 0.08
|
_phase_direction_threshold_percent = 0.08
|
||||||
_pullback_min_change_percent = 0.18
|
_pullback_min_change_percent = 0.18
|
||||||
_pullback_min_direction_consistency = 0.6
|
_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(
|
def analyze(
|
||||||
self,
|
self,
|
||||||
@@ -109,6 +114,16 @@ class MarketAnalysisService:
|
|||||||
phase_direction=phase_direction,
|
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(
|
market_phase, phase_reason = self._classify_market_phase(
|
||||||
trend=trend,
|
trend=trend,
|
||||||
volatility=volatility,
|
volatility=volatility,
|
||||||
@@ -170,6 +185,19 @@ class MarketAnalysisService:
|
|||||||
if phase_direction_consistency is not None
|
if phase_direction_consistency is not None
|
||||||
else None,
|
else None,
|
||||||
"market_phase_reason": phase_reason,
|
"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)
|
"market_trend_gap_percent": round(trend_gap_percent, 5)
|
||||||
if trend_gap_percent is not None
|
if trend_gap_percent is not None
|
||||||
else None,
|
else None,
|
||||||
@@ -198,8 +226,140 @@ class MarketAnalysisService:
|
|||||||
phase_change_percent=phase_change_percent,
|
phase_change_percent=phase_change_percent,
|
||||||
phase_reason=phase_reason,
|
phase_reason=phase_reason,
|
||||||
phase_direction_consistency=phase_direction_consistency,
|
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(
|
def _trend_gap_percent_value(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -533,6 +693,13 @@ class MarketAnalysisService:
|
|||||||
"market_phase_change_percent": None,
|
"market_phase_change_percent": None,
|
||||||
"market_phase_direction_consistency": None,
|
"market_phase_direction_consistency": None,
|
||||||
"market_phase_reason": reason,
|
"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_gap_percent": None,
|
||||||
"market_trend_consistency": None,
|
"market_trend_consistency": None,
|
||||||
"candles_count": candles_count,
|
"candles_count": candles_count,
|
||||||
@@ -547,4 +714,12 @@ class MarketAnalysisService:
|
|||||||
phase_direction=TrendDirection.UNKNOWN,
|
phase_direction=TrendDirection.UNKNOWN,
|
||||||
phase_change_percent=None,
|
phase_change_percent=None,
|
||||||
phase_reason=reason,
|
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,
|
||||||
)
|
)
|
||||||
@@ -8,6 +8,8 @@ from src.integrations.exchange.service import ExchangeService
|
|||||||
from src.trading.market_analysis.models import (
|
from src.trading.market_analysis.models import (
|
||||||
MarketPhase,
|
MarketPhase,
|
||||||
MarketState,
|
MarketState,
|
||||||
|
MomentumState,
|
||||||
|
TrendDirection,
|
||||||
TrendQuality,
|
TrendQuality,
|
||||||
TrendStrength,
|
TrendStrength,
|
||||||
)
|
)
|
||||||
@@ -128,12 +130,24 @@ class TrendStrategy:
|
|||||||
"market_phase_change_percent": market.phase_change_percent,
|
"market_phase_change_percent": market.phase_change_percent,
|
||||||
"market_phase_direction_consistency": market.payload.get("market_phase_direction_consistency"),
|
"market_phase_direction_consistency": market.payload.get("market_phase_direction_consistency"),
|
||||||
"market_phase_reason": market.phase_reason,
|
"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_gap_percent": market.trend_gap_percent,
|
||||||
"market_trend_consistency": market.trend_consistency,
|
"market_trend_consistency": market.trend_consistency,
|
||||||
"runtime_window_ttl_seconds": self._window_ttl_seconds,
|
"runtime_window_ttl_seconds": self._window_ttl_seconds,
|
||||||
"runtime_window_size": len(prices),
|
"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:
|
if not market.is_trade_allowed:
|
||||||
return SignalResult(
|
return SignalResult(
|
||||||
signal=SignalType.HOLD,
|
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:
|
def _analysis_price(self, snapshot: dict[str, object]) -> float:
|
||||||
bid = self._safe_float(snapshot.get("bid_price"))
|
bid = self._safe_float(snapshot.get("bid_price"))
|
||||||
ask = self._safe_float(snapshot.get("ask_price"))
|
ask = self._safe_float(snapshot.get("ask_price"))
|
||||||
|
|||||||
@@ -1115,6 +1115,46 @@
|
|||||||
- execution runtime подготовлен к probabilistic semantic ranking
|
- execution runtime подготовлен к probabilistic semantic ranking
|
||||||
- execution runtime подготовлен к AI-driven market reasoning
|
- 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
|
### 07.4.5
|
||||||
|
|||||||
@@ -1091,6 +1091,46 @@
|
|||||||
- execution runtime подготовлен к probabilistic semantic ranking
|
- execution runtime подготовлен к probabilistic semantic ranking
|
||||||
- execution runtime подготовлен к AI-driven market reasoning
|
- 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
|
### 07.4.5
|
||||||
|
|||||||
@@ -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.
|
||||||
Reference in New Issue
Block a user