1. 예수금 정보를 얻어오는 TR(opw00001)
- 사실상 계좌번호만 전달하면됨
- 계좌번호는 아래 get_account_number를 통해서
def get_account_number(self, tag="ACCNO"):
account_list = self.dynamicCall("GetLoginInfo(QString)", tag)
account_number = account_list.split(';')[0] #계좌만 분리해서 가져옴 [1]은 공백임
print(account_number)
return account_number
- 생성자부분에서 self.account_number에 저장해둠
class Kiwoom(QAxWidget):
def __init__(self):
super().__init__()
self._make_kiwoom_instance()
self._set_signal_slots()
self._comm_connect()#로그인 요청하는 메소드 시작
self.account_number = self.get_account_number()#계좌번호 가져옴
self.tr_event_loop = QEventLoop()#TR 요청에 대한 응답 대기를 위한 변수 데이터가 올 때까지 기다렸다가 처리해!" 하는 용도로 사용하는 이벤트 루프
- 참고로 KOA에서 개발가이드 - 로그인 버전처리 - 관련함수 - GetLoginInfo를 보면 계좌번호를 얻어오는 관련함수를 볼 수 있음
- 예수금을 얻어오는 함수인 get_deposit는 다음과 같음
def get_deposit(self):
self.dynamicCall("SetInputValue(QString, QString","계좌번호", self.account_number)
self.dynamicCall("SetInputValue(QString, QString", "비밀번호입력매체구분", "00")
self.dynamicCall("SetInputValue(QString, QString", "조회구분", "2")
self.dynamicCall("CommRqData(QString, QString, int, QString","opw00001_req", "opw00001", 0, "0002")
self.tr_event_loop.exec()#응답을 대기할 수 있는 상태로 만듬
return self.tr_data
- 계좌번호는 self.account_number를 넘겨주고 나머지는 파라미터를 강제로 줌
- 그리고 self.tr_event_loop.exec()코드를 통해 응답을 대기할 수 있는 상태로 만듬
2. 예수금 정보를 받는 함수
- 기존의 _on_receive_tr_data 함수에서 아래쪽 elif부분이 예수금을 바다오는 부분임
def _on_receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
print("[Kiwoon _on_receive_tr_data is called {} / {} / {}".format(screen_no, rqname, trcode))
tr_data_cnt = self.dynamicCall("GetRepeatCnt(QString, QString", trcode, rqname) #가져온 TR의 응답갯수 즉 600일치면 600이 저장됨
#만약 600일치가 넘은 일본데이터를 필요하면 next를 2로 설정해서 _on_receive_tr_data를 한번더 호출할 수 있게 함
if next == '2':
self.has_next_tr_data = True
else:
self.has_next_tr_data = False
if rqname == "opt10081_req":
ohlcv = {'date': [], 'open': [], 'high': [], 'low': [], 'close': [], 'volume': []}#ohlcv는 지역변수임
for i in range(tr_data_cnt):
date = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "일자")
open = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "시가")
high = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "고가")
low = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "저가")
close = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "현재가")
volume = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "거래량")
ohlcv['date'].append(date.strip())
ohlcv['open'].append(int(open))
ohlcv['high'].append(int(high))
ohlcv['low'].append(int(low))
ohlcv['close'].append(int(close))
ohlcv['volume'].append(int(volume))
self.tr_data = ohlcv#글로벌 변수로 편입시킴
#예수금 얻어오기 받는 부분
elif rqname == "opw00001_req":
deposit = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, 0, "주문가능금액")
self.tr_data = int(deposit)
print(self.tr_data)
self.tr_event_loop.exit()#tr 요청을 보내고 응답을 대기시키는데 사용하는 self.tr_event_loop 를 종료 시킴
time.sleep(0.5)#0.5초만듬 쉼
GetCommData함수를 통해서 받아옴
- if문을 넣어서 rqname이 opw00001_req일때만 처리할 코드를 넣었다.(get_deposit에 보면 rqname을 opw00001_req를 넣어줬음)
- 예수금을 얻어오는 TR(opw00001)은 단 한번 호출로 얻어 오므로 싱글데이터 응답으로 주문가능 금액 항목을 얻어와 변수 deposit에 담았다.
- 왜 예수금을 안가져왔는지는 사실 예수금은 D+2에 처리가 되고 주문가능 금액은 주식을 팔고 바로 주문을 넣을 수 있는 금액이기 때문에 시스템 트레이딩을 하는 입장에서는 주문가능금액이 더 중요하기 때문이다.
- 그리고 여기서 가져온 deposit 값을 int로 바꿔주는데 예수금이 100만원이면 00001000000 이런식으로 0000이 앞에 붙기때문에 0을 제거하기 위함이다.
self.tr_data = int(deposit)
3. 실행 결과
- 현재 모의 투자 계좌에 99,997,590원이 있는데
- 실제 실행해보면 99,938,490원이다!?
- 곰곰히 생각해보니까 1억원 - 삼성전자1주 매수가격(61300원) = 99,938,700원이 맞다.
- 위 모의투자계좌는 추정예탁자산이었다..
참고. 소스코드 깃헙
https://github.com/GaKaRi/python_trading/tree/main/SystemTrading
python_trading/SystemTrading at main · GaKaRi/python_trading
Contribute to GaKaRi/python_trading development by creating an account on GitHub.
github.com
'프로그래밍 > 파이썬' 카테고리의 다른 글
4. 파이썬 - 키움API 활용한 주문 체결 확인하기 (1) | 2025.06.15 |
---|---|
3. 파이썬 - 키움API 활용한 주문 접수하기 (2) | 2025.06.09 |
1. 파이썬 - 키움API 활용한 가격정보 불러오기 (0) | 2025.06.03 |