[Elasticsearch] Python으로 삼성전자 주식 데이터 저장

    자바(Java)로만 엘라스틱서치(Elastic Search)에 대해서 다뤄봤는데 이번에는 파이썬(Python)으로 엘라스틱 서치를 다뤄보도록 하겠습니다. 데이터는 추후 주가 분석을 등을 하기 위해서, 삼성전자의 주식 데이터를 저장해보는 것으로 해보겠습니다.

     

    삼성전자 주식 데이터

    Yahoo Finance의 삼성전자 종목

     

    야후의 Finance라는 사이트에 가시면, 종목을 입력할 수 있고 삼성전자의 종목(005930.KS)[1]를 입력하면 위와 같이 삼성전자 종목 정보로 넘어갑니다. 

     

    화면의 붉은색 네모박스로 체크한 곳을 보면, Download라고 되어 있는데 이 곳을 클릭하면, 삼성전자의 Historical Prices 데이터를 받을 수 있습니다. 귀찮은 분들을 위해서 아래의 파일을 받으셔도 됩니다.

     

    삼성전자 주가 데이터

    005930.KS.csv
    0.02MB

     

    직접 위 사이트에서 받으시거나, 아니면 블로그에 올려놓은 csv 파일을 받으시면 됩니다. 

    이제 받은 데이터를 기반으로 csv 데이터를 그대로 엘라스틱서치에 넣어보는 것을 해보겠습니다.

     

     

    라이브러리 설치

    엘라스틱서치를 사용하기 위해서는 elasticsearch라는 동명의 라이브러리를 받아야 합니다. 아래와 같이 pip install elasticsearch로 라이브러리를 인스톨 합니다.

    (ml) C:\Python\ml>pip install elasticsearch
    Collecting elasticsearch
    Downloading elasticsearch-7.16.3-py2.py3-none-any.whl (385 kB)
    |████████████████████████████████| 385 kB 6.8 MB/s
    Collecting urllib3<2,>=1.21.1
    Downloading urllib3-1.26.8-py2.py3-none-any.whl (138 kB)
    |████████████████████████████████| 138 kB 6.4 MB/s
    Requirement already satisfied: certifi in c:\anaconda3\envs\ml\lib\site-packages (from elasticsearch) (2021.10.8)
    Installing collected packages: urllib3, elasticsearch
    Successfully installed elasticsearch-7.16.3 urllib3-1.26.8

     

    삼성 데이터 읽기

    코드를 한줄 한줄 설명하면서 이해하도록 해보죠. 우선 csv 데이터를 읽어 들이기 위해서 판다스(Pandas)와 엘라스틱서치를 위해서 2개의 라이브러리를 import 하겠습니다.

     

    dataset 폴더에 있는 삼성전자 파일

     

    그리고 삼성전자 주가 데이터는 위 캡쳐처럼 dataset 폴더를 만들어서 넣은 후 판다스로 읽어보도록 하겠습니다. dataset에 있는 파일을 읽기 위해서 판다스의 read_csv를 사용했습니다.

    from elasticsearch import Elasticsearch
    import pandas as pd
    
    # elastic 폴더에 py 파일이 있기에 ..으로 하였으며, py 파일 안에 폴더가 있으면 .하나만 찍는다
    samsung_pd = pd.read_csv("../dataset/005930.KS.csv")
    print(samsung_pd.head())

     

    Date     Open     High      Low    Close     Adj Close    Volume
    0  2021-01-25  87000.0  89900.0  86300.0  89400.0  88192.921875  27258534
    1  2021-01-26  88800.0  89200.0  86500.0  86700.0  85529.382813  33178936
    2  2021-01-27  86600.0  87700.0  85600.0  85600.0  84444.234375  26423070
    3  2021-01-28  83200.0  85600.0  83200.0  83700.0  82569.890625  31859808
    4  2021-01-29  84500.0  85000.0  82000.0  82000.0  80892.835938  39615978

    위와 같이 samsung_pd에 데이터가 잘 저장된 것을 확인할 수 있습니다. 데이터를 넣기에 앞서 우선 넣을려는 인덱스(index)가 있는지 확인을 해보도록 해보죠.

     

    stock index가 없는 것을 확인

     

    위와 같이 나온다면, 당연히 stock index가 없는 것이니, 이제 삼성전자 주가 데이터를 그대로 엘라스틱 서치에 삽입(insert) 해보도록 하겠습니다. 

     

    데이터를 한번에 넣는 방법도 있지만, 그건 다른 포스팅에서 다뤄볼 주제이니 여기서는 한건 한건 데이터를 넣는다고 해보겠습니다.

     

     

    엘라스틱 데이터 넣기

    # default localhost:9200
    es = Elasticsearch('localhost:9200')
    
    
    from datetime import datetime
    
    
    # stock_data 세팅
    def stock_data(row, stock_nm):
        return {
            'Date': row['Date'],
            'Open': row['Open'],
            'High': row['High'],
            'Low': row['Low'],
            'Close': row['Close'],
            'Adj Close': row['Adj Close'],
            'Volumn': row['Volume'],
            'timestamp': datetime.now(),
        }
    
    
    for index, row in samsung_pd.iterrows():
        doc = stock_data(row, "samsung")
        res = es.index(index="stock", doc_type="_doc", document=doc)

     

    엘라스틱서치 객체 생성

    # default localhost:9200
    es = Elasticsearch('localhost:9200')

    엘라스틱을 사용하기 위해서 Elasticsearch 객체를 생성합니다. 예제에서는 괄호에 ip와 port를 넣었지만 지정하지 않을 경우 default로 localhost:9200이 세팅됩니다. 즉 위 소스는 Elasticsearch()로 해도 동일합니다.

     

    from datetime import datetime
    
    # stock_data 세팅
    def stock_data(row, stock_nm):
        return {
            'Date': row['Date'],
            'Open': row['Open'],
            'High': row['High'],
            'Low': row['Low'],
            'Close': row['Close'],
            'Adj Close': row['Adj Close'],
            'Volumn': row['Volume'],
            'stock_nm': stock_nm,
            'timestamp': datetime.now(),
        }

    stock_data라는 엘라스틱에 넣고 싶은 데이터 형태로 변환하는 펑션을 만들었습니다. 해당 펑션에는 timestamp라는 것을 추가하였는데 현재 밀어넣는 시간을 기록합니다.

     

    for index, row in samsung_pd.iterrows():
        doc = stock_data(row, "samsung")
        res = es.index(index="stock", doc_type="_doc", document=doc)

    판다스로 되어 있는 samsung_pd를 iterrows로 loop를 돌려서, stock_data로 doc 객체를 생성해내고 이를 es.index 명령어에 태워서 주식 데이터에 저장합니다.

     

    일단 데이터가 저장된 것은 확인할 수 있다

     

    카운트 api를 호출하니 248건의 count가 집계된 것을 보아, 데이터가 정상적으로 저장이 된것으로 유추할 수 있지만, 아직 확실하지 않으니 데이터를 확인해보도록 하겠습니다.

    http://localhost:9200/stock/_search?q=Date:2022-01-24

    샘플로 위와 같이 Date값이 오늘인 2022년 1월 24일자인 것을 호출해봤고

    // 20220124235600
    // http://localhost:9200/stock/_search?q=Date:2022-01-24
    
    {
      "took": 2,
      "timed_out": false,
      "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
      },
      "hits": {
        "total": {
          "value": 1,
          "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
          {
            "_index": "stock",
            "_type": "_doc",
            "_id": "I7KHjH4BGM5yWyN8oJJd",
            "_score": 1.0,
            "_source": {
              "Date": "2022-01-24",
              "Open": 75400.0,
              "High": 75800.0,
              "Low": 74700.0,
              "Close": 75100.0,
              "Adj Close": 75100.0,
              "Volumn": 13629682,
              "stock_nm": "samsung",
              "timestamp": "2022-01-24T23:40:05.723334"
            }
          }
        ]
      }
    }

    이와 같이 데이터가 잘 들어간 것을 확인할 수 있습니다. 

     

    References

    [1] Yahoo Finance 삼성전자 종목 정보, https://finance.yahoo.com/quote/005930.KS/history?p=005930.KS

    [2] Elasticsearch client python example, https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/examples.html#ex-get

    연관자료

    [키바나] 설치 및 엘라스틱서치 연동

    [엘라스틱서치] 데이터 입력과 Index, Type, Document

     

    댓글

    Designed by JB FACTORY