프로젝트

한국투자증권 Open API 기반 주식 자동매매 프로그램 개발일지 #1

Jin-Co 2025. 9. 24. 22:21
반응형

코인 봇 프로젝트에 이어, 이제 국내 주식 시장으로!
코인 봇으로 아직 첫 거래가 이루어지진 않았지만 주식 자동화 프로그램도 개발해 볼까 하는 마음 첫 삽을 뜹니다. 해당 프로젝트는 단순 시세 조회 단계를 넘어 종목발굴, 실시간 데이터를 활용한 자동 매매 및 모니터링을 목표로 합니다. 자동화 구축은 클라우드 서버와 Docker 환경과 Sqlite를 사용하여 무료로 잘 굴러가도록 설계했습니다.


프로젝트 환경

  • 서버: AWS EC2 위에서 Docker로 띄웠습니다. 환경 재현? 배포? Docker면 끝이죠. 안정성도 기본 장착입니다. (아마존 무료서버 구축하기)
  • 언어: Python, Node.js (핫 리로딩 - 설정방법 보러가기)
  • 데이터베이스: SQLite
  • 메시지: Telegram - 설정방법 보러 가기
  • 주요 라이브러리: requests, sqlite3, pandas, python-telegram-bot, python-dotenv. 필요한 건 다 때려 박았습니다.
  • 보안: API Key, Telegram Token 같은 민감한 정보는 secrets.env 파일에 짱박아뒀습니다. 내 정보는 소중하니까요.
# main.py
import time
import pandas as pd
from datetime import datetime
import requests
from config import API_BASE, ACCESS_TOKEN, KIS_API_KEY, KIS_API_SECRET, c, conn, USE_SANDBOX
from telegram_client import send_telegram # Import from the new module

한국투자증권 Open API - 이제 직접 물어본다

  • 모의투자/실전: USE_SANDBOX 변수 하나로 모의랑 실전 모드 왔다 갔다 합니다. 일단 간은 봐야죠?
  • 고난의 토큰 발급: 처음엔 토큰 받다가 헤맸습니다. POST /oauth2/tokenP 이거 하나 찾느라... 그래도 결국 해냈죠.
  • 핵심: 토큰 받고 나니 종목 시세를 분봉 단위로 촤르륵 가져옵니다. 실시간 시세, 제 손안에 있습니다.
  • def get_access_token(): url = f"{API_BASE}/oauth2/tokenP" # ... (쿨하게 토큰 가져오는 로직) return res.json()["access_token"]

서버연결

1. 서버 접속 (EC2 → SSH)

AWS EC2 인스턴스를 만들면 키 페어 (.pem 파일)을 받습니다. 이걸로 서버에 접속하면 됩니다.

 

윈도우 기준 키가 저장된 폴더에서 shell을 열고, 권한설정

chmod 400 <키_경로>

서버접속

ssh -i <키_경로> ubuntu@<서버_IP>

 

👉 ubuntu 대신 Amazon Linux는 ec2-user을 유저네임으로 씁니다.

2. Docker 설치

서버에서 봇을 컨테이너로 돌릴 수 있게 Docker를 설치합니다.

sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose 
sudo systemctl enable docker sudo usermod -aG docker $USER

👉 여기서 한 번 로그아웃/로그인해야 docker 권한이 적용됩니다.

3. 코드 배포

프로젝트 폴더를 서버에 올립니다. (/home/ubuntu/ 는 서버 생성 시 기본경로)

scp -i <키_경로> <파일경로> ubuntu@<서버주소>:/home/ubuntu/

4. Docker 빌드 & 실행

cd <프로젝트 폴더명> 
docker-compose run

 

5. 실행 확인

docker ps
docker logs -f <이미지명>

데이터 저장 - 기억은 미화되지만, 데이터는 남는다

  • 데이터베이스: SQLitestocks.db라는 이름으로 차곡차곡 저장합니다.
  • 스키마: 필요한 것만 딱. 가격, 거래량, 코드, 시간. 이게 전부입니다.
  • CREATE TABLE IF NOT EXISTS stock_data( code TEXT, -- 종목 코드 date TEXT, -- 시간은 곧 돈 open REAL, -- 시가 high REAL, -- 고가 low REAL, -- 저가 close REAL, -- 종가 (중요!) volume INTEGER -- 거래량 (더 중요!) )
  • 활용: 이 데이터를 기반으로 나중에 백테스팅이고 뭐고 다 할 겁니다.
# 데이터 저장
def save_stock_data(data):
    c.execute(
        """
        INSERT INTO stock_data (code, date, open, high, low, close, volume)
        VALUES (?, ?, ?, ?, ?, ?, ?)
        """,
        (
            data["code"],
            data["date"],
            data["open"],
            data["high"],
            data["low"],
            data["close"],
            data["volume"],
        ),
    )
    conn.commit()

추가로, SQLite는 파일형식의 데이터베이스로 서버가 재가동되면 데이터도 사라지므로 데이터를 지속하려면 추가설정이 필요합니다. 여러 방법 중 저는 docker-compose.yml파일을 생성하여 볼륨설정 (프로젝트와 데이터를 따로 관리하도록 설정)

version: '3.8'

services:
  stock_bot:
    build: .
    volumes:
      - stock_data:/app/data
    env_file:
      - .env

volumes:
  stock_data:

텔레그램 알림 - 귓속말이 아니라 실시간 속보

  • 봇 출동: 모니터링 결과를 텔레그램으로 바로 쏴줍니다. 휴대폰만 봐도 시장 상황 파악 끝.
  • 똑똑한 알림: "평균 종가 몇!", "거래량 폭발!" 등 조건 맞으면 즉시 핑 띄워줍니다. 비서가 따로 없습니다.
  • def send_telegram(msg): bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=msg)
# telegram_client.py
from config import bot, TELEGRAM_CHAT_ID

def send_telegram(msg: str):
    """
    Sends a text message to the specified Telegram chat.

    Args:
        msg: The string message to be sent.
    """
    try:
        bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=msg)
        print(f"Message sent to Telegram: {msg}")
    except Exception as e:
        print(f"Failed to send Telegram message: {e}")

핵심 로직 - 시작은 가볍게

STOCK_LIST = ["005930", "000660", "035420"]

while True:
    prices = [get_stock_price(code) for code in STOCK_LIST]
    avg_close = sum([p["close"] for p in prices if p]) / len(prices)
    send_telegram(f"평균 종가: {avg_close:.2f}")
    time.sleep(60 * 5)
  • 현재: 일단 삼성전자, SK하이닉스, NAVER 3대 장만 주시 중입니다.
  • 미래: 나중엔 지가 알아서 유망 종목 찾아내서 리스트에 추가하고 감시할 겁니다. 지금은 5분 간격으로 시세 긁어오고 평균 종가만 알리지만, 곧 봇이 직접 투자하는 그림을 그립니다.

배포 및 운영 - 봇은 오늘도 쉬지 않는다

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "han_invest_auto.py"]
  • 컨테이너: Dockerfile로 포장해서 EC2 서버에서 돌립니다. 깔끔하죠. Dockerfile은 이미지 설계도로 서버가동을 자동화해 주는 등 운영을 편리하게 해 줌

다음 목표 - 어디까지 갈 수 있을까?

  • 스마트 종목 발굴: 전 종목 스캔해서 내 기준에 맞는 녀석들만 쏙쏙 골라냅니다.
def discover_stocks():
    all_codes = get_all_stock_codes()
    candidates = []
    for code in all_codes:
        data = get_stock_price(code)
        if data and data["volume"] > 1_000_000:
            candidates.append(code)
    return candidates
  • 실제 매매: 매수/매도 API 연결해서 진짜 돈을 벌어볼 때입니다.
def buy_stock(code, qty):
    url = f"{API_BASE}/uapi/domestic-stock/v1/trading/order-cash"
    headers = {
        "authorization": f"Bearer {ACCESS_TOKEN}",
        "appkey": KIS_API_KEY,
        "appsecret": KIS_API_SECRET,
        "tr_id": "TTTC0802U"  # 매수 주문
    }
    body = {
        "CANO": "계좌번호앞8자리",
        "ACNT_PRDT_CD": "01",
        "PDNO": code,
        "ORD_DVSN": "01",  # 시장가
        "ORD_QTY": str(qty),
        "ORD_UNPR": "0"    # 시장가일 때 0
    }
    res = requests.post(url, headers=headers, json=body)
    return res.json()
  • 전략 고도화: 백테스팅 돌려가며 전략 보강하고, 리스크 관리까지 완벽하게. 제 봇은 매일 진화합니다.
import backtrader as bt

class MovingAverageStrategy(bt.Strategy):
    def __init__(self):
        self.sma = bt.indicators.SimpleMovingAverage(period=20)

    def next(self):
        if self.data.close[0] > self.sma[0]:
            self.buy(size=10)
        elif self.data.close[0] < self.sma[0]:
            self.sell(size=10)

그리고 효율적인 개발을 위해 로컬과 서버 동기화는 필수이죠 (설정방법 보러 가기)

마무리

지금까지 '한국투자증권 Open API 기반 주식 자동매매 프로그램 개발일지 #1'을 통해 대략적인 프로젝트 구조와 코드예지, 프로젝트의 시작부터 텔레그램 알림 봇 연동까지, 핵심적인 부분들을 함께 살펴보았습니다. 단순히 코드를 짜는 것을 넘어, 이렇게 스마트한 알림 시스템을 구축함으로써 또 하나의 비서가 생긴 느낌입니다.

 

다음 개발일지에서는 더 심화된 로직과 실제 매매 기능, 그리고 백테스팅 방법에 대해 다룰 예정이니 기대해 주세요! 여러분의 스마트한 투자 여정에 이 프로젝트가 큰 도움이 되기를 바랍니다. 다음 편에서 만나요!

728x90
반응형