[머신러닝] 주식 종목 추천 시스템 - (2) 데이터 수집
2024. 8. 14. 19:05ㆍAI & DS/머신러닝
yfinance 라이브러리와 pandas를 사용하여
S&P 500에 속한 회사들의 재무 정보를 수집하고
이를 데이터프레임으로 변환하는 과정에 대해 알아보겠습니다.
1. 라이브러리 임포트
import pandas as pd
import yfinance as yf
from tqdm import tqdm
- pandas: 데이터 조작 및 분석을 위한 라이브러리 → 특히 데이터프레임을 다루는 데 유용
- yfinance: 야후 파이낸스 데이터를 손쉽게 가져올 수 있게 해주는 라이브러리
- tqdm: 루프의 진행 상황을 시각적으로 보여주는 진행률 표시줄 라이브러리
DataFrame
- DataFrame은 pandas 라이브러리에서 제공하는 2차원 데이터 구조로, 행(row)과 열(column)로 구성된 데이터 테이블
tqdm
- 예시 코드
from tqdm import tqdm
import time
# 예제 작업: 100번의 반복 수행, 각 반복마다 0.1초 대기
for i in tqdm(range(100), desc="Processing"):
time.sleep(0.1)
- 출력 결과
Processing: 100%|████████████████████████████████| 100/100 [00:10<00:00, 9.99it/s]
2. Wikipedia에서 S&P 500 목록 가져오기
url = '<https://en.wikipedia.org/wiki/List_of_S%26P_500_companies>'
tables = pd.read_html(url)
sp500_table = tables[0]
- pd.read_html(url): 지정된 URL에서 HTML 테이블을 읽어 데이터프레임 리스트로 반환
- 여기서는 S&P 500 목록이 포함된 Wikipedia 페이지를 사용
- tables[0]: 첫 번째 테이블을 선택 → S&P 500 기업 목록이 첫 번째 테이블에 있음
첫번째 테이블만 가져온 이유
import pandas as pd
# Wikipedia에서 S&P 500 목록 가져오기
url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
tables = pd.read_html(url)
# 첫 번째 테이블
sp500_table_1 = tables[0]
print("첫 번째 테이블:")
print(sp500_table_1)
# 두 번째 테이블
sp500_table_2 = tables[1]
print("\n두 번째 테이블:")
print(sp500_table_2)
첫 번째 테이블과 두 번째 테이블 비교 분석
1. 첫 번째 테이블 분석 : S&P 500에 속한 기업들의 목록을 포함
- Symbol: 주식의 티커 심볼(Ticker Symbol)
- Security: 회사의 이름
- GICS Sector: 회사가 속한 GICS(Global Industry Classification Standard) 섹터
- GICS Sub-Industry: 회사가 속한 GICS 하위 산업
- Headquarters Location: 회사의 본사 위치
- Date added: 해당 회사가 S&P 500 지수에 추가된 날짜
- CIK: SEC(미국 증권거래위원회)에 의해 부여된 고유 식별자(Central Index Key)
- Founded: 회사가 설립된 연도두 번째 테이블 분석
2. 두 번째 테이블 분석 : S&P 500 구성 요소의 변경 내역을 포함
- S&P 500 지수에서 어떤 회사가 추가되고, 어떤 회사가 제거되었는지에 대한 정보
- Date Added: 회사가 S&P 500 지수에 추가된 날짜
- Ticker: 새로 추가된 회사의 티커 심볼
- Security: 새로 추가된 회사의 이름
- Removed Date: 회사가 S&P 500 지수에서 제거된 날짜
- Ticker: 제거된 회사의 티커 심볼
- Security: 제거된 회사의 이름
- Reason: 회사가 제거된 이유
3. S&P 500 티커 심볼 목록 생성
sp500_tickers = sp500_table['Symbol'].tolist()
- sp500_table['Symbol']: 데이터프레임의 'Symbol' 열을 선택
- .tolist(): 이 열을 리스트로 변환 → 각 항목은 S&P 500에 속한 기업의 티커 심볼
4. 가져올 재무 정보 목록
financial_fields = [
"industry", "sector", "fullTimeEmployees", "auditRisk", "boardRisk",
"compensationRisk", "shareHolderRightsRisk", "overallRisk", "dividendYield",
"payoutRatio", "fiveYearAvgDividendYield", "beta", "trailingPE",
"averageVolume", "marketCap", "currency", "enterpriseValue", "profitMargins",
"heldPercentInsiders", "heldPercentInstitutions", "bookValue", "priceToBook",
"pegRatio", "enterpriseToEbitda", "52WeekChange", "recommendationMean",
"recommendationKey", "numberOfAnalystOpinions", "totalCash", "ebitda",
"totalDebt", "quickRatio", "currentRatio", "totalRevenue", "returnOnAssets",
"returnOnEquity", "grossProfits", "freeCashflow", "operatingCashflow",
"earningsGrowth", "revenueGrowth", "grossMargins", "ebitdaMargins",
"operatingMargins"
]
- financial_fields: 수집할 재무 정보의 목록을 정의 → 이 목록은 딕셔너리의 키로 사용됨
5. 데이터 저장을 위한 리스트 초기화
financial_data = []
- financial_data: 각 기업의 재무 정보를 저장할 빈 리스트
6. 각 종목의 재무 정보 수집
for ticker in tqdm(sp500_tickers, desc="Fetching financial data"):
stock = yf.Ticker(ticker)
info = stock.info
# 필요한 재무 정보 추가
data = {'Ticker': ticker}
for field in financial_fields:
data[field] = info.get(field)
financial_data.append(data)
for ticker in tqdm(sp500_tickers, desc="Fetching financial data")
- tqdm을 사용하여 진행률 표시줄을 출력하면서 sp500_tickers 리스트(S&P 500 기업 목록)의 각 티커 심볼에 대해 루프를 수행
- 첫 번째 인수는 진행률 표시줄을 표시할 이터러블 객체
- 두 번째 인수는 진행률 표시줄의 설명(description) 텍스트를 설정하는 매개변수
stock = yf.Ticker(ticker)
- yfinance 라이브러리의 Ticker 클래스를 사용하여 각 티커에 대한 Ticker 객체를 생성
- Ticker 객체를 생성하는 이유
- Ticker 객체를 생성하면 해당 티커(symbol)와 관련된 모든 데이터를 손쉽게 접근할 수 있다.
- (ex) stock.info, stock.history(), stock.financials 등 다양한 속성과 메서드를 사용할 수 있다.
info = stock.info : 해당 티커에 대한 주식의 주요 재무 정보를 담고 있는 딕셔너리를 반환
data = {'Ticker': ticker}: 현재 티커를 포함하는 딕셔너리를 초기화
- 초기화된 상태의 예시
# 예시로 사용할 S&P 500 티커 심볼 목록
sp500_tickers = ['AAPL', 'MSFT', 'GOOGL'] # 간단한 예시로 일부만 포함
# 각 종목의 재무 정보 수집
for ticker in sp500_tickers:
data = {'Ticker': ticker} # 현재 티커를 포함하는 딕셔너리 초기화
print(f"Data for {ticker} after initialization: {data}")
- 출력 결과
Data for AAPL after initialization: {'Ticker': 'AAPL'}
Data for MSFT after initialization: {'Ticker': 'MSFT'}
Data for GOOGL after initialization: {'Ticker': 'GOOGL'}
for field in financial_fields: 수집할 재무 정보 목록을 순회
data[field] = info.get(field): 재무 정보를 딕셔너리에 추가
- info.get(field)는 해당 키가 존재하지 않을 경우 None을 반환하여 에러를 방지
- 재무 정보가 추가된 딕셔너리 예시
- dic = { 'Ticker': 'AAPL', 'industry': 'Consumer Electronics', 'sector': 'Technology', 'fullTimeEmployees': 147000, 'beta': 1.2, 'trailingPE': 28.5, 'marketCap': 2200000000000 ... }
financial_data.append(data): 수집된 재무 정보를 리스트에 추가
7. 데이터프레임으로 변환
df = pd.DataFrame(financial_data)
- pd.DataFrame(financial_data): 수집된 재무 정보 리스트를 데이터프레임으로 변환
데이터 결합
combined_df = pd.concat([df, sp500_table['Security']], axis=1)
pd.concat : 두 데이터프레임을 결합
[df, sp500_table['Security']]는 결합할 데이터프레임 목록
- 여기서 df는 기존의 재무 데이터를 포함한 데이터프레임
Ticker industry sector fullTimeEmployees beta trailingPE marketCap
0 AAPL Consumer Electronics Technology 147000 1.2 28.5 2200000000000
1 MSFT Software Technology 181000 0.8 35.2 1850000000000
2 GOOGL Interactive Media & Services Communication Services 135301 1.1 30.4 1500000000000
- sp500_table['Security']는 S&P 500 기업 이름을 포함하는 시리즈
0 Apple Inc.
1 Microsoft Corporation
2 Alphabet Inc.
Name: Security, dtype: object
- axis=1은 열(column)을 기준으로 결합하겠다는 의미 → 즉, 기존 데이터프레임 df의 오른쪽에 sp500_table['Security'] 열을 추가
Ticker industry sector fullTimeEmployees beta trailingPE marketCap Security
0 AAPL Consumer Electronics Technology 147000 1.2 28.5 2200000000000 Apple Inc.
1 MSFT Software Technology 181000 0.8 35.2 1850000000000 Microsoft Corporation
2 GOOGL Interactive Media & Services Communication Services 135301 1.1 30.4 1500000000000 Alphabet Inc.
열 순서 재정렬
열 이름 가져오기
columns = list(combined_df.columns)
- combined_df.columns는 결합된 데이터프레임의 모든 열 이름을 반환
- list()를 사용하여 열 이름을 리스트로 변환
Security 열 재정렬
security_col = columns.pop()
- columns.pop()은 리스트 columns의 마지막 요소를 제거하고, 그 값을 security_col 변수에 저장
- 여기서는 sp500_table['Security']가 결합 후의 마지막 열이라고 가정하고, 그 열 이름을 리스트에서 제거하고 저장
columns.insert(1, security_col)
- columns.insert(1, security_col)는 security_col을 리스트의 두 번째 위치(인덱스 1)에 삽입 → 이렇게 하면 Security 열이 Ticker 열 다음에 오게 됨
열 순서 조정
df = combined_df[columns]
- combined_df[columns]는 columns 리스트에 정의된 순서대로 열을 정렬한 새로운 데이터프레임을 반환 → 이를 df 변수에 다시 저장하여, 열 순서가 재정렬된 최종 데이터프레임을 얻음
출력 결과 예시
Ticker Security industry sector fullTimeEmployees beta trailingPE marketCap
0 AAPL Apple Inc. Consumer Electronics Technology 147000 1.2 28.5 2200000000000
1 MSFT Microsoft Corporation Software Technology 181000 0.8 35.2 1850000000000
2 GOOGL Alphabet Inc. Interactive Media & Services Communication Services 135301 1.1 30.4 1500000000000
- 이 출력 결과에서 Security 열이 Ticker 열 다음에 위치하도록 재정렬
'AI & DS > 머신러닝' 카테고리의 다른 글
[데이터 사이언스/문법] Python 라이브러리 - tqdm 이란? (0) | 2024.08.14 |
---|---|
[머신러닝] 주식 종목 추천 시스템 - (3) 데이터 전처리 & k-NN 모델 최근접 이웃 찾기 (0) | 2024.08.14 |
[머신러닝] 주식 종목 추천 시스템 - (1) yfinance 라이브러리 설치 & Ticker란? (0) | 2024.08.14 |
[데이터분석] 데이터 크롤링 실습(2) - 인프런 크롤링 (0) | 2024.08.14 |
[데이터분석] 데이터 크롤링 실습(1) (0) | 2024.08.14 |