Changes: - Added a new API endpoint for managing permanent subscriptions, allowing users to enable or disable subscriptions dynamically. - Implemented a function to fill candle data from Kiwoom, ensuring that only relevant data is inserted into the database. - Introduced a mechanism to handle master subscription states, improving the management of subscription statuses. - Updated the database schema to include new fields for managing subscription states and order book filtering. Impact: - These enhancements improve the flexibility and reliability of the trading system, allowing for better management of subscriptions and order book data, while reducing the risk of data inconsistencies. 히스토리 align 제거 븅신같은 초기설계 아예 제거 진입모드에 구멍메움 호가진입을 켜도 호가가 안들어올때 호가 안보고 그냥 사버림
24 KiB
호가.md — 진입 필터 · 익절 지정가 · IOC(13) · 수익구간 호가매도 · 손실구간 호가매도
이 문서는 대화·코드·DB 기준으로 호가 관련 기능을 역할별로 구분해 정리한다.
이름이 비슷해도 서로 다른 스위치이므로 혼동하지 말 것.
아래에서는 L3 / SL-OB 같은 줄임말을 쓰지 않고 한글로 푼다.
0-0. 「호가 쌓기」는 설계가 아니다 (헷갈림 방지)
DB에 호가 한 장씩 넣는 것(저장)은 이미 돌아가는 수집 기능이다.
새 매매 로직·새 설계 항목이 아니다.
| 말 | 진짜 뜻 |
|---|---|
| “호가 INSERT / 쌓기” | 봇이 장중 호가를 ws_orderbook / ls_ws_orderbook 에 기록하는 중 (지금 하고 있음) |
| “필터·호가매도 끄고 쌓기만” | 끄는 건 매매 스위치다. 저장은 켠 채, 매수 막을지 / 호가로 팔지 스위치만 OFF |
| 설계에 적어 둔 이유 | “저장이 새 기능”이 아니라 스위치 켜서 실험하지 말자는 운영 메모 |
초등 비유:
일기장에 날씨를 매일 적는 것 = 쌓기(이미 함).
일기 보고 “비 오면 우산 사기” 규칙을 켜는 것 = 필터·호가매도 ON.
규칙은 아직 끄고, 일기만 모으자는 뜻이었다.
2026-08-03 장일 확인 (틱 동기)
| 테이블 | 오늘 | 방식 | 판정 |
|---|---|---|---|
ls_ws_orderbook (ls_uh1) |
약 274만 행 / 88종목 | 체결 1건 ≈ 호가 1장 (비율 ≈ 0.999) | 틱 동기화로 쌓임 ✅ |
ws_orderbook (kiwoom_0d) |
약 12.5만 행 / 38종목 | 간격 중앙값 약 3초 | 연속 저장 ✅ · 틱 1:1은 아님 |
ws_orderbook (filter_eval) |
29행 | 진입 판정 순간 1장 | 필터 판정 로그용 |
모멘텀 실매 매수 오늘 0건 (유니버스 이슈) → 매도쪽 측정 스크립트는 오늘 모수 없음.
최근 모수: 2026-07-31 모멘텀 7건 + 키움 호가 (§4 측정).
0-1. 운영 메모 (2026-08-15 기준 · DB가 진실)
아래는 옛 “OFF 유지” 메모를 폐기한 현재 운영이다. 스위치는 웹「운영 설정」·전략탭 DB를 본다.
- 호가 저장 — ON. 시계열 TTL =
WS_ORDERBOOK_TICK_MAX_AGE_SEC(코드 기본 30초. UI에 예전에 “3초”라고 적혀 있던 것은 저장용 힌트 오류였음). - 매수 호가필터
*_ORDERBOOK_FILTER_ENABLED= ON (모멘텀·돌파·스캘프·꼬리). 숫자는 전략별(스프·잔량·매도벽). - 수익구간 호가매도
MOMENTUM_EXIT_OB_ENABLED/BREAKOUT_EXIT_OB_ENABLED= 운영 ON인 적이 있음 → DB 확인. 본 문서 옛 “OFF 유지”는 폐기. - 손절호가
*_STOP_OB_ENABLED= 마찬가지로 DB 확인 (코드 배선됨). - 필터 RAM 나이 (B안, 2026-08-15)
WS_ORDERBOOK_FILTER_MAX_AGE_SEC기본 0 = 마지막 RAM 호가로 반드시 검사. REST 없음.- 저장 TTL과 공유 금지. 예전에 둘 다
TICK_MAX_AGE라서 30초 넘으면None→ 필터 ON인데 통과(구멍). - 한 번도 호가가 없고 필터 ON이면 안 삼 (
WS_ORDERBOOK_FILTER_REJECT_IF_EMPTY기본 true). REST 없음. 다음 매수 검사에서 사진 있으면 다시 봄.
한산해서 사진이 안 바뀌는 것과 다름 — 마지막 사진이 있으면 그걸로 검사.
- Optuna Stage2(후처리) 는 캔들 TPE와 별도. 진입 격자·매도벽 축은
docs/옵투나.md· §8.--apply-best없이 후처리만 재실행 가능 (optuna_rerun_postprocess.py).
0. 한눈에 구분
| 구분 | 언제 | 하는 일 | 대표 키 | 상태 |
|---|---|---|---|---|
| 호가 저장(쌓기) | 장중 항상 | DB에 호가 기록 | LS_WS_ORDERBOOK_SAVE / WS_ORDERBOOK_SAVE_ENABLED 등 |
이미 동작 중 · 설계 아님 |
| 매수 호가필터 | 사기 직전 | 호가 나쁘면 안 삼 | {전략}_ORDERBOOK_FILTER_ENABLED |
코드 있음 · 2026-08 운영 ON |
| 익절 호가 ON | 이미 매도 신호 난 뒤 | 익절을 지정가로 냄 | SELL_USE_ORDERBOOK_ON_PROFIT |
운영 ON |
| 매도 시장가 IOC(13) | 시장가로 팔 때 | 실전만 13 | USE_MARKET_IOC_SELL |
운영·코드 분리 |
| 수익구간 호가매도 | 들고 있을 때 이득 난 뒤 | 사려는 사람 줄면 미리 이익 실현 | MOMENTUM_EXIT_OB_* / BREAKOUT_EXIT_OB_* |
코드 있음 · 시드 OFF / 운영은 DB |
| 손실구간 호가매도 | 들고 있을 때 손해 난 뒤 | 사려는 사람 줄면 큰 손절 전에 먼저 나옴 | MOMENTUM_STOP_OB_* / BREAKOUT_STOP_OB_* |
배선 완료 · 시드 OFF / 운영은 DB |
거래내역 「매수호가」 = 살 때 근처 · 「매도호가」 = 팔 때 근처. 서로 다른 칸.
수익구간 호가매도 vs 손실구간 호가매도 (초등)
둘 다 “호가판에 사려는 사람이 확 줄었다”를 본다.
언제 쓰느냐만 다르다.
| 수익구간 호가매도 | 손실구간 호가매도 | |
|---|---|---|
| 내 장부 | 이미 조금 이득일 때만 | 이미 조금 손해일 때만 |
| 하는 일 | “이득 났는데 분위기 깨지면 이익 챙기고 나감” | “손해인데 분위기 더 깨지면, −몇% 손절선까지 안 가고 먼저 나감” |
| −몇% 손절선 | 안 건드림 | 공식은 그대로 · 그 앞에서 따로 한 번 더 봄 |
| 지금 | 코드 있음 · ENABLED는 DB | 코드 있음(STOP_OB) · ENABLED는 DB |
| 파람서치 | 캔들 TPE 본체에는 안 넣음. 후처리 Stage2 (docs/옵투나.md) |
후처리 STOP 축 |
1. 매수 호가필터 (진입)
역할
- TRIGGER 단계에서 스프레드·매수/매도 잔량비·얇은 호가·매도벽 등으로 매수 차단.
- 청산 신호가 아님.
키 (전략별)
글로벌 ORDERBOOK_* 수치 폐기 → 전략 prefix만 사용.
SCALP_ORDERBOOK_FILTER_ENABLEDMOMENTUM_ORDERBOOK_FILTER_ENABLEDBREAKOUT_ORDERBOOK_FILTER_ENABLEDTAIL_ORDERBOOK_FILTER_ENABLED(SHORT → TAIL)
임계 예: *_ORDERBOOK_MAX_SPREAD_PCT, *_MIN_BID_ASK_RATIO, *_ENTRY_BID_LEVELS 등.
코드
- 판정 공통:
kis_trader/engine/orderbook_filter.py - env:
kis_trader/engine/orderbook_env.py - 웹: 예) 모멘텀 「호가필터 ON」(
mom_ob_filter) — 이 백테 회차 진입 필터
왜 전략별로 갈라졌나
스캘프·모멘텀·돌파·꼬리는 호가 의미가 달라 ON/OFF·임계를 전략마다 둔다.
판정 함수는 공유, 설정 키만 분리.
수집 vs 필터
KIWOOM_WS_ORDERBOOK_ENABLED— 호가 WS 수신- 시계열
kiwoom_0d/ LSls_ws_orderbook— 저장(필터 OFF여도 저장 가능) - 필터 ON = 그 스냅으로 매수 탈락 적용
켜면 매매가 확 줄어드는 이유 (조건식 탓 아님)
- HTS/조건식 = “살 만한 이야기(타점)” 선별
- 호가필터 = “지금 이 순간 대기표가 들어가기 좋은가” 추가 게이트
- 모멘텀·돌파류는 급등·얇은 종이 많아, 통과 직후 호가가 스프레드 큼 / 살힘 약함 / 매도벽인 경우가 흔함
- 거래내역 「매수호가」에 간격큼·살힘 0.1x대가 보여도 데이터가 이상한 게 아니라 그 타점 유동성이 그런 것
→ “조건식이 잘못 뽑았다”로 단정하지 말 것. 유동성 게이트가 한 겹 더 있어서 건수가 줄어든다.
RAM(실매) vs DB 저장(백테)
| 실매 필터 ON | 백테 필터 ON | |
|---|---|---|
| 보는 것 | RAM get_orderbook_snapshot(max_age=FILTER_MAX_AGE) |
DB 스냅 / filter_eval 재생 |
| 나이 | FILTER_MAX_AGE=0 → 마지막 장으로 검사 (저장 30초와 무관) |
체결 시각 근처 행 |
| 스냅 한 번도 없음 | 필터 ON이면 안 삼(기본). REST 없음 | 재생·본체 없으면 그 타점 못 탐 |
저장 TTL(TICK_MAX_AGE, 기본 30)은 0D 덤프·가짜 채움 방지용.
필터가 이걸 같이 쓰면 만료=None=통과 구멍이 난다 (2026-08-14 실매에서 확인).
거래내역 「매수호가」칸의 +N초 탈락-매도벽 은 근처 스냅 스탬프이지, 그 초가 필터를 통과했다는 뜻이 아님.
임계값(0.45 · 0.85 …) — 업계 표준 아님
orderbook_env.py 프로젝트 시드/시작값 (Optuna·웹에서 변경 가능). “보편적으로 다들 0.45”가 아님.
| 기본 | 의미 | 체감 |
|---|---|---|
| 스프레드 0.45% (시드) | (ask−bid)/mid 상한 |
운영 모멘텀은 3.0 근처도 있음. orderbook_env 시드 ≠ 실매 DB |
| 잔량비 0.85 | 상위 N호가 매수÷매도 | 살 쪽이 거의 비슷해야 통과 |
| 깊이 1.2 | 필요수량 ×1.2 ≤ 매수호가 합 | |
| 매도벽 3.0 | 매도잔량 과다 컷 |
AND라서 하나라도 깨지면 탈락 → 체감이 셈.
이 필터가 굳이 필요한가? → 필수 아님
| 목표 | 선택 |
|---|---|
| 거래 수·백테 건수 유지 | OFF 또는 임계 완화 |
| 얇은 호가·큰 갭 진입을 줄이고 싶다 | ON (2026-08 실매는 이 쪽) |
| 조건식이 이미 유동성 좋은 종만 | 필터 체감↓ |
- 진입 필터 = 살까 말까
- 익절 호가 ON = 이미 산 뒤 어떻게 팔까 (
SELL_USE_ORDERBOOK_ON_PROFIT) — 다른 스위치
호가가 안 좋게 찍힌다는 사실 자체가 “필터 필수” 근거가 아님.
안 좋은 호가에 들어가느냐를 막을지 선택일 뿐. 과하면 끄거나 숫자만 푼다.
키움 조건 vs LS 조건 (진입·수익구간 호가매도 공통)
kiwoom_condition/condition→ 호가 키움 0D RAM · DBws_orderbookls_condition→ 호가 LS UH1 RAM · DBls_ws_orderbook(키움으로 메우지 않음)
수익구간·손절호가도 같은 스냅샷 API. 2026-08 운영: 4전략 유니버스는 키움 조건이 본체. LS는 틱/호가 구독 spill 3차이지 “LS 전용 종목”이 아님 (LIVE_OB_PROVIDER=kiwoom).
2. 익절 「호가 ON」— 지정가 매도 (실행)
역할
청산 판정(래칫·어깨·트레일)이 이미 난 뒤, 주문을 어떻게 내는지.
| 스위치 | ON | OFF / 호가 없음 |
|---|---|---|
SELL_USE_ORDERBOOK_ON_PROFIT |
익절·어깨·트레일 → 매수1호가 지정가(ORD_DVSN=00) · 잔량 부족 시 대기 |
같은 익절 신호 → 시장가 |
손절 · 긴급 · 장마감(EOD) → 이 스위치와 무관, 항상 시장가.
운영 값 (확인 시점 기준)
저장: config_short
| 키 | 값 | 의미 |
|---|---|---|
SELL_USE_ORDERBOOK_ON_PROFIT |
true | 익절 지정가 경로 ON |
SELL_ORDERBOOK_BID_LEVELS |
2 | 매수 1~2호가 잔량 합 검사 |
SELL_ORDERBOOK_DEPTH_MULT |
1.5 | 필요 잔량 = 수량 × 1.5 |
코드
kis_trader/execution/order_manager.py— 매도 전송 분기kis_trader/execution/orderbook_sell.py— 잔량·지정가 가격 산출
전 전략 공통(OrderManager 한 경로). 진입 필터처럼 전략별 키가 아님.
UI
라이브 스키마에 진입 「호가필터 ON」은 잘 보이지만,
SELL_USE_ORDERBOOK_ON_PROFIT는 스키마 전용 체크가 약하고 DB(config_short)·get_env로 동작.
3. 매도 주문코드 13 — 시장가 IOC (실전만)
역할
시장가 매도를 낼 때의 ORD_DVSN 선택.
익절 지정가(00)와는 별개.
| 환경 | 시장가 매도 코드 |
|---|---|
| 모의 | 항상 01 (IOC 13 미지원 → 코드에서 고정) |
실전 + USE_MARKET_IOC_SELL=true |
13 (시장가 IOC) |
| 실전 + false | 01 (일반 시장가) |
매수용은 별도: USE_MARKET_IOC (실전 매수 13 / 모의 01).
코드
kis_trader/execution/kis_client.py
sell_market_order/uses_market_sell_ioc()sell_limit_order→ 항상00
운영 UI
live_config_schema: 「매도 시장가 IOC」=USE_MARKET_IOC_SELL
흐름 요약
익절 신호
├─ SELL_USE_ORDERBOOK_ON_PROFIT ON + 잔량 OK → 지정가 00
└─ OFF / 호가없음 / 잔량실패 후 시장가
├─ 실전 + IOC ON → 13
└─ 모의 → 01
손절·긴급·EOD → 시장가 (위와 동일하게 실전 13 / 모의 01)
4. 수익구간 호가매도 (코드 있음 · 기본 OFF)
진입 필터·익절 지정가와 다른 축:
이미 산 뒤, 이득이 난 상태에서 “사려는 사람이 줄었다”면 팔지 말지를 본다.
초등으로
- 주식을 샀다.
- 가격이 조금 올랐다 (이득).
- 호가판을 보니 “사고 싶다”는 줄이 확 짧아졌다.
- 그때 이익을 챙기고 나간다 = 수익구간 호가매도.
- 아직 이득이 아니면 이 규칙으로 안 판다. (그건 손실구간 쪽)
왜 맨 위에 두면 안 되나
- 장 초반·급등 초입은 원래 파는 사람이 많다 → “분위기 끝”으로 오해하기 쉬움
- 사자마자 팔면 수수료만 나고 기회 날림
→ 맨 위(1순위) 금지. 래칫·어깨 다음, −% 손절 앞.
측정(실매 매수 + ws_orderbook, 예: 2026-07-27 모멘텀):
- 가드 없이 순간만 보면: 조기 신호 많음
- 이득·최소보유 가드 후: 크게 줄어듦
※ 이 %는 수익률이 아님 = “산 뒤 N분 안에 이 신호가 뜬 건수 비율”
합의된 매도 순서
래칫 → 어깨 → 수익구간 호가매도 → 손실구간 호가매도 → −% 손절 → 트레일 → …
- 코드: 어깨 다음 · 손절 전 = 수익구간(
호가컷) + 손절호가 · 코드 시드 OFF(운영 DB) - 모멘텀=키움 호가 · 돌파=LS 호가 (교차 메우기 금지)
- −% 손절은 가격 하나만. 호가를 손절 % 숫자에 섞지 않음.
env 키 (모멘텀=키움 · 돌파=LS · 수익구간)
| 키 | 기본 | 역할 |
|---|---|---|
MOMENTUM_EXIT_OB_ENABLED / BREAKOUT_EXIT_OB_ENABLED |
false | 켜기/끄기 |
*_EXIT_OB_RATIO_MIN |
0.4 | 사려는/팔려는 비율 이동평균이 이하면 “줄었다” |
*_EXIT_OB_MA_WINDOW |
5 | 몇 장 평균 볼지 |
*_EXIT_OB_MIN_PROFIT_PCT |
0.005 (+0.5%) | 이만큼 이득일 때만 |
*_EXIT_OB_MIN_HOLD_BARS |
3 | 산 지 최소 N분 |
등록: database.py (config_momentum / config_breakout) · defaults → exit_ob_*.
웹 모멘텀·돌파 탭에 컨트롤 있음. 코드 기본 false · 실제 ON/OFF는 DB.
발동 조건 (모두 만족)
| 조건 | |
|---|---|
| 스위치 ON | |
| 비율 이동평균 < 기준 | 스냅 부족 → 안 함 |
| 최소 이득 | |
| 최소 보유 |
배선 상태 (2026-08)
실매·백테 OR 히스토리 주입 ✅ · 웹 ✅ · Optuna 캔들 본체 TPE에는 미포함.
숫자 탐색은 후처리 Stage2 (optuna_orderbook_recommend.py EXIT/STOP 축). OFF면 예전과 동일.
측정 스크립트 (매도쪽 · 필터 켜기 전)
scripts/measure_ob_exit_early_fire.py
- 실매 매수 + 실매 호가 테이블
- A) 맨 위+가드없음 / B) 맨 위+가드 / C) 3순위+가드(현 설계)
- 예:
--date 2026-07-31 --ob-table ws_orderbook - 2026-08-03: 모멘텀 매수 0건 → 측정 불가 (호가는 쌓여 있음)
2026-07-31 매도쪽 한 줄 (키움 ws_orderbook)
모멘텀 7건 전부 호가 있음.
A 28.6% → B/C 14.3% (가드가 핵심).
같은 날 ls_ws_orderbook은 그 종목들 스냅 0 → LS로 못 재현 (모멘텀=키움 조건 쪽).
전략 범위
모멘텀+돌파 배선. 진입 필터 키와 혼용 금지.
4-1. 손실구간 호가매도 (배선 완료 · 기본 OFF · 모멘텀+돌파)
수익구간과 같은 호가 눈, 반대 장부.
초등으로
- 주식을 샀다.
- 가격이 조금 떨어졌다 (손해).
- 호가판에 사려는 사람이 확 줄었다.
- −3% 같은 큰 손절선까지 기다리기 전에 먼저 나온다.
- 이득 중이면 이 규칙으로 안 판다. (그건 수익구간)
왜 만드나
−% 손절만 있으면, 호가가 이미 무너진 뒤에 가격이 손절선에 닿아 더 나쁜 가격에 팔 수 있음.
수익구간 규칙만 있으면 손해 날 때는 안 도와줌.
원칙
- −% 손절 숫자는 그대로. 이 규칙은 앞에서 한 번 더 보는 것뿐.
- 손해일 때만.
- 맨 위 금지 — 래칫·어깨 다음, −% 손절 직전.
- 호가 스냅 없으면 안 함 (가격봉으로 호가 지어내기 금지).
- 나갈 때는 시장가/IOC(도망). 익절 지정가「호가 ON」과 다름.
- 기본 OFF. 측정 → 승인 → 코드 → ON.
목표 순서
1 래칫
2 어깨
3 수익구간 호가매도 ← 이득 + 호가 줄음
4 손실구간 호가매도 ← 손해 + 호가 줄음 ★배선·기본 OFF
5 −% 손절 ← 가격만
6 트레일 · 시간 · …
env (모멘텀 · 배선됨) — 한글 뜻
| 키 (영문) | 한글 이름 | 기본 | 한줄 |
|---|---|---|---|
MOMENTUM_STOP_OB_ENABLED / BREAKOUT_STOP_OB_ENABLED |
손절호가 켜기 | false | 끄면 이 규칙 전부 무시 |
MOMENTUM_STOP_OB_RATIO_MIN |
호가 붕괴 기준 | 0.4 | 총사÷총팔 평균이 이보다 작으면 “사람 줄었다” |
MOMENTUM_STOP_OB_MA_WINDOW |
평균 몇 장 | 5 | 위 비율을 최근 5장 평균내서 봄 (순간 깜빡임 방지) |
MOMENTUM_STOP_OB_MIN_LOSS_PCT |
최소 손해 폭 | 0.003 (−0.3%) | 이만큼은 이미 손해여야 발동 (수익 중엔 안 씀) |
MOMENTUM_STOP_OB_MIN_HOLD_BARS |
최소 보유 분 | 2 | 산 지 2분 전엔 안 씀 |
DDL·컬럼 COMMENT: scripts/sql/config_momentum_ob_column_comments.sql · scripts/sql/config_breakout_ob_column_comments.sql
하드 손절 4%일 때 언제 나감? (손절호가 ON 가정)
- 산 지 2분 미만 → 손절호가 안 함. (−4% 하드만 가능)
- 2분 이상 + 현재가 −0.3% 이하 + OR평균 < 0.4 → 사유
손절호가로 즉시 시장가 (하드 4%까지 안 기다림) - 호가는 안 무너졌는데 가격만 −4% → 예전처럼 사유
손절 - 지금 DB 기본은 ENABLED=false → 2번은 아예 없고 4% 하드만.
“얼마나 빨리” = “−0.3%에 OR만 깨지면 그때”. 4%까지 버티는 규칙이 아님.
OR 5장 채우는 시간: LS 틱동기면 체결 몇 번(초 단위) · 키움 ~3초 저장이면 대략 십수 초면 충분. 최소보유 2분이 보통 더 긴 병목.
삼성전자급 두꺼운 호가: 평소 OR이 0.4 아래로 잘 안 떨어짐 → 손절호가가 거의 안 울릴 수 있음. 진짜 수급 붕괴·급락 구간에서야 −0.3%~−4% 사이에서 선제. 얇은 중소형에서 체감이 큼.
사유 문자열: 손절호가 (수익구간의 호가컷과 구분 · 시장가 긴급).
상태
| 항목 | |
|---|---|
| 설계 | ✅ |
| 코드·DB·웹 | ✅ 2026-08-03 배선 |
| 기본값 | 코드 시드 OFF · 실제는 DB |
| TPE | 캔들 본체 축 아님. 후처리 STOP 축 (docs/옵투나.md) |
측정 (호가 쌓인 뒤 · 모멘텀 매수가 있는 날)
- 손실→−%손절(또는 큰 손실) 건 중, 손절 직전에 이미 호가가 줄었던 비율
- 손해였다가 회복한 건에서 이 규칙이 너무 일찍 나갔을 비율
→ 측정 후 ON 여부 결정 (지금 기본 OFF).
5. 데이터 · UI 참고
| 항목 | 내용 |
|---|---|
| 호가 테이블 | ws_orderbook (키움), ls_ws_orderbook (LS) |
| 테이블에 있는 것 | best_bid/best_ask, total_bid_qty/total_ask_qty, bid_qty_l3/ask_qty_l3 등 원본 |
| 테이블에 없는 것 | 0.45%·살힘·OR 같은 계산된 %/비율 — DB 컬럼이 아님 |
| 거래내역 「매수호가」「매도호가」 | trade_orderbook_enrich.py가 매수/매도 시각 근처 스냅을 붙인 뒤, 웹 JS가 원본으로 계산·색칠 |
| 기준 숫자(시드) | 매수: 간격≤0.45% · 살힘≥0.85 / 매도 OR: ≈0.40 (수익구간 호가매도 기본) — 업계 표준 아님 |
| LS 오늘 | 틱 동기 (체결≈호가 1:1) |
| 키움 오늘 | 연속 저장 · 간격 약 3초 (틱 1:1 아님) |
UI 칸 — 이상(높을수록 / 낮을수록)
| 칸 | 지표 | 이상 | 초등 |
|---|---|---|---|
| 매수호가 | 가격간격 % | ↓ 낮을수록 | 사·팔 가격이 가까울수록 들어가기 쉬움 |
| 매수호가 | 살 힘 (위3칸 사÷팔) | ↑ 높을수록 | 사겠다는 대기가 많을수록 버팀 |
| 매도호가 | OR (총사÷총팔) | ↑ 높을수록 수급OK · ↓ 낮으면 약함 | 팔 때 사려는 사람이 많으면 버팀, 적으면 무너짐 |
| 매도호가 | 가격간격 % | ↓ 낮을수록 | 팔 때도 간격 작을수록 체결 덜 미끄러짐 |
열 헤더: ↓간격 ↑살힘 / ↑OR ↓간격 (마우스 올리면 상세).
6. 하지 말 것 (요약)
- 매수필터 · 익절지정가 · 수익구간호가매도 · 손실구간호가매도를 한 스위치로 취급하지 말 것.
- “호가 쌓기”를 새 매매 설계로 착각하지 말 것 — 이미 있는 저장.
- 호가를 −% 손절 공식에 섞지 말 것.
- 호가매도를 1순위에 두지 말 것.
- 스냅 없이 OHLC로 호가 지어내기 금지.
- 모의에 ORD_DVSN=13 강제 금지.
- 필터 TTL과 저장 TTL을 한 키로 묶지 말 것 (
FILTER_MAX_AGEvsTICK_MAX_AGE). - 캔들 TPE 본체에 호가 ON/OFF를 넣지 말 것. 숫자 탐색은 후처리만 (§8).
- 거래대금·시총회전 만으로 손절 만들지 말 것.
- 필터 ON인데 호가 사진이 없다고 통과시키지 말 것. REST로 메우지 말 것 (
REJECT_IF_EMPTY).
7. 관련 파일
| 파일 | 내용 |
|---|---|
kis_trader/engine/orderbook_filter.py |
매수 호가필터 |
kis_trader/engine/orderbook_env.py |
전략별 진입 env |
kis_trader/execution/orderbook_sell.py |
익절 지정가·잔량 |
kis_trader/execution/order_manager.py |
매도 실행 분기 |
kis_trader/execution/kis_client.py |
00/01/13 주문 |
kis_trader/backtest/trade_orderbook_enrich.py |
거래내역 호가 표시 |
kis_trader/engine/momentum_hts_logic.py |
수익구간·손절호가 판정 (모멘텀·돌파 공용) |
kis_trader/engine/momentum_engine.py |
exit_ob_* defaults |
kis_trader/engine/momentum_env_keys.py · BREAKOUT_*_OB_*(database/config_breakout) |
전략별 env |
kis_trader/strategies/momentum.py |
실매 OR append |
scripts/measure_ob_exit_early_fire.py |
매도쪽 조기신호 측정 |
docs/layered_exit_design.md |
옛 설계서 (현행은 본 MD §4·§4-1) |
docs/호가.md |
본 문서 |
8. Optuna / TPE (2026-08-15)
캔들 본체 TPE (Stage 1)
매수필터 ON/OFF · EXIT_OB · STOP_OB 를 차트 trial 축에 넣지 않음.
끈 구간과 켠 구간이 한 랭킹에 섞이면 순위가 호가 날씨에 흔들린다.
후처리 (Stage 2) — 이미 동작
optuna_postprocess_topn.py → optuna_orderbook_recommend.py.
구 JSON만 다시: python3 -u kis_trader/backtest/optuna_rerun_postprocess.py --result-json <path>
(--apply-best 아님. 실매 숫자는 안 바뀜.)
진입 탐색 격자 (ensure_optuna_gate_env_defaults / OPTUNA_OB_ENTRY_*, env_config_ext):
| 축 | 범위 (널널 검사, 2026-08-15) | 실매 참고 |
|---|---|---|
| 스프레드 % | 0.1 ~ 8.0 step 0.1 | 모멘텀 운영 3.0 포함 |
| 잔량비 | 0.05 ~ 1.5 step 0.05 | 0.58~1.0 포함 |
| 매도벽 배수 | 1 ~ 80 step 1 | 운영 3 / 스캘프 8. 예전 후처리는 이 축이 없어 벽 탈락을 못 봄 |
| lookback | OPTUNA_OB_LOOKBACK_MIN 기본 30분 |
건수 하한: 잔여가 원본의 30% 미만이면 trial 무효 → 너무 센 컷은 점수에서 죽음.
후처리는 이미 난 체결 + 근처 호가 재생. 실매 “스냅 없음 통과” 구멍은 모델링하지 않음 (그건 B안 필터 TTL).
DB 반영은 사용자 명시 / scripts/apply_optuna_ob_consensus.py 만. 후처리 재실행 ≠ 적용.
9. env 등록 주의
신규 키는 database.py ENV 등록 + get_env_from_db 재조회 검증.