본문 바로가기
  • You find inspiration to create your own path !
업무 자동화/python

기본 데이터.csv → 분석 데이터로 계산 하기

by ToolBOX01 2026. 8. 3.
반응형

 

 

특정 종목의 기본 데이터 가져오기

네이버 금융에서 특정 주식 종목의 지정한 연도(기본값: 2026년) 일별 주가 데이터를 수집하여 CSV 파일로 저장하는 크롤링 프로그램입니다.📌 주요 기능 요약1.종목명 자동 조회 (get_stock_name)입력

tool-2020.tistory.com

 

■분석 데이터로 변환

기술지표 계산 코드. 먼저 analysis.py의 역할을 명확히 정의하겠습니다.

  • 5일 이동평균선
  • 20일 이동평균선
  • 60일 이동평균선
  • 120일 이동평균선
  • 240일 이동평균선
  • 거래량 5일 평균
  • 거래량 20일 평균
  • EMA12
  • EMA26
  • MACD
  • Signal
  • Histogram : MACD 오실레이터(Oscillator)
  • RSI(14)
  • Bollinger Band(20)

 

 

 

이동평균선 이란?

주식에서 이동평균선(Moving Average, MA)은 일정 기간 동안의 주가 평균을 내어 선으로 연결한 지표로, 주가의 전체적인 추세와 방향성을 파악하는 데 가장 기본적이고 널리 쓰이는 기술적 분석 도

tool-2020.tistory.com

 

 

MACD (Moving Average Convergence Divergence) 란?

주식에서 MACD (Moving Average Convergence Divergence)는 이동평균선의 한계를 보완하기 위해 개발된 가장 대표적인 추세 추종형 보조 지표입니다. 쉽게 말해 "두 이동평균선의 간격이 멀어지면(수렴과 확

tool-2020.tistory.com

 

 

 

RSI(Relative Strength Index, 상대강도지수)

주식에서 RSI(Relative Strength Index, 상대강도지수)는 주가의 상승 압력과 하락 압력 간의 상대적인 강도를 나타내는 대표적인 모멘텀 보조 지표입니다. 쉽게 말해 현재 주가가 너무 많이 올랐는지(

tool-2020.tistory.com

 

 

 

볼린저 밴드(Bollinger Bands)?

주식에서 볼린저 밴드(Bollinger Bands)는 미국의 재무 분석가 존 볼린저(John Bollinger)가 창안한 기술적 분석 지표로, 주가의 변동성을 측정하고 주가가 높은지 낮은지를 상대적으로 판단하기 위해 사

tool-2020.tistory.com

 

 

추천 컬럼

최종 CSV는 아래처럼 구성하는 것을 추천합니다.  날짜별 계산 항목들

  • 날짜
  • 종가
  • 시가
  • 고가
  • 저가
  • 거래량
  • MA5
  • MA20
  • MA60
  • MA120
  • MA240
  • VOL_MA5
  • VOL_MA20
  • EMA12
  • EMA26
  • MACD
  • Signal
  • Histogram
  • RSI14
  • BB_Middle
  • BB_Upper
  • BB_Lower

▶ 파이썬 코드

설치해야 하는 패키지

pip install pandas numpy matplotlib openpyxl requests beautifulsoup4 lxml

import os
import glob
import pandas as pd


INPUT_FOLDER = "StockData"
OUTPUT_FOLDER = "Output"

os.makedirs(OUTPUT_FOLDER, exist_ok=True)


############################################################
# RSI
############################################################

def calculate_rsi(close, period=14):

    delta = close.diff()

    gain = delta.clip(lower=0)

    loss = -delta.clip(upper=0)

    avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()

    avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()

    rs = avg_gain / avg_loss

    rsi = 100 - (100 / (1 + rs))

    return rsi


############################################################
# Bollinger Band
############################################################

def calculate_bollinger(close):

    middle = close.rolling(20).mean()

    std = close.rolling(20).std()

    upper = middle + std * 2

    lower = middle - std * 2

    return middle, upper, lower


############################################################
# Analysis
############################################################

def analyze(df):

    df["날짜"] = pd.to_datetime(df["날짜"])

    df = df.sort_values("날짜").reset_index(drop=True)

    cols = ["종가", "시가", "고가", "저가", "거래량"]

    for c in cols:

        df[c] = (
            df[c]
            .astype(str)
            .str.replace(",", "", regex=False)
            .astype(float)
        )

    #######################################################
    # Moving Average
    #######################################################

    df["MA5"] = df["종가"].rolling(5).mean()

    df["MA20"] = df["종가"].rolling(20).mean()

    df["MA60"] = df["종가"].rolling(60).mean()

    df["MA120"] = df["종가"].rolling(120).mean()

    df["MA240"] = df["종가"].rolling(240).mean()

    #######################################################
    # Volume MA
    #######################################################

    df["VOL_MA5"] = df["거래량"].rolling(5).mean()

    df["VOL_MA20"] = df["거래량"].rolling(20).mean()

    #######################################################
    # EMA
    #######################################################

    df["EMA12"] = df["종가"].ewm(
        span=12,
        adjust=False
    ).mean()

    df["EMA26"] = df["종가"].ewm(
        span=26,
        adjust=False
    ).mean()

    #######################################################
    # MACD
    #######################################################

    df["MACD"] = df["EMA12"] - df["EMA26"]

    df["Signal"] = df["MACD"].ewm(
        span=9,
        adjust=False
    ).mean()

    df["Histogram"] = df["MACD"] - df["Signal"]

    #######################################################
    # RSI
    #######################################################

    df["RSI14"] = calculate_rsi(df["종가"])

    #######################################################
    # Bollinger
    #######################################################

    middle, upper, lower = calculate_bollinger(df["종가"])

    df["BB_Middle"] = middle

    df["BB_Upper"] = upper

    df["BB_Lower"] = lower

    #######################################################

    df["날짜"] = df["날짜"].dt.strftime("%Y-%m-%d")

    return df


############################################################
# Main
############################################################

def main():

    files = glob.glob(
        os.path.join(INPUT_FOLDER, "*.csv")
    )

    if len(files) == 0:

        print("CSV가 없습니다.")

        return

    for file in files:

        if "_Analysis" in file:

            continue

        print("--------------------------------")

        print(os.path.basename(file))

        try:

            df = pd.read_csv(
                file,
                encoding="utf-8-sig"
            )

            result = analyze(df)

            name = os.path.splitext(
                os.path.basename(file)
            )[0]

            save = os.path.join(
                OUTPUT_FOLDER,
                name + "_Analysis.csv"
            )

            result.to_csv(
                save,
                index=False,
                encoding="utf-8-sig"
            )

            print("저장 :", save)

        except Exception as e:

            print(e)

    print()

    print("완료")


if __name__ == "__main__":

    main()

analysis.py
0.00MB


by korealionkk@gmail.com

반응형