자동차 배터리가 한달 전 거의 방전이 되었습니다.

시동을 거는데 처음 시동이 걸리지 않았어요~~

순간~~ 아~~ 배터리 방전이구나~ 하는 생각이 뇌리를 스쳤죠~

정신 바짝 차리고 다시 한번 시동을 걸었지만 역시나~~ 시동이 걸리지 않았습니다.

자동차 방전 서비스를 전화를 해야하나하는 고민에 빠져 있다가 한번 인터넷을 찾아보면 길이 보일 수 있겠다는 생각이 들더군요.

역시나~~ 차량 배터리가 거의 방전이 대처 요령들이 쭉~~ 있더군요.

그 중에 시동이 걸리지 않을 때 P단을 N단으로 바꾸고 걸면 좀더 잘 걸린다는 말이 있었습니다.

뭐~~ 좀 신빙성이 없어 보이기는 했지만 그냥 한번 시도해보는 느낌으로 N단으로 바꾸고 시동을 걸어보았습니다.

그런데 웬걸~~ 시동이 걸리는 거예요~~

앗싸~~~ 따봉~~~ 저는 뭔가 산에서 심마니가 산삼을 발견한 기분이 들었습니다.

이런 깃동찬 방법이 있다니~~ 역시 유튜브신은 뭐든 알려주시는구나하고 유튜브에 해당 영상을 올려주신 분에게 감사를 드렸습니다.

이제 자동차 방전 서비스를 부를 일은 없겠구나 하는 생각도 들더군요.

허허~~ 이것은 저의 오판이었습니다. 몇 주후에 시동을 거는데 또 시동이 안걸리는 겁니다.

지난번 N단의 마법이 또 재현 되라가는 확신과 함께 시동을 거는데 시동이 안 걸리는 겁니다.

뭔가~~ 걸릴 듯~~ 안 걸릴 듯~~ 푸쉬쉬쉬~~ 푸쉬쉬쉬~~~

안 걸리 듯  안 걸릴 듯~~ 쉬쉬쉬~~ 히힝힝~~ 힝힝~~~

N단의 마법이 재현되지는 않았습니다.

그래서 어쩔 수 없이 자동차 방전 AS를 불렀습니다.

와~~~ 진짜 빨리 오더군요.

10분이 채 안되서 왔습니다.

일요일 오전이었는데 어디서 AS 대기하다가 바로 오는 듯한 느낌이 들었습니다.

친절히 다른 배터리와 연결해주시더군요.

덕분에 금방 시동을 걸었습니다.

감사의 인사를 드리는데 AS 기사분이 배터리 교체를 얼마라고 하시는 겁니다.

그래서 우선~ 알겠다고 하였습니다.

뭐~~ 연락하면 금방 오시니 인터넷에서 가격 한번 알아보고 교체 해보자는 생각이 들었거든요.

그리고 제가 원래~~ 뭐 뜯고 분해하고 인터넷 뒤지고 고치는 것을 좋아하는 편이라 더더욱 한번 알아보자는 생각이 들더군요.

암튼 인터넷을 뒤져보니 새 배터리와 공구를 주고 나중에 폐 배터리와 공구를 반납하는 형태로 인터넷에서 많이 판매하더군요.

가격도 착하고 주문후에 2 ~ 3일 이면 오더라구요.

그래서 한번 배워보자는 심정으로 주문을 했습니다.

그리고 주문 시 배터리 규격에 맞게 주문하면 된다고 했는데 저는 혹시나~ 제가 다른 규격의 제품을 주문할까봐~ 그냥 같은 제품을 주문했습니다.

같은 회사 같은 모델 번호로 주문했다는 거죠.

배터리 주문후에 박스가 온 모습니다.

요런 식으로 옵니다.

 

박스를 열어보니 배터리가 있었고 상하좌우 스티로폼과 그안에 배터리 분해/조립 공구가 있었습니다.

 

안에 들어있는 공구는 요~ 2개 입니다.

원래 사진을 찍었어야 했는데 깜빡 잊고 사진을 찍는 것을 까먹었어요.

그래서 쇼핑몰 후기에 있는 해당 공구 사진을 가져왔어요.

 

배터리를 보면 양옆에 청테이프가 붙어 있습니다.

해당 테이프는 우선 떼지 않습니다.

자동차 배터리 양옆에는 배기구가 있습니다.

해당 테이프를 떼고 움직이다가 배터리가 쓰러지면 전해액이 새어나올 수 있기 때문입니다.

자동차에 배터리 장작 후에는 배기구 테이프를 떼어내야 배터리가 정상작동 한다고 합니다.

만약 자동차에 장착 후에도 떼지 않으면 배터리가 부풀어 오를 수도 있기 때문에 장착 후에는 반드시 떼어 내야 한다고 합니다.

암튼~~ 자동차에 장착하러 갈 때는 우선 떼지 않습니다.

 

자동차 배터리 교체 전 모습입니다.

 

자동차 배터리 교체 방법은 다음과 같다고 하네요.

1) 음극(-) 단자 제거

2) 양극(+) 단자 제거

3) 배터리 연결 나사 제거

4) 폐 배터리 제거

5) 새 배터리 청테이프 제거 후 장착

6) 배터리 연결 나사 연결

7) 양극(+) 단자 연결

8) 음극(-) 단자 연결

9) 폐 배터리와 공구 곱게 싸서 반납하기

 

1) 음극(-) 단자 제거

음극(-) 단자를 먼저 제거하래요.

궁금증이 생겨서 확인해보니 양극(+) 단자를 먼저 제거한 상태에서 차체 어느 부분에 닿는 순간 쇼트가 발생한다고 하네요.

잘 보면 음극(-) 단자는 단순하게 되어있는데요.

양극(+)는 커버가 있고 커버를 열면 선들이 많이 연결되어 있어요.

아래 이미지를 보면 양극(+) 커버를 열면 선들이 많이 있어요.

그래서 양극을 먼저 제거를 했는데 이 것이 차체와 닿는 순간 쇼트가 되면서~~ 뭔가 망가진다는 거죠..

암튼~ 전문가들이 그런가 부다 하면 따라하는 것이 진리이니 음극(-)를 우선 제거했어요.

 

2) 양극(+) 단자 제거

양극은 커버가 덮여져 있는데 손으로 오픈하는 부분을 눌러주면서 열면 됩니다.

차량 기종에 따라 다를 수 있으니 자신의 차량에 맞게 눌러주면 됩니다.

아마도 직관적으로 느낌이 확 오게 휴먼 인지스틱하게 디자인 되어 있을 겁니다. 아마도 그럴 겁니다.

 

그리고 양극(+)는 제거 시 주의할 점이 있어요.

아래 이미지의 제가 렌치로 돌리고 있는 저부분만 제거하면 됩니다.

다른 부분 제거하면 안돼요~~ 

저도 처음 음극(-)는 나사가 1개 여서 렌치로 잘 제거를 했는데 양극(+) 는 나사가 여러개 있는 겁니다.

머리가 갑자기 복잡해지면서 모든 나사를 풀어야 하나하는 생각이 들었습니다.

그러나 다행스럽게도 실행에 옮기기 전에 그럴리가~~ 라는 생각이 불현듯 들더군요.

잘 보니 배터리 봉과 연결된 부분만 제거를 하면 된다는 다행스러운 결론이 나왔습니다.

그래서 다행스럽게도 아래 이미지처럼 올바른 1개의 나사만 돌린 후에 잘 제거를 했습니다.

 

3) 배터리 연결 나사 제거

양쪽 배터리 단자 봉 연결 나사를 제거한 후에 자동차 본체와 연결된 나사를 제거해야 합니다.

당연스럽게도 배터리가 견고하게 고정이 되도록 연결 나사가 연결되어 있습니다.

제 차종은 지금 아래 이미지의 1개의 나사만 제거하면 배터리가 제거가 가능했습니다.

 

4) 폐 배터리 제거

폐 배터리 제거 시에 배터리가 무거워서 들기 힘들어요.

그런데 배터리 위 부분을 보면 손잡이가 있어요.

아래 이미지처럼 손잡이를 위로 올리면 되요. 간단하죠?

손잡이를 위로 올려서 들면 한결 수월하게 들 수 있어요.

역시~~ 인간은 머리를 써야겠죠?

 

그리고 배터리 연결 부분을 보니 구조적을 설계가 잘 되어있더라구요.

전문가들이 오랜 연구끝에 잘 만들어서 그런 거라고 생각합니다. 하하~~

잘보면 배터리 아래 양옆은 옆으로 튀어 나와 있습니다.

그래서 지금 나사를 풀고 있는 곳과 반대편이 견고하게 연결이 되도록 되어 있습니다.

아래 이미지 빨간색 박스 2개가 보이죠?

여기에 배터리 하단이 견고하게 고정이 되는 겁니다.

그래서 배터리 장착시에 우측 빨간색 박스 부분에 잘 고정이 되도록 해야 주행 중 배터리가 떨어지는 불상사가 없습니다.

 

5) 새 배터리 청테이프 제거 후 장착

이미지 처럼 청테이프는 꼭 제거 후에 장착해주세요.

배터리 배기구 테이를 안떼면 제성능이 안나오고 배터리가 부풀어서 터질 수가 있데요.

좀~~ 무시무시하네요. 꼭~~ 제거해주세요.

 

6) 배터리 연결 나사 연결

이후 연결은 해체의 역순으로 하면 됩니다.

7) 양극(+) 단자 연결

8) 음극(-) 단자 연결

9) 폐 배터리와 공구 곱게 싸서 반납하기

배터리를 뒤집어 넣어도 안돼요. 상하가 맞는 방향으로 넣어야 해요.

그리고 폐 배터리 반납시에는 꼭 배터리 배기구를 청테이프로 막아야해요.

만약 배기구를 테이프로 막지 않으면 전해액이 새어 나온다고 하네요.

배달하시는 분들이 지금도 고생하시는데 전해액이 새어 나오면 정말 낭패겠죠?

전해액이 몸에도 좋지 않을 거 잖아요.

그리고 다른 택배 물품에 전해액이 묻으면 택배 기사분들이 배상해야 할 수도 있잖아요.

암특 걱정도 팔자이긴 한데 그런 생각이 들더군요.

그리고 배기구 막을 때는 청테이프가 좋은 것 같아요.

제가 집에 있는 투명 스카치 테이프로 막아봤는데 금방 떨어져요.

불안해서~ 다이소가서 청테이프 사서 배터리 배기구 막고 포장했어요.

집앞에 놓으면 몇일 후에 가져간다고 하네요.

쇼핑몰에 문자도 보내라는 메시지가 있었서 판매자 분에게 이름과 회수요청으로 문자도 보냈습니다.

하하~~~ 오늘은 배터리 교체 중간 중간 모르는 부분이 있어서 인터넷 검색하느라 시간이 좀 걸렸는데요.

다음번에는 번개불에 콩 구워먹 듯이 금방~ 후다닥~~ 끝낼 수 있을 것 같아요.

암튼 자동차 시동이 우렁차게 걸리는 모습을 보니 뭔가 뿌듯하고 기분이 좋네요.

카센터에 가서 고치면 금방 교체가 되겠지만 이런 뿌듯함은 느끼지 못하겠죠?

암튼 행복한 하루되세요.

Posted by 제이브레인
,

1)  자동 버전 처리 필요성

키움 OpenAPI+  는 자동 로그인이 설정되어 있는 경우 버전 처리가 제대로 수행되지 않을 수 있습니다.

버전처리가 수행되지 않으면 프로그램이 오동작할 수  있기 때문에 업그레이드가 반드시 필요합니다.

번개 HTS 로그인 시에 버전 처리가 이루어지므로 번개 HTS 를 자동으로 실행하는 스크립트 추가가 필요합니다.

 

번개 HTS 실행을 윈도우 작업 스케줄러를 이용하여 실행하고 로그인 비밀번호를 입력하는 것은 

2) pywinauto 패키지 설치

pywinauto 패키지를 사용하여 번개 HTS 실행 코드를 추가하도록 하겠습니다.

pywinauto 패키지는 윈도우 대화상자에 자동으로 키입력을 보낼 수 있습니다.

게임등을 할 때 사용하는 Auto Click 같은 것인데 마우스 클릭 뿐만 아니라 키 입력도 지원하는 프로그램이라고 생각하면 됩니다.

pywinauto  패키지를 설치합니다.

 

만약 아래와 같이 오류가 발생하면 컨맨드로 수동 설치가 필요합니다.

Invalid version: '4.0.0-unsupported' 라고 에러 발생 후 설치 실패하였습니다.

Anaconda Prompt 를 관리자 권한으로 실행합니다.

다음 명령들을 실행합니다.

1. 32비트 가상 환경 활성화

conda activate py38_32

2. pyodbc 패키지 제거 후 다시 설치

pip uninstall pyodbc pip install pyodbc
pip uninstall pyodbc
pip install pyodbc

3. pip 최신 버전으로 업데이트

먼저 pip을 최신 버전으로 업그레이드하세요.

python -m pip install --upgrade pip
 

4. pywinauto 다시 설치

 
pip install pywinauto

Successfully installed 라고 뜨면 정상 설치입니다.

3) 번개3 실행 후 자동 로그인 코드 생성

코드는  ChatGPT 에 다음과 같은 프롬프트로 생성하였습니다.

pywinauto 패키지를 사용하여 번개 HTS 를 실행 후 자동으로 버전 업데이트하는 코드를 알려주세요.
아이디, 비밀번호, 인증서 비밀번호는 kiwoom.conf 라는 파일에서 읽어서 실행하는 코드를 만들어주세요.

kiwoom.conf

아래 파일을 본인의 계정 정보로 변경해야 합니다.

그리고 중요한 정보이므로 외부에 노출되지 않도록 주의해야 합니다.

[LOGIN]
id = your_kiwoom_id
password = your_kiwoom_password
cert_password = your_certificate_password

 

kiwoom_auto_update.py

아래 코드는 다음 위치에서 다운 받는 것이 가능합니다.

git clone https://github.com/jbpark/JbTraderExample.git
cd JbTraderExample/jbtrader/ch5.3
import configparser
import time
import os
from pywinauto import application
from pywinauto import timings

# 설정 파일 읽기
config = configparser.ConfigParser()
config.read("kiwoom.conf", encoding="utf-8")

# 로그인 정보 가져오기
kiwoom_id = config["LOGIN"]["id"]
kiwoom_pw = config["LOGIN"]["password"]
kiwoom_cert_pw = config["LOGIN"]["cert_password"]

hts_path = "C:/KiwoomFlash3/bin/nkministarter.exe"

# 번개 HTS 실행
if not os.path.exists(hts_path):
    raise FileNotFoundError(f"HTS 실행 파일을 찾을 수 없습니다: {hts_path}")

app = application.Application()
app.start(hts_path)

title = "번개3 Login"
dlg = timings.wait_until_passes(20, 0.5, lambda: app.window(title=title))

pass_ctrl = dlg.Edit2
pass_ctrl.SetFocus()
pass_ctrl.TypeKeys(kiwoom_pw)

cert_ctrl = dlg.Edit3
cert_ctrl.SetFocus()
cert_ctrl.TypeKeys(kiwoom_cert_pw)

btn_ctrl = dlg.Button0
btn_ctrl.Click()

time.sleep(30)
os.system("taskkill /im nkmini.exe")

print("HTS 실행 완료")

 

4) 자동 버전 처리 코드 실행

실행 시 관리자 권한으로 실행해야 합니다.

DLL 초기화  에러가 발생할 수 있습니다.

 

우선 Python 인터프리터, Python 콘솔이  32 비트 인지 확인해야 합니다.

설정 > 프로젝트 > Python 인터프리터에서 확인이 가능합니다.

설정 > 빌드, 실행,배포 > Python 콘솔 에서 확인이 가능합니다.

pywinauto는 pywin32에 의존하므로, 먼저 pywin32를 재설치하고 다시 시도해 보세요.

pip install --upgrade --force-reinstall pywin32

그리고 pywin32_postinstall.py 파일을 수동 실행 합니다.

저는 아래와 같은 경로에 설치되어 있어서 다음과 같이 실행했습니다.

python C:\Anaconda3\envs\py38_32\Scripts\pywin32_postinstall.py -install

 

5) hkopenapi.ocx 파일 삭제 실패

아래와 같이 hkopenapi.ocx 파일 삭제 실패라고 계속 뜨는 경우 

 

C:\OpenAPI\opversionup.exe
프로그램을 권리자 권한으로 실행해야 합니다.

Posted by 제이브레인
,

pykiwoom 이라는 kiwoom api 라이브러리를 사용하여 매수를 하는 예제를 만들어보겠습니다.

pykiwoom 모듈은 키움증권의 Open API+를 파이썬에서 보다 쉽게 사용할 수 있도록 매수, 매도, 조회 등의 기본적인 기능을 손쉽게 사용할 수 있도록 만들어 놓은 모듈입니다.

1) pykiwoom 모듈 설치

conda activate py38_32
pip install pykiwoom

 

이미  pykiwoom 모듈이 설치되어 있는 경우 업데이트를 해주는 것이 좋습니다.

해당 모듈은 계속적으로 업데이트되기 때문입니다.

pip install -U pykiwoom

2) 매수 코드 작성

ChatGPT 프로프트는 다음과 같습니다.

키움증권 api 라이브러리인 pykiwoom 을 사용하여 매수하는 코드를 만들어주세요. 
pyqt 와도 같이 연결해주세요. 
OrderType이라는 이름을 가진 ComboBox 로 시장가, 매수가 선택이 있고 매수가 선택시 OrderPrice라는 LineEdit 에서 매수가를 불러옵니다. 
그리고 수량을 입력한 OrderAmount라는 LineEdit 도 있습니다. 
그리고 종목코드를 입력한 StockCode라는 LineEdit 도 있습니다. 
매수 주문이 나가면 Log라는 TextEdit에 종목코드에 해당하는 종목명을 가져와서 종목명이 매수가 얼마에 몇개가 주문되었다고 표시합니다.
그리고 매수가 체결이 되면 매수가 체결되었다라는 메시지를 표시합니다.
파이썬 코드를 만들고 주석도 추가해주세요

 

생성된 코드는 다음과 같습니다.

아래 코드는 다음 위치에서 다운 받는 것이 가능합니다.

git clone https://github.com/jbpark/JbTraderExample.git
cd JbTraderExample/jbtrader/ch5.5
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QTextEdit
from pykiwoom.kiwoom import Kiwoom

class KiwoomAPI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Kiwoom Stock Buyer")
        self.setGeometry(100, 100, 500, 300)
        
        # Kiwoom API 객체 생성
        self.kiwoom = Kiwoom()
        self.kiwoom.CommConnect(block=True)  # 로그인 실행 (블록킹 방식)
        
        # UI 요소 설정
        self.stock_label = QLabel("종목코드:", self)
        self.stock_label.move(20, 30)
        self.StockCode = QLineEdit(self)
        self.StockCode.setGeometry(100, 30, 100, 20)
        
        self.qty_label = QLabel("수량:", self)
        self.qty_label.move(20, 70)
        self.OrderAmount = QLineEdit(self)
        self.OrderAmount.setGeometry(100, 70, 100, 20)
        
        self.price_label = QLabel("가격:", self)
        self.price_label.move(20, 110)
        self.OrderPrice = QLineEdit(self)
        self.OrderPrice.setGeometry(100, 110, 100, 20)
        self.OrderPrice.setEnabled(False)  # 기본적으로 비활성화
        
        self.order_type_label = QLabel("주문유형:", self)
        self.order_type_label.move(20, 150)
        self.OrderType = QComboBox(self)
        self.OrderType.setGeometry(100, 150, 100, 20)
        self.OrderType.addItems(["시장가", "매수가"])
        self.OrderType.currentIndexChanged.connect(self.update_price_input)
        
        self.buy_button = QPushButton("매수", self)
        self.buy_button.setGeometry(100, 190, 100, 30)
        self.buy_button.clicked.connect(self.buy_stock)
        
        self.log_label = QLabel("Log:", self)
        self.log_label.move(220, 30)
        self.Log = QTextEdit(self)
        self.Log.setGeometry(220, 50, 250, 200)
        self.Log.setReadOnly(True)
        
        # 체결 이벤트 연결
        self.kiwoom.OnReceiveChejanData = self.receive_chejan_data
        
    def update_price_input(self):
        """주문 유형에 따라 가격 입력 활성화/비활성화"""
        if self.OrderType.currentText() == "매수가":
            self.OrderPrice.setEnabled(True)
        else:
            self.OrderPrice.setEnabled(False)
            self.OrderPrice.clear()
        
    def buy_stock(self):
        """키움 API를 이용하여 주식 매수 주문 실행"""
        account = self.kiwoom.GetLoginInfo("ACCNO").split(';')[0]  # 계좌번호 가져오기
        code = self.StockCode.text()
        qty = self.OrderAmount.text()
        price = self.OrderPrice.text() if self.OrderPrice.isEnabled() else "0"  # 시장가 주문일 경우 가격 0
        
        if not code or not qty:
            self.Log.append("종목코드와 수량을 입력하세요.")
            return
        
        # 종목명 가져오기
        stock_name = self.kiwoom.GetMasterCodeName(code)
        
        order_type = 1  # 1: 매수
        hoga = "00" if self.OrderPrice.isEnabled() else "03"  # 00: 지정가, 03: 시장가
        
        self.kiwoom.SendOrder(
            "매수주문", "0101", account, order_type, code, int(qty), int(price), hoga, ""
        )
        self.Log.append(f"{stock_name}({code}) {qty}주 매수 주문 실행 ({'지정가' if self.OrderPrice.isEnabled() else '시장가'})")
        
    def receive_chejan_data(self, gubun, item_cnt, fid_list):
        """체결 데이터 수신 이벤트 처리"""
        if gubun == "0":  # 주문 체결
            stock_name = self.kiwoom.GetChejanData(302)  # 종목명
            price = self.kiwoom.GetChejanData(910)  # 체결가
            qty = self.kiwoom.GetChejanData(911)  # 체결 수량
            self.Log.append(f"{stock_name} {qty}주 체결 완료 (가격: {price})")

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

 

3) 매수 코드 실행

실행 시 다음과 같이 매수에 필요한 가장 간단한 기능으로 실행됩니다.

종목 코드 입력 후 수량 입력하고 매수 버튼을 클릭하면 매수가 진행됩니다.

 

해당 코드는 기능은 아래와 같이 간단하게 요약 할 수 있습니다.

 

  • OrderType(ComboBox)에서 매수가 선택 시 OrderPrice(LineEdit) 활성화
  • 주문이 실행되면 Log(QTextEdit)에 종목명, 매수가, 주문 수량 출력
  • 주문이 체결되면 체결 정보를 Log에 표시

 

실제 주문은 SendOrder 함수에 의해 실행됩니다.

self.kiwoom.SendOrder(
            "매수주문", "0101", account, order_type, code, int(qty), int(price), hoga, ""
        )

 

Posted by 제이브레인
,