한투 호가 = 2번째 앱키 전용 키 없거나 start 실패 시 메인에 H0STASP0 안 붙임. 운영설정 WS_ORDERBOOK_SAVE_KIS 빨간 danger. LS RAM 합집합 후보∪보유∪영구∪grace. sync_targets와 split reconcile 둘 다. 틱 DB 영구 게이트는 그대로. 분봉 쓰레기 → 다음 소스 봉 통째 그 분 틱 0건이거나 전부 봉끝 대비 LIVE_FEED_FALLBACK_MAX_AGE_SEC 초과면 구멍. 메인 WS → 2차 → LS → REST → rollup. CANDLE_GARBAGE_FALLBACK 기본 true. 파일: feed_fallback.py(신규), ws_manager.py, kis_ws.py, candle_series.py, bt_candle_source.py, live_config_schema.py, database.py, 스모크, MD 2개. 같은 ws_manager/database/kis_ws/live_config에는 직전 커밋 이후 쌓여 있던 시세 폴백·ENV 키 정리도 같이 들어갔습니다. 파일 단위로 나눌 수 없어서입니다.
10 KiB
화요일 확인 — ALIGN 폐기 + 호가필터 구멍 + 가격 TTL/EOD
확인일: 2026-08-18 (화) 장중.
토~월에 쌓인 일이 세 묶음. 봉 정합(T−1 신호 / T 진입 / freeze)과 다른 이야기.
*_LIVE_BACKTEST_ALIGN(봉 진입)은 끄지 않음. 없앤 건 유니버스 history 교집합뿐.
| 묶음 | 한 줄 | 화요일 봇 |
|---|---|---|
| A. 유니버스 ALIGN | 키움 RAM ∩ history 교집합 삭제. history는 INSERT만 | 토에 재시작. 또 안 해도 됨 |
| B. 호가 눈가림 | 사진 만료=통과 폐기 + 사진 없으면 안 삼 | 월 23:55 재시작에 포함되면 OK |
| C. 가격 TTL / EOD | 체결 없어도 마지막가 유지. EOD는 min_hold·유령삭제에 안 막힘 |
월 23:55 kis_trader_main 재시작함 → 화 장부터 이 코드 |
웹: kis_backtest_web 재시작됨. 운영 설정만 보면 됨.
시세·호가 = 실키(키움 mock=False, 한투 WS :21000). 매매 REST = 한투 모의 (openapivts). 이번 패치로 모의키를 시세에 붙인 적 없음.
왜 고쳤나 (한 줄씩)
- A. 운영 ON이던
LIVE_UNIVERSE_SLOT_ALIGN이 RAM 후보를 history와 교집합 → 중간 사진 ∩ 실시간 =universe_wipe. - B. 호가 저장 TTL과 검사 TTL을 같이 써서 사진이
None이면 필터 ON인데 통과(눈가림 매수). - C. REST→WS 바꿀 때 “오래된 캐시=죽음”으로 가격을
None→ 매도continue. 199원이 체결이 없어도 계속 199원인데 지워서 손절·EOD가 안 나감 (8/5 돌파, 금요일 leftover). 호가 B와 같은 병.
적용된 내용
1. ALIGN 스위치 완전 삭제 (눈앞·코드·DB·MD)
| 위치 | 결과 |
|---|---|
| 실매 후보 | base.py _post_filter_candidates — history 교집합 없음. RAM에 있으면 후보 |
| UI | 운영 설정에서 LIVE_UNIVERSE_SLOT_ALIGN 토글 삭제. /api/live_config JSON에도 키 없음 |
| DB | env_config_ext 행 DELETE. 전략 config 컬럼 DROP |
| 알림 | universe_wipe 발송 경로 삭제 |
| 문서 | code_architecture.md · MODIFICATION_GUIDE.md · 정합성.md 유니버스 한 줄 |
실매 진실 = 키움 REAL I/D → RAM 푸시/팝. history는 백테 재생용 복사본만.
2. 키움 history: INSERT만 + 마이크로초
| 항목 | 전 | 후 |
|---|---|---|
| 쓰기 | 같은 슬롯 DELETE 후 한 줄씩 INSERT (중간 노출) | DELETE 없음. N종목 한 트랜잭션 |
event_time |
초 varchar(19) |
마이크로초 varchar(26) |
| 같은 초 두 변동 | 두 번째가 첫 장을 지움 | 두 장 다 남음 |
백테: 그 초의 마지막 스냅샷. ±1분 슬롯 해킹 없음.
건드리지 않음: ls_candidates_history, WS_TICK_GRACE_SEC 기본 180.
3. 호가 — 대기표 사진 없이 사던 구멍
- 만료=통과 → 검사 시계
WS_ORDERBOOK_FILTER_MAX_AGE_SEC기본 0(마지막 사진). 저장WS_ORDERBOOK_TICK_MAX_AGE_SEC(30초)와 합치지 말 것. - 사진 0장인데 통과 →
WS_ORDERBOOK_FILTER_REJECT_IF_EMPTY기본 ON. REST 없음.
한산해서 사진이 안 바뀌는 것 ≠ 사진이 없는 것. 팔 때 지정가·익절/손절 호가매도는 안 바꿈.
4. 가격 TTL / EOD (월 밤) — 화요일 실매 본체
초등: 칠판에 199원. 체결이 10분 없어도 199원. 지우고 “없다”고 하면 손절·장마감이 안 돌아간다.
| 위치 | 결과 |
|---|---|
| 매도 | live_sell_price.py — 마지막 WS(나이 무시). 죽은선만 REST 1회·쿨다운 30초. 실패해도 WS 유지 |
| EOD | 타이머 없음. WS 없으면 매수가 폴백. 무조건 청산 |
min_hold |
EOD를 막지 않음 (모멘텀/스캘프/꼬리) |
| 매수 | _ws_last_quote / get_price_last. WS_PRICE_MAX_AGE_SEC 기본 0 |
| WS 기본 | KIS·키움·LS·해외 get_price 기본 None(나이 무시). LS 옛 10초·해외 옛 20분 폐기 |
| 40240000 | 잔고검증 qty>0 이면 「잔고 없음」 문구로 ghost_purge 금지 |
| 기동 | ORPHAN_RECONCILE_ON_STARTUP — 전략 전 잔고=DB 맞춤(매도 없음) |
옵투나·웹백테는 DB 봉·틱 재생이라 이 TTL이 봉을 성기게 만들지 않음. 예전 옵투나 best는 “실매가 안 팔던 세상”과 어긋날 수 있음. 화 하루 쌓인 뒤에 수요일 재탐색이 그 하루만 가깝다. --apply-best 하지 말 것.
재시작 기록
| 때 | 무엇 |
|---|---|
| 토 | 웹 + (ALIGN) 실매 |
| 월 23:55 | kis_trader_main 재시작 (PID 바뀜). 🚀 통합 봇 시작 · 키움 LOGIN OK · 시세 실키 · 매매 모의 REST |
| 화 장전 | 또 재시작 불필요 (월 밤에 C묶음까지 올린 프로세스). 의심되면 한 번 더 |
systemctl is-active kis_trader_main.service
journalctl -u kis_trader_main.service --since '2026-08-18 08:50' --no-pager | head -40
정상 시그니처: 🚀 kis_trader 통합 봇 시작, 키움 WS LOGIN OK, 실키/실전 도메인, heartbeat … dead=[].
이상: Traceback, ImportError, universe_wipe, 시세 URL :31000(모의 WS).
화요일 장중 체크리스트
A. 실매 — 가짜 전량탈락이 없어야 함
kis_trader_main.serviceactive.- 알림/저널에
universe_wipe,history=kiwoom 교집합,[유니버스슬롯] … 후보 N→0없어야 함. - 키움 RAM과 매수 후보가 같이 움직임. HTS가 진짜로 비우면 RAM도 0인 것은 정상.
universe_zero는 키움 조건이 진짜 0일 때만.
journalctl -u kis_trader_main.service --since '2026-08-18 09:00' --no-pager \
| grep -E 'universe_wipe|유니버스슬롯|교집합|universe_zero' | head -50
B. history 저장 — 중간 1종목 사진이 없어야 함
event_time에 점 + 마이크로초.- 같은 초 안 두 번 변동이면 행이 두 세트.
SHOW COLUMNS FROM target_candidates_history;
-- event_time varchar(26)
SELECT strategy_id, event_time, COUNT(*) n
FROM target_candidates_history
WHERE event_time >= '2026-08-18 09:00:00'
GROUP BY strategy_id, event_time
ORDER BY event_time DESC
LIMIT 20;
pymysql LIKE의 %는 바인딩.
C. 웹
http://192.168.0.149:5050/ → 운영 설정
- 유니버스 히스토리 교집합 토글 없음
- 「호가 사진 없으면 매수 안 함」 켜짐
WS_ORDERBOOK_FILTER_MAX_AGE_SEC= 0WS_PRICE_MAX_AGE_SEC= 0 (마지막 체결가 유지)
D. 백테 (여유 있으면)
최근 거래일 1일. 유니버스가 비어 거래 0이면 안 됨. 백테 = 완성 스냅샷 재생. ALIGN ON 시절 숫자와 같을 필요 없음.
E. 호가 — 눈가림이 없어야 함
- 저널
탈락-호가없음이 가끔은 정상(구독 직후). 같은 종목 종일만이면 구독 실패. - 「매수호가」가 빨강인데 체결 — 예전 구멍이면 화요일부터 줄어야 함. 빨강 = 나중에 그린 사진일 수도.
- 한산하다고 거래 전부 0이면 안 됨. 사진 한 장이 있으면 검사하고 통과하면 산다.
journalctl -u kis_trader_main.service --since '2026-08-18 09:00' --no-pager \
| grep -E '탈락-호가없음|호가없음' | head -40
F. 가격 TTL / EOD — 횡보해도 팔아야 함 (화 신규)
- 보유 중 체결이 뜸해도 저널에 현재가 없음으로 매도 스킵이 쌓이면 안 됨.
- 손절·트레일이 횡보 종목에서도 나와야 함 (가격을 지워서
continue하던 패턴 재발 금지). - 전략 EOD 시각에 매도 주문이 나가야 함. 모멘텀은 살아 있고 돌파만 EOD 0건이면 예전 구멍.
40240000/ 「잔고 없음」인데 계좌에 주식이 있으면 ghost_purge 로그가 아니라실잔고 N주 → 유령정리 안 함이어야 함. 그다음 EOD 재시도.min_hold때문에 EOD가 스킵되면 안 됨.- leftover(당일 못 판 종목)가 전날처럼 대량이면 실패. 장 마감 후
active_tradesvs 잔고.
journalctl -u kis_trader_main.service --since '2026-08-18 09:00' --no-pager \
| grep -E '유령정리 안 함|ghost_purge|장마감|EOD|sell_ws|현재가 없음|탈락-가격' | head -60
장 마감 후: 당일 매수 → 당일 EOD/손절 주문 유무. 8/5 티앤엘처럼 EOD 0건 다음날 손절이 반복되면 C묶음 미적용(구 프로세스).
영향 분류
| 축 | ALIGN | 호가 눈가림 | 가격 TTL/EOD |
|---|---|---|---|
| 실매 | 후보가 history에 안 막힘 | 필터 ON이면 사진 없이 안 삼 | 횡보해도 마지막가로 손절·EOD |
| 백테 | history 재생. 타임스탬프만 촘촘 | 호가 검사 ON이면 사진 없는 타점 안 삼 | 봉·틱 재생. TTL 없음 |
| Optuna | 엔진 분기 없음 | 1과목은 호가 끈 채 | 예전 best ≠ 화 실매 예고편. 수요일은 화 하루만 가깝다 |
| freeze / SKIP_HTS | 없음 | 없음 | 없음 |
안 바뀐 것 (헷갈리지 말 것)
*_LIVE_BACKTEST_ALIGN/ 형성봉 ALIGN — 봉 진입 정합. 유니버스 ALIGN 삭제와 다른 키. ON 유지.LIVE_PORTFOLIO_BUDGET_ALIGN— 총한도. 유지.WS_TICK_GRACE_SEC180초.*_SKIP_HTS_SCAN_DUPESfalse.- LS t1859 /
ls_candidates_history. - 매도 지정가 · 익절/손절 호가매도.
- 프로그램매매 “스냅 없으면 통과”.
- 시세 실키 / 매매 한투 모의 분리.
화요일에 이상하면
| 증상 | 볼 곳 |
|---|---|
| 또 N→0 알림 | 교집합 재유입? universe_zero(진짜 0) vs universe_wipe(없어져야 함) |
| history 초만 찍힘 | 구버전 프로세스 |
| 백테 유니버스 구멍 | event_time 문자열. 초 조회 상한 .999999 |
| 같은 초 명단 유실 | INSERT에 DELETE가 다시 생겼는지 |
| 호가 없이 또 매수 | 구버전 / REJECT_IF_EMPTY OFF / 전략 필터 OFF |
| 한산 종목 종일 0건 | 차트 무신호 vs 사진 보고 탈락 vs 사진 0장 |
탈락-호가없음 폭주 |
호가 구독 실패. REST로 메우지 말 것 |
| 횡보인데 손절·EOD 0건 | 가격 TTL 재발. WS_PRICE_MAX_AGE_SEC가 양수인지, 매도가 get_price_last인지 |
| EOD 주문 0 + 다음날 손절 | 8/5와 동일. 봇 PID가 월 23:55 이후인지 |
| 「잔고 없음」으로 포지션 DB 삭제 | qty>0인데 ghost_purge 탄 것. 패치 미적용 |
| 시세가 모의 | WS :31000 / 키움 mock=True. 매매만 openapivts는 정상 |