114 lines
4.7 KiB
Plaintext
114 lines
4.7 KiB
Plaintext
"""
|
|
Grid Trading Bot — config.
|
|
All secrets MUST come from environment (.env), never from defaults in code.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
# Load .env from project root (cwd or script dir) so all os.getenv() below
|
|
# see real values, not code defaults. Safe to call multiple times.
|
|
_ENV_PATH = Path(__file__).resolve().parent / ".env"
|
|
if _ENV_PATH.exists():
|
|
load_dotenv(_ENV_PATH, override=False)
|
|
else:
|
|
# fallback: cwd/.env (for 'python main.py' from project dir)
|
|
load_dotenv(override=False)
|
|
|
|
|
|
def _require(name: str) -> str:
|
|
"""Read required env var. Empty/None → raise (only when LIVE mode is on)."""
|
|
v = os.getenv(name, "").strip()
|
|
if not v:
|
|
raise RuntimeError(
|
|
f"Environment variable {name!r} is empty. "
|
|
f"Set it in .env (see .env.example). Aborting."
|
|
)
|
|
return v
|
|
|
|
|
|
def _opt(name: str, default: str = "") -> str:
|
|
return os.getenv(name, default).strip()
|
|
|
|
|
|
# === Tradernet API credentials ===
|
|
# LIVE: ключи обязательны → main.py вызовет _require().
|
|
# DEMO: ключи могут быть пустыми (например, dry-run без сети).
|
|
TRADERNET_PUBLIC_KEY = os.getenv("TRADERNET_PUBLIC_KEY", "")
|
|
TRADERNET_PRIVATE_KEY = os.getenv("TRADERNET_PRIVATE_KEY", "")
|
|
TRADERNET_LOGIN = os.getenv("TRADERNET_LOGIN", "")
|
|
TRADERNET_PASSWORD = os.getenv("TRADERNET_PASSWORD", "")
|
|
TRADERNET_BASE_URL = os.getenv("TRADERNET_BASE_URL", "https://tradernet.by")
|
|
|
|
|
|
def require_tradernet_keys() -> None:
|
|
"""Вызывайте из main.py в начале LIVE-режима.
|
|
Падает, если хотя бы один ключ пустой."""
|
|
_require("TRADERNET_PUBLIC_KEY")
|
|
_require("TRADERNET_PRIVATE_KEY")
|
|
|
|
|
|
# === Trading settings ===
|
|
SYMBOL = os.getenv("SYMBOL", "BTC-USDT.IMEX")
|
|
QUOTE = os.getenv("QUOTE", "USDT")
|
|
BASE = os.getenv("BASE", "BTC")
|
|
|
|
# === Grid settings (default 10 levels = 20 orders total) ===
|
|
GRID_LEVELS = int(os.getenv("GRID_LEVELS", "10"))
|
|
GRID_STEP_PERCENT = float(os.getenv("GRID_STEP_PERCENT", "0.005"))
|
|
GRID_TAKE_PROFIT_PERCENT = float(os.getenv("GRID_TAKE_PROFIT_PERCENT", "0.5"))
|
|
GRID_RENEW_THRESHOLD = int(os.getenv("GRID_RENEW_THRESHOLD", "3"))
|
|
GRID_PRICE_OFFSET = float(os.getenv("GRID_PRICE_OFFSET", "0"))
|
|
|
|
# === Stale grid recovery ===
|
|
GRID_STALE_DROP_PERCENT = float(os.getenv("GRID_STALE_DROP_PERCENT", "5.0"))
|
|
|
|
# === State ===
|
|
STATE_DIR = Path(os.getenv("STATE_DIR", str(Path.home() / ".openclaw")))
|
|
STATE_FILE = str(STATE_DIR / "grid-state.json")
|
|
|
|
# === Public server URL ===
|
|
SERVER_URL = os.getenv("SERVER_URL", "https://gridbot.kolp.pro")
|
|
|
|
# === Demo / Live ===
|
|
DEMO_MODE = os.getenv("DEMO_MODE", "true").lower() in ("true", "1", "yes")
|
|
DEMO_START_BALANCE = float(os.getenv("DEMO_START_BALANCE", "100"))
|
|
LIVE_TRADING_DRY_RUN = os.getenv("LIVE_TRADING_DRY_RUN", "true").lower() in ("true", "1", "yes")
|
|
|
|
# === Telegram ===
|
|
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
|
|
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID", "")
|
|
|
|
# === Flask ===
|
|
HOST = os.getenv("HOST", "0.0.0.0")
|
|
PORT = int(os.getenv("PORT", "5555"))
|
|
DEBUG = os.getenv("DEBUG", "false").lower() in ("true", "1", "yes")
|
|
|
|
# === Web auth (Basic Auth для дашборда /api/*) ===
|
|
# ВАЖНО: обязательно сменить дефолты в .env. Сейчас — deprecation-дефолты,
|
|
# которые выдаются на 1 запуск, если .env не заполнен.
|
|
WEB_USERNAME = os.getenv("WEB_USERNAME", "admin")
|
|
WEB_PASSWORD = os.getenv("WEB_PASSWORD", "changeme")
|
|
|
|
# === Log ===
|
|
LOG_FILE = "margin-bot.log"
|
|
|
|
# === Kronos advisor ===
|
|
# KRONOS_ENABLED: подмешивать kronos_advice.json в параметры сетки
|
|
# KRONOS_LIVE_ENABLED: только в LIVE — реально применять советы к ордерам
|
|
# KRONOS_MODEL: "kronos-mini" | "kronos-small" (mini быстрее, small точнее)
|
|
# KRONOS_TF_MIN: таймфрейм свечей (1, 5, 15, 60, 1440)
|
|
# KRONOS_LOOKBACK: сколько свечей подавать в модель (≤ 512 для small/mini)
|
|
# KRONOS_PRED_LEN: сколько свечей прогнозировать
|
|
# KRONOS_MIN_CONFIDENCE: ниже этого — fallback на константы из .env
|
|
KRONOS_ENABLED = os.getenv("KRONOS_ENABLED", "false").lower() in ("true", "1", "yes")
|
|
KRONOS_LIVE_ENABLED = os.getenv("KRONOS_LIVE_ENABLED", "false").lower() in ("true", "1", "yes")
|
|
KRONOS_MODEL = os.getenv("KRONOS_MODEL", "kronos-mini")
|
|
KRONOS_TF_MIN = int(os.getenv("KRONOS_TF_MIN", "60"))
|
|
KRONOS_LOOKBACK = int(os.getenv("KRONOS_LOOKBACK", "400"))
|
|
KRONOS_PRED_LEN = int(os.getenv("KRONOS_PRED_LEN", "24"))
|
|
KRONOS_MIN_CONFIDENCE = float(os.getenv("KRONOS_MIN_CONFIDENCE", "0.4"))
|
|
KRONOS_ADVICE_FILE = os.getenv("KRONOS_ADVICE_FILE", str(STATE_DIR / "kronos_advice.json"))
|