← Maqolalarga qaytish
September 25, 2025
5 daqiqa o'qish

Kripto uchun Markowitz portfel nazariyasi: noldan qahramongacha

Kripto uchun Markowitz portfel nazariyasi: noldan qahramongacha
#portfolio optimization
#Markowitz
#crypto
#Python
#quantitative finance
#risk management
#diversification
#efficient frontier
#Sharpe ratio
#algorithmic trading
📊
Part 1 of 5 · Collection
Portfolio Construction & Risk

Python yordamida optimal kripto portfellar qurish - chunki YOLO strategiya emas

Markowitz Portfolio Theory Markowitz portfel nazariyasi: berilgan xavf darajasi uchun daromadni maksimal darajaga yetkazish maqsadida raqamli aktivlarga qo'llaniladigan matematik optimallashtirish.


Kirish: nega sizning kripto portfelingizga faqat hissiyot emas, matematika kerak

Salom, kripto-degenlar! 👋

Elon tvit yozgani uchun butun stackingizni DOGE'ga tashlab yuborgan paytingizni eslaysizmi? Yoki oxirgi qulash paytida hamma narsani vahima ichida sotib yuborgan paytingizni? Ha, hammamiz bu yerdan o'tganmiz. Bugun biz portfelingizni (va aql-hushingizni) saqlab qolishi mumkin bo'lgan narsa haqida gaplashamiz: Markowitz portfel nazariyasi.

Harri Markowitz buning uchun 1990 yilda rostdan ham Nobel mukofotiga sazovor bo'lgan. Asosiy g'oya nima? Siz istalgan xavf darajasi uchun eng yaxshi mumkin bo'lgan daromadga erishish maqsadida portfelingizni matematik jihatdan optimallashtira olasiz. Bu ko'zingizni yumib mashina haydashning o'rniga investitsiyalaringiz uchun GPS bo'lishga o'xshaydi.

Asosiy tushuncha: xavf va daromad (abadiy raqs)

Kodga o'tishdan oldin, nima bilan shug'ullanayotganimizni tushunib olaylik:

  • Kutilayotgan daromad: qancha pul topishni kutayapsiz
  • Xavf (o'zgaruvchanlik): portfelingiz qiymati qanchalik tebranadi
  • Korrelyatsiya: turli aktivlar bir-biriga qanchalik o'xshash harakat qiladi

Sehr o'zaro mukammal sinxron harakat qilmaydigan aktivlarni birlashtirganingizda sodir bo'ladi. Bitcoin qulaganda, ba'zi DeFi tokenlar yaxshiroq chidashi mumkin. Bu sizning foydangizga ishlayotgan diversifikatsiya.

Risk vs Return Xavf va daromad: optimal geometrik o'rtacha daromadga erishish uchun yuqori daromadli, o'zgaruvchan aktivlarni barqaror asos bilan muvozanatlash.

Python muhitimizni sozlash

Avvalo eng muhimi - asboblarimizni tayyorlaymiz:

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-daraja: dastlabki qadamlar - oddiy portfel matematikasi

Asoslardan boshlaylik. Oddiy 2 aktivli portfel uchun daromad va xavfni hisoblaymiz.

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())

Endi bir nechta asosiy portfel ko'rsatkichlarini hisoblaymiz:

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-daraja: jiddiyroq harakat - samarali chegara (efficient frontier)

Endi haqiqiy ish boshlanadi! Samarali chegara bizga barcha mumkin bo'lgan optimal portfellarni ko'rsatadi. Har bir nuqta berilgan xavf darajasi uchun eng yaxshi mumkin bo'lgan daromadni bildiradi.

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()

Efficient Frontier Samarali chegara: berilgan xavf darajasi uchun maksimal mumkin bo'lgan kutilayotgan daromadni ifodalovchi egri chiziq.

3-daraja: optimallashtirish ustasi - mukammal portfelni topish

Tasodifiy tanlash qiziqarli, lekin bizga matematik jihatdan optimal yechim kerak. Og'ir artilleriyani ishga solish vaqti keldi - scipy optimallashtirishi!

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-daraja: ko'p aktivli aljashuv - haqiqiy kripto portfel

Buni bir nechta aktivdan iborat to'liq huquqli kripto portfeliga kengaytiramiz:

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}")

Multi-Asset Portfolio Optimization Ko'p aktivli diversifikatsiya: bir-biriga bog'liq bo'lmagan kripto aktivlarni barqaror geometrik tuzilmaga birlashtirish orqali mustahkam portfel qurish.

5-daraja: ilg'or texnikalar - Black-Litterman va xavf paritetlari

Portfelni optimallashtirishning haqiqiy ninjalari uchun bir nechta ilg'or texnikani amalga oshiramiz:

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()

![Portfolio Strategy Backtests](/images/blog/markowitz-backtest.webp)
*Algoritmik bektesting: nazariy optimallashtirish modellarini tasdiqlash uchun tarixiy natijalarni simulyatsiya qilish.*


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)

Haqiqatga qaytish: Markowitz sizga aytmaydigan narsalar

Matematik optimallashtirishga to'liq bel bog'lashdan oldin, kripto haqida bir nechta qattiq haqiqatlar:

1. O'tmishdagi natijalar kelajakdagi natijalarga teng emas Kripto bozori yosh va tartibsiz. Siz hisoblagan korrelyatsiyalar-chi? Ular tartibga solish qoidalari o'zgarganda yoki keyingi katta xakerlik hujumi sodir bo'lganda bir kechada teskarisiga aylanishi mumkin.

2. Tranzaksiya xarajatlari muhim Portfelingizni qayta muvozanatlash pul talab qiladi. DeFi'da gaz to'lovlari foydangizni yeyishi mumkin. Buni strategiyangizda hisobga oling.

3. Likvidlik muammolari Barcha kriptovalyutalar bir xil darajada likvid emas. O'sha kichik kapitalli altkoin optimallashtiruvingizda ajoyib ko'rinishi mumkin, lekin uni qulash paytida sotib ko'ring.

4. Rejim o'zgarishlari Kripto bozorlarida turli "rejimlar" mavjud - ko'tarilish bozorlari, tushish bozorlari, yon tomonga siljish bozorlari. Bittasida ishlaydigan narsa boshqasida ishlamasligi mumkin.

Amaliy joriy etish bo'yicha maslahatlar

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)

Xulosa: portfelni optimallashtirish uchun asboblar to'plamingiz

Endi sizda kripto portfelini optimallashtirish uchun to'liq asboblar to'plami bor:

  1. Xavf va daromad uchun asosiy hisob-kitoblar
  2. Samarali chegarani vizualizatsiya qilish
  3. Turli maqsadlar uchun matematik optimallashtirish
  4. Xavf pariteti kabi ilg'or strategiyalar
  5. Strategiyalaringizni tasdiqlash uchun bektesting freymvorki
  6. Real dunyoda joriy etish uchun amaliy mulohazalar

Asosiy xulosalar

  • Diversifikatsiya - bu bepul tushlik - investitsiyalardagi yagona bepul narsa
  • Xavfga bardoshliligingizga qarab optimallashtiring - maksimal Sharpe koeffitsienti har doim ham siz uchun eng yaxshisi bo'lavermaydi
  • Tizimli ravishda qayta muvozanatlang, lekin ortiqcha savdo qilmang
  • Kamtar bo'ling - modellar asbob, sehrli sharlar emas
  • Oddiydan boshlang va o'rganib borgan sari murakkablikni qo'shing

Esda tuting: kriptoda hatto eng yaxshi matematik modellar ham Elon Dogecoin haqida qachon tvit yozishini yoki keyingi birja qachon xakerlik hujumiga uchrashini bashorat qila olmaydi. Portfel nazariyasini asos sifatida ishlating, lekin har doim biroz zaxira saqlang va yo'qotishga tayyor bo'lmagan miqdordan ko'proq hech qachon investitsiya qilmang.

Endi boring va mas'uliyat bilan optimallashtiring! 🚀

Qo'shimcha o'qish

Kod repozitoriysi

Ushbu qo'llanmadagi barcha kod GitHub'da mavjud: https://github.com/suenot/markowitz

Muvaffaqiyatli optimallashtirish! 📈

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

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.

Newsletter

Bozordan bir qadam oldinda bo'ling

Sun'iy intellekt savdo tahlillari, bozor tahlili va platforma yangiliklari uchun bizning xabarnomaga obuna bo'ling.

Biz sizning maxfiyligingizni hurmat qilamiz. Istalgan vaqtda obunadan chiqishingiz mumkin.