Крипто үчүн Марковиц портфель теориясы: нөлдөн баатырга чейин
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-деңгээл: өнүккөн ыкмалар - Black-Litterman жана тобокелдик паритети
Портфель оптималдаштыруунун чыныгы нинзялары үчүн бир нече өнүккөн ыкманы ишке ашыралы:
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
Ийгиликтүү оптималдаштыруу! 📈