대신증권 CYBOS PLUS 프로그램 구현 (19) - 전종목 차트 데이터 저장하기 ②
프로그램 구현 목표
- 문제점 확인하기: 이어받기가 안 되네 ?
- 문제점 보완하기 ①: 차트 데이터를 조회한 시점을 저장할 테이블을 생성해보자.
- 문제점 보완하기 ②: 차트 데이터 조회 일자가 저장된 테이블을 불러와보자.
문제점 확인하기: 이어받기가 안 되네 ?
기존까지 제작한 프로그램을 다시 실행시켜서 전종목 차트 데이터 조회 버튼을 누르면 차트 데이터를 조회하는 것은 정상적으로 동작하지만 정작 데이터를 조회하는 꼴을 보면 이미 저장되어 있는 종목에 대한 차트 데이터도 조회한다는 것을 확인할 수 있다. 이와 더불어 기존에 `class manage_db`(con_mysql.py 파일) 클래스 내부에서 오류가 발생했을 때(`except`)에 "오류가 발생했습니다. 데이터를 저장하지 않습니다."라는 문구와 함께 오류 메시지(`e`)를 출력하도록 했는데, 이 메시지가 출력되면서 오류가 발생한다는 것 역시 확인할 수 있다.
▶ 오류 메시지 확인하기(Table 'a000050' already exists.)
sqlalCon 클래스가 호출되었습니다.
with 구문이 호출되었습니다.
오류가 발생했습니다. 데이터를 저장하지 않습니다. 오류 메시지:Table 'a000050' already exists.
이 오류는 단순하게 '이미 이 테이블이 존재합니다.'라는 오류로 해석할 수 있다. 물론 이 부분은 `to_sql` 구문을 사용할 때 메서드에서 지원하는 옵션(`if_exists=`)을 활용하여 테이블이 존재하더라도 강제로 저장하도록 하거나 기존의 데이터에 아예 추가하여 저장하도록 할 수도 있긴 하다. 하지만 이미 정상적으로 저장되어 있는 종목에 대해서도 다시 차트 데이터를 조회하는 것은 확실히 문제점이 맞다. 현재 해결해야 하는 문제점은 아래의 두 가지로 요약할 수 있다.
- 정상적으로 저장되어 있는 종목에 대해서도 차트 데이터를 다시 조회한다.
- 추가적으로 데이터가 추가되어야 하는 종목도 이미 저장된 테이블이 있다고 데이터를 저장하지 않는다.
문제점 보완하기 ①: 차트 데이터를 조회한 시점을 저장할 테이블을 생성해보자.
첫 번째 문제점을 보완하는 방법은 간단하다. 단순하게 '우리가 차트 데이터를 조회했던 날짜'를 저장함으로써 차트 데이터를 조회하는 날짜와 사전에 저장되어 있는 날짜 간의 대소 비교를 통해 차트 데이터를 조회해야 하는 종목인지 아닌지를 구분해내는 것이다. 이전의 게시글에서 MySQL WorkBench 사진을 보여줄 때 봤을지 모르겠지만, 본인의 경우에는 'item_data'라는 데이터베이스 내에서 차트 데이터를 조회한 날짜 데이터들을 처리하고 있다.
이와 관련하여 우리는 `def _load_DB()` 함수 내에서 정의해두었던 `DB_list` 변수 내에 프로그램이 실행되는 시점에 데이터베이스의 존재 여부를 판단해야 할 데이터베이스 목록을 적어두었었는데, 그 안에 'saved_point'라는 데이터베이스도 추가해주도록 하자. 이제 앞으로는 프로그램을 실행시키면 이 데이터베이스가 생성(또는 연결)될 것이다.
## Boss.py ##
def _load_DB(self):
"""아래의 DB_list 목록에 있는 데이터베이스 존재 여부 확인"""
DB_list = ['min5_data', 'min15_data', 'day_data', 'week_data', 'month_data', 'saved_point']
for db in DB_list:
con_mysql.check_db()._make_db(db)
그렇다면 이제 데이터베이스에 들어가야 할 테이블(데이터프레임, `DataFrame`)을 생성해준 후에 'saved_point' 데이터베이스에 저장해주어야 하는데, 차트 데이터를 조회한 시점을 저장하기 위한 데이터프레임은 어떻게 만들어야 할까 ? 아래의 표를 확인해보자. 우리가 만들고자 하는 데이터프레임 형식과 동일한 표다. 이제 이 아래와 같은 표를 하나의 데이터프레임으로 만들어서 'saved_point' 데이터베이스에 저장해줄 것인데, 기본적으로 이 데이터프레임은 차트 데이터 조회를 시작하기 전에 만들어져 있어야 할 것이다.
왜냐하면, 이 표가 우리가 차트 데이터를 조회하고자 할 때 필요한 기준치가 되기 때문이다. 예를 들어, 오늘 날짜가 2024년 9월 20일이고 차트 데이터를 조회하던 도중에 프로그램이 꺼져서 다시 이어받기를 하려고 한다고 가정하고 아래의 표를 확인해보도록 하자. 2024년 9월 20일을 기준으로 보았을 때, 우리는 저장되어 있는 차트 데이터를 조회 일자가 9월 20일보다 이전인 경우에만 차트 데이터를 조회하면 될 것이다.
위의 두 사진 중 왼쪽의 사진은 '어제 차트 데이터를 조회하다가 멈추었고 금일 다시 차트 데이터를 조회하기 시작한 경우'에 나타날 수 있는 데이터의 모습으로, 차트 데이터를 조회한 날짜가 어제인 부분(주황색 배경)에 대해서만 차트 데이터를 조회하면 된다. 오른쪽의 사진은 '한 번도 차트 데이터를 조회하지 않은 경우'에 나타날 수 있는 데이터의 모습으로 왼쪽 사진과 마찬가지로 저장되어 있는 날짜("0")가 조회하고자 하는 날짜("20240920")보다 이전이기 때문에 차트 데이터를 조회하면 된다.
그렇다면 이제 위의 데이터프레임을 생성하는 함수를 새롭게 생성해보도록 하자. 이 기능은 처음에 차트 데이터 조회 날짜 정보를 저장할 때 한 번만 사용하고 그 후로는 새롭게 생성할 목적으로 사용할 일이 없기 때문에, 한 번만 사용하고 나서부터는 아예 다른 내용의 함수로 바꾸어줄 것이다.(추후에 새롭게 생성해야 할 일이 있을 것 같다면 남겨두어도 된다.) 일단 아래의 코드를 참고해보자.
※ Line: 26, 37 ~ 51
## Boss.py ##
import pandas as pd
import win32com.client
from pywinauto import application
import con_mysql
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time
from threading import Thread
## GUI ##
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from gui import qt_gui
main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
def __init__(self):
super().__init__()
self.setupUi(self)
self._open_cybosplus() ## 자동 로그인 함수
self._load_account() ## 계좌 조회 함수
self._load_DB() ## 데이터베이스 조회 함수
self._load_savepoint() ## saved_point 테이블 생성 함수
## GUI 관련 이벤트 처리 ##
self.pushButton.clicked.connect(self._GetStockListByMarket)
self.pushButton_2.clicked.connect(self._day_range)
self.pushButton_3.clicked.connect(self._len_chart)
self.comboBox_2.currentIndexChanged.connect(lambda: qt_gui.etc(self).comboBox_2_CIC())
self.pushButton_4.clicked.connect(self._save_all_chart)
def _load_savepoint(self):
"""
일단은 종목별 차트 데이터 조회 날짜를 저장할 데이터프레임을 생성해보자.
"""
all_code = self._GetStockListByMarket()
a = {'item_code':[], 'min3_data':[], 'min5_data':[], 'min15_data':[], 'min30_data':[],
'day_data':[], 'week_data':[], 'month_data':[]}
df = pd.DataFrame(a, columns=['item_code', 'min3_data', 'min5_data', 'min15_data', 'min30_data',
'day_data', 'week_data', 'month_data'])
for item_code in all_code:
df.loc[len(df), 'item_code'] = item_code
print(df)
con_mysql.manage_db()._save_table('saved_point', 'saved_point', df.fillna('0'))
문제점 보완하기 ②: 차트 데이터 조회 일자가 저장된 테이블을 불러와보자.
가장 먼저 테이블을 불러오는 기능이 필요한데, 이 기능은 테이블을 저장하는 함수인 `def _save_table()` 함수가 입력되어 있는 con_mysql.py 내에서 구현할 예정이다. (함수 이름은 `def _read_table()`이다.)
※ Line: 28 ~ 37
## con_mysql.py ##
class manage_db:
def __init__(self):
pass
def _save_table(self, db_name, table_name, table_data):
"""
table_data(데이터프레임, 차트 데이터 등)을 데이터베이스(db_name)에
table_name(보통 종목코드가 됨)라는 이름으로 하여 저장"""
if type(table_data) != pd.DataFrame: ## 데이터타입이 데이터프레임이 아닌 경우
print(f"전달받은 데이터의 데이터타입이 데이터프레임이 아닙니다.")
return False ## False를 반환하고 종료
with sqlalCon(f'{db_name}') as con:
try:
table_data.to_sql(name=table_name, con=con.engine, index=False)
print(f"데이터가 저장되었습니다. (테이블명:{table_name})")
except Exception as e:
con.session.rollback()
print(f"오류가 발생했습니다. 데이터를 저장하지 않습니다. 오류 메시지:{e}")
finally:
con.session.commit()
print(f"데이터를 저장하였습니다.")
print(f"MySQL 연결을 종료합니다.")
con.engine.dispose() ## MySQL 프로그램 연결 종료
print(f"MySQL과의 연결이 종료되었습니다.")
def _read_table(self, db_name, table_name):
with sqlalCon(f'{db_name}') as con:
try:
table_data = pd.read_sql_table(table_name, con=con.engine)
return table_data
except Exception as e:
print(f"오류가 발생했습니다. 오류 메시지:{e}")
print(f"MySQL 연결을 종료합니다.")
con.engine.dispose() ## MySQL 프로그램 연결 종료
print(f"MySQL과의 연결이 종료되었습니다.")
이제 다시 Boss.py 파일로 돌아와서, 초기화 함수에서 이 `def _read_table()` 함수를 활용하여 'saved_point' 테이블을 불러와서 출력해보자.
※ Line: 28, 29
## Boss.py ##
import pandas as pd
import win32com.client
from pywinauto import application
import con_mysql
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time
from threading import Thread
## GUI ##
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from gui import qt_gui
main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
def __init__(self):
super().__init__()
self.setupUi(self)
self._open_cybosplus() ## 자동 로그인 함수
self._load_account() ## 계좌 조회 함수
self._load_DB() ## 데이터베이스 조회 함수
self.saved_point = con_mysql.manage_db()._read_table('saved_point', 'saved_point')
print(self.saved_point)
# self._load_savepoint() ## saved_point 테이블 생성 함수
▶ 실행 결과 확인하기
sqlalCon 클래스가 호출되었습니다.
with 구문이 호출되었습니다.
with 구문이 종료되었습니다.
세션을 종료하였습니다.
item_code min3_data min5_data ... day_data week_data month_data
0 A000020 0 0 ... 0 0 0
1 A000040 0 0 ... 0 0 0
2 A000050 0 0 ... 0 0 0
3 A000070 0 0 ... 0 0 0
4 A000075 0 0 ... 0 0 0
... ... ... ... ... ... ... ...
3993 A950160 0 0 ... 0 0 0
3994 A950170 0 0 ... 0 0 0
3995 A950190 0 0 ... 0 0 0
3996 A950200 0 0 ... 0 0 0
3997 A950220 0 0 ... 0 0 0
[3998 rows x 8 columns]
이제 'saved_point' 테이블을 정상적으로 불러온 후 그 데이터를 활용할 수 있게 되었으니 차트 데이터를 조회할 때마다 저장되어 있는 날짜 데이터를 불러오고 오늘 날짜와 비교하여 오늘 날짜보다 이전 날짜에 차트 데이터를 조회했다면 차트 데이터를 조회하도록 하고, 저장되어 있는 데이터가 이미 최신 데이터라면 따로 조회하지 않고 넘어가도록 하는 기능을 구현해보도록 하자.
그렇다면 이제는 데이터프레임에 입력되어 있는 데이터에 접근할 수 있는 방법에 대해 알아야 하는데, `loc`을 통해 접근할 수 있다. 이 함수는 기본적으로 `데이터프레임.loc[인덱스번호, 칼럼명]`과 같은 형태로 사용하게 되는데, 아래와 같은 예시 데이터(변수 이름은 `df`로 가정)가 있다고 가정하고 특정 데이터에 접근하기 위해 사용해야 하는 코드를 살펴보도록 하자.
- `df.loc[0, 'min3_data']`: A000020 종목의 min3_data인 20240101 데이터에 접근
- `df.loc[1, 'min5_data']`: A000040 종목의 min5_data인 20230101 데이터에 접근
- `df.loc[2, 'min15_data']`: A000060 종목의 min15_data인 20220101 데이터에 접근
- `df.loc[4, 'day_data']`: A000100 종목의 day_data인 20200101 데이터에 접근
이제 데이터프레임의 데이터에 접근하는 방법을 알았다면, 특정 종목코드의 인덱스 번호를 조회하는 방법을 알아야 한다. 여태까지는 A000020이라는 종목의 인덱스 번호가 0이라는 것을 우리가 알기 때문에 0이라는 데이터를 전달해주긴 했지만, 우리가 코드를 구현할 때에는 종목코드를 가지고 인덱스 번호를 가져와야 하기 때문에, item_data 칼럼의 A000020 종목코드가 갖는 인덱스 번호를 가져와야 한다. 여전히 데이터프레임의 변수명이 `df`라 가정하고 그 방법을 살펴보자.
- `df.index[df['item_code'] == "A000020"]` : A000020 종목의 인덱스 번호인 0 데이터에 접근
- `df.index[df['item_code'] == "A000040"]` : A000040 종목의 인덱스 번호인 1 데이터에 접근
- `df.index[df['item_code'] == "A000060"]` : A000060 종목의 인덱스 번호인 2 데이터에 접근
- `df.index[df['item_code'] == "A000100"]` : A000100 종목의 인덱스 번호인 4 데이터에 접근
이제 위의 두 내용을 조합해보자.
- `df.loc[df.index[df['item_code'] == "A000020"], 'min3_data']` : 종목코드 A000020의 min3_data인 20240101 접근
- `df.loc[df.index[df['item_code'] == "A000100"], 'day_data']` : 종목코드 A000100의 day_data인 20200101 접근
여기까지 이해가 됐다면, 다시 Boss.py 파일의 전 종목 차트 데이터를 조회하는 함수(`def _save_all_chart`)로 돌아와보자. 이 함수에는 반복문(`for`)을 통해 전체 종목코드를 대상으로 한 종목씩 차트 데이터를 조회하고 저장하도록 하는 기능까지 구현되어 있는 상태인데, 여기서 프로그램 시작과 동시에 불러왔던 `self.saved_point` 변수를 가지고 종목코드별로 갖고 있는 인덱스 번호를 불러와보도록 하자.
def _save_all_chart(self):
"""전종목 차트 데이터 조회 후 저장하는 함수"""
all_code = self._GetStockListByMarket()
data_len = 1000000 ## 차트 데이터를 조회할 개수
for item_code in all_code:
print(f"조회 중인 종목코드:{item_code}")
print(f" 이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.")
idx_num = self.saved_point.index[self.saved_point['item_code'] == item_code]
print(f" 인덱스 번호는 {idx_num} 입니다.")
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 5, save_gubun=True) ## 5분봉 조회
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 15, save_gubun=True) ## 15분봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "D", data_len, save_gubun=True) ## 일봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "W", data_len, save_gubun=True) ## 주봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "M", data_len, save_gubun=True) ## 월봉 조회
▶ 프로그램 실행 결과
조회 중인 종목코드:A000020
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([0], dtype='int64') 입니다.
조회 중인 종목코드:A000040
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([1], dtype='int64') 입니다.
조회 중인 종목코드:A000050
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([2], dtype='int64') 입니다.
조회 중인 종목코드:A000070
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([3], dtype='int64') 입니다.
조회 중인 종목코드:A000075
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([4], dtype='int64') 입니다.
조회 중인 종목코드:A000080
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([5], dtype='int64') 입니다.
조회 중인 종목코드:A000087
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([6], dtype='int64') 입니다.
조회 중인 종목코드:A000100
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([7], dtype='int64') 입니다.
조회 중인 종목코드:A000105
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([8], dtype='int64') 입니다.
조회 중인 종목코드:A000120
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([9], dtype='int64') 입니다.
조회 중인 종목코드:A000140
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([10], dtype='int64') 입니다.
이제 차트 데이터를 조회하는 종목 코드의 인덱스 번호를 불러와서 `idx_num`이라는 변수에 정보를 입력했으니, 이 변수를 활용하여 `self.saved_point` 변수 내에서 각 종목들의 'min3_data', 'min5_data', 'min15_data' 등의 칼럼에 어떠한 데이터가 입력되어 있는지 확인해보도록 하자.
※ Line: 13 ~ 19
def _save_all_chart(self):
"""전종목 차트 데이터 조회 후 저장하는 함수"""
all_code = self._GetStockListByMarket()
data_len = 1000000 ## 차트 데이터를 조회할 개수
for item_code in all_code:
print(f"조회 중인 종목코드:{item_code}")
print(f" 이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.")
idx_num = self.saved_point.index[self.saved_point['item_code'] == item_code]
print(f" 인덱스 번호는 {idx_num} 입니다.")
print(f"저장되어 있는 3분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min3_data']}")
print(f"저장되어 있는 5분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min5_data']}")
print(f"저장되어 있는 15분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min15_data']}")
print(f"저장되어 있는 30분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min30_data']}")
print(f"저장되어 있는 일봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'day_data']}")
print(f"저장되어 있는 주봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'week_data']}")
print(f"저장되어 있는 월봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'month_data']}")
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 5, save_gubun=True) ## 5분봉 조회
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 15, save_gubun=True) ## 15분봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "D", data_len, save_gubun=True) ## 일봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "W", data_len, save_gubun=True) ## 주봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "M", data_len, save_gubun=True) ## 월봉 조회
▶ 실행 결과 확인하기
조회 중인 종목코드:A000020
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([0], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0 0
Name: min3_data, dtype: object
저장되어 있는 5분봉 차트 데이터 조회일자:0 0
Name: min5_data, dtype: object
저장되어 있는 15분봉 차트 데이터 조회일자:0 0
Name: min15_data, dtype: object
저장되어 있는 30분봉 차트 데이터 조회일자:0 0
Name: min30_data, dtype: object
저장되어 있는 일봉 차트 데이터 조회일자:0 0
Name: day_data, dtype: object
저장되어 있는 주봉 차트 데이터 조회일자:0 0
Name: week_data, dtype: object
저장되어 있는 월봉 차트 데이터 조회일자:0 0
Name: month_data, dtype: object
조회 중인 종목코드:A000040
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([1], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:1 0
Name: min3_data, dtype: object
저장되어 있는 5분봉 차트 데이터 조회일자:1 0
Name: min5_data, dtype: object
저장되어 있는 15분봉 차트 데이터 조회일자:1 0
Name: min15_data, dtype: object
저장되어 있는 30분봉 차트 데이터 조회일자:1 0
Name: min30_data, dtype: object
저장되어 있는 일봉 차트 데이터 조회일자:1 0
Name: day_data, dtype: object
저장되어 있는 주봉 차트 데이터 조회일자:1 0
Name: week_data, dtype: object
저장되어 있는 월봉 차트 데이터 조회일자:1 0
Name: month_data, dtype: object
조회 중인 종목코드:A000050
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([2], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:2 0
Name: min3_data, dtype: object
저장되어 있는 5분봉 차트 데이터 조회일자:2 0
Name: min5_data, dtype: object
저장되어 있는 15분봉 차트 데이터 조회일자:2 0
Name: min15_data, dtype: object
저장되어 있는 30분봉 차트 데이터 조회일자:2 0
Name: min30_data, dtype: object
저장되어 있는 일봉 차트 데이터 조회일자:2 0
Name: day_data, dtype: object
저장되어 있는 주봉 차트 데이터 조회일자:2 0
Name: week_data, dtype: object
저장되어 있는 월봉 차트 데이터 조회일자:2 0
Name: month_data, dtype: object
조회 중인 종목코드:A000070
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([3], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:3 0
Name: min3_data, dtype: object
저장되어 있는 5분봉 차트 데이터 조회일자:3 0
Name: min5_data, dtype: object
저장되어 있는 15분봉 차트 데이터 조회일자:3 0
Name: min15_data, dtype: object
저장되어 있는 30분봉 차트 데이터 조회일자:3 0
Name: min30_data, dtype: object
저장되어 있는 일봉 차트 데이터 조회일자:3 0
Name: day_data, dtype: object
저장되어 있는 주봉 차트 데이터 조회일자:3 0
Name: week_data, dtype: object
저장되어 있는 월봉 차트 데이터 조회일자:3 0
Name: month_data, dtype: object
데이터는 정확하게 갖고 오고 있긴 하지만, 데이터 타입이 뭔가 이상하게 반환되고 있다는 걸 확인할 수 있다. 우리가 필요한 데이터는 0이라는 데이터만 필요한데, 0이라는 데이터가 인덱스 번호 데이터를 포함한 여러 가지 데이터들이 반환되고 있는 것이다. 우리는 이러한 데이터 타입에서 0이라는 데이터만 갖고 오고자 할 때에는 `.item()` 메서드를 사용하면 된다.
※ Line: 13 ~ 19
def _save_all_chart(self):
"""전종목 차트 데이터 조회 후 저장하는 함수"""
all_code = self._GetStockListByMarket()
data_len = 1000000 ## 차트 데이터를 조회할 개수
for item_code in all_code:
print(f"조회 중인 종목코드:{item_code}")
print(f" 이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.")
idx_num = self.saved_point.index[self.saved_point['item_code'] == item_code]
print(f" 인덱스 번호는 {idx_num} 입니다.")
print(f"저장되어 있는 3분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min3_data'].item()}")
print(f"저장되어 있는 5분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min5_data'].item()}")
print(f"저장되어 있는 15분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min15_data'].item()}")
print(f"저장되어 있는 30분봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'min30_data'].item()}")
print(f"저장되어 있는 일봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'day_data'].item()}")
print(f"저장되어 있는 주봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'week_data'].item()}")
print(f"저장되어 있는 월봉 차트 데이터 조회일자:{self.saved_point.loc[idx_num, 'month_data'].item()}")
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 5, save_gubun=True) ## 5분봉 조회
# CpSysDib.StockChart().chart_MT(item_code, "m", data_len, 15, save_gubun=True) ## 15분봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "D", data_len, save_gubun=True) ## 일봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "W", data_len, save_gubun=True) ## 주봉 조회
# CpSysDib.StockChart().chart_DWM(item_code, "M", data_len, save_gubun=True) ## 월봉 조회
▶ 실행 결과 확인하기
조회 중인 종목코드:A000020
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([0], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
조회 중인 종목코드:A000040
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([1], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
조회 중인 종목코드:A000050
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([2], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
조회 중인 종목코드:A000070
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([3], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
조회 중인 종목코드:A000075
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([4], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
조회 중인 종목코드:A000080
이 종목코드가 self.saved_point 변수(DataFrame)에서 갖는 인덱스 번호를 추출합니다.
인덱스 번호는 Int64Index([5], dtype='int64') 입니다.
저장되어 있는 3분봉 차트 데이터 조회일자:0
저장되어 있는 5분봉 차트 데이터 조회일자:0
저장되어 있는 15분봉 차트 데이터 조회일자:0
저장되어 있는 30분봉 차트 데이터 조회일자:0
저장되어 있는 일봉 차트 데이터 조회일자:0
저장되어 있는 주봉 차트 데이터 조회일자:0
저장되어 있는 월봉 차트 데이터 조회일자:0
이제 다음 게시글에서는 차트 데이터를 조회했을 때 조회한 날짜를 기존에 저장되어 있는 날짜와 비교하고 새롭게 조회했다면 `self.saved_point` 테이블에 저장하는 기능을 구현해보도록 하자.
'AUTO TRADE > [대신증권] CYBOS PLUS' 카테고리의 다른 글
대신증권 CYBOS PLUS 프로그램 구현 (21) - 실시간 데이터 수신받기 ① (7) | 2024.09.27 |
---|---|
대신증권 CYBOS PLUS 프로그램 구현 (20) - 전종목 차트 데이터 저장하기 ③ (0) | 2024.09.23 |
대신증권 CYBOS PLUS 프로그램 구현 (18) - 전종목 차트 데이터 저장하기 ① (7) | 2024.09.18 |
대신증권 CYBOS PLUS 프로그램 구현 (17) - 데이터베이스 관리 자동화 (0) | 2024.09.18 |
대신증권 CYBOS PLUS 프로그램 구현 (16) - 차트 데이터 저장하기 ③ (2) | 2024.09.18 |
소중한 공감 감사합니다