Крипто үчүн Марковиц портфель теориясы: нөлдөн баатырга чейин
Python менен оптималдуу крипто портфелдерди түзүү - анткени YOLO стратегия эмес
Марковиц портфель теориясы: белгилүү бир тобокелдик деңгээли үчүн кирешени максималдаштыруу максатында санарип активдерге колдонулган математикалык оптималдаштыруу.
Киришүү: эмне үчүн сиздин крипто портфелиңизге сезим эмес, математика керек
Салам, крипто-дегендер! 👋
Илон твит жазганы үчүн бүт стегиңизди DOGE'го таштап жибергениңизди эстейсизби? Же болбосо акыркы кулаган учурда баарын дүрбөлөңдө сатып жибергениңизди? Ооба, баарыбыз да ушундан өттүк. Бүгүн биз портфелиңизди (жана акыл-эсиңизди) сактап кала турган нерсе жөнүндө сүйлөшөбүз: Марковиц портфель теориясы.
Гарри Марковиц бул үчүн 1990-жылы чын эле Нобель сыйлыгын алган. Негизги идея кандай? Сиз каалаган тобокелдик деңгээли үчүн эң жакшы мүмкүн болгон кирешени алуу үчүн портфелиңизди математикалык жол менен оптималдаштыра аласыз. Бул көзүңүздү таңып айдоонун ордуна инвестицияларыңыз үчүн GPS болгону менен бирдей.
Негизги түшүнүк: тобокелдик менен киреше (түбөлүктүү бий)
Кодго киришээрден мурун, эмне менен алектенип жатканыбызды түшүнөлү:
- Күтүлгөн киреше: канча акча табам деп күтөсүз
- Тобокелдик (өзгөрмөлүүлүк): портфелиңиздин наркы канчалык термелет
- Корреляция: ар түрдүү активдер бири-бирине окшош кандай кыймылдайт
Сыйкыр так синхрондуу кыймылдабаган активдерди бириктиргенде пайда болот. Bitcoin кулаганда, кээ бир 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-деңгээл: алгачкы кадамдар - жөнөкөй портфель математикасы
Негиздерден баштайлы. Биз жөнөкөй 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
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-деңгээл: маселе олуттуулашат - эффективдүү чек ара (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):
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-деңгээл: өнүккөн ыкмалар - 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
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
Ийгиликтүү оптималдаштыруу! 📈
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.