triangular_arbitrage_bot/common/config.py

65 lines
2.1 KiB
Python

import asyncio
from pathlib import Path
from typing import Optional
import yaml
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings
class FHobSettings(BaseModel):
symbols: list[str] = Field(
default_factory=list,
description="Trading pairs to subscribe to. Empty = no subscriptions. oe_em adds pairs via REST.",
)
log_level: str = Field(default="INFO", description="Logging level")
log_file: Path = Field(
default=Path("/tmp/fh_ob.log"),
description="Path to log file. Logs are written here in addition to stdout.",
)
socket_path: Path = Field(
default=Path("/tmp/fh_ob.sock"),
description="Unix domain socket path for OE+EM",
)
rest_host: str = Field(default="0.0.0.0", description="FastAPI debug host")
rest_port: int = Field(default=8000, description="FastAPI debug port")
ws_url: str = Field(
default="wss://ws-api-spot.kucoin.com",
description="KuCoin WebSocket endpoint",
)
token_url: str = Field(
default="https://api.kucoin.com/api/v1/bullet-public",
description="KuCoin public token endpoint",
)
reconnect_base_delay: float = Field(
default=1.0,
description="Base delay for reconnect exponential backoff (seconds)",
)
reconnect_max_delay: float = Field(
default=60.0,
description="Max delay for reconnect exponential backoff (seconds)",
)
heartbeat_interval: float = Field(
default=18.0,
description="WS ping interval (seconds) - KuCoin uses 18s",
)
class Settings(BaseSettings):
fh_ob: FHobSettings = Field(default_factory=FHobSettings)
@classmethod
async def from_yaml(cls, path: Path) -> "Settings":
loop = asyncio.get_running_loop()
def _read() -> dict:
with open(path) as f:
return yaml.safe_load(f) or {}
data = await loop.run_in_executor(None, _read)
fh_ob_data = data.get("fh_ob", {})
if fh_ob_data.get("symbols") is None:
fh_ob_data["symbols"] = []
return cls(**data)
model_config = {"env_prefix": "TRIARB_", "extra": "ignore"}