주식 자동매매 프로그램 전략 엔진 1차 개선 기록
요약
2026년 5월 8일, 주식 자동매매 프로그램의 전략 엔진을 1차 개선했다.
이번 작업은 프로그램을 완전히 새로 설계하는 작업이 아니라, 실제 계좌 운영 데이터를 바탕으로 현재 전략의 약점을 줄이고 다음 단계 개선을 위한 구조를 정리하는 작업이었다.
최근 약 2주간의 실계좌 운영 결과를 보면, 기존 전략은 수익보다 손실 쪽의 폭이 더 큰 구조였다. 평균 수익은 약 2.5% 수준이었고, 손절은 약 -3.0% 수준이었다. 결과적으로 손익비가 약 0.8:1에 가까워 장기 운용에는 불리한 구조였다.
자동매매 프로그램은 단순히 매수 신호를 많이 찾는 것이 중요한 것이 아니다. 진입했을 때 손실은 제한하고, 수익은 더 길게 가져갈 수 있는 구조가 필요하다.
이번 개선의 핵심
이번 개선에서 정리한 핵심은 다음과 같다.
- 1,000만 원 실계좌 운용 기준 반영
- 종목당 투자금 200만 원 기준 설정
- 현금 20% 유보 구조 적용
- 손절 기준을 -3.0%에서 -2.5%로 조정
- 목표 수익률 +5.0% 기준 추가
- MA20 이격 기준을 7%에서 5%로 강화
- 보유기간을 10거래일에서 5거래일로 단축
- 섹터 중복 진입 제한 추가
- RSI 모멘텀 조건 추가
- 손익분석 로그 위치 수정
이번 패치에서는 config.py, risk_engine.py, rule_engine.py, main.py를 중심으로 전략 파라미터를 정리했다.
자본 구조 정리
가장 큰 변화는 운용 구조다.
기존에는 종목당 투자금과 전체 운용 자금 기준이 다소 느슨하게 연결되어 있었다. 이번에는 총 운용 기준을 1,000만 원으로 잡고, 종목당 투자금을 200만 원으로 정리했다.
최대 보유 종목 수는 4종목으로 설정했다. 이를 통해 전체 자금의 약 80%만 포지션에 사용하고, 나머지 20%는 현금으로 남기는 구조를 만들었다.
이 구조는 급락장, 추가 매수 기회, 시스템 오류 상황에 대응하기 위한 최소한의 완충 장치다.
손절과 목표 수익 구조
손절 기준은 기존 -3.0% 수준에서 -2.5%로 더 타이트하게 조정했다. 목표 수익률은 +5.0%로 신규 설정했다.
이 기준만 놓고 보면 손익비는 2.0:1 구조가 된다.
다만 이번 패치에서는 손익비 필터를 실제 매수 차단 조건으로 사용하지 않았다. RR_FILTER_ENABLED=False 상태로 두고, 우선 로그만 출력하도록 했다.
아직 손절가가 모든 종목에 동일하게 적용되고 있기 때문이다. 종목별 변동성을 반영하지 않은 고정 손절 구조에서는 손익비 필터를 바로 활성화해도 실질적인 차별성이 크지 않다.
따라서 손익비 필터는 다음 단계에서 ATR 기반 동적 손절 구조를 적용한 뒤 활성화하는 것이 더 적절하다고 판단했다.
섹터 중복 제한과 RSI 모멘텀
이번 개선에서는 동일 섹터 종목이 중복으로 매수되는 것을 막기 위해 SECTOR_MAP을 추가했다.
현재 유니버스 20종목에 대해 섹터를 수동 매핑하고, 이미 같은 섹터 종목을 보유 중이면 신규 매수를 건너뛰도록 했다. 예를 들어 반도체 종목을 이미 보유 중이라면, 다른 반도체 종목이 조건을 만족하더라도 신규 매수는 제한된다.
이 기능은 자동매매 프로그램이 특정 테마나 섹터에 과도하게 쏠리는 것을 막기 위한 장치다.
RSI 조건도 보완했다. 기존에는 RSI가 일정 범위 안에 들어오는지만 판단했다. 이번에는 RSI 현재값이 직전값보다 높고, 현재값이 30 이상인지 함께 확인하도록 했다.
단순 낙폭 과대 종목이 아니라, 반등 모멘텀이 실제로 생기고 있는 종목을 더 선별하려는 의도다.
청산 우선순위 재정렬
청산 로직도 명확하게 정리했다.
우선순위는 다음과 같다.
- 손절
- 트레일링 스탑
- 일일손실한도 초과
- 보유기간 초과
- 추세이탈
손절, 트레일링, 일일손실한도는 즉시 청산 조건으로 분류했다. 반면 추세이탈은 다음 시가 청산 방식으로 분류했다.
이렇게 우선순위를 정리한 이유는 자동매매 프로그램이 여러 조건을 동시에 만났을 때 어떤 판단을 먼저 해야 하는지 명확히 하기 위해서다.
손익분석 로그 위치 수정
이번 작업에서 중요한 수정 중 하나는 [손익분석] 로그의 위치 변경이다.
기존에는 손익분석 로그가 실제 매수 수량 계산 단계에서 출력되었다. 문제는 MA20 이격, RSI, RS 등 앞단 필터에서 종목이 탈락하면 손익분석 로그가 아예 출력되지 않는다는 점이었다.
이러면 운영자가 다음 내용을 확인하기 어렵다.
- 종목이 어느 가격에서 검토되었는지
- 손절가는 얼마로 계산되었는지
- 목표가는 얼마로 설정되었는지
- 손익비 구조는 어떻게 잡혔는지
- 어느 필터에서 탈락했는지
그래서 이번에는 [손익분석] 로그를 check_buy_signal() 함수의 종목별 루프 진입 직후로 이동했다.
이제는 매수 후보로 검토되는 종목마다 먼저 손익분석 로그가 출력되고, 그 다음에 MA20 이격, RSI, RS 등의 필터 탈락 사유가 이어서 기록된다.
이 변경은 단순한 로그 위치 수정이지만, 운영 관점에서는 매우 중요하다. 자동매매 프로그램은 결과보다 판단 과정이 더 중요하기 때문이다.
DRY RUN 결과
2026년 5월 8일 기준 DRY RUN 결과, 실제 매수 신호는 발생하지 않았다.
탈락 원인은 다음과 같았다.
| 탈락 원인 | 건수 |
|---|---|
| MA20 이격 5% 초과 | 9건 |
| MA20 하회 | 8건 |
| RSI 범위 이탈 | 1건 |
| RS 탈락 | 1건 |
| BUY 신호 도달 | 0건 |
이번 결과는 버그가 아니라 정상 동작으로 해석했다.
최근 KOSPI가 단기간에 크게 상승하면서 여러 종목이 MA20 대비 과도하게 이격된 상태였다. 전략 엔진은 이 상황에서 추격 매수를 차단했다.
즉, 매수 0건은 프로그램이 멈춘 것이 아니라, 현재 시장 조건에서 진입하지 않는 것이 더 적절하다고 판단한 결과다.
이번 작업의 의미
이번 개선은 자동매매 프로그램을 더 공격적으로 만드는 작업이 아니었다.
오히려 반대에 가깝다.
이번 작업의 핵심은 다음과 같다.
- 무리한 진입을 줄인다.
- 손절 기준을 더 명확히 한다.
- 수익 목표와 손실 한계를 구조화한다.
- 섹터 쏠림을 줄인다.
- 로그를 통해 판단 과정을 더 잘 보이게 만든다.
자동매매 프로그램은 수익을 내는 코드이기 전에, 손실을 통제하는 운영 시스템이어야 한다.
이번 개선은 그 방향으로 가기 위한 1차 정리 작업이었다.
다음 개선 예정
다음 단계에서는 다음 항목을 우선 검토한다.
- ATR 기반 종목별 동적 손절가 계산
- 손익비 필터 활성화
- 로그 태그 형식 통일
- 미사용 상수 정리
- 고가주 트레일링 기준 통일
- 수수료와 세금 반영
이번 패치로 전략 엔진의 기본 구조는 더 명확해졌다. 다음 단계에서는 고정 손절 구조를 종목별 변동성 기반 구조로 전환하는 것이 핵심 과제가 될 것이다.
관련 Insight: 자동매매에서 중요한 것은 매수 신호보다 탈락 이유다
※ 본 콘텐츠는 개인의 실험 기록이며 투자 권유가 아닙니다.
투자의 판단과 책임은 본인에게 있습니다.