
1. 갭 매매 전략이란?
갭 매매란 주가가 전일 종가 대비 큰 폭으로 상승(갭업)하거나 하락(갭다운)하여 개장할 때, 발생한 갭의 움직임을 활용하여 수익을 내는 전략입니다.
이번에 소개할 전략은 다음 조건에 해당하는 종목을 대상으로 합니다.
- 조건검색: 전일 대비 오늘 시가가 5% 이상 갭업으로 시작한 종목
- 전략 실행: 개장 후 30분 이내에 주가가 전일 종가 수준까지 회귀하면 매수 진입 후, 갭이 완전히 메워질 때 매도합니다.
- 손절매: 진입 가격에서 갭 상승분의 50% 하락 시 손절
- 익절매: 갭 상승분의 50% 이상 추가 상승 시 익절합니다.
2. 구현 환경 및 준비사항
- 키움증권 API+ 설치 (영웅문 API)
- Visual Studio Community Edition (C#)
- 키움증권 계좌 (모의투자 계좌 추천)
3. C# 코드 전체 구현 (주석 포함)
다음 코드에는 갭 매매 전략, 주문 실행, 체결 확인 및 정정 주문까지 포함되어 있습니다.
using System;
using System.Collections.Generic;
using AxKHOpenAPILib;
public class GapTrading
{
private AxKHOpenAPI axKHOpenAPI;
private string accountNumber;
// 매수 후 체결된 정보를 저장할 Dictionary (종목코드, (체결가격, 체결수량))
private Dictionary<string, (int price, int qty)> positions = new Dictionary<string, (int, int)>();
public GapTradingStrategy(AxKHOpenAPI api, string accountNo)
{
axKHOpenAPI = api;
accountNumber = accountNo;
axKHOpenAPI.OnReceiveChejanData += OnReceiveChejanData;
axKHOpenAPI.OnReceiveRealData += axKHOpenAPI_OnReceiveRealData;
}
// 1. 갭 상승 확인 후 매매 실행
public void ExecuteGapTrade(string stockCode)
{
int yesterdayClose = int.Parse(axKHOpenAPI.GetMasterLastPrice(stockCode));
int todayOpen = int.Parse(axKHOpenAPI.GetCommRealData(stockCode, 16)); // 시가 실시간 코드: 16
double gapPercent = (todayOpen - yesterdayClose) / (double)yesterdayClose * 100.0;
// 5% 이상 갭업 체크
if (gapPercent >= 5)
{
Console.WriteLine($"[갭업] {stockCode}: {gapPercent}% 상승");
// 개장 30분 내에 전일 종가로 회귀하는 조건 체크
// (이 부분은 실시간 데이터 이벤트를 통해 지속적으로 확인 필요)
}
}
// 실시간 주가 이벤트 핸들러
private void axKHOpenAPI_OnReceiveRealData(object sender, _DKHOpenAPIEvents_OnReceiveRealDataEvent e)
{
string stockCode = e.sRealKey;
int currentPrice = Math.Abs(int.Parse(axKHOpenAPI.GetCommRealData(stockCode, 10))); // 현재가 코드: 10
if (!positions.ContainsKey(stockCode))
{
// 매수 조건 확인 (전일 종가 이하로 회귀)
int yesterdayClose = int.Parse(axKHOpenAPI.GetMasterLastPrice(stockCode));
if (currentPrice <= yesterdayClose)
{
int qty = 10; // 매수 수량
SendOrder(stockCode, 1, qty, currentPrice, "03"); // 시장가 매수
}
}
else
{
// 이미 보유 중이면 손절/익절 체크
ManagePosition(stockCode, currentPrice);
}
}
// 체결 데이터 이벤트 처리
private void axKHOpenAPI_OnReceiveChejanData(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnReceiveChejanDataEvent e)
{
if (e.sGubun == "0") // 체결
{
string stockCode = axKHOpenAPI.GetChejanData(9001).Trim();
int executedPrice = int.Parse(axKHOpenAPI.GetChejanData(910));
int executedQty = int.Parse(axKHOpenAPI.GetChejanData(911));
// 매수 체결인 경우, 포지션 기록
if (!positions.ContainsKey(stockCode))
{
positions.Add(stockCode, (executedPrice, executedQty));
Console.WriteLine($"매수 체결 완료: {stockCode}, 가격: {executedPrice}, 수량: {executedQty}");
}
}
}
// 포지션 관리 (익절/손절 처리)
private void ManagePosition(string stockCode, int currentPrice)
{
if (positions.TryGetValue(stockCode, out (int entryPrice, int qty) position))
{
int yesterdayClose = int.Parse(axKHOpenAPI.GetMasterLastPrice(stockCode));
int gapAmount = position.price - yesterdayClose;
int stopLossPrice = position.price - (gapAmount / 2); // 손절: 갭의 50% 하락 시
int takeProfitPrice = position.price + (gapAmount / 2); // 익절: 갭의 50% 추가 상승 시
if (currentPrice <= stopLossPrice)
{
// 손절매 실행
SendOrder(stockCode, 2, position.qty, currentPrice, "03"); // 시장가 매도
positions.Remove(stockCode);
Console.WriteLine($"손절매 실행: {stockCode}, 가격: {currentPrice}");
}
else if (currentPrice >= takeProfitPrice)
{
// 익절매 실행
SendOrder(stockCode, 2, position.qty, currentPrice, "03", "");
Console.WriteLine($"익절매 실행: {stockCode}, 가격: {currentPrice}");
positions.Remove(stockCode);
}
}
}
// 주문 전송 메서드
private void SendOrder(string stockCode, int orderType, int qty, int price, string hogaGb, string orderNo = "")
{
int result = axKHOpenAPI.SendOrder("AutoTrade", "0101", accountNumber, orderType, stockCode, qty, price, hogaGb, orderNo);
if (result == 0)
{
Console.WriteLine("주문 전송 성공");
}
else
{
Console.WriteLine("주문 전송 실패");
}
}
// 주문 정정 로직 추가
public void CorrectOrder(string stockCode, int newQty, int newPrice)
{
string orderNumber = axKHOpenAPI.GetChejanData(9203); // 기존 주문번호
int cancelResult = axKHOpenAPI.SendOrder("OrderCancel", "0101", accountNumber, 3, stockCode, 0, 0, "00", orderNumber);
if (cancelResult == 0)
{
Console.WriteLine("주문 취소 성공, 새로운 주문 재전송");
SendOrder(stockCode, 2, newQty, newPrice, "00", "");
}
}
private void SendOrder(string stockCode, int orderType, int qty, int price, string hogaGb, string orderNo)
{
axKHOpenAPI.SendOrder("AutoTrade", "0101", accountNumber, orderType, stockCode, qty, price, hogaGb, orderNo);
}
}
4. 주의사항 및 팁
- 실제 거래 전에 반드시 키움증권의 모의투자 계좌를 활용해 충분한 테스트를 진행하세요.
- API 호출 제한, 거래시간 제한 등을 고려하여 구현해야 합니다.
- 손절매와 익절매는 자동매매의 핵심으로, 로직을 철저히 검증하고 실행하세요.
이 글을 참고하여 초단타 매매 전략을 실전에 성공적으로 적용하시길 바랍니다!
'IT개발' 카테고리의 다른 글
만나이 계산기 (0) | 2025.03.10 |
---|---|
한영 타자 변환기 (0) | 2025.03.10 |
Kiwoom OpenAPI를 활용한 자동 주식 매매 프로그램 개발 (0) | 2025.03.10 |
C# 10 & C# 11 주요 업데이트 (0) | 2025.03.06 |
C#에서 비동기 프로그래밍과 병렬 처리 (0) | 2025.03.06 |