배당 주식 투자자/파이썬으로 배당 투자 분석하기

파이썬을 활용한 S&P500 PER 및 PBR 순위 분석

리치즈 2023. 10. 15. 10:58
728x90

S&P 500 지수의 주식 데이터를 분석하고 원하는 지표(예: 시가총액, PER, PBR)에 따라 상위 N개의 주식을 추출하고 CSV 파일로 저장하는 코드를 소개합니다.

 

이전글 

 

앞에서 주식 평가 지표인 PER(Price-to-Earnings Ratio)와 PBR(Price-to-Book Ratio)은 무엇이고, 미국 주식 시장에서 낮은 PER 및 PBR을 가진 주식을 찾는 방법을 살펴보았습니다.

이번 글에서는 파이썬을 사용하여 PER과 PBR 순위를 찾는 방법에 대해 소개하겠습니다.

 

 

이번 코드는 riverKangg의 Github을 바탕으로 작성되었습니다.

 

GitHub - riverKangg/stock-report

Contribute to riverKangg/stock-report development by creating an account on GitHub.

github.com

 

 

1. 라이브러리 설정

import os
import warnings
import pandas as pd
from numerize import numerize
from stock_report.stock_analyzer import StockAnalyzer
from stock_report.sp500_list_fetcher import SP500ListFetcher

warnings.filterwarnings('ignore')

이 스크립트는 필요한 라이브러리를 가져옵니다. os 모듈은 파일 및 디렉토리 관리를 위해 사용되며, pandas는 데이터 프레임을 다루기 위해 사용됩니다. numerize는 숫자를 읽기 쉽게 포맷팅하기 위한 라이브러리입니다. StockAnalyzerSP500ListFetcher는 사용자 정의 모듈로, 주식 분석과 S&P 500 목록을 가져오기 위해 사용됩니다.

 

2. S&P500 데이터 수집

def fetch_or_load_sp500_data(save_directory):
    data_file_path = os.path.join(save_directory, 'sp500_valuation_data.csv')

    # Check if the data file already exists
    if os.path.exists(data_file_path):
        # Load and return the existing data
        valuation_data = pd.read_csv(data_file_path, index_col=0)
        return valuation_data

    # Step 1: Get S&P 500 tickers
    sp500_data = SP500ListFetcher().get_sp500_data()
    sp500_tickers = sp500_data.index.tolist()

    # Step 2: Fetch S&P 500 stocks
    analyzed_data = {}
    error_tickers = []  # 에러가 발생한 티커 목록

    for ticker in sp500_tickers:
        try:
            stock_analyzer = StockAnalyzer(ticker)
            analyzed_data[ticker] = stock_analyzer.last_quarter_ratios().iloc[0]
        except Exception as e:
            error_tickers.append(ticker)
            print(f"Error analyzing {ticker}: {str(e)}")

    for error_ticker in error_tickers:
        sp500_tickers.remove(error_ticker)  # 에러 티커 제외

    # Step 3: Sort by PER in descending order
    valuation_data = pd.DataFrame(analyzed_data).T

    # Step 4: Save the data to a CSV file
    if not os.path.exists(save_directory):
        os.makedirs(save_directory)

    valuation_data.to_csv(data_file_path)

    return valuation_data

이 함수는 S&P 500 주식 데이터를 수집하거나 이미 수된 데이터를 로드합니다. 데이터 파일이 존재하는 경우, 파일을 읽어옵니다. 그렇지 않은 경우, S&P 500 목록을 가져오고 각 주식을 분석합니다. 에러가 발생한 경우, 해당 티커를 에러 목록에 추가하고 로그에 출력합니다. 마지막으로, 분석된 데이터를 PER을 기준으로 정렬하여 CSV 파일로 저장합니다.

 

3. S&P 500 정보 추가

def add_sp500_info(valuation_data):
    sp500_data = SP500ListFetcher().get_sp500_data()
    valuation_data = valuation_data.join(sp500_data)
    return valuation_data

이 함수는 S&P 500의 섹터, 산업군 정보를 추가합니다.

 

4. 상위 주식을 CSV 파일로 저장하는 함수

def save_top_stocks_to_csv(top_stocks, metric, save_directory, group_by=None):
    if group_by:
        csv_file_name = f'top_{metric}_{group_by}.csv'
    else:
        csv_file_name = f'top_{metric}.csv'

    csv_file_path = os.path.join(save_directory, csv_file_name)
    top_stocks.to_csv(csv_file_path, sep="\t", index=False)

이 함수는 상위 N개 주식을 지정된 지표(예: 시가총액)에 따라 CSV 파일로 저장합니다. group_by 매개변수를 사용하여 섹터에 따라 그룹화된 데이터를 저장할 수 있습니다.

 

5. 그룹화된 데이터를 CSV 파일로 저장하는 함수

def save_grouped_data_to_csv(grouped_data, metric, save_directory):
    csv_file_name = f'GRP_{metric}.csv'
    csv_file_path = os.path.join(save_directory, csv_file_name)
    grouped_data.to_csv(csv_file_path, sep="\t")

이 함수는 그룹화된 데이터를 CSV 파일로 저장합니다. 주로 섹터별 평균 지표를 저장하는 데 사용됩니다.

 

6. 상위 N개 주식을 가져오는 함수

def get_top_n_stocks(valuation_data, metric, n=10, ascending=True, group_by=None):
    if metric not in valuation_data.columns:
        print(f"Column '{metric}' not found in the data.")
        return None

    if group_by:
        valuation_data = add_sp500_info(valuation_data)
        valuation_data = valuation_data[valuation_data[metric]>0]
        top_stocks = valuation_data.groupby(group_by).apply(lambda x: x.nsmallest(n, metric))[[metric,'MarketCap']].reset_index()
        top_stocks.columns = [group_by, 'Symbol', metric, 'MarketCap']
        top_stocks[metric] = top_stocks[metric].apply(lambda x: round(x, 1))
        top_stocks['MarketCap'] = top_stocks['MarketCap'].apply(lambda x: numerize.numerize(x))

        # Calculating the Number of Companies and Average Metric by Sector.
        grouped_data = valuation_data.groupby(group_by)[metric].agg(['count', 'mean'])
        grouped_data = grouped_data.sort_values(by='mean')
        grouped_data['mean'] = grouped_data['mean'].apply(lambda x: round(x, 1))
        save_grouped_data_to_csv(grouped_data, metric, save_directory)

    else:
        top_stocks = valuation_data.nlargest(n, metric)[[metric]]
        top_stocks[metric] = top_stocks[metric].apply(lambda x: numerize.numerize(x))
        top_stocks = top_stocks.reset_index()
        top_stocks.columns = ['Symbol', metric]

    return top_stocks

이 함수는 이미 분석된 데이터에서 상위 N개 주식을 가져옵니다. 지표(예: PER, PBR) 및 그룹화(섹터별) 옵션을 설정할 수 있습니다.

 

7. 메인 코드 블록

if __name__ == "__main__":
    save_directory = "sp500_data"

    analyzed_data = fetch_or_load_sp500_data(save_directory)

    if analyzed_data is not None:
        print(analyzed_data.shape)

        # Get the top 10 MarketCap stocks and save to CSV:
        top_10_market_cap_stocks = get_top_n_stocks(analyzed_data, 'MarketCap', n=10, ascending=False)
        save_top_stocks_to_csv(top_10_market_cap_stocks, 'MarketCap', save_directory)

        # Get the top 10 PER Sector and save to CSV:
        top_10_per_sector = get_top_n_stocks(analyzed_data, 'PER', n=5, ascending=True, group_by='Sector')
        save_top_stocks_to_csv(top_10_per_sector, 'PER', save_directory, 'Sector')

        # Get the top 10 PBR Sector and save to CSV:
        top_10_pbr_sector = get_top_n_stocks(analyzed_data, 'PBR', n=5, ascending=True, group_by='Sector')
        save_top_stocks_to_csv(top_10_pbr_sector, 'PBR', save_directory, 'Sector')

메인 코드 블록에서는 위에서 정의한 함수들을 호출하여 S&P 500 주식 데이터를 분석하고 상위 주식을 CSV 파일로 저장합니다. 시가총액, PER, PBR 등 다양한 지표를 기반으로 상위 주식을 추출하고 섹터별 그룹화 데이터를 저장합니다.

 

728x90
LIST