SECTION 1: LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Define digital asset exchanges and their role in the ecosystem.
-
Differentiate between Centralised Exchanges (CEX) and Decentralised Exchanges (DEX).
-
Explain order book mechanics and matching engines.
-
Understand Automated Market Makers (AMMs) and liquidity pools.
-
Describe trading types (spot, margin, futures, options).
-
Identify security and regulatory considerations for exchanges.
-
Implement a simplified exchange simulation in Python.
-
Develop a framework for evaluating exchange platforms.
SECTION 2: WHAT IS A DIGITAL ASSET EXCHANGE?
2.1 Definition
A digital asset exchange is a platform that facilitates the trading of cryptocurrencies and digital assets. It connects buyers and sellers, provides price discovery, and enables the transfer of assets between participants.
2.2 Exchange Types
┌─────────────────────────────────────────────────────────────────────────────┐ │ DIGITAL ASSET EXCHANGE TYPES │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ CENTRALISED EXCHANGE (CEX) │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Operated by a centralised company │ │ │ │ • Custodial (holds user funds) │ │ │ │ • High liquidity and speed │ │ │ │ • Examples: Binance, Coinbase, Kraken, Bybit │ │ │ │ • Pros: User-friendly, deep liquidity, customer support │ │ │ │ • Cons: Custodial risk, hacks, regulatory scrutiny │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ DECENTRALISED EXCHANGE (DEX) │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Operated by smart contracts │ │ │ │ • Non-custodial (users hold own funds) │ │ │ │ • Lower liquidity (but growing) │ │ │ │ • Examples: Uniswap, SushiSwap, Curve, dYdX │ │ │ │ • Pros: Non-custodial, transparent, permissionless │ │ │ │ • Cons: Slippage, impermanent loss, limited features │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ HYBRID EXCHANGE │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Combines CEX and DEX features │ │ │ │ • On-chain settlement with off-chain order books │ │ │ │ • Examples: dYdX, GMX, Hashflow │ │ │ │ • Pros: Speed of CEX, security of DEX │ │ │ │ • Cons: Complexity, still evolving │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
SECTION 3: CENTRALISED EXCHANGES (CEX)
3.1 Exchange Architecture
┌─────────────────────────────────────────────────────────────────────────────┐ │ CEX ARCHITECTURE │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ USER INTERFACE │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ API GATEWAY │ │ │ │ • Authentication │ │ │ │ • Rate limiting │ │ │ │ • Request routing │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────┼──────────────┐ │ │ v v v │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ │ │ Order Book │ │ Matching Engine │ │ Trade Database │ │ │ │ • Buy orders │ │ • Order matching │ │ • Trade history │ │ │ │ • Sell orders │ │ • Trade execution│ │ • Balances │ │ │ │ • Order depth │ │ • Fee calculation│ │ • User data │ │ │ └──────────────────┘ └──────────────────┘ └──────────────────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ WALLET & CUSTODY SYSTEM │ │ │ │ • Hot wallet (for active trading) │ │ │ │ • Cold storage (for long-term holdings) │ │ │ │ • Withdrawal processing │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
3.2 Order Book Mechanics
| Order Type | Description | Example |
|---|---|---|
| Market Order | Execute immediately at best available price | Buy 1 BTC at market price |
| Limit Order | Execute at specified price or better | Buy 1 BTC at $60,000 |
| Stop Order | Trigger market order at a stop price | Sell at $58,000 stop |
| Stop-Limit Order | Trigger limit order at a stop price | Sell limit at $58,500 triggered at $58,000 |
3.3 Key CEX Metrics
| Metric | Description |
|---|---|
| Trading Volume | Total value traded (24h, 30d) |
| Order Book Depth | Liquidity available at different price levels |
| Number of Pairs | Available trading pairs |
| Fee Structure | Maker/taker fees |
| Number of Users | Active users and total accounts |
SECTION 4: DECENTRALISED EXCHANGES (DEX)
4.1 DEX Architecture
┌─────────────────────────────────────────────────────────────────────────────┐ │ DEX ARCHITECTURE │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ USER WALLET (MetaMask, etc.) │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ DEX SMART CONTRACTS │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ Factory │ │ Router │ │ Pool │ │ │ │ │ │ Contract │ │ Contract │ │ Contracts │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ LIQUIDITY POOLS │ │ │ │ • Pool 1: ETH/USDC │ │ │ │ • Pool 2: WBTC/USDC │ │ │ │ • Pool 3: DAI/USDC │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ PRICE ORACLES │ │ │ │ • Uniswap TWAP │ │ │ │ • Chainlink Price Feeds │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
4.2 AMM Models
| Model | Formula | Example | Best For |
|---|---|---|---|
| Constant Product | x × y = k | Uniswap V2 | General trading |
| Constant Sum | x + y = k | (Rare) | Stable pairs |
| Constant Mean | Weighted product | Balancer | Multi-token pools |
| StableSwap | Hybrid (sum + product) | Curve | Stablecoin trading |
| Concentrated Liquidity | Range-bound | Uniswap V3 | Capital efficiency |
4.3 Slippage and Impermanent Loss
Slippage: Difference between expected and actual price due to pool size and trade size.
-
Higher trade size vs pool size = higher slippage.
Impermanent Loss: Temporary loss incurred by liquidity providers when pool prices change relative to holding assets.
-
Example: ETH price doubles, IL ~5.7% for 2x price change.
SECTION 5: TRADING TYPES
| Trading Type | Description | Risk Level | Use Case |
|---|---|---|---|
| Spot Trading | Buy/sell for immediate delivery | Low-Medium | Investing, trading |
| Margin Trading | Trade with borrowed funds | High | Leveraged positions |
| Futures | Contracts for future delivery | High | Hedging, speculation |
| Options | Right to buy/sell at specified price | Medium-High | Hedging, income |
| Perpetuals | Futures without expiry | High | Leverage trading |
SECTION 6: IMPLEMENTATION IN PYTHON
# =================================================================== # MODULE 2, LESSON 5: DIGITAL ASSET EXCHANGES # =================================================================== import time import json import random from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import pandas as pd import matplotlib.pyplot as plt import numpy as np import warnings warnings.filterwarnings('ignore') print("="*70) print("DIGITAL ASSET EXCHANGES") print("="*70) # ---------------------------------------------------------------- # PART A: ORDER BOOK SIMULATION (CEX) # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART A: Centralised Exchange Order Book Simulation") print("-"*60) @dataclass class Order: id: str user: str side: str # 'buy' or 'sell' price: float amount: float order_type: str # 'limit' or 'market' timestamp: float @property def value(self) -> float: return self.price * self.amount class OrderBook: def __init__(self, base_asset: str, quote_asset: str): self.base_asset = base_asset self.quote_asset = quote_asset self.buy_orders: List[Order] = [] # Sorted by price DESC self.sell_orders: List[Order] = [] # Sorted by price ASC self.trades: List[Dict] = [] self.order_id_counter = 0 def _generate_order_id(self) -> str: self.order_id_counter += 1 return f"ORD-{self.order_id_counter:06d}" def add_order(self, user: str, side: str, price: float, amount: float, order_type: str = 'limit') -> str: order = Order( id=self._generate_order_id(), user=user, side=side, price=price, amount=amount, order_type=order_type, timestamp=time.time() ) if side == 'buy': self.buy_orders.append(order) # Sort buy orders DESC self.buy_orders.sort(key=lambda x: x.price, reverse=True) else: self.sell_orders.append(order) # Sort sell orders ASC self.sell_orders.sort(key=lambda x: x.price) return order.id def match_orders(self) -> List[Dict]: matched_trades = [] while self.buy_orders and self.sell_orders: best_buy = self.buy_orders[0] best_sell = self.sell_orders[0] # Check if buy price >= sell price if best_buy.price >= best_sell.price: # Match at sell price (or buy price? Exchange determines) trade_price = best_sell.price trade_amount = min(best_buy.amount, best_sell.amount) # Record trade trade = { 'buyer': best_buy.user, 'seller': best_sell.user, 'price': trade_price, 'amount': trade_amount, 'value': trade_price * trade_amount, 'timestamp': time.time() } matched_trades.append(trade) self.trades.append(trade) # Update orders best_buy.amount -= trade_amount best_sell.amount -= trade_amount # Remove filled orders if best_buy.amount <= 0: self.buy_orders.pop(0) if best_sell.amount <= 0: self.sell_orders.pop(0) else: break return matched_trades def get_current_price(self) -> Optional[float]: if self.buy_orders and self.sell_orders: return (self.buy_orders[0].price + self.sell_orders[0].price) / 2 return None def get_market_depth(self) -> Dict: return { 'bids': [(o.price, o.amount) for o in self.buy_orders[:5]], 'asks': [(o.price, o.amount) for o in self.sell_orders[:5]] } def get_metrics(self) -> Dict: return { 'buy_orders': len(self.buy_orders), 'sell_orders': len(self.sell_orders), 'trades': len(self.trades), 'current_price': self.get_current_price(), 'total_buy_value': sum(o.value for o in self.buy_orders), 'total_sell_value': sum(o.value for o in self.sell_orders) } # Create exchange exchange = OrderBook("BTC", "USD") print("Order Book Simulation:") print("Add orders:") exchange.add_order("Alice", 'buy', 60000, 1.5) exchange.add_order("Bob", 'buy', 59900, 0.5) exchange.add_order("Charlie", 'buy', 60100, 2.0) exchange.add_order("David", 'sell', 60200, 1.0) exchange.add_order("Eve", 'sell', 60300, 0.5) exchange.add_order("Frank", 'sell', 59800, 1.0) print("\n--- Matching ---") trades = exchange.match_orders() if trades: print(f"Trades executed: {len(trades)}") for trade in trades: print(f" {trade['buyer']} bought {trade['amount']:.4f} BTC at ${trade['price']:.2f}") else: print("No trades matched") print("\n--- Market Depth ---") depth = exchange.get_market_depth() print("Bids (Buy Orders):") for price, amount in depth['bids']: print(f" ${price:.2f}: {amount:.4f} BTC") print("Asks (Sell Orders):") for price, amount in depth['asks']: print(f" ${price:.2f}: {amount:.4f} BTC") print("\n--- Metrics ---") metrics = exchange.get_metrics() for k, v in metrics.items(): print(f" {k}: {v}") # ---------------------------------------------------------------- # PART B: AMM / DEX SIMULATION (Uniswap-style) # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART B: Decentralised Exchange (AMM) Simulation") print("-"*60) class AMMExchange: def __init__(self, token_a: str, token_b: str, reserve_a: float, reserve_b: float): self.token_a = token_a self.token_b = token_b self.reserve_a = reserve_a self.reserve_b = reserve_b self.fee = 0.003 # 0.3% self.lp_tokens: Dict[str, float] = {} self.total_lp_supply = 0 self.swaps = [] self.transactions = [] def get_price(self) -> float: return self.reserve_b / self.reserve_a def swap_a_for_b(self, user: str, amount_a: float) -> Optional[float]: if amount_a > self.reserve_a: print("Insufficient reserve") return None # Apply fee amount_a_with_fee = amount_a * (1 - self.fee) amount_b_out = self.reserve_b * (amount_a_with_fee / (self.reserve_a + amount_a_with_fee)) self.reserve_a += amount_a self.reserve_b -= amount_b_out self.swaps.append({ 'user': user, 'direction': f'{self.token_a}→{self.token_b}', 'amount_in': amount_a, 'amount_out': amount_b_out, 'timestamp': time.time() }) print(f"Swapped {amount_a:.2f} {self.token_a} for {amount_b_out:.2f} {self.token_b}") return amount_b_out def swap_b_for_a(self, user: str, amount_b: float) -> Optional[float]: if amount_b > self.reserve_b: print("Insufficient reserve") return None amount_b_with_fee = amount_b * (1 - self.fee) amount_a_out = self.reserve_a * (amount_b_with_fee / (self.reserve_b + amount_b_with_fee)) self.reserve_b += amount_b self.reserve_a -= amount_a_out self.swaps.append({ 'user': user, 'direction': f'{self.token_b}→{self.token_a}', 'amount_in': amount_b, 'amount_out': amount_a_out, 'timestamp': time.time() }) print(f"Swapped {amount_b:.2f} {self.token_b} for {amount_a_out:.2f} {self.token_a}") return amount_a_out def add_liquidity(self, user: str, amount_a: float, amount_b: float) -> float: current_ratio = self.reserve_a / self.reserve_b if amount_a / amount_b != current_ratio: # Adjust to maintain ratio if amount_a / amount_b > current_ratio: amount_a = amount_b * current_ratio else: amount_b = amount_a / current_ratio self.reserve_a += amount_a self.reserve_b += amount_b # Mint LP tokens lp_amount = amount_a + amount_b # Simplified self.lp_tokens[user] = self.lp_tokens.get(user, 0) + lp_amount self.total_lp_supply += lp_amount print(f"Added liquidity: {amount_a:.2f} {self.token_a}, {amount_b:.2f} {self.token_b}, minted {lp_amount:.2f} LP tokens") return lp_amount def remove_liquidity(self, user: str, lp_amount: float) -> Tuple[float, float]: if self.lp_tokens.get(user, 0) < lp_amount: print("Insufficient LP tokens") return (0, 0) # Share of pool share = lp_amount / self.total_lp_supply amount_a_out = self.reserve_a * share amount_b_out = self.reserve_b * share self.reserve_a -= amount_a_out self.reserve_b -= amount_b_out self.lp_tokens[user] -= lp_amount self.total_lp_supply -= lp_amount print(f"Removed liquidity: {amount_a_out:.2f} {self.token_a}, {amount_b_out:.2f} {self.token_b}") return (amount_a_out, amount_b_out) def get_metrics(self) -> Dict: return { 'token_a': self.token_a, 'token_b': self.token_b, 'reserve_a': self.reserve_a, 'reserve_b': self.reserve_b, 'price': self.get_price(), 'fee': self.fee, 'num_lps': len(self.lp_tokens), 'total_lp': self.total_lp_supply, 'num_swaps': len(self.swaps) } # Create AMM amm = AMMExchange("ETH", "USDC", 100, 200000) print(f"AMM Created: 100 ETH, 200,000 USDC") print(f"Initial Price: {amm.get_price():.2f} USDC/ETH") print("\n--- Add Liquidity ---") amm.add_liquidity("Alice", 50, 100000) amm.add_liquidity("Bob", 30, 60000) print("\n--- Swaps ---") amm.swap_a_for_b("Charlie", 5) # Sell ETH amm.swap_b_for_a("David", 5000) # Buy ETH with USDC print("\n--- Metrics ---") metrics = amm.get_metrics() for k, v in metrics.items(): print(f" {k}: {v}") # ---------------------------------------------------------------- # PART C: EXCHANGE COMPARISON # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART C: Exchange Comparison Dashboard") print("-"*60) exchange_comparison = pd.DataFrame({ 'Exchange': ['Binance', 'Coinbase', 'Kraken', 'Uniswap', 'dYdX', 'Curve'], 'Type': ['CEX', 'CEX', 'CEX', 'DEX', 'Hybrid', 'DEX'], '24h Volume (B)': [15, 3, 1.5, 2.5, 1.2, 0.8], 'Pairs': [1400, 250, 350, 'Many', 40, 'Many'], 'Trading Fee': ['0.1%', '0.5%', '0.16%', '0.3%', '0.05%', '0.04%'], 'Security Score': [8, 9, 8, 7, 7, 8], 'Regulated': ['Yes (various)', 'Yes', 'Yes', 'Partial', 'Partial', 'Partial'] }) print(exchange_comparison.to_string(index=False)) # Visualise exchange volumes fig, ax = plt.subplots(figsize=(10, 5)) ax.bar(exchange_comparison['Exchange'], exchange_comparison['24h Volume (B)'], color='teal', alpha=0.7) ax.set_ylabel('24h Volume (Billion USD)') ax.set_title('Exchange Daily Trading Volume Comparison') ax.grid(True, alpha=0.3) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('exchange_volumes.png', dpi=300, bbox_inches='tight') plt.show() print("Exchange volume chart saved as 'exchange_volumes.png'") # ---------------------------------------------------------------- # PART D: TRADING STRATEGY SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART D: Simple Trading Strategy Simulation") print("-"*60) class TradingSimulator: def __init__(self, initial_balance: float): self.balance = initial_balance self.holdings = 0 self.trades = [] self.pnl = [] def execute_buy(self, price: float, amount: float) -> bool: cost = price * amount if cost > self.balance: print(f"Insufficient balance: need {cost:.2f}, have {self.balance:.2f}") return False self.balance -= cost self.holdings += amount self.trades.append({ 'type': 'buy', 'price': price, 'amount': amount, 'cost': cost, 'timestamp': time.time() }) print(f"Bought {amount:.4f} at ${price:.2f}") return True def execute_sell(self, price: float, amount: float) -> bool: if amount > self.holdings: print(f"Insufficient holdings: have {self.holdings:.4f}, want {amount:.4f}") return False revenue = price * amount self.holdings -= amount self.balance += revenue self.trades.append({ 'type': 'sell', 'price': price, 'amount': amount, 'revenue': revenue, 'timestamp': time.time() }) print(f"Sold {amount:.4f} at ${price:.2f}") return True def get_portfolio_value(self, current_price: float) -> float: return self.balance + self.holdings * current_price def get_metrics(self, current_price: float) -> Dict: return { 'balance': self.balance, 'holdings': self.holdings, 'portfolio_value': self.get_portfolio_value(current_price), 'num_trades': len(self.trades), 'total_buy_cost': sum(t['cost'] for t in self.trades if t['type'] == 'buy'), 'total_sell_revenue': sum(t['revenue'] for t in self.trades if t['type'] == 'sell') } # Simulate trading with price data trader = TradingSimulator(10000) price_series = [2000, 2100, 2050, 2200, 2300, 2250, 2400, 2350, 2500] print("Trading Simulation:") for i, price in enumerate(price_series): print(f"\nDay {i+1}: Price = ${price:.2f}") if price < 2100 and trader.holdings == 0: trader.execute_buy(price, 4.0) # Buy when low elif price > 2300 and trader.holdings > 0: trader.execute_sell(price, 2.0) # Sell some when high elif price > 2400 and trader.holdings > 0: trader.execute_sell(price, trader.holdings) # Sell all final_price = price_series[-1] print(f"\nFinal Portfolio Value: ${trader.get_portfolio_value(final_price):.2f}") metrics = trader.get_metrics(final_price) for k, v in metrics.items(): print(f" {k}: {v}") # ---------------------------------------------------------------- # PART E: EXCHANGE SECURITY CHECKLIST # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART E: Exchange Security Checklist") print("-"*60) security_checklist = { "User Security": [ "Two-factor authentication (2FA)", "Withdrawal whitelisting", "Anti-phishing codes", "Session management" ], "Platform Security": [ "Cold storage for majority of funds", "Multi-sig wallets", "Regular security audits", "Bug bounty program" ], "Operational Security": [ "DDoS protection", "Regular penetration testing", "Incident response plan", "Data encryption" ], "Regulatory Compliance": [ "KYC/AML procedures", "Sanctions screening", "Transaction monitoring", "Regulatory reporting" ] } for category, items in security_checklist.items(): print(f"\n{category.upper()}:") for item in items: print(f" ✓ {item}") # ---------------------------------------------------------------- # PART F: SUMMARY AND RECOMMENDATIONS # ---------------------------------------------------------------- print("\n" + "="*70) print("PART F: Summary and Recommendations") print("="*70) print(""" Digital Asset Exchanges – Key Takeaways: 1. Exchanges facilitate trading of cryptocurrencies and digital assets. 2. Types: CEX (centralised, custodial), DEX (decentralised, non-custodial), Hybrid. 3. CEXs use order books with matching engines for trade execution. 4. DEXs use AMMs with liquidity pools and price algorithms. 5. Trading types: spot, margin, futures, options, perpetuals. 6. Key considerations: security, liquidity, fees, regulation, user experience. 7. Risks: hacks, regulatory changes, slippage, impermanent loss, counterparty risk. Recommendations: - Use CEXs for high liquidity and ease of use. - Use DEXs for self-custody and privacy. - Store only trading funds on exchanges. - Use hardware wallets for long-term storage. - Understand fee structures before trading. - Enable all security features (2FA, whitelisting). - Monitor regulatory developments. """)