ai-hedge-fund 6) Portfolio Management Agent

Tasker_Jang·2025년 3월 18일
0

포트폴리오 관리 에이전트: AI 헤지펀드의 최종 의사결정권자

벤 그레이엄, 빌 액크만, 펀더멘털 에이전트 등의 분석 결과를 종합하여 실제 매매 결정을 내리는 이 에이전트는 AI 헤지펀드 시스템의 최종 실행 단계를 담당합니다.

포트폴리오 관리 에이전트의 역할

포트폴리오 관리 에이전트는 다음과 같은 중요한 역할을 수행합니다:

  1. 다양한 분석 에이전트들의 신호 통합
  2. 리스크 관리 제약 조건 적용
  3. 포트폴리오 현재 상태(현금, 포지션) 고려
  4. 최종 매매 결정(매수, 매도, 공매도, 커버, 홀드) 생성
  5. 매매 수량 결정

이 에이전트는 실질적으로 헤지펀드 매니저의 역할을 수행하며, 다양한 정보를 종합하여 최적의 투자 결정을 내립니다.

코드 구조 분석

먼저 이 에이전트가 사용하는 데이터 모델부터 살펴보겠습니다:

class PortfolioDecision(BaseModel):
    action: Literal["buy", "sell", "short", "cover", "hold"]
    quantity: int = Field(description="Number of shares to trade")
    confidence: float = Field(description="Confidence in the decision, between 0.0 and 100.0")
    reasoning: str = Field(description="Reasoning for the decision")


class PortfolioManagerOutput(BaseModel):
    decisions: dict[str, PortfolioDecision] = Field(description="Dictionary of ticker to trading decisions")
  • PortfolioDecision: 각 종목별 매매 결정(액션, 수량, 신뢰도, 근거)을 담는 모델
  • PortfolioManagerOutput: 전체 포트폴리오 결정을 담는 모델(모든 종목의 결정을 포함)

포트폴리오 관리 프로세스

포트폴리오 관리 에이전트는 다음과 같은 단계로 작동합니다:

  1. 데이터 준비:
# Get the portfolio and analyst signals
portfolio = state["data"]["portfolio"]
analyst_signals = state["data"]["analyst_signals"]
tickers = state["data"]["tickers"]

# Get position limits, current prices, and signals for every ticker
position_limits = {}
current_prices = {}
max_shares = {}
signals_by_ticker = {}
  1. 각 종목별 정보 수집:
for ticker in tickers:
    # Get position limits and current prices for the ticker
    risk_data = analyst_signals.get("risk_management_agent", {}).get(ticker, {})
    position_limits[ticker] = risk_data.get("remaining_position_limit", 0)
    current_prices[ticker] = risk_data.get("current_price", 0)

    # Calculate maximum shares allowed based on position limit and price
    if current_prices[ticker] > 0:
        max_shares[ticker] = int(position_limits[ticker] / current_prices[ticker])
    else:
        max_shares[ticker] = 0

    # Get signals for the ticker
    ticker_signals = {}
    for agent, signals in analyst_signals.items():
        if agent != "risk_management_agent" and ticker in signals:
            ticker_signals[agent] = {"signal": signals[ticker]["signal"], "confidence": signals[ticker]["confidence"]}
    signals_by_ticker[ticker] = ticker_signals
  1. 매매 결정 생성:
result = generate_trading_decision(
    tickers=tickers,
    signals_by_ticker=signals_by_ticker,
    current_prices=current_prices,
    max_shares=max_shares,
    portfolio=portfolio,
    model_name=state["metadata"]["model_name"],
    model_provider=state["metadata"]["model_provider"],
)
  1. 결과 처리 및 반환:
message = HumanMessage(
    content=json.dumps({ticker: decision.model_dump() for ticker, decision in result.decisions.items()}),
    name="portfolio_management",
)

# 필요시 결정 내용 표시
if state["metadata"]["show_reasoning"]:
    show_agent_reasoning({ticker: decision.model_dump() for ticker, decision in result.decisions.items()}, "Portfolio Management Agent")

매매 결정 생성 함수

가장 중요한 부분은 실제 매매 결정을 생성하는 generate_trading_decision 함수입니다:

def generate_trading_decision(
    tickers: list[str],
    signals_by_ticker: dict[str, dict],
    current_prices: dict[str, float],
    max_shares: dict[str, int],
    portfolio: dict[str, float],
    model_name: str,
    model_provider: str,
) -> PortfolioManagerOutput:
    """Attempts to get a decision from the LLM with retry logic"""
    # 프롬프트 템플릿 생성
    template = ChatPromptTemplate.from_messages([...])
    
    # 프롬프트 생성
    prompt = template.invoke({...})
    
    # LLM 호출 및 결과 반환
    return call_llm(
        prompt=prompt, 
        model_name=model_name, 
        model_provider=model_provider, 
        pydantic_model=PortfolioManagerOutput, 
        agent_name="portfolio_management_agent", 
        default_factory=create_default_portfolio_output
    )

이 함수는 LLM(대형 언어 모델)을 사용하여 다양한 신호와 제약 조건을 고려한 최종 매매 결정을 생성합니다.

매매 결정 프롬프트 분석

포트폴리오 관리 에이전트가 사용하는 프롬프트는 매우 상세하며 중요한 트레이딩 규칙을 포함하고 있습니다:

Trading Rules:
- For long positions:
  * Only buy if you have available cash
  * Only sell if you currently hold long shares of that ticker
  * Sell quantity must be ≤ current long position shares
  * Buy quantity must be ≤ max_shares for that ticker

- For short positions:
  * Only short if you have available margin (50% of position value required)
  * Only cover if you currently have short shares of that ticker
  * Cover quantity must be ≤ current short position shares
  * Short quantity must respect margin requirements

- The max_shares values are pre-calculated to respect position limits
- Consider both long and short opportunities based on signals
- Maintain appropriate risk management with both long and short exposure

Available Actions:
- "buy": Open or add to long position
- "sell": Close or reduce long position
- "short": Open or add to short position
- "cover": Close or reduce short position
- "hold": No action

이 규칙들은 실제 트레이딩 환경에서 반드시 지켜야 할 제약 조건들을 반영하고 있습니다:

  1. 롱 포지션(매수) 규칙:

    • 사용 가능한 현금이 있을 때만 매수
    • 현재 보유한 종목만 매도 가능
    • 매도 수량은 현재 보유 수량을 초과할 수 없음
    • 매수 수량은 최대 허용 수량을 초과할 수 없음
  2. 숏 포지션(공매도) 규칙:

    • 마진 요구사항을 충족할 때만 공매도 가능
    • 현재 공매도 중인 종목만 커버 가능
    • 커버 수량은 현재 공매도 수량을 초과할 수 없음
    • 공매도는 마진 요구사항을 고려해야 함
  3. 가능한 액션:

    • "buy": 롱 포지션 진입 또는 추가
    • "sell": 롱 포지션 청산 또는 축소
    • "short": 숏 포지션 진입 또는 추가
    • "cover": 숏 포지션 청산 또는 축소
    • "hold": 포지션 유지

실제 작동 방식

실제 매매 결정이 어떻게 이루어지는지 단계별로 살펴보겠습니다:

  1. 입력 데이터 수집:

    • 분석 에이전트들(벤 그레이엄, 빌 액크만, 펀더멘털 등)의 신호
    • 리스크 관리 에이전트의 포지션 한도 및 현재 가격
    • 포트폴리오 현황(현금, 보유 포지션)
  2. 종목별 제약 조건 계산:

    • 각 종목의 최대 매수 가능 수량 계산
    • 현재 가격과 포지션 한도 기반으로 계산
  3. LLM 기반 매매 결정:

    • 모든 신호와 제약 조건을 고려하여 최적의 매매 결정 생성
    • 각 종목별로 액션, 수량, 신뢰도, 근거 제공
  4. 결과 통합 및 반환:

    • 모든 종목의 매매 결정을 통합하여 최종 포트폴리오 결정 생성

매매 결정 예시

실제 매매 결정은 다음과 같은 형태로 생성됩니다:

{
  "decisions": {
    "AAPL": {
      "action": "buy",
      "quantity": 10,
      "confidence": 85.5,
      "reasoning": "Strong bullish signals from Warren Buffett and fundamental analysis agents, with high ROE and reasonable P/E ratio."
    },
    "MSFT": {
      "action": "hold",
      "quantity": 0,
      "confidence": 65.0,
      "reasoning": "Mixed signals with slightly bullish bias, but current position already at optimal level."
    },
    "NVDA": {
      "action": "sell",
      "quantity": 5,
      "confidence": 70.0,
      "reasoning": "Bearish signals from valuation agent indicating overvaluation. Reducing position while maintaining some exposure."
    }
  }
}

각 종목에 대해:

  • action: 취할 액션(buy, sell, short, cover, hold)
  • quantity: 거래할 주식 수량
  • confidence: 결정에 대한 신뢰도(0-100)
  • reasoning: 결정 근거

포트폴리오 관리 에이전트의 장단점

장점

  1. 종합적 판단: 다양한 분석 에이전트의 신호를 종합적으로 고려
  2. 리스크 관리: 포지션 한도 및 마진 요구사항 등 리스크 관리 규칙 준수
  3. 포트폴리오 상황 고려: 현재 보유 포지션, 사용 가능 현금 등을 고려한 현실적 결정
  4. 다양한 전략 지원: 롱 포지션과 숏 포지션을 모두 활용한 다양한 전략 구사 가능

단점

  1. LLM 의존성: 최종 결정이 LLM에 많이 의존하여 블랙박스적 요소 존재
  2. 확정적 규칙 부족: 매매 결정 규칙이 경험적이며 통계적 최적화가 부족
  3. 과거 성과 반영 미흡: 과거 매매 결정의 성과를 학습하여 개선하는 메커니즘 부족
  4. 복잡한 거래 전략 제한: 옵션, 선물 등 복잡한 파생상품 전략 미지원
profile
터널을 지나고 있을 뿐, 길은 여전히 열려 있다.

0개의 댓글

관련 채용 정보