feat(config): BAT-028 M1 — max_active_slots per-instance TOML (dcy-020/REQ-060)
자산 중심 모드 게이트 + M 값. DaemonInstanceConfig/DaemonConfig 에 max_active_slots: Optional[int] 추가, from_toml 파싱(>0 검증), from_config 전파. 미설정(None) → legacy pool 모드. additive — 전체 375 passed, ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -143,6 +143,10 @@ class DaemonInstanceConfig:
|
|||||||
# Optional — absent keys fall back to KST / midnight defaults.
|
# Optional — absent keys fall back to KST / midnight defaults.
|
||||||
trading_timezone: str = "Asia/Seoul"
|
trading_timezone: str = "Asia/Seoul"
|
||||||
daily_preallocation_time: str = "00:00"
|
daily_preallocation_time: str = "00:00"
|
||||||
|
# dcy-020 / REQ-060 (BAT-028): max concurrent active (holding) slots, M.
|
||||||
|
# Presence is the asset-centric mode gate: set -> universe reconcile + FCFS/M
|
||||||
|
# admission; absent -> legacy pool model (preallocation + find_allocatable).
|
||||||
|
max_active_slots: Optional[int] = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_toml(path: str) -> "DaemonInstanceConfig":
|
def from_toml(path: str) -> "DaemonInstanceConfig":
|
||||||
@@ -155,11 +159,18 @@ class DaemonInstanceConfig:
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"instance TOML missing required 'instance_key': {path}"
|
f"instance TOML missing required 'instance_key': {path}"
|
||||||
)
|
)
|
||||||
|
raw_max = data.get("max_active_slots")
|
||||||
|
max_active = int(raw_max) if raw_max is not None else None
|
||||||
|
if max_active is not None and max_active <= 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"instance TOML 'max_active_slots' must be > 0, got {raw_max}: {path}"
|
||||||
|
)
|
||||||
return DaemonInstanceConfig(
|
return DaemonInstanceConfig(
|
||||||
instance_key=str(instance_key),
|
instance_key=str(instance_key),
|
||||||
portfolio_hub_token=str(data.get("portfolio_hub_token") or ""),
|
portfolio_hub_token=str(data.get("portfolio_hub_token") or ""),
|
||||||
trading_timezone=str(data.get("trading_timezone") or "Asia/Seoul"),
|
trading_timezone=str(data.get("trading_timezone") or "Asia/Seoul"),
|
||||||
daily_preallocation_time=str(data.get("daily_preallocation_time") or "00:00"),
|
daily_preallocation_time=str(data.get("daily_preallocation_time") or "00:00"),
|
||||||
|
max_active_slots=max_active,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -172,6 +183,9 @@ class DaemonConfig:
|
|||||||
# BAT-013 / REQ-049: instance identity for multi-instance queue naming.
|
# BAT-013 / REQ-049: instance identity for multi-instance queue naming.
|
||||||
# "default" keeps legacy literal queue names (backward-compat).
|
# "default" keeps legacy literal queue names (backward-compat).
|
||||||
instance_key: str = "default"
|
instance_key: str = "default"
|
||||||
|
# dcy-020 / REQ-060 (BAT-028): M (max concurrent active slots) + asset-centric
|
||||||
|
# mode gate. None -> legacy pool model.
|
||||||
|
max_active_slots: Optional[int] = None
|
||||||
kis: Optional[KISConfig] = None
|
kis: Optional[KISConfig] = None
|
||||||
# REQ-011: paper broker tuning (only consulted when broker == 'paper').
|
# REQ-011: paper broker tuning (only consulted when broker == 'paper').
|
||||||
paper: PaperBrokerConfig = PaperBrokerConfig()
|
paper: PaperBrokerConfig = PaperBrokerConfig()
|
||||||
@@ -316,4 +330,5 @@ class DaemonConfig:
|
|||||||
portfolio_hub=pf,
|
portfolio_hub=pf,
|
||||||
trading_timezone=inst.trading_timezone,
|
trading_timezone=inst.trading_timezone,
|
||||||
daily_preallocation_time=inst.daily_preallocation_time,
|
daily_preallocation_time=inst.daily_preallocation_time,
|
||||||
|
max_active_slots=inst.max_active_slots,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user