Fájl részletek

Ezen az oldalon egy konkrét fájl aktuális állapotát tudod megnézni.

Vissza a fájltérképhez Csak változott Stratégia-labor Monitor főoldal Következő módosult →
Fájl útvonala
/opt/bots/saturnus/app/rule_engine.py
Létezik most?
IGEN
Aktuális státusz
MODIFIED
Méret
31165
Módosítás ideje
1776173717.205729
Korábbi baseline időpont
1776107087.9101276
SHA256 rövid

Előnézet (első 120 sor)

# rule_engine.py
# Saturnus – kanonikus rule engine
# Fő elvek:
# - normál trade-pár ne legyen veszteséges, ha ezt a piac megengedi
# - panic trade után recovery mód kötelező
# - recovery BUY csak akkor engedhető, ha a következő SELL oldalon
#   a korábbi veszteség visszahozható
# - recovery SELL csak akkor engedhető, ha ténylegesen visszahozza
#   a korábbi veszteséget
# - panic szabályokra kötelező az MA + iránykényszer
# - catastrophe szabályok külön végső védelmi ágként maradnak

from __future__ import annotations

from typing import Any, Dict, List, Optional, Tuple


DEFAULT_CFG = {
    "STD_SELL_RETRACE_PCT": 0.006,
    "STD_BUY_REBOUND_PCT": 0.006,
    "RECOVERY_SELL_RETRACE_PCT": 0.004,
    "RECOVERY_BUY_REBOUND_PCT": 0.012,
    "PANIC_OFFSET_PCT": 0.03,
    "CATASTROPHE_OFFSET_PCT": 0.10,
    "MIN_REBOUND_CONFIRM_PCT": 0.003,
    "RECOVERY_ARM_TIMEOUT_BARS": 240,
    "SPREAD_MAX_PCT": 0.05,
    "STALENESS_MAX_MS": 999999999,
    "PROFIT_BUFFER_PCT": 0.001,
    "COST_GUARD_ENABLED": True,
    "PANIC_RECOVERY_EXTRA_GAP_PCT": 0.002,
    "SIDEWAYS_MA_GAP_PCT": 0.0015,
    "RECOVERY_PROFIT_TARGET_PCT": 0.003,
    "RECOVERY_BUY_MAX_ABOVE_BASE_PCT": 0.0,
}


def _f(value: Any) -> Optional[float]:
    try:
        if value is None:
            return None
        return float(value)
    except Exception:
        return None


def _b(value: Any, default: bool = False) -> bool:
    if isinstance(value, bool):
        return value
    if value is None:
        return default
    if isinstance(value, str):
        v = value.strip().lower()
        if v in ("1", "true", "yes", "on"):
            return True
        if v in ("0", "false", "no", "off"):
            return False
    return bool(value)


def _cfg_value(params: Dict[str, Any], *keys: str, default: Any, cast=float):
    for key in keys:
        if key in params and params.get(key) is not None:
            try:
                return cast(params.get(key))
            except Exception:
                pass
    return default


def _hold(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
    payload = {
        "action": "HOLD",
        "rule": "HOLD",
        "reason": reason,
        "trigger_level": None,
        "gate_reason": "",
        "data": data or {},
        "decision_action": "HOLD",
        "decision_rule_id": "HOLD",
        "decision_level": None,
        "decision_reason": reason,
    }
    return payload


def _no_trade(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
    return _hold(reason, data or {})


def _sell(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]:
    payload = {
        "action": "SELL",
        "rule": rule_id,
        "reason": reason,
        "trigger_level": level,
        "gate_reason": "",
        "data": data,
        "decision_action": "SELL",
        "decision_rule_id": rule_id,
        "decision_level": level,
        "decision_reason": reason,
    }
    return payload


def _buy(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]:
    payload = {
        "action": "BUY",
        "rule": rule_id,
        "reason": reason,
        "trigger_level": level,
        "gate_reason": "",
        "data": data,
        "decision_action": "BUY",
        "decision_rule_id": rule_id,
        "decision_level": level,
        "decision_reason": reason,
    }
    return payload

Csak változott diff sorok

--- baseline +++ current @@ -1,52 +1,39 @@ -# Saturnus v2 – recovery-alapú, 6 szabályos döntési motor -# Kompatibilis wrapperrel a meglévő egyparaméteres decide(raw_state) hívásokhoz +# Saturnus – kanonikus rule engine +# Fő elvek: +# - normál trade-pár ne legyen veszteséges, ha ezt a piac megengedi +# - panic trade után recovery mód kötelező +# - recovery BUY csak akkor engedhető, ha a következő SELL oldalon +# a korábbi veszteség visszahozható +# - recovery SELL csak akkor engedhető, ha ténylegesen visszahozza +# a korábbi veszteséget +# - panic szabályokra kötelező az MA + iránykényszer +# - catastrophe szabályok külön végső védelmi ágként maradnak -from typing import Any, Dict, Optional, Tuple - - -# ========================================================= -# Default config -# ========================================================= - -DEFAULT_CFG: Dict[str, Any] = { - "STD_SELL_RETRACE_PCT": 0.010, - "STD_BUY_REBOUND_PCT": 0.010, - "RECOVERY_SELL_RETRACE_PCT": 0.006, - "RECOVERY_BUY_REBOUND_PCT": 0.006, - "PANIC_OFFSET_PCT": 0.020, - "CATASTROPHE_OFFSET_PCT": 0.120, - "MIN_REBOUND_CONFIRM_PCT": 0.002, +from typing import Any, Dict, List, Optional, Tuple + + +DEFAULT_CFG = { + "STD_SELL_RETRACE_PCT": 0.006, + "STD_BUY_REBOUND_PCT": 0.006, + "RECOVERY_SELL_RETRACE_PCT": 0.004, + "RECOVERY_BUY_REBOUND_PCT": 0.012, + "PANIC_OFFSET_PCT": 0.03, + "CATASTROPHE_OFFSET_PCT": 0.10, + "MIN_REBOUND_CONFIRM_PCT": 0.003, - "SPREAD_MAX_PCT": 0.0020, - "STALENESS_MAX_MS": 500, - "PROFIT_BUFFER_PCT": 0.0010, + "SPREAD_MAX_PCT": 0.05, + "STALENESS_MAX_MS": 999999999, + "PROFIT_BUFFER_PCT": 0.001, - "RECOVERY_PROFIT_TARGET_PCT": 0.001, - "RECOVERY_BUY_MAX_ABOVE_BASE_PCT": 0.006, + "RECOVERY_PROFIT_TARGET_PCT": 0.003, + "RECOVERY_BUY_MAX_ABOVE_BASE_PCT": 0.0, - -SELL_PRIORITY = { - "SELL_PANIC": 1, - "SELL_STANDARD": 2, - "SELL_RECOVERY": 3, -} - -BUY_PRIORITY = { - "BUY_PANIC": 1, - "BUY_STANDARD": 2, - "BUY_RECOVERY": 3, -} - - -# ========================================================= -# Helpers -# ========================================================= @@ -71,86 +58,123 @@ -def _decision( - *, - action: str, - rule: str, - reason: str, - trigger_level: Optional[float] = None, - gate_reason: str = "", - data: Optional[Dict[str, Any]] = None, -) -> Dict[str, Any]: - return { - "action": action, - "rule": rule, +def _cfg_value(params: Dict[str, Any], *keys: str, default: Any, cast=float): + for key in keys: + if key in params and params.get(key) is not None: + try: + return cast(params.get(key)) + except Exception: + pass + return default + + +def _hold(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + payload = { + "action": "HOLD", + "rule": "HOLD", - "trigger_level": trigger_level, - "gate_reason": gate_reason, + "trigger_level": None, + "gate_reason": "", - # új mezők a monitor/export felé - "decision_action": action, - "decision_rule_id": rule, - "decision_level": trigger_level, + "decision_action": "HOLD", + "decision_rule_id": "HOLD", + "decision_level": None, - - -def _hold(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="HOLD", rule="HOLD", reason=reason, trigger_level=None, data=data) - - -def _no_trade(gate_reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision( - action="NO_TRADE", - rule="NO_TRADE", - reason=gate_reason, - trigger_level=None, - gate_reason=gate_reason, - data=data, - ) - - -def _buy(rule: str, level: float, reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="BUY", rule=rule, reason=reason, trigger_level=level, data=data) - - -def _sell(rule: str, level: float, reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="SELL", rule=rule, reason=reason, trigger_level=level, data=data) - - -def _choose_sell(active_rules: list[Tuple[str, float]]) -> Tuple[str, float]: - # SELL: legmagasabb árszint nyer - # tie-break: RECOVERY > STANDARD > PANIC - return sorted(active_rules, key=lambda x: (x[1], SELL_PRIORITY.get(x[0], 0)), reverse=True)[0] - - -def _choose_buy(active_rules: list[Tuple[str, float]]) -> Tuple[str, float]: - # BUY: legalacsonyabb árszint nyer - # tie-break: RECOVERY > STANDARD > PANIC - return sorted(active_rules, key=lambda x: (x[1], -BUY_PRIORITY.get(x[0], 0)))[0] - - -# ========================================================= -# Normalization / compatibility layer -# ========================================================= + return payload + + +def _no_trade(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + return _hold(reason, data or {}) + + +def _sell(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]: + payload = { + "action": "SELL", + "rule": rule_id, + "reason": reason, + "trigger_level": level, + "gate_reason": "", + "data": data, + "decision_action": "SELL", + "decision_rule_id": rule_id, + "decision_level": level, + "decision_reason": reason, + } + return payload + + +def _buy(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]: + payload = { + "action": "BUY", + "rule": rule_id, + "reason": reason, + "trigger_level": level, + "gate_reason": "", + "data": data, + "decision_action": "BUY", + "decision_rule_id": rule_id, + "decision_level": level,

Teljes diff

--- baseline +++ current @@ -1,52 +1,39 @@ # rule_engine.py -# Saturnus v2 – recovery-alapú, 6 szabályos döntési motor -# Kompatibilis wrapperrel a meglévő egyparaméteres decide(raw_state) hívásokhoz +# Saturnus – kanonikus rule engine +# Fő elvek: +# - normál trade-pár ne legyen veszteséges, ha ezt a piac megengedi +# - panic trade után recovery mód kötelező +# - recovery BUY csak akkor engedhető, ha a következő SELL oldalon +# a korábbi veszteség visszahozható +# - recovery SELL csak akkor engedhető, ha ténylegesen visszahozza +# a korábbi veszteséget +# - panic szabályokra kötelező az MA + iránykényszer +# - catastrophe szabályok külön végső védelmi ágként maradnak from __future__ import annotations -from typing import Any, Dict, Optional, Tuple - - -# ========================================================= -# Default config -# ========================================================= - -DEFAULT_CFG: Dict[str, Any] = { - "STD_SELL_RETRACE_PCT": 0.010, - "STD_BUY_REBOUND_PCT": 0.010, - "RECOVERY_SELL_RETRACE_PCT": 0.006, - "RECOVERY_BUY_REBOUND_PCT": 0.006, - "PANIC_OFFSET_PCT": 0.020, - "CATASTROPHE_OFFSET_PCT": 0.120, - "MIN_REBOUND_CONFIRM_PCT": 0.002, +from typing import Any, Dict, List, Optional, Tuple + + +DEFAULT_CFG = { + "STD_SELL_RETRACE_PCT": 0.006, + "STD_BUY_REBOUND_PCT": 0.006, + "RECOVERY_SELL_RETRACE_PCT": 0.004, + "RECOVERY_BUY_REBOUND_PCT": 0.012, + "PANIC_OFFSET_PCT": 0.03, + "CATASTROPHE_OFFSET_PCT": 0.10, + "MIN_REBOUND_CONFIRM_PCT": 0.003, "RECOVERY_ARM_TIMEOUT_BARS": 240, - "SPREAD_MAX_PCT": 0.0020, - "STALENESS_MAX_MS": 500, - "PROFIT_BUFFER_PCT": 0.0010, + "SPREAD_MAX_PCT": 0.05, + "STALENESS_MAX_MS": 999999999, + "PROFIT_BUFFER_PCT": 0.001, "COST_GUARD_ENABLED": True, "PANIC_RECOVERY_EXTRA_GAP_PCT": 0.002, "SIDEWAYS_MA_GAP_PCT": 0.0015, - "RECOVERY_PROFIT_TARGET_PCT": 0.001, - "RECOVERY_BUY_MAX_ABOVE_BASE_PCT": 0.006, + "RECOVERY_PROFIT_TARGET_PCT": 0.003, + "RECOVERY_BUY_MAX_ABOVE_BASE_PCT": 0.0, } - -SELL_PRIORITY = { - "SELL_PANIC": 1, - "SELL_STANDARD": 2, - "SELL_RECOVERY": 3, -} - -BUY_PRIORITY = { - "BUY_PANIC": 1, - "BUY_STANDARD": 2, - "BUY_RECOVERY": 3, -} - - -# ========================================================= -# Helpers -# ========================================================= def _f(value: Any) -> Optional[float]: try: @@ -71,86 +58,123 @@ return bool(value) -def _decision( - *, - action: str, - rule: str, - reason: str, - trigger_level: Optional[float] = None, - gate_reason: str = "", - data: Optional[Dict[str, Any]] = None, -) -> Dict[str, Any]: - return { - "action": action, - "rule": rule, +def _cfg_value(params: Dict[str, Any], *keys: str, default: Any, cast=float): + for key in keys: + if key in params and params.get(key) is not None: + try: + return cast(params.get(key)) + except Exception: + pass + return default + + +def _hold(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + payload = { + "action": "HOLD", + "rule": "HOLD", "reason": reason, - "trigger_level": trigger_level, - "gate_reason": gate_reason, + "trigger_level": None, + "gate_reason": "", "data": data or {}, - # új mezők a monitor/export felé - "decision_action": action, - "decision_rule_id": rule, - "decision_level": trigger_level, + "decision_action": "HOLD", + "decision_rule_id": "HOLD", + "decision_level": None, "decision_reason": reason, } - - -def _hold(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="HOLD", rule="HOLD", reason=reason, trigger_level=None, data=data) - - -def _no_trade(gate_reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision( - action="NO_TRADE", - rule="NO_TRADE", - reason=gate_reason, - trigger_level=None, - gate_reason=gate_reason, - data=data, - ) - - -def _buy(rule: str, level: float, reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="BUY", rule=rule, reason=reason, trigger_level=level, data=data) - - -def _sell(rule: str, level: float, reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - return _decision(action="SELL", rule=rule, reason=reason, trigger_level=level, data=data) - - -def _choose_sell(active_rules: list[Tuple[str, float]]) -> Tuple[str, float]: - # SELL: legmagasabb árszint nyer - # tie-break: RECOVERY > STANDARD > PANIC - return sorted(active_rules, key=lambda x: (x[1], SELL_PRIORITY.get(x[0], 0)), reverse=True)[0] - - -def _choose_buy(active_rules: list[Tuple[str, float]]) -> Tuple[str, float]: - # BUY: legalacsonyabb árszint nyer - # tie-break: RECOVERY > STANDARD > PANIC - return sorted(active_rules, key=lambda x: (x[1], -BUY_PRIORITY.get(x[0], 0)))[0] - - -# ========================================================= -# Normalization / compatibility layer -# ========================================================= + return payload + + +def _no_trade(reason: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + return _hold(reason, data or {}) + + +def _sell(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]: + payload = { + "action": "SELL", + "rule": rule_id, + "reason": reason, + "trigger_level": level, + "gate_reason": "", + "data": data, + "decision_action": "SELL", + "decision_rule_id": rule_id, + "decision_level": level, + "decision_reason": reason, + } + return payload + + +def _buy(rule_id: str, level: float, reason: str, data: Dict[str, Any]) -> Dict[str, Any]: + payload = { + "action": "BUY", + "rule": rule_id, + "reason": reason, + "trigger_level": level, + "gate_reason": "", + "data": data, + "decision_action": "BUY", + "decision_rule_id": rule_id, + "decision_level": level, ... [DIFF LEVÁGVA] további sorok: 840