KevinFire2030 / Fire2025

0 stars 0 forks source link

17.1 SQLite #6

Open KevinFire2030 opened 1 year ago

KevinFire2030 commented 1 year ago

17.1 SQLite

KevinFire2030 commented 1 year ago

17.1.1 sqlite 모듈 기초

con = sqlite3.connect("D:\Fire2025\23W23\ch17\kospi.db")
Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2022.3.2\plugins\python-ce\helpers\pydev\pydevconsole.py", line 364, in runcode
    coro = func()
  File "<input>", line 1, in <module>
sqlite3.OperationalError: unable to open database file
con = sqlite3.connect("D:/Fire2025/23W23/ch17/kospi.db")

cursor.execute("CREATE TABLE kakao (Date text, Open int, High int, Low int, Close int, Volume int)")


- 테이블에 데이터 넣기

INSERT INTO kakao VALUES ("6.06.03", 97000, 98600, 9690, 98000, 321405) cursor.execute("INSERT INTO kakao VALUES ("6.06.03", 97000, 98600, 9690, 98000, 321405)")

주의! SQL 내부에서 큰따옴표 사용시 에러 발생 cursor.execute("INSERT INTO kakao VALUES ("6.06.03", 97000, 98600, 9690, 98000, 321405)") ^ SyntaxError: invalid syntax 예)


- 작업한 내용 데이터베이스에 반영

con.commit() con.close()

KevinFire2030 commented 1 year ago

17.1.2 데이터베이스 브라우저

데이터베이스 브라우저는 데이터베이스에 저장된 데이터를 효과적으로 보여주는 프로그램

https://sqlitebrowser.org/dl/

image

image

image

KevinFire2030 commented 1 year ago

7.1.3 데이터베이스로부터 데이터 읽기

con = sqlite3.connect("D:/Fire2025/23W23/ch17/kospi.db")
cursor = con.cursor()
df = cursor.execute("SELECT * FROM kakao")
cursor.fetchone()
('16.06.03', 97000, 98600, 9690, 98000, 321405)
con = sqlite3.connect("D:/Fire2025/23W23/ch17/kospi.db")
cursor = con.cursor()
df = cursor.execute("SELECT * FROM kakao")
kakao = cursor.fetchall()

In [12]: kakao[0][0]
Out[12]: '16.06.03'

In [13]: kakao[0][1]
Out[13]: 97000

In [14]: kakao[0][2]
Out[14]: 98600
KevinFire2030 commented 1 year ago

7.2 Pandas와 SQLite

KevinFire2030 commented 1 year ago

7.2.1 DataFrame 객체를 SQLite DB에 저장하기

import pandas as pd
from pandas import Series, DataFrame
raw_data = {'col0': [1, 2, 3, 4], 'col1': [10, 20, 30, 40], 'col2':[100, 200, 300, 400]}
df = DataFrame(raw_data)
df
   col0  col1  col2
0     1    10   100
1     2    20   200
2     3    30   300
3     4    40   400

pandas 웹 페이지(http://pandas.pydata.org/)에서 to_sql 메서드를 살펴보면 다음과 같이 정의돼 있습니다.

df.to_sql('test', con)


DataFrame.to_sql(name, con, flavor='sqlite', schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None)

표 17.1 DataFrame.to_sql 메서드 파라미터

파라미터 | 설명 -- | -- name | SQL 테이블 이름으로 파이썬 문자열로 형태로 나타낸다. con | Cursor 객체 flavor | 사용한 DBMS를 지정할 수 있는데 'sqlite' 또는 'mysql'을 사용할 수 있다. 기본값은 'sqlite'이다. schema | Schema를 지정할 수 있는데 기본값은 None이다. if_exists | 데이터베이스에 테이블이 존재할 때 수행 동작을 지정한다. 'fail', 'replace', 'append' 중 하나를 사용할 수 있는데 기본값은 'fail'이다. 'fail'은 데이터베이스에 테이블이 있다면 아무 동작도 수행하지 않는다. 'replace'는 테이블이 존재하면 기존 테이블을 삭제하고 새로 테이블을 생성한 후 데이터를 삽입한다. 'append'는 테이블이 존재하면 데이터만을 추가한다. index | DataFrame의 index를 데이터베이스에 칼럼으로 추가할지에 대한 여부를 지정한다. 기본값은 True이다. index_label | 인덱스 칼럼에 대한 라벨을 지정할 수 있다. 기본값은 None이다. chunksize | 한 번에 써지는 로우의 크기를 정숫값으로 지정할 수 있다. 기본값은 None으로 DataFrame 내의 모든 로우가 한 번에 써진다. dtype | 칼럼에 대한 SQL 타입을 파이썬 딕셔너리로 넘겨줄 수 있다.

to_sql 메서드에는 여러 파라미터가 있지만 대부분 기본값을 가지고 있어 따로 지정할 필요가 없는 경우가 많습니다. 다만

KevinFire2030 commented 1 year ago

7.2.2 SQLite DB에서 테이블 로드하기

df2 = pd.read_sql("SELECT * FROM test", con, index_col=None)

df2
   index  col0  col1  col2
0      0     1    10   100
1      1     2    20   200
2      2     3    30   300
3      3     4    40   400

df = pd.read_sql("SELECT * FROM test", con, index_col='index')

       col0  col1  col2
index                  
0         1    10   100
1         2    20   200
2         3    30   300
3         4    40   400
KevinFire2030 commented 1 year ago

7.2.3 Pandas를 이용한 주가 데이터 저장


import pandas as pd
import pandas_datareader.data as web
import sqlite3

df = web.DataReader('005930', 'naver', '2023-01-01', '2023-06-09')

con = sqlite3.connect("kospi.db")
df.to_sql('005930', con, if_exists='replace')

readed_df = pd.read_sql("SELECT * FROM '005930'", con, index_col = 'Date')
print(readed_df)
KevinFire2030 commented 1 year ago

7.3 증권사 API를 이용한 주가 데이터 저장

KevinFire2030 commented 1 year ago

7.3.1 종목 코드 리스트 얻어 오기

image

미국 image

image

import sys
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtCore import *

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

    def _create_kiwoom_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")

    def comm_connect(self):
        self.dynamicCall("CommConnect()")
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec_()

    def _set_signal_slots(self):
        self.OnEventConnect.connect(self._event_connect)

    def get_code_list_by_market(self, market):
        code_list = self.dynamicCall("GetCodeListByMarket(QString)", market)
        code_list = code_list.split(';')
        return code_list[:-1]

    def _event_connect(self, err_code):
        if err_code == 0:
            print("connected")
        else:
            print("disconnected")

        self.login_event_loop.exit()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    kiwoom = Kiwoom()
    kiwoom.comm_connect()
    code_list = kiwoom.get_code_list_by_market('10')
    for code in code_list:
        print(code, end=" ")
class Kiwoom(QAxWidget):
    def __init__(self):
        super().__init__()
        self._create_kiwoom_instance()

    def _create_kiwoom_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")

image

KevinFire2030 commented 1 year ago

7.3.2 일봉 데이터 연속 조회

image


import sys
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtCore import *
import time

TR_REQ_TIME_INTERVAL = 0.2

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

    def _create_kiwoom_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")

    def _set_signal_slots(self):
        self.OnEventConnect.connect(self._event_connect)
        self.OnReceiveTrData.connect(self._receive_tr_data)

    def comm_connect(self):
        self.dynamicCall("CommConnect()")
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec_()

    def _event_connect(self, err_code):
        if err_code == 0:
            print("connected")
        else:
            print("disconnected")

        self.login_event_loop.exit()

    def get_code_list_by_market(self, market):
        code_list = self.dynamicCall("GetCodeListByMarket(QString)", market)
        code_list = code_list.split(';')
        return code_list[:-1]

    def get_master_code_name(self, code):
        code_name = self.dynamicCall("GetMasterCodeName(QString)", code)
        return code_name

    def set_input_value(self, id, value):
        self.dynamicCall("SetInputValue(QString, QString)", id, value)

    def comm_rq_data(self, rqname, trcode, next, screen_no):
        self.dynamicCall("CommRqData(QString, QString, int, QString", rqname, trcode, next, screen_no)
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    def _comm_get_data(self, code, real_type, field_name, index, item_name):
        ret = self.dynamicCall("CommGetData(QString, QString, QString, int, QString", code,
                               real_type, field_name, index, item_name)
        return ret.strip()

    def _get_repeat_cnt(self, trcode, rqname):
        ret = self.dynamicCall("GetRepeatCnt(QString, QString)", trcode, rqname)
        return ret

    def _receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
        if next == '2':
            self.remained_data = True
        else:
            self.remained_data = False

        if rqname == "opt10081_req":
            self._opt10081(rqname, trcode)

        try:
            self.tr_event_loop.exit()
        except AttributeError:
            pass

    def _opt10081(self, rqname, trcode):
        data_cnt = self._get_repeat_cnt(trcode, rqname)

        for i in range(data_cnt):
            date = self._comm_get_data(trcode, "", rqname, i, "일자")
            open = self._comm_get_data(trcode, "", rqname, i, "시가")
            high = self._comm_get_data(trcode, "", rqname, i, "고가")
            low = self._comm_get_data(trcode, "", rqname, i, "저가")
            close = self._comm_get_data(trcode, "", rqname, i, "현재가")
            volume = self._comm_get_data(trcode, "", rqname, i, "거래량")
            print(date, open, high, low, close, volume)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    kiwoom = Kiwoom()
    kiwoom.comm_connect()

    # opt10081 TR 요청
    kiwoom.set_input_value("종목코드", "039490")
    kiwoom.set_input_value("기준일자", "20170224")
    kiwoom.set_input_value("수정주가구분", 1)
    kiwoom.comm_rq_data("opt10081_req", "opt10081", 0, "0101")

    while kiwoom.remained_data == True:
        time.sleep(TR_REQ_TIME_INTERVAL)
        kiwoom.set_input_value("종목코드", "039490")
        kiwoom.set_input_value("기준일자", "20170224")
        kiwoom.set_input_value("수정주가구분", 1)
        kiwoom.comm_rq_data("opt10081_req", "opt10081", 2, "0101")
connected
**600**
20170224 76900 77900 76000 76300 57565
20170223 78100 78100 76000 77000 60117
20170222 76600 78100 76300 77300 49600
20170221 73500 76900 73300 76500 46682
20170220 74600 75000 73600 73800 30275
20170217 74600 75900 73900 75600 30195
20170216 72100 75900 72100 75800 67704
20170215 71700 73600 71400 71800 72560
...

20040503 4774 4987 4683 4683 144569
20040430 4911 5200 4911 4949 107002
20040429 5117 5436 5025 5101 109911
20040428 5071 5452 4995 5444 182604
20040427 5452 5482 5033 5063 299489
20040426 5436 5741 5261 5398 343283
20040423 6076 6799 5353 5353 1415109
def comm_rq_data(self, rqname, trcode, next, screen_no):
    self.dynamicCall("CommRqData(QString, QString, int, QString", rqname, trcode, next, screen_no)
    self.tr_event_loop = QEventLoop()
    self.tr_event_loop.exec_()