90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
"""
|
|
Configuration schema for the opportunity engine (oe_em).
|
|
|
|
Parsed from config.yaml into OeEmSettings. Controls logging, signal
|
|
thresholds, the fee discount flag, symbol subscription, and the socket
|
|
path to the executor.
|
|
"""
|
|
import asyncio
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
import yaml
|
|
from pydantic import BaseModel, Field
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
|
class OeEmSettings(BaseModel):
|
|
"""Settings that control oe_em's runtime behaviour."""
|
|
|
|
fh_ob_url: str = Field(
|
|
default="http://127.0.0.1:8000",
|
|
description="REST URL of fh_ob server",
|
|
)
|
|
socket_path: Path = Field(
|
|
default=Path("/tmp/fh_ob.sock"),
|
|
description="Unix domain socket path for fh_ob",
|
|
)
|
|
log_level: str = Field(default="INFO", description="Logging level")
|
|
log_file: Path = Field(
|
|
default=Path("/tmp/oe_em.log"),
|
|
description="Path to log file. Logs are written here in addition to stdout.",
|
|
)
|
|
signal_threshold_bps: float = Field(
|
|
default=0.2,
|
|
description="Minimum net return in basis points to fire a signal",
|
|
)
|
|
opportunity_log_path: Path = Field(
|
|
default=Path("/tmp/opportunities.log"),
|
|
description="Path to log detected opportunities",
|
|
)
|
|
stats_interval_seconds: float = Field(
|
|
default=60.0,
|
|
description="Seconds between stats log lines. 0 to disable.",
|
|
)
|
|
cooldown_seconds: float = Field(
|
|
default=0.0,
|
|
description="Deprecated — use executor's in-flight blocking instead. "
|
|
"Kept here for operational flexibility; set to 0.",
|
|
)
|
|
excluded_currencies: list[str] = Field(
|
|
default_factory=list,
|
|
description="Currencies to exclude from triangle enumeration",
|
|
)
|
|
hold_currencies: list[str] = Field(
|
|
default=["USDT"],
|
|
description="Currencies held as capital. Only triangles starting and ending in one of these are evaluated.",
|
|
)
|
|
kcs_discount_active: bool = Field(
|
|
default=False,
|
|
description="If true, all taker fees are multiplied by 0.8 (KCS 20% fee discount)",
|
|
)
|
|
executor_socket_path: Path = Field(
|
|
default=Path("/tmp/executor.sock"),
|
|
description="Unix domain socket path for executor",
|
|
)
|
|
send_signals: bool = Field(
|
|
default=False,
|
|
description="If true, emit signals to executor socket when opportunities are found",
|
|
)
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Top-level settings parsed from config.yaml."""
|
|
|
|
oe_em: OeEmSettings = Field(default_factory=OeEmSettings)
|
|
fh_ob_url: Optional[str] = None
|
|
|
|
@classmethod
|
|
async def from_yaml(cls, path: Path) -> "Settings":
|
|
"""Load settings from a YAML file."""
|
|
loop = asyncio.get_running_loop()
|
|
|
|
def _read() -> dict:
|
|
with open(path) as f:
|
|
return yaml.safe_load(f)
|
|
|
|
data = await loop.run_in_executor(None, _read)
|
|
return cls(**data)
|
|
|
|
model_config = {"env_prefix": "TRIArb_", "extra": "ignore"} |