PyPortfolioOpt는 고전적인 평균 분산 최적화 기술 및 Black-Litterman 할당뿐만 아니라 축소 및 계층적 위험 패리티와 같은 분야의 최신 개발을 포함한 포트폴리오 최적화 방법을 구현하는 라이브러리입니다.
광범위 하면서도 쉽게 확장할 수 있으며, 일반 투자자나 쉬운 프로토타이핑 도구를 찾는 전문가에게 유용할 수 있습니다. 소수의 저평가된 종목을 식별한 펀더멘털 중심의 투자자이든, 다양한 전략을 보유한 알고리즘 트레이더이든, PyPortfolioOpt는 위험 효율적인 방식으로 알파 소스를 결합하는 데 도움을 줄 수 있습니다.
PyPortfolioOpt는 Journal of Open Source Software에 게재되었습니다.
PyPortfolioOpt는 현재 Tuan Tran이 관리하고 있습니다.
ReadTheDocs의 문서 로 이동하여 프로젝트를 심층적으로 살펴보거나 요리책을 확인하여 데이터 다운로드부터 포트폴리오 구축까지 전체 프로세스를 보여주는 몇 가지 예를 확인하세요.
브라우저에서 PyPortfolioOpt를 대화식으로 사용하려면 여기에서 Binder를 시작할 수 있습니다. 설정하는 데 시간이 좀 걸리지만 모든 요구 사항을 처리하지 않고도 요리책 레시피를 시험해 볼 수 있습니다.
참고: macOS 사용자는 명령줄 도구를 설치해야 합니다.
참고: Windows를 사용하는 경우 먼저 C++를 설치해야 합니다. (다운로드, 설치 지침)
이 프로젝트는 PyPI에서 사용할 수 있습니다. 즉, 다음을 수행할 수 있습니다.
pip install PyPortfolioOpt
(cvxopt 및 cvxpy에 대해 별도의 설치 지침을 따라야 할 수도 있습니다).
그러나 가상 환경 내에서는 종속성 관리자를 사용하는 것이 가장 좋습니다. 나의 현재 권장 사항은 시로 설정한 다음 실행하는 것입니다.
poetry add PyPortfolioOpt
그렇지 않으면 프로젝트를 복제/다운로드하고 프로젝트 디렉터리에서 다음을 실행합니다.
python setup.py install
PyPortfolioOpt는 Docker를 지원합니다. docker build -f docker/Dockerfile . -t pypfopt
. 이미지를 사용하여 테스트를 실행하거나 Jupyter 서버를 시작할 수도 있습니다.
# iPython interpreter:
docker run -it pypfopt poetry run ipython
# Jupyter notebook server:
docker run -it -p 8888:8888 pypfopt poetry run jupyter notebook --allow-root --no-browser --ip 0.0.0.0
# click on http://127.0.0.1:8888/?token=xxx
# Pytest
docker run -t pypfopt poetry run pytest
# Bash
docker run -it pypfopt bash
자세한 내용은 이 가이드를 읽어보세요.
이를 독점 시스템과 통합하기 위해 주요 변경을 수행하려면 이 저장소를 복제하고 소스 코드만 사용하는 것이 합리적일 것입니다.
git clone https://github.com/robertmartin8/PyPortfolioOpt
또는 다음을 시도해 볼 수도 있습니다.
pip install -e git+https://github.com/robertmartin8/PyPortfolioOpt.git
다음은 실제 주식 데이터에 대한 예로서, 샤프 비율(위험 조정 수익률의 척도)을 최대화하는 장기 포트폴리오를 찾는 것이 얼마나 쉬운지 보여줍니다.
import pandas as pd
from pypfopt import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
# Read in price data
df = pd . read_csv ( "tests/resources/stock_prices.csv" , parse_dates = True , index_col = "date" )
# Calculate expected returns and sample covariance
mu = expected_returns . mean_historical_return ( df )
S = risk_models . sample_cov ( df )
# Optimize for maximal Sharpe ratio
ef = EfficientFrontier ( mu , S )
raw_weights = ef . max_sharpe ()
cleaned_weights = ef . clean_weights ()
ef . save_weights_to_file ( "weights.csv" ) # saves to file
print ( cleaned_weights )
ef . portfolio_performance ( verbose = True )
그러면 다음과 같은 가중치가 출력됩니다.
{'GOOG': 0.03835,
'AAPL': 0.0689,
'FB': 0.20603,
'BABA': 0.07315,
'AMZN': 0.04033,
'GE': 0.0,
'AMD': 0.0,
'WMT': 0.0,
'BAC': 0.0,
'GM': 0.0,
'T': 0.0,
'UAA': 0.0,
'SHLD': 0.0,
'XOM': 0.0,
'RRC': 0.0,
'BBY': 0.01324,
'MA': 0.35349,
'PFE': 0.1957,
'JPM': 0.0,
'SBUX': 0.01082}
Expected annual return: 30.5%
Annual volatility: 22.2%
Sharpe Ratio: 1.28
이것은 흥미롭지만 그 자체로는 유용하지 않습니다. 그러나 PyPortfolioOpt는 위의 연속 가중치를 구매할 수 있는 실제 할당으로 변환할 수 있는 방법을 제공합니다. 가장 최근 가격과 원하는 포트폴리오 규모(이 예에서는 $10,000)를 입력하세요.
from pypfopt . discrete_allocation import DiscreteAllocation , get_latest_prices
latest_prices = get_latest_prices ( df )
da = DiscreteAllocation ( weights , latest_prices , total_portfolio_value = 10000 )
allocation , leftover = da . greedy_portfolio ()
print ( "Discrete allocation:" , allocation )
print ( "Funds remaining: ${:.2f}" . format ( leftover ))
12 out of 20 tickers were removed
Discrete allocation: {'GOOG': 1, 'AAPL': 4, 'FB': 12, 'BABA': 4, 'BBY': 2,
'MA': 20, 'PFE': 54, 'SBUX': 1}
Funds remaining: $ 11.89
면책조항: 이 프로젝트에 관한 어떠한 내용도 투자 조언을 구성하지 않으며, 저자는 귀하의 후속 투자 결정에 대해 어떠한 책임도 지지 않습니다. 자세한 내용은 라이센스를 참조하십시오.
Harry Markowitz의 1952년 논문은 포트폴리오 최적화를 예술에서 과학으로 전환시킨 부인할 수 없는 고전입니다. 핵심 통찰력은 서로 다른 기대 수익률과 변동성을 지닌 자산을 결합함으로써 목표 수익률에 대한 위험을 최소화하는 수학적으로 최적의 배분을 결정할 수 있다는 것입니다. 이러한 모든 최적 포트폴리오 세트를 효율적 프론티어 라고 합니다.
이 주제에 대해 많은 발전이 이루어졌지만 반세기 이상이 지난 후에도 Markowitz의 핵심 아이디어는 여전히 근본적으로 중요하며 많은 포트폴리오 관리 회사에서 매일 사용됩니다. 평균-분산 최적화의 주요 단점은 이론적 처리에 자산의 예상 수익과 미래 위험 특성(공분산)에 대한 지식이 필요하다는 것입니다. 분명히, 주식 생활의 기대 수익률을 안다면 훨씬 쉬울 것입니다. 그러나 전체 게임에서 주식 수익률은 예측하기가 매우 어렵습니다. 대안으로, 과거 데이터를 기반으로 기대 수익률과 공분산에 대한 추정치를 도출할 수 있습니다. 비록 Markowitz가 제공한 이론적 보장은 상실하지만 추정치가 실제 가치에 가까울수록 포트폴리오는 더 좋아질 것입니다.
따라서 이 프로젝트는 네 가지 주요 기능 세트를 제공합니다(물론 서로 밀접하게 관련되어 있음).
PyPortfolioOpt의 주요 디자인 목표는 모듈성 입니다. 사용자는 PyPortfolioOpt가 제공하는 프레임워크를 계속 사용하면서 구성 요소를 교체할 수 있어야 합니다.
이 섹션에서는 PyPortfolioOpt의 사용 가능한 기능 중 일부를 자세히 설명합니다. 여기 Jupyter 노트북에서 더 많은 예제가 제공됩니다. 또 다른 좋은 자원은 테스트입니다.
이에 대한 훨씬 더 포괄적인 버전은 ReadTheDocs에서 찾을 수 있을 뿐만 아니라 고급 사용자를 위한 가능한 확장도 있습니다.
공분산 행렬은 자산의 변동성뿐만 아니라 다른 자산과의 상관관계도 인코딩합니다. 이는 다각화의 이점을 누리고(따라서 단위 위험당 수익률을 높이려면) 포트폴리오의 자산이 가능한 한 상관관계가 없어야 하기 때문에 중요합니다.
sklearn.covariance
가 제공하는 효율적인 벡터화 구현에 대한 래퍼를 제공합니다.constant_variance
, single_factor
및 constant_correlation
제공합니다.sklearn.covariance
에서 구현됨 (이 플롯은 plotting.plot_covariance
를 사용하여 생성되었습니다)
ef = EfficientFrontier ( mu , S , weight_bounds = ( - 1 , 1 ))
efficient_risk
및 efficient_return
방법의 경우 PyPortfolioOpt는 시장 중립 포트폴리오를 구성하는 옵션을 제공합니다(즉, 가중치 합계가 0이 됩니다). 최대 Sharpe 포트폴리오와 최소 변동성 포트폴리오에서는 레버리지에 대해 불변하지 않기 때문에 이는 불가능합니다. 시장 중립성을 위해서는 음의 가중치가 필요합니다. ef = EfficientFrontier ( mu , S , weight_bounds = ( - 1 , 1 ))
ef . efficient_return ( target_return = 0.2 , market_neutral = True )
ef = EfficientFrontier ( mu , S , weight_bounds = ( 0 , 0.1 ))
평균 분산 최적화의 한 가지 문제는 많은 0 가중치가 발생한다는 것입니다. 이는 표본 내에서는 "최적"이지만, 이러한 특성으로 인해 평균 분산 포트폴리오가 표본 외 성과가 저조하다는 사실을 보여주는 많은 연구가 있습니다. 이를 위해 목적 함수에 대해 무시할 수 있는 가중치의 수를 줄일 수 있는 목적 함수를 도입했습니다. 본질적으로 기계 학습의 L2 정규화와 유사한 용어를 사용하여 작은 가중치에 페널티( gamma
로 매개변수화됨)를 추가합니다. 무시할 수 없는 가중치의 원하는 수를 달성하려면 여러 gamma
값을 시도해야 할 수도 있습니다. 20개 증권으로 구성된 테스트 포트폴리오의 경우 gamma ~ 1
이면 충분합니다.
ef = EfficientFrontier ( mu , S )
ef . add_objective ( objective_functions . L2_reg , gamma = 1 )
ef . max_sharpe ()
v0.5.0부터 우리는 Black-Litterman 자산 배분을 지원합니다. 이를 통해 사전 수익 추정치(예: 시장 내재 수익)와 자신의 견해를 결합하여 사후 추정치를 구성할 수 있습니다. 이는 평균 역사적 수익률을 사용하는 것보다 훨씬 더 나은 기대 수익률 추정치를 제공합니다. 이론에 대한 토론과 입력 형식 지정에 대한 조언은 문서를 확인하세요.
S = risk_models . sample_cov ( df )
viewdict = { "AAPL" : 0.20 , "BBY" : - 0.30 , "BAC" : 0 , "SBUX" : - 0.2 , "T" : 0.131321 }
bl = BlackLittermanModel ( S , pi = "equal" , absolute_views = viewdict , omega = "default" )
rets = bl . bl_returns ()
ef = EfficientFrontier ( rets , S )
ef . max_sharpe ()
위의 기능은 주로 2차 프로그래밍을 통해 평균-분산 최적화 문제를 해결하는 것과 관련이 있습니다(이는 cvxpy
에서 처리되지만). 그러나 우리는 다양한 최적화 프로그램도 제공합니다:
자세한 내용은 설명서를 참조하세요.
테스트는 pytest로 작성되었으며(내 의견으로는 unittest
및 변형보다 훨씬 직관적임) 거의 100% 적용 범위를 보장하려고 노력했습니다. 패키지 디렉터리로 이동하고 명령줄에서 pytest
실행하여 테스트를 실행하세요.
PyPortfolioOpt는 20개의 티커에 대한 일일 수익률 테스트 데이터 세트를 제공합니다.
[ 'GOOG' , 'AAPL' , 'FB' , 'BABA' , 'AMZN' , 'GE' , 'AMD' , 'WMT' , 'BAC' , 'GM' ,
'T' , 'UAA' , 'SHLD' , 'XOM' , 'RRC' , 'BBY' , 'MA' , 'PFE' , 'JPM' , 'SBUX' ]
이 티커는 여러 기준을 충족하기 위해 비공식적으로 선택되었습니다.
현재 테스트에서는 모든 엣지 케이스와 목적 함수 및 매개변수의 조합을 탐색하지 않았습니다. 그러나 각 방법과 매개변수는 의도한 대로 작동하도록 테스트되었습니다.
출판된 작업에 PyPortfolioOpt를 사용하는 경우 JOSS 논문을 인용해 주세요.
인용 문자열:
Martin, R. A., (2021). PyPortfolioOpt: portfolio optimization in Python. Journal of Open Source Software, 6(61), 3066, https://doi.org/10.21105/joss.03066
빕텍스::
@article { Martin2021 ,
doi = { 10.21105/joss.03066 } ,
url = { https://doi.org/10.21105/joss.03066 } ,
year = { 2021 } ,
publisher = { The Open Journal } ,
volume = { 6 } ,
number = { 61 } ,
pages = { 3066 } ,
author = { Robert Andrew Martin } ,
title = { PyPortfolioOpt: portfolio optimization in Python } ,
journal = { Journal of Open Source Software }
}
기여를 환영합니다 . 자세한 내용은 기여 가이드를 살펴보세요.
2018년 출시 이후 PyPortfolioOpt에 기여해 주신 모든 분들께 감사의 말씀을 전하고 싶습니다. 특별히 감사드립니다.