07.4.3.19.2 — Journal Noise Reduction & Position-aware Signal Logg
This commit is contained in:
@@ -36,6 +36,9 @@ class AutoTradeRunner:
|
||||
_last_event_version: int = 0
|
||||
_retry_after_until: float = 0.0
|
||||
|
||||
_position_aligned_signal_log_interval_seconds = 900
|
||||
_last_position_aligned_signal_log_at_by_key: dict[str, float] = {}
|
||||
|
||||
@classmethod
|
||||
def register_screen(
|
||||
cls,
|
||||
@@ -206,6 +209,14 @@ class AutoTradeRunner:
|
||||
if signal not in {"BUY", "SELL"}:
|
||||
return
|
||||
|
||||
if cls._is_position_aligned_signal(state=state, signal=signal):
|
||||
cls._log_position_aligned_signal_suppressed(
|
||||
state=state,
|
||||
payload=payload,
|
||||
signal=signal,
|
||||
)
|
||||
return
|
||||
|
||||
cls._publish_strong_signal_event(state=state, payload=payload)
|
||||
return
|
||||
|
||||
@@ -221,6 +232,73 @@ class AutoTradeRunner:
|
||||
)
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def _is_position_aligned_signal(cls, *, state, signal: str) -> bool:
|
||||
position_side = str(getattr(state, "position_side", "NONE") or "NONE").upper()
|
||||
|
||||
if position_side == "LONG" and signal == "BUY":
|
||||
return True
|
||||
|
||||
if position_side == "SHORT" and signal == "SELL":
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _log_position_aligned_signal_suppressed(
|
||||
cls,
|
||||
*,
|
||||
state,
|
||||
payload: dict,
|
||||
signal: str,
|
||||
) -> None:
|
||||
position_side = str(getattr(state, "position_side", "NONE") or "NONE").upper()
|
||||
symbol = str(payload.get("symbol") or state.symbol or "—")
|
||||
strategy = str(payload.get("strategy") or state.strategy or "—")
|
||||
confidence = float(payload.get("confidence") or state.last_signal_confidence or 0.0)
|
||||
repeat_count = int(payload.get("repeat_count") or state.last_signal_repeat_count or 0)
|
||||
|
||||
log_key = (
|
||||
f"{position_side}:"
|
||||
f"{symbol}:"
|
||||
f"{strategy}:"
|
||||
f"{signal}"
|
||||
)
|
||||
|
||||
now = time.monotonic()
|
||||
last_logged_at = cls._last_position_aligned_signal_log_at_by_key.get(log_key)
|
||||
|
||||
if (
|
||||
last_logged_at is not None
|
||||
and now - last_logged_at < cls._position_aligned_signal_log_interval_seconds
|
||||
):
|
||||
return
|
||||
|
||||
cls._last_position_aligned_signal_log_at_by_key[log_key] = now
|
||||
|
||||
try:
|
||||
JournalService().log_ui_info(
|
||||
event_type="auto_position_aligned_signal_suppressed",
|
||||
message=(
|
||||
f"Сигнал {signal} совпадает с открытой позицией "
|
||||
f"{position_side}; уведомление подавлено."
|
||||
),
|
||||
screen="auto",
|
||||
action="signal_notification",
|
||||
payload={
|
||||
"symbol": symbol,
|
||||
"strategy": strategy,
|
||||
"signal": signal,
|
||||
"position_side": position_side,
|
||||
"confidence": confidence,
|
||||
"repeat_count": repeat_count,
|
||||
"reason": payload.get("reason") or state.last_signal_reason,
|
||||
"suppression_interval_seconds": cls._position_aligned_signal_log_interval_seconds,
|
||||
},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def _publish_strong_signal_event(cls, *, state, payload: dict) -> None:
|
||||
signal = str(payload.get("signal", "")).upper()
|
||||
@@ -366,29 +444,11 @@ class AutoTradeRunner:
|
||||
|
||||
@classmethod
|
||||
def _log_refresh_skip(cls, reason: str, payload: dict | None = None) -> None:
|
||||
try:
|
||||
JournalService().log_ui_info(
|
||||
event_type="auto_screen_refresh_skipped",
|
||||
message=f"Auto screen refresh skipped: {reason}",
|
||||
screen="auto",
|
||||
action="refresh_screen",
|
||||
payload=payload or {},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def _log_refresh_success(cls, payload: dict | None = None) -> None:
|
||||
try:
|
||||
JournalService().log_ui_info(
|
||||
event_type="auto_screen_refreshed",
|
||||
message="Auto screen refreshed.",
|
||||
screen="auto",
|
||||
action="refresh_screen",
|
||||
payload=payload or {},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def _log_refresh_error(cls, reason: str, payload: dict | None = None) -> None:
|
||||
|
||||
@@ -11,7 +11,7 @@ from src.storage.repositories.journal import JournalRepository
|
||||
from src.storage.session import check_database_health
|
||||
from src.trading.journal.exporter import build_csv, build_xlsx
|
||||
|
||||
EXPORT_LIMIT = 5000
|
||||
EXPORT_LIMIT = 10000
|
||||
|
||||
|
||||
class JournalService:
|
||||
|
||||
Reference in New Issue
Block a user