> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intention.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Сопоставление

> Стакан заявок, как представлен приоритет «цена — время» и как относительно него отрабатывают срок действия и предотвращение самосделок.

Сопоставление — стадия внутри [исполнения ядра](/ru/protocol/architecture/kernel), а не сервис, с которым блокчейн общается. Оно берёт ордера блока в зафиксированной последовательности, проводит их по стакану и порождает исполнения. Оно не двигает ничей баланс — это работа [клиринговой палаты](/ru/protocol/architecture/clearinghouse), и она идёт после того, как сопоставление закончилось.

Именно разделение этих двух вещей делает движок тестируемым. Сопоставление отвечает на вопрос, *что против чего сторговалось*. Клиринговая палата — на вопрос, *сколько это стоит и кто теперь кому должен*.

<h2 id="the-book">
  Стакан
</h2>

У каждого инструмента свой стакан, который держится в памяти как три взаимодействующие структуры:

<div className="dg" data-dg="matching-book">
  <div className="dg-c" style={{aspectRatio:"720 / 302"}}>
    <svg className="dg-w" viewBox="0 0 720 302" aria-hidden="true">
      <path className="dg-wire dg-soft" d="M 348.60 82.00 L 352.60 82.00" />

      <path className="dg-wire dg-soft" d="M 438.20 82.00 L 442.20 82.00" />

      <path className="dg-wire dg-soft" d="M 527.80 82.00 L 531.80 82.00" />

      <path className="dg-wire dg-soft" d="M 617.40 82.00 L 621.40 82.00" />

      <path className="dg-wire dg--blue" d="M 205.00 68.00 L 238.60 68.00" />

      <path className="dg-head dg--blue" d="M 245.00 68.00 L 238.60 72.40 L 238.60 63.60 Z" />

      <path className="dg-wire dg--sky" d="M 205.00 162.00 L 238.60 162.00" />

      <path className="dg-head dg--sky" d="M 245.00 162.00 L 238.60 166.40 L 238.60 157.60 Z" />
    </svg>

    <div className="dg-band" style={{left:"34.7222%",top:"9.9338%",width:"65.2778%",height:"56.2914%"}}><span className="dg-cap">Slab arena — одна выделенная область слотов ордеров</span></div>
    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"9.9338%",width:"27.7778%",height:"25.1656%"}}><span className="dg-t">Ценовые уровни</span><span className="dg-s">отображение цена → уровень</span><span className="dg-n">вершина находится проходом до конца, а не сканированием</span></div>
    <div className="dg-b dg--sky" style={{left:"0.0000%",top:"41.0596%",width:"27.7778%",height:"25.1656%"}}><span className="dg-t">Индекс ордеров</span><span className="dg-s">id ордера → слот</span><span className="dg-n">отмена и изменение — константное время</span></div>
    <div className="dg-b dg--yellow" style={{left:"36.9444%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">ордер</span></div>
    <div className="dg-b dg--yellow" style={{left:"49.3889%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">ордер</span></div>
    <div className="dg-b dg--yellow" style={{left:"61.8333%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">ордер</span></div>
    <div className="dg-b dg--yellow" style={{left:"74.2778%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">ордер</span></div>
    <div className="dg-b dg--yellow" style={{left:"86.7222%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">ордер</span></div>
    <div className="dg-b dg-plain dg-left" style={{left:"36.9444%",top:"41.3907%",width:"60.8333%",height:"15.2318%"}}><span className="dg-s">Двусвязная цепочка в порядке поступления: приоритет внутри уровня позиционный, а не вычисляемый.</span></div>
    <div className="dg-b dg-dashed dg-left" style={{left:"0.0000%",top:"74.8344%",width:"100.0000%",height:"20.5298%"}}><span className="dg-t">Почему порядок слотов фиксирован</span><span className="dg-s">Слоты переиспользуются в фиксированном порядке, индекс — с фиксированным зерном. Не ради производительности: разный порядок слотов у двух валидаторов — это форк.</span></div>
    <div className="dg-lbl" style={{left:"31.2500%",top:"17.8808%",width:"15.2778%",whiteSpace:"normal"}}>голова каждого уровня</div>
    <div className="dg-lbl" style={{left:"31.2500%",top:"62.9139%",width:"15.2778%",whiteSpace:"normal"}}>прямой поиск</div>
  </div>
</div>

| Структура           | Роль                                                                                                                        |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Ценовые уровни**  | Упорядоченное отображение цены в уровень, так что лучший бид и лучший аск находятся проходом до конца, а не сканированием   |
| **Цепочка ордеров** | Двусвязный список, нанизывающий ордера в порядке поступления, так что приоритет внутри уровня позиционный, а не вычисляемый |
| **Индекс ордеров**  | Прямое отображение ID ордера в его слот, так что отмена и изменение выполняются за константное время, а не поиском          |

Ордера живут в **slab arena** — заранее выделенной области с константным временем выделения и освобождения. Поэтому операции со стаканом не выделяют память на горячем пути, а освободившиеся слоты переиспользуются в фиксированном порядке, а не там, куда их положит аллокатор. Последняя деталь — не выбор ради производительности: если бы два валидатора переиспользовали слоты в разном порядке, всё, что наблюдает раскладку слотов, разошлось бы.

Та же дисциплина применяется к индексу ордеров: он инициализируется фиксированным зерном, а не случайным. Хеш-таблица со случайным зерном на процесс — стандартная защита от атак на коллизии; на пути исполнения консенсуса это форк.

Цены всюду целочисленные — в субтиковых единицах, а не в десятичных дробях. Как это соотносится с тем, что вы отправляете, — см. [Точность](/ru/trading/precision).

<h2 id="priority">
  Приоритет
</h2>

Приоритет — сначала цена, затем позиция в цепочке на этой цене. «Время» — это каноническая позиция ордера в зафиксированной последовательности блока, а не момент его прихода на узел.

Именно это убирает гонку задержек внутри блока. У двух ордеров в одном блоке есть определённое старшинство, которое каждый валидатор вычисляет одинаково, и никакая близость к конкретному узлу его не меняет. Между блоками момент прихода по-прежнему важен, но единицей соревнования становится блок, а не микросекунда.

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

<h2 id="matching-an-order">
  Сопоставление ордера
</h2>

<div className="dg" data-dg="matching-walk">
  <div className="dg-c" style={{aspectRatio:"720 / 334"}}>
    <svg className="dg-w" viewBox="0 0 720 334" aria-hidden="true">
      <path className="dg-wire dg--blue" d="M 134.00 144.00 L 155.60 144.00" />

      <path className="dg-head dg--blue" d="M 162.00 144.00 L 155.60 148.40 L 155.60 139.60 Z" />

      <path className="dg-wire dg--sky" d="M 320.00 144.00 L 345.60 144.00" />

      <path className="dg-head dg--sky" d="M 352.00 144.00 L 345.60 148.40 L 345.60 139.60 Z" />

      <path className="dg-wire dg--green" d="M 510.00 144.00 L 535.60 144.00" />

      <path className="dg-head dg--green" d="M 542.00 144.00 L 535.60 148.40 L 535.60 139.60 Z" />

      <path className="dg-wire dg--sky" d="M 633.00 114.00 L 633.00 80.00 L 241.00 80.00 L 241.00 103.60" />

      <path className="dg-head dg--sky" d="M 241.00 110.00 L 236.60 103.60 L 245.40 103.60 Z" />

      <path className="dg-wire dg--green" d="M 633.00 174.00 L 633.00 213.60" />

      <path className="dg-head dg--green" d="M 633.00 220.00 L 628.60 213.60 L 637.40 213.60 Z" />

      <path className="dg-wire dg--sky" d="M 241.00 178.00 L 241.00 213.60" />

      <path className="dg-head dg--sky" d="M 241.00 220.00 L 236.60 213.60 L 245.40 213.60 Z" />
    </svg>

    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"35.3293%",width:"18.0556%",height:"15.5689%"}}><span className="dg-t">Входящий ордер</span></div>
    <div className="dg-b dg--yellow dg-round" style={{left:"23.0556%",top:"34.1317%",width:"20.8333%",height:"17.9641%"}}><span className="dg-t">Пересекает стакан?</span></div>
    <div className="dg-b dg--sky" style={{left:"49.4444%",top:"35.3293%",width:"20.8333%",height:"15.5689%"}}><span className="dg-t">Забрать лучший встречный уровень</span></div>
    <div className="dg-b dg--green" style={{left:"75.8333%",top:"35.3293%",width:"24.1667%",height:"15.5689%"}}><span className="dg-t">Выдать исполнение</span></div>
    <div className="dg-b dg--green" style={{left:"75.8333%",top:"67.0659%",width:"24.1667%",height:"25.7485%"}}><span className="dg-t">Готово</span></div>
    <div className="dg-b dg--sky dg-left" style={{left:"10.5556%",top:"67.0659%",width:"45.8333%",height:"25.7485%"}}><span className="dg-t">Встать в стакан или отклонить по сроку действия</span><span className="dg-s">GTC остаётся · IOC отменяет · FOK не исполняет ничего без полного исполнения · «только мейкер» отклоняется вместо пересечения</span></div>
    <div className="dg-lbl" style={{left:"60.6944%",top:"23.9521%",width:"27.7778%",whiteSpace:"normal"}}>остаток — следующий уровень</div>
    <div className="dg-lbl" style={{left:"87.9167%",top:"58.9820%"}}>остатка нет</div>
  </div>
</div>

Движок сопоставления раз за разом забирает голову встречной стороны, выдавая исполнение на каждого мейкера, которого он снимает, пока входящий ордер не исчерпан или пока стакан больше не пересекается. Что происходит с остатком, решает срок действия:

* **GTC** — оставить остаток в стакане.
* **IOC** — отменить остаток.
* **FOK** — если ордер нельзя исполнить целиком, не исполняется вообще ничего.
* **ALO** — только мейкер: если ордер забрал бы ликвидность, он отклоняется, а не пересекает стакан.

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

<h2 id="self-trade-prevention">
  Предотвращение самосделок
</h2>

Если входящий ордер сопоставился бы со стоящей в стакане ликвидностью того же владельца, сопоставление подавляется, а не исполняется. Какая сторона уступает — настраивается:

| Режим              | Поведение                                                             |
| ------------------ | --------------------------------------------------------------------- |
| **Отмена тейкера** | Входящий ордер отменяется                                             |
| **Отмена мейкера** | Стоящий в стакане ордер отменяется, а входящий продолжает исполняться |
| **Отмена обоих**   | Отменяются оба                                                        |

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

Принадлежность для этой проверки определяется на том уровне счёта, который отслеживает стакан. Взгляд со стороны торговли — см. [Предотвращение самосделок](/ru/trading/self-trade-prevention).

<h2 id="what-matching-does-not-do">
  Чего сопоставление не делает
</h2>

Оно не считает комиссии, не реализует прибыль и убыток, не корректирует позиции и не проверяет маржу. Это происходит после сопоставления, в [клиринговой палате](/ru/protocol/architecture/clearinghouse), на основе исполнений, которые породило сопоставление.

Оно также не решает, имел ли ордер право существовать. Достаточность маржи, лимиты на число активных ордеров, ограничения «только уменьшение» и превращение рыночного ордера в лимитный проверяются и отрабатывают до того, как ордер доходит до стакана. К моменту, когда движок сопоставления видит ордер, вопрос только один: где его место в стакане.

<h2 id="where-to-go-next">
  Что дальше
</h2>

<CardGroup cols={2}>
  <Card title="Клиринговая палата" href="/ru/protocol/architecture/clearinghouse">
    Что происходит с балансами и позициями, когда исполнения уже есть.
  </Card>

  <Card title="Типы ордеров" href="/ru/trading/order-types">
    Взгляд со стороны торговли: что можно отправить и как каждый тип себя ведёт.
  </Card>

  <Card title="Стакан заявок" href="/ru/trading/order-book">
    Глубина, уровни и чтение стакана глазами трейдера.
  </Card>

  <Card title="IntentionKernel" href="/ru/protocol/architecture/kernel">
    Где сопоставление стоит в исполнении блока.
  </Card>
</CardGroup>
