Разработка симулятора торговли (paper trading)

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

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

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

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

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

Разработка симулятора торговли (paper trading)

Paper trading — это торговля с виртуальными деньгами на реальных рыночных данных. Позволяет протестировать стратегию или ознакомиться с платформой без риска потери реальных средств. Технически это симуляция execution engine, использующая live цены, но без реальных транзакций.

Архитектура симулятора

Виртуальный аккаунт

from decimal import Decimal
from dataclasses import dataclass, field
from typing import dict, list

@dataclass
class PaperAccount:
    user_id: str
    initial_balance: Decimal = Decimal('10000')
    balances: dict[str, Decimal] = field(default_factory=lambda: {'USDT': Decimal('10000')})
    open_orders: list['PaperOrder'] = field(default_factory=list)
    trade_history: list['PaperTrade'] = field(default_factory=list)

    def get_portfolio_value(self, prices: dict[str, float]) -> Decimal:
        total = self.balances.get('USDT', Decimal(0))
        for currency, amount in self.balances.items():
            if currency != 'USDT' and currency in prices:
                total += amount * Decimal(str(prices[currency]))
        return total

    def get_pnl_percent(self, current_prices: dict) -> float:
        current_value = self.get_portfolio_value(current_prices)
        return float((current_value - self.initial_balance) / self.initial_balance * 100)

Симуляция исполнения ордеров

Главная задача: реалистично имитировать биржевое поведение.

class PaperTradingEngine:
    def __init__(self, market_data_feed):
        self.feed = market_data_feed
        self.accounts: dict[str, PaperAccount] = {}

    async def place_order(
        self,
        user_id: str,
        symbol: str,
        side: str,
        order_type: str,
        quantity: Decimal,
        price: Decimal = None
    ) -> PaperOrder:
        account = self.accounts[user_id]
        current_price = await self.feed.get_price(symbol)

        order = PaperOrder(
            id=generate_id(),
            symbol=symbol,
            side=side,
            order_type=order_type,
            quantity=quantity,
            price=price,
            status='open',
            created_at=datetime.utcnow()
        )

        if order_type == 'market':
            # Market ордер исполняется немедленно с симуляцией slippage
            slippage = current_price * Decimal('0.0005')  # 0.05% slippage
            fill_price = current_price + slippage if side == 'buy' else current_price - slippage
            await self.fill_order(account, order, fill_price)

        elif order_type == 'limit':
            # Limit ордер резервируем и добавляем в очередь
            await self.reserve_funds(account, order, price)
            account.open_orders.append(order)

        return order

    async def fill_order(
        self,
        account: PaperAccount,
        order: PaperOrder,
        fill_price: Decimal
    ):
        base_currency = order.symbol.replace('USDT', '')
        fee = order.quantity * fill_price * Decimal('0.001')  # 0.1% комиссия

        if order.side == 'buy':
            cost = order.quantity * fill_price + fee
            account.balances['USDT'] -= cost
            account.balances[base_currency] = account.balances.get(
                base_currency, Decimal(0)
            ) + order.quantity
        else:
            proceeds = order.quantity * fill_price - fee
            account.balances['USDT'] = account.balances.get('USDT', Decimal(0)) + proceeds
            account.balances[base_currency] -= order.quantity

        order.status = 'filled'
        order.fill_price = fill_price
        order.fee = fee
        account.trade_history.append(PaperTrade.from_order(order, fill_price))

    async def check_limit_orders(self, symbol: str, current_price: Decimal):
        """Проверяем лимитные ордера при каждом обновлении цены"""
        for user_id, account in self.accounts.items():
            triggered = []
            for order in account.open_orders:
                if order.symbol != symbol:
                    continue

                should_fill = (
                    (order.side == 'buy' and current_price <= order.price) or
                    (order.side == 'sell' and current_price >= order.price)
                )

                if should_fill:
                    await self.fill_order(account, order, order.price)
                    triggered.append(order)

            for order in triggered:
                account.open_orders.remove(order)

Leaderboard и соревновательный элемент

async def get_leaderboard(
    self,
    period: str = '7d'
) -> list[dict]:
    all_accounts = await self.db.get_all_accounts()
    prices = await self.feed.get_all_prices()

    rankings = []
    for account in all_accounts:
        pnl = account.get_pnl_percent(prices)
        rankings.append({
            'user': account.user_id,
            'pnl_percent': pnl,
            'portfolio_value': float(account.get_portfolio_value(prices)),
            'trades_count': len(account.trade_history),
        })

    return sorted(rankings, key=lambda x: x['pnl_percent'], reverse=True)[:100]

Leaderboard добавляет соревновательный элемент и мотивирует пользователей активнее использовать platform — хороший инструмент для engagement и конверсии в реальную торговлю.

Ограничения симулятора

Paper trading имеет фундаментальное ограничение: ваши ордера не влияют на рынок. В реальности крупный ордер двигает цену (market impact). Симулятор завышает результаты стратегий, торгующих большими объёмами.

Для более реалистичной симуляции: добавьте модель slippage зависящую от объёма (чем больше ордер относительно объёма рынка, тем хуже execution). Это значительно приближает paper trading к реальному миру.