📖 "말만 하지 말고 코인 트레이딩 해봅시다"

어느 날, 평범한 직장인 '엑셀'은 매일 시세만 들여다보며 이렇게 중얼거렸다.

“왜 내가 사면 떨어지고, 팔면 오르는 거지…?”

그날도 출근길에 코인 차트를 보던 엑셀은 문득 이런 생각을 하게 된다.

“내가 사는 가격, 파는 가격을 엑셀에 적어두면, 파이썬이 대신 사고팔아주면 안 되나?”

엑셀은 곧장 집으로 달려가 노트북을 켰다. 그리고 이렇게 외쳤다.

“그래, 자동 매매를 만드는 거야! 내가 주인공인 시스템 트레이딩의 시작이야!”


🧱 Step 1. 엑셀로 트레이딩 전략 정리

엑셀 파일 이름: coin_trading.xlsx

코인명매수가매도가
BTC 70000000 73000000
ETH 4000000 4200000
 

💡 엑셀에 사고 싶은 가격(매수가)와 팔고 싶은 가격(매도가)을 적기만 하면 된다!


🔌 Step 2. 업비트 API 연동

업비트는 모의투자를 공식적으로 제공하지 않지만, 실제 API 키로 소액으로 테스트하거나 백테스트로 전략을 시뮬레이션할 수 있습니다.

먼저 pyupbit 설치:


pip install pyupbit openpyxl

🤖 Step 3. 파이썬 자동 매매 코드

import pyupbit
import time
import pandas as pd

# 업비트 API 키 입력
access_key = "YOUR_ACCESS_KEY"
secret_key = "YOUR_SECRET_KEY"
upbit = pyupbit.Upbit(access_key, secret_key)

# 엑셀에서 매매 전략 불러오기
df = pd.read_excel("coin_trading.xlsx")

def get_current_price(ticker):
    try:
        return pyupbit.get_current_price(ticker)
    except Exception as e:
        print(f"가격 조회 실패: {e}")
        return None

for index, row in df.iterrows():
    coin_name = row['코인명']
    buy_price = row['매수가']
    sell_price = row['매도가']

    ticker = f"KRW-{coin_name}"
    current_price = get_current_price(ticker)

    if current_price is None:
        continue

    print(f"[{coin_name}] 현재가: {current_price}, 목표 매수가: {buy_price}, 목표 매도가: {sell_price}")

    # 매수 조건
    if current_price <= buy_price:
        print(f"📥 {coin_name} 매수 시도 중...")
        try:
            krw_balance = upbit.get_balance("KRW")
            if krw_balance >= 5000:
                order = upbit.buy_market_order(ticker, 5000)  # 5000원 매수
                print(f"✅ 매수 완료: {order}")
            else:
                print("❌ 잔고 부족")
        except Exception as e:
            print(f"매수 실패: {e}")

    # 매도 조건
    elif current_price >= sell_price:
        print(f"📤 {coin_name} 매도 시도 중...")
        try:
            coin_balance = upbit.get_balance(ticker)
            if coin_balance and coin_balance > 0:
                order = upbit.sell_market_order(ticker, coin_balance)
                print(f"✅ 매도 완료: {order}")
            else:
                print("❌ 보유 수량 없음")
        except Exception as e:
            print(f"매도 실패: {e}")

    time.sleep(1)  # 너무 자주 호출하면 제한 걸림
 
 

🛡️ 안전을 위한 팁

  • ✅ 실 계정 전에 백테스트 필수!
  • ✅ 금액 제한 (5000원, coin_balance) 등 실수 방지 코드 필수!
  • ✅ 반복 실행 시 while True: 루프와 스케줄러로 자동화 가능

🎯 결론: 당신도 엑셀이 될 수 있다

이제 당신은 ‘차트를 바라보며 한숨 쉬던 엑셀’이 아닌,
**“엑셀에 가격만 적어도 자동으로 움직이는 트레이딩 시스템의 주인공”**입니다.


🤩 다음 단계 아이디어

  • 실시간 감시 GUI (PyQt 연동)
  • 전략 다양화 (틱 단위 분할 매수, 이동평균 돌파 등)
  • 백테스트 시스템 결합
  • 로그 기록 자동 저장
Posted by 제이브레인
,

🧱 1단계 – 콘솔에서 혼자 거래를 시작합니다

처음에는 파이썬으로 주식 매매 프로그램을 간단히 만들었습니다.
엑셀 파일에 종목, 매수가, 매도가를 기록하고, 매매 조건에 따라 콘솔에 매수/매도 메시지를 출력합니다.

🔹 사용한 코드:

            current_price = get_current_price(kiwoom, code)
            print(f"[{name}] 현재가: {current_price} | 매수: {buy_price} | 매도: {sell_price}")

            qty = 10  # 10주 매매 예시

            if current_price <= buy_price and name not in bought:
                print(f"[매수] {name} @ {current_price}")
                kiwoom.SendOrder("매수", "1001", account, 1, code, qty, 0, "03", "")
                bought.add(name)
                sold.discard(name)

            elif current_price >= sell_price and name not in sold:
                print(f"[매도] {name} @ {current_price}")
                kiwoom.SendOrder("매도", "1002", account, 2, code, qty, 0, "03", "")
                sold.add(name)
                bought.discard(name)

하지만 문제는 매매 내역만 볼 수 있고, 현재 어떤 종목을 가지고 있는지 확인하기가 어렵다는 점입니다.
보유 종목 현황이 없어 불편함을 느낍니다.


💡 2단계 – GUI로 보유 주식을 눈으로 확인하고자 합니다

콘솔 출력만으로는 부족하다는 것을 깨닫고, GUI를 통해 보유 주식을 시각적으로 보여주자는 결심을 합니다.
PyQt를 이용하여 간단한 창과 표를 만드는 것부터 시작합니다.


🪟 3단계 – PyQt5로 테이블 GUI를 구성합니다

PyQt5를 사용하여 종목명, 수량, 평균 매수가를 보여주는 테이블을 생성합니다.

🔹 PyQt 기본 구조:

import sys
import time
import pandas as pd
from datetime import datetime
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimer
from pykiwoom.kiwoom import Kiwoom

EXCEL_PATH = "stocks.xlsx"
LOG_FILE = "trade_log.txt"
INTERVAL_MS = 30000  # 30초 주기

class TradingBot(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("\U0001F4C8 Excel 기반 자동 매매 시스템")
        self.setGeometry(300, 100, 900, 700)

        self.kiwoom = Kiwoom()
        self.kiwoom.CommConnect(block=True)
        self.account = self.kiwoom.GetLoginInfo("ACCNO")[0]
        self.account_pw = ""

        self.bought_set = set()
        self.sold_set = set()

        self.init_ui()
        self.get_password()
        self.update_holdings()
        self.log("시스템 트레이딩 시작됨 ✅")

        self.timer = QTimer()
        self.timer.timeout.connect(self.run_trading)
        self.timer.start(INTERVAL_MS)

    def init_ui(self):
        self.text_log = QTextEdit()
        self.text_log.setReadOnly(True)

        self.btn_manual = QPushButton("\U0001F501 수동 실행")
        self.btn_manual.clicked.connect(self.run_trading)

        self.status_label = QLabel("⏱️ 대기 중...")

        self.table = QTableWidget()
        self.table.setColumnCount(4)
        self.table.setHorizontalHeaderLabels(["종목명", "수량", "매입가", "현재가"])
        self.table.horizontalHeader().setStretchLastSection(True)

        layout = QVBoxLayout()
        layout.addWidget(self.text_log)
        layout.addWidget(self.status_label)
        layout.addWidget(self.btn_manual)
        layout.addWidget(QLabel("\n📦 현재 보유 종목"))
        layout.addWidget(self.table)

        central = QWidget()
        central.setLayout(layout)
        self.setCentralWidget(central)

    def get_password(self):
        pw, ok = QInputDialog.getText(self, "계좌 비밀번호 입력", "계좌 비밀번호를 입력하세요:", QLineEdit.Password)
        if ok and pw:
            self.account_pw = pw
            self.log("🔐 계좌 비밀번호가 등록되었습니다.")
        else:
            QMessageBox.critical(self, "오류", "비밀번호가 입력되지 않았습니다. 프로그램을 종료합니다.")
            sys.exit(1)

    def log(self, message):
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_msg = f"[{now}] {message}"
        self.text_log.append(log_msg)
        with open(LOG_FILE, "a", encoding="utf-8") as f:
            f.write(log_msg + "\n")

    def read_excel(self):
        return pd.read_excel(EXCEL_PATH)

    def name_to_code(self, name):
        codes = self.kiwoom.GetCodeListByMarket('0') + self.kiwoom.GetCodeListByMarket('10')
        for code in codes:
            if self.kiwoom.GetMasterCodeName(code) == name:
                return code
        return None

    def get_current_price(self, code):
        price = self.kiwoom.GetMasterLastPrice(code)
        if isinstance(price, str):
            return int(price.replace(",", ""))
        elif isinstance(price, int):
            return price
        else:
            return 0

    def run_trading(self):
        self.status_label.setText("🔍 주가 확인 중...")
        df = self.read_excel()

        for _, row in df.iterrows():
            name = row['종목명']
            buy_price = int(row['매수가'])
            sell_price = int(row['매도가'])
            code = self.name_to_code(name)

            if not code:
                self.log(f"[오류] 종목명 {name} → 코드 변환 실패")
                continue

            current = self.get_current_price(code)
            self.log(f"{name} 현재가: {current} / 매수: {buy_price} / 매도: {sell_price}")

            qty = 10

            if current <= buy_price and name not in self.bought_set:
                self.log(f"📥 매수 주문: {name} @ {current}")
                self.kiwoom.SendOrder("매수", "1001", self.account, 1, code, qty, 0, "03", "")
                self.bought_set.add(name)
                self.sold_set.discard(name)

            elif current >= sell_price and name not in self.sold_set:
                self.log(f"📤 매도 주문: {name} @ {current}")
                self.kiwoom.SendOrder("매도", "1002", self.account, 2, code, qty, 0, "03", "")
                self.sold_set.add(name)
                self.bought_set.discard(name)

        self.update_holdings()
        self.status_label.setText("⏱️ 대기 중...")

    def update_holdings(self):
        try:
            data = self.kiwoom.block_request("opw00018",
                                             계좌번호=self.account,
                                             비밀번호=self.account_pw,
                                             비밀번호입력매체구분="00",
                                             조회구분=2,
                                             output="계좌평가잔고개별합산",
                                             next=0)

            self.log(f"[디버그] 계좌번호: {self.account}")
            self.log(f"[디버그] 비밀번호: {'입력됨' if self.account_pw else '미입력'}")
            self.log(f"[디버그] opw00018 응답 타입: {type(data)}")
            self.log(f"[디버그] opw00018 응답: {data}")

            if not isinstance(data, dict) or '종목번호' not in data:
                self.log("[경고] 보유 종목 정보가 없습니다.")
                self.table.setRowCount(0)
                return

            codes = data['종목번호']
            names = data['종목명']
            qtys = data['보유수량']
            prices = data['매입가']

            self.table.setRowCount(len(codes))
            for i in range(len(codes)):
                name = names[i].strip()
                qty = int(qtys[i]) if str(qtys[i]).strip().isdigit() else 0
                buy_price = int(prices[i]) if str(prices[i]).strip().isdigit() else 0
                cur_price = self.get_current_price(codes[i].strip())

                self.table.setItem(i, 0, QTableWidgetItem(name))
                self.table.setItem(i, 1, QTableWidgetItem(str(qty)))
                self.table.setItem(i, 2, QTableWidgetItem(str(buy_price)))
                self.table.setItem(i, 3, QTableWidgetItem(str(cur_price)))
        except Exception as e:
            self.log(f"[보유 종목 조회 오류] {str(e)}")

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

이제 콘솔이 아닌 GUI 창을 통해 보유 종목을 확인할 수 있게 됩니다.
한눈에 보기 편하고, 시각적으로도 깔끔해서 훨씬 관리가 쉬워집니다.


🏁 4단계 – GUI를 통해 실전 트레이딩을 관리합니다

PyQt로 보유 현황을 시각화한 후, 프로그램의 실용성이 크게 향상되었습니다.
더 이상 콘솔 메시지를 뒤져볼 필요 없이, 어떤 종목을 몇 주나 가지고 있는지, 평단가는 얼마인지 한눈에 확인할 수 있습니다.
트레이딩 과정이 체계적으로 정리되어 개발자이자 트레이더로서의 만족도가 매우 높아졌습니다.


✅ 정리

구분 개선 전 개선 후
데이터 확인 콘솔 로그 GUI 테이블
시각화 없음 실시간 보유 종목 표시
사용성 불편 직관적이고 명확함
 

GUI를 도입한 이 작은 변화는 프로그램의 품질을 한 단계 끌어올렸습니다.
이제 이 주식 트레이더는 콘솔 속에서 혼잣말을 하던 시절을 뒤로하고,
PyQt라는 창을 통해 매매를 직관적이고 명확하게 관리하고 있습니다.

Posted by 제이브레인
,

📘 AI는 너무 멀고, 엑셀은 가깝다 – 파이썬으로 자동 주식 매매하기


🧠 Chapter 1. 인공지능 시스템 트레이딩은… 멋지지만

"딥러닝으로 시장을 예측하고 싶다…"
"RNN으로 주가를 예측해볼까?"
"Transformer 기반 모델에 재무제표를 넣으면?"

그렇다.
AI 기반 시스템 트레이딩은 정말 멋집니다.
하지만 문제는…
📆 시간이 너무 많이 듭니다.
📚 논문 읽고,
🧮 모델 만들고,
⚙️ 튜닝하고,
💀 수익은 안 나고…

그래서 나는 생각했습니다.

"이걸 진짜 간단하게 시작할 방법은 없을까?"


🧾 Chapter 2. 엑셀로 전략을 세우고, 파이썬으로 실행하자!

하루를 마무리하며 커피 한 잔.
나는 엑셀을 열고 이렇게 적었습니다.

종목명 매수가 매도가
삼성전자 70000 73000
카카오 45000 48000
 
혹시라도 오피스가 없는 분들은 엑셀을 구글 쉬트에서 만들 수 있습니다.
 
구글? AI는 너무 멀고, 엑셀은 가깝다 – 파이썬으로 자동 주식 매매하기
🧠 Chapter 1. 인공지능 시스템 트레이딩은… 멋지지만
"딥러닝으로 시장을 예측하고 싶다…"
"RNN으로 주가를 예측해볼까?"
"Transformer 기반 모델에 재무제표를 넣으면?"
 
그렇다.
AI 기반 시스템 트레이딩은 정말 멋집니다.
하지만 문제는…
📆 시간이 너무 많이 듭니다.
📚 논문 읽고,
🧮 모델 만들고,
⚙️ 튜닝하고,
💀 수익은 안 나고…
 
그래서 나는 생각했습니다.
 
"이걸 진짜 간단하게 시작할 방법은 없을까?"
 
🧾 Chapter 2. 엑셀로 전략을 세우고, 파이썬으로 실행하자!
하루를 마무리하며 커피 한 잔.
나는 엑셀을 열고 이렇게 적었습니다.
 
종목명 매수가 매도가
삼성전자 70000 73000
카카오 45000 48000
 
혹시라도 오피스가 없는 분들은 엑셀을 구글 쉬트에서 만들 수 있습니다.
구글 앱 중에 구글 쉬트가 있습니다.
 

구글 쉬트에서 위와 같이 입력 후 파일 > 다운로드 > Microsoft Exel 을 선택하면 됩니다.

 
 

“내가 원하는 가격에 사서, 원하는 가격에 팔아줘”
이 전략은 단순하다.
하지만 꾸준히, 빠르게, 감정 없이 실행만 해준다면?
사람보다 나을 수도 있지 않을까?

그래서 파이썬에게 시켰습니다.


🔧 Chapter 3. 만드는 방법은 이렇게 간단합니다.

1단계: 필요한 도구 설치

pip install pandas openpyxl pykiwoom

2단계: 엑셀 만들기 (stocks.xlsx)

종목명 매수가 매도가
삼성전자 70000 73000
카카오 45000 48000
 

저장 후 닫아두자. 나머지는 파이썬이 알아서 합니다.


🤖 Chapter 4. 파이썬 시스템 트레이딩 코드

import pandas as pd
from pykiwoom.kiwoom import Kiwoom
import time

EXCEL_PATH = "stocks.xlsx"
CHECK_INTERVAL = 30  # 몇 초마다 주가를 확인할지

def read_excel(path):
    return pd.read_excel(path)

def name_to_code(kiwoom, name):
    market_codes = kiwoom.GetCodeListByMarket('0') + kiwoom.GetCodeListByMarket('10')
    for code in market_codes:
        if kiwoom.GetMasterCodeName(code) == name:
            return code
    return None

def get_current_price(kiwoom, code):
    price = kiwoom.GetMasterLastPrice(code)
    if isinstance(price, str):
        return int(price.replace(",", ""))
    elif isinstance(price, int):
        return price
    else:
        return 0

def auto_trade_loop(kiwoom, account):
    bought = set()
    sold = set()

    while True:
        df = read_excel(EXCEL_PATH)
        for _, row in df.iterrows():
            name = row['종목명']
            buy_price = int(row['매수가'])
            sell_price = int(row['매도가'])
            code = name_to_code(kiwoom, name)

            if not code:
                print(f"[{name}] 종목 코드 못 찾음.")
                continue

            current_price = get_current_price(kiwoom, code)
            print(f"[{name}] 현재가: {current_price} | 매수: {buy_price} | 매도: {sell_price}")

            qty = 10  # 10주 매매 예시

            if current_price <= buy_price and name not in bought:
                print(f"[매수] {name} @ {current_price}")
                kiwoom.SendOrder("매수", "1001", account, 1, code, qty, 0, "03", "")
                bought.add(name)
                sold.discard(name)

            elif current_price >= sell_price and name not in sold:
                print(f"[매도] {name} @ {current_price}")
                kiwoom.SendOrder("매도", "1002", account, 2, code, qty, 0, "03", "")
                sold.add(name)
                bought.discard(name)

        print(f"🕐 {CHECK_INTERVAL}초 후 다시 확인...\n")
        time.sleep(CHECK_INTERVAL)

def main():
    kiwoom = Kiwoom()
    kiwoom.CommConnect(block=True)
    account = kiwoom.GetLoginInfo("ACCNO")[0]
    auto_trade_loop(kiwoom, account)

if __name__ == "__main__":
    main()

 

파일 삭제 실패 오류

실행 시 아래와 같은 에러가 발생할 수 있습니다.

이 경우 권한 부족 때문에 발생할 수 있습니다.

아래 폴더로 이동한 후 opversionup.exe 프로그램을 관리자 권한으로 실행하세요.

C:\OpenAPI

 

비밀번호 오류

계좌 비밀번호 입력창을 통해 계좌 비밀번호를 입력 및 등록하십시오

라는 에러가 발생하는 경우가 있을 수 있습니다.

 

윈도우 우측 하단을 보면 KOAStudio 실행 아이콘이 보입니다.

여기에서 계좌 비밀번호 저장을 선택 후 비밀번호를 등록하고 AUTO 체크 박스를 체크하면 됩니다.

혹시라도 아이콘이 보이지 않으면 C:\OpenAPI 에서 KOAStudioSA.exe 를 관리자 권한으로 실행 시킵니다.

이후 파일 > Open API 접속을 선택하면 됩니다.

✅ Chapter 5. 결과는?

  • 종목명을 엑셀에 적습니다.
  • 매수/매도 가격을 쓰면,
  • 파이썬이 지정가가 되면 매수하고, 매도가 되면 팔아줍니다.

이걸 모의투자부터 돌려보자.
진짜로 "자동 매매"가 눈앞에서 벌어집니다.


🏁 Chapter 6. 결론

AI는 아직 멀어보일 수 있습니다.
하지만 엑셀은 오늘 당장 시작할 수 있습니다.

엑셀은 나의 전략 노트,
파이썬은 나의 트레이딩 비서.

이제 복잡한 모델이 없어도
단순한 전략으로,
꾸준하게 수익을 쌓아갈 수 있습니다.

Posted by 제이브레인
,