Alpha Vantage API에서 미국 주식 분석기 만들기 11)

Tasker_Jang·2025년 6월 9일
0

"AAPL의 ROE가 138%라고? 이게 좋은 건지 나쁜 건지 어떻게 알지?"

재무제표를 보면서 한 번쯤 이런 생각 해보셨을겁니다. 🤔

🎯 왜 점수화 시스템이 필요할까?

기존 재무분석의 한계점

# 기존 방식: 단순한 지표 나열
ROE: 138.50%
ROA: 22.61% 
Operating Margin: 30.29%
Current Ratio: 0.87
Debt-to-Equity: 5.41

# 🤷‍♂️ 이게... 좋은 건가요? 나쁜 건가요?

문제점들:

  • 지표가 좋은지 나쁜지 판단하기 어려움
  • 종합적인 평가 없이 개별 지표만 나열
  • 투자 의사결정을 위한 명확한 가이드라인 부족

💡 해결 방안: 간단하고 실용적인 점수화 시스템

설계 원칙

  1. 단순하고 명확한 기준: 복잡한 업종별 구분 없이 일반적 기준 적용
  2. 가중치 기반 종합 점수: 수익성(60%) + 안정성(40%)
  3. 직관적 점수: 100점 만점 + A+~D 등급
  4. 기존 시스템과 완벽 호환: 상세 분석은 그대로, 점수만 추가

1단계: 간단한 점수화 클래스 설계

class FinancialScoringSystem:
    """간단하고 실용적인 재무 점수화 시스템"""
    
    def extract_number(self, text: str) -> Optional[float]:
        """텍스트에서 숫자 추출 (% 기호 및 기타 문자 제거)"""
        if not text or text == "No data":
            return None
        
        # % 기호, 쉼표 제거하고 숫자만 추출
        cleaned_text = str(text).replace('%', '').replace(',', '').strip()
        match = re.search(r'(-?\d+\.?\d*)', cleaned_text)
        
        return float(match.group(1)) if match else None

핵심 전략:

  • 복잡한 업종별 구분 없이 일반적 기준 사용
  • 기존 분석 결과에서 숫자만 추출하여 점수화
  • 에러 발생해도 기존 분석에 영향 없음

2단계: 실용적인 점수 기준 설정

def _score_roe(self, roe: Optional[float]) -> int:
    """ROE 점수 계산 (0-100점)"""
    if roe is None: return 0
    
    if roe >= 20: return 100      # 20% 이상 = 최고 수준
    elif roe >= 15: return 85     # 15% 이상 = 우수
    elif roe >= 10: return 70     # 10% 이상 = 양호
    elif roe >= 5: return 40      # 5% 이상 = 보통
    else: return 25               # 5% 미만 = 미흡

def _score_debt_to_equity(self, ratio: Optional[float]) -> int:
    """부채비율 점수 (낮을수록 좋음)"""
    if ratio is None: return 0
    
    if ratio <= 0.3: return 100   # 0.3 이하 = 매우 안전
    elif ratio <= 0.5: return 85  # 0.5 이하 = 안전
    elif ratio <= 0.8: return 70  # 0.8 이하 = 양호
    elif ratio <= 1.2: return 50  # 1.2 이하 = 보통
    else: return 25               # 1.2 초과 = 주의

간단한 구간별 점수:

  • 복잡한 선형 보간 대신 명확한 구간별 점수
  • 일반적으로 알려진 재무 기준 활용
  • 이해하기 쉽고 설명하기 쉬움

3단계: 기존 시스템에 최소한의 통합

# analyze_financial_data 함수 끝에 3줄만 추가
def analyze_financial_data(api_wrapper, data: dict) -> dict:
    # ... 기존 모든 분석 코드 (그대로 유지) ...
    analysis = calculate_overall_stability_assessment(analysis)
    
    # ===== 점수화 시스템 추가 (3줄!) =====
    try:
        scoring_system = FinancialScoringSystem()
        financial_scores = scoring_system.calculate_financial_scores(analysis)
        analysis['financial_scores'] = financial_scores
    except Exception as e:
        analysis['financial_scores'] = {'overall_score': 0, 'overall_grade': 'N/A'}
    
    return analysis

통합 전략:

  • 기존 코드 99% 그대로 유지
  • 점수 계산 실패해도 기존 분석은 정상 동작
  • 점진적 개선 가능

4단계: 포매터에 점수 섹션 추가

def format_financial_analysis(analysis_data: Dict) -> str:
    # ... 기존 헤더 코드 ...
    
    # ===== 점수 섹션만 상단에 추가 =====
    financial_scores = analysis.get("financial_scores", {})
    
    if financial_scores and financial_scores.get('overall_score', 0) > 0:
        score_section = f"""
## 📊 **재무 건전성 종합 점수**

### 💯 **전체 평가**
- **종합 점수**: {financial_scores['overall_score']}/100점 ({financial_scores['overall_grade']})
- 🔥 **수익성**: {financial_scores['profitability_score']}/100점 ({financial_scores['profitability_grade']})
- 🛡️ **안정성**: {financial_scores['stability_score']}/100점 ({financial_scores['stability_grade']})
"""
        output.append(score_section)
    
    # ... 기존 상세 분석 코드는 완전히 그대로 ...
    return "\n".join(output)

📊 실제 구현 결과

Apple (AAPL) 분석 결과

## 📊 전체 평가 점수
- **종합 점수: 65/100점 (B)**
- **수익성 점수: 100/100점 (A+)**
- **안정성 점수: 13/100점 (D)**

## 1. 수익성 분석 (Profitability)
- **ROE (자기자본이익률): 138.0%** | 점수: 100/100 (A+)
- **ROA (총자산이익률): 23.8%** | 점수: 100/100 (A+)
- **영업이익률: 31.51%** | 점수: 100/100 (A+)

## 2. 재무 안정성 분석 (Stability)
- **유동비율: 0.87** | 점수: 15/100 (D)
- **부채비율: 5.41** | 점수: 10/100 (D)

> **해설:** 애플은 수익성은 최고 수준이지만, 
> 유동성과 부채 관리에서 우려점이 있어 종합 65점을 받았습니다.

핵심 인사이트:

  • 수익성 100점 = 모든 수익성 지표가 최고 수준
  • 안정성 13점 = 단기 유동성과 높은 부채비율 우려
  • 종합 65점 = "신중한 검토 필요" 수준

🛠️ 기술적 구현의 핵심

1. 기존 텍스트에서 숫자 추출

문제: 이미 포맷된 분석 텍스트에서 점수 계산용 숫자 추출

# 다양한 형태의 기존 분석 텍스트
"ROE: 138.50%"
"Current Ratio: 0.87" 
"Debt-to-Equity: 5.41"

해결:

def extract_number(self, text: str) -> Optional[float]:
    """간단하고 안정적인 숫자 추출"""
    if not text or text == "No data":
        return None
    
    # % 기호, 쉼표 제거 후 첫 번째 숫자 추출
    cleaned = str(text).replace('%', '').replace(',', '')
    match = re.search(r'(-?\d+\.?\d*)', cleaned)
    return float(match.group(1)) if match else None

2. 에러 처리로 안정성 보장

try:
    scoring_system = FinancialScoringSystem()
    scores = scoring_system.calculate_financial_scores(analysis)
    analysis['financial_scores'] = scores
except Exception as e:
    # 점수 계산 실패해도 기존 분석은 정상 동작
    analysis['financial_scores'] = {
        'overall_score': 0, 
        'overall_grade': 'N/A',
        'error': str(e)
    }

핵심 설계 철학:

  • 점수 시스템은 "보너스" 기능
  • 실패해도 기존 상세 분석에 영향 없음
  • 점진적 개선과 안정성 보장

3. 프롬프트 업데이트

system_prompt = (
    "You are a financial statement analysis agent for US stocks. "
    "The analysis includes a comprehensive financial scoring system (0-100 points). "
    "You MUST prominently display the financial scores: "
    "- Total Score: X/100 points (Grade) "
    "- Profitability Score: X/100 points (Grade) "
    "- Stability Score: X/100 points (Grade) "
    "- Individual metric scores (ROE, ROA, Operating Margin, Current Ratio, Debt-to-Equity) "
    "Always highlight the overall financial score prominently in your response."
)

💡 향후 개선 방향

1. 동종업계 상대 순위

# 현재: 절대 점수
apple_score = 65

# 목표: 상대 순위
tech_companies = get_tech_companies()
apple_rank = calculate_rank(apple_score, tech_companies)
# "Technology 섹터 500개 기업 중 156위 (상위 31%)"

🎉 마무리

복잡한 재무분석을 65점 (B등급)이라는 직관적인 형태로 요약할 수 있게 되었습니다.

핵심 성과:

  • ✅ 기존 상세 분석 100% 보존
  • ✅ 직관적인 점수 시스템 추가
  • ✅ 최소한의 코드 변경 (3줄!)
  • ✅ 안정적인 에러 처리
  • ✅ 실제 투자 의사결정에 도움

이제 "AAPL이 투자하기 좋은 회사인가?"라는 질문에 "65점이니까 신중하게 검토해보세요"라고 명확하게 답할 수 있습니다! 🚀

실제 결과물:

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글