코인 거래소들이 신규 고객을 유치하기 위해 무료 코인 지급 등의 이벤트를 많이 진행했었다.

 

그중 코인원에 가입하지는 않았지만, 인터넷으로 이런저런 정보를 검색도 해봤었다.

 

그러다가 다음과 같은 문자를 받았다.

 

 

코인원 피싱 사기 문자

 

코인원에는 회원가입을 한 적이 없었기 때문에 대수롭지 않게 생각하고 넘겼다. 그래도 문자가 찝찝해서 회원가입 여부를 확인해봤는데, 회원정보가 없음을 확인했다.

 

"누가 내 개인정보로 가입했는가?"라는 생각이 들어서 코인원에 위 문자 스샷을 보내주면 문의해봤다.

 

 

 

코인원 피싱 사기 상담

 

 

상담자께 답변을 받고보니, 코인원 인터넷 주소가 달랐다.

사기 문자의 주소는 coinones.com 이고, 코인원의 정상주소는 coinone.com 이다. "s" 하나 차이다.

 

창의적인 놈들이다.

 


이런 피싱 사기 문자를 받았다는 것 자체가 이미 나의 연락정보와 코인에 관심이 있다는 사실까지 털렸다는 말인 거 같아 씁쓸하다.

 

 

2021.07.14.

코리

 

 

그림 출처 : [1]

 

 

한글(hwp) 파일 약 9천개를 만들어야 하는 일이 생겼다.

엑셀에 table 형식으로 저장된 하나의 행에 해당하는 정보를 한글(hwp)의 표 형식에 복붙하고 하나의 파일로 저정해야 하는 반복 작업인데, 만들어야 할 한글 파일이 총 9천개 정도이다.

 

작업 효율성을 위해 3개의 폴더에 나눠서 저장하고 있는데, 이를 하나의 폴더로 합칠 예정이다. 하나로 합칠 생각을 하니, 하나의 폴더에 저장할 수 있는 파일 개수에 제한이 있는지 궁금해졌다.

 

구글링을 해서 찾은 정보는 다음과 같다.

 

NTFS(New Technology File System)에서 제한 사항은 다음과 같다

- 최대 디스크 사이즈 : 256 테라바이트

- 최대 파일 사이즈 : 256 테라바이트

- 디스크에 쓸 수 있는 최대 파일 수 : 4,294,967,295개

- 하나의 폴더에 담을 수 있는 최대 파일 수 : 4,294,967,295개

 

 

별 쓸데 없는 걱정을 했나 보다.ㅎㅎ

 

 

도움받은 감사한 글

[1] : www.datto.com/library/does-ntfs-have-a-file-size-limit

 

 

2021.02.01. 코리.

 

do not reinvent the wheel [1]

 

 

이전 글 보러가기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

09_키움 OPEN API 계좌평가 잔고 가져오기

10_키움 OPEN API 일봉데이터 가져오기_1

11_키움 OPEN API 일봉데이터 가져오기_2

12_파이참에서 주피터노트북 열기

13_키움API 삼성전자 자동매매 개요

14_if __name__ == “__main__” 에 대하여...

 

 

 

 

머신러닝 주가 예측 및 자동매매 project에 큰 변화가 생겼다.

 

Do not reinvent the wheel!

바퀴를 재발명하지 마라!

 

 

주식 자동화 project를 통해 매일 5천원 벌기라는 목표가 있었지만, 이면에는 python 학습이라는 목표도 있었다. 그래서 pykiwoom 패키지를 사용하지 않고 직접 코딩을 결정했다.

 

OPEN API도 심도 깊게 배워보고 싶었다.

 

하지만, 파이썬의 class, __init__, 상속, 오탈자(특히 def나 if 뒤의 :), 코드 줄 맞춤 등등 기초적인 것들에서 너무 많은 시간을 소비했고, 나는 지쳐가고, 성과는 나오지 않았다.

 

진도가 나가지 않아 답답하던 시기에 if __name__ == "__main__" 문제가 터졌다. 이걸 이해하고 해결하는데 2~3시간이나 걸렸다. 몰랐던걸 알게 되었으니, 가치 있는 시간이었지만, 뭔가 잘못되고 있음을 알게 되었다.

 

지금과 같은 속도로는 올봄이 오기 전에 주식 자동화 코드를 만들 수 없을 거 같다는 생각이 들었다. 그래서 키움 API 사용은 직접 코딩을 포기하고, 잘 만들어진 패키지를 import 해서 사용하기로 마음을 고쳐먹었다. 사실 내가 더 많은 시간을 투자해야 하는 것은 가격 예측 모델링이라는 생각도 들었다.

 

 

파이썬에서의 클래스 개념이 잘 안 잡혀서 주변에 계신 분께 여쭤보니, 구글링해서 얻은 정도의 답변을 해주셨다. 그리고, 다음의 말씀도 주셨다.

 

개발자가 직접 class를 만드는 일은 잘 없다. 개발자는 잘 만들어진 패키지를 잘 찾고 잘 쓰는 것이 더 중요한 능력이다. class와 모듈을 처음부터 만들려고 접근하는 것은 비효율적이다.

 

 

 

[2]

 

이미 바퀴가 있는데, 바퀴를 만든다고 시간을 소모할 필요가 없겠다.

 

 

 

[3]

 

이미 바퀴가 있으니, 바퀴를 재발명하는 것이 아니라, 바퀴를 개선해야겠다.

잘 만들어진 패키지를 import 해서 사용하고, 그 패키지들이 어떻게 만들어졌고, 어떻게 작동하는지 알아보면서 공부를 해야겠다. 능력이 닿인다면, 패키지들의 개선할 수 있는 방법도 찾아봐야겠다.

 

 

 

 

도움받은 감사한 글

[1] www.ibmbigdatahub.com/blog/dont-reinvent-wheel-increase-productivity-strategic-reuse

[2] medium.com/@bansalbhavik9/reinvent-the-wheel-or-not-5013f6d1ac2c

[3] medium.com/@hendra.susanto37/dont-reinvent-the-wheel-just-realign-it-557c66a6a5d7

 

 

 

 

2021.01.22. 코리.

if __name__ == “__main__”

 

 

이전 글 보러 가기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

09_키움 OPEN API 계좌평가 잔고 가져오기

10_키움 OPEN API 일봉데이터 가져오기_1

11_키움 OPEN API 일봉데이터 가져오기_2

12_파이참에서 주피터노트북 열기

13_키움API 삼성전자 자동매매 개요

 

 

 

if __name__ == “__main__”

 

이 짧은 코드 한 줄이 나에게 많은 것을 깨우치게 해줬다. 깨달음은 다음 글에서 포스팅할 예정이다. 키움 주식 자동화 14번째 글은 많은 시간을 투자해서 알게 된 if __name__ == “__main__” 에 대한 글이다.

 

 

이 코드의 목적은 명확하다.

해당 모듈이 인터프리터에서 직접 실행된 경우에는 if절 아래의 내용을 실행하는 것이다.

 

 

이 짧은 문장을 이해하기 위해선 모듈을 실행시키는 방법에 대한 이해가 필요하다.

1. 실행시키고자 하는 모듈을 다른 모듈에서 import 해서 실행

2. 실행시키고자 하는 모듈을 인터프리터(interpreter)에서 직접 실행

 

 

주식 자동화 포스팅을 하면서 유튜브 프로그램 동산(이하 "프동")의 도움을 많이 받았다. 프동이 실습 모듈을 제작하고 실행하는 과정은 다음과 같았다.

 

1. __init__.py 에서 ui.py를 import

2. ui.py 에서 kiwoom.py를 import

 

__init__.py와 ui.py 모듈은 별다는 코드가 없었다. 키움 API를 사용하는 모든 내용은 kiwoom.py에 들어있었다. 이 상태에서 코드를 실행시킬 때 kiwoom.py 파일이 아닌 __init__.py 파일을 실행한다. 그럼 kiwoom.py 파일이 import(init ← ui ← kiwoom) 되어 실행된다. 이렇게 kiwoom.py 모듈이 다른 모듈에 의해 import 되어 실행되면, 오늘의 주제인 <<if __name__ == “__main__”>> 코드가 필요 없다.

 

### __init__.py
from ui.ui import *

class Main():
    def __init__(self):
        print("실행할 메인 class")

        Ui_class()

if __name__ == "__main__":
    Main()



### ui.py
from kiwoom.kiwoom import *
import sys
from PyQt5.QtWidgets import *

class Ui_class():
    def __init__(self):
        print("Ui_class 입니다.")
        self.app = QApplication(sys.argv)
        self.kiwoom = Kiwoom()
        self.app.exec()


### kiwoom.py
class Kiwoom(QAxWidget):
    def __init__(self):
        super().__init__()
        print("Kiwoom 클래스 입니다.")
    ...
	...
    ...

그러고 보니 인터프리터에서 직접 실행하는 init.py 모듈에도 마지막에 <<if __name__ == “__main__”>> 코드가 있었다....

 

 

 

모듈이 import 되지 않고 인터프리터(interpreter)에서 바로 실행한다는 것은, kiwoom.py 모듈을 단독으로 실행하는 것을 의미하며, 이럴 경우에는 <<if __name__ == “__main__”>> 코드가 필요하다.

 

 

 

그 이유는 다음과 같다.

 

__name__은 인터프리터(interpreter)가 실행 전에 만들어준 글로벌 변수이다.

모듈이 import 되어 실행되면 __name__ 변수에 현매 모듈 이름인 kiwoom이 할당된다.

하지만, 모듈을 인터프리터(interpreter)에서 직접 실행하면 __name__ 변수에 __main__이 할당된다.

 

그래서 if 절 다음에 나오는 코드들은 class 또는 def로 정의한 내용들이다.

 

 

 

도움받은 감사한 글

1. medium.com/@chullino/if-name-main-%EC%9D%80-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C-bc48cba7f720

2. dojang.io/mod/page/view.php?id=2448

 

 

 

2021.01.22. 코리.

 

키움 API 삼성전자 자동매매 개요

 

 

이전 글 보기

 

10_키움 OPEN API 일봉데이터 가져오기_1

11_키움 OPEN API 일봉데이터 가져오기_2

12_파이참에서 주피터노트북 열기

 

 

 

앞서 1~12번의 글에서 키움 API를 활용해 로그인하고 데이터를 가져오는 등 다양한 방법을 학습하였다. 지금까지는 유튜브 채널 "프로그램 동산"의 도움이 컸다.

 

머신러닝 주가예측 및 자동매매를 위해 키움 API에 대한 기본적인 내용을 학습하였으니, 앞으로는 내가 생각한 방향으로 코딩을 진행하고, 단기 목표인 1일 5천원 벌기를 시작하고자 한다.

 

 

 

자동매매 개요

 

내가 잡은 폴더 구조이다.

 

data 폴더는 각종 자료를 쌓아둘 데이터 마트이다. 삼성주식 예측에 우선적으로 KOSPI200 종목의 주가를 사용할 예정이다. 유가와 금리 등 각종 경제 지표를 확보해서 data 폴더에 차곡차곡 쌓고, 업데이트하고, 활용할 것이다. 나중에 기회가 된다면, SQLite를 활용하여 DB를 구조화해볼 생각도 있다. 당장은 csv 파일로 관리할 예정이다.

 

 

kiwoom 폴더는 키움API를 활용해서 진행할 폴더이다. 가장 주된 역할은 주식 매매를 위한 자동주문 역할이다. 그리고 KOSPI200과 같은 시장 데이터를 확보하기 위해서도 활용할 것이다. 주피터 노트북으로 하나씩 만든 후, ".py" 파일로 변환해서 파이참에서 구동시킬 예정이다.

 

 

prediction 폴더는 data 폴더의 자료를 활용해서 머신러닝 모델링을 진행할 폴더이다. 회귀, LSTM 등 다양한 모델링을 통해 삼성전자 주가를 예측하는 모델을 만들고 업데이트할 예정이다. 주피터 노트북을 주로 활용할 예정이다.

 

 

 

 

생각한데로 잘 돼서,

매일 5천원씩 벌어서 딸내미 학원비를 마련할 거다.

투자금을 까먹지나 않았으면 좋겠다는 마음도 있다.

 

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

 

2021.01.18. 코리.

 

파이참에서 주피터노트북 열기

 

이전 글 보기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

09_키움 OPEN API 계좌평가 잔고 가져오기

10_키움 OPEN API 일봉데이터 가져오기_1

11_키움 OPEN API 일봉데이터 가져오기_2

 

 

사실 난 파이참이나 vs code와 같은 IDE 환경에 익숙하지 않다. 파이썬도 주피터노트북으로 학습을 했기 때문에 대화형 코딩에 익숙하다.

 

그간 파이참에서 코딩하면서 한줄 한줄 결과를 보고 싶었는데, 그 부분이 좀 답답했었다. IDE에 익숙해질 수 있는 시간이었다 생각한다.

 

파이참에서 주피터 노트북을 열어볼 생각을 해보다가 실행에 옮겨보았다. 너무 한방에 돼버려서 좀 허무했다. 이제 오류가 안 나면 허전하다.

 

 

 

파이참에서 주피터 노트북을 사용하려면, 주피터 노트북이 사전에 설치되어 있어야 한다.

나는 아나콘다로 파이썬을 설치했으니, 주피터 노트북이 이미 설치되어 있다.

 

 

 

파이참에서 주피터노트북 열기

 

 

파이참에서 새로운 프로젝트를 만들고, 폴더명을 정해준다.

키움 API 구동을 위해 실행 중인 32비트 가상환경에서 구동되고 있음을 확인한다(py37_32). 주가 예측을 위한 모델링은 64비트 환경에서 진행할 예정이다.

 

 

 

파이참에서 주피터노트북 열기

 

파이참 하단에 "Terminal"을 눌러준다. 터미널은 윈도우의 CMD 창과 같은 창이다. 주피터 노트북을 실행할 폴더로 이동한 뒤, jypyter notebook를 입력하고 엔터를 눌러준다.

 

 

 

파이참에서 주피터노트북 열기

 

실행 과정이 나타나고, 위 빨간 상자와 같이 주소가 출력되면 끝이다. 그리고 자동으로 브라우저(크롬 등)가 열릴 것이다. 브라우저가 자동으로 열리지 않으면 위 빨간 상자의 주소 2줄 중 한 줄을 복사한 후, 브라우저 주소에 입력하고 엔터를 누르면 다음과 같이 마음이 편안해지는 주피터 노트북이 열린다.

 

 

 

파이참에서 주피터노트북 열기

 

 

반갑다.

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

 

2021.01.18. 코리.

 

키움 OPEN API 주식 자동화

 

 

이전 글 보러 가기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

09_키움 OPEN API 계좌평가 잔고 가져오기

10_키움 OPEN API 일봉데이터 가져오기_1

 

 

 

이전 글에서 일봉데이터를 가져오기 위한 배경에 대해 학습했다. 이제 코드에 대해 알아보자. 코드 작성을 위한 전반적인 도움은 지난 글에서 설명한 유튜브 "프로그램 동산" 채널을 도움을 받았다.

 

 

먼저 조회할 종목 리스트를 만들어보자. 앞서 살펴본 바와 같이 키움 KOA에서 종목정보 관련 함수인 "GetCodeListByMarket()"를 활용할 수 있다.

 

 

키움 KOA 종목 리스트 만들기(GetCodeListByMarket)

 

GetCodeListByMarket()는 시장 구분 값만 파라미터로 보내주면, 해당 시장의 종목코드를 세미콜론(';)으로 구분하여 보내준다.

 

 

"0 장내"는 거래소에 상장되어 있는 주식과 채권 등을 모두 의미한다. 코스피(KOSPI), 코스닥(KOSDAQ) 등을 모두 포함한다.

 

"10 코스닥"은 미국의 벤처기업으로 구성된 시장인 나스닥을 본떠 만든 시장으로 벤처기업과 유망 중소기업을 위한 시장이다.

 

3 ELW, 8 ETF, 50, KONEX, 4 뮤추얼펀드, 5, 신주인수권, 6, 리츠, 9 하이얼펀드, 30 K-OTC 는 아직 별 관심이 없어서 PASS. 

 

 

from PyQt5.QtTest import *  # 일봉조회 타이머 걸기

# 종목 목록 가져오기
def get_code_list_by_market(self, market_code):
    code_list = self.dynamicCall("GetCodeListByMarket(QString)", market_code)
    code_list = code_list.split(";")[:-1]
    return code_list

# 종목 분석 실행용 함수
def calculator_fnc(self):
    code_list = self.get_code_list_by_market("10") # 10: 코스탁
    print("코스닥 갯수 %s" % len(code_list))

    for idx, code in enumerate(code_list):
        self.dynamicCall("DisconnectRealData(QString)", "4000")  # 스크린 연결 끊기
        print("%s / %s : KOSDAQ Stock Code : %s is updating..." % (idx+1, len(code_list), code))
        self.day_kiwoom_db(code=code)
        
# 일봉 가져오기
def day_kiwoom_db(self, code=None, date=None, sPrevNext="0"):
    QTest.qWait(3600) # 3.6초 delay
    self.dynamicCall("SetInputValue(QString, QString)", "종목코드", code)
    self.dynamicCall("SetInputValue(QString, QString)", "수정주가구분", "1")

# date 빈값은 오늘. None이 아니면 날짜를 입력하도록
    if date != None:
        self.dynamicCall("SetInputValue(QString, QString)", "기준일자", date)
    self.dynamicCall("CommRqData(QString, QString, int, QString)", "주식일봉차트조회", "opt10081", sPrevNext, self.screen_calculation_stock) #TR 서버로 전송
        self.calculator_event_loop.exec_()

 

종목 목록을 가져오기 위한 함수를 "get_code_list_by_market"로 만들고, market_code를 GetCodeListByMarket() 함수로 넘겨준다. 앞서 살펴본 바와 같이 GetCodeListByMarket() 함수는 종목코드를 세미콜론(;)으로 구분하여 넘겨주므로, 세미콜론을 지우기 위해 ".split(";")"을 사용한다. 끝에 [:-1]을 해준 이유는 끝자리에 남아있는 세미콜론을 지워주기 위함이다.

 

"get_code_list_by_market" 함수는 code_list를 return 해 준다.

 

 

calculator_fnc 라는 함수를 만들어서 

1. 위에서 만든 "get_code_list_by_market" 함수에 market_code를 "10"으로 넘겨주고

2. code_list 개수를 프린트하고

3. code_list에서 하나씩 빼와서

4. DisconnectRealData로 스크린 연결을 끊어주고 (이건 안 해도 됨)

5. 진행 상황을 프린트하고

6. 가지고 있는 code_list 하나를 "day_kiwoom_db"로 보내준다.

 

 

"day_kiwoom_db"라는 함수를 만들어서

1. code는 위에서 만든 "calculator_fnc"에서 넘겨받고

2. date는 빈 값으로 두고(빈 값은 오늘을 의미함)

3. sPrevNext는 일단 0으로 설정 (0은 "이전" 버튼을 누르지 않는 것임)

4. Qtest.qwait(3600)으로 이번 조회 후 다음 조회하기까지 3.6초를 기다려 준다. 기다림 없이 조회하면 키움 서버 과부하 방지를 위해 오류를 반환한다.

5. CommRqData로 데이터를 요청한다.

6. calculator_event_loop를 실행해준다.

 

 

 

def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):


    if sRQName == "주식일봉차트조회":
        code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드")
        code = code.strip()
        print("%s 일봉데이터 요청" % code)

        # 조회된 row 출력
        cnt = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)
        print(cnt)

        # 조회 자료 리스트 만들기
        # GetCommDataEx 매소드 사용 검토
        # data = self.dynamicCall("GetCommDataEx(QString, QString)", sTrCode, sRQName)
        # [['', '현재가', ...., '저가', ''] .... ['', '현재가', ...., '저가', '']]
        # [['', '현재가', '거래량', '거래대금', '날짜', '시기', '고가', '저가', '']]
        for i in range(cnt):
            data = []
            current_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") # 종가
            volume = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래량")
            trading_value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래대금")
            date = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "일자")
            staring_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "시가")
            high_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "고가")
            low_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "저가")

			data.append("")
            data.append(current_price.strip())
            data.append(volume.strip())
            data.append(trading_value.strip())
            data.append(date.strip())
            data.append(staring_price.strip())
            data.append(high_price.strip())
            data.append(low_price.strip())
            data.append("")

			self.calcul_data.append(data.copy())

		print(len(self.calcul_data))
        
        
        # 일봉 600일 이상치 가져오기(페이지 넘기기)
        if sPrevNext == "2":
            self.day_kiwoom_db(code=code, sPrevNext=sPrevNext)
        else:
            print("총 일수 %s" % len(self.calcul_data))
            pass_success = False
        
            self.calculator_event_loop.exit()

 

 

trdata_slot 함수로 준비된 데이터를 활용해서 요청한다.

중간중간에 print를 활용해서 진행상황을 출력하도록 해야 오류 생성 시 디버깅이 가능하다.

 

일봉데이터를 요청하면 다음과 같은 리스트 형태로 반환된다.

[['', '현재가', '거래량', '거래대금', '날짜', '시기', '고가', '저가', '']]

 

반환된 값을 하나씩 data 리스트에 담아준다.

 

 

 

일봉을 조회하는 opt10081 TR은 한번 조회 시 600일치의 데이터를 보내준다. 600일 이전의 데이터를 가져오기 위해서는 sPrevNext를 "2"로 넘겨줘야 한다.

 

 

600일 이전의 데이터를 모두 받아왔으면, "calculator_event_loop"를 끊어준다.

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

 

2021.01.18. 코리.

 

 

 

키움 OPEN API 일봉데이터 가져오기

 

 

이전 글 보러 가기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

09_키움 OPEN API 계좌평가 잔고 가져오기

 

 

 

이전까지 키움 OPEN API에 대한 기본적인 조회와 기능을 알아봤다면, 이제 데이터를 가져오는 방법이다. 그 시작으로 일봉데이터를 가져오는 방법을 학습한다.

 

 

영웅문 삼성전자 일봉 조회

 

 

영웅문에서 일봉차트를 조회하면 위와 같은 결과를 볼 수 있다. 보기에는 복잡해 보이는 저 차트를 그리는 데이터는 생각보다 간단한다.

 

종목의 시가, 종가, 저가, 고가, 거래량. 5가지 데이터만 있으면 캔들 차트를 그릴 수 있다.

 

 

일봉차트

 

 

시가, 종가, 고가, 저가 데이터로 일봉차트를 그릴 수 있고, 이동평균선(보라색, 파란색, 노란색 선)은 과거 20일, 60일, 120일 등의 평균 가격으로 그릴 수 있다. 

 

즉, 일봉데이터를 가져온다는 말은, 하루의 시가, 종가, 고가, 저가, 거래량 데이터를 가지고 온다는 말이다.

 

 

 

영웅문 일봉 조회, 600일

 

일봉차트를 조회하면 600일치만 가지고 온다. 위 차트에서 마지막 날짜가 2018년이다. 데이터 분석을 위해서는 더 많은 날짜의 데이터가 필요하다.

 

 

영웅문 일봉 조회, 9541일

 

과거 차트 조회 버튼을 계속 눌러주면 600일씩 늘어난다. 삼성전자의 경우, 9541일까지인 1985년까지 조회된다.

코드에서도 과거 자료가 있는 경우, 과거 차트 조회 버튼을 계속 눌러줘야 한다.

 

 

삼성전자 일봉 과거 데이터

 

과거 조회 버튼을 누를수록 화면에 전체 일봉 수(9541)가 늘어나는 것을 확인할 수 있다.

 

그러므로 "09_계좌평가 잔고 가져오기"에서 살펴본 "sPrevNext"를 이번에도 사용해야 한다. 

 

 

 

 

다음으로 조회할 종목의 리스트는 만들어야 한다. 시장 구분별로 장내, 코스닥, ELW, ETF, KONEX 등으로 구분할 수 있으며, 시장 구분에 대한 파라미터와 함께 데이터를 요청할 수 있다.

 

키움 OPEN API - KOA 종목 목록 가져오기 

 

키움 KOA에서 종목정보 관련 함수인 "GetCodeListByMarket()"를 제공한다. 시장 구분 값을 마라메터로 함께 제공하면 된다. 학습에서는 코스닥 구분 값이 10번을 사용한다.

 

 

 

키움 KOA 주식일봉차트조회

 

키움 KOA의 TR목록에서 opt10081번으로 주식 일봉 차트조회 요청을 할 수 있다. 위에서 살펴본 바와 같이, 한 번에 600개 데이터가 조회된다는 안내가 있다.

 

넘겨야 할 파라미터는 "종목코드, 기준일자, 수정주가구분" 3가지이다.

  - 종목코드는 위에서 살펴본 "GetCodeListByMarket()" 함수로 확보한다.

  - 날짜는 오늘을 기준으로 하려면 공란으로 둔다. 

  - 수정주가구분은 0과 1로 구분되는데, 1번이 수정주가구분이다. 삼성전자 주가가 2018년에 약 250만원이었는데, 이를 약 50:1로 액면분할하며 주가가 53,000원이 되었다. 수정주가구분을 0으로 주면 2018년 주가는 250만원, 현재 주가는 9만원으로 조회된다. 액면분할 등을 바로잡아 놓은 주가가 수정주가이다.

 

 

3가지 파라미터를 넘기면 받을 수 있는 데이터는 다음의 15개이다.

 

0. 종목코드

1. 현재가

2. 거래량

3. 거래대금

4. 일자

5. 시가

6. 고가

7. 저가

8. 수정주가구분

9. 수정비율

10. 대업종구분

11. 소업종구분

12. 종목정보

13. 수정주가이벤트

14. 전일종가

 

0~7번까지의 8개 데이터는 제공되는데, 8~14번까지의 7개 데이터는 조회/제공되지 않는다.

 

 

 

일봉데이터 조회 코드를 짜기 위한 기본 내용은 여기까지 이고, 코드는 다음 글에서 소개한다.

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

2021.01.14. 코리.

 

 

 

키움 OPEN API 계좌평가 잔고내역 가져오기

 

 

이전 글 보기

 

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

08_키움 KOA 이해하기_2

 

 

 

지난 05번 글에서, 키움 OPEN API에서 TR(transaction) 요청으로 예수금과 계좌잔고를 받아왔다.

 

오늘 계좌평가 잔고내역을 가지고 오고자 한다.

 

계좌평가 잔고내역은 다음 영웅문에서와 같이 내 계좌에 가지고 있는 종목들의 현황과 계좌잔고, 수익률 등의 정보를 담고 있는 화면이다. 영웅문에서는 화면번호 0391번이다.

 

 

키움 계좌평가 잔고내역

 

 

나의 모의 투가 계좌에는 총 22개 종목이 있다. 모의투자 금액으로 22개 종목을 담았는데 벌써 수익률이 5.34%로 48만원을 벌고 있다. 왜 모의투자만 버냐고....

 

 

 

계좌평가 잔고내역 조회를 하기 전에 몇가지 개념을 잡아야 한다. 계좌평가 잔고내역에서는 상당히 많은 정보가 있다.

 

1. 내 계좌 전체 평가액, 수익률, 추정자산, 매입, 손익

2. 내 계좌에 담겨있는 종목명

3. 내 계좌에 담겨있는 종목별 평가손익, 수익률, 매입가, 보유수량, 가능수량, 현재가

4. 화면 우측 상단에 있는 "다음" 버튼

 

 

1~3번은 직관적이라 설명은 생략하고, 4번에 대한 설명이 필요하다.

영웅문에서 계좌평가 잔고내역을 조회하면 종목 20개만 우선 조회된다. 보유 종목이 20개가 넘는다면, 창 우측 상단의 "다음" 버튼을 눌러 20개를 초과하는 종목 정보를 불러올 수 있다.

 

위 그림에서 봐도 "하이트진로 ~ SK이노베이션"이 20개이다. 총 수익률이 6.48%를 보이고 있다. 이 수익률은 나의 보유 종목 22개 중 우선 조회된 20개 종목에 대한 수익률이다.

 

이 상태에서 화면 우측 상단의 "다음" 버튼을 눌러주면 그 뒤에 숨어있던 "카카오게임, 빅히트" 종목이 드러난다. 그리곤 수익률이 5.34%로 감소한다. 이는 22개 종목에 대한 수익률이다.

 

이러한 방식이 키움 OPEN API에서도 동일하게 작동한다. "다음" 버튼을 눌러줄 필요가 있다는 것이다.

 

 

 

이제 키움 KOA에서 내용을 확인해 보자

 

키움 KOA - opw00018

 

키움 KOA에서 계좌평가잔고내역요청의 TR번호는 opw00018이다. 넘겨줘야하는 파라메터들에 대한 정보가 나타나 있다.

 

 

 

이번에는 키움 KOA에서 "GetRepeatCnt"에 대해 알아보자.

 

키움 KOA - GetRepeatCnt

 

GetRepeatCnt() 함수는 조회수신한 멀티데이터의 갯수(반복)수를 얻을수 있다. 예를들어 차트조회는 한번에 최대 900개 데이터를 수신할 수 있는데 이렇게 수신한 데이터갯수를 얻을때 사용한다. 이 함수는 반드시 OnReceiveTRData()이벤트가 호출될때 그 안에서 사용해야 한다.

 

지금은 계좌평가 잔고내역을 조회하고 있으며, 한번에 조회가능한 최대 데이터는 20개이다.

 

 

 

이제 코드를 알아보자.

코드 작성을 위한 전반적인 도움은 지난 글에서 설명한 유튜브 "프로그램 동산" 채널을 도움을 받았다.

 

 

class Kiwoom(QAxWidget):
    def __init__(self):
        super().__init__()

        self.account_num = "81547491111"
        self.account_pw = "********"
        self.account_stock_dict = {}
        self.detail_account_mystock()


    def detail_account_mystock(self, sPrevNext="0"):
        # 계좌평가 잔고내역 요청
        # sPrevNext="0" : 종목 페이지(목록) 넘기지 않기
        print("계좌평가 잔고내역 요청하기 연속조회 %s" % sPrevNext)
        self.dynamicCall("SetInputValue(QString, QString)", "계좌번호", self.account_num)
        self.dynamicCall("SetInputValue(QString, QString)", "비밀번호", self.account_pw)
        self.dynamicCall("SetInputValue(QString, QString)", "비밀번호입력매체구분", "00")
        self.dynamicCall("SetInputValue(QString, QString)", "조회구분", "2")
        self.dynamicCall("CommRqData(QString, QString, int, QString)", "계좌평가잔고내역요청", "opw00018", sPrevNext, self.screen_my_info)

        self.detail_account_info_event_loop.exec_()


	def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):
        if sRQName == "계좌평가잔고내역요청":
            total_buy_money = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총매입금액")
            print("총매입금액 %s" % int(total_buy_money))

            total_profit_loss_rate = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총수익률(%)")
            print("총수익률(%s) : %s" % ("%", float(total_profit_loss_rate)))

            # 계좌평가잔고 개별 종목 Count 조회, 멀티데이터 가져오기
            rows = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)
            cnt = 0
            for i in range(rows):
                code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목번호")
                code_nm = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명")
                stock_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "보유수량")
                buy_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매입가")
                learn_rate = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "수익률(%)")
                current_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가")
                total_chegual_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매입금액")
                possible_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매매가능수량")

                if code in self.account_stock_dict:
                    pass
                else:
                    self.account_stock_dict.update({code:{}})

                #code = code.strip()[1:] # 공백지우고 종목코드 앞 알파벳 제외한 값 만들기(A:장내주식, J:ELW종목, Q:ETN종목)
                code_nm = code_nm.strip() # 공백지우기
                stock_quantity = int(stock_quantity.strip())
                buy_price = int(buy_price.strip())
                learn_rate = float(learn_rate.strip())
                current_price = int(current_price.strip())
                total_chegual_price = int(total_chegual_price.strip())
                possible_quantity = int(possible_quantity.strip())

                # account_stock_dict에 담기
                self.account_stock_dict[code].update({"종목명": code_nm})
                self.account_stock_dict[code].update({"보유수량": stock_quantity})
                self.account_stock_dict[code].update({"매입가": buy_price})
                self.account_stock_dict[code].update({"수익률(%)": learn_rate})
                self.account_stock_dict[code].update({"현재가": current_price})
                self.account_stock_dict[code].update({"매입금액": total_chegual_price})
                self.account_stock_dict[code].update({"매매가능수량": possible_quantity})

                cnt += 1

            print("계좌에 있는 종목 %s" % cnt)
            print("계좌에 있는 종목 %s" % self.account_stock_dict)

            # 종목이 20개 초과라 다음 페이지 클릭이 필요한 경우
            # 종목이 20개 초과인 경우, sPrevNext가 2로 반환됨
            if sPrevNext == "2" :
                self.detail_account_mystock(sPrevNext="2")
            else:
                self.detail_account_info_event_loop.exit()

 

"def detail_account_mystock(self, sPrevNext="0"):"에서 목록이 몇개인지 모르므로, sPrevNext는 우선 0으로 지정한다. 0은 "다음" 버튼을 누르지 않는 것을 의미한다.

 

SetInputValue함수로 넘길 파라메터(아이디, 비번 등)를 넘겨준다. 그것들을 모아 CommRqData 함수로 데이터를 넘긴다.

 

 

"def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):" TR보내는 슬롯을 만들어 작업한다.

 

"total_buy_money"와 "total_profit_loss_rate"는 내 계좌의 총정보를 의미한다. 가장 위의 영웅문 그림에서 "총수익률, 총손익" 등을 의미한다.

 

 

"rows = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)"로 행 수를 rows 변수에 담아 둔다. 그 아래 for문에서 종목 하나씩 관련 정보를 요청한다. code가 account_stock_dict에 있으면 넘어가고, 없으면 딕셔너리를 업데이트(자료 추가하기)를 실행한다. 

 

"self.account_stock_dict.update({code:{}})"는 다음으로 대체하여 사용할 수 있다.

"self.account_stock_dict[code] = {}"

 

수신한 데이트 전처리를 해주고, 만들어 놓은 account_stock_dict에 자료를 업데이트 한다.

 

"cnt+= 1" cnt 변수를 1 증가시켜 준다.

 

 

종목이 20개를 초과하여 sPrevNextrk "2"로 반환되는 경우, "sPrevNext="2" 로 넘겨 "다음버튼"을 누를 수 있도록 해준다.

 

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

2021.01.13. 코리.

 

 

 

키움 KOA 이해하기_2

 

이전 글 보기

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

06_키움 KOA 설치하기

07_키움 KOA 이해하기

 

 

 

 

키움 KOA의 개요는 다음과 같다.

 

OpenAPI(Application Programing Interface)는 
국내주식상품과 코스피200 지수선물/옵션, 주식선물을 거래할 수 있는 거래/분석프로그램을 개발 할 수 있는 일종의 프로그램이며 COM형태로 제공합니다. 

주요기능은 시세데이터 조회와 실시간 데이터제공, 주문기능, 조건검색기능(주식만 가능)을 제공하며 모두 로그인 이후 가능합니다.

 

여기서 COM은 OCX를 의미한다. OCX는 "07. 키움 KOA 이해하기"에서 다루었다.

 

주요기능은 "시세데이터 조회, 실시간 데이터제공, 주문기능, 조건검색기능(주식만 가능)"이다. 이 정도면 내가 만들고자 하는 것을 하기엔 문제가 없어 보인다.

 

 

 

키움 API의 통신동작은 다음과 같다.

 

[통신동작] OpenAPI함수호출과 이벤트는 모두 비동식 방식으로 서버에 시세조회나 주문등을 함수호출로 요청하면 처리 결과를 전용 이벤트를 호출해서 전달합니다.

여기서 수신데이터를 가져오려면 반드시 이벤트 리턴전에 적절한 데이터 획득함수를 사용해서 얻어와야 합니다. 이벤트가 호출하기 전에 데이터 획득함수를 사용하거나 이벤트 리턴후에 호출하게 되면 혹은 임의로 이벤트를 호출하면 정상적인 데이터를 얻을수 없습니다.

지금까지 설명을 조회요청을 예를들어 정리하면 다음과 같습니다. 이외 OpenAPI기능도 관련 함수와 이벤트 차이가 있을뿐 전체 동작은 동일합니다.

기능요청(조회함수 CommRqData, CommKwRqData 호출) --->
이벤트 호출(OnReceiveTRData ) --->
데이터 획득 (GetCommData함수) 

 

요청은 반드시 전용 이벤트를 호출해서 전달한다. 수신한 데이터는 이벤트 리턴 전에 얻어와야 한다. 이벤트를 리턴하면 정상적인 데이터를 얻을 수 없게 된다.

 

CommRqData, CommKwRqData, OnReceiveTRData, GetCommData...

유튜브 프로그램 동산 채널을 보면서 공부한 코드의 의미를 하나씩 깨우쳤다.

 

 

[화면번호] 화면번호는 서버에 조회나 주문등 필요한 기능을 요청할때 이를 구별하기 위한 키값으로 이해하시면 됩니다. 0000(혹은 0)을 제외한 임의의 숫자를 사용하시면 되는데 갯수가 200개로 한정되어 있기 때문에 이 갯수를 넘지 않도록 관리하셔야 합니다. 만약 사용하는 화면번호가 200개를 넘는 경우 조회결과나 주문결과에 다른 데이터가 섞이거나 원하지 않는 결과를 나타날 수 있습니다. 

 

화면번호(스크린번호)는 "05_키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)"에서 살펴본 내용이다.

 

 

 

[이벤트] 시세조회나 조건검색요청등 관련함수 호출로 요청하면 서버에서 이를 처리해서 결과를 OpenAPI의 특정함수를 호출해서 알려주는데 이 함수를 이벤트라고 합니다.

조회를 예로 들면 SetInputValue(), CommRqData()함수로 조회를 하면 조회결과를 만들어서 OpenAPI로 전달하고 조회한 사용자의 OnReceiveTRData를 호출하게 됩니다.

이벤트는 일반함수와 구별하기 위해 이름앞에 On~에 있으며 OnEventConnect, OnReceiveTRData, OnReceiveRealData등이 있습니다. 로그인, 조회, 주문, 조건검색등 기능별로 함수와 이벤트가 분류되어 있으니 용도에 맞는 함수와 이벤트를 사용해야 합니다.

 

SetInputValue(), CommRqData(), OnReceiveTRData, OnEventConnect, OnReceiveTRData, OnReceiveRealData 등 코딩하면서 봤던 함수와 이벤트 이름들이 다 여기에 기인한 것들이다.

 

사용 목적과 이유를 모르고 코딩할 때는 궁금한 게 많았는데, 작동 원리를 확인하니 마음이 편해진다.

 

 

 

 

이런 내용들이 "KOA-개발가이드-키움OPenAPI"에 다 있었는데, 안본게 후회된다. 이제라도 봐서 다행이다. 그때 봤다면,,,, 지금처럼 무슨 말인지 이해를 했을까??

 

 

 

참고한 내용

- 키움 KOA

- 키움 OpenAPI+ 개발가이드

 

 

 

2021.01.09. 코리.

 

+ Recent posts