Harden scheduler and stale breakout reentry
This commit is contained in:
@@ -57,7 +57,7 @@
|
||||
|
||||
### 5. 시스템 이슈
|
||||
|
||||
- **15:10 봇 재시작 감지**: 로그에서 결산(15:10:01) 직후 봇이 재초기화됨(15:10:04). 이후 KIS API "초당 거래건수 초과" 오류 발생(15:10:04). 결산 완료 후 자동 또는 수동 재시작이 있었던 것으로 보임. 정산 직후 재시작 시 KIS 토큰 재사용 정상 동작 확인.
|
||||
- **15:10 봇 재시작 감지(수정 완료)**: 로그에서 결산(15:10:01) 직후 watchdog이 종료된 봇을 재시작함(15:10:04). 이후 KIS API "초당 거래건수 초과" 오류 발생. 원인은 watchdog 감시 조건이 `15:10`을 포함한 것이며, `scripts/_watchdog.py`, `scripts/run_watchdog.ps1`, `scripts/setup_scheduler.ps1`을 수정해 watchdog을 09:00-15:05로 제한했다.
|
||||
- **점심 섹터 변경**: 오전 어보이드(건설, 금융) → 점심 어보이드(기계, 운수창고, 2차전지). 흥아해운(해운업/운수창고)은 오전 진입이므로 룰 위반 없음. 그러나 점심 이후 해당 종목 재진입 시 차단이 정상 작동했는지 확인 필요.
|
||||
|
||||
---
|
||||
@@ -90,5 +90,5 @@
|
||||
## 다음 체크 포인트
|
||||
|
||||
- 대한광통신 형태(고변동성 즉시 SL) 재발 시 진입 슬리피지/변동성 필터 강화 검토
|
||||
- 15:10 봇 재시작 원인 확인 및 필요 시 결산 후 자동 재시작 억제
|
||||
- 2026-06-10 15:10에 watchdog이 결산 직후 봇을 재시작하지 않는지 확인
|
||||
- KIS API 초당 거래건수 초과 오류 빈도 모니터링
|
||||
|
||||
@@ -73,15 +73,16 @@ TP 청산 비율 66.7%, FORCE/TIME 0%. 강제청산 없이 깔끔하게 마감.
|
||||
## AI 필터 품질
|
||||
|
||||
- 오늘 전 거래 `ai_boosted = 0`. AI 모델은 관찰 모드만.
|
||||
- 학습 데이터 부족(53 봇 거래 행)으로 AI 판단 의존은 아직 부적절.
|
||||
- 학습 데이터는 아직 대부분 외부 분봉 기반 후보 행이며, 실제 봇 거래 표본은 부족해 AI 판단 의존은 아직 부적절.
|
||||
- 오후 신호 진단: 목표가 미달 종목 다수, SL 차단 2종, TP 재진입 차단 2종 — 필터링 정상.
|
||||
|
||||
## 실행 품질
|
||||
|
||||
- 제로 가격 행 없음, 가격 불일치 없음.
|
||||
- 라이콤/광전자 진입 후 초단시간 TP 달성 — 변동성 돌파 로직 정상.
|
||||
- KIS 율한도 초과 경고 2회 (13:39, 13:42): `ENTRY price retry 1/4` 로그 확인.
|
||||
- KIS 율한도 초과 경고가 장중 여러 차례 발생: `ENTRY price retry 1/4` 로그 확인.
|
||||
- retry 후 정상 재개. 치명적 장애 아님.
|
||||
- 장 마감 후 KISClient 기본 조회 간격 확대 및 rate-limit 전역 쿨다운 추가.
|
||||
- 14:00 이후 ENTRY 차단 정상 동작 확인.
|
||||
- 14:50 강제 청산 시작 → 완료 정상 (미청산 포지션 없음).
|
||||
- 결산 중복 처리 방어 정상: `결산 이미 처리됨: 2026-06-10` 로그 확인.
|
||||
@@ -89,9 +90,10 @@ TP 청산 비율 66.7%, FORCE/TIME 0%. 강제청산 없이 깔끔하게 마감.
|
||||
## 운영 이슈
|
||||
|
||||
### KIS 율한도 초과 (경미)
|
||||
- 13:39, 13:42 가격 조회 시 `초당 거래건수를 초과하였습니다` 2회 발생.
|
||||
- 가격 조회 시 `초당 거래건수를 초과하였습니다`가 여러 차례 발생.
|
||||
- 현행 retry 로직으로 자동 복구됨.
|
||||
- 오후 감시 루프에서 다수 종목 동시 조회 시 빈도 집중 가능성. 지속 모니터링 필요.
|
||||
- 오후 감시 루프에서 다수 종목 순차 조회 시 빈도 집중 가능성.
|
||||
- 2026-06-10 장 마감 후 `app/execution/kis_client.py`에서 기본 조회 간격을 보수화하고 rate-limit 응답 후 전역 쿨다운을 추가함.
|
||||
|
||||
## 30일 누적 지표 (2거래일)
|
||||
|
||||
@@ -117,6 +119,6 @@ TP 청산 비율 66.7%, FORCE/TIME 0%. 강제청산 없이 깔끔하게 마감.
|
||||
|
||||
## 다음 체크사항
|
||||
|
||||
- KIS 율한도 초과 빈도가 주 2회 이상 지속되면 조회 간격 확대 검토.
|
||||
- 2026-06-11에 KIS 율한도 초과 빈도가 줄었는지 확인.
|
||||
- 대우건설 80분 보유 후 SL: `MAX_HOLD_MIN=90` 경계에 근접. 현행 유지.
|
||||
- 운영 데이터 누적 지속. 30거래일 도달 시 라이브 준비 재점검.
|
||||
|
||||
@@ -120,20 +120,22 @@ TP 청산 비율 66.7%, SL 비율 11.1%. 강제청산 없음.
|
||||
- KIS 타임아웃: 라이콤(388790) 12:30 2회 재시도, 현대건설(000720) 12:57 1회 재시도.
|
||||
모두 정상 복구. 실거래 영향 없음.
|
||||
|
||||
## 구조 이슈 — 삼성전자 진입가 > 목표가
|
||||
## 구조 이슈 — 삼성전자 TIME 후 동일 신호 재진입
|
||||
|
||||
| 항목 | 1차 진입 | 2차 진입 |
|
||||
|---|---|---|
|
||||
| 진입가 | 340,000 | 338,500 |
|
||||
| 목표가(TP) | 334,000 | 334,000 |
|
||||
| 돌파 목표가 | 334,000 | 334,000 |
|
||||
| 차이 | **-6,000원** | **-4,500원** |
|
||||
| 청산 | TIME | TIME |
|
||||
|
||||
- 아침 변동성 돌파 목표가는 전일 종가 기준 계산. 삼성전자가 개장 시 갭업하여
|
||||
목표가(334,000)를 이미 초과한 가격(340,000)에 진입.
|
||||
- 이 구조에서는 TP 달성이 원천 불가. 결국 TIME 또는 SL만 가능.
|
||||
- 현행 코드에 `current_price < tp_target` 진입 차단 로직 없음.
|
||||
- **별도 제안서 작성** (`reports/proposals/2026-06-15_strategy_proposal.md`).
|
||||
- 코드상 `목표가`는 익절가가 아니라 변동성 돌파 진입 기준가.
|
||||
따라서 `현재가 >= 목표가` 자체는 정상 진입 조건.
|
||||
- 실제 문제는 1차 `TIME` 청산 후에도 가격이 목표가 위에 머물러,
|
||||
60분 쿨다운 종료만으로 같은 돌파 신호를 재사용해 2차 진입한 점.
|
||||
- **적용 완료**: `TIME/FORCE` 청산 후에는 목표가 아래로 한 번 내려왔다가
|
||||
다시 돌파해야 재진입 가능하도록 `재돌파 대기` 필터 추가.
|
||||
- 적용 문서: `reports/proposals/2026-06-15_strategy_proposal.md`.
|
||||
|
||||
## 30일 누적 지표 (5거래일)
|
||||
|
||||
@@ -151,7 +153,7 @@ TP 청산 비율 66.7%, SL 비율 11.1%. 강제청산 없음.
|
||||
|
||||
## 다음 체크사항
|
||||
|
||||
- `진입가 > 목표가` 필터 제안서 검토 및 수동 승인 여부 결정.
|
||||
- `TIME/FORCE` 후 재돌파 대기 필터 내일 로그에서 정상 차단 여부 확인.
|
||||
- AI 부스트 누적 손익 별도 집계 시작 권장.
|
||||
- 에이팩트 대량 포지션 사이징(193주) — 리스크 대비 포지션 계산 재확인.
|
||||
- 운영 데이터 누적 지속. 30거래일 도달 시 라이브 준비 재점검.
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
# Implementation Log
|
||||
|
||||
## 2026-06-10
|
||||
|
||||
- Enabled wake-from-sleep behavior for Scheduler tasks:
|
||||
- `scripts/setup_scheduler.ps1` now registers stock tasks with `WakeToRun`.
|
||||
- Re-registered tasks and verified `WakeToRun=True` and `StartWhenAvailable=True`.
|
||||
- Hardened KIS request throttling:
|
||||
- Mock request spacing default: 1.7s.
|
||||
- Real request spacing default: 0.35s, rate limit default: 3/sec.
|
||||
- Added local `.env` override support for request spacing/rate limits.
|
||||
- Added global cooldown after rate-limit responses.
|
||||
- Updated the 2026-06-10 daily report to reflect repeated KIS rate-limit retries.
|
||||
|
||||
## 2026-06-09
|
||||
|
||||
- Re-registered all Windows Scheduler tasks from the live project path:
|
||||
- `C:\Users\whdwo\Desktop\coding\stockbot_v3`
|
||||
- Verified every task action script exists at that path.
|
||||
- Fixed watchdog end-of-day behavior:
|
||||
- `StockBot_Watchdog` now runs 09:00-15:05 every 5 minutes.
|
||||
- `scripts/_watchdog.py` excludes 15:10 so normal daily settlement shutdown is not restarted.
|
||||
- `scripts/run_watchdog.ps1` skips after 15:09:59.
|
||||
- Hardened target calculation:
|
||||
- Targets are cleared before recalculation.
|
||||
- `open=0` is ignored before market open.
|
||||
- Delayed restarts after 08:50 recalculate targets immediately.
|
||||
- Updated operational docs and the 2026-06-09 daily report.
|
||||
|
||||
## 2026-05-28
|
||||
|
||||
- Applied the approved 2026-05-28 strategy update:
|
||||
@@ -120,3 +147,18 @@ Open risks:
|
||||
- Verification:
|
||||
- Python compile check passed.
|
||||
- Runtime import confirmed `ENTRY_START == "09:15"`.
|
||||
|
||||
## 2026-06-15
|
||||
|
||||
- Applied a stale breakout re-entry guard after reviewing the Samsung Electronics `TIME` re-entry.
|
||||
- Changed `app/strategy/volatility_breakout.py`:
|
||||
- `TIME` and `FORCE` final exits now mark the ticker as requiring a fresh breakout.
|
||||
- While that marker is active, a ticker is blocked with `재돌파 대기` if it remains above the same volatility breakout target.
|
||||
- The marker clears only after price moves back below the target, allowing a later fresh breakout entry.
|
||||
- Rationale:
|
||||
- The existing `current_price >= target` condition is the normal volatility breakout entry rule.
|
||||
- The bug was reusing a still-active same-day breakout signal after `TIME/FORCE` cooldown, not the first breakout itself.
|
||||
- This would have blocked the 2026-06-15 Samsung Electronics second entry after the first `TIME` exit.
|
||||
- Updated docs:
|
||||
- `reports/daily/2026-06-15.md`
|
||||
- `reports/proposals/2026-06-15_strategy_proposal.md`
|
||||
|
||||
@@ -2,39 +2,44 @@
|
||||
|
||||
## 요약
|
||||
|
||||
진입 시점에 현재가가 목표가(TP)를 이미 초과한 경우 진입을 차단하는 필터 추가.
|
||||
`TIME/FORCE` 청산 후에는 같은 당일 돌파 신호를 그대로 재사용하지 않고,
|
||||
목표가 아래로 한 번 식었다가 다시 돌파할 때만 재진입하도록 필터 추가.
|
||||
|
||||
**수동 승인 필수.**
|
||||
**적용 완료:** 2026-06-15
|
||||
|
||||
---
|
||||
|
||||
## 관찰된 문제
|
||||
|
||||
오늘(2026-06-15) 삼성전자(005930)가 두 차례 진입됐으나 두 번 모두 목표가(334,000)가
|
||||
진입가(340,000 / 338,500)보다 낮았다.
|
||||
오늘(2026-06-15) 삼성전자(005930)가 두 차례 진입됐다. 1차는 09:20 돌파 진입이었고,
|
||||
10:51 `TIME` 청산 후 60분 쿨다운이 끝난 11:51에 다시 진입됐다.
|
||||
|
||||
| 진입 | 진입가 | 목표가(TP) | 차이 | 결과 |
|
||||
|---|---|---|---|---|
|
||||
| 1차 09:20 | 340,000 | 334,000 | -6,000 | TIME -21,681원 |
|
||||
| 2차 11:51 | 338,500 | 334,000 | -4,500 | TIME -1,422원 |
|
||||
|
||||
원인: 변동성 돌파 목표가는 전일 종가 기준으로 계산되는데, 삼성전자가 개장 시 갭업하여
|
||||
목표가를 이미 상회한 가격에 진입 트리거가 발동했다.
|
||||
주의: 코드상 `목표가`는 익절가가 아니라 변동성 돌파 진입 기준가다.
|
||||
따라서 `현재가 >= 목표가`를 무조건 막으면 전략 전체 진입이 중단된다.
|
||||
|
||||
이 구조에서는 TP 달성이 원천 불가능하다. TIME 또는 SL 청산만 남는다.
|
||||
실제 구조적 문제는 `TIME/FORCE` 청산 후에도 현재가가 목표가 위에 머물면,
|
||||
새로운 돌파가 없는데도 쿨다운 종료만으로 같은 신호를 재사용해 재진입할 수 있다는 점이다.
|
||||
|
||||
---
|
||||
|
||||
## 제안 내용
|
||||
|
||||
### 진입 차단 조건 추가
|
||||
### TIME/FORCE 후 재돌파 조건 추가
|
||||
|
||||
`check_entry()` 내부에 다음 조건을 hard gate로 추가:
|
||||
`mark_final_exit()`에서 `TIME` 또는 `FORCE` 청산 종목을 재돌파 대기 목록에 넣고,
|
||||
`check_entry()`에서 해당 종목이 목표가 아래로 내려오기 전까지 진입을 차단한다.
|
||||
|
||||
```python
|
||||
# 현재가가 TP1 목표가 이상이면 진입 차단 (갭업 후 목표가 무효화)
|
||||
if current_price >= tp_target:
|
||||
return False, f"현재가({current_price:,})가 목표가({tp_target:,}) 이상 — 진입 차단"
|
||||
if ticker in self._rebreak_required_tickers:
|
||||
if current_price >= target:
|
||||
result["reason"] = f"재돌파 대기 ({current_price:,} >= {target:,.0f})"
|
||||
return result
|
||||
self._rebreak_required_tickers.discard(ticker)
|
||||
```
|
||||
|
||||
적용 위치: `app/strategy/volatility_breakout.py` — `check_entry()` 함수 내
|
||||
@@ -44,19 +49,17 @@ if current_price >= tp_target:
|
||||
|
||||
## 기대 효과
|
||||
|
||||
- 오늘 기준: 삼성전자 2건(-23,103원) 방어 가능.
|
||||
- 갭업 종목이 TP를 이미 소화한 상태로 진입하는 구조적 실수 차단.
|
||||
- 오늘 기준: 삼성전자 2차 TIME 재진입(-1,422원) 방어 가능.
|
||||
- 같은 날 같은 돌파 신호를 쿨다운 후 반복 사용하는 구조 차단.
|
||||
- SL/TIME 낭비 거래 제거 → R:R 개선.
|
||||
|
||||
---
|
||||
|
||||
## 위험 및 주의사항
|
||||
|
||||
- TP 목표가 계산 로직이 정확해야 필터가 올바르게 동작한다.
|
||||
(`tp_target`이 진입 가능 구간 안에 있을 때만 진입하는 원래 의도와 동일.)
|
||||
- 극히 드문 케이스: 목표가 재계산(장중 업데이트) 여부 확인 필요.
|
||||
현재 구현이 고정 목표가라면 문제없음; 장중 재계산이 있다면 로직 검토 추가 필요.
|
||||
- 샘플: 오늘 2건 관찰. 통계적 근거로는 부족하나, 이는 파라미터 조정이 아니라
|
||||
- 최초 돌파 진입은 기존과 동일하게 허용된다.
|
||||
- TIME/FORCE 뒤에도 가격이 목표가 아래로 내려갔다가 다시 돌파하면 재진입 가능하다.
|
||||
- 샘플: 오늘 1건의 명확한 재진입 사례 관찰. 통계적 근거로는 부족하나, 이는 파라미터 조정이 아니라
|
||||
**논리적 버그 수정**에 해당하므로 소량 샘플로도 충분히 정당화됨.
|
||||
|
||||
---
|
||||
@@ -72,8 +75,8 @@ if current_price >= tp_target:
|
||||
|
||||
## 승인 조건
|
||||
|
||||
- [ ] `volatility_breakout.py` 내 `tp_target` 변수가 진입 시점에 접근 가능한지 확인.
|
||||
- [ ] 장중 목표가 재계산 여부 확인.
|
||||
- [ ] 수동 코드 검토 후 적용.
|
||||
- [x] `volatility_breakout.py` 내 돌파 목표가 변수(`target`) 접근 확인.
|
||||
- [x] `TIME/FORCE` 청산 후 같은 신호 재사용 경로 확인.
|
||||
- [x] 수동 코드 검토 후 적용.
|
||||
|
||||
**FORCE_EXIT = "14:50"** 변경 없음. SL 우선순위 변경 없음.
|
||||
|
||||
Reference in New Issue
Block a user