랭귀지/python
재무제표 분석
유키공
2025. 8. 6. 21:17
import pandas as pd
import requests
def get_financial_statement(ticker):
"""
네이버 금융에서 손익계산서 데이터를 가져오는 함수
"""
url = f'https://finance.naver.com/item/main.naver?code={ticker}'
try:
tables = pd.read_html(url, encoding='euc-kr')
except:
return None
for table in tables:
if table.shape[1] >= 3 and '매출액' in table.iloc[:, 0].values:
return table
return None
def clean_financial_df(df):
"""
데이터프레임 전처리: 인덱싱, 숫자 변환, 결측치 처리 등
"""
df.set_index(df.columns[0], inplace=True)
df = df.replace('-', '0') # 결측치는 0으로
df = df.applymap(lambda x: int(str(x).replace(',', '')) if isinstance(x, str) else x)
return df
def analyze_financials(df):
"""
주요 지표 분석 및 해석 제공
"""
analysis = {}
try:
df_cleaned = clean_financial_df(df)
# 컬럼(연도 또는 분기) 자동 탐지
latest = df_cleaned.columns[-1]
prev = df_cleaned.columns[-2]
# 유연한 행 이름 처리 (예: '영업이익(손실)', '당기순이익(손실)')
def get_row_name(df, candidates):
for candidate in candidates:
if candidate in df.index:
return candidate
raise ValueError(f"다음 항목을 찾을 수 없습니다: {candidates}")
row_매출 = get_row_name(df_cleaned, ['매출액'])
row_영업이익 = get_row_name(df_cleaned, ['영업이익', '영업이익(손실)'])
row_순이익 = get_row_name(df_cleaned, ['당기순이익', '당기순이익(손실)'])
# 주요 지표 추출
revenue_now = df_cleaned.loc[row_매출, latest]
revenue_prev = df_cleaned.loc[row_매출, prev]
op_now = df_cleaned.loc[row_영업이익, latest]
op_prev = df_cleaned.loc[row_영업이익, prev]
net_now = df_cleaned.loc[row_순이익, latest]
net_prev = df_cleaned.loc[row_순이익, prev]
# 증가 여부 판단
analysis['매출액 증가 여부'] = '📈 증가' if revenue_now > revenue_prev else '📉 감소'
analysis['영업이익 증가 여부'] = '📈 증가' if op_now > op_prev else '📉 감소'
analysis['당기순이익 증가 여부'] = '📈 증가' if net_now > net_prev else '📉 감소'
# 증가율(%) 계산
def calc_rate(now, prev):
try:
if prev == 0:
return "N/A"
return f"{((now - prev) / abs(prev)) * 100:.2f}%"
except:
return "N/A"
analysis['매출액 증가율'] = calc_rate(revenue_now, revenue_prev)
analysis['영업이익 증가율'] = calc_rate(op_now, op_prev)
analysis['당기순이익 증가율'] = calc_rate(net_now, net_prev)
# 영업이익률
if revenue_now != 0:
op_margin = op_now / revenue_now * 100
analysis['영업이익률'] = f"{op_margin:.2f}%"
if op_margin >= 10:
analysis['영업이익률 평가'] = '✅ 우수'
elif op_margin >= 5:
analysis['영업이익률 평가'] = '⚠️ 보통'
else:
analysis['영업이익률 평가'] = '❌ 낮음'
else:
analysis['영업이익률'] = "N/A"
# 연간/분기 추정 힌트
if any("년" in str(col) for col in df.columns):
analysis['데이터 유형'] = '📅 연간 실적'
else:
analysis['데이터 유형'] = '📆 분기 실적 (추정)'
except Exception as e:
analysis['에러'] = f"⚠️ 분석 실패: {str(e)}"
return analysis
def print_analysis(ticker):
print(f"[{ticker}] 재무 분석 요약")
df = get_financial_statement(ticker)
if df is None:
print("❌ 재무제표 데이터 로딩 실패 또는 해당 종목 없음")
return
result = analyze_financials(df)
for k, v in result.items():
print(f"{k}: {v}")
# 예시 실행: 삼성전자(005930)
if __name__ == "__main__":
print_analysis("005930") # 원하는 종목 코드 입력