주식 애플리케이션은 신호 산출까지는 갖췄으나 집행 경로가 없다. 4팩터 시그널(감성·모멘텀·수급·재무, ml/app/signal.py#combine)과 VCP 게이트가 매수 등급을 매기고, 토스 주문 API 연동(PlaceOrderUseCase·TossOrderGatewayImpl)도 실동작하지만, 신호에서 주문까지는 사람이 화면을 보고 손으로 옮겨야 한다.
이 과제는 그 구간을 자동화한다. 신호 → 리스크 판정 → 주문 집행 → 체결·손익 추적을 하나의 상시 루프로 만든다.
현재 자산 (2026-08-27 실측)
자산
상태
4팩터 시그널·추천 스냅샷
운영 중 (signal 도메인, 자정 적재)
토스 주문 API (POST /api/v1/orders, 정정·취소)
연동 완료, 실호출 200
토스 조건부 주문 (/api/v1/conditional-orders, OCO)
미사용 — 손절·익절 브로커 위임 가능
토스 실시간 체결 이벤트 (wss://openapi-ws.tossinvest.com/ws/v1, personal:order)
이 PRD는 아래 두 사실을 알면서 진행하는 결정 위에 쓰였다. 숨기지 않고 요구사항으로 방어한다.
검증된 엣지가 없다.엣지검증결과|P2 엣지 검증 결과]에서 모멘텀·컨트라리안 두 가설 모두 비용 차감·비중첩 표본·OOS 시간분할 후 |t| < 2, 승률 42~45%로 통계적 유의성 없음이 확인됐다. 즉 이 봇이 집행할 신호는 아직 초과수익이 증명되지 않았다.
표본이 단일 국면 12개월에 머물러 있다. 일봉 누적 배치(DailyPriceAppendScheduler)는 PRICEHISTORY_APPEND_SCHEDULER_ENABLED=true로 활성화돼 있으나, 배치는 앱이 떠 있을 때만 돈다. 2026-08-27 점검 시 앱 스택이 내려가 있어 max(trade_date)가 2026-08-03에 멈춰 있었다(24일 누락). 같은 날 백필로 복구해 2026-08-27까지 채웠다. 현재 표본은 종목당 약 227캔들(≈12개월)이며, 토스 캔들 API count ≤ 200 제약으로 과거 방향 확장은 불가능하고 앞으로 매일 append하는 방법밖에 없다. P2 재검증에 필요한 다국면 표본에는 아직 못 미친다.
즉 앱 가동률이 곧 표본 누적률이다. 앱이 며칠 내려가면 그만큼 표본에 구멍이 난다.
따라서 이 봇의 1차 목적은 수익 창출이 아니라 집행 인프라 확보와 실시간 갭 측정이다. 수익 기대는 엣지가 확인된 뒤에 건다. 이 전제 때문에 손실 상한·킬 스위치를 P0로 둔다.
토스 Open API에 sandbox가 없다 (2026-08-27 확인)
토스 OpenAPI 스펙의 servers는 https://openapi.tossinvest.com단 하나이며, 스펙·가이드 전문에 sandbox·모의투자·mock 환경에 대한 언급이 0건이다. 즉 브로커가 제공하는 안전한 테스트 환경이 존재하지 않는다.
함의가 크다. Alpaca처럼 “페이퍼 계정 자격증명을 분리해 실수로 실주문이 나가는 것을 원천 차단”하는 방식을 쓸 수 없다. 같은 자격증명·같은 엔드포인트로 실주문이 나간다. 따라서 paper 모드의 안전성은 전적으로 우리 코드의 분기에만 의존하며, 이 분기가 유일한 방어선이다. 이 때문에 “paper 모드에서 발생한 토스 주문 호출 0건”을 자동 검증 대상으로 둔다(FR-35).
기존 로드맵 문서와의 관계
부 증식 파이프라인 로드맵의 P3(리스크 관리)·P4(실행 자동화)가 같은 영역을 다루나, 본 과제는 독립 과제로 새로 정의한다. 아래 두 ADR은 본 PRD의 결정과 충돌하므로 개정 대상이다.
기존 결정
본 PRD의 결정
처리
ADR-005 — 완전 자동 미채택, 전건 수동 승인
조건부 자동 (한도 내 자동, 초과분 승인)
ADR 개정 필요
ADR-006 — live는 별도 게이트, 이번 범위 밖
paper·live 모두 본 과제 범위
ADR 개정 필요
로드맵 P3·P4 티켓(7장)은 폐기하지 않고 본 과제 설계 시 입력 자료로 재검토한다.
Problem Definition
AS-IS
신호가 “매수 유망” 등급을 내도 주문은 사람이 앱을 열어 종목·수량·가격을 다시 입력해야 한다.
신호 발생 시각과 주문 시각 사이의 지연이 측정되지 않는다. 백테스트가 가정한 체결가와 실제 체결가의 차이(슬리피지)를 아무도 모른다.
손절 기준이 사람 머릿속에만 있다. 시스템에 손절가·목표가가 기록되지 않으므로, 하락 시 대응은 전적으로 그날 화면을 봤는지에 달려 있다.
종목당 얼마를 넣을지 결정하는 규칙이 없다. 포지션 사이징·분산·총 노출 한도가 시스템에 존재하지 않는다.
하루에 얼마까지 잃으면 멈춰야 하는지에 대한 자동 차단 장치가 없다.
문제의 핵심
집행이 수동이라 신호 품질을 측정할 수 없다. 언제 얼마에 샀는지가 기록되지 않으니 백테스트와 현실의 차이를 좁힐 근거가 쌓이지 않는다. 그리고 손실을 끊는 장치가 없어, 신호가 틀렸을 때 손실 크기가 사람의 주의력에 좌우된다.
Goals / Non-Goals
Goals
ID
목표
G-1
신호에서 주문 집행까지 사람 개입 없이 도는 루프를 만든다 (한도 내)
G-2
모든 집행에 손절·익절을 강제로 붙여, 봇이 죽어도 손실이 무한히 커지지 않게 한다
G-3
일일·누적 손실 한도와 즉시 정지 수단(킬 스위치)을 시스템에 내장한다
G-4
paper 모드로 실시간 신호 품질과 슬리피지를 실손실 없이 측정한다
G-5
검증 후 동일 경로로 live 실집행까지 연결한다
G-6
모든 판단·집행·거부를 감사 가능한 기록으로 남긴다
Non-Goals
범위 밖
사유
신호·전략 알고리즘 개선
본 과제는 집행 계층. 전략 품질은 별도 엣지 재검증 과제
ML 모델 도입
ADR-004 게이트 — 엣지 미검증 상태에서 모델은 과적합 장난감
미국 주식·해외 종목
1차는 KRX만. 환율·거래시간·세제 복잡도 회피. 주의: 현재 daily_prices 199종목 중 82개가 미국 종목이므로 유니버스 필터로 배제해야 한다 (FR-16)
검증-집행 정의 공유 (젠포트) — 백테스트가 쓰는 비용 모델(cost_model.py)을 페이퍼 체결 시뮬레이션에도 그대로 쓴다.
반영하지 않는 것
젠포트의 전략 마켓플레이스·전략 공유 — 사용자 1명 시스템에 불필요.
QuantConnect의 다자산·다브로커 추상화 — 토스 단일 브로커·KRX 단일 시장이므로 과설계.
확정 파라미터 (2026-08-27, paper 단계)
전부 설정값이며 코드 상수로 박지 않는다 (FR-15).
항목
값
근거
가상 총자본
100만원
사용자 확정. 실제 입금 예정 규모와 맞춤
매매 유니버스
KRX 117종목 (6자리 숫자 심볼)
환율·미장 시간·해외 과세 회피. daily_prices의 미국 82종목 배제
종목당 투입 상한
총자본 대비 비율 — 단계별 (T1 10% / T2 15% / T3 20%)
아래 “리스크 사다리” 참조. 금액이 아닌 비율로 정의한다
동시 보유 종목 수
단계별 (T1·T2 5종목 / T3 4종목)
T3는 20%×5=100%가 되어 현금이 0이 되므로 4종목으로 줄인다
자동 집행 임계
종목당 상한과 동일 (= 전건 자동)
paper는 돈이 안 나가므로 승인 게이트가 수집 속도만 늦춘다
일일 손실 한도
단계별 (T1 2% / T2 2.5% / T3 3%)
종목당 비율이 오르면 손절 1건의 총자본 영향도 커진다. 한도를 함께 올리지 않으면 T3에서 손절 1건에 하루가 끝난다
총 손실 한도(MDD)
총자본 10% (10만원) — 제안값
5종목 전량 손절(-3.5%)의 약 3배. 여기 도달하면 신호 자체를 의심할 구간
손절률
-7% — 제안값
손익비 1:2.1
익절률
+15% — 제안값
위와 동일. 일봉 신호 기준 도달 빈도는 paper에서 측정해 조정 (FR-33)
리스크 사다리 (FR-38)
작게 시작해 시스템이 설계대로 동작함이 확인되면 단계적으로 확대한다. 승급 조건을 수익률이 아니라 검증 지표로 두는 것이 이 사다리의 핵심이다.
단계
종목당
보유
일일 한도
접근 종목
손절 1건 영향
승급 조건
T1
10%
5
2%
54종목 (46%)
-0.7%
기본값. paper 시작 시점
T2
15%
5
2.5%
70종목 (60%)
-1.05%
20거래일 무중단 + 집행 실패 0건 + 리스크 한도 위반 0건 + 실현 슬리피지 ±0.3%p 이내
T3
20%
4
3%
78종목 (67%)
-1.4%
T2를 20거래일 추가 유지 + 비중첩 표본에서 엣지 t > 2
T2 승급은 “돈을 벌었나”가 아니라 “시스템이 설계대로 동작했나”를 본다. 소표본으로도 판정 가능한 운영 지표들이다.
T3만 통계적 엣지를 요구한다. 실질적으로 리스크를 키우는 단계이기 때문이다.
강등은 대칭으로 작동한다. MDD 한도의 절반(총자본 -5%)에 도달하면 한 단계 내려간다. 올리기만 하고 내리지 않는 사다리는 마틴게일이다.
단계 전환은 자동 판정하되, 승급은 사용자 확인을 거치고 강등은 즉시 자동 적용한다.
왜 트리거가 수익률이면 안 되는가
P2 엣지 검증에서 같은 함정을 두 번 겪었다 — 모멘텀은 중첩 윈도우 자기상관이 t를 +2~+4.7로 부풀렸고, 컨트라리안은 12조합 다중검정과 전반 국면의 우연으로 t = +2.65가 나왔다가 OOS 분할에서 소멸했다. 승률 42~45% 신호로도 소표본에서는 연속 수익이 나온다. 20거래일 · 5슬롯이면 거래는 많아야 수십 건이고, 그 표본의 “목표 이득 도달”은 실력의 증거가 아니라 분산의 정상 범위다. 거기서 포지션을 키우면 평균회귀 시 손실도 함께 커진다.
비율 정의가 주는 자동 스케일링
종목당 상한을 금액이 아닌 총자본 대비 비율로 정의했으므로, 자본이 변하면 포지션도 자동으로 따라 변한다. 별도 상향 조작이 필요 없다.
총자본
T1(10%) 종목당
접근 종목
100만원
10만원
54종목 (46%)
150만원
15만원
70종목 (60%)
200만원
20만원
78종목 (67%)
손실 시에도 대칭으로 작동한다 — 자본이 80만원으로 줄면 종목당 8만원이 되어 리스크가 함께 축소된다(자동 디레버리징). 사다리(비율 상향)와 이 자동 스케일링(자본 변동)은 독립적으로 곱해지므로, 둘이 동시에 오를 때 리스크가 이중 증폭되는 점을 강등 규칙이 방어한다.
T1·100만원에서 나오는 수치
한 종목 손절 시 총자본 영향: -0.7% (7,000원) / 5종목 전량 손절 시 -3.5% (35,000원)
왕복 거래비용: 수수료 0.015%×2 + 매도세 0.18% + 슬리피지 0.1% ≈ 0.31% (10만원 포지션당 약 310원)
매수 불가로 후보에서 빠지는 종목: KRX 117종목 중 63종목(54%) — 1주 가격이 10만원을 넘음
한도 소진율(정수 매수로 인한 낭비): T1 82.1% / T2 84.9% / T3 85.3%
100만원에서는 T3(20%)까지 올려도 삼성전자(265,250원)·SK하이닉스(1,730,000원) 같은 대형주가 여전히 제외된다. 삼성전자는 종목당 30%까지 올려야 들어오는데 그러면 3종목 분산이 되므로, 대형주 편입은 비율이 아니라 자본으로 푸는 문제다. 신호가 대형주에 몰린다면 paper 20거래일 후 “신호 발생 대비 집행률”로 이를 확인할 수 있다.
Functional Requirements
실행 모드·안전장치 (P0)
ID
요구사항
우선순위
FR-1
실행 모드를 paper(모의 체결 기록)와 live(토스 실주문) 중 하나로 설정한다. **기본값은 paper**이며, live 전환은 설정 변경 + 재기동을 요구한다
P0
FR-35
paper 모드에서 토스 주문·조건부주문 API를 호출하는 경로가 존재하지 않음을 테스트로 강제한다. 브로커 sandbox가 없어 코드 분기가 유일한 방어선이므로, 모드 분기를 우회하는 집행 경로가 생기면 테스트가 실패해야 한다
P0
FR-2
킬 스위치를 제공한다. 켜면 1초 이내에 ① 신규 주문 차단 ② 미체결 주문 전량 취소 ③ 대기 제안 전량 무효화가 이뤄진다. 보유 포지션과 손절 주문은 유지한다. 해제는 사용자의 명시적 조작으로만 가능하다
P0
FR-3
당일 실현손실이 일일 손실 한도(현재 단계값)에 도달하면 당일 신규 매수를 자동 중단한다. 다음 거래일 개장 시 자동 해제된다
P0
FR-4
누적 손실이 총 손실 한도(MDD 10%)에 도달하면 자동매매를 중단하고, 재개는 사용자의 명시적 조작을 요구한다. 그 절반(-5%)에서는 사다리 한 단계 강등이 먼저 발동한다 (FR-38)
P0
FR-5
live 모드의 모든 매수 체결에 손절·익절 OCO 조건부 주문을 등록한다. OCO 등록 실패 시 해당 포지션을 즉시 시장가로 청산한다 — 손절 없는 포지션을 보유하지 않는다
P0
리스크 게이트 (P0)
ID
요구사항
우선순위
FR-6
모든 주문은 집행 전 리스크 게이트를 통과해야 한다. 게이트를 우회하는 집행 경로는 존재하지 않는다
P0
FR-7
종목당 투입 상한(총자본 대비 비율, 현재 단계값)을 초과하는 주문을 거부한다. 상한은 금액이 아니라 비율로 정의해, 자본이 변하면 포지션도 자동으로 따라 변하게 한다
P0
FR-8
총 노출 상한(현금 대비 투자 비중)을 초과하는 주문을 거부한다
P0
FR-9
동시 보유 종목 수 상한(현재 단계값)을 초과하는 신규 진입을 거부한다
P0
FR-36
1주 가격이 종목당 투입 상한을 초과해 1주도 살 수 없는 종목은 후보에서 제외하고, 제외 사유를 기록한다. 100만원·T1(10%) 기준 KRX 117종목 중 63종목(54%)이 여기에 해당한다
P0
FR-38
리스크 사다리를 지원한다. 종목당 비율·보유 종목 수·일일 손실 한도를 T1/T2/T3 세트로 묶어 관리하고, 승급 조건 충족 여부를 시스템이 판정한다. 승급은 사용자 확인을 거치고, 강등(총자본 -5% 도달)은 즉시 자동 적용한다. 단계 전환 이력을 기록한다
P0
FR-39
paper 가상 자본의 손익 반영 여부를 설정으로 정한다. M1~M2는 고정(항상 100만원 기준 — 자본 효과를 배제하고 신호 품질·슬리피지를 깨끗하게 측정), M3부터 변동(페이퍼 손익을 자본에 반영해 복리·자동 스케일링을 실제로 검증)
20 거래일 페이퍼 운영 완료, 성공 지표 전 항목 충족. T2 승급 판정 + 가상 자본 변동 전환
M4 라이브 전환
FR-5 (OCO 실등록), live 모드 개시
M3 지표 충족 + Open Questions의 자본·한도 수치 확정 + 입금 완료
M1의 P0 항목은 전부 M1~M2에 포함된다. M4는 별도 사용자 승인 게이트를 거친다.
사다리 단계는 마일스톤과 독립적으로 움직인다 — T3 승급은 엣지 유의성(t > 2)을 요구하므로 M3 완료 시점에 달성되지 않을 수 있고, 그 경우 T2에 머문 채 M4를 검토한다. T3 미달이 M4의 차단 사유는 아니지만, live 개시 판단(Q-8)의 핵심 입력이다.
M1~M3는 paper 전용으로 진행한다 (2026-08-27 결정). 입금은 앱 완성 후이므로, 그전까지 토스 주문·조건부주문 API는 한 번도 호출하지 않는다. 브로커 sandbox가 없으므로 이 구간의 “테스트 환경”은 우리가 만든 paper 모드가 전부다 — FR-35가 그 경계를 지킨다.
T2 승급 조건의 “20거래일”이 적절한가? T3의 “엣지 t > 2”를 어떤 표본으로 판정할 것인가?
FR-38 승급 판정. 페이퍼 거래 표본만으로는 t 검정 표본이 부족할 수 있다
T3 승급이 영구히 판정 불가 상태로 남는다
Q-5
손절 -7% / 익절 +15% 제안값을 확정할 것인가?
OCO 등록 파라미터
paper에서 도달 빈도를 측정해 조정 (FR-33)
Q-8
엣지 미검증 상태에서 live를 여는 판단 기준은 무엇인가? 페이퍼 성과가 어떤 조건일 때 여는가?
M4 게이트 조건
게이트가 형식만 남고 실질 판단 부재
Q-9
앱 스택 가동률을 어떻게 보장할 것인가?
배치는 켜져 있으나 앱이 떠 있을 때만 돈다. 2026-08-27에 24일 누락이 발견됐고 백필로 복구했다. 앱 가동률이 곧 표본 누적률이다
표본에 구멍이 생겨 재검증이 계속 밀린다
Q-10
ADR-005·ADR-006을 개정할 것인가, 본 과제 전용 ADR을 새로 쓸 것인가?
문서 정합성
확정 ADR과 구현이 모순된 채 남는다
Q-12
daily_prices의 통화 혼재(KRW·USD 동일 컬럼)를 스키마로 해소할 것인가, 유니버스 필터로만 막을 것인가?
FR-37. 미국 종목을 나중에 다시 다루려면 스키마 해소가 필요하다
KRX 한정인 동안은 필터로 충분. 확장 시 재발
Q-3~Q-5·Q-13은 제안값으로 진행하되 M2 착수 전 확정한다. Q-8·Q-10은 M4 전까지, Q-12는 미국 종목 확장 시점까지 확정한다. Q-9는 상시 운영 과제다.
해소된 질문
#
질문
결정 (2026-08-27)
Q-1
총 투입 자본 규모
입금은 앱 완성 후 (2026-08-27 결정). M1~M3는 가상 자본으로 진행, 실입금액은 M4 직전 확정
Q-2
자동 집행 임계
paper 구간은 종목당 상한과 동일 (전건 자동). live 전환 시 재설정
Q-6
매매 유니버스
KRX 117종목만 (미국 82종목 배제)
Q-7
종목당 비율·보유 종목 수
10% × 최대 5종목
Q-11
paper 가상 자본
100만원
Document History
날짜
변경 내용
2026-08-27
최초 작성. 범위=신규 독립 과제, 자동화 수준=조건부 자동, 실행 모드=paper+live 포함으로 확정. ADR-005·006과의 충돌을 명시
2026-08-27
정정 — 초판의 “일봉 배치가 어디에도 활성화돼 있지 않다”는 사실 오류였다. ~/.zshrc:201에 true로 설정돼 있었고, 실제 원인은 앱 다운으로 배치가 실행되지 않은 것이었다(24일 누락, 같은 날 백필로 복구). 표본 현황을 실측치로 교체하고 Q-9를 가동률 문제로 재정의
2026-08-27
토스 Open API에 sandbox·모의투자 환경이 없음을 확인(서버 1개, 관련 언급 0건). 제약으로 명시하고 FR-35(paper 모드 실주문 경로 부재를 테스트로 강제) 추가
2026-08-27
입금을 앱 완성 후로 결정. M1~M3를 paper 전용으로 확정하고 Q-11(가상 자본 규모) 추가