PyPortfolioOpt هي مكتبة تطبق أساليب تحسين المحفظة، بما في ذلك تقنيات تحسين متوسط التباين الكلاسيكية وتخصيص Black-Litterman، بالإضافة إلى التطورات الحديثة في هذا المجال مثل الانكماش وتكافؤ المخاطر الهرمي.
إنها واسعة النطاق ولكنها قابلة للتوسيع بسهولة، ويمكن أن تكون مفيدة للمستثمرين العاديين، أو المحترفين الذين يبحثون عن أداة نماذج أولية سهلة. سواء كنت مستثمرًا موجهًا نحو الأساسيات وقد حدد مجموعة من الاختيارات المقومة بأقل من قيمتها، أو متداولًا خوارزميًا لديه سلة من الاستراتيجيات، يمكن أن تساعدك PyPortfolioOpt على الجمع بين مصادر ألفا الخاصة بك بطريقة فعالة من حيث المخاطر.
تم نشر PyPortfolioOpt في مجلة البرمجيات مفتوحة المصدر؟
تتم الآن صيانة 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 طريقة تسمح لك بتحويل الأوزان المستمرة المذكورة أعلاه إلى تخصيص فعلي يمكنك شراؤه. ما عليك سوى إدخال أحدث الأسعار وحجم المحفظة المطلوبة (10000 دولار في هذا المثال):
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
إخلاء المسؤولية: لا يوجد شيء في هذا المشروع يشكل نصيحة استثمارية، ولا يتحمل المؤلف أي مسؤولية عن قراراتك الاستثمارية اللاحقة. يرجى الرجوع إلى الترخيص لمزيد من المعلومات.
تعتبر ورقة هاري ماركويتز عام 1952 هي الورقة الكلاسيكية التي لا يمكن إنكارها، والتي حولت تحسين المحفظة من فن إلى علم. الفكرة الرئيسية هنا هي أنه من خلال الجمع بين الأصول ذات العوائد والتقلبات المتوقعة المختلفة، يمكن للمرء أن يقرر التخصيص الأمثل رياضياً والذي يقلل من مخاطر العائد المستهدف - ويشار إلى مجموعة كل هذه المحافظ المثالية باسم الحدود الفعالة .
على الرغم من حدوث الكثير من التطوير في هذا الموضوع، إلا أنه بعد مرور أكثر من نصف قرن، لا تزال أفكار ماركويتز الأساسية ذات أهمية أساسية وترى الاستخدام اليومي في العديد من شركات إدارة المحافظ. العيب الرئيسي لتحسين متوسط التباين هو أن المعالجة النظرية تتطلب معرفة العوائد المتوقعة وخصائص المخاطر المستقبلية (التباين) للأصول. من الواضح أننا إذا علمنا أن العوائد المتوقعة لحياة الأسهم ستكون أسهل بكثير، ولكن اللعبة بأكملها هي أن عوائد الأسهم من الصعب التنبؤ بها. وكبديل، يمكننا استخلاص تقديرات للعائد المتوقع والتباين المشترك استنادا إلى البيانات التاريخية ــ ورغم أننا نفقد الضمانات النظرية التي يقدمها ماركويتز، فكلما اقتربت تقديراتنا من القيم الحقيقية، كلما كانت محفظتنا الاستثمارية أفضل.
وبالتالي يوفر هذا المشروع أربع مجموعات رئيسية من الوظائف (على الرغم من أنها مرتبطة ارتباطًا وثيقًا بالطبع)
أحد أهداف التصميم الرئيسية لـ 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 خيارًا لتشكيل محفظة محايدة للسوق (أي مجموع الأوزان يساوي الصفر). هذا غير ممكن بالنسبة لمحفظة Max 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 ))
إحدى المشكلات المتعلقة بتحسين متوسط التباين هي أنه يؤدي إلى العديد من الأوزان الصفرية. في حين أن هذه هي "الأمثل" في العينة، إلا أن هناك مجموعة كبيرة من الأبحاث التي تبين أن هذه الخاصية تؤدي إلى انخفاض أداء المحافظ ذات التباين المتوسط خارج العينة. ولتحقيق هذه الغاية، قدمت وظيفة موضوعية يمكنها تقليل عدد الأوزان التي لا تذكر لأي من الوظائف الموضوعية. بشكل أساسي، يضيف عقوبة (محددة بواسطة gamma
) على الأوزان الصغيرة، بمصطلح يشبه تمامًا تنظيم L2 في التعلم الآلي. قد يكون من الضروري تجربة عدة قيم gamma
لتحقيق العدد المطلوب من الأوزان التي لا يمكن إهمالها. بالنسبة لمحفظة الاختبار المكونة من 20 ورقة مالية، فإن gamma ~ 1
كافية
ef = EfficientFrontier ( mu , S )
ef . add_objective ( objective_functions . L2_reg , gamma = 1 )
ef . max_sharpe ()
اعتبارًا من الإصدار 0.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 ()
تتعلق الميزات المذكورة أعلاه في الغالب بحل مشكلات تحسين متوسط التباين عبر البرمجة التربيعية (على الرغم من أن 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 }
}
المساهمات هي موضع ترحيب كبير . قم بإلقاء نظرة على دليل المساهمة للمزيد.
أود أن أشكر جميع الأشخاص الذين ساهموا في PyPortfolioOpt منذ صدوره في عام 2018. تحية خاصة إلى: