파이썬 자동매매 개발, 키움증권 API, PyQt 소개

최근 주식 시장의 자동매매 시스템은 많은 투자자들 사이에서 주목받고 있습니다.
특히 파이썬(Python)은 그 간결함과 강력한 라이브러리들 덕분에 금융 데이터 처리 및 자동 매매 시스템
개발에 적합한 언어로 자리 잡았습니다. 이번 글에서는 키움증권 API를 활용한 자동매매
시스템 개발 방법과 사용자 인터페이스를 구축하기 위한 PyQt의 활용에 대해 알아보겠습니다.

1. 자가 진단: 왜 자동매매 시스템인가?

자동매매 시스템은 인간의 감정이나 순간의 판단에서 벗어나,
사전에 설정한 알고리즘에 따라 자동으로 매매를 수행할 수 있게 해줍니다.
이는 거래의 일관성을 유지하고 거래 시간을 최적화함으로써
수익을 극대화할 수 있는 가능성을 높입니다.

2. 키움증권 API 개요

키움증권 API는 키움증권에서 제공하는 프로그램적으로 매매를 수행할 수 있도록
도와주는 도구입니다. 이 API를 통해 사용자들은 실시간으로
주식 데이터를 조회하고, 주문을 생성하며, 거래 내역을 관리할 수 있습니다.

2.1. 키움 API 설치

키움 API를 사용하기 위해서는 먼저 키움증권의 Open API+를 설치해야 합니다.
설치 후, 다음과 같은 단계를 통해 API를 설정할 수 있습니다.

1. 키움증권의 홈페이지에서 'Open API+'를 다운로드합니다.
2. 설치 후, '키움증권 Open API' 폴더 안의 'OPKorea_1.2.0.exe'를 실행합니다.
3. API 키와 비밀번호를 입력하여 인증을 진행합니다.
4. API가 정상적으로 작동하는지 확인합니다.

2.2. 키움 API의 주요 기능

  • 주식 종목 검색
  • 실시간 시세 조회
  • 주문 및 매매 체결
  • 거래 내역 조회
  • 포트폴리오 관리

3. 파이썬과 키움증권 API 연동

파이썬을 사용하여 키움증권 API를 연동하기 위해서는 PyQt5와 같은 GUI 프레임워크를 병행하여
사용할 수 있습니다. 키움 API와 PyQt5를 활용한 예제 코드를 살펴보겠습니다.

3.1. PyQt5 설치하기

pip install PyQt5
pip install PyQt5-tools

3.2. 키움 API를 통한 로그인 구현하기

아래는 키움증권 API에 로그인하는 기본 코드입니다.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
from PyQt5.QtCore import pyqtSlot
import win32com.client

class Kiwoom(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("키움증권 자동매매 시스템")
        self.setGeometry(300, 300, 400, 300)
        self.login_button = QPushButton("로그인", self)
        self.login_button.clicked.connect(self.login)
        self.login_button.resize(100, 40)
        self.login_button.move(150, 130)

        self.kiwoom = win32com.client.Dispatch("KHOpenAPI.KHOpenAPICtrl.1")
    
    @pyqtSlot()
    def login(self):
        self.kiwoom.CommConnect()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    kiwoom = Kiwoom()
    kiwoom.show()
    sys.exit(app.exec_())

4. 실시간 주식 데이터 조회

이제 로그인 기능을 추가한 후, 실시간 데이터 조회 기능을 추가해 보겠습니다.
실시간 시세를 조회하기 위해서는 데이터 요청을 위한 함수를 작성해야 합니다.

class Kiwoom(QMainWindow):
    # ... 이전 코드 생략 ...
    def retrieve_stock_data(self, stock_code):
        self.kiwoom.SetInputValue("종목코드", stock_code)
        self.kiwoom.CommRqData("주식기본정보", "opt10001", 0, "0101")

    def OnReceiveTrData(self, scrno, rqname, trcode, recordname, prevnext, 
                       dataLength, errorCode, message, splm):
        print("데이터 수신")
        self.current_price = self.kiwoom.GetCommData(trcode, rqname, 0, "현재가")
        print(f"현재가: {self.current_price.strip()}")

4.1. 실시간 데이터 수신 기능 추가

위에서 돌아가는 기본 코드에 `OnReceiveTrData` 메서드를 추가하였습니다.
이 메서드에서는 수신된 데이터의 처리 로직을 구현하게 됩니다.

5. 주문 기능 구현

이제 간단한 주문 기능을 추가해 보겠습니다.
매수, 매도 주문을 처리하기 위한 코드 예제를 살펴보겠습니다.

def buy_stock(self, stock_code, quantity):
    self.kiwoom.SetInputValue("종목코드", stock_code)
    self.kiwoom.SetInputValue("주문수량", quantity)
    self.kiwoom.SetInputValue("가격", 0)  # 시장가
    self.kiwoom.SetInputValue("주문구분", 1)  # 매수
    self.kiwoom.CommRqData("주식주문", "opt00001", 0, "0101")

def sell_stock(self, stock_code, quantity):
    self.kiwoom.SetInputValue("종목코드", stock_code)
    self.kiwoom.SetInputValue("주문수량", quantity)
    self.kiwoom.SetInputValue("가격", 0)  # 시장가
    self.kiwoom.SetInputValue("주문구분", 2)  # 매도
    self.kiwoom.CommRqData("주식주문", "opt00001", 0, "0101")

6. GUI 디자인 최적화

PyQt5를 사용하여 좀 더 직관적이고 사용하기 쉬운 GUI를 설계할 수 있습니다.
다양한 위젯을 사용하여 사용자 경험을 높일 수 있습니다.

self.quantity_input = QLineEdit(self)
self.quantity_input.move(150, 50)
self.quantity_input.resize(100, 30)

self.stock_code_input = QLineEdit(self)
self.stock_code_input.move(150, 90)
self.stock_code_input.resize(100, 30)

self.buy_button = QPushButton("매수", self)
self.buy_button.move(150, 130)
self.buy_button.clicked.connect(self.on_buy_click)

6.1. 주문 버튼 클릭 이벤트 처리

def on_buy_click(self):
    stock_code = self.stock_code_input.text()
    quantity = int(self.quantity_input.text())
    self.buy_stock(stock_code, quantity)

7. 자동매매 알고리즘 개발

이제 자동매매의 핵심인 알고리즘을 구현해 보겠습니다.
간단한 전략을 예제로 들면, 이동 평균 교차 전략을 사용할 수 있습니다.

def moving_average_strategy(self):
    short_window = 5
    long_window = 20
    prices = self.get_past_prices(stock_code)

    short_ma = prices[-short_window:].mean()
    long_ma = prices[-long_window:].mean()

    if short_ma > long_ma:
        self.buy_stock(stock_code, 1)
    elif short_ma < long_ma:
        self.sell_stock(stock_code, 1)

7.1. 과거 가격 데이터 가져오기

def get_past_prices(self, stock_code):
    # 과거 가격 데이터를 가져오는 메서드 구현
    pass

8. 종료 및 지속적 거래

자산을 관리할 때에는 주문이 체결된 후 거래 내역을 모니터링하고,
필요한 조치를 취하는 것이 매우 중요합니다. 거래가 완료된 후에는
포트폴리오를 업데이트하는 절차가 필요합니다.

def update_portfolio(self):
    # 포트폴리오 상태 업데이트 메서드 구현
    pass

결론

본 글에서는 키움증권 API를 사용하여 파이썬으로 간단한 자동매매 시스템을
구현하는 방법을 살펴보았습니다. PyQt를 통해 사용자 인터페이스를 추가함으로써
더욱 직관적이고 사용하기 쉬운 시스템을 만들 수 있었습니다.
다음으로는 이 기초 위에 더 복잡하고 다양한 알고리즘을 추가하여
개인화된 자동매매 시스템을 만드는 것을 추천합니다.