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

# Файл алгоритма

> Функции жизненного цикла и структура файла стратегии Ziplime от Финама

Стратегия Ziplime от Финама — это Python-файл с функциями жизненного цикла. Создавать подкласс не нужно: определите функции, которые должен вызывать Ziplime, а состояние стратегии храните в `context`.

## Каркас файла

```python theme={null}
from ziplime.finance.execution import MarketOrder


async def initialize(context):
    context.asset = await context.symbol("SBER")
    context.short_window = 20
    context.long_window = 100


async def handle_data(context, data):
    history = await data.history(
        assets=[context.asset],
        fields=["close"],
        bar_count=context.long_window,
    )
    closes = history["close"].to_numpy()

    if len(closes) < context.long_window:
        return

    short_ma = closes[-context.short_window:].mean()
    long_ma = closes.mean()

    if short_ma > long_ma:
        await context.order_target_percent(context.asset, 1.0, style=MarketOrder())
    else:
        await context.order_target_percent(context.asset, 0.0, style=MarketOrder())

    context.record(short_ma=short_ma, long_ma=long_ma)
```

## `initialize(context)`

Требуется для большинства стратегий. Ziplime вызывает эту функцию один раз перед первым баром.

Используйте её, чтобы:

* Найти инструменты.
* Сохранить константы и изменяемое состояние в `context`.
* Зарегистрировать функции, запускаемые по расписанию.
* Настроить торговые ограничения.
* Подключить пайплайны.
* Прочитать конфигурацию алгоритма из `context.algorithm.config`.

```python theme={null}
async def initialize(context):
    context.assets = [
        await context.symbol("SBER", mic="MISX"),
        await context.symbol("GAZP@MISX"),
    ]
    context.max_weight = 0.25
    context.days_seen = 0
```

Не размещайте заявки в `initialize`. Функции работы с заявками доступны только после инициализации.

## `handle_data(context, data)`

Основная функция торговой логики. Ziplime вызывает её на каждом баре с периодичностью, заданной параметром симуляции `emission_rate`.

Используйте её, чтобы:

* Получать текущие и исторические значения из `data`.
* Рассчитывать сигналы.
* Проверять денежные средства, позиции и открытые заявки.
* Размещать, приводить к целевому значению или отменять заявки.
* Записывать метрики в итоговую таблицу.

```python theme={null}
async def handle_data(context, data):
    current = await data.current(
        assets=[context.asset],
        fields=["close", "volume"],
    )
    close = current["close"][0]
    volume = current["volume"][0]

    if volume > 0 and close > context.entry_price:
        await context.order_target_percent(context.asset, 1.0, style=MarketOrder())

    context.record(close=close)
```

## `before_trading_start(context, data)`

Необязательная функция. Ziplime вызывает её один раз за торговую сессию до обычной обработки баров.

В текущей версии среды функция вызывается синхронно, поэтому определяйте её через `def`, а не через `async def`.

Используйте её, чтобы:

* Сбросить дневное состояние.
* Получить результат пайплайна.
* Подготовить список инструментов на день.

Не размещайте здесь заявки: во время выполнения `before_trading_start` функции работы с заявками явно запрещены.

```python theme={null}
def before_trading_start(context, data):
    context.traded_this_session = False

    if "universe" in getattr(context, "pipeline_names", set()):
        context.pipeline_results = context.pipeline_output("universe")
```

## `analyze(context, perf)`

Необязательная функция. Ziplime вызывает её один раз после завершения симуляции.

В текущей версии среды функция вызывается синхронно, поэтому определяйте её через `def`, а не через `async def`.

`perf` — итоговая таблица результатов, созданная исполнителем. В неё входят переменные, записанные с помощью `context.record(...)`.

```python theme={null}
def analyze(context, perf):
    print(perf.tail())
    print("Итоговая стоимость портфеля:", perf["portfolio_value"].iloc[-1])
```

## Хранение состояния

Все данные, которые должны сохраняться между барами, записывайте в атрибуты `context`:

```python theme={null}
async def initialize(context):
    context.last_rebalance_date = None
    context.open_order_ids = []
    context.assets = [await context.symbol("SBER")]


async def handle_data(context, data):
    context.last_seen_dt = context.get_datetime()
```

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

## Конфигурация алгоритма

Если в файле алгоритма определён подкласс `BaseAlgorithmConfig`, Ziplime может загрузить его из JSON-конфигурации, переданной в `run_simulation(..., config_file=...)`.

```python theme={null}
from ziplime.config.base_algorithm_config import BaseAlgorithmConfig


class AlgorithmConfig(BaseAlgorithmConfig):
    symbols: list[str] = ["SBER", "GAZP"]
    target_weight: float = 0.5


async def initialize(context):
    cfg = context.algorithm.config
    context.assets = [await context.symbol(symbol) for symbol in cfg.symbols]
    context.target_weight = cfg.target_weight
```

Пример JSON:

```json theme={null}
{
  "symbols": ["SBER", "GAZP", "LKOH"],
  "target_weight": 0.33
}
```

## Частые ошибки

| Ошибка                                                                                | Исправление                                                                                   |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `before_trading_start` определена через `async def`                                   | Используйте обычную функцию `def before_trading_start(...)`.                                  |
| `analyze` определена через `async def`                                                | Используйте обычную функцию `def analyze(...)`.                                               |
| Пропущен `await` перед `data.current`, `data.history` или функциями работы с заявками | Добавьте `await`.                                                                             |
| Заявки размещаются в `initialize` или `before_trading_start`                          | Размещайте заявки в `handle_data` или в функциях, запланированных через расписание.           |
| Целевые заявки повторно отправляются, пока предыдущие ещё открыты                     | Проверяйте `context.get_open_orders(asset)` или сделайте логику ребалансировки идемпотентной. |
