Skip to content

Commit 1091549

Browse files
authored
Merge pull request #421 from easygap/docs/mdd-hysteresis-guide
docs: MDD halt 히스테리시스 동작을 PROJECT_GUIDE에 반영
2 parents a24fbc5 + 9991a87 commit 1091549

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

docs/PROJECT_GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ quant_trader/
272272
| **indicator_engine.py** | pandas-ta로 RSI, MACD, 볼린저, MA, 스토캐스틱, ADX, ATR, OBV, volume_ratio. `calculate_all(df)`로 지표 컬럼 추가. |
273273
| **signal_generator.py** | `strategies.yaml` 스코어링 가중치로 점수 합산 → BUY/SELL/HOLD. `generate(df)`, `get_latest_signal(df)`. **`collinearity_mode`**: `max_per_direction`(방향별 최대 1개) 또는 `representative_only`(3그룹 대표 1개씩=MACD+볼린저+거래량만 사용, 권장). 초기화 시 가격 모멘텀 그룹 다중공선성 경고 자동 출력. |
274274
| **risk_manager.py** | 포지션 사이징(1% 룰), `check_diversification`(**업종 비중 포함**: `max_sector_ratio`, FDR/KRX KIND 업종 매핑), `check_recent_performance`, 손절/익절/트레일링, MDD·일일 손실 한도 계산. `calculate_transaction_costs`. |
275-
| **order_executor.py** | `trading.mode`: paper면 DB만, live면 KIS API. 거래 시간·블랙스완 쿨다운·**실적 발표일 필터**(`skip_earnings_days`) 검사, 재시도(지수 백오프+지터). PositionLock, OrderGuard·KIS 미체결 조회. `max_monthly_roundtrips`로 종목·모드·계좌별 월간 신규 BUY 횟수를 운영 주문에서도 제한하고, `drawdown.max_portfolio_mdd`/`max_daily_loss`에 닿으면 신규 BUY만 fail-closed 차단한다. live 손실 한도 확인에서 KIS 잔고가 확인되지 않으면 DB fallback 평가금액으로 신규 BUY를 판단하지 않고 차단한다. 시장 국면 필터가 `allow_buys=false`를 반환하면 직접 executor BUY 호출도 주문 전 중단한다. SELL/exit는 손실 축소 경로라 월간 cap·손실 한도와 무관하게 계속 허용한다. live 주문 전 미체결 조회 실패는 `live_unfilled_check.checked=False`로 fail-closed 차단한다. live 주문 ACK 뒤 체결가·체결수량 확인이 안 되거나 부분체결이면 `ACKED`/`PARTIAL_FILLED` pending으로 `order_records`에 저장하고 DB 거래·포지션 반영을 보류한다. `SUBMITTED`/`ACKED`/`PARTIAL_FILLED` 상태가 남아 있으면 OrderGuard TTL이 지나도 같은 종목 신규 주문을 차단한다. 이때 반환값의 `success=False`는 브로커 주문 없음이 아니라 reconcile 필요 상태다. **Dead-letter 큐**: 모든 재시도 실패 시 `FailedOrder` 테이블에 영구 저장. |
275+
| **order_executor.py** | `trading.mode`: paper면 DB만, live면 KIS API. 거래 시간·블랙스완 쿨다운·**실적 발표일 필터**(`skip_earnings_days`) 검사, 재시도(지수 백오프+지터). PositionLock, OrderGuard·KIS 미체결 조회. `max_monthly_roundtrips`로 종목·모드·계좌별 월간 신규 BUY 횟수를 운영 주문에서도 제한하고, `drawdown.max_portfolio_mdd`/`max_daily_loss`에 닿으면 신규 BUY만 fail-closed 차단한다. MDD 한도 돌파 후에는 **히스테리시스**(RiskManager.check_mdd의 `_is_halted`)가 한도의 절반 아래로 회복할 때까지 신규 BUY 차단을 유지한다 — 한도 경계 깜빡 회복 시 재진입→재돌파 반복 방지(상시 스케줄러에서 누적 동작, 1회성 CLI는 정적 체크와 동일). live 손실 한도 확인에서 KIS 잔고가 확인되지 않으면 DB fallback 평가금액으로 신규 BUY를 판단하지 않고 차단한다. 시장 국면 필터가 `allow_buys=false`를 반환하면 직접 executor BUY 호출도 주문 전 중단한다. SELL/exit는 손실 축소 경로라 월간 cap·손실 한도와 무관하게 계속 허용한다. live 주문 전 미체결 조회 실패는 `live_unfilled_check.checked=False`로 fail-closed 차단한다. live 주문 ACK 뒤 체결가·체결수량 확인이 안 되거나 부분체결이면 `ACKED`/`PARTIAL_FILLED` pending으로 `order_records`에 저장하고 DB 거래·포지션 반영을 보류한다. `SUBMITTED`/`ACKED`/`PARTIAL_FILLED` 상태가 남아 있으면 OrderGuard TTL이 지나도 같은 종목 신규 주문을 차단한다. 이때 반환값의 `success=False`는 브로커 주문 없음이 아니라 reconcile 필요 상태다. **Dead-letter 큐**: 모든 재시도 실패 시 `FailedOrder` 테이블에 영구 저장. |
276276
| **portfolio_manager.py** | 보유 포지션·잔고·수익률. `sync_with_broker()`로 KIS 잔고↔DB 크로스체크. live `get_portfolio_summary()`는 조회용 DB fallback 여부를 `broker_balance_ok/source/error`로 표시하고, 주문 sizing에 쓰는 `get_current_capital()`/`get_available_cash()`는 KIS 잔고 미확인 시 예외로 fail-closed 처리한다. 자동보정 시 KIS 기준 수량을 절대값으로 반영하고, 복구 포지션에는 손절·익절·트레일링 스탑을 재생성한다. |
277277
| **basket_rebalancer.py** | 바스켓 리밸런싱 엔진. `baskets.yaml`에서 바스켓 로드. `get_target_weights()`(신호 가중 지원), `get_current_weights()`, `calculate_drift()`, `should_rebalance()`(drift/weekly/monthly 트리거), `plan_rebalance()`(SELL→BUY 순서, max_turnover 제한), `execute()`(dry_run 지원). paper BUY 실행은 `PortfolioManager.get_current_capital()`/`get_available_cash()`로 자본과 현금을 조회한 뒤 `OrderExecutor.execute_buy_quantity()`에 넘긴다. live 실행은 `basket_rebalance:<basket>` 승인 단위가 account_key와 주문 strategy에 동일하게 전달되고, KIS↔DB 포지션 동기화가 성공해야 주문 실행부에 도달한다. CLI와 스케줄러 자동 체크 모두 같은 승인 단위를 사용한다. `get_status_report()`로 현황 리포트 생성. |
278278
| **scheduler.py** | 실전 무한 루프. 장전/장중/장마감. **시장 국면 필터**(단계적: bearish→매수 중단, caution→사이징 축소). 장중 10분 간격. 루프 10분 초과 시 다음 사이클 스킵. 장전 단계에서 **바스켓 리밸런싱 자동 체크** (`_run_basket_rebalance_check`). live에서는 바스켓별 `basket_rebalance:<basket>` readiness gate와 KIS↔DB 동기화를 통과한 뒤에만 주문 계획과 실행으로 넘어간다. live 신규 진입 중 `requires_reconcile` 또는 `order_pending` 결과가 나오면 남은 BUY 후보와 같은 루프 재스캔을 중단하고, 다음 성공적인 KIS↔DB 동기화 전까지 미확정 체결분을 무시한 추가 진입을 막는다. **전략 레지스트리** 기반 `_get_strategy()`. |

0 commit comments

Comments
 (0)