Нажмите ESC, чтобы закрыть

Стакан ордеров vs AMM: Микроструктура рынка и HFT-арбитраж

Если вы до сих пор думаете, что сделка на бирже - это просто клик по кнопке «Buy», за которым происходит магия, у меня для вас новости. На уровне микросекунд и миллисекунд рынок - это жесткое поле боя, где ликвидность переливается из одного состояния в другое, а скорость исполнения и анатомия пула определяют, кто получит профит, а кто заплатят за проскальзывание (slippage) и токсичный поток.

В централизованном трейдинге (TradFi и CEX) правит Order Book. В DeFi базовым стандартом стал AMM. Но когда мы спускаемся на высокочастотный уровень (HFT), разница между ними оказывается не просто технологической, она фундаментально меняет механику ценообразования, арбитража и исполнения ордеров.

Давайте разберем, как устроена механика ликвидности под капотом обеих систем, где кроются неявные издержки и как использовать эти знания на практике.

1. Анатомия L2/L3 стакана: Как на самом деле выглядит ликвидность

Большинство розничных трейдеров видят стакан L2: агрегированные объемы на каждом ценовом уровне. Но HFT-алгоритмы и институционалы работают с L3 (Order-by-Order) - сырым потоком данных, где каждое событие имеет свой уникальный идентификатор (order_id), точный таймштамп и позицию в очереди.

Market Data
 

Принцип Price-Time Priority (FIFO)

В классическом matching engine ордера исполняются строго по приоритету:

  • Цена (лучшая цена получает приоритет).
  • Время (при равной цене первым исполняется тот, кто встал в очередь раньше).

Из-за очереди по времени возникают два ключевых эффекта микроструктуры:

Adverse Selection (Неблагоприятный выбор): Если ваш лимитный ордер на покупку быстро исполняется, велика вероятность, что на рынок пришел крупный продавец с агрессивным потоком (toxic flow), и цена продолжит падать дальше.

Queue Position Value: Место в начале очереди ценового уровня имеет самостоятельную стоимость. Высокочастотные роботы постоянно отменяют и перевыставляют ордера (механика Spoofing/Layering или адаптивное управление ликвидностью), чтобы удерживать приоритет, не принимая на себя лишний инвентарный риск.

2. AMM: От классического Constant Product к концентрированной ликвидности

AMM принципиально отличается от стакана: здесь нет очереди ордеров. Цена определяется математической функцией инварианта.

Constant Product (v2): x · y = k

В классическом Uniswap v2 ликвидность распределена от нуля до бесконечности.

При совершении сделки на объем Δx трейдер забирает из пула Δy, вычисляемый с учетом комиссии γ = (1 - fee):

Δy = (y · Δx · γ) / (x + Δx · γ)

Цена исполнения не фиксирована, она «скользит» вдоль кривой в момент исполнения.

Concentrated Liquidity (v3 / Tick-based)

Uniswap v3 превратил AMM в подобие стакана, разрешив поставщикам ликвидности (LP) задавать диапазоны [Pa, Pb].

Цена разбита на тики (ticks), где каждый тик соответствует изменению цены на 0.01% (1 bps):

P(i) = 1.0001i

Ликвидность L внутри диапазона работает как «виртуальный» инвариант, но при пересечении границы тика активная ликвидность резко меняется. Для высокочастотного арбитражера это означает следующее: стакан AMM v3 дискретен, и его глубина меняется ступенчато при пробитии тиков.

3. Сравнительный анализ: Microstructure Matrix

ПараметрOrder Book (CEX/TradFi)AMM (Uniswap v2)Concentrated AMM (v3)
Приоритет исполненияPrice-Time (FIFO) / Pro-RataGas Price / MEV (Priority Fee)Gas Price / MEV (Priority Fee)
Задержка (Latency)Микросекунды / НаносекундыВремя блока (или slotted latency)Время блока / P2P-мемпул
Формирование ценыНепрерывный аукцион (Continuous Double Auction)Динамически от объёма сделки (x · y = k)Динамически в рамках активного тика
Издержки ликвидностиНепостоянный убыток отсутствует (но есть Inventory Risk)Impermanent Loss (IL)Loss-Versus-Rebalancing (LVR)
Прозрачность потокаL3 Data Feeds (Pitch, ITCH, FIX)Mempool (до блока) / On-chain (после)Mempool (до блока) / On-chain (после)

4. Скрытые механики: MEV, LVR и Toxic Flow

В стакане CEX высокочастотник сражается за наносекунды физической сетевой задержки (colocation в дата-центре биржи, оптоволокно, FPGA-платы).

В DeFi понятие времени искривляется: фундаментальную роль играет структурирование блока.

MEV (Maximal Extractable Value)

В AMM порядок транзакций внутри блока формируется поисковиками (Searchers) и строителями блоков (Builders). Это порождает специфические HFT-механики:

  • Front-running / Back-running: Перехват сделок в мемпуле путем предложения более высокой комиссии (Priority Fee).
  • Sandwich Attacks: Покупка перед крупной пользовательской транзакцией для завышения цены и немедленная продажа сразу после нее.

LVR (Loss-Versus-Rebalancing)

Все привыкли считать риски LP через Impermanent Loss (IL). Но на высокочастотном уровне актуальнее метрика LVR, предложенная исследователями из Колумбийского университета и Paradigm.

LVR (Loss-Versus-Rebalancing) — это систематический убыток поставщика ликвидности в AMM по сравнению с тем же портфелем, постоянно ребалансируемым на CEX с использованием внешних цен.

Причина LVR - арбитраж волатильности. Когда цена на CEX уходит вперед, AMM-пул оставляет устаревшую цену (stale price). Высокочастотный арбитражер видит этот спред, забирает дешевую ликвидность из AMM и перекрывает ее на CEX. Поставщик ликвидности в AMM всегда исполняется по худшей цене против информированного потока (toxic flow).

LVR ≈ (σ² / 8) · ∫0T St · Lt dt

Где σ — волатильность актива, St — цена, Lt — активная ликвидность. Вывод: Чем выше волатильность рынка, тем больше денег LP отдают HFT-арбитражерам.

5. Практика: Python-скрипт расчета котировки AMM v3 vs L2 Depth

Перейдем к коду. Напишем рабочий инструмент для расчета реальной цены исполнения (с учетом проскальзывания) для условного ордера, сравнивая глубину L2-стакана и пул Constant Product AMM.

Код написан на чистом Python без тяжелых сторонних фреймворков.

from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import List
class FeeMode(Enum):
    QUOTE = "quote"  # комиссия удерживается из входящего USDT
    BASE = "base"    # комиссия удерживается из полученного ETH
@dataclass
class AskLevel:
    price: float
    volume: float
class OrderBookL2:
    """
    L2 стакан (Ask сторона).
    Пример пары ETH/USDT:
        price  = USDT за 1 ETH
        volume = ETH
    """
    def __init__(
        self,
        asks: List[tuple[float, float]],
        taker_fee: float = 0.001,
    ) -> None:
        if not (0 <= taker_fee < 1):
            raise ValueError("taker_fee должен быть в диапазоне [0, 1)")
        self.taker_fee = float(taker_fee)
        self.asks: List[AskLevel] = []
        for price, volume in asks:
            if price <= 0:
                raise ValueError("Цена должна быть > 0")
            if volume <= 0:
                raise ValueError("Объем должен быть > 0")
            self.asks.append(
                AskLevel(
                    price=float(price),
                    volume=float(volume),
                )
            )
        self.asks.sort(key=lambda x: x.price)
    def best_ask(self) -> float:
        if not self.asks:
            raise ValueError("Стакан пуст")
        return self.asks[0].price
    def spot_price(self) -> float:
        return self.best_ask()
    def total_liquidity_quote(self) -> float:
        return sum(
            level.price * level.volume
            for level in self.asks
        )
    def total_liquidity_base(self) -> float:
        return sum(
            level.volume
            for level in self.asks
        )
    def simulate_buy(
        self,
        amount_in_quote: float,
        mutate: bool = True,
        fee_mode: FeeMode = FeeMode.QUOTE,
    ) -> tuple[float, float]:
        """
        Покупка базового актива за amount_in_quote.
        Возвращает:
            (
                получено_базового_актива,
                средняя_эффективная_цена
            )
        """
        if amount_in_quote <= 0:
            raise ValueError(
                "amount_in_quote должен быть > 0"
            )
        if fee_mode == FeeMode.QUOTE:
            quote_for_trade = (
                amount_in_quote *
                (1.0 - self.taker_fee)
            )
        else:
            quote_for_trade = amount_in_quote
        remaining_quote = quote_for_trade
        total_base_bought = 0.0
        new_levels: List[AskLevel] = []
        for level in self.asks:
            if remaining_quote <= 0:
                new_levels.append(level)
                continue
            level_cost = (
                level.price *
                level.volume
            )
            if remaining_quote >= level_cost:
                total_base_bought += level.volume
                remaining_quote -= level_cost
            else:
                base_from_level = (
                    remaining_quote /
                    level.price
                )
                total_base_bought += base_from_level
                remaining_volume = (
                    level.volume -
                    base_from_level
                )
                if remaining_volume > 1e-12:
                    new_levels.append(
                        AskLevel(
                            level.price,
                            remaining_volume,
                        )
                    )
                remaining_quote = 0.0
        if remaining_quote > 1e-9:
            raise ValueError(
                "Недостаточно ликвидности в стакане"
            )
        if fee_mode == FeeMode.BASE:
            total_base_bought *= (
                1.0 - self.taker_fee
            )
        if total_base_bought <= 0:
            raise ValueError(
                "Получен нулевой объем"
            )
        avg_price = (
            amount_in_quote /
            total_base_bought
        )
        if mutate:
            self.asks = new_levels
        return total_base_bought, avg_price
class ConstantProductAMM:
    """
    Uniswap V2 style AMM
    x = ETH
    y = USDT
    spot = y / x
    """
    def __init__(
        self,
        reserve_x: float,
        reserve_y: float,
        fee: float = 0.003,
    ) -> None:
        if reserve_x <= 0:
            raise ValueError(
                "reserve_x должен быть > 0"
            )
        if reserve_y <= 0:
            raise ValueError(
                "reserve_y должен быть > 0"
            )
        if not (0 <= fee < 1):
            raise ValueError(
                "fee должен быть в диапазоне [0, 1)"
            )
        self.x = float(reserve_x)
        self.y = float(reserve_y)
        self.fee = float(fee)
    def spot_price(self) -> float:
        return self.y / self.x
    def invariant(self) -> float:
        return self.x * self.y
    def simulate_buy(
        self,
        amount_y_in: float,
        mutate: bool = True,
    ) -> tuple[float, float]:
        """
        Покупка ETH за USDT.
        Возвращает:
            (
                получено_ETH,
                средняя_цена
            )
        """
        if amount_y_in <= 0:
            raise ValueError(
                "amount_y_in должен быть > 0"
            )
        y_effective = (
            amount_y_in *
            (1.0 - self.fee)
        )
        x_out = (
            self.x *
            y_effective
        ) / (
            self.y +
            y_effective
        )
        if x_out <= 0:
            raise ValueError(
                "Получен нулевой объем"
            )
        if x_out >= self.x:
            raise ValueError(
                "Недостаточно ликвидности пула"
            )
        avg_price = (
            amount_y_in /
            x_out
        )
        if mutate:
            self.x -= x_out
            self.y += amount_y_in
        return x_out, avg_price
def print_trade_result(
    title: str,
    received: float,
    avg_price: float,
    spot_price: float,
) -> None:
    slippage = (
        (avg_price - spot_price)
        / spot_price
    ) * 100
    print(
        f"{title:<12}"
        f" Получено: {received:.6f}"
        f" | Средняя цена: {avg_price:,.4f}"
        f" | Проскальзывание: {slippage:.4f}%"
    )
def main() -> None:
    asks = [
        (3000.0, 1.5),
        (3001.0, 2.0),
        (3002.5, 5.0),
        (3005.0, 10.0),
        (3010.0, 25.0),
    ]
    orderbook = OrderBookL2(
        asks=asks,
        taker_fee=0.001,
    )
    amm = ConstantProductAMM(
        reserve_x=1000.0,
        reserve_y=3_000_000.0,
        fee=0.003,
    )
    trade_size = 15_000.0
    ob_spot = orderbook.spot_price()
    amm_spot = amm.spot_price()
    ob_received, ob_avg = orderbook.simulate_buy(
        amount_in_quote=trade_size,
        mutate=True,
        fee_mode=FeeMode.QUOTE,
    )
    amm_received, amm_avg = amm.simulate_buy(
        amount_y_in=trade_size,
        mutate=True,
    )
    print(
        f"\n=== Сравнение исполнения заявки "
        f"на {trade_size:,.2f} USDT ===\n"
    )
    print_trade_result(
        "ORDERBOOK",
        ob_received,
        ob_avg,
        ob_spot,
    )
    print_trade_result(
        "AMM V2",
        amm_received,
        amm_avg,
        amm_spot,
    )
    print("\n=== Состояние после сделки ===\n")
    if orderbook.asks:
        print(
            f"Best Ask: "
            f"{orderbook.best_ask():,.4f}"
        )
    else:
        print("Стакан полностью выкуплен")
    print(
        f"AMM Spot: "
        f"{amm.spot_price():,.4f}"
    )
    print(
        f"AMM Reserves: "
        f"{amm.x:.6f} ETH | "
        f"{amm.y:.2f} USDT"
    )
if __name__ == "__main__":
    main()

Как трактовать результаты

В глубоких пулах AMM малые ордера исполняются с минимальным проскальзыванием, но при росте объема цена в AMM растет по выпуклой кривой. В стакане же все зависит от «стенок» (liquidity walls). Если в стакане тонко, вы пробьете несколько уровней и получите разнос по цене куда хуже, чем в AMM.

6. Гибридные модели: Как DEX внедряют Order Book и почему CEX смотрят на AMM

Граница между стаканами и AMM постепенно размывается. Высокочастотные трейдеры и институционалы быстро уперлись в потолок возможностей классического Uniswap v2: низкая капиталоэффективность и невозможность выставлять сложные лимитные ордера (Stop-loss, Take-profit, Iceberg) делали DEX неудобными для активного market making.

Это привело к эволюционному сдвигу и появлению гибридных архитектур.

1. On-Chain и L2 Order Books (dYdX, Hyperliquid, Vertex)

С появлением высокопроизводительных L1/L2 сетей (Aptos, Sui, Arbitrum) и специализированных AppChain стал возможен запуск полноценных стаканов прямо в блокчейне.

Off-chain matching + On-chain settlement: Модули сведения ордеров работают на ультра-быстрых движках вне сети (для достижения задержки < 10 мс), а результаты исполнения и маржинальные требования фиксируются в смарт-контрактах.

Fully On-chain (Hyperliquid, Serum/Ellipsis): Стакан полностью живёт в консенсусе блокчейна. Главный вызов здесь - обработка фатального объема операций: замена и отмена ордеров (Cancel/Replace) в HFT составляет до 95–98% от всех входящих транзакций.

2. Intent-Based архитектура и RFQ (Request for Quote)

Модель "Intents" (Uniswap X, 1inch Fusion, CoW Protocol) фактически возвращает институциональный подход к исполнению.

Трейдер подписывает не транзакцию взаимодействия с конкретным пулом, а намерение (например: «Хочу обменять 100 ETH на не менее чем 300,000 USDC»). Далее сеть сторонних исполнителей (Fillers / Solvers) соревнуется за право исполнить этот ордер, используя любые источники ликвидности — CEX, private market maker inventory или DEX.

Architecture
 

Для практикующего трейдера это означает нулевой slippage и защиту от MEV-сэндвичей: весь риск проскальзывания и исполнения берет на себя Solver, зарабатывая на межактивном арбитраже.

7. Практика: Продвинутый скрипт арбитража между CEX L2 Order Book и AMM v2

На практике HFT-боты постоянно ищут ценовые дисбалансы между CEX и AMM. Если на CEX цена актива взлетает из-за рыночной покупки, пул AMM на некоторое время остается «устаревшим» (stale). Арбитражер покупкой в AMM сдвигает его цену до уровня CEX, продавая купленный объем обратно на CEX.

Ниже представлен рабочий Python-скрипт, который в реальном времени рассчитывает оптимальный размер арбитражной сделки (dx) с учетом комиссии AMM, глубины стакана CEX и комиссии мейкера/тейкера.

from __future__ import annotations
from dataclasses import dataclass
from typing import List, Dict, Any
@dataclass
class BidLevel:
    price: float
    volume: float
class OrderBookSide:
    """
    Bid сторона стакана.
    price  = цена покупки
    volume = объем базового актива
    """
    def __init__(self, bids: List[tuple[float, float]]):
        self.bids: List[BidLevel] = []
        for price, volume in bids:
            if price <= 0:
                raise ValueError("Цена должна быть > 0")
            if volume <= 0:
                raise ValueError("Объем должен быть > 0")
            self.bids.append(
                BidLevel(
                    float(price),
                    float(volume)
                )
            )
        self.bids.sort(
            key=lambda x: x.price,
            reverse=True
        )
    def is_empty(self) -> bool:
        return len(self.bids) == 0
    def best_bid(self) -> float:
        if self.is_empty():
            raise ValueError("Стакан пуст")
        return self.bids[0].price
    def cumulative_levels(self) -> List[tuple[float, float]]:
        """
        Возвращает точки изменения ликвидности.
        [
            (2 ETH, VWAP до 2 ETH),
            (7 ETH, VWAP до 7 ETH),
            ...
        ]
        """
        result = []
        cumulative_x = 0.0
        cumulative_y = 0.0
        for level in self.bids:
            cumulative_x += level.volume
            cumulative_y += level.volume * level.price
            result.append(
                (
                    cumulative_x,
                    cumulative_y
                )
            )
        return result
    def execute_sell(
        self,
        amount_x: float
    ) -> tuple[float, float]:
        """
        Продажа amount_x в стакан.
        Возвращает:
        (
            получено_USDT,
            VWAP
        )
        """
        if amount_x <= 0:
            raise ValueError(
                "amount_x должен быть > 0"
            )
        remaining_x = amount_x
        received_y = 0.0
        for level in self.bids:
            if remaining_x <= 0:
                break
            executed = min(
                remaining_x,
                level.volume
            )
            received_y += (
                executed *
                level.price
            )
            remaining_x -= executed
        if remaining_x > 1e-9:
            raise ValueError(
                "Недостаточно ликвидности стакана"
            )
        vwap = received_y / amount_x
        return received_y, vwap
class AMMPool:
    """
    Constant Product AMM
    x = ETH
    y = USDT
    """
    def __init__(
        self,
        reserve_x: float,
        reserve_y: float,
        fee: float = 0.003
    ):
        if reserve_x <= 0:
            raise ValueError(
                "reserve_x должен быть > 0"
            )
        if reserve_y <= 0:
            raise ValueError(
                "reserve_y должен быть > 0"
            )
        if not (0 <= fee < 1):
            raise ValueError(
                "fee должен быть в диапазоне [0,1)"
            )
        self.x = float(reserve_x)
        self.y = float(reserve_y)
        self.fee = float(fee)
    def spot_price(self) -> float:
        return self.y / self.x
    def calculate_out_x(
        self,
        amount_y_in: float
    ) -> float:
        if amount_y_in <= 0:
            raise ValueError(
                "amount_y_in должен быть > 0"
            )
        y_effective = (
            amount_y_in *
            (1.0 - self.fee)
        )
        x_out = (
            self.x *
            y_effective
        ) / (
            self.y +
            y_effective
        )
        return x_out
    def calculate_required_y_for_x(
        self,
        target_x_out: float
    ) -> float:
        """
        Инверсия формулы AMM.
        Сколько USDT нужно внести,
        чтобы получить target_x_out.
        """
        if target_x_out <= 0:
            raise ValueError(
                "target_x_out должен быть > 0"
            )
        if target_x_out >= self.x:
            raise ValueError(
                "Нельзя вывести весь резерв"
            )
        y_effective = (
            target_x_out *
            self.y
        ) / (
            self.x -
            target_x_out
        )
        amount_y_in = (
            y_effective /
            (1.0 - self.fee)
        )
        return amount_y_in
def find_optimal_arbitrage(
    amm: AMMPool,
    cex_bids: OrderBookSide,
    cex_fee: float = 0.001
) -> Dict[str, Any]:
    if not (0 <= cex_fee < 1):
        raise ValueError(
            "cex_fee должен быть в диапазоне [0,1)"
        )
    if cex_bids.is_empty():
        return {
            "opportunity": False,
            "reason": "Пустой стакан CEX"
        }
    best_bid = cex_bids.best_bid()
    if (
        best_bid *
        (1.0 - cex_fee)
        <=
        amm.spot_price()
    ):
        return {
            "opportunity": False,
            "reason": "Спред отсутствует"
        }
    best_result = None
    best_profit = float("-inf")
    cumulative = cex_bids.cumulative_levels()
    for cumulative_x, cumulative_y in cumulative:
        try:
            required_usdt = (
                amm.calculate_required_y_for_x(
                    cumulative_x
                )
            )
            gross_usdt = cumulative_y
            net_usdt = (
                gross_usdt *
                (1.0 - cex_fee)
            )
            profit = (
                net_usdt -
                required_usdt
            )
            if profit > best_profit:
                avg_buy_price = (
                    required_usdt /
                    cumulative_x
                )
                avg_sell_price = (
                    gross_usdt /
                    cumulative_x
                )
                amm_spot = (
                    amm.spot_price()
                )
                impact_pct = (
                    (
                        avg_buy_price -
                        amm_spot
                    )
                    /
                    amm_spot
                ) * 100
                roi_pct = (
                    profit /
                    required_usdt
                ) * 100
                best_profit = profit
                best_result = {
                    "opportunity": True,
                    "input_usdt_amm": required_usdt,
                    "bought_x": cumulative_x,
                    "gross_usdt_cex": gross_usdt,
                    "net_usdt_cex": net_usdt,
                    "net_profit_usdt": profit,
                    "roi_pct": roi_pct,
                    "amm_spot_price": amm_spot,
                    "amm_avg_buy_price": avg_buy_price,
                    "amm_price_impact_pct": impact_pct,
                    "cex_vwap": avg_sell_price,
                }
        except ValueError:
            continue
    if best_result is None:
        return {
            "opportunity": False,
            "reason": "Ликвидность недостаточна"
        }
    if best_result["net_profit_usdt"] <= 0:
        return {
            "opportunity": False,
            "reason": "Проскальзывание уничтожает прибыль"
        }
    return best_result
def main():
    amm = AMMPool(
        reserve_x=1000.0,
        reserve_y=3_000_000.0,
        fee=0.003
    )
    cex = OrderBookSide([
        (3050.0, 2.0),
        (3048.0, 5.0),
        (3045.0, 10.0),
        (3040.0, 20.0),
        (3030.0, 50.0),
    ])
    result = find_optimal_arbitrage(
        amm,
        cex,
        cex_fee=0.0005
    )
    print(
        "\n=== Результат поиска арбитража ===\n"
    )
    if not result["opportunity"]:
        print(
            f"Статус: ОТМЕНА\n"
            f"Причина: {result['reason']}"
        )
        return
    print("Статус: НАЙДЕНА СВЯЗКА")
    print()
    print(
        f"Вход в AMM: "
        f"${result['input_usdt_amm']:,.2f}"
    )
    print(
        f"Куплено ETH: "
        f"{result['bought_x']:.6f}"
    )
    print(
        f"Выручка CEX: "
        f"${result['gross_usdt_cex']:,.2f}"
    )
    print(
        f"Чистая выручка CEX: "
        f"${result['net_usdt_cex']:,.2f}"
    )
    print(
        f"Чистый профит: "
        f"${result['net_profit_usdt']:,.2f}"
    )
    print(
        f"ROI: "
        f"{result['roi_pct']:.4f}%"
    )
    print(
        f"AMM Spot: "
        f"{result['amm_spot_price']:.4f}"
    )
    print(
        f"AMM Avg Buy: "
        f"{result['amm_avg_buy_price']:.4f}"
    )
    print(
        f"AMM Impact: "
        f"{result['amm_price_impact_pct']:.4f}%"
    )
    print(
        f"CEX VWAP: "
        f"{result['cex_vwap']:.4f}"
    )
if __name__ == "__main__":
    main()

8. Прикладные выводы для трейдера: Как не платить «налог на неведение»

Понимание микроструктуры - это не просто теоретическая академическая база. Это инструмент, спасающий депозит от скрытых утечек капитала.

  • Контролируйте тип ордера под задачи рынка: На CEX покупка «по рынку» (Market Order) большого объема гарантированно исполняет вас об несколько уровней стакана, давая отрицательное проскальзывание. Если вам нужна срочность, используйте ордера IOC (Immediate-or-Cancel) или FOK (Fill-or-Kill) с явным указанием худшей приемлемой цены.
  • Считайте эффективную глубину, а не спред: Узкий спред на L2 ($0.01) часто бывает иллюзией. Если на лучшем Bid/Ask стоит объем в $100, ваш ордер на $50,000 «прошьет» стакан до глубин с совершенно другой ценой.
  • Учитывайте токсичность потока в AMM: Если вы предоставляете ликвидность в Uniswap v3 в узком диапазоне во время выхода важных новостей или высокой волатильности, вы становитесь мишенью для HFT-арбитражера. Метрика LVR сожрет всю доходность от комиссий за считанные минуты.
  • Защищайтесь от MEV на DEX: При сделках в AMM всегда ограничивайте параметр Slippage Tolerance (ставите не более 0.1–0.3%) или используйте частные RPC-узлы (например, Flashbots Protect / MEV-Blocker), чтобы ваши транзакции не попадали в публичный мемпул для сэндвич-атак.

Делитесь в комментариях, с какими объемами проскальзывания вы чаще всего сталкиваетесь при исполнении крупных ордеров и какую модель (CEX Order Book или DEX AMM) предпочитаете для повседневных задач!


FAQ

Стакан (Order Book) сводит лимитные и рыночные заявки через непрерывный двойной аукцион по принципу приоритета цены и времени (FIFO), в то время как автоматизированные маркетмейкеры (AMM) исполняют сделки алгоритмически против пулов ликвидности на основе математических инвариантов вроде X x Y = k.

Impermanent Loss отражает относительное изменение стоимости портфеля по сравнению с пассивным удержанием активов (HODL), тогда как Loss-Versus-Rebalancing (LVR) измеряет реальные нехеджируемые издержки от неблагоприятного выбора, которые забирают HFT-арбитражники при отставании цен в AMM от внешних котировок CEX.

MEV-боты сканируют публичный мемпул, перехватывают целевую ордер-транзакцию и выставляют перед ней собственный ордер с повышенной комиссией (front-running), искусственно завышая цену актива вплоть до максимального порога проскальзывания пользователя, после чего мгновенно фиксируют прибыль встречной продажей (back-running) в том же блоке.
Martyn Borkowski

I am a crypto trader specializing in digital assets and blockchain markets.

My focus is on identifying opportunities, managing risk, and optimizing strategies to achieve consistent growth in the fast-evolving world of cryptocurrency.

Verification & Professional Profiles: X Profile

...

Поделитесь своим мнением

Ваш e-mail не будет опубликован. Обязательные поля отмечены *