Paper Trading Simulator Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Paper Trading Simulator Development
Medium
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Paper Trading Simulator Development

Paper trading is trading with virtual money on real market data. It allows you to test a strategy or familiarize yourself with a platform without the risk of losing real funds. Technically, it's an execution engine simulation using live prices, but without real transactions.

Simulator Architecture

Virtual Account

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)

Order Execution Simulation

The main task: realistically imitate exchange behavior.

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 order executes immediately with slippage simulation
            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 order reserved and added to queue
            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% commission

        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):
        """Check limit orders on each price update"""
        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 and Competitive Element

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 adds a competitive element and motivates users to use the platform more actively — good tool for engagement and conversion to real trading.

Simulator Limitations

Paper trading has a fundamental limitation: your orders don't affect the market. In reality, a large order moves the price (market impact). The simulator overestimates results of strategies trading large volumes.

For more realistic simulation: add a slippage model dependent on volume (the larger the order relative to market volume, the worse execution). This significantly brings paper trading closer to the real world.