자동매매봇 PRD

Background

주식 애플리케이션은 신호 산출까지는 갖췄으나 집행 경로가 없다. 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)미사용
일봉 시계열 (daily_prices)45,090행 / 199종목 / 2025-08-29~2026-08-27 (2026-08-27 실측)
백테스트 엔진·비용모델 (ml/app/backtest_engine.py, cost_model.py)구현·실행 완료
리스크 레이어·포지션 사이징없음
주문 제안·승인·페이퍼 체결없음
Discord 알림 2채널 (stock-alert / error-alert)운영 중

전제로 깔고 가는 두 가지 사실

이 PRD는 아래 두 사실을 알면서 진행하는 결정 위에 쓰였다. 숨기지 않고 요구사항으로 방어한다.

  1. 검증된 엣지가 없다. 엣지검증결과|P2 엣지 검증 결과]에서 모멘텀·컨트라리안 두 가설 모두 비용 차감·비중첩 표본·OOS 시간분할 후 |t| < 2, 승률 42~45%로 통계적 유의성 없음이 확인됐다. 즉 이 봇이 집행할 신호는 아직 초과수익이 증명되지 않았다.
  2. 표본이 단일 국면 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 스펙의 servershttps://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-4paper 모드로 실시간 신호 품질과 슬리피지를 실손실 없이 측정한다
G-5검증 후 동일 경로로 live 실집행까지 연결한다
G-6모든 판단·집행·거부를 감사 가능한 기록으로 남긴다

Non-Goals

범위 밖사유
신호·전략 알고리즘 개선본 과제는 집행 계층. 전략 품질은 별도 엣지 재검증 과제
ML 모델 도입ADR-004 게이트 — 엣지 미검증 상태에서 모델은 과적합 장난감
미국 주식·해외 종목1차는 KRX만. 환율·거래시간·세제 복잡도 회피. 주의: 현재 daily_prices 199종목 중 82개가 미국 종목이므로 유니버스 필터로 배제해야 한다 (FR-16)
신용·미수·레버리지현금 매수만. 강제 청산 리스크 배제
분·틱 단위 단타일봉 신호 기반. 초단타는 데이터·인프라 전제가 다름
다계좌·타인 자금 운용본인 단일 계좌만
공매도·파생토스 Open API 미지원

User Scenarios

사용자는 본인 1명(계좌 소유자)이다.

S-1 한도 내 자동 매수 (해피 패스)

  1. 장 시작 후 봇이 매매 유니버스의 최신 시그널 스냅샷을 읽는다.
  2. 005930이 “매수 유망” 등급(composite ≥ 0.5, VCP 성립)으로 올라온다.
  3. 포지션 사이저가 투입 금액을 산출한다 — 예: 총자본 5%.
  4. 리스크 게이트를 통과한다 (보유 종목 수 미달, 일일 손실 한도 여유, 종목당 상한 이내).
  5. 산출 금액이 자동 집행 임계 이하이므로 승인 없이 주문이 나간다.
  6. 체결과 동시에 손절(-7%)·익절(+15%) OCO 조건부 주문이 등록된다.
  7. Discord stock-alert로 “자동 매수 체결: 삼성전자 3주 @265,500 / 손절 246,900 / 익절 305,300”이 온다.

S-2 임계 초과 — 승인 대기 (해피 패스)

  1. 산출 투입 금액이 자동 집행 임계를 초과한다.
  2. 봇은 주문을 내지 않고 제안으로 남긴다. Discord로 승인 요청이 온다.
  3. 사용자가 앱에서 제안을 확인하고 승인한다.
  4. 승인 시점 가격으로 주문이 집행된다. 이후 흐름은 S-1과 동일.
  5. 제안은 발행 후 당일 장 마감까지 유효하고, 미승인 시 자동 만료된다.

S-3 손절 발동 (예외 흐름)

  1. 보유 종목이 손절가에 도달한다.
  2. 토스에 미리 걸어둔 OCO 조건부 주문이 브로커 측에서 발동해 매도 체결된다. 봇의 생존 여부와 무관하다.
  3. 봇은 실시간 체결 이벤트로 이를 감지해 포지션을 닫고 실현손익을 기록한다.
  4. Discord로 손절 체결 알림이 온다.

S-4 일일 손실 한도 도달 (예외 흐름)

  1. 당일 실현손실 누계가 일일 한도에 도달한다.
  2. 봇이 당일 신규 매수를 전면 중단한다. 보유 포지션의 손절·익절은 유지된다.
  3. Discord로 중단 알림이 온다. 다음 거래일 개장 시 자동 해제된다.

S-5 킬 스위치 (예외 흐름)

  1. 사용자가 이상을 감지해 킬 스위치를 켠다.
  2. 1초 이내에 신규 주문이 차단되고, 미체결 주문이 전량 취소되며, 대기 중인 제안이 전부 무효화된다.
  3. 보유 포지션은 청산하지 않는다 — 손절 주문은 유지한다.
  4. 해제는 사용자의 명시적 조작으로만 가능하다. 자동 해제되지 않는다.

S-6 외부 장애 (예외 흐름)

  1. 토스 API가 5xx·타임아웃·429를 반환한다.
  2. 주문 제출은 재시도하지 않는다 — 중복 체결 위험이 재시도 이득보다 크다. 대신 주문 상태를 조회해 실제 접수 여부를 확인한다.
  3. 상태 확인이 불가능하면 해당 종목을 당일 매매 대상에서 제외하고 사용자에게 알린다.
  4. 서킷 브레이커가 열리면 자동 집행을 중단하고 error-alert로 알린다.

S-7 휴장·시간 외 (예외 흐름)

  1. 봇이 장 운영일·시간을 확인한다 (GET /api/v1/market-calendar/KR).
  2. 휴장일·장 시간 외에는 주문을 만들지 않는다. 신호 수집·분석은 계속한다.
  3. 장 마감 5분 전부터는 신규 진입을 중단한다 (종가 슬리피지 회피).

Benchmarking

제품카테고리참조 패턴URL
뉴지스탁 젠포트 / 젠트레이더국내 주식 알고리즘 자동매매백테스트한 전략을 그대로 실전 자동매매로 배포하는 구조. 전략 검증과 집행이 같은 정의를 공유해 “검증한 것과 다른 것을 집행”하는 문제를 차단genport.newsystock.com
QuantConnect LEAN통합 퀀트 플랫폼최대 낙폭 제한·자본 대비 주문 크기 제한·조건부 자동 청산을 알고리즘과 분리된 리스크 관리 계층으로 둠. 전략 코드가 리스크를 우회할 수 없는 구조quantconnect.com/docs — Risk Management
Alpaca미국 주식 API 브로커계정 자체가 페이퍼가 기본이고 실계좌는 별도 자격증명으로 분리. 실수로 실주문이 나가는 사고를 자격증명 수준에서 차단alpaca.markets/quantconnect

본 과제에 반영하는 것

  • 리스크 계층 분리 (QuantConnect) — 리스크 판정을 전략과 독립된 게이트로 두고, 모든 주문이 반드시 통과하게 한다.
  • 페이퍼 기본값 (Alpaca) — live는 명시적 전환이 있어야만 켜진다. 기본값은 항상 paper.
  • 검증-집행 정의 공유 (젠포트) — 백테스트가 쓰는 비용 모델(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건 영향승급 조건
T110%52%54종목 (46%)-0.7%기본값. paper 시작 시점
T215%52.5%70종목 (60%)-1.05%20거래일 무중단 + 집행 실패 0건 + 리스크 한도 위반 0건 + 실현 슬리피지 ±0.3%p 이내
T320%43%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-35paper 모드에서 토스 주문·조건부주문 API를 호출하는 경로가 존재하지 않음을 테스트로 강제한다. 브로커 sandbox가 없어 코드 분기가 유일한 방어선이므로, 모드 분기를 우회하는 집행 경로가 생기면 테스트가 실패해야 한다P0
FR-2킬 스위치를 제공한다. 켜면 1초 이내에 ① 신규 주문 차단 ② 미체결 주문 전량 취소 ③ 대기 제안 전량 무효화가 이뤄진다. 보유 포지션과 손절 주문은 유지한다. 해제는 사용자의 명시적 조작으로만 가능하다P0
FR-3당일 실현손실이 일일 손실 한도(현재 단계값)에 도달하면 당일 신규 매수를 자동 중단한다. 다음 거래일 개장 시 자동 해제된다P0
FR-4누적 손실이 총 손실 한도(MDD 10%)에 도달하면 자동매매를 중단하고, 재개는 사용자의 명시적 조작을 요구한다. 그 절반(-5%)에서는 사다리 한 단계 강등이 먼저 발동한다 (FR-38)P0
FR-5live 모드의 모든 매수 체결에 손절·익절 OCO 조건부 주문을 등록한다. OCO 등록 실패 시 해당 포지션을 즉시 시장가로 청산한다 — 손절 없는 포지션을 보유하지 않는다P0

리스크 게이트 (P0)

ID요구사항우선순위
FR-6모든 주문은 집행 전 리스크 게이트를 통과해야 한다. 게이트를 우회하는 집행 경로는 존재하지 않는다P0
FR-7종목당 투입 상한(총자본 대비 비율, 현재 단계값)을 초과하는 주문을 거부한다. 상한은 금액이 아니라 비율로 정의해, 자본이 변하면 포지션도 자동으로 따라 변하게 한다P0
FR-8총 노출 상한(현금 대비 투자 비중)을 초과하는 주문을 거부한다P0
FR-9동시 보유 종목 수 상한(현재 단계값)을 초과하는 신규 진입을 거부한다P0
FR-361주 가격이 종목당 투입 상한을 초과해 1주도 살 수 없는 종목은 후보에서 제외하고, 제외 사유를 기록한다. 100만원·T1(10%) 기준 KRX 117종목 중 63종목(54%)이 여기에 해당한다P0
FR-38리스크 사다리를 지원한다. 종목당 비율·보유 종목 수·일일 손실 한도를 T1/T2/T3 세트로 묶어 관리하고, 승급 조건 충족 여부를 시스템이 판정한다. 승급은 사용자 확인을 거치고, 강등(총자본 -5% 도달)은 즉시 자동 적용한다. 단계 전환 이력을 기록한다P0
FR-39paper 가상 자본의 손익 반영 여부를 설정으로 정한다. M1~M2는 고정(항상 100만원 기준 — 자본 효과를 배제하고 신호 품질·슬리피지를 깨끗하게 측정), M3부터 변동(페이퍼 손익을 자본에 반영해 복리·자동 스케일링을 실제로 검증)P1
FR-10포지션 사이저가 종목별 투입 금액을 산출한다. 산출 근거(총자본·비율·신호 강도)를 기록한다P0
FR-11게이트 거부 시 거부 사유를 기록하고, 거부된 주문은 집행되지 않는다P0

조건부 자동 집행 (P0)

ID요구사항우선순위
FR-12산출 투입 금액이 자동 집행 임계 이하면 승인 없이 자동 집행한다. paper 구간의 임계는 종목당 투입 상한과 같게 두어 사실상 전건 자동으로 돌린다 — 승인 게이트가 데이터 수집 속도만 늦추기 때문이다. live 전환 시 실자본 규모에 맞춰 재설정한다P0
FR-13임계를 초과하면 주문 제안을 만들고 승인을 대기한다. 승인 전에는 집행하지 않는다P0
FR-14대기 제안은 당일 장 마감 시각에 자동 만료된다. 만료된 제안은 승인할 수 없다P0
FR-15자동 집행 임계·손절률·익절률·각종 한도는 코드 상수가 아닌 설정값으로 두고, 재기동으로 변경 가능해야 한다P0

신호·집행 루프 (P0)

ID요구사항우선순위
FR-16매매 유니버스는 KRX 종목만(6자리 숫자 심볼, 2026-08-27 기준 117종목)으로 한정한다. 미국 종목은 후보에서 배제한다P0
FR-37가격 데이터의 통화를 구분해 취급한다. 현재 daily_prices는 통화 컬럼 없이 close 하나에 KRW와 USD가 섞여 있어, 원화 자본 대비 비중 계산이 불가능하다. 유니버스를 KRX로 한정하는 것으로 1차 해소하되, 통화 혼재 자체를 데이터 결함으로 다룬다P0
FR-17기존 4팩터 시그널 스냅샷을 읽어 매수 후보를 선정한다. 신호 산출 로직은 수정하지 않는다P0
FR-18장 운영일·운영시간을 확인해 휴장·시간 외에는 주문을 만들지 않는다. 장 마감 5분 전부터 신규 진입을 중단한다P0
FR-19주문에 멱등 키(clientOrderId)를 부여해 중복 주문을 차단한다P0
FR-20주문 제출이 타임아웃·5xx로 실패하면 재시도하지 않고 주문 상태를 조회해 접수 여부를 확인한다. 확인 불가 시 해당 종목을 당일 매매에서 제외한다P0
FR-21paper 모드는 모의 체결을 기록한다. 체결가는 백테스트와 동일한 비용 모델(수수료·세금·슬리피지)을 적용한다P0

추적·기록 (P0)

ID요구사항우선순위
FR-22포지션(보유 종목·수량·평단·손절가·익절가)을 시스템이 추적한다P0
FR-23실현손익·미실현손익을 기록한다. paperlive를 분리해 집계한다P0
FR-24모든 판단을 감사 로그로 남긴다 — 신호 입력값, 사이징 근거, 게이트 통과·거부 사유, 집행 결과. 사후에 “왜 이 주문이 나갔는가”를 재구성할 수 있어야 한다P0
FR-25자동 집행·승인 요청·거부·손절 발동·한도 도달·킬 스위치 작동을 Discord로 알린다P0

운영·검증 (P1)

ID요구사항우선순위
FR-26대기 중인 제안을 조회하고 승인·거부하는 화면을 제공한다P1
FR-27페이퍼 성과 리포트를 제공한다 — 누적 손익·승률·MDD·평균 보유일P1
FR-28실시간 체결 이벤트(WebSocket personal:order)를 구독해 체결을 즉시 반영한다. 미구현 시 주기 폴링으로 대체한다P1
FR-29백테스트 가정 체결가와 실제 체결가의 차이(실현 슬리피지)를 측정·기록한다P1
FR-30live 전환 전 충족해야 할 게이트 체크리스트를 시스템이 판정한다 — 페이퍼 최소 운영 기간, 집행 실패 0건, 한도 위반 0건P1
FR-31당일 주문 수·체결률·실현손익·한도 소진율을 대시보드로 본다P1

확장 (P2)

ID요구사항우선순위
FR-32매도 신호(하락 전환)에 의한 자동 청산을 지원한다. 1차 범위는 손절·익절 도달 청산만P2
FR-33전략 파라미터(손절률·익절률·사이징 비율) 조합별 페이퍼 성과를 비교한다P2
FR-34세금·수수료를 반영한 세후 실현손익을 산출한다P2

Non-Functional Requirements

성능

항목기준
신호 판정 → 주문 제출P95 3초 이내
킬 스위치 반영1초 이내
체결 감지 → 포지션 반영P95 5초 이내 (WebSocket 기준), 폴링 대체 시 30초 이내
유니버스 전체 1회 평가100종목 기준 60초 이내

외부 API 제약 (2026-08-27 실측)

항목한도대응
ORDER 그룹초당 10회 (09:00~09:10도 동일)자체 스로틀로 8 TPS 상한, 429 도달 0건 목표
ORDER_INFO 그룹초당 6회, 09:00~09:10은 초당 3회개장 10분간 조회 주기를 늘려 피크 한도 준수
CONDITIONAL_ORDER 그룹초당 5회OCO 등록을 체결 이벤트 단위로 직렬화
ACCOUNT 그룹초당 1회계좌 정보는 캐싱, 주문 직전 1회만 갱신
액세스 토큰24시간 (expires_in=86399)만료 60초 전 선제 갱신 (기존 TossAuthClient 재사용)

정합성·안전성

항목기준
중복 주문0건 — 멱등 키로 보장
손절 미등록 포지션0건 — 등록 실패 시 즉시 청산 (FR-5)
리스크 한도 위반 집행0건
체결 기록 누락0건 — 일일 마감 시 토스 체결 내역과 대조
paper 모드에서 발생한 토스 주문 호출0건

가용성

항목기준
장중(09:00~15:30 KST) 가동률99% 이상
프로세스 재기동 후 상태 복구30초 이내, 포지션·한도 소진량 유실 없음
봇 다운 시 손실 방어브로커 측 OCO 주문으로 유지 — 봇 가용성에 손절이 의존하지 않는다

보안

  • 주문 실행 API는 인증 없이 노출하지 않는다.
  • 킬 스위치와 live 전환은 별도 인증을 요구한다.
  • 계좌번호·토큰은 로그에 남기지 않는다.

Operations

알림 (Discord)

이벤트채널시점
자동 매수·매도 체결stock-alert즉시
승인 대기 제안 발생stock-alert즉시
손절·익절 발동stock-alert즉시
일일 손실 한도 80% 도달stock-alert즉시 (사전 경고)
일일 손실 한도 도달·당일 중단stock-alert즉시
킬 스위치 작동·해제stock-alert즉시
주문 실패·상태 확인 불가error-alert즉시
서킷 브레이커 오픈error-alert즉시
일일 마감 요약 (주문 수·체결률·실현손익)stock-alert장 마감 후 1회

대시보드 지표

  • 당일 주문 수 / 체결 수 / 체결률
  • 당일 실현손익, 일일 손실 한도 소진율
  • 총 노출 비중, 보유 종목 수
  • 리스크 게이트 거부 건수 (사유별)
  • 토스 API 429 발생 수, 서킷 상태
  • paper / live 현재 모드

마감 점검 (일 1회)

  • 시스템 체결 기록과 토스 체결 내역 대조 → 불일치 0건 확인
  • 보유 포지션 전량에 유효한 OCO 주문이 걸려 있는지 확인

Success Metrics

페이퍼 단계 (M1~M3)

지표목표측정 방법
자동 집행 실패 (예외로 미집행)0건 / 주감사 로그 집계
리스크 한도 위반 집행0건감사 로그 + 마감 점검
실현 슬리피지와 백테스트 가정의 차이±0.3%p 이내FR-29 측정값 vs cost_model 가정
신호 판정 → 주문 제출 P953초 이내대시보드
킬 스위치 실증훈련 1회 성공 (작동 후 신규 주문 0건)계획된 훈련
체결 기록 누락0건일일 마감 대조
페이퍼 연속 운영20 거래일 이상 무중단가동률 지표
신호 발생 대비 집행률측정만 (목표값 없음)1주 미달·한도 초과로 거부된 비율. T1에서 낮으면 종목당 비율 재검토 근거
사다리 강등 발생0회단계 전환 이력

위 지표는 그대로 T2 승급 조건이기도 하다 (FR-38). 수익률이 아니라 이 운영 지표들로 승급을 판정한다.

라이브 단계 (M4)

지표목표측정 방법
일일 손실 한도 초과0회감사 로그
손절 미등록 포지션0건마감 점검
페이퍼 대비 실거래 실현손익 괴리±1%p 이내동일 기간 비교
중복 주문0건멱등 키 충돌 로그

수익률은 성공 지표에 넣지 않는다. 검증된 엣지가 없는 상태에서 수익률을 목표로 잡으면 리스크 한도를 늘리는 압력이 된다. 이 단계의 성공은 손실이 설계된 한도 안에 있었는가로 판정한다.

Milestones

단계범위완료 조건
M1 페이퍼 루프FR-1, FR-16~FR-24 (모드·유니버스·신호 소비·모의 체결·기록)유니버스 신호가 모의 체결로 기록되고 손익이 집계된다
M2 리스크·안전장치FR-2~FR-11, FR-25, FR-38 (킬 스위치·손실 한도·게이트·사이징·사다리·알림)킬 스위치 훈련 1회 성공, 게이트 우회 경로 0개. T1 고정 운영
M3 조건부 자동 + 검증FR-12FR-15, FR-26FR-31, FR-3920 거래일 페이퍼 운영 완료, 성공 지표 전 항목 충족. 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가 그 경계를 지킨다.

Open Questions

#질문왜 필요한가미해결 시 영향
Q-3일일 손실 한도 단계별 제안값(T1 2% / T2 2.5% / T3 3%)을 확정할 것인가?FR-3의 판정 기준제안값으로 진행하되 paper 운영 중 재조정 가능
Q-4총 손실 한도(MDD) 10%, 강등 트리거 -5% 제안값을 확정할 것인가?FR-4·FR-38의 판정 기준위와 동일
Q-13T2 승급 조건의 “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-10ADR-005·ADR-006을 개정할 것인가, 본 과제 전용 ADR을 새로 쓸 것인가?문서 정합성확정 ADR과 구현이 모순된 채 남는다
Q-12daily_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-11paper 가상 자본100만원

Document History

날짜변경 내용
2026-08-27최초 작성. 범위=신규 독립 과제, 자동화 수준=조건부 자동, 실행 모드=paper+live 포함으로 확정. ADR-005·006과의 충돌을 명시
2026-08-27정정 — 초판의 “일봉 배치가 어디에도 활성화돼 있지 않다”는 사실 오류였다. ~/.zshrc:201true로 설정돼 있었고, 실제 원인은 앱 다운으로 배치가 실행되지 않은 것이었다(24일 누락, 같은 날 백필로 복구). 표본 현황을 실측치로 교체하고 Q-9를 가동률 문제로 재정의
2026-08-27토스 Open API에 sandbox·모의투자 환경이 없음을 확인(서버 1개, 관련 언급 0건). 제약으로 명시하고 FR-35(paper 모드 실주문 경로 부재를 테스트로 강제) 추가
2026-08-27입금을 앱 완성 후로 결정. M1~M3를 paper 전용으로 확정하고 Q-11(가상 자본 규모) 추가
2026-08-27파라미터 확정 — 가상 자본 100만원, 유니버스 KRX 117종목, 종목당 10%×최대 5종목, paper 전건 자동. “확정 파라미터” 섹션 신설, Q-1·Q-2·Q-6·Q-7·Q-11 해소
2026-08-27daily_prices에 미국 82종목이 통화 구분 없이 섞여 있음을 발견. FR-16(KRX 한정)·FR-37(통화 구분)·FR-36(1주 미달 종목 제외) 추가, Q-12 신설
2026-08-27리스크 사다리 도입 — 종목당 비율을 T1 10% / T2 15% / T3 20%로 단계화하고 일일 손실 한도를 2%/2.5%/3%로 연동. 승급 트리거를 수익률이 아닌 운영 지표(T2)·엣지 유의성(T3)으로 정의하고, 총자본 -5%에서 자동 강등을 대칭 배치. FR-38·FR-39 추가, Q-13 신설. 종목당 상한을 금액이 아닌 비율로 정의해 자본 변동에 자동 스케일링되게 명시