feat(signal_v2-phase3a): config + state extensions for KIS data
- config.py: KIS_APP_KEY/SECRET/ACCOUNT/IS_VIRTUAL + V1_TOKEN_PATH env - state.py: PollState extended with minute_bars (deque) and asking_price - requirements.txt: websockets>=12 19 existing tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,3 +6,4 @@ python-dotenv>=1.0
|
|||||||
pytest>=8.0
|
pytest>=8.0
|
||||||
pytest-asyncio>=0.23
|
pytest-asyncio>=0.23
|
||||||
respx>=0.21
|
respx>=0.21
|
||||||
|
websockets>=12
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from pathlib import Path
|
|||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
# web-ai/.env 명시 로드 (signal_v2/config.py 의 parent.parent = web-ai/)
|
|
||||||
load_dotenv(Path(__file__).parent.parent / ".env")
|
load_dotenv(Path(__file__).parent.parent / ".env")
|
||||||
|
|
||||||
|
|
||||||
@@ -21,8 +20,20 @@ class Settings:
|
|||||||
db_path: Path = field(
|
db_path: Path = field(
|
||||||
default_factory=lambda: Path(__file__).parent / "data" / "signal_v2.db"
|
default_factory=lambda: Path(__file__).parent / "data" / "signal_v2.db"
|
||||||
)
|
)
|
||||||
|
# Phase 3a additions
|
||||||
|
kis_app_key: str = field(default_factory=lambda: os.getenv("KIS_APP_KEY", "").strip())
|
||||||
|
kis_app_secret: str = field(default_factory=lambda: os.getenv("KIS_APP_SECRET", "").strip())
|
||||||
|
kis_account: str = field(default_factory=lambda: os.getenv("KIS_ACCOUNT", "").strip())
|
||||||
|
kis_is_virtual: bool = field(
|
||||||
|
default_factory=lambda: os.getenv("KIS_IS_VIRTUAL", "true").lower() == "true"
|
||||||
|
)
|
||||||
|
v1_token_path: Path = field(
|
||||||
|
default_factory=lambda: Path(
|
||||||
|
os.getenv("V1_TOKEN_PATH",
|
||||||
|
str(Path(__file__).parent.parent / "signal_v1" / "data" / "kis_token.json"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_settings() -> Settings:
|
def get_settings() -> Settings:
|
||||||
"""매 호출 시 신선한 Settings (테스트 monkeypatch 호환)."""
|
|
||||||
return Settings()
|
return Settings()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""PollState — process-wide singleton."""
|
"""PollState — process-wide singleton."""
|
||||||
|
from collections import deque
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
|
||||||
@@ -7,9 +8,11 @@ class PollState:
|
|||||||
portfolio: dict | None = None
|
portfolio: dict | None = None
|
||||||
news_sentiment: dict | None = None
|
news_sentiment: dict | None = None
|
||||||
screener_preview: dict | None = None
|
screener_preview: dict | None = None
|
||||||
|
# Phase 3a additions
|
||||||
|
minute_bars: dict[str, deque] = field(default_factory=dict)
|
||||||
|
asking_price: dict[str, dict] = field(default_factory=dict)
|
||||||
last_updated: dict[str, str] = field(default_factory=dict)
|
last_updated: dict[str, str] = field(default_factory=dict)
|
||||||
fetch_errors: dict[str, int] = field(default_factory=dict)
|
fetch_errors: dict[str, int] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
# Process-wide singleton. Phase 3 imports: from signal_v2.state import state
|
|
||||||
state = PollState()
|
state = PollState()
|
||||||
|
|||||||
Reference in New Issue
Block a user