Ezen az oldalon egy konkrét fájl aktuális állapotát tudod megnézni.
/opt/bots/saturnus/freqtrade/user_data/strategies/SaturnusUiStateStrategy.pyfrom __future__ import annotations
from freqtrade.strategy import IStrategy
from datetime import datetime, timezone
from pathlib import Path
import logging
import json
# Opcionális, de erősen ajánlott: ha van nyitott trade Freqtrade-ben,
# akkor NE küldjünk új BUY jelet akkor sem, ha az UI state még nem frissült.
try:
from freqtrade.persistence import Trade
except Exception:
Trade = None # fallback
logger = logging.getLogger(__name__)
# A Flask UI ide írja az állapotot
STATE_PATH = Path("/opt/bots/saturnus/app/state.json")
# --- 6 szabály paraméterei (a leírásod szerint) ---
SELL_PEAK_DD_PCT = 0.03 # 1) 3% esés a csúcshoz képest
SELL_PROFIT_TARGET = 0.03 # 2) 3% profitot nem érte el (peak < buy*(1+0.03))
SELL_FALLBACK_PCT = 0.001 # de visszaesik 100,1%-ra (buy*1.001)
SELL_PANIC_PCT = 0.01 # 3) vételi ár 99%-ára csökken (panic sell)
BUY_REBOUND_PCT = 0.03 # 4) eladás után 3% emelkedés a mélyponthoz képest
BUY_RECOVER_PCT = 0.999 # 5) enyhe csökkenés után eléri a 99,9%-ot (sell*0.999)
BUY_IMMEDIATE_PCT = 1.01 # 6) azonnali emelkedés 101%-ra (sell*1.01)
STATE_MAX_AGE_SEC = 180
# Szabály-azonosítók magyar megnevezéssel (UI-hoz / trade taghez)
_RULES_HU = {
1: "ELADÁS #1 – 3% esés a csúcshoz képest",
2: "ELADÁS #2 – nem volt meg a +3%, visszaesett 100,1%-ra",
3: "ELADÁS #3 – pánik: vételi ár 99%-ára csökkent",
4: "VÉTEL #4 – eladás után +3% emelkedés a mélyponthoz képest",
5: "VÉTEL #5 – enyhe csökkenés után eléri a 99,9%-ot",
6: "VÉTEL #6 – azonnali emelkedés 101%-ra",
}
# ha ennél régebbi a state, nem kereskedünk
def _parse_utc(ts) -> datetime | None:
"""
Elfogad:
- ISO string (pl. 2026-01-03T20:37:01Z)
- "Z" végződés is ok
- "AUTO" / üres / hibás -> None
"""
if not ts or not isinstance(ts, str):
return None
if ts.strip().upper() == "AUTO":
return None
try:
s = ts.strip().replace("Z", "+00:00")
dt = datetime.fromisoformat(s)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
return dt.astimezone(timezone.utc)
except Exception:
return None
def _read_ui_state() -> dict:
try:
if STATE_PATH.exists():
return json.loads(STATE_PATH.read_text(encoding="utf-8"))
except Exception as e:
logger.error("STATE READ ERROR: %s", e)
return {}
def _num(v, default=None):
try:
if v is None:
return default
return float(v)
except Exception:
return default
def _is_true(v) -> bool:
if v is True:
return True
if isinstance(v, str) and v.strip().lower() in ("1", "true", "yes", "y", "on"):
return True
if isinstance(v, (int, float)) and v != 0:
return True
return False
def _has_open_trade_for_pair(pair: str) -> bool:
"""
Ha Freqtrade-ben már van nyitott trade erre a párra, akkor tekintsük úgy,
hogy poziban vagyunk (BUY tiltás).
"""
if not pair:
return False
if Trade is None:
return False
try:
for t in Trade.get_open_trades():
if getattr(t, "pair", None) == pair:
return True
except Exception:
return False
return False
class SaturnusUiStateStrategy(IStrategy):
timeframe = "1m"
can_short = False
# dry-run / teszt paraméterek (nem a 6 szabály része)
minimal_roi = {"0": 0.01}
stoploss = -0.10
startup_candle_count = 10