> For the complete documentation index, see [llms.txt](https://docs.termina.technology/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.termina.technology/documentation/developer-docs-ru/ustanovka-i-nastroika/s-chego-nachat.md).

# С чего начать

{% stepper %}
{% step %}

#### **Как создать сессию**

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

* `startSlot` / `endSlot`: с какого по какой слот проигрывать историю. Оба крайних слота входят в симуляцию.
* `signerFilter` (необязательно): адреса, чьи транзакции нужно убрать из истории. Например, чтобы исключить сделки своего бота и посмотреть, как рынок жил бы без них.
* `disconnectTimeoutSecs` (необязательно): если соединение оборвется, сессия не закроется сразу, а подождет переподключения. Здесь задается, сколько ждать: до 900 секунд, то есть 15 минут.

Для запроса нужен API-ключ: его передают в заголовке `X-API-Key`.

{% code title="// via websocket to `ws(s)://<host>/backtest`" %}

```json
{
  "method": "createBacktestSession",
  "params": {
    "startSlot": 123456,
    "endSlot": 234567,
    "signerFilter": ["addr..."],
    "disconnectTimeoutSecs": 30
  }
}
```

{% endcode %}

После создания сессии сервер присылает два сообщения по порядку. Сначала `slotNotification` со стартовым слотом: симуляция встала на начало выбранного отрезка. Затем `readyForContinue`: сессия готова, можно двигаться дальше.

Вместе с сессией приходит и ее собственный RPC-адрес. Все дальнейшие запросы к этой сессии отправляются туда.

```json
{
  "method": "sessionCreated",
  "params": {
    "sessionId": "<session_id>",
    "rpcEndpoint": "/backtest/<session_id>"
  }
}
```

> Пока идет сессия, WebSocket-соединение должно оставаться открытым. Если его закрыть, сессия завершится, а все состояние аккаунтов будет удалено: начинать придется заново.
> {% endstep %}

{% step %}

#### **Как получить данные аккаунтов**

С сессией можно работать как с обычной нодой Solana: она поддерживает стандартные методы JSON-RPC и подписки по адресу `/backtest/<session_id>`. Среди них:

* для чтения данных: `getAccountInfo`, `getBalance`, `getMultipleAccounts`
* для подписки на изменения: `accountSubscribe`, `programSubscribe`, `signatureSubscribe`

> Полный список поддерживаемых подписок есть в разделе [**Справочник API**](https://app.gitbook.com/o/7uvfi1sn9uLKfLv8MEz1/sites/site_U2Vl0/s/Vkei3hPl3HKf8KIppIiE/~/edit/~/changes/129/ustanovka-i-nastroika/api-reference).
> {% endstep %}

{% step %}

#### **Как отправить свои транзакции**

В симуляцию можно добавить собственные транзакции. Есть два способа, и разница между ними в том, когда транзакция исполнится.

* **Через RPC:** Транзакция отправляется стандартным методом Solana `sendTransaction` и исполняется сразу, в текущем слоте, после исторических транзакций блока.
* &#x20;**Через WebSocket.**&#x20;
  * Транзакции в кодировке base64 передаются вместе с запросом `continue`. Они исполняются одним пакетом, после чего симуляция переходит к следующему слоту.&#x20;
  * Проще говоря: RPC подходит, чтобы действовать внутри текущего слота, а `continue`, чтобы отправить транзакции и сразу двигаться дальше.

Порядок исполнения внутри слота:

1. Исторические транзакции блока
2. Транзакции, отправленные через `sendTransaction`
3. Транзакции из пакета в запросе `continue`
   {% endstep %}

{% step %}

#### Как управлять симуляцией

Симуляция начинается со `startSlot` и дальше сама не двигается: к следующему слоту она переходит только по запросу `continue`. Так после каждого шага можно спокойно изучить состояние сети.

Что можно передать в `continue`:

* `advanceCount`: сколько слотов пройти, прежде чем снова остановиться. По умолчанию 1.
* `transactions`: свои транзакции для исполнения.
* `modifyAccountStates`: изменения состояния аккаунтов, которые применятся до исполнения.

{% code title="// via websocket to `/backtest/<session_id>`" %}

```json
{
  "method": "continue",
  "params": {
    "advanceCount": 1,
    "transactions": ["<base64_encoded_transaction>"],
    "modifyAccountStates": {
      "addr...": {
        "data": {
          "data": "<base64_bytes>",
          "encoding": "base64"
        },
        "executable": false,
        "lamports": 33594,
        "owner": "11111111111111111111111111111111",
        "space": 80
      }
    }
  }
}

```

{% endcode %}

Пока выполняется `continue`, сервер присылает сообщения `status`: по ним видно, на каком этапе сейчас симуляция. Например:

* `preparingBundle`: собирается пакет транзакций
* `decodedTransactions`: транзакции расшифрованы
* `appliedAccountModifications`: изменения аккаунтов применены
* `executedBlockTransactions`: транзакции блока исполнены
* `programAccountsLoaded`: аккаунты программ загружены

Когда все готово, приходит `readyForContinue`: можно переходить к следующему слоту.
{% endstep %}

{% step %}

#### Повторное подключение к сессии <a href="#reattach-session" id="reattach-session"></a>

Если соединение случайно оборвалось, сессию не нужно создавать заново: достаточно снова подключиться к ней, пока не истекло время ожидания. Это время задается параметром `disconnectTimeoutSecs` при создании сессии.

Сервер хранит события подписок WebSocket за последние 100 слотов. Поэтому события, пропущенные во время обрыва, не потеряются, если с того момента прошло не больше 100 слотов.

{% code title="// via websocket to `/backtest`" %}

```json
{
  "method": "attachBacktestSession",
  "params": {
    "sessionId": "<session_id>",
    "lastSequence": 42
  }
}
```

{% endcode %}

Параметр `lastSequence` необязательный. В нем указывается номер последнего полученного события, и тогда сервер пришлет только то, что было после него. Если параметр не указать, сервер заново пришлет все сохраненные события.
{% endstep %}

{% step %}

#### **Как завершить сессию**

{% code title="// via websocket to `/backtest/<session_id>`" %}

```json
{
  "method": "closeBacktestSession"
}
```

{% endcode %}

В ответ сервер пришлет `success` и удалит сессию. Вернуться к ней после этого уже не получится.
{% endstep %}
{% endstepper %}

#### На что обратить внимание при тестировании стратегий&#x20;

* Чтобы симуляция всегда стартовала одинаково, программы стоит загрузить заранее через `preloadPrograms` и дождаться статуса `programAccountsLoaded`. Только после этого отправлять первый `continue`.
* Чтобы быстрее проверять варианты, можно проходить несколько слотов за один шаг: для этого `advanceCount` задается больше 1. Уведомления о каждом слоте при этом все равно приходят.
* Проверка подписей отключена, поэтому транзакцию можно отправить от имени любого аккаунта, даже без его ключа. Это удобно, например, чтобы смоделировать действия крупного участника рынка.
