ทฤษฎีพอร์ตโฟลิโอ Markowitz สำหรับคริปโต: จากศูนย์สู่ผู้เชี่ยวชาญ

การสร้างพอร์ตโฟลิโอคริปโตที่เหมาะสมที่สุดด้วย Python - เพราะ YOLO ไม่ใช่กลยุทธ์ เรียนรู้วิธีประยุกต์ใช้ทฤษฎีพอร์ตโฟลิโอที่ได้รับรางวัลโนเบลกับการลงทุนในคริปโต พร้อมตัวอย่างโค้ด Python ที่ใช้งานได้จริง

การสร้างพอร์ตโฟลิโอคริปโตที่เหมาะสมที่สุดด้วย Python — เพราะ YOLO ไม่ใช่กลยุทธ์

Markowitz Portfolio Theory ทฤษฎีพอร์ตโฟลิโอ Markowitz: การเพิ่มประสิทธิภาพทางคณิตศาสตร์ที่ประยุกต์ใช้กับสินทรัพย์ดิจิทัลเพื่อเพิ่มผลตอบแทนสูงสุดสำหรับระดับความเสี่ยงที่กำหนด


บทนำ: ทำไมพอร์ตโฟลิโอคริปโตของคุณถึงต้องการคณิตศาสตร์ (ไม่ใช่แค่ความรู้สึก)

สวัสดีนักเก็งกำไรคริปโตทุกท่าน! 👋

คุณยังจำตอนที่ทุ่มเงินทั้งหมดซื้อ DOGE เพราะ Elon ทวีตอยู่ไหม? หรือตอนที่ตื่นตระหนกขายทุกอย่างระหว่างการตกของตลาดครั้งล่าสุด? ใช่แล้ว พวกเราเคยผ่านสิ่งนั้นกันมาหมด วันนี้เราจะพูดถึงสิ่งที่อาจช่วยพอร์ตโฟลิโอของคุณ (และสติสัมปชัญญะของคุณ): ทฤษฎีพอร์ตโฟลิโอ Markowitz

Harry Markowitz ได้รับรางวัลโนเบลสำหรับสิ่งนี้เมื่อปี 1990 แนวคิดพื้นฐาน? คุณสามารถเพิ่มประสิทธิภาพพอร์ตโฟลิโอของคุณทางคณิตศาสตร์เพื่อให้ได้ผลตอบแทนที่ดีที่สุดเท่าที่เป็นไปได้สำหรับระดับความเสี่ยงที่กำหนด มันเหมือนกับการมี GPS สำหรับการลงทุนของคุณแทนที่จะขับรถโดยปิดตา

แนวคิดหลัก: ความเสี่ยงเทียบกับผลตอบแทน (การเต้นรำชั่วนิรันดร์)

ก่อนที่เราจะเริ่มเขียนโค้ด มาทำความเข้าใจกับสิ่งที่เรากำลังจัดการ:

  • ผลตอบแทนที่คาดหวัง: จำนวนเงินที่คุณคาดว่าจะได้รับ
  • ความเสี่ยง (ความผันผวน): ค่าพอร์ตโฟลิโอของคุณกระโดดขึ้นลงมากแค่ไหน
  • ความสัมพันธ์: สินทรัพย์ต่างๆ เคลื่อนไหวพร้อมกันอย่างไร

ความมหัศจรรย์เกิดขึ้นเมื่อคุณรวมสินทรัพย์ที่ไม่เคลื่อนไหวพร้อมกันอย่างสมบูรณ์แบบ เมื่อ Bitcoin ตก บางทีโทเค็น DeFi บางตัวอาจยืนหยัดได้ดีกว่า นั่นคือการกระจายความเสี่ยงที่ทำงานเพื่อคุณ

Risk vs Return ความเสี่ยงเทียบกับผลตอบแทน: การสร้างสมดุลระหว่างสินทรัพย์ที่ให้ผลตอบแทนสูงแต่ผันผวนกับฐานที่มั่นคงเพื่อให้ได้ค่าเฉลี่ยผลตอบแทนทางเรขาคณิตที่เหมาะสมที่สุด

การตั้งค่าสภาพแวดล้อม 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

ตอนนี้เราเริ่มต้นแล้ว! 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()

Efficient Frontier Efficient Frontier: เส้นโค้งที่แสดงถึงผลตอบแทนที่คาดหวังสูงสุดที่เป็นไปได้สำหรับระดับความเสี่ยงที่กำหนด

ระดับ 3: การเพิ่มประสิทธิภาพขั้นปรมาจารย์ — ค้นหาพอร์ตโฟลิโอที่สมบูรณ์แบบ

การสุ่มตัวอย่างเป็นเรื่องสนุก แต่เราต้องการคำตอบที่เหมาะสมที่สุดทางคณิตศาสตร์ ถึงเวลาใช้อาวุธหนัก — scipy optimization!

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

Multi-Asset Portfolio Optimization การกระจายความเสี่ยงในหลายสินทรัพย์: การสร้างพอร์ตโฟลิโอที่แข็งแกร่งโดยการรวมสินทรัพย์คริปโตที่ไม่มีความสัมพันธ์กันเป็นโครงสร้างทางเรขาคณิตที่มั่นคง

ระดับ 5: เทคนิคขั้นสูง — Black-Litterman และ Risk Parity

สำหรับนินจาการเพิ่มประสิทธิภาพพอร์ตโฟลิโอตัวจริง มาใช้งานเทคนิคขั้นสูง:

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

![Portfolio Strategy Backtests](/images/blog/markowitz-backtest.webp)
*การทดสอบย้อนหลังเชิงอัลกอริทึม: การจำลองประสิทธิภาพในอดีตเพื่อตรวจสอบความถูกต้องของโมเดลการเพิ่มประสิทธิภาพทางทฤษฎี*


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

การตรวจสอบความเป็นจริง: สิ่งที่ Markowitz ไม่บอกคุณ

ก่อนที่คุณจะทุ่มทุนทั้งหมดไปกับการเพิ่มประสิทธิภาพทางคณิตศาสตร์ นี่คือความจริงที่ยากสำหรับคริปโต:

1. ประสิทธิภาพในอดีต ≠ ผลลัพธ์ในอนาคต ตลาดคริปโตยังอยู่ในช่วงเริ่มต้นและวุ่นวาย ความสัมพันธ์ที่คุณคำนวณไว้? มันอาจพลิกกลับข้ามคืนเมื่อกฎระเบียบเปลี่ยนแปลงหรือเมื่อการแฮ็กครั้งใหญ่ครั้งต่อไปเกิดขึ้น

2. ต้นทุนการทำธุรกรรมมีความสำคัญ การปรับสมดุลพอร์ตโฟลิโอของคุณมีค่าใช้จ่าย ใน DeFi ค่าธรรมเนียมแก๊สสามารถกินกำไรของคุณหมด คำนึงถึงสิ่งนี้ในกลยุทธ์ของคุณ

3. ปัญหาสภาพคล่อง คริปโตทุกตัวไม่มีสภาพคล่องเท่ากัน altcoin มูลค่าตลาดเล็กที่ดูดีในการเพิ่มประสิทธิภาพของคุณ? ลองขายมันในช่วงตลาดตก

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)

สรุป: ชุดเครื่องมือการเพิ่มประสิทธิภาพพอร์ตโฟลิโอของคุณ

ตอนนี้คุณมีชุดเครื่องมือครบครันสำหรับการเพิ่มประสิทธิภาพพอร์ตโฟลิโอคริปโต:

  1. การคำนวณพื้นฐาน สำหรับความเสี่ยงและผลตอบแทน
  2. การแสดงภาพ Efficient Frontier
  3. การเพิ่มประสิทธิภาพทางคณิตศาสตร์ สำหรับวัตถุประสงค์ที่แตกต่างกัน
  4. กลยุทธ์ขั้นสูง เช่น risk parity
  5. กรอบการทดสอบย้อนหลัง เพื่อตรวจสอบกลยุทธ์ของคุณ
  6. ข้อพิจารณาในทางปฏิบัติ สำหรับการนำไปใช้งานในโลกจริง

ประเด็นสำคัญ

  • การกระจายความเสี่ยงคืออาหารกลางวันฟรี — อาหารกลางวันฟรีเดียวในการลงทุน
  • เพิ่มประสิทธิภาพตามความเสี่ยงที่ยอมรับได้ — max Sharpe ไม่ใช่สิ่งที่ดีที่สุดเสมอไปสำหรับคุณ
  • ปรับสมดุลอย่างเป็นระบบ แต่อย่าซื้อขายมากเกินไป
  • อยู่กับความถ่อมตัว — โมเดลเป็นเครื่องมือ ไม่ใช่ลูกแก้วทำนายอนาคต
  • เริ่มอย่างเรียบง่าย และเพิ่มความซับซ้อนเมื่อคุณเรียนรู้

จำไว้ว่า: ในคริปโต แม้แต่โมเดลทางคณิตศาสตร์ที่ดีที่สุดก็ไม่สามารถทำนายได้ว่าเมื่อไหร่ Elon จะทวีตเรื่อง Dogecoin หรือเมื่อไหร่การแลกเปลี่ยนครั้งต่อไปจะถูกแฮ็ก ใช้ทฤษฎีพอร์ตโฟลิโอเป็นรากฐาน แต่เสมอต้องเก็บเงินสำรองและอย่าลงทุนมากกว่าที่คุณจะสูญเสียได้

ตอนนี้ออกไปและเพิ่มประสิทธิภาพอย่างมีความรับผิดชอบ! 🚀

อ่านเพิ่มเติม

โค้ดของบทเรียนนี้

โค้ดทั้งหมดจากบทเรียนนี้มีให้บน GitHub: https://github.com/suenot/markowitz

ขอให้สนุกกับการเพิ่มประสิทธิภาพ! 📈