YOGYUI

MySQL - 2021 국내주식 공모주(IPO) 데이터베이스 만들기 (1) 본문

Software/SQL

MySQL - 2021 국내주식 공모주(IPO) 데이터베이스 만들기 (1)

요겨 2021. 9. 13. 14:30
반응형

작년 SK바이오팜을 시작으로 미래에셋증권에서 진행하는 공모주 청약에 대부분 참여하고 있다

상반기에는 거의 대부분 익절할 수 있었는데 하반기 종목들은 시퍼렇게 질린채 회복하지를 못하고 있다 ㅠ

 

분석기사나 유튜브를 보면 청약경쟁률, 기관의무보유확약비율 등 몇몇 지표에 따라 희비가 엇갈렸다고 하는데, 다른 사람이 분석한 것만 쳐다보면 재미가 없으니깐 직접 DB를 구축하고 레코드를 입력해서 직접 분석(R이나 Python을 써서)을 해보려 한다


우선 DB부터 구축해보자

DBMS는 개인 NAS(ipTime 제품)에 탑재해 둔 MySQL을 활용하기로 했다 (요즘은 시놀로지 NAS에 설치해둔 몽고DB를 주로 사용하는지라 SQL은 진짜 오랜만이라 차근차근 정리할 겸 ㅎㅎ)

 

대부분 작업은 커맨드 라인 툴 (MariaDB 설치하면 제공되는 MySQL Client 사용!)로 진행했다

1. DB 접속

mysql --host=my.sql.server --port=3306 --user=yogyui --password=12345678

주로 사용되는 argument들은 다음과 같다 (https://dev.mysql.com/doc/refman/8.0/en/connecting.html)

  • --host: host 이름/주소 (default: localhost)
  • --port: 포트번호 (default: 3306)
  • --user, --password: DB 접속 계정 정보

1.1 MySQL 서버 버전 확인

(http://jinolog.com/programming/mysql/2011/03/21/mysql-version-check.html)

1.1.1. SELECT VERSION 쿼리

MySQL [(none)]> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.6.17    |
+-----------+
1 row in set (0.003 sec)

1.1.2. SHOW VARIABLE 쿼리

MySQL [(none)]> SHOW VARIABLES LIKE '%VERSION%';
+-------------------------+---------------------+
| Variable_name           | Value               |
+-------------------------+---------------------+
| innodb_version          | 5.6.17              |
| protocol_version        | 10                  |
| slave_type_conversions  |                     |
| version                 | 5.6.17              |
| version_comment         | Source distribution |
| version_compile_machine | x86_64              |
| version_compile_os      | Linux               |
+-------------------------+---------------------+
7 rows in set (0.012 sec)

5.6.17이라니.. 더럽게 옛날 버전이구만? (무려 2014년 3월 27일 릴리즈)

글을 쓰고 있는 2021년 9월 13일 기준 최신 릴리즈 버전은 8.0.26 (2021.07.20 릴리즈)

사용하는데 별 무리는 없겠지 ㅎㅎ

2. 데이터베이스 생성

DDL중 하나인 CREATE DATABASE 쿼리로 DB를 만들자 (DB 이름은 간단하게 'STOCK'으로 결정)

(https://dev.mysql.com/doc/refman/5.6/en/create-database.html)

MySQL [(none)]> CREATE DATABASE IF NOT EXISTS STOCK;
Query OK, 1 row affected (0.021 sec)

제대로 생성되었는지 SHOW DATABASES 쿼리로 확인해보자

MySQL [(none)]> SHOW DATABASES;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| _eaccelerator         |
| _logs                 |
| _session              |
| _tmp                  |
| mysql                 |
| performance_schema    |
| #mysql50#php.d        |
| stock                 |
+-----------------------+
9 rows in set (0.001 sec)

DB의 문자집합 및 데이터 정렬방식 정보를 쿼리해보자

(SELECT FROM information_schema 쿼리)

MySQL [(none)]> SELECT default_character_set_name, default_collation_name FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'STOCK';
+----------------------------+------------------------+
| default_character_set_name | default_collation_name |
+----------------------------+------------------------+
| utf8                       | utf8_general_ci        |
+----------------------------+------------------------+
1 row in set (0.005 sec)

서버의 default값인 utf8, utf8_general_ci로 설정되었다 

utf8은 MySQL이나 MariaDB에서는 3바이트 문자열로 처리하기 때문에 간혹 운용상의 문제가 발생하게 되는데 (이모지 데이터를 추가하는 등등), 이 때는 4바이트 문자열인 utf8mb4로 바꿔주면 된다

 

역시 DDL중 하나인 ALTER DATABASE 쿼리로 변경해주자 (CHARACTER SET 과 COLLATE 변경)

MySQL [(none)]> ALTER DATABASE STOCK CHARACTER SET = 'utf8mb4' COLLATE = 'utf8mb4_general_ci';
Query OK, 1 row affected (0.001 sec)

다시 DB 정보를 가져와보면

MySQL [(none)]> SELECT default_character_set_name, default_collation_name FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'STOCK';
+----------------------------+------------------------+
| default_character_set_name | default_collation_name |
+----------------------------+------------------------+
| utf8mb4                    | utf8mb4_general_ci     |
+----------------------------+------------------------+

정상적으로 변경된 것을 알 수 있다

 

3. 테이블 생성

2021년 국내주식 신규상장 종목들의 데이터를 담을 테이블을 STOCK 데이터베이스에 하나 추가해주자

3.1. ER Design

테이블명은 간단하게 IPO2021로 설정

일단은 간단하게 종목 이름과 (주가 정보 가져오기 위한) 종목 고유코드 두 개 속성만 갖게 ER 디자인을 한 뒤, 종목코드는 종목별로 유일하므로 기본키(Primary Key)로 설정하도록 한다

(추후 필요한 속성들을 계속 추가해나가도록 한다)

3.2. Create Table

앞서 만들어둔 데이터베이스로 진입하자 (USE문 사용)

MySQL [(none)]> USE STOCK
Database changed
MySQL [STOCK]>

CREATE TABLE 쿼리를 사용해서 설계대로 만들어주자

종목코드는 6자리의 숫자(ex: 삼성전자 보통주 = 005930)이므로 길이 6의 VARCHAR로, 이름은 넉넉하게 길이 32의 VARCHAR로 자료형을 정해줬다

MySQL [STOCK]> CREATE TABLE IF NOT EXISTS `IPO2021` (
    ->     `종목코드` varchar(6) NOT NULL,
    ->     `이름` varchar(32) NOT NULL,
    ->     PRIMARY KEY (`종목코드`)
    -> );
Query OK, 0 rows affected (0.161 sec)

DESC 쿼리로 테이블 필드 정보를 가져와보자

MySQL [STOCK]> DESC IPO2021;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| 종목코드 | varchar(6)  | NO   | PRI | NULL    |       |
| 이름     | varchar(32) | NO   |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.017 sec)

3.3. Fill Records

2021년 신규상장종목 리스트는 38 커뮤니케이션의 신규 상장 메뉴에서 확인할 수 있다(링크)

 

그리고 종목코드 정보는는 한국거래소(KRX) 정보데이터 시스템 통계(링크)에서 찾을 수 있다

 

DML의 INSERT 문을 사용해서 레코드를 삽입하는 쿼리를 작성해 추가할 수 있다

* 스팩은 DB에서 제외하기로 한다, 별다른 이유는 없음 ㅎㅎ

MySQL [STOCK]> INSERT INTO `IPO2021`(`종목코드`, `이름`) VALUES ('236810', '엔비티');
Query OK, 1 row affected (0.013 sec)

SELECT 문으로 전체 레코드를 쿼리해보자

MySQL [STOCK]> SELECT * FROM IPO2021;
+----------+--------+
| 종목코드 | 이름   |
+----------+--------+
| 236810   | 엔비티 |
+----------+--------+
1 row in set (0.001 sec)

제대로 레코드가 삽입되었다

 

그런데 모든 신규상장종목에 대해 이런 노가다를 할 순 없으니 레코드 삽입 자동화 코드를 파이썬으로 작성해보자

3.3.1. 신규상장종목 리스트업

38 커뮤니케이션 사이트에서 신규상장종목 특정 페이지의 기업 리스트를 가져오는 함수를 구현했다

import requests
from datetime import datetime
from bs4 import BeautifulSoup
from collections import OrderedDict

def getIPOElements(page_no):
    url = 'https://www.38.co.kr/html/fund/index.htm?o=nw&page={}'.format(page_no)
    
    # URL로부터 신규상장종목 리스트가 들어있는 table 태그를 가져온다 
    # (summary 속성이 신규상장종목인 태그)
    html = requests.get(url.format(page_no)).text
    soup = BeautifulSoup(html, 'html.parser')
    tables = soup('table')
    table_ipo_list = list(filter(lambda x: x.attrs.get('summary') == '신규상장종목', tables))[0]
    
    # 테이블 헤더 태그(thead)를 읽는다
    head = table_ipo_list('thead')[0]
    th = head('tr')[0]('th')
    column_headers = [x.text for x in th]
    
    # 테이블 본체 (tbody)를 읽어서 리스트에 딕셔너리 형태로 저장한
    result = []
    tbody = table_ipo_list('tbody')[0]
    rows = tbody('tr')
    for row in rows:
        td = row('td')
        info = OrderedDict()
        for i, e in enumerate(td):
            header_text = column_headers[i]
            if len(header_text) == 0:
                continue
            temp = e.text.replace('\xa0', '')
            temp = temp.replace('%', '')
            if header_text in ['공모가(원)', '시초가(원)', '첫날종가(원)', '현재가(원)']:
                if temp in ['-', '예정', '상장']:
                    info[header_text] = ''  # Nan
                else:
                    info[header_text] = int(temp.replace(',', ''))
            elif header_text in ['공모가대비등락률(%)', '시초/공모(%)', '전일비(%)']:
                if temp in ['-'] or len(temp) == 0:
                    info[header_text] = ''  # Nan
                else:
                    info[header_text] = float(temp)
            elif header_text in ['신규상장일']:
                info[header_text] = datetime.strptime(e.text, '%Y/%m/%d')
            elif header_text in ['기업명']:
                info[header_text] = temp.replace('(유가)', '')
            else:
                info[header_text] = e.text
        result.append(info)
    
    return result

귀찮으니 구현 과정은 생략!

첫번째 페이지를 테스트해보자

In [1]: res = getIPOElements(1)

In [2]: len(res)
Out[2]: 20

In [3]: res[10]
Out[3]: 
OrderedDict([('기업명', '와이엠텍'),
             ('신규상장일', datetime.datetime(2021, 9, 10, 0, 0)),
             ('현재가(원)', 48950),
             ('전일비(%)', -17.03),
             ('공모가(원)', 28000),
             ('공모가대비등락률(%)', 74.82),
             ('시초가(원)', 56000),
             ('시초/공모(%)', 100.0),
             ('첫날종가(원)', 59000)])

제대로 된 결과를 얻을 수 있다

 

이제 전체 페이지를 순차적으로 루프를 돌며 크롤링하되, 신규상장일이 2021년이 아닌 항목이 나오는 경우 루프를 멈추도록 구현해보자 (기업명에 '스팩'이 들어가는 레코드도 제외)

결과는 pandas 데이터프레임으로 반환하자

import pandas as pd

def getIPOAllList(year: int) -> pd.DataFrame:
    result = list()
    page_no = 1
    
    while True:
        page_result = getIPOElements(page_no)
        result.extend(page_result)
        
        dates = [x.get('신규상장일') for x in page_result]
        find = list(filter(lambda x: x.year < year, dates))
        if len(find) > 0:
            break
        page_no += 1
    
    result = list(filter(lambda x: x.get('신규상장일').year >= year and '스팩' not in x.get('기업명'), result))
    return pd.DataFrame(result)

테스트해보자

In [4]: res = getIPOAllList(2021)

In [5]: len(res)
Out[5]: 68

In [6]: res.tail(5)
Out[6]: 
         기업명      신규상장일 현재가(원) 전일비(%)  ... 공모가대비등락률(%) 시초가(원) 시초/공모(%) 첫날종가(원)
63        핑거 2021-01-29  18600  -2.11  ...       16.25  32000      100   29100
64    씨앤투스성진 2021-01-28  20650  -0.96  ...      -35.47  31700    -0.94   28700
65      모비릭스 2021-01-28  20800  -0.95  ...       48.57  28000      100   36400
66  선진뷰티사이언스 2021-01-27  17950  -2.97  ...       56.09  23000      100   29900
67       엔비티 2021-01-21  20100  -2.43  ...        5.79  38000      100   36500

[5 rows x 9 columns]

In [7]: res.head(5)
Out[7]:
        기업명      신규상장일 현재가(원) 전일비(%) 공모가(원) 공모가대비등락률(%) 시초가(원) 시초/공모(%) 첫날종가(원)
0  아이패밀리에스씨 2021-10-28                                                         
1     카카오페이 2021-10-14                                                         
2      에스앤디 2021-09-29                28000                                    
3      실리콘투 2021-09-29                27200                                    
4    바이오플러스 2021-09-27  51500   0.49  31500       63.49

글을 쓰고 있는 9월 13일 기준, 1월 21 상장된 엔비티를 필두로 10월 28일 상장 예정인 아이패밀리에스씨까지 총 68개 기업 레코드를 크롤링할 수 있다 (카카오페이는 빠꾸먹었다고 하던데 ㅎㅎ)

In [8]: res['기업명']
Out[8]:
0        아이패밀리에스씨
1           카카오페이
2            에스앤디
3            실리콘투
4          바이오플러스
5           현대중공업
6            SK리츠
7            와이엠텍
8            에이비온
9         일진하이솔루스
10       디앤디플랫폼리츠
11           바이젠셀
12           아주스틸
13        브레인즈컴퍼니
14           롯데렌탈
15           딥노이드
16        한컴라이프케어
17             엠로
18           플래티어
19           원티드랩
20           크래프톤
21       에이치케이이노엔
22          카카오뱅크
23           에브리봇
24            맥스트
25            큐라클
26       에스디바이오센서
27            오비고
28           아모센스
29            이노뎁
    ...
38          에이치피오
39     SK아이이테크놀로지
40             쿠콘
41          해성티피씨
42        이삭엔지니어링
43            엔시스
44         자이언트스텝
45            제노코
46        라이프시맨틱스
47      SK바이오사이언스
48          바이오다인
49          네오이뮨텍
50    프레스티지바이오로직스
51           싸이버원
52         나노씨엠에스
53             뷰노
54         유일에너테크
55            씨이랩
56       오로스테크놀로지
57        피엔에이치테크
58     프레스티지바이오파마
59          아이퀘스트
60         와이더플래닛
61       레인보우로보틱스
62            솔루엠
63             핑거
64         씨앤투스성진
65           모비릭스
66       선진뷰티사이언스
67            엔비티
Name: 기업명, Length: 68, dtype: object

아따...많이도 했다 ㅋㅋㅋ (스팩까지 합치면 100개...)

3.3.2. 신규상장종목 코드 매칭

KRX 통계 페이지의 테이블은 JS로 작성되어 있어서 스크롤이 변할 때마다 항목이 refresh되는 방식이라 간단한 크롤링 구현이 어렵다

그래서!!!

약간의 HTML 디버깅 끝에 다운로드 POST를 특정 주소로 보내주면 전체 데이터를 CSV 형식으로 저장할 수 있는 방법을 찾아냈다 ㅎㅎ (일회성 토큰방식인지 여부를 모르겠다;)

def getKrxStockCsvFile() -> pd.DataFrame:
    target_path = os.path.abspath('./temp.csv')
    url = 'http://data.krx.co.kr/comm/fileDn/download_csv/download.cmd'
    value = 'yewA9Y8Xg/ZThGWI2oS0KV8Kgcd6eycE9T7vnQnRAcgRtSksuLS7Bnxpl86F7dAOvXfGx9S2U5wgvoxsacATRRtmGtORI4WrGDmruVe6oXtCqUypoW0Lp6SAPP0PhVkgThCTcjIZNPI5lCTubZnhjio6AHXdxc45YVEhz4JdugHPMxvIwHadpQpCGE1HxZAXvTCprTIXuXT9XxFb88awpQ=='
    
    result = requests.post(url, data={'code': value})
    with open(target_path, 'wb') as fp:
        fp.write(result.content)
    
    df = pd.read_csv(target_path, encoding='cp949')
    os.remove(target_path)  # 데이터프레임 생성 후 원본파일은 삭제
    
    return df

한글이 포함되어서 그런지 utf-8으로는 디코딩 에러가 발생하니 인코딩은 cp949로 설정했다

 

테스트해보자

In [9]: df = getKrxStockCsvFile()

In [10]: len(df)
Out[10]: 2580

In [11]: df.columns 
Out[11]:
Index(['표준코드', '단축코드', '한글 종목명', '한글 종목약명', '영문 종목명', '상장일', '시장구분', '증권구분',
       '소속부', '주식종류', '액면가', '상장주식수'],
      dtype='object')

In [12]: df.head(5)
Out[12]: 
           표준코드    단축코드        한글 종목명  ... 주식종류   액면가     상장주식수
0  KR7098120009  098120  (주)마이크로컨텍솔루션  ...  보통주   500   8312766
1  KR7131100000  131100     (주)스카이이앤엠  ...  보통주   100  41281205
2  KR7009520008  009520      (주)포스코엠텍  ...  보통주   500  41642703
3  KR7095570008  095570     AJ네트웍스보통주  ...  보통주  1000  46822295
4  KR7006840003  006840      AK홀딩스보통주  ...  보통주  5000  13247561

[5 rows x 12 columns]

In [13]: df[df['한글 종목명'].str.contains('삼성전자')]
Out[13]: 
             표준코드    단축코드    한글 종목명 한글 종목약명  ...  소속부   주식종류  액면가       상장주식수
827  KR7005931001  005935  삼성전자1우선주   삼성전자우  ...  NaN  구형우선주  100   822886700
828  KR7005930003  005930   삼성전자보통주    삼성전자  ...  NaN    보통주  100  5969782550

[2 rows x 12 columns]

앞서 언급했던 6자리의 단축코드뿐만 아니라 표준코드, 상장일, 코스피/코스닥/코넥스 시장구분, 주식종류, 액면가, 상장주식수 등 다양한 정보를 한번에 얻을 수 있다 (최초 CSV파일은 한글종목명 기준으로 정렬되어 있다)

KRX 통계상 국내주식시장 전체 상장된 종목 수는 2021년 9월 13일 기준 2580개 (생각보다 많진 않네? 상장폐지된 종목들은 집계해주지 않아서 그렇겠지?)

 

만약 위 코드로 영구적으로 자동 데이터 획득이 된다면 자료가 변경될 때마다 매번 파일을 새로 다운받고 여는 동작을 자동화할 수 있으므로 상당히 편리하게 사용할 수 있을 것 같다

 

3.3.3. DB 테이블 레코드 자동 삽입

신규상장된 기업의 이름과 코드를 크롤링했으니, 이제 테이블에 레코드를 자동으로 삽입해주는 코드를 만들어보자

 

삽입하기 전에, IPO2021 테이블에 상장일과 상장주식수 및 공모가 속성도 추가해주자

ALTER TABLE ADD COLUMN 쿼리

MySQL [STOCK]> ALTER TABLE IPO2021 ADD COLUMN `상장일` DATE;
Query OK, 0 rows affected (0.183 sec)
Records: 0  Duplicates: 0  Warnings: 0

MySQL [STOCK]> ALTER TABLE IPO2021 ADD COLUMN `상장주식수` INT;
Query OK, 0 rows affected (0.305 sec)
Records: 0  Duplicates: 0  Warnings: 0

MySQL [STOCK]> ALTER TABLE IPO2021 ADD COLUMN `공모가` INT AFTER `상장일`;
Query OK, 0 rows affected (0.377 sec)
Records: 0  Duplicates: 0  Warnings: 0

MySQL [STOCK]> DESC IPO2021;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| 종목코드   | varchar(6)  | NO   | PRI | NULL    |       |
| 이름       | varchar(32) | NO   |     | NULL    |       |
| 상장일     | date        | YES  |     | NULL    |       |
| 공모가     | int(11)     | YES  |     | NULL    |       |
| 상장주식수 | int(11)     | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
5 rows in set (0.026 sec)

파이썬에서의 mysql은 pymysql 패키지를 활용한다

https://github.com/PyMySQL/PyMySQL

 

GitHub - PyMySQL/PyMySQL: Pure Python MySQL Client

Pure Python MySQL Client. Contribute to PyMySQL/PyMySQL development by creating an account on GitHub.

github.com

import pymysql
from datetime import datetime

def updateIPODatabase():
    db_conn = pymysql.connect(host='my.sql.server', port=3306, user='yogyui', passwd='password', db='STOCK')
    cursor = db_conn.cursor()
    # 테이블 SELECT 쿼리로 저장되어 있는 레코드들 불러오기
    cursor.execute('SELECT * FROM IPO2021;')
    result = cursor.fetchall()
    # 저장되어있는 코드들만 따로 추출
    codes = [x[0] for x in result]
    
    # 2021년 신규상장 종목 리스트업 (스팩 제외)
    df_new = getIPOAllList(2021)
    # 오늘 이후의 데이터 (상장예정)는 제거
    now = datetime.now()
    df_new = df_new[df_new['신규상장일'] < now]
    # 상장일 기준으로 오름차순 정렬
    df_new = df_new.sort_values(by=['신규상장일'], ascending=True)
    
    # KRX 상장종목 데이터 가져오기
    df_all = getKrxStockCsvFile()
    
    # 모든 신규상장종목에 대해 루프
    for i in range(len(df_new)):
        dr = df_new.iloc[i]
        name = dr['기업명']
        date = dr['신규상장일']
        value1 = dr['공모가(원)']
        # 단축코드 가져오기
        if name == '에이치케이이노엔':
            find = df_all[df_all['한글 종목약명'] == 'HK이노엔'].iloc[0]
        else:
            find = df_all[df_all['한글 종목약명'].str.contains(name)].iloc[0]
        code = find['단축코드']
        value2 = find['상장주식수']
        
        # 종목코드가 이미 저장되었는지 여부에 따라 쿼리 분기
        if code in codes:
            sql = "UPDATE IPO2021 SET "
            sql += "`이름` = '{}',".format(name)
            sql += "`상장일` = '{}',".format(date.strftime('%Y-%m-%d'))
            sql += "`공모가` = '{}',".format(value1)
            sql += "`상장주식수` = '{}',".format(value2)
            sql = sql[:-1] + " WHERE `종목코드` = '{}';".format(code)
        else:
            sql = "INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ("
            sql += "'{}',".format(code)
            sql += "'{}',".format(name)
            sql += "'{}',".format(date.strftime('%Y-%m-%d'))
            sql += "'{}',".format(value1)
            sql += "'{}',".format(value2)
            sql = sql[:-1] + ");"
        result = cursor.execute(sql)
        print('({}) {}'.format(result, sql))
    
    db_conn.commit()
    db_conn.close()

에이치케이이노엔은 종목약명이 HK이노엔으로 기재되어 있는 등 약간의 예외사항이 있지만 쉽게 구현할 수 있다

 

바로 테스트해보자

In [14]: updateIPODatabase()
(1) UPDATE IPO2021 SET `이름` = '엔비티',`상장일` = '2021-01-21',`공모가` = '19000',`상장주식수` = '8487713' WHERE `종목코드` = '236810';
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('086710','선진뷰티사이언스','2021-01-27','11500','6115650');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('352700','씨앤투스성진','2021-01-28','32000','9995531');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('348030','모비릭스','2021-01-28','14000','9304000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('163730','핑거','2021-01-29','16000','9239014');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('248070','솔루엠','2021-02-02','17000','50005551');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('277810','레인보우로보틱스','2021-02-03','10000','16135214');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('321820','와이더플래닛','2021-02-03','16000','6897482');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('262840','아이퀘스트','2021-02-05','11000','9860000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('950210','프레스티지바이오파마','2021-02-05','32000','60096155');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('239890','피엔에이치테크','2021-02-16','18000','4516016');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('322310','오로스테크놀로지','2021-02-24','21000','9309542');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('189330','씨이랩','2021-02-24','35000','3013642');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('340930','유일에너테크','2021-02-25','16000','10590044');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('338220','뷰노','2021-02-26','21000','11168656');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('247660','나노씨엠에스','2021-03-09','20000','4208920');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('334970','프레스티지바이오로직스','2021-03-11','12400','47206389');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('356890','싸이버원','2021-03-11','9500','4640830');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('950220','네오이뮨텍','2021-03-16','7500','98417010');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('314930','바이오다인','2021-03-17','30000','6168195');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('302440','SK바이오사이언스','2021-03-18','65000','76500000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('347700','라이프시맨틱스','2021-03-23','12500','10119770');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('361390','제노코','2021-03-24','36000','2442140');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('289220','자이언트스텝','2021-03-24','11000','9655765');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('333620','엔시스','2021-04-01','19000','10556344');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('351330','이삭엔지니어링','2021-04-21','11500','8288520');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('059270','해성티피씨','2021-04-21','13000','4630000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('294570','쿠콘','2021-04-28','45000','8077071');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('361610','SK아이이테크놀로지','2021-05-11','105000','71297592');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('357230','에이치피오','2021-05-14','22200','19938160');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('352480','씨앤씨인터내셔널','2021-05-17','47500','6675961');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('252990','샘씨엔에스','2021-05-20','6500','50153846');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('361670','삼영에스앤씨','2021-05-21','11000','5557158');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('178320','진시스템','2021-05-26','20000','18790321');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('276730','제주맥주','2021-05-26','3200','56485461');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('187660','에이디엠코리아','2021-06-03','3800','21836250');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('376190','엘비루셈','2021-06-11','14000','24600000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('232680','라온테크','2021-06-17','18000','4886005');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('303530','이노뎁','2021-06-18','18000','7143151');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('357580','아모센스','2021-06-25','12400','11200076');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('352910','오비고','2021-07-13','14300','11350834');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('137310','에스디바이오센서','2021-07-16','52000','103271353');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('365270','큐라클','2021-07-22','25000','13355968');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('377030','맥스트','2021-07-27','15000','8533491');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('270660','에브리봇','2021-07-28','36700','6095671');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('323410','카카오뱅크','2021-08-06','39000','475100237');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('195940','에이치케이이노엔','2021-08-09','59000','28904499');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('259960','크래프톤','2021-08-10','498000','48951445');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('376980','원티드랩','2021-08-11','35000','4703068');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('367000','플래티어','2021-08-12','11000','8269707');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('058970','엠로','2021-08-13','22600','5426060');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('372910','한컴라이프케어','2021-08-17','13700','27674406');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('315640','딥노이드','2021-08-17','42000','4290997');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('089860','롯데렌탈','2021-08-19','59000','36634063');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('099390','브레인즈컴퍼니','2021-08-19','25000','4108796');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('139990','아주스틸','2021-08-20','15100','26452189');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('308080','바이젠셀','2021-08-25','52700','9432400');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('377190','디앤디플랫폼리츠','2021-08-27','5000','64400000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('271940','일진하이솔루스','2021-09-01','34300','36313190');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('203400','에이비온','2021-09-08','17000','15249795');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('273640','와이엠텍','2021-09-10','28000','5393000');
(1) INSERT INTO IPO2021 (`종목코드`, `이름`, `상장일`, `공모가`, `상장주식수`) VALUES ('395400','SK리츠','2021-09-14','5000','155020532');

이미 등록해둔 엔비티 레코드는 UPDATE 쿼리가, 나머지 종목들은 INSERT 쿼리가 제대로 수행된 것 (execute 결과가 1 = 영향을 받은 레코드가 1개)을 알 수 있다

 

커밋까지 했으니 MySQL 커맨드라인에서 테이블을 조회해보자

(ORDER BY절 사용해서 상장일 기준 내림차순 정렬)

MySQL [STOCK]> SELECT * FROM IPO2021 ORDER BY `상장일` DESC;
+----------+------------------------+------------+--------+------------+
| 종목코드 | 이름                   | 상장일     | 공모가 | 상장주식수 |
+----------+------------------------+------------+--------+------------+
| 395400   | SK리츠                 | 2021-09-14 |   5000 |  155020532 |
| 273640   | 와이엠텍               | 2021-09-10 |  28000 |    5393000 |
| 203400   | 에이비온               | 2021-09-08 |  17000 |   15249795 |
| 271940   | 일진하이솔루스         | 2021-09-01 |  34300 |   36313190 |
| 377190   | 디앤디플랫폼리츠       | 2021-08-27 |   5000 |   64400000 |
| 308080   | 바이젠셀               | 2021-08-25 |  52700 |    9432400 |
| 139990   | 아주스틸               | 2021-08-20 |  15100 |   26452189 |
| 089860   | 롯데렌탈               | 2021-08-19 |  59000 |   36634063 |
| 099390   | 브레인즈컴퍼니         | 2021-08-19 |  25000 |    4108796 |
| 372910   | 한컴라이프케어         | 2021-08-17 |  13700 |   27674406 |
| 315640   | 딥노이드               | 2021-08-17 |  42000 |    4290997 |
| 058970   | 엠로                   | 2021-08-13 |  22600 |    5426060 |
| 367000   | 플래티어               | 2021-08-12 |  11000 |    8269707 |
| 376980   | 원티드랩               | 2021-08-11 |  35000 |    4703068 |
| 259960   | 크래프톤               | 2021-08-10 | 498000 |   48951445 |
| 195940   | 에이치케이이노엔       | 2021-08-09 |  59000 |   28904499 |
| 323410   | 카카오뱅크             | 2021-08-06 |  39000 |  475100237 |
| 270660   | 에브리봇               | 2021-07-28 |  36700 |    6095671 |
| 377030   | 맥스트                 | 2021-07-27 |  15000 |    8533491 |
| 365270   | 큐라클                 | 2021-07-22 |  25000 |   13355968 |
| 137310   | 에스디바이오센서       | 2021-07-16 |  52000 |  103271353 |
| 352910   | 오비고                 | 2021-07-13 |  14300 |   11350834 |
| 357580   | 아모센스               | 2021-06-25 |  12400 |   11200076 |
| 303530   | 이노뎁                 | 2021-06-18 |  18000 |    7143151 |
| 232680   | 라온테크               | 2021-06-17 |  18000 |    4886005 |
| 376190   | 엘비루셈               | 2021-06-11 |  14000 |   24600000 |
| 187660   | 에이디엠코리아         | 2021-06-03 |   3800 |   21836250 |
| 178320   | 진시스템               | 2021-05-26 |  20000 |   18790321 |
| 276730   | 제주맥주               | 2021-05-26 |   3200 |   56485461 |
| 361670   | 삼영에스앤씨           | 2021-05-21 |  11000 |    5557158 |
| 252990   | 샘씨엔에스             | 2021-05-20 |   6500 |   50153846 |
| 352480   | 씨앤씨인터내셔널       | 2021-05-17 |  47500 |    6675961 |
| 357230   | 에이치피오             | 2021-05-14 |  22200 |   19938160 |
| 361610   | SK아이이테크놀로지     | 2021-05-11 | 105000 |   71297592 |
| 294570   | 쿠콘                   | 2021-04-28 |  45000 |    8077071 |
| 059270   | 해성티피씨             | 2021-04-21 |  13000 |    4630000 |
| 351330   | 이삭엔지니어링         | 2021-04-21 |  11500 |    8288520 |
| 333620   | 엔시스                 | 2021-04-01 |  19000 |   10556344 |
| 289220   | 자이언트스텝           | 2021-03-24 |  11000 |    9655765 |
| 361390   | 제노코                 | 2021-03-24 |  36000 |    2442140 |
| 347700   | 라이프시맨틱스         | 2021-03-23 |  12500 |   10119770 |
| 302440   | SK바이오사이언스       | 2021-03-18 |  65000 |   76500000 |
| 314930   | 바이오다인             | 2021-03-17 |  30000 |    6168195 |
| 950220   | 네오이뮨텍             | 2021-03-16 |   7500 |   98417010 |
| 334970   | 프레스티지바이오로직스 | 2021-03-11 |  12400 |   47206389 |
| 356890   | 싸이버원               | 2021-03-11 |   9500 |    4640830 |
| 247660   | 나노씨엠에스           | 2021-03-09 |  20000 |    4208920 |
| 338220   | 뷰노                   | 2021-02-26 |  21000 |   11168656 |
| 340930   | 유일에너테크           | 2021-02-25 |  16000 |   10590044 |
| 322310   | 오로스테크놀로지       | 2021-02-24 |  21000 |    9309542 |
| 189330   | 씨이랩                 | 2021-02-24 |  35000 |    3013642 |
| 239890   | 피엔에이치테크         | 2021-02-16 |  18000 |    4516016 |
| 950210   | 프레스티지바이오파마   | 2021-02-05 |  32000 |   60096155 |
| 262840   | 아이퀘스트             | 2021-02-05 |  11000 |    9860000 |
| 277810   | 레인보우로보틱스       | 2021-02-03 |  10000 |   16135214 |
| 321820   | 와이더플래닛           | 2021-02-03 |  16000 |    6897482 |
| 248070   | 솔루엠                 | 2021-02-02 |  17000 |   50005551 |
| 163730   | 핑거                   | 2021-01-29 |  16000 |    9239014 |
| 352700   | 씨앤투스성진           | 2021-01-28 |  32000 |    9995531 |
| 348030   | 모비릭스               | 2021-01-28 |  14000 |    9304000 |
| 086710   | 선진뷰티사이언스       | 2021-01-27 |  11500 |    6115650 |
| 236810   | 엔비티                 | 2021-01-21 |  19000 |    8487713 |
+----------+------------------------+------------+--------+------------+
62 rows in set (0.003 sec)

MySQL [STOCK]> SELECT COUNT(*) FROM IPO2021;
+----------+
| COUNT(*) |
+----------+
|       62 |
+----------+
1 row in set (0.007 sec)

스팩을 제외하면 9월 14일 기준 총 62개 기업이 상장된 것 같다 (맞겠지...?)

 

데이터베이스 업데이트 자동화 코드를 구현해두었으니, 개인 서버에서 하루에 한번 스케쥴링해서 계속 refresh해줄 예정 (IPO2021 테이블의 속성 추가/변경 시 자동화 코드도 같이 수정해주면 된다)


글이 너무 길어졌다...

여기서 끊고, 다음 포스트에서는 DART에 등록된 기업별 상장 공시자료에 기재된 여러 지표들을 추가하는 과정을 진행해보자

반응형
Comments