EXCELSIOR

3. 주식 데이터를 PostgreSQL에 저장하기 본문

Python/주식 분석

3. 주식 데이터를 PostgreSQL에 저장하기

Excelsior-JH 2017. 10. 29. 21:21

주식 데이터를 PostgreSQL에 저장하기


이전에 포스팅한 2. 주식 분석 개발환경 설정 - 파이썬 환경 설정 및 실행에서 설정한 주식 분석 환경을 이용해 Open RDBMS인 PostgreSQL에 테이블을 만들어 데이터를 Insert 해보도록 한다. 굳이 RDBMS에 데이터를 저장하는 이유는 매번 주식 분석을 할때마다 증권API를 관리자 권한으로 실행해주고 python 32bit에서 코딩을 해야하는 번거로움을 피하고자 RDBMS을 이용하는 방법을 선택하였다. PostgreSQL 설치 Windows에 PostgreSQL 설치 및 실행를 참고하면 된다.

1. PostgreSQL DB 및 테이블 생성

1) Database 생성

PostgreSQL을 설치한 뒤 pgAdmin 4를 실행한다. pgAdmin 4 화면에서 아래의 그림과 같이 [Create] \rightarrow [Database] \rightarrow StockDB(DB이름은 본인이 원하는 이름으로 하면된다) 를 만든다.


2) 테이블(Table) 생성

데이터베이스(DB)를 생성한 뒤 주식 일자별 데이터를 저장할 daily_stock_price 테이블을 생성한다.

  • 해당 테이블의 CREATE Scripts는 아래와 같다  → 수정: 2017.11.07(화) 테이블 컬럼명 변경
  • CREATE TABLE public.daily_stock_price
    (
        code character varying(20) COLLATE pg_catalog."default" NOT NULL,
        name character varying(100) COLLATE pg_catalog."default" NOT NULL,
        date date NOT NULL,
        open integer NOT NULL,
        high integer NOT NULL,
        low integer NOT NULL,
        close integer NOT NULL,
        diff integer NOT NULL,
        volume bigint NOT NULL,
        CONSTRAINT daily_stock_price_item_code_fkey FOREIGN KEY (code)
            REFERENCES public.stock_item_code (code) MATCH SIMPLE
            ON UPDATE NO ACTION
            ON DELETE NO ACTION
    )
    WITH (
        OIDS = FALSE
    )
    TABLESPACE pg_default;
    ALTER TABLE public.daily_stock_price
        OWNER to postgres;
    COMMENT ON TABLE public.daily_stock_price
        IS '종목/일자별 주가데이터';

2. 주식 일자별 데이터 테이블에 저장하기

Creon Plus 증권API를 이용하여 주식 일자별 데이터를 조회하여 PostgreSQL 테이블에 Insert해보도록 한다. 주식 일자별 데이터 조회 소스코드는 크레온플러스자료실에서 확인할 수 있으며, 여기서는 소스코드를 조금 수정하여 셀트리온  신라젠 종목코드의(본인이 원하는 기업을 선택하면 됨) 일자별 데이터를 테이블에 Insert해 주었다.

1) 관리자 권한으로 Creon Plus 실행

CREON HTS를 반드시 관리자 권한으로 실행 해야한다. 그런 다음, Creon Plus를 선택한 뒤 로그인 한다.


다음과 같은 화면이 나타나면 Creon plus API가 실행 된 것이다.


2) 필요한 모듈(패키지) 설치

파이썬에서 PostgreSQL을 연동해 주기 위해서는 psycopg2 라는 모듈이 필요하다. 먼저 명령프롬프트 관리자 권한으로 실행한 뒤 가상환경을 활성화 후 psycopg2를 설치한다.

  • activate py35_32 \rightarrow 가상환경 py35_32 활성화(activate)
  • pip install psycopg2 \rightarrow psycopg2 설치

3) 관리자 권한으로 Jupyter Notebook 실행

jupyter notebook또한 관리자 권한으로 실행 해줘야 한다. 먼저 아래의 그림처럼 명령프롬프트를 관리자 권한으로 실행한 뒤 다음의 명령어를 입력하여 jupyter notebook을 실행한다.

  • activate py35_32 \rightarrow 가상환경 py35_32 활성화(activate)
  • jupyter notebook \rightarrow jupyter notebook 실행


4) 일자별 데이터 PostgreSQL 테이블에 Insert 하기

i. 주식 일자별 데이터 조회
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import win32com.client # win32com 모듈 import
 
# 연결 여부 체크
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
print(bConnect)
if (bConnect == 0):
    print("PLUS가 정상적으로 연결되지 않음. ")
    exit()
    
# 종목코드 리스트 구하기
objCpCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
codeList = objCpCodeMgr.GetStockListByMarket(1#거래소
codeList2 = objCpCodeMgr.GetStockListByMarket(2#코스닥
 
item_code = {}
 
print("거래소 종목코드"len(codeList))
for i, code in enumerate(codeList[:5]):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    print(i, code, secondCode, stdPrice, name)
 
print("코스닥 종목코드"len(codeList2))
for i, code in enumerate(codeList2):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    if name in ['셀트리온''신라젠']: # -->> 원하는 종목(기업) 이름 입력하면 됨
        item_code[name] = code 
        print(i, code, secondCode, stdPrice, name)
 
# 전체 종목코드 개수        
# print("거래소 + 코스닥 종목코드 ",len(codeList) + len(codeList2))
print(item_code)
 
'''결과
거래소 종목코드 1363
0 A000020 1 9270 동화약품
1 A000030 1 17000 우리은행
2 A000040 1 396 KR모터스
3 A000050 1 13900 경방
4 A000060 1 26300 메리츠화재
코스닥 종목코드 1257
603 A068270 1 178300 셀트리온
1109 A215600 1 60200 신라젠
{'신라젠': 'A215600', '셀트리온': 'A068270'}
'''
# 일자별 데이터 호출 함수
def ReqeustData(obj, name, code):
    # 데이터 요청
    obj.BlockRequest()
 
    # 통신 결과 확인
    rqStatus = obj.GetDibStatus()
    rqRet = obj.GetDibMsg1()
#     print("통신상태", rqStatus, rqRet)
    if rqStatus != 0:
        return False
 
    # 일자별 정보 데이터 처리
    count = obj.GetHeaderValue(1)  # 데이터 개수
    
    temp_data = []
    for i in range(count):
        date = obj.GetDataValue(0, i)  # 일자
        open = obj.GetDataValue(1, i)  # 시가
        high = obj.GetDataValue(2, i)  # 고가
        low = obj.GetDataValue(3, i)  # 저가
        close = obj.GetDataValue(4, i)  # 종가
        diff = obj.GetDataValue(5, i)  
        vol = obj.GetDataValue(6, i)  # 거래량
        
        year = slice(0,4)
        month = slice(4,6)
        day = slice(6,8)
        date = str(date)
        date_time = '{0}-{1}-{2}'.format(date[year], date[month], date[day])
        
#         print(date, open, high, low, close, diff, vol)
        stock_data.append((code, date_time, open, high, low, close, diff, vol, name))
    return temp_data
    
stock_data = []
 
# 일자별 object 구하기
objStockWeek = win32com.client.Dispatch("DsCbo1.StockWeek")
 
for name, code in item_code.items():
    objStockWeek.SetInputValue(0, code)   #종목 코드 - 셀트리온:A068270, 신라젠:A215600
    # 최초 데이터 요청
    ret = ReqeustData(objStockWeek, name, code)
    stock_data += ret
    # 연속 데이터 요청
    # 예제는 5번만 연속 통신 하도록 함.
    NextCount = 1
    while objStockWeek.Continue:  #연속 조회처리
        NextCount+=1;
        if NextCount > 6 :
            break
        ret = ReqeustData(objStockWeek, name, code)
        stock_data += ret
        if ret == False:
            exit()
 
cs
ii. PostgreSQL 테이블에 Insert하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import psycopg2 # postgreSQL 연동 모듈 import
 
# Connect to an existing database
host = 'localhost'
dbname = 'StockDB'
user = 'postgres'
pwd = '계정 비밀번호'
conn = psycopg2.connect('host={0} dbname={1} user={2} password={3}'.format(host, dbname, user, pwd))
cur = conn.cursor()
 
cur.executemany("INSERT INTO daily_stock_price(code, name, date, open, high, low, close, diff, volume) \
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)", stock_data)
conn.commit()
 
cs
iii. PostgreSQL 테이블에서 주식 일자별 데이터 조회하기
1
2
3
4
5
6
7
8
9
10
11
12
cur.execute("SELECT * FROM daily_stock_price WHERE name='셀트리온'")
 
for row in cur.fetchall():
    print(row)
    
'''결과
('A068270', '셀트리온', datetime.date(2017, 10, 27), 174200, 178700, 168200, 175000, 2900, 1977292)
('A068270', '셀트리온', datetime.date(2017, 10, 26), 181900, 182400, 172100, 172100, -8900, 2263821)
('A068270', '셀트리온', datetime.date(2017, 10, 25), 189300, 189400, 180600, 181000, -9900, 2864225)
...
생략
'''
cs

5) pgAdmin 4에서 테이블 조회하기




Comments