목 차
1. 들어가기
2. 사전설명
1) 리스트 내 for문 작성하기
2) 리스트 내 for문의 실제 활용 형태
3. 코드설명
4. 전체코드
5. 마치며
1. 들어가기
지난 글에서는 1분봉 데이터를 활용하여 3분봉 데이터를 구하는 방법을 알아보았다. 각 분(minute)을 3으로 나누어 몫(quotient)과 나머지(remainder)을 구하여 3분봉 데이터를 추출할 수 있는 접근법이었다.
이번 글에서는 지난글의 코드를 조금씩 줄여나가는 방법에 대해 알아볼 예정이다. 처음부터 간략한 코드를 설명할까 생각했는데, 장문의 코드가 단문으로 줄어드는 과정을 보여주는 것도 좋아보여서 지난글(총 134줄)이 길어졌던거 같다.
2. 사전설명
1) 리스트 내 for문 작성하기
그 동안은 코드가 길어지더라도 for문과 리스트를 각각 작성하였다. "리스트 내 for문 작성"이 낯설었던 이유가 크게 작용한다. 그런데, 이번에는 코드의 간결성도 그렇고, 최대값/최소값을 변수에 담아야 하기 때문에 어쩔 수 없이 "리스트 for문을 작성"하였다.
aaa = []
for i in range(0,4):
aaa.append(i)
print(aaa)
### (expected result) ###
### [0, 1, 2, 3]
코드 1-1. for문과 리스트문을 각각 작성한 경우
아래는 for문과 리스트문을 함께 써준 경우이다.
aaa = [i for i in range(0,4)]
print(aaa)
### (expected result) ###
### [0, 1, 2, 3]
코드 1-2. for문과 리스트문을 같이 써준 경우
코드1-1 및 코드1-2는 결과물이 같다는 점에서 큰 차이는 없다. 0~3까지 출력하는 코드는 간단하다. 그런데 공부하면서 느끼는 것이지만, for문과 리스트문을 함께 쓰는 것은 숙지하게 되니, 그렇게 코드 작성이 편할 수 밖에 없다.
for문 내 리스트 작성의 결론은 아래와 같다.
aaa = [i for in range(0 ,4)]일 때, 결과물은 < 코드1-2 >에서 확인하였듯이 [0,1,2,3,]이다.
2) 리스트 내 for문의 실제 활용 형태
아래 코드에서 활용하겠지만, 여기서 그 형태를 보자. 14:36~14:38분, 14:39~14:41분 등 각각 최대값을 구해야한다.
high_price = max(abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())),
abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-1, "고가").strip())),
abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-2, "고가").strip())))
low_price = min(abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "저가").strip())),
abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-1, "저가").strip())),
abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-1, "저가").strip())))
코드2-1. 3분내 최대값과 최소값을 구한다.
< 코드2-1 >의 1줄~3줄 및 4줄~6줄은 3분 사이의 최고값을 구하는 코드이다.
high_price = max([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
low_price = min([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
코드2-2. 3분내 최대값과 최소값을 리스트와 for문을 통해 구한다.
< 코드2-2 >는 < 코드2-1 >의 6줄을 2줄로 간략히 정리한 for문/리스트 문이다. 위의 < 코드2-2 >코드 형태에 익숙해지자!
3. 코드설명
라이브러리 및 로그인에 관한 설명은 생략한다.
1줄~25줄 : 라이브러리 및 로그인에 관한 내용이며, 설명을 생략한다.
27줄~33줄 : 116줄에서 함수를 실행하기 위해 함수를 정의한다.
36줄~41줄 : 키움증권에서 데이터를 수신받는다.
42줄 : 58줄~110줄에서 정의된 함수를 실행한다.
45줄~51줄 : 현재 체결시간을 정의하고, 인수화(51줄)한다.
53줄~56줄 : 1분봉 데이터를 담아줄 리스트를 선언한다.
58줄~69줄 : 체결시간(51줄)을 3으로 나누어서, 나머지(remainder)에 따라 적용되는 함수를 정의한다.
62줄~64줄 : 3분 내 최대값/최소값을 각각 구한다.
66줄~69줄 : 시가, 고가, 저가, 종가를 리스트에 넣는다.
76줄~110줄 : 51줄(체결시간)의 분(minute)를 3으로 나눈 나머지(remainder)가 1 혹은 2일 때 적용되는 코드이다.
116줄 : 28줄(rq_data_opc10002)에서 정의된 함수를 실행한다.
4. 전체코드
아래 코드는 키움증권에 월 시세 이용료($185)를 지불하여야 실행된다. 변경된 코드는 리스트 및 for문이 쓰인 62줄~63줄, 80줄~81줄, 98줄~99줄이다.
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class btl_system():
def __init__(self):
self.kiwoom = QAxWidget("KFOPENAPI.KFOpenAPICtrl.1")
print("로그인 시작!")
self.kiwoom.dynamicCall("CommConnect(1)") # CommConnect() : 괄호 안에 자동(1)을 넣는다.
self.kiwoom.OnEventConnect.connect(self.login_Connect)
self.kiwoom.OnReceiveTrData.connect(self.trdata_get)
self.login_event_loop = QEventLoop()
self.login_event_loop.exec_()
self.kiwoom.dynamicCall("GetCommonFunc(QString, QString)", "ShowAccountWindow", "") # 계좌번호 입력창을 띄우는 내부함수
def login_Connect(self, err_code):
if err_code == 0:
print('로그인 성공했습니다!')
else:
print('로그인 실패했습니다!')
self.login_event_loop.exit()
########## 키움서버에 TR 요청하는 함수 모음 ##########
def rq_data_opc10002(self, stock_code_num, time_unit): # 1분봉 받기
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "종목코드", stock_code_num)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "시간단위", time_unit)
self.kiwoom.dynamicCall("CommRqData(QString, QString, QString, QString)", "opc_10002", "opc10002", "", "1002")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
########## OnReceiveTrData을 통해 수신받은 데이터 함수 ##########
def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
if rqname == "opc_10002":
getrepeatcnt = self.kiwoom.dynamicCall("GetRepeatCnt(QString,QString)", trcode, recordname)
self.getrepeatcnt = getrepeatcnt
self.tr_event_loop.exit()
btl.minute_1_3_bong()
def minute_1_3_bong(self):
time_0 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", 0, "체결시간")
print(time_0)
print(time_0[8:12])
print(time_0[10:12])
aaa = time_0[10:12]
aaa = int(time_0[10:12])
self.bbb = []
self.ccc = []
self.ddd = []
self.eee = []
if aaa % 3 == 0: ### aaa는 현재시간 ### 0으로 떨어지면 시가, 2로 떨어지면 종가
for i in range(12, 0, -3): # 1분전 봉까지 출력 (과거 → 현재)
if i//3 == i/3:
open_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "시가").strip()))
high_price = max([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
low_price = min([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
close_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-2, "현재가").strip()))
self.bbb.append(open_price)
self.ccc.append(high_price)
self.ddd.append(low_price)
self.eee.append(close_price)
print(self.bbb)
print(self.ccc)
print(self.ddd)
print(self.eee)
elif aaa % 3 == 1: ### aaa는 현재시간 ### 0으로 떨어지면 시가, 2로 떨어지면 종가
for i in range(12+1, 1, -3): # 1분전 봉까지 출력 (과거 → 현재)
if i//3 == (i-1)/3:
open_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "시가").strip()))
high_price = max([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
low_price = min([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
close_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-2, "현재가").strip()))
self.bbb.append(open_price)
self.ccc.append(high_price)
self.ddd.append(low_price)
self.eee.append(close_price)
print(self.bbb)
print(self.ccc)
print(self.ddd)
print(self.eee)
elif aaa % 3 == 2: ### aaa는 현재시간 ### 0으로 떨어지면 시가, 2로 떨어지면 종가
for i in range(12+2, 2, -3): # 1분전 봉까지 출력 (과거 → 현재)
if i//3 == (i-2)/3:
open_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "시가").strip()))
high_price = max([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
low_price = min([abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip())) for i in range(i-2, i+1)])
close_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i-2, "현재가").strip()))
self.bbb.append(open_price)
self.ccc.append(high_price)
self.ddd.append(low_price)
self.eee.append(close_price)
print(self.bbb)
print(self.ccc)
print(self.ddd)
print(self.eee)
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
btl.rq_data_opc10002("NQZ23", "1")
app.exec_()
5. 마치며
이번 글의 핵심은 리스트 내 for문을 작성하여 코드를 간략하게 만드는 것이었다. 지난글이 134줄이며, 이번글은 118줄(△16줄)로 작성이 되었다. 다음 글에서는 코드를 더 줄여보도록 하자.
'2. 해외선물 > 2-3. 해외선물 설명' 카테고리의 다른 글
(키움증권 해외선물 자동매매 파이썬) (2) 실시간 데이터 받기의 한계 (6) | 2023.11.04 |
---|---|
(키움증권 해외선물 OpenAPI-W) 1분봉 데이터로 3분봉, 60분봉 만들기 (4) 3분/60봉 데이터 만들기 (고급) (2) | 2023.11.02 |
(키움증권 해외선물 OpenAPI-W) 1분봉 데이터로 3분봉, 60분봉 만들기 (2) 3분봉 받아보기 (초급) (10) | 2023.10.31 |
(키움증권 해외선물 OpenAPI-W) 1분봉 데이터로 3분봉, 60분봉 만들기 (1) 개념 이해하기 (2) | 2023.10.30 |
(키움증권 해외선물) 1분봉 데이터 받기 (4) 키움차트에서 1분봉 받기 (0) | 2023.09.02 |
(키움증권 해외선물) 1분봉 데이터 받기 (3) 데이터 합친 후 수정사항 (0) | 2023.01.13 |
(키움증권 해외선물) 1분봉 데이터 받기 (2) 데이터 한 파일(엑셀)로 합치기 (concat 함수) (0) | 2023.01.12 |
(키움증권 해외선물) 1분봉 데이터 받기 (1) 영웅문G에서 엑셀로 받기 (0) | 2023.01.11 |