주식 벤치마크 수익률 구하기

랜디 Randy·2023년 12월 26일
0

저는 주식을 아주 열심히 하고있습니다.
다만 수익률이라는 것이 증권사 앱에 들어가게 되면 볼 수 있는데,
코스피, 코스닥, 나스닥같이 여러 벤치마크들과의 비교수익률은 보기가 힘듭니다.

따라서 이를 데이터로 받아와서, 내 수익률과 비교하는 코드를 한번 작성해보려고 합니다.
제 계좌의 수익률은 API로 정보를 가져오기엔 힘들 것 같아 수작업으로 EXCEL에 적어두고,
코스피/코스닥/나스닥 수익률은 각각 API로 정보를 가져와 CSV파일로 저장하도록 하겠습니다.

1. 동작 방식 구상하기

  1. 사용자로부터 '시작 날짜'와 '종료 날짜'를 입력받음
  2. 시작 날짜는 시작 날짜를 포함한 주의 월요일로 변경
    • 예를 들어 입력받은 시작 날짜가 화요일이라면, 시작 날짜를 1일 전인 월요일로 변경
  3. 종료 날짜는 종료 날짜를 포함한 주의 금요일로 변경
    • 예를 들어 입력받은 종료 날짜가 수요일이라면, 종료 날짜를 2일 후인 금요일로 변경
  4. 시작 날짜와 종료 날짜 사이의 일주일을 구분
    • 예를 들어 시작 날짜와 종료 날짜 사이에 4주의 간격이 있다면,
    • 각각의 월요일~금요일 날짜를 구해서 일주일로 구성,
    • 총 네 개의 week가 나오게 됨
  5. 벤치마크의 각 week의 수익률 구하기
    • 각 week는 월요일 날짜와 금요일 날짜로 구성되어있음
    • 이를 기준으로 코스피, 코스닥, 나스닥의 수익률 구하기
    • 4번의 예시를 따르면 현재 4개의 week가 존재
    • 각각의 week에 대해 코스피/코스닥/나스닥의 주간 수익률 get
  6. 이 수익률 DataFrame을 바탕으로 데이터 시각화 진행
  7. 내 계좌 데이터도 포함 (수작업)

2. 만들기

1. pykrx

pykrx 라는 라이브러리가 있습니다. krx의 api를 좀 더 간편하고 쉽게 사용하게 만들어주셨습니다.

링크는 여기 있습니다

1 - 1. pykrx 사용법

# Dataframe shape
from pykrx import stock

start_date = '20221226'
end_date = '20221230'
KOSPI = 'KOSPI'
KOSDAQ = 'KOSDAQ'

# KOSPI
kospi_full = stock.get_index_price_change(start_date, end_date, KOSPI)
kospi_full.head()

데이터를 어떻게 받아올 수 있는지 보여주는 예제코드입니다.
start_date, end_date, (KOSPI or KOSDAQ) 세 개의 파라미터를 함수에 넣어서 주면
코스피와 관련된 다양한 지수들과, 이들의 시가/종가/등락률/거래량/거래대금을 리턴합니다.

저희는 여기서 코스피의 등락률만 사용할 예정이니 나중에 DataFrame을 변경할 필요가 있습니다.

2. 일주일 간격 구하기

# Get Every Week's Mondays and Fridays

from datetime import datetime, timedelta
import pandas as pd

def get_every_monday_friday(start_date, end_date):
    # Translate input dates into datetime objects
    start_date_dt = datetime.strptime(start_date, "%Y%m%d")
    end_date_dt = datetime.strptime(end_date, "%Y%m%d")

    # Empty list to store weekly dates
    weekly_dates = []

    current_date = start_date_dt

    # Iterate through weeks until the end_date
    while current_date <= end_date_dt:
        # Calculate the Monday of the current week
        week_start = current_date - timedelta(days=current_date.weekday())

        # Calculate the Friday of the current week
        week_end = week_start + timedelta(days=4)

        # Append the start and end dates of the current week to the list
        weekly_dates.append((week_start.strftime("%Y%m%d"), week_end.strftime("%Y%m%d")))

        # Move to the next week
        current_date = week_end + timedelta(days=3)  # Move to the next Monday

    # Create a DataFrame with weekly Mondays and Fridays
    df = pd.DataFrame(weekly_dates, columns=['Monday', 'Friday'])

    return df

# This function will return weekly mondays and fridays between
# start_date and end_date.
start_date = '20221201'
end_date = '20221227'
weekly_dates_df = get_every_monday_friday(start_date, end_date)
weekly_dates_df

시작 날짜와 종료 날짜를 입력하면 그 사이의 일주일들을 반환하는 함수입니다.

이런 식으로 반환하게 됩니다.

이제 이걸 합쳐서 하나의 함수로 만들어봅시다.

3. 코스피, 코스닥 등락률 구하기

# Get Every Week's Fluctuation Rate

from pykrx import stock
import numpy as np

KOSPI = 'KOSPI'
KOSDAQ = 'KOSDAQ'

total_weekly = weekly_dates_df.copy()
total_weekly['KOSPI'] = 100
total_weekly['KOSDAQ'] = 100

def get_weekly_korea_fluctuation():
  for idx in weekly_dates_df.index:
      # Get index's monday and friday date
      monday = weekly_dates_df.loc[idx, 'Monday']
      friday = weekly_dates_df.loc[idx, 'Friday']

      # KOSPI and KOSDAQ's weekly fluctuation rate
      # KOSPI
      weekly_kospi_full = stock.get_index_price_change(monday, friday, KOSPI)
      kospi_result = weekly_kospi_full.iloc[0,2]
      total_weekly.at[idx, 'KOSPI'] = kospi_result

      # KOSDAQ
      weekly_kosdaq_full = stock.get_index_price_change(monday, friday, KOSDAQ)
      kosdaq_result = weekly_kosdaq_full.iloc[0,2]
      total_weekly.at[idx, 'KOSDAQ'] = kosdaq_result

  return total_weekly

result_df = get_weekly_korea_fluctuation()
result_df

미리 만들어진 월~금 간격들을 구해서, 이 기간동안의 코스피와 코스닥 수익률을 구하는 코드입니다.
코드를 보니 코스피와 코스닥의 수익률을 구하는 코드가 똑같습니다. 이걸 하나의 함수로 만들면 괜찮을 것 같은데...

사실 코스피랑 코스닥 두 개의 벤치마크만 사용하는지라 이걸 하나의 함수로 또 만들 필요가 굳이 있나 싶긴하지만, 최대한 중복을 피하고 함수화하는게 좋다고들 하니까...
나중에 업데이트할 때 시도해보겠습니다.

4. 나스닥 등락률 구하기

나스닥의 등락률을 구하기 위해 사용한 라이브러리는 yfinance 입니다.

yfinancepykrx 와는 다르게 날짜의 입력방식을 %Y-%m-%d의 형태로 받습니다.

import yfinance as yf

# Function to get weekly fluctuation rates for Nasdaq
total_weekly['NASDAQ'] = 100

def get_weekly_nasdaq_fluctuation():
    NASDAQ = '^IXIC'  # Ticker symbol for Nasdaq in yfinance

    for idx in weekly_dates_df.index:

        monday = weekly_dates_df.loc[idx, 'Monday']
        friday = weekly_dates_df.loc[idx, 'Friday']

        # transform string to datetime object
        monday_obj = datetime.strptime(monday, '%Y%m%d')
        friday_obj = datetime.strptime(friday, '%Y%m%d')

        # transform the date which fit in yfinance parameter.
        formatted_monday = monday_obj.strftime('%Y-%m-%d')
        formatted_friday = friday_obj.strftime('%Y-%m-%d')

        # Nasdaq
        nasdaq_data = yf.download(NASDAQ, start=formatted_monday, end=formatted_friday)
        nasdaq_result = (nasdaq_data['Adj Close'].pct_change().fillna(0) + 1).prod() - 1
        # Adj Close: Adjusted Closing Prie; 조정 종가
        # pct_change(): get daily fluctuation rate of 'Adj Close'
        # fillna(0): replace NaN to 0
        # + 1: to calculate compound interest
        # prod(): multiple all daily fluctuation rate
        # - 1: to get Nasdaq's weekly pure fluctuation rate
        total_weekly.at[idx, 'NASDAQ'] = nasdaq_result

    return total_weekly

# Example usage
weekly_fluctuation_df = get_weekly_nasdaq_fluctuation()
weekly_fluctuation_df

여기서 나스닥의 주간 수익률을 구하는 코드는 지피티의 힘을 빌렸는데,
아무래도 제가 직접 한번 확실한지 검사를 해봐야겠습니다.
일단 기능 구현이 우선이라 똑바로 가져오는지에 대한 검증은 진행하지 않았습니다.

5. 하나의 함수로 합치기

def get_weekly_benchmark_fluctuation_rate(start_date, end_date):

  # Make DataFrame which have weeekly date
  def get_every_monday_friday(start_date, end_date):
      # Translate input dates into datetime objects
      start_date_dt = datetime.strptime(start_date, "%Y%m%d")
      end_date_dt = datetime.strptime(end_date, "%Y%m%d")

      # Initialize an empty list to store weekly dates
      weekly_dates = []

      current_date = start_date_dt

      # Iterate through weeks until the end_date
      while current_date <= end_date_dt:
          # Calculate the Monday of the current week
          week_start = current_date - timedelta(days=current_date.weekday())

          # Calculate the Friday of the current week
          week_end = week_start + timedelta(days=4)

          # Append the start and end dates of the current week to the list
          weekly_dates.append((week_start.strftime("%Y%m%d"), week_end.strftime("%Y%m%d")))

          # Move to the next week
          current_date = week_end + timedelta(days=3)  # Move to the next Monday

      # Create a DataFrame with weekly Mondays and Fridays
      df = pd.DataFrame(weekly_dates, columns=['Monday', 'Friday'])
      return df

  # Append Data of benchmark's fluctuation rate into DataFrame
  def get_weekly_fluctuation(weekly_dates):
    KOSPI = 'KOSPI'
    KOSDAQ = 'KOSDAQ'
    NASDAQ = '^IXIC'  # Ticker symbol for Nasdaq in yfinance

    total_weekly = weekly_dates.copy()
    total_weekly['KOSPI'] = 100
    total_weekly['KOSDAQ'] = 100
    total_weekly['NASDAQ'] = 100

    for idx in weekly_dates.index:
        # Get index's monday and friday date
        monday = weekly_dates.loc[idx, 'Monday']
        friday = weekly_dates.loc[idx, 'Friday']

        # KOSPI and KOSDAQ's weekly fluctuation rate
        # KOSPI
        weekly_kospi_full = stock.get_index_price_change(monday, friday, KOSPI)
        kospi_result = weekly_kospi_full.iloc[0,2]
        total_weekly.at[idx, 'KOSPI'] = kospi_result

        # KOSDAQ
        weekly_kosdaq_full = stock.get_index_price_change(monday, friday, KOSDAQ)
        kosdaq_result = weekly_kosdaq_full.iloc[0,2]
        total_weekly.at[idx, 'KOSDAQ'] = kosdaq_result

        # transform string to datetime object
        monday_obj = datetime.strptime(monday, '%Y%m%d')
        friday_obj = datetime.strptime(friday, '%Y%m%d')

        # transform the date which fit in yfinance parameter.
        formatted_monday = monday_obj.strftime('%Y-%m-%d')
        formatted_friday = friday_obj.strftime('%Y-%m-%d')

        # Nasdaq
        nasdaq_data = yf.download(NASDAQ, start=formatted_monday, end=formatted_friday)
        nasdaq_result = (nasdaq_data['Adj Close'].pct_change().fillna(0) + 1).prod() - 1
        total_weekly.at[idx, 'NASDAQ'] = nasdaq_result

    return total_weekly

  weekdays = get_every_monday_friday(start_date, end_date)
  result = get_weekly_fluctuation(weekdays)

  return result

이때까지 만든 함수들을 한번에 작동하도록 하나의 함수로 만들었습니다.
위에서 설명한 함수의 합이라 여기서 무언가를 더 설명할 필요는 없어보입니다

start_date = '20231003'
end_date = '20231030'

total = get_weekly_benchmark_fluctuation_rate(start_date, end_date)
total

이젠 이렇게 날짜를 입력해서 넘겨주기만 하면...!

이렇게 결과를 얻을 수 있습니다.

CSV로 저장

total.to_csv(f"{start_date}~{end_date}_benchmark_fluctuation_rate.csv", index=False)

이를 csv파일로 저장해두고,
다른 ipynb파일을 만들어 그 파일에서 시각화를 진행할 예정입니다.

profile
데이터는 계단, 직관은 다리

0개의 댓글