Porfolio With Python 3

Updated:

Finance

1. 자산배분과 포트폴리오

  • 자산배분은 효율적 포트폴리오를 찾아내는 과정이다. 자산배분은 샤프의 CAPM 모델에 기초한다.
  • 수학/통계적인 방법으로 자산들을 분류하고 조합해 원하는 목적에 부합하는 자산군을 만들어내는 것이다.
  • 자산배분에는 리밸런싱 작업이 필요하다.
    적립식 펀드가 일반적으로 쉽게 이해할수 있는 리밸런싱이다. 정기적으로 리밸런싱을 하기도 하지만 시장 상황에 따라
    조정하는 동적자산배분 전략도 있다. 리밸런싱은 단순히 월마다 또는 분기마다 종목을 교체하는 것이 아니라 가격의 변동에
    따라 내재가치를 증가시켜나가는 작업이고, 이 과정에서 비중 조절이나 종목 교체도 일어난다.
  • 자산배분의 시작은 리스크가 없는 자산과 리스크가 있는 자산, 즉 위험자산과 무위험자산으로 분류하고
    좋은 위험자산 포트폴리오를 찾아내는 것이다.
    이런 노력의 결과로 찾아낸 가장 훌륭한 포트폴리오를 효율적 포트폴리오(efficient frontier)라고 부른다.

2. 포트폴리오 성과의 결정 요인들

  • 연구논문 Determinants of Portfolio Performance을 통해 1974년에서 1983년까지의 91개의 미국 대형연기금 데이터를 분석한 결과에 따르면,
    자산배분이 투자전략보다 중요하며 총수익률 변동성의 95.6%를 설명한다. 이 조사 결과는 종목선택과 마켓 타이밍을 사용한 투자전략이
    장기간에 걸쳐 반복적으로 성공하기 어렵다는 것이다.

3. 포트폴리오 성과 측정 삼총사

  • 포트폴리오(또는 펀드)를 평가하는 지표는 여러 가지가 있다.
    위험 관점에서 수익률의 표준편차는 총위험이나 변동성을 나타낸다. 펀드의 베타는 시장 대비 민감도를 나타낸다.
    표준편차나 베타 외에도 위험조정지표로 샤프지수, 트레이너지수, 젠센알파지수가 있다.
  • 샤프지수, 트레이너지수, 정보비율 등은 단위위험당 초과성과를 나타내는 위험조정성과지표이며,
    젠센알파는 초과성과를 보여주는 위험조정수익률을 나타낸다.

3.1 샤프지수

  • 노벨 경제학상 수상자인 윌리엄 샤프는 자본시장성(Capital Market Line, CML)의 원리를 이용해
    투자수익률 대 변동성 비율(reward to variability ration)로 포트폴리오 성과를 측정했다.
  • 지배원리에 따라 동일한 수익률에서 낮은 변동성 또는 동일한 변동성에서 높은 수익률을 가진 포트폴리오 또는
    펀드 상품이 비교우위를 가진다.
  • 샤프지수는 한 단위의 위험을 부담하는 대신 얻을 수 있는 수익률을 가리킨다.
    그러므로 샤프지수가 클수록 좋다고 볼 수 있다.
$샤프지수 = \frac{수익률-무위험수익률}{수익률의 표준편차}$

3.2 젠센알파지수

  • 마이클 젠센의 방법은 자본자산가격결정모델(CAPM)을 기반으로 하고 있다.
    젠센알파지수가 클수록 포트폴리오의 성과가 우수하며, 이는 종목 선택능력이 우수하다고 본다.
  • 젠센알파지수는 포트폴리오 수익률과 기대수익률의 차이를 나타내는 수치로, 시장 대비 얼마나 높은 성과를 냈는지 알 수 있다.
$젠센의 알파(\alpha) = 포트폴리오 수익률 - 기대(적정)수익률$
  • 포트폴리오 수익률에서 기대(적정)수익률을 제외하기 때문에 펀드 매니저의 종목 선정 능력을 확인할 수 있는 지표로 활용된다.
    기대수익률 또는 적정수익률로 삼을 수 있는 것이 시장수익률을 의미하는 벤치마크 수익률이다.

3.3 트레이너지수

  • 잭 트레이너는 CAPM 이론의 창시자 중 한 사람으로 인정받고 있지만, 퀀트 분석의 창시자 중 한사람이고,
    트레이너 비율(Treynor’s ratio)이 그의 대표작이다.
  • 트레이너 비율은 위험보상비율(reward-to-volatility ratio)로, 위험 한 단위를 받고 얻은 초과성과가 얼마인지를 측정하는 성과지표다.
    초과성과란 무위험수익률을 뛰어넘는 수익률을 말한다.
  • 트레이너 비율에서 위험은 포트폴리오 베타로 알려진 분산 불가능한 체계적 위험을 말한다.
    베타는 전체 시장수익률의 변화율 대비 포트폴리오 수익률 기울기로 측정된다.
  • 트레이너의 방법은 샤프의 방법과 동일하게 자본자산가격결정모델(CAPM)에 기반을 둔 방법이지만,
    총위험의 척도인 표준편차가 아니라 시장위험의 척도인 베타값을 사용하고 있다.
$트레이너지수(T) = \frac {포트폴리오 수익률(R_p) - 무위험수익률(R_f)}{포트폴리오 베타(\beta_P)}$
  • 트레이너지수 역시 값이 클수록 포트폴리오 성과가 우월함을 나타낸다.

3.4 정보비율

  • 정보비율은 트레이너와 블랙이 주장한 것으로, 투자자들이 수익률을 선호하고 위험을 회피한다는 가정하에
    위험을 고려해 적극적인 투자 성과를 평가하겠다는 목적을 갖고 있다.
  • 정보비율의 특징은 위험조정 후 수익률이 수익률의 변동 또는 분산 가능한 위험에 대한 노출로 달성된 것인지를 파악하고자 하는 데 있다.
  • 정보비율의 산출 방법은 두가지다.
    • 첫째, 벤치마크 수익률과 포트폴리오 수익률 간의 차이(추적오차(tracking error))를 이용하는 방법
      • 포트폴리오의 수익률이 벤치마크를 초과하는 수익률을 달성하는 것은 벤치마크보다 높은 위험을 부담한 결과라는 것을 의미한다.
    • 둘째, 벤치마크 수익률과 포트폴리오 수익률 간의 회귀분석(regression)을 이용하는 방법
      • 포트폴리오의 위험조정 후 수익률을 비체계적 위험으로 나눠 평가하고자 하는 척도다.
$정보비율(첫째) = \frac {포트폴리오 수익률 - 벤치마크 수익률}{표준편차}$
$정보비율(둘째) = \frac {젠센알파지수}{비체계적 위험(잔차의 표준편차)}$

3.5 최대 낙폭

  • 조금씩 수익을 내더라도 시장의 폭락으로 위험/손실관리를 못해서, 포트폴리오가 폭싹 망가져 청산하는 겨우도 생길 수 있다.
  • 최대 낙폭(Maximum Drawdown), 즉 MDD는 특정 투자 기간 중 포트폴리오의 고점에서 저점까지 최대 누적 손실을 의미한다.
  • 기존의 표준편차가 놓치기 쉬운 하락위험 및 연속손실위험을 잘 설명한다.
$MDD = \frac {기간 중 최저 가치 - 최고 가치}{최고 가치} = \frac {기간 중 최고 가치 - 최저 가치}{최고 가치}$
  • 다만, MDD가 자산가치 하락 빈도를 반영하지는 못한다. MDD는 자산가치 하락의 MDD를 알려주지만,
    자산가치의 대폭적인 하락 빈도를 알려주진 못한다. 또한, 자산가치의 회복 속도도 알려주지 못한다.
    다시 말해 자산가치가 무너지고 난 후 얼마나 빠른 시간 안에 이전 자산가치를 회복해 상승하는지는 표현하지 못한다.
# MDD를 계산해보자
# cummax라는 이름의 함수를 선언한다. 이 함수는 nums 매개변수를 받는다.
def cummax(nums):
    # 역대 최고값을 저장하기 위한 리스트 cum과 초기 최고값 max를 설정한다.
    cum = []
    max = 0
    """nums를 순회하면서 item을 현재 최고값과 비교한다.
    item > max이면 최고값 max를 업데이트한다. 
    그리고 if문의 결과와 상관없이 최고값을 cum에 추가한다."""
    for item in nums:
        if item > max:
            max = item
        cum.append(max)
    return cum

# 자산 A 가치를 리스트에 저장한다.
values = [200, 220, 230, 200, 165, 180, 200, 220, 240, 260]

# 자산 A 가치(values)에서 for 루프로 반복하면서 cummax()로 구한 최고값을 뺀다(x-y).
# 두 개의 변수를 묶어서(zip), 마치 하나의 변수처럼 사용하는 방법이다.
drawdown = [x - y for x, y in zip(values, cummax(values))]

# drawdown에서 최솟값이 저장된 인덱스를 구한다.
idx_lower = drawdown.index(min(drawdown))

# 자산 A 가치(values)의 인덱스 0부터 idx_lower까지 데이터 중 가장 큰 값이 저앚ㅇ된 위치를 구한다.
idx_upper = values.index(max(values[:idx_lower]))

# MDD 공식에 따라 계산해 출력한다.
print((values[idx_lower] - values[idx_upper]) / values[idx_upper])
-0.2826086956521739
# numpy를 이용하여 MDD를 계산해보자
import numpy as np

# mdd 함수는 x를 매개변수로 받아 numpy의 array 객체로 변환한다. 이후 계산할 값을 가진 인덱스를 찾아 MDD를 계산한다.
def mdd(x):
    arr = np.array(x)
    idx_lower = np.argmin(arr - np.maximum.accumulate(arr))
    idx_upper = np.argmax(arr[:idx_lower])
    return (arr[idx_lower] - arr[idx_upper]) / arr[idx_upper]

print(mdd(values))
-0.2826086956521739

Leave a comment