ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 미국 ETF 상위 수익률 종목 뽑아내기: python yahoo finance 활용
    금융퀀트/자산평가&프로그램매매 2024. 7. 25. 02:02
    반응형

    종목별 과거 종가 찾기 : get_historical_closeprice

    미국 ETF 대표 종목 뽑아내기: python yahoo finance 활용에서 살펴본 것처럼 ETF Database 사이트에서(https://etfdb.com/) 아래와 같은 ETF 목록 정보를 입수할 수 있다. 

    ETF_Ticker.csv
    0.12MB

     

    이 정보를 바탕으로 pip install yfinance 명령어를 통해서 설치한(아나콘다 프롬프트) yahoo finance 라이브러리의 history 함수를 통해서 각 티커의 과거 종가를 불러올 수 있다. 구조는 간단한데, 먼저 yfinance의 Ticker 클래스의 stock이라는 객체를 만든 뒤 객체에 대해서 시작일과 종료일을 붙인 history 속성을 불러오면 된다. 종가를 불러오면 아래와 같은 그림처럼 결과가 나오는데 종가를 이용해서 수익률을 계산할 것이기 때문에 "Close" 컬럼 데이터만 불러오면 된다.

    그림1: history 함수 사용을 통한 결과 예시

    코드로 구현하면 아래와 같다. 

    import yfinance as yf
    import pandas as pd
    from datetime import datetime
    
    ...(생략)...
    
    # ETF종목코드(ticker), 시작일(start_date), 종료일(end_date)를 변수로 받는 함수
    def get_historical_closeprice(ticker: str, start_date: str, end_date: str):
        # yahoo finance yf 라이브러리 Ticker 클래스 객체를 stock에 저장
        stock = yf.Ticker(ticker)
        # 시작일자를 문자열 "YYYY-MM-DD"로 변경
        start_date = datetime.strptime(start_date, "%Y%m%d").strftime("%Y-%m-%d")
        # 종료일자를 문자열 "YYYY-MM-DD"로 변경
        end_date = datetime.strptime(end_date, "%Y%m%d").strftime("%Y-%m-%d")
        # stock 객체의 history 속성을 불러옴 = 시계열 가격을 불러옴
        historical_closeprice = stock.history(start=start_date, end=end_date)
        # 시계열 시가, 고가, 저가, 종가 데이터 중 종가 자료만 추출
        return historical_closeprice["Close"]

     

    종목별 규모 및 종가 데이터 만들기 : get_etf_analysis_raw_data

    미국 ETF 대표 종목 뽑아내기: python yahoo finance 활용에서 만든 get_total_asset을 통해서 종목별 규모를 가져올 수 있고, 위에서 만든 get_historical_closeprice 함수로 종목별 시계열 종가를 가져올 수 있게 되었다. 결과적으로 ETF종목코드(Ticker), 종목명, ETF총자산, [과거 종가 시계열 데이터]로 이루어진 데이터를 구할 수 있다.

    데이터를 구하는 함수를 코드로 구현하면 아래와 같다.

    import yfinance as yf
    import pandas as pd
    from datetime import datetime
    
    ...(생략)...
    
    # 파일경로, 시작일, 종료일을 변수로 받는 함수
    def get_etf_analysis_raw_data(file_path, fromdate:str, todate:str):
        # 파일경로을 변수로 받는 get_df라는 함수를 이용해서 Tickers라는 데이터프레임 생성
        # get_df는 "미국 ETF 대표 종목 뽑아내기: python yahoo finance 활용" 글에서 만들었음
        Tickers = get_df(file_path)
        # 빈 데이터 만들기
        data = []
        # 각 ETF 코드를 i 에 넣어서 for 문 실행
        for i in Tickers["티커"]:
            ticker = i
            # 위 Tickers 데이터프레임에서 i에 들어간 ETF코드와 같은 코드를 가진 ETF의 종목명 추출
            name = Tickers.loc[Tickers["티커"]==i, "종목명"].values[0]
            # get_total_asset 함수로 ETF 총자산 구하기
            # get_total_asset는 "미국 ETF 대표 종목 뽑아내기: python yahoo finance 활용" 글에서 만들었음
            # get_historical_closeprice 로 시계열 종가정보 뽑아내기
            try:
                totalasset = get_total_asset(i)
                prices = get_historical_closeprice(i, fromdate, todate)
            except:
            	# 정보가 없거나 에러가 날 경우 0으로 처리
                totalasset = 0
                prices = 0
            # ETF코드, ETF명, ETF총자산, 시계열가격데이터로 이루어진 리스트 만들기
            addtional_data = [ticker, name, totalasset, prices]
            # 추가 리스트(addtional_data)를 data list 에 추가
            data.append(addtional_data)
        return data

     

     

    종목별 성장률 구하는 함수 만들기 : calculate_yields

    get_etf_analysis_raw_data 함수로 모은 데이터는 ETF코드(ticker), ETF명, ETF의 자산규모, [시계열 가격데이터]로 이루어져 있다. 우리가 알고 싶은 것은 수익률이므로 시계열가격데이터를 이용해서 수익률을 구해야 한다. 수익률 계산은 "시계열 가격데이터의 최종 가격 - 최초가격 / 최초가격"으로 간단하게 수행할 수 있다. 이를 코드로 나타내면 아래와 같다. 

    import yfinance as yf
    import pandas as pd
    from datetime import datetime
    
    ...(생략)...
    
    # data를 변수로 받는 함수, 이 때 데이터는 시계열 가격정보의 list
    def calculate_yields(data):
    	# 0 번째 최초 가격 가져오기
        price_start = data.iloc[0]
        # 마지막번째 최종 가격 가져오기
        price_end = data.iloc[-1]   
        # 수익률 반환
        return (price_end - price_start) / price_start

     

    종합 데이터 만들기 : get_etf_analysis_data

    최종적으로 get_etf_analysis_raw_data를 이용해서  ETF종목코드(Ticker), 종목명, ETF총자산, [과거 종가 시계열 데이터]로 이루어진 데이터를 먼저 구한 뒤 [과거 종가 시계열 데이터]를 calculate_yields 함수를 통해서 수익률 데이터로 변환하고 최종적인 데이터프레임을 만들어서 총자산 또는 수익률을 기준으로 줄을 세우면 추천 종목을 뽑아낼 수 있다. 아래 예시 코드는 분석시작일(fromdate), 분석종료일(todate), 추천종목수(num_of_recommendations)를 변수로 받는 get_etf_analysis_data 함수의 코드이다. 

    import yfinance as yf
    import pandas as pd
    from datetime import datetime
    
    ...(중략)...
    
    # 파일경로, 시작일자, 종료일자, 추천 종목수를 변수로 받는 함수
    def get_etf_analysis_data(file_path:str, fromdate:str, todate:str, num_of_recommendations:int):
        # get_etf_analysis_raw_data를 이용해서 ETF코드, 종목명, ETF총자산, [가격시계열데이터]로 
        # 이루어진 데이터를 series 변수에 저장
        series = get_etf_analysis_raw_data(file_path, fromdate, todate)
        data = []
        # series에 저장된 순서대로 0 ~ series 데이터 수 만큼 for 문을 통해서 작업
        for i in range(0, len(series)):
        	# series 데이터의 i 번째 데이터(리스트) 속의 0 번째 데이터 = ETF코드 
            ticker = series[i][0]
            # series 데이터의 i 번째 데이터(리스트) 속의 1 번째 데이터 = ETF명
            name = series[i][1]
            # series 데이터의 i 번째 데이터(리스트) 속의 2 번째 데이터 = ETF총자산
            totalasset = series[i][2]
            try:
            # series 데이터의 i 번째 데이터(리스트) 속의 3 번째 데이터 = ETF종가의 시계열 리스트
            # 이 리스트를 calculate_yields의 변수로 넣어서 수익률(yields) 산출
                yields = calculate_yields(series[i][3])
            except:
            	# 예외처리 : 수익률 = 0
                yields = 0
            if totalasset > 0:
            	# ETF 총자산 데이터가 있는 데이터만 최종 데이터에 추가
                addtional_data = [ticker, name, totalasset, yields]
                data.append(addtional_data)
        # ETF코드, ETF명, ETF총자산, 수익률로 이루어진 최종 데이터프레임 구축
        df = pd.DataFrame(data, columns=["ticker", "name", "totalasset", "yields"])
        # num_of_recommendations 만큼 ETF 총자산이 큰 순서대로 추천
        bestcapdata = df.sort_values(by="totalasset", ascending=False).head(num_of_recommendations)
        # num_of_recommendations 만큼 ETF 수익률이 큰 순서대로 추천
        bestreturndata = df.sort_values(by="yields", ascending=False).head(num_of_recommendations)
        # 두 결과를 동시에 반환
        return bestcapdata, bestreturndata

     

    미국 ETF 상위 수익률 종목 뽑아내기

    아래는 수익률 기준 시작일자를 2023-01-01, 종료일자를 2024-07-24 일로 설정한 뒤 ETFTicker.csv 를 이용해서 전체 자산기준으로 5개, 수익률 기준으로 5개 종목 추천을 받은 결과이다

    그림2: 종목추천 결과

    전체 코드는 아래와 같다. 

    import yfinance as yf
    import pandas as pd
    from datetime import datetime
    
    file_path = "ETF_Ticker.csv의 파일 경로"
    
    def get_etf_info(ticker: str):
        stock = yf.Ticker(ticker)
        return stock.info
    
    def get_df(file_path: str):
        return pd.read_csv(file_path)
    
    def get_total_asset(ticker: str):
        stock = yf.Ticker(ticker)
        return stock.info.get("totalAssets")
    
    def get_historical_closeprice(ticker: str, start_date: str, end_date: str):
        stock = yf.Ticker(ticker)
        start_date = datetime.strptime(start_date, "%Y%m%d").strftime("%Y-%m-%d")
        end_date = datetime.strptime(end_date, "%Y%m%d").strftime("%Y-%m-%d")
        historical_closeprice = stock.history(start=start_date, end=end_date)
        return historical_closeprice["Close"]
    
    def get_etf_analysis_raw_data(file_path, fromdate:str, todate:str):
        Tickers = get_df(file_path)
        data = []
        for i in Tickers["티커"]:
            ticker = i
            name = Tickers.loc[Tickers["티커"]==i, "종목명"].values[0]
            try:
                totalasset = get_total_asset(i)
                prices = get_historical_closeprice(i, fromdate, todate)
            except:
                totalasset = 0
                prices = 0
            addtional_data = [ticker, name, totalasset, prices]
            data.append(addtional_data)
        return data
    
    def calculate_yields(data):
        price_start = data.iloc[0]  
        price_end = data.iloc[-1]   
        return (price_end - price_start) / price_start
    
    def get_etf_analysis_data(file_path:str, fromdate:str, todate:str, num_of_recommendations:int):
        series = get_etf_analysis_raw_data(file_path, fromdate, todate)
        data = []
        for i in range(0, len(series)):
            ticker = series[i][0]
            name = series[i][1]
            totalasset = series[i][2]
            try:
                yields = calculate_yields(series[i][3])
            except:
                yields = 0
            if totalasset > 0:
                addtional_data = [ticker, name, totalasset, yields]
                data.append(addtional_data)
        df = pd.DataFrame(data, columns=["ticker", "name", "totalasset", "yields"])
        bestcapdata = df.sort_values(by="totalasset", ascending=False).head(num_of_recommendations)
        bestreturndata = df.sort_values(by="yields", ascending=False).head(num_of_recommendations)
        return bestcapdata, bestreturndata
    
    fromdate = "20230101"
    todate = "20240724"
    data2, data3 = get_etf_analysis_data(file_path, fromdate, todate, 5)
    print(data2, data3)
    반응형
Designed by Tistory.