feat(execution): AccountOrderWorker로 매수·매도 주문 직렬화
전략별 tick/scan 매도 락 대신 계좌 단일 PriorityQueue로 place를 B-full 직렬화한다. 틱매도 only_code 필터와 inflight 중복 enqueue 방지로 REST 폭주를 줄인다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -70,6 +70,7 @@ from .database.db_manager import get_db
|
||||
from .execution.kis_client import KISClient
|
||||
from .execution.account_cash import AccountCashLedger
|
||||
from .execution.order_manager import OrderManager
|
||||
from .execution.order_worker import AccountOrderWorker
|
||||
from .network.condition_manager import ConditionSearchManager
|
||||
from .network.kiwoom_condition_manager import KiwoomConditionSearchManager
|
||||
from .network.ls_condition_manager import (
|
||||
@@ -189,6 +190,7 @@ class TradingOrchestrator:
|
||||
self.order_mgr = OrderManager(
|
||||
client=self.client, db=self.db, cash_ledger=self.cash_ledger,
|
||||
)
|
||||
self.order_worker = AccountOrderWorker(self.order_mgr)
|
||||
self.ws = WSManager(db=self.db, kis_client=self.market_client)
|
||||
# 해외(US) 실시간(지연)체결가 수신기 — 국내 WS와 분리된 별도 인스턴스(야간 가동).
|
||||
# permanent_subscriptions 테이블의 US 종목을 HDFSCNT0 로 구독. start()에서 기동.
|
||||
@@ -380,7 +382,7 @@ class TradingOrchestrator:
|
||||
if buy_price > 0 and px > 0:
|
||||
profit_pct = (px - buy_price) / buy_price * 100.0
|
||||
try:
|
||||
strat._submit_sell({
|
||||
strat._enqueue_sell({
|
||||
"code": code,
|
||||
"name": (row or {}).get("name") or h.get("name") or code,
|
||||
"qty": qty,
|
||||
@@ -389,7 +391,7 @@ class TradingOrchestrator:
|
||||
"buy_price": buy_price,
|
||||
"profit_pct": profit_pct,
|
||||
"reason": reason,
|
||||
})
|
||||
}, source="halt")
|
||||
except Exception as ex:
|
||||
logger.warning(
|
||||
"⚠️ [리스크버짓] %s %s 청산 실패: %s", sid_u, code, ex,
|
||||
@@ -723,6 +725,10 @@ class TradingOrchestrator:
|
||||
self._register_strategies()
|
||||
# 해외 WS 는 등록 전에 기동됨 → 여기서 US_MOMENTUM 에 핸들 주입
|
||||
self._attach_overseas_ws_to_strategies()
|
||||
for strat in self.strategies:
|
||||
self.order_worker.register_strategy(strat)
|
||||
strat.order_worker = self.order_worker
|
||||
self.order_worker.start()
|
||||
for strat in self.strategies:
|
||||
strat.start() # threading.Thread.start()
|
||||
logger.info("▶ 쓰레드 기동: %s", strat.name)
|
||||
@@ -2666,6 +2672,8 @@ class TradingOrchestrator:
|
||||
)
|
||||
if getattr(ns, "strategy_id", "") == "US_MOMENTUM" and self.overseas_ws:
|
||||
ns.overseas_ws = self.overseas_ws
|
||||
ns.order_worker = self.order_worker
|
||||
self.order_worker.register_strategy(ns)
|
||||
ns.start()
|
||||
new_list.append(ns)
|
||||
logger.info("🔁 전략 재기동: %s", ns.name)
|
||||
@@ -2734,6 +2742,10 @@ class TradingOrchestrator:
|
||||
def stop(self) -> None:
|
||||
for s in self.strategies:
|
||||
s.stop_loop()
|
||||
try:
|
||||
self.order_worker.stop()
|
||||
except Exception:
|
||||
pass
|
||||
for s in self.strategies:
|
||||
try:
|
||||
s.join(timeout=5)
|
||||
@@ -2802,6 +2814,13 @@ class TradingOrchestrator:
|
||||
|
||||
|
||||
def main() -> None:
|
||||
import faulthandler
|
||||
import signal
|
||||
faulthandler.enable()
|
||||
try:
|
||||
faulthandler.register(signal.SIGUSR1, all_threads=True, chain=False)
|
||||
except:
|
||||
pass
|
||||
orch = TradingOrchestrator()
|
||||
try:
|
||||
orch.start()
|
||||
|
||||
Reference in New Issue
Block a user