Криптовалютаға арналған Марковиц портфель теориясы: нөлден кейіпкерге дейін
Python көмегімен оңтайлы крипто портфельдер құру - себебі YOLO стратегия емес. Нобель сыйлығын алған портфель теориясын практикалық Python код мысалдарымен крипто инвестицияларға қалай қолдануды үйреніңіз.

Python көмегімен оңтайлы крипто портфельдер құру - себебі YOLO стратегия емес
Марковиц портфель теориясы: белгілі бір тәуекел деңгейі үшін кірісті барынша арттыру мақсатында цифрлық активтерге қолданылатын математикалық оңтайландыру.
Кіріспе: неге сіздің крипто портфеліңізге тек сезім емес, математика керек
Сәлем, крипто-дегендер! 👋
Илон твит жазғаны үшін бүкіл стегіңізді DOGE-ге тастаған кезіңізді есіңізде ме? Немесе соңғы құлдырау кезінде бәрін дүрбелеңмен сатып жіберген кезіңізді? Иә, бәріміз де осыдан өттік. Бүгін біз портфеліңізді (және ақыл-есіңізді) құтқара алатын нәрсе туралы сөйлесеміз: Марковиц портфель теориясы.
Гарри Марковиц бұл үшін 1990 жылы шын мәнінде Нобель сыйлығын алды. Негізгі идея қандай? Кез келген берілген тәуекел деңгейінде ең жақсы мүмкін кірісті алу үшін портфеліңізді математикалық түрде оңтайландыруға болады. Бұл көзіңізді таңып жүргізудің орнына инвестицияларыңыз үшін GPS болғанмен бірдей.
Негізгі түсінік: тәуекел мен кіріс (мәңгілік би)
Кодқа кірмес бұрын, немен айналысатынымызды түсінейік:
- Күтілетін кіріс: қанша ақша табамын деп күтесіз
- Тәуекел (құбылмалылық): портфеліңіздің құны қаншалықты ауытқиды
- Корреляция: әртүрлі активтер бір-біріне ұқсас қалай қозғалады
Сиқыр бір-бірімен дәл синхронды қозғалмайтын активтерді біріктірген кезде пайда болады. Bitcoin құлдыраса, кейбір DeFi токендер жақсырақ ұстап тұруы мүмкін. Бұл сіз үшін жұмыс істеп тұрған диверсификация.
Тәуекел мен кіріс: оңтайлы геометриялық орта кірісті алу үшін жоғары кірісті, құбылмалы активтерді тұрақты негізбен теңгеру.
Python ортамызды дайындау
Ең алдымен - құралдарымызды дайындайық:
# Essential libraries for our crypto portfolio optimization
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')
# Set up plotting style
plt.style.use('dark_background')
sns.set_palette("husl")
1-деңгей: алғашқы қадамдар - қарапайым портфель математикасы
Негіздерден бастайық. Біз қарапайым 2 активті портфель үшін кіріс пен тәуекелді есептейміз.
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
# Get data for Bitcoin and Ethereum
crypto_symbols = ['BTC-USD', 'ETH-USD']
prices = get_crypto_data(crypto_symbols)
# Calculate daily returns
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 (annualized)
portfolio_return = np.sum(returns.mean() * weights) * 252
# Portfolio volatility (annualized)
portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
return portfolio_return, portfolio_vol
# Example: 50% BTC, 50% ETH
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-деңгей: іске асайық - тиімді шекара (efficient frontier)
Енді нағыз жұмыс басталады! Тиімді шекара бізге барлық мүмкін оңтайлы портфельдерді көрсетеді. Әр нүкте берілген тәуекел деңгейі үшін ең жақсы мүмкін кірісті білдіреді.
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):
# Generate random weights
weights = np.random.random(num_assets)
weights /= np.sum(weights) # Normalize to sum to 1
# Calculate portfolio metrics
portfolio_return, portfolio_vol = portfolio_performance(weights, returns)
sharpe_ratio = portfolio_return / portfolio_vol
# Store results
results[0,i] = portfolio_return
results[1,i] = portfolio_vol
results[2,i] = sharpe_ratio
results[3,i:] = weights
return results
# Generate 10,000 random portfolios
results = generate_random_portfolios(returns)
# Create a dataframe for easier handling
portfolio_results = pd.DataFrame({
'Returns': results[0],
'Volatility': results[1],
'Sharpe_Ratio': results[2]
})
# Plot the efficient frontier
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 and bounds
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
initial_guess = num_assets * [1. / num_assets]
if objective == 'sharpe':
# Maximize Sharpe ratio
result = minimize(negative_sharpe_ratio, initial_guess,
args=(returns,), method='SLSQP',
bounds=bounds, constraints=constraints)
elif objective == 'min_vol':
# Minimize volatility
result = minimize(minimize_volatility, initial_guess,
args=(returns,), method='SLSQP',
bounds=bounds, constraints=constraints)
elif objective == 'target_return':
# Minimize volatility for 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
# Find optimal portfolios
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-деңгей: көп активті ерекшелік - нағыз крипто портфель
Мұны бірнеше активтен тұратын толыққанды крипто портфельге дейін кеңейтейік:
# Expand to more cryptocurrencies
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()
# Check correlations
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
"""
# Calculate range of target returns
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)
# Calculate efficient frontier
efficient_port = efficient_frontier(returns_multi)
# Plot everything together
plt.figure(figsize=(14, 10))
# Random portfolios
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)
# Efficient frontier
if len(efficient_port) > 0:
plt.plot(efficient_port[:,1], efficient_port[:,0], 'r-', linewidth=3, label='Efficient Frontier')
# Optimal portfolios
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()
# Display optimal allocations
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
# Calculate Risk Parity portfolio
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)
# Calculate cumulative returns
cumulative_returns = (1 + portfolio_returns).cumprod()
# Performance metrics
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
}
# Backtest our strategies
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 table
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
# Example usage
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
Сәтті оңтайландыру! 📈