نظرية محفظة ماركويتز للعملات المشفرة: من الصفر إلى الاحتراف
بناء محافظ عملات مشفرة مثالية باستخدام Python — لأن YOLO ليست استراتيجية
نظرية محفظة ماركويتز: التحسين الرياضي المطبّق على الأصول الرقمية لتعظيم العوائد عند مستوى مخاطر معين.
المقدمة: لماذا تحتاج محفظة العملات المشفرة إلى الرياضيات (وليس مجرد حدس)
مرحباً يا عشاق العملات المشفرة! 👋
هل تتذكر تلك المرة التي ألقيت فيها كل أموالك في DOGE لأن إيلون غرّد؟ أو عندما بعت كل شيء في حالة ذعر أثناء آخر انهيار؟ نعم، كلنا مررنا بذلك. اليوم سنتحدث عن شيء قد ينقذ محفظتك (وصحتك النفسية): نظرية محفظة ماركويتز.
حصل هاري ماركويتز على جائزة نوبل لهذا العمل في عام 1990. الفكرة الأساسية؟ يمكنك تحسين محفظتك رياضياً للحصول على أفضل عوائد ممكنة لأي مستوى من المخاطر. إنه مثل امتلاك GPS لاستثماراتك بدلاً من القيادة معصوب العينين.
المفهوم الأساسي: المخاطر مقابل العائد (الرقصة الأبدية)
قبل الغوص في الكود، لنفهم ما نتعامل معه:
- العائد المتوقع: كم من المال تتوقع أن تربح
- المخاطر (التقلب): مقدار تذبذب قيمة محفظتك
- الارتباط: مدى تشابه حركة الأصول المختلفة معاً
يحدث السحر عندما تجمع أصولاً لا تتحرك بتزامن مثالي. عندما ينهار البيتكوين، ربما تصمد بعض رموز DeFi بشكل أفضل. هذا هو التنويع يعمل لصالحك.
المخاطر مقابل العائد: موازنة الأصول عالية التقلب والعائد مع أساس مستقر لتحقيق العائد الهندسي الأمثل.
إعداد بيئة Python
أولاً وقبل كل شيء، لنجهّز أدواتنا:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.optimize import minimize
import yfinance as yf
import warnings
warnings.filterwarnings('ignore')
plt.style.use('dark_background')
sns.set_palette("husl")
المستوى 1: الخطوات الأولى — رياضيات محفظة بسيطة
لنبدأ بالأساسيات. سنحسب العوائد والمخاطر لمحفظة بسيطة من أصلين.
def get_crypto_data(symbols, period="1y"):
"""
Fetch crypto data from Yahoo Finance
symbols: list of crypto symbols (e.g., ['BTC-USD', 'ETH-USD'])
period: time period for data
"""
data = yf.download(symbols, period=period)['Adj Close']
return data
crypto_symbols = ['BTC-USD', 'ETH-USD']
prices = get_crypto_data(crypto_symbols)
returns = prices.pct_change().dropna()
print("Daily Returns Preview:")
print(returns.head())
الآن لنحسب بعض مقاييس المحفظة الأساسية:
def portfolio_performance(weights, returns):
"""
Calculate portfolio return and volatility
weights: array of portfolio weights
returns: dataframe of asset returns
"""
portfolio_return = np.sum(returns.mean() * weights) * 252
portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
return portfolio_return, portfolio_vol
weights_5050 = np.array([0.5, 0.5])
ret_5050, vol_5050 = portfolio_performance(weights_5050, returns)
print(f"50/50 Portfolio:")
print(f"Expected Annual Return: {ret_5050:.2%}")
print(f"Annual Volatility: {vol_5050:.2%}")
print(f"Sharpe Ratio: {ret_5050/vol_5050:.3f}")
المستوى 2: الجدية — الحدود الفعالة
الآن نبدأ الطبخ الحقيقي! تُظهر لنا الحدود الفعالة جميع المحافظ المثالية الممكنة. كل نقطة تمثل أفضل عائد ممكن لمستوى مخاطر معين.
def generate_random_portfolios(returns, num_portfolios=10000):
"""
Generate random portfolio combinations
"""
num_assets = len(returns.columns)
results = np.zeros((4, num_portfolios))
for i in range(num_portfolios):
weights = np.random.random(num_assets)
weights /= np.sum(weights) # Normalize to sum to 1
portfolio_return, portfolio_vol = portfolio_performance(weights, returns)
sharpe_ratio = portfolio_return / portfolio_vol
results[0,i] = portfolio_return
results[1,i] = portfolio_vol
results[2,i] = sharpe_ratio
results[3,i:] = weights
return results
results = generate_random_portfolios(returns)
portfolio_results = pd.DataFrame({
'Returns': results[0],
'Volatility': results[1],
'Sharpe_Ratio': results[2]
})
plt.figure(figsize=(12, 8))
scatter = plt.scatter(portfolio_results['Volatility'],
portfolio_results['Returns'],
c=portfolio_results['Sharpe_Ratio'],
cmap='viridis', alpha=0.6)
plt.colorbar(scatter, label='Sharpe Ratio')
plt.xlabel('Volatility (Risk)')
plt.ylabel('Expected Return')
plt.title('Efficient Frontier - Random Portfolios')
plt.show()
الحدود الفعالة: المنحنى الذي يمثل أقصى عائد متوقع ممكن لمستوى مخاطر معين.
المستوى 3: سيد التحسين — إيجاد المحفظة المثالية
أخذ العينات العشوائية ممتع، لكننا نريد الحل الأمثل رياضياً. حان وقت إخراج الأسلحة الثقيلة — تحسين scipy!
def negative_sharpe_ratio(weights, returns, risk_free_rate=0.02):
"""
Calculate negative Sharpe ratio (we minimize this)
"""
portfolio_return, portfolio_vol = portfolio_performance(weights, returns)
sharpe = (portfolio_return - risk_free_rate) / portfolio_vol
return -sharpe
def minimize_volatility(weights, returns):
"""
Calculate portfolio volatility (we minimize this)
"""
_, portfolio_vol = portfolio_performance(weights, returns)
return portfolio_vol
def portfolio_return_objective(weights, returns):
"""
Calculate portfolio return (we maximize this)
"""
portfolio_return, _ = portfolio_performance(weights, returns)
return -portfolio_return # Negative because we minimize
def optimize_portfolio(returns, objective='sharpe', target_return=None):
"""
Optimize portfolio based on different objectives
"""
num_assets = len(returns.columns)
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) # Weights sum to 1
bounds = tuple((0, 1) for _ in range(num_assets)) # No short selling
initial_guess = num_assets * [1. / num_assets]
if objective == 'sharpe':
result = minimize(negative_sharpe_ratio, initial_guess,
args=(returns,), method='SLSQP',
bounds=bounds, constraints=constraints)
elif objective == 'min_vol':
result = minimize(minimize_volatility, initial_guess,
args=(returns,), method='SLSQP',
bounds=bounds, constraints=constraints)
elif objective == 'target_return':
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
{'type': 'eq', 'fun': lambda x: portfolio_performance(x, returns)[0] - target_return})
result = minimize(minimize_volatility, initial_guess,
args=(returns,), method='SLSQP',
bounds=bounds, constraints=constraints)
return result
max_sharpe = optimize_portfolio(returns, 'sharpe')
min_vol = optimize_portfolio(returns, 'min_vol')
print("🎯 Maximum Sharpe Ratio Portfolio:")
for i, symbol in enumerate(crypto_symbols):
print(f"{symbol}: {max_sharpe.x[i]:.3f}")
ret_sharpe, vol_sharpe = portfolio_performance(max_sharpe.x, returns)
print(f"Return: {ret_sharpe:.2%}, Volatility: {vol_sharpe:.2%}")
print(f"Sharpe Ratio: {ret_sharpe/vol_sharpe:.3f}\n")
print("🛡️ Minimum Volatility Portfolio:")
for i, symbol in enumerate(crypto_symbols):
print(f"{symbol}: {min_vol.x[i]:.3f}")
ret_minvol, vol_minvol = portfolio_performance(min_vol.x, returns)
print(f"Return: {ret_minvol:.2%}, Volatility: {vol_minvol:.2%}")
المستوى 4: جنون الأصول المتعددة — محفظة عملات مشفرة حقيقية
لنوسّع هذا إلى محفظة عملات مشفرة حقيقية بأصول متعددة:
crypto_portfolio = ['BTC-USD', 'ETH-USD', 'BNB-USD', 'ADA-USD', 'SOL-USD', 'DOT-USD']
prices_multi = get_crypto_data(crypto_portfolio, period="2y")
returns_multi = prices_multi.pct_change().dropna()
correlation_matrix = returns_multi.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='RdYlBu_r', center=0)
plt.title('Crypto Asset Correlation Matrix')
plt.show()
def efficient_frontier(returns, num_portfolios=50):
"""
Calculate the efficient frontier
"""
ret_range = np.linspace(returns.mean().min()*252, returns.mean().max()*252, num_portfolios)
efficient_portfolios = []
for target_ret in ret_range:
try:
result = optimize_portfolio(returns, 'target_return', target_ret)
if result.success:
ret, vol = portfolio_performance(result.x, returns)
efficient_portfolios.append([ret, vol, result.x])
except:
continue
return np.array(efficient_portfolios)
efficient_port = efficient_frontier(returns_multi)
plt.figure(figsize=(14, 10))
random_results = generate_random_portfolios(returns_multi, 5000)
plt.scatter(random_results[1], random_results[0],
c=random_results[2], cmap='viridis', alpha=0.3, s=10)
if len(efficient_port) > 0:
plt.plot(efficient_port[:,1], efficient_port[:,0], 'r-', linewidth=3, label='Efficient Frontier')
max_sharpe_multi = optimize_portfolio(returns_multi, 'sharpe')
min_vol_multi = optimize_portfolio(returns_multi, 'min_vol')
ret_sharpe_multi, vol_sharpe_multi = portfolio_performance(max_sharpe_multi.x, returns_multi)
ret_minvol_multi, vol_minvol_multi = portfolio_performance(min_vol_multi.x, returns_multi)
plt.scatter(vol_sharpe_multi, ret_sharpe_multi, marker='*', color='gold', s=500, label='Max Sharpe')
plt.scatter(vol_minvol_multi, ret_minvol_multi, marker='*', color='red', s=500, label='Min Volatility')
plt.colorbar(label='Sharpe Ratio')
plt.xlabel('Volatility (Risk)')
plt.ylabel('Expected Return')
plt.title('Multi-Asset Crypto Portfolio Optimization')
plt.legend()
plt.show()
print("🚀 Optimal Multi-Asset Allocations:")
print("\nMaximum Sharpe Ratio Portfolio:")
sharpe_weights = pd.Series(max_sharpe_multi.x, index=crypto_portfolio).sort_values(ascending=False)
for asset, weight in sharpe_weights.items():
if weight > 0.01: # Only show significant allocations
print(f"{asset}: {weight:.1%}")
print(f"\nPortfolio Metrics:")
print(f"Expected Return: {ret_sharpe_multi:.1%}")
print(f"Volatility: {vol_sharpe_multi:.1%}")
print(f"Sharpe Ratio: {ret_sharpe_multi/vol_sharpe_multi:.2f}")
تنويع الأصول المتعددة: بناء محفظة متينة من خلال الجمع بين أصول مشفرة غير مترابطة في هيكل هندسي مستقر.
المستوى 5: تقنيات متقدمة — بلاك-ليترمان وتكافؤ المخاطر
لمحترفي تحسين المحافظ الحقيقيين، لننفذ بعض التقنيات المتقدمة:
def risk_parity_portfolio(returns):
"""
Risk Parity Portfolio - each asset contributes equally to portfolio risk
"""
def risk_contribution(weights, cov_matrix):
portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
marginal_contrib = np.dot(cov_matrix, weights) / portfolio_vol
contrib = weights * marginal_contrib
return contrib
def risk_parity_objective(weights, cov_matrix):
contrib = risk_contribution(weights, cov_matrix)
target_contrib = np.ones(len(weights)) / len(weights)
return np.sum((contrib - target_contrib)**2)
num_assets = len(returns.columns)
cov_matrix = returns.cov() * 252
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bounds = tuple((0.001, 1) for _ in range(num_assets))
initial_guess = num_assets * [1. / num_assets]
result = minimize(risk_parity_objective, initial_guess,
args=(cov_matrix,), method='SLSQP',
bounds=bounds, constraints=constraints)
return result
risk_parity_result = risk_parity_portfolio(returns_multi)
print("⚖️ Risk Parity Portfolio:")
rp_weights = pd.Series(risk_parity_result.x, index=crypto_portfolio).sort_values(ascending=False)
for asset, weight in rp_weights.items():
print(f"{asset}: {weight:.1%}")
ret_rp, vol_rp = portfolio_performance(risk_parity_result.x, returns_multi)
print(f"\nRisk Parity Metrics:")
print(f"Expected Return: {ret_rp:.1%}")
print(f"Volatility: {vol_rp:.1%}")
print(f"Sharpe Ratio: {ret_rp/vol_rp:.2f}")
def backtest_portfolio(weights, prices):
"""
Simple backtest of portfolio performance
"""
returns = prices.pct_change().dropna()
portfolio_returns = (returns * weights).sum(axis=1)
cumulative_returns = (1 + portfolio_returns).cumprod()
total_return = cumulative_returns.iloc[-1] - 1
annualized_return = (1 + total_return) ** (252 / len(portfolio_returns)) - 1
annualized_vol = portfolio_returns.std() * np.sqrt(252)
sharpe_ratio = annualized_return / annualized_vol
max_dd = (cumulative_returns / cumulative_returns.expanding().max() - 1).min()
return {
'total_return': total_return,
'annualized_return': annualized_return,
'annualized_volatility': annualized_vol,
'sharpe_ratio': sharpe_ratio,
'max_drawdown': max_dd,
'cumulative_returns': cumulative_returns
}
strategies = {
'Max Sharpe': max_sharpe_multi.x,
'Min Volatility': min_vol_multi.x,
'Risk Parity': risk_parity_result.x,
'Equal Weight': np.ones(len(crypto_portfolio)) / len(crypto_portfolio)
}
plt.figure(figsize=(14, 8))
for name, weights in strategies.items():
backtest_results = backtest_portfolio(weights, prices_multi)
plt.plot(backtest_results['cumulative_returns'], label=f"{name} (Sharpe: {backtest_results['sharpe_ratio']:.2f})")
plt.title('Portfolio Strategy Backtests')
plt.xlabel('Date')
plt.ylabel('Cumulative Returns')
plt.legend()
plt.yscale('log')
plt.grid(True, alpha=0.3)
plt.show()

*الاختبار الخلفي الخوارزمي: محاكاة الأداء التاريخي للتحقق من نماذج التحسين النظرية.*
performance_summary = pd.DataFrame()
for name, weights in strategies.items():
results = backtest_portfolio(weights, prices_multi)
performance_summary[name] = [
f"{results['annualized_return']:.1%}",
f"{results['annualized_volatility']:.1%}",
f"{results['sharpe_ratio']:.2f}",
f"{results['max_drawdown']:.1%}"
]
performance_summary.index = ['Annual Return', 'Annual Volatility', 'Sharpe Ratio', 'Max Drawdown']
print("\n📊 Strategy Performance Summary:")
print(performance_summary)
فحص الواقع: ما لا يخبرك به ماركويتز
قبل أن تراهن كل شيء على التحسين الرياضي، إليك بعض الحقائق القاسية حول العملات المشفرة:
1. الأداء الماضي ≠ النتائج المستقبلية سوق العملات المشفرة شاب وفوضوي. تلك الارتباطات التي حسبتها؟ قد تنقلب بين عشية وضحاها عندما تتغير اللوائح أو عندما يحدث الاختراق الكبير التالي.
2. تكاليف المعاملات مهمة إعادة توازن محفظتك تكلف مالاً. في DeFi، يمكن لرسوم الغاز أن تلتهم أرباحك. ضع هذا في اعتبارك في استراتيجيتك.
3. مشاكل السيولة ليست كل العملات المشفرة سائلة بنفس القدر. تلك العملة البديلة الصغيرة قد تبدو رائعة في التحسين، لكن حاول بيعها أثناء الانهيار.
4. تغيّرات النظام أسواق العملات المشفرة لديها "أنظمة" مختلفة — سوق صاعد، سوق هابط، سوق جانبي. ما يعمل في نظام قد لا يعمل في آخر.
نصائح التطبيق العملي
def practical_portfolio_rebalancing(target_weights, current_weights, threshold=0.05):
"""
Only rebalance when weights drift beyond threshold
"""
weight_diff = np.abs(target_weights - current_weights)
needs_rebalancing = np.any(weight_diff > threshold)
if needs_rebalancing:
print("🔄 Rebalancing needed!")
for i, (target, current) in enumerate(zip(target_weights, current_weights)):
if abs(target - current) > threshold:
print(f"Asset {i}: {current:.1%} → {target:.1%}")
else:
print("✅ Portfolio within tolerance, no rebalancing needed")
return needs_rebalancing
current_allocation = np.array([0.35, 0.25, 0.15, 0.10, 0.10, 0.05])
target_allocation = max_sharpe_multi.x
practical_portfolio_rebalancing(target_allocation, current_allocation)
الخلاصة: مجموعة أدوات تحسين المحفظة
لديك الآن مجموعة أدوات كاملة لتحسين محفظة العملات المشفرة:
- حسابات أساسية للمخاطر والعائد
- تصور الحدود الفعالة
- تحسين رياضي لأهداف مختلفة
- استراتيجيات متقدمة مثل تكافؤ المخاطر
- إطار اختبار خلفي للتحقق من استراتيجياتك
- اعتبارات عملية للتطبيق في العالم الحقيقي
النقاط الرئيسية
- التنويع هو وجبة مجانية — الوجبة المجانية الوحيدة في الاستثمار
- حسّن بناءً على تحمّلك للمخاطر — أقصى شارب ليس دائماً الأفضل لك
- أعد التوازن بشكل منهجي لكن لا تفرط في التداول
- كن متواضعاً — النماذج أدوات وليست كرات بلورية
- ابدأ ببساطة وأضف التعقيد كلما تعلمت
تذكّر: في عالم العملات المشفرة، حتى أفضل النماذج الرياضية لا تستطيع التنبؤ بموعد تغريد إيلون عن Dogecoin أو اختراق البورصة التالية. استخدم نظرية المحفظة كأساس، لكن احتفظ دائماً ببعض الاحتياطي ولا تستثمر أكثر مما يمكنك تحمّل خسارته.
والآن، انطلق وحسّن بمسؤولية! 🚀
قراءات إضافية
مستودع الكود
جميع الأكواد من هذا الدرس متاحة على GitHub: https://github.com/suenot/markowitz
Happy optimizing! 📈
MarketMaker.cc Team
البحوث والاستراتيجيات الكمية