07.4.4.1.13 — AutoTrade Runtime Journal, Execution Refactor & Trade Analytics

This commit is contained in:
2026-05-28 10:30:54 +03:00
parent f9a25e7671
commit d9e6392e28
75 changed files with 9934 additions and 10508 deletions

View File

@@ -23,9 +23,6 @@ def build_signal_notification(event: RuntimeEvent) -> NotificationMessage | None
position_context = str(payload.get("position_context") or "NONE").upper()
semantic_lines = _as_json_list(payload.get("semantic_lines"))
bid_price = payload.get("bid_price")
ask_price = payload.get("ask_price")
priority = str(
event.priority
or _alert_priority(
@@ -40,24 +37,32 @@ def build_signal_notification(event: RuntimeEvent) -> NotificationMessage | None
strength = _strength_label(priority)
strength_bar = _strength_bar(priority)
market_price_line = _market_price_line(
direction=direction_key,
bid_price=bid_price,
ask_price=ask_price,
)
lines = [
f"<b>Сигнал {icon} {symbol} · {direction}</b>",
"",
]
if market_price_line:
lines.extend([market_price_line, ""])
position_line = _position_context_line(
signal=signal,
position_context=position_context,
)
if position_context not in {"NONE", "", ""} and position_context != direction_key:
lines.extend(["⚠️ ПРОТИВ ПОЗИЦИИ", ""])
if position_line:
lines.append(position_line)
lines.append(f"{strength_bar} {strength} · {confidence:.2f}")
price_lines = _market_price_lines(
direction=direction_key,
bid_price=payload.get("bid_price"),
ask_price=payload.get("ask_price"),
)
if price_lines:
lines.append("")
lines.extend(price_lines)
lines.extend([
"",
f"{strength_bar} {strength} · {confidence:.2f}",
])
if semantic_lines:
lines.extend(
@@ -74,6 +79,68 @@ def build_signal_notification(event: RuntimeEvent) -> NotificationMessage | None
)
def _position_context_line(
*,
signal: str,
position_context: str,
) -> str:
if position_context in {"NONE", "", ""}:
return ""
if position_context == "LONG" and signal == "BUY":
return " В сторону открытой позиции"
if position_context == "SHORT" and signal == "SELL":
return " В сторону открытой позиции"
if position_context == "LONG" and signal == "SELL":
return "⚠️ Против открытой позиции"
if position_context == "SHORT" and signal == "BUY":
return "⚠️ Против открытой позиции"
return ""
def _market_price_lines(
*,
direction: str,
bid_price: NumericLike | None,
ask_price: NumericLike | None,
) -> list[str]:
bid = _format_price_usd(bid_price)
ask = _format_price_usd(ask_price)
if bid == "" and ask == "":
return []
if direction == "LONG":
return [
f"Цена входа Long · {ask} (Ask)",
f"Цена Bid · {bid}",
]
if direction == "SHORT":
return [
f"Цена входа Short · {bid} (Bid)",
f"Цена Ask · {ask}",
]
return [
f"Цена Bid · {bid}",
f"Цена Ask · {ask}",
]
def _format_price_usd(value: NumericLike | None) -> str:
number = safe_float(value)
if number is None:
return ""
return f"${number:,.2f}".replace(",", " ")
def _alert_priority(*, confidence: float, repeat_count: int) -> str:
if confidence >= 0.8 and repeat_count >= 3:
return "HIGH"
@@ -131,27 +198,6 @@ def _format_symbol(symbol: str) -> str:
return symbol.split("_", 1)[0].split("/", 1)[0].upper()
def _market_price_line(
*,
direction: str,
bid_price: NumericLike | None,
ask_price: NumericLike | None,
) -> str:
bid = _format_price(bid_price)
ask = _format_price(ask_price)
if bid == "" and ask == "":
return ""
if direction == "LONG":
return f"Цена входа: Ask ${ask} / Bid ${bid}"
if direction == "SHORT":
return f"Цена входа: Bid ${bid} / Ask ${ask}"
return f"Цена рынка: Bid ${bid} / Ask ${ask}"
def _format_price(value: NumericLike | None) -> str:
number = safe_float(value)