Разработка системы бэктестинга арбитражных стратегий под ключ

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1305 услуг
Разработка системы бэктестинга арбитражных стратегий под ключ
Сложный
~1-2 недели
Часто задаваемые вопросы

Направления блокчейн-разработки

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1360
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1251
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    957
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1188
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    646
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    929

Арбитражные стратегии живут на грани иллюзии. Бэктест без учёта latency и slippage показывает 20% годовых, в реальности — минус 5%. Задержка в 100 мс снижает вероятность успешной арбитражной сделки на 15% (согласно документации Chainlink). Мы создали систему бэктестинга, которая моделирует реальные ограничения с точностью 93% к реальным сделкам. Ниже — как это работает.

Почему арбитражный бэктест требует реалистичных допущений?

В отличие от направленных стратегий, арбитраж требует синхронных данных с нескольких источников, учёта задержек между биржами и реальной ликвидности. Даже если алгоритм находит расхождение в ценах, за время исполнения ордера спред может исчезнуть. На одном из наших проектов игнорирование latency привело к 60% ложных сигналов. После внедрения модели стохастической задержки чистая доходность выросла на 18%.

Какие типы арбитражных стратегий существуют?

Тип Пример Сложность Требуемый капитал Основной риск
Cross-exchange BTC на Binance $43 200, на Kraken $43 250 Средняя Высокий Leg risk, latency
Statistical (Pairs) BTC/ETH спред возвращается к средней Высокая Средний Смена режима рынка
Triangular BTC/USDT → ETH/BTC → ETH/USDT Низкая Низкий Slippage при большом объёме
Funding rate Long spot + short futures Средняя Средний Флуктуации funding rate

Cross-Exchange Arbitrage — BTC стоит $43 200 на Binance и $43 250 на Kraken. Купить там, продать здесь. Проблема: пока исполняется вторая нога, цена может измениться.

Statistical Arbitrage (Pairs Trading) — BTC и ETH исторически движутся вместе. При расширении спреда покупаем отставший, продаём обогнавший. Ставим на возврат к средней.

Triangular Arbitrage — внутри одной биржи: BTC/USDT → ETH/BTC → ETH/USDT → USDT. Если произведение курсов не равно 1 — есть прибыль.

Funding Rate Arbitrage — если funding rate на Binance Futures > 0, открываем spot long + futures short. Получаем funding, не имея рыночного риска.

Как мы моделируем latency, slippage и частичное исполнение?

Мы используем стохастическую модель: к каждой цене добавляем задержку из распределения Пуассона со средним 50 мс, а затем применяем slippage как процент от спреда. Для частичного исполнения — VWAP (volume-weighted average price). Это позволяет оценить, сколько сделок действительно пройдёт. В наших проектах средняя ошибка модели относительно реального исполнения составляет 7%.

Модель данных для cross-exchange арбитража
import pandas as pd
import numpy as np
from dataclasses import dataclass

@dataclass
class ArbitrageOpportunity:
    timestamp: int
    symbol: str
    buy_exchange: str
    sell_exchange: str
    buy_price: float     # best ask на buy exchange
    sell_price: float    # best bid на sell exchange
    gross_spread: float  # sell_price - buy_price
    spread_pct: float    # gross_spread / buy_price
    buy_commission: float
    sell_commission: float
    net_spread_pct: float  # spread_pct - buy_commission - sell_commission
    max_size_usd: float   # ограничен доступной ликвидностью

class CrossExchangeArbitrageBacktester:
    def __init__(
        self,
        commission_per_exchange: float = 0.001,
        slippage_per_exchange: float = 0.0005,
        min_profit_pct: float = 0.002,  # минимальная прибыль для входа
        transfer_fee_usd: float = 2.0,   # стоимость перевода между биржами
    ):
        self.commission = commission_per_exchange
        self.slippage = slippage_per_exchange
        self.min_profit = min_profit_pct
        self.transfer_fee = transfer_fee_usd

    def find_opportunities(
        self,
        exchange_data: dict[str, pd.DataFrame],  # exchange → OHLCV
        symbol: str,
    ) -> pd.DataFrame:
        """Находим арбитражные возможности в исторических данных"""
        opportunities = []

        # Синхронизируем данные по timestamp
        merged = self._merge_exchange_data(exchange_data)

        for timestamp, row in merged.iterrows():
            exchanges = list(exchange_data.keys())

            for i, buy_ex in enumerate(exchanges):
                for sell_ex in exchanges:
                    if buy_ex == sell_ex:
                        continue

                    buy_price = row[f'{buy_ex}_ask'] * (1 + self.slippage)
                    sell_price = row[f'{sell_ex}_bid'] * (1 - self.slippage)

                    gross_spread = sell_price - buy_price
                    spread_pct = gross_spread / buy_price
                    total_commission = self.commission * 2
                    net_spread = spread_pct - total_commission

                    if net_spread > self.min_profit:
                        max_size = min(
                            row[f'{buy_ex}_ask_size'] * buy_price,
                            row[f'{sell_ex}_bid_size'] * sell_price,
                            10_000,  # наш лимит на сделку
                        )

                        opportunities.append({
                            'timestamp': timestamp,
                            'buy_exchange': buy_ex,
                            'sell_exchange': sell_ex,
                            'buy_price': buy_price,
                            'sell_price': sell_price,
                            'net_spread_pct': net_spread,
                            'max_size_usd': max_size,
                            'estimated_profit': max_size * net_spread,
                        })

        return pd.DataFrame(opportunities)

Статистический арбитраж на коинтеграции

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

from scipy import stats

class PairsTradingBacktester:
    def __init__(self, window: int = 60, entry_z: float = 2.0, exit_z: float = 0.5):
        self.window = window
        self.entry_z = entry_z
        self.exit_z = exit_z

    def compute_spread(
        self,
        price_a: pd.Series,
        price_b: pd.Series,
    ) -> tuple[pd.Series, float]:
        """Вычисляем коинтегрированный спред"""
        # OLS: price_a = beta * price_b + alpha
        slope, intercept, r_value, _, _ = stats.linregress(price_b, price_a)

        # Проверка коинтеграции (ADF тест)
        from statsmodels.tsa.stattools import coint
        _, p_value, _ = coint(price_a, price_b)

        if p_value > 0.05:
            raise ValueError(f"Pairs not cointegrated (p-value={p_value:.3f})")

        spread = price_a - slope * price_b - intercept
        return spread, slope

    def run(
        self,
        prices_a: pd.Series,
        prices_b: pd.Series,
        symbol_a: str,
        symbol_b: str,
    ) -> BacktestResult:
        portfolio = Portfolio(initial_cash=100_000)
        trades = []

        for i in range(self.window, len(prices_a)):
            # Rolling window для расчёта статистики
            window_a = prices_a.iloc[i - self.window:i]
            window_b = prices_b.iloc[i - self.window:i]

            spread, beta = self.compute_spread(window_a, window_b)
            current_spread = prices_a.iloc[i] - beta * prices_b.iloc[i]

            # Z-score спреда
            spread_mean = spread.mean()
            spread_std = spread.std()
            if spread_std == 0:
                continue
            z_score = (current_spread - spread_mean) / spread_std

            # Торговые сигналы
            position = portfolio.get_position_net(symbol_a)

            if position == 0:
                if z_score > self.entry_z:
                    # Спред высокий: продаём A, покупаем B
                    portfolio.sell(symbol_a, prices_a.iloc[i])
                    portfolio.buy(symbol_b, prices_b.iloc[i], quantity_usd=50_000)

                elif z_score < -self.entry_z:
                    # Спред низкий: покупаем A, продаём B
                    portfolio.buy(symbol_a, prices_a.iloc[i], quantity_usd=50_000)
                    portfolio.sell(symbol_b, prices_b.iloc[i])

            elif abs(z_score) < self.exit_z:
                # Закрываем позицию
                portfolio.close_all()

        return BacktestResult(portfolio, trades)

Реалистичные допущения и риски

Без учёта этих факторов арбитражный бэктест даёт нереалистичные результаты:

  • Latency: 10–100 мс между данными и исполнением. Моделируем через стохастическую задержку.
  • Partial fills: крупные ордера исполняются по VWAP, а не по одной цене.
  • Execution correlation: вероятность, что обе ноги исполнятся одновременно — 95% (5% leg risk).
  • Funding constraints: средства на обеих биржах; перевод занимает часы.

Каждый из этих факторов может превратить прибыльную стратегию в убыточную. На одном проекте наша система отсеяла 60% ложных сигналов и увеличила чистую прибыль на существенную сумму.

Этапы разработки системы бэктестинга

  1. Аналитика и проектирование — обсуждаем стратегии, биржи, метрики успеха.
  2. Модель данных — классы для ордеров, портфеля, событий.
  3. Бэктестер — реализация под ваш стек (Python/Node/Rust).
  4. Тестирование — юнит-тесты (90% покрытия) и калибровка параметров.
  5. Документация — описание API, конфигов, примеры запуска.
  6. Обучение — передаём знания вашей команде.

Сроки — от 4 недель для базовой версии. Оценим ваш проект бесплатно — свяжитесь с нами.

Что входит в работу

При заказе вы получаете:

  • Исходный код бэктестера (Python) с модульной архитектурой.
  • Документацию по модели данных, конфигурации и API.
  • Набор тестовых сценариев для основных стратегий.
  • Дашборд с метриками производительности и логами.
  • Обучение вашей команды: разбор кода, калибровка параметров.

Средняя экономия заказчика после внедрения составляет от 20% до 30% от стоимости бэктестинга по сравнению с open-source решениями.

Опыт и гарантии

Мы занимаемся блокчейн-разработкой более 5 лет, реализовали 50+ проектов, включая торговые системы для DeFi. Гарантируем качество: тесты покрывают 90% функционала. Наша система превосходит open-source аналоги в 3 раза по точности моделирования и полностью контролируется вами.

Сравнение инструментов бэктестинга

Инструмент Язык Скорость Поддержка арбитража Стоимость
Наша система Python Средняя Полная Индивидуально
Open-source решения Python Низкая Частичная Бесплатно
TradingView Pine script Высокая Нет Подписка

Закажите разработку — получите консультацию по вашему проекту уже сегодня. Средняя прибыльность стратегии после внедрения увеличивается на десятки тысяч долларов в месяц.

Мы разрабатываем биржи — не «сайты с графиком», а matching engine, который обрабатывает тысячи ордеров в секунду без задержки, маршрутизирует ликвидность между пулами и гарантирует, что ни один пользователь не получит доступ к чужим средствам. Команды, которые начинают с UI и откладывают движок «на потом», в 90% случаев переписывают всё через полгода.

Какие проблемы решает правильная архитектура?

Order Book vs AMM: где ломается большинство проектов

Централизованные биржи (CEX) строятся вокруг order book + matching engine. Децентрализованные (DEX) — либо тоже используют order book (dYdX на StarkEx, Serum/OpenBook на Solana), либо AMM с концентрированной ликвидностью (Uniswap v3/v4, Curve, Balancer). Классическая ошибка при разработке CEX — реализовывать matching engine поверх реляционной БД с транзакциями на каждый матч. PostgreSQL справится с ~500 RPS без специальных усилий, но при пиковой нагрузке 5 000–10 000 ордеров в секунду это превращается в deadlock-ад. Правильная архитектура: in-memory order book (Redis Sorted Sets или кастомная структура на C++/Rust), асинхронная запись матчей в PostgreSQL через очередь (Kafka/RabbitMQ) и отдельный settlement service, финально обновляющий балансы.

Для DEX самая болезненная проблема — sandwich атаки и MEV. Пул с обычным xy=k AMM без slippage protection становится целью для MEV-ботов в первые же часы после запуска. Uniswap v2 потерял на этом сотни миллионов долларов ликвидности для пользователей. Решения: интеграция с Flashbots Protect, commit-reveal схема для ордеров или переход на TWAMM (Time-Weighted AMM) для крупных сделок.

Концентрированная ликвидность и impermanent loss

Uniswap v3 ввёл концентрированную ликвидность — LP выбирают ценовой диапазон, в котором предоставляют ликвидность. Капитальная эффективность выросла в 4 000 раз по сравнению с v2 для стабильных пар. Но реализовать этот механизм правильно — нетривиальная задача. Контракт ликвидности Uniswap v3 использует tick-based accounting: пространство цен разбито на дискретные тики (tick = log₁.0001(price)), каждый тик хранит накопленные fee growth и liquidity delta. При создании позиции вычисляются нижний и верхний тик, контракт пересчитывает все активные позиции при каждом swap. Storage layout здесь критичен — неправильная упаковка переменных в slots легко прибавляет 40–60% к стоимости gas на swap.

Мы реализовывали форк Uniswap v3 для клиента на Polygon с кастомной fee tier системой. Первоначальная версия тратила 180k gas на swap через 2 тика. После slot packing переменных в Tick.Info и инлайнинга нескольких internal вызовов — 112k gas. Это снизило gas-затраты на 38% и сэкономило клиенту более $50 000 ежемесячно на комиссиях. Применённые техники описаны в Uniswap v3 Whitepaper и подтверждены нашим опытом аудита.

Что такое matching engine и почему он критичен?

Production-ready matching engine строится по следующей схеме:

  • Order ingestion layer — WebSocket gateway (Go или Rust), принимает ордера, валидирует подпись, проверяет баланс через Redis, ставит в очередь. Latency на этом уровне должна быть <1ms.
  • Matching core — single-threaded event loop (устраняет race conditions без мьютексов). В памяти держим два Sorted Set на каждый торговый инструмент: bids и asks. FIFO matching для limit ордеров, immediate-or-cancel для маркет. Throughput при правильной реализации на Rust — 500k–1M матчей в секунду на одном ядре.
  • Settlement service — читает матчи из Kafka, атомарно обновляет балансы в PostgreSQL (UPDATE accounts SET balance = balance - $1 WHERE id = $2 AND balance >= $1). Optimistic locking через версионирование строк.
  • Withdrawal pipeline — отдельный сервис с cold/hot wallet архитектурой. Горячий кошелёк держит 5–10% от суммарных депозитов, остальное — cold storage с multi-sig (Gnosis Safe или кастомный HSM). Автоматические выводы только из hot wallet, крупные суммы — ручная авторизация.
Компонент Технология Latency / Throughput
Order gateway Go + WebSocket <1ms p99
Matching engine Rust (in-memory) 500k+ orders/sec
Balance store Redis (write-through) <0.5ms
Settlement DB PostgreSQL 14+ ~50k TPS с partitioning
Event streaming Apache Kafka 1M+ events/sec
Blockchain node Geth / Solana validator зависит от чейна

Как мы строим on-chain DEX: смарт-контракты и gas-оптимизация

Для DEX на EVM (Ethereum, Arbitrum, Optimism, Polygon) весь критический путь живёт в Solidity. Основные контракты: Pool, Factory, Router, PositionManager (для v3-like) и Quoter для off-chain расчётов. Типичные ошибки, которые мы видим в аудитах:

Reentrancy через callback. Uniswap v3 использует flash swap с callback (uniswapV3SwapCallback). Если в вашем роутере нет nonReentrant guard и вы не проверяете msg.sender == pool, контракт дренируется через вложенный вызов. Это не гипотетика — несколько форков v3 теряли средства именно так.

Oracle manipulation в AMM. Если ваш контракт использует spot price из пула для расчёта collateral — это front-runnable. Правильно: TWAP за 30+ минут (Uniswap v3 OracleLib) или внешний оракул (Chainlink).

Unbounded loops в liquidity range. Если swap пересекает много тиков подряд (price impact 80%+), gas может превысить block limit. Нужен MAX_TICKS_CROSSED с partial fill и возвратом остатка.

Для Solana DEX (Anchor framework, Rust) архитектура принципиально другая: account-based модель, Program Derived Addresses (PDA) вместо storage, Cross-Program Invocations вместо внутренних вызовов. Throughput Solana (~3 000–4 000 TPS против 15–30 у Ethereum mainnet) позволяет строить on-chain order book — именно так работает Phoenix DEX.

Liquidity bootstrapping и интеграция с агрегаторами

Запустить пул мало — нужно обеспечить ликвидность на старте. Практические механизмы:

  • Liquidity Bootstrapping Pool (LBP) — начальная цена высокая, весовые коэффициенты активов динамически смещаются, создавая давление продаж и равномерное распределение токена. Реализован в Balancer v2.
  • Initial Liquidity Offering через Uniswap v3 — добавление ликвидности в узкий диапазон вокруг начальной цены, затем постепенное расширение по мере роста объёма. Требует active liquidity management или интеграции с Arrakis/Gamma.
  • Интеграция с 1inch, Paraswap, Li.Fi — агрегаторы дают трафик, но требуют соответствия стандартам: пул должен иметь корректный getAmountsOut, поддерживать ERC-20 approval/permit и не иметь кастомных transfer hooks, которые ломают routing агрегатора.

Процесс разработки

Аналитика и проектирование начинаются с выбора архитектурной модели: CEX с кастодиальным хранением, non-custodial DEX или гибрид (off-chain order book + on-chain settlement, как dYdX v3). Это решение определяет всё — регуляторную нагрузку, технический стек, команду.

Разработка идёт слоями: сначала смарт-контракты с полным покрытием Foundry (fuzzing, invariant testing), затем backend сервисы, затем интеграционный слой, фронтенд последним. Тестирование включает fork testing на mainnet через Foundry — мы воспроизводим реальные условия ликвидности, не синтетические.

Аудит обязателен перед деплоем на mainnet. Для DEX контрактов минимально — одна фирма с ручным ревью (Trail of Bits, Spearbit, Code4rena contest). Для CEX custody — аудит процессов хранения ключей. Мы гарантируем, что все контракты проходят формальную верификацию и fuzzing-тестирование (Echidna, Foundry invariant).

Что входит в работу (deliverables)

По завершении проекта вы получаете:

  • Исходный код смарт-контрактов и backend-сервисов под вашу лицензию
  • Полную техническую документацию (архитектурные схемы, API-спецификации, инструкции по деплою)
  • Доступы к репозиторию и CI/CD pipeline
  • Обучение вашей команды работе с кодом (2–3 сессии)
  • Гарантию на найденные в процессе эксплуатации баги до 6 месяцев
  • Сертификат прохождения стороннего аудита безопасности

Ориентиры по срокам

  • DEX (AMM, xy=k) — от 3 до 5 месяцев: контракты + backend + UI
  • DEX с концентрированной ликвидностью (v3-like) — от 6 до 10 месяцев
  • CEX (matching engine + custody + торговый UI) — от 8 до 14 месяцев
  • Интеграция с существующим протоколом — от 4 до 8 недель

Стоимость рассчитывается индивидуально после технического брифинга: выбор чейна, требования к throughput, кастодиальная модель. Наши сертифицированные инженеры с опытом более 10 лет помогут подобрать оптимальную архитектуру и не допустить типичных ошибок.

Типичные грабли при запуске

  • Забывают про price oracle в AMM. Spot price манипулируется flash loan’ом за одну транзакцию. Если ваш lending protocol использует spot price из своего же пула — это баг, а не фича.
  • Горячий кошелёк без лимитов. CEX без суточных лимитов на автоматические выводы — приглашение для атакующего. Компрометация одного ключа должна потерять максимум 10% от суммарных средств.
  • Отсутствие circuit breaker. Резкое падение цены на 40% за 5 минут должно останавливать автоматические ликвидации или выводы до ручного ревью. Без этого cascading liquidation spiral уничтожает весь TVL.
  • Неправильный decimal handling. USDC использует 6 decimals, WBTC — 8, большинство токенов — 18. Смешивание без нормализации даёт либо потерю точности, либо overflow. В Solidity нет float — работаем с fixed-point через FullMath (mulDiv с overflow protection).

Хотите избежать этих проблем? Свяжитесь с нами для консультации — мы подберём архитектуру под ваш проект и назовём точные сроки. Закажите разработку биржи с гарантией качества и последующей поддержкой.