Разработка системы алертов по техническим индикаторам

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка системы алертов по техническим индикаторам
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1062
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка платформы социального трейдинга

Социальный трейдинг — это копирование сделок успешных трейдеров в реальном времени. eToro сделал это mainstream в традиционных финансах, затем появились крипто-аналоги: Bybit Copy Trading, Bitget Copy Trade, OKX Copy Trading. Разработка собственной платформы — сложная задача с уникальными вызовами в синхронизации ордеров и распределении комиссий.

Архитектура платформы

Роли участников

Provider (мастер-трейдер) — опытный трейдер, чьи сделки копируются. Зарабатывает profit share (обычно 5–30% от прибыли копировщиков) или фиксированную подписку.

Follower (копировщик) — пользователь, выделяющий часть капитала на копирование. Выбирает провайдера по статистике, устанавливает лимиты.

Platform — получает комиссию с каждой скопированной сделки или с profit share.

Копирование ордеров

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

type CopyEngine struct {
    orderEngine *OrderEngine
    db          *DB
    mu          sync.RWMutex
}

func (ce *CopyEngine) OnProviderOrder(providerOrder Order) {
    followers := ce.getActiveFollowers(providerOrder.UserID)
    
    if len(followers) == 0 {
        return
    }
    
    // Параллельное размещение ордеров для всех копировщиков
    var wg sync.WaitGroup
    errors := make(chan error, len(followers))
    
    for _, follower := range followers {
        wg.Add(1)
        go func(f Follower) {
            defer wg.Done()
            
            copyOrder, err := ce.buildCopyOrder(providerOrder, f)
            if err != nil {
                errors <- fmt.Errorf("follower %d: %w", f.UserID, err)
                return
            }
            
            _, err = ce.orderEngine.PlaceOrder(copyOrder)
            if err != nil {
                errors <- fmt.Errorf("follower %d order failed: %w", f.UserID, err)
            }
        }(follower)
    }
    
    wg.Wait()
    close(errors)
    
    // Логируем неудавшиеся копирования
    for err := range errors {
        log.Error("Copy order failed", "error", err)
    }
}

Расчёт размера позиции копировщика

У провайдера может быть $100k, у копировщика — $500. Нужна пропорциональная адаптация:

type PositionSizer struct{}

func (ps *PositionSizer) Calculate(
    providerOrder Order,
    providerBalance Decimal,
    follower Follower,
) (Decimal, error) {
    // Какой % от баланса использует провайдер
    providerUsagePct := providerOrder.Quantity.Mul(providerOrder.Price).
        Div(providerBalance).Mul(Decimal("100"))
    
    // Три режима копирования
    switch follower.CopyMode {
    case "fixed_amount":
        // Всегда копируем фиксированную сумму
        return follower.FixedAmount.Div(providerOrder.Price), nil
        
    case "proportional":
        // Такой же % от баланса копировщика
        copyAmount := follower.AllocatedBalance.Mul(providerUsagePct).Div(Decimal("100"))
        return copyAmount.Div(providerOrder.Price), nil
        
    case "multiplier":
        // X-кратное умножение относительного размера
        copyAmount := follower.AllocatedBalance.Mul(providerUsagePct).
            Mul(follower.Multiplier).Div(Decimal("100"))
        return copyAmount.Div(providerOrder.Price), nil
    }
    
    return Decimal("0"), ErrUnknownCopyMode
}

Важные проверки перед копированием:

  • Достаточно ли свободного баланса у копировщика
  • Не превышает ли позиция max risk limit копировщика
  • Не выходит ли позиция за пределы max open positions настройки

Синхронизация закрытия позиций

Когда провайдер закрывает позицию — нужно закрыть все копированные позиции:

func (ce *CopyEngine) OnProviderPositionClose(providerTradeID string) {
    // Находим все открытые копированные ордера связанные с этой сделкой
    copyOrders := ce.db.GetCopyOrdersByProviderTrade(providerTradeID)
    
    for _, copyOrder := range copyOrders {
        if copyOrder.Status == OrderStatusOpen {
            // Закрываем рыночным ордером немедленно
            closeOrder := Order{
                UserID: copyOrder.FollowerID,
                Pair:   copyOrder.Pair,
                Side:   copyOrder.Side.Opposite(),
                Type:   Market,
                Quantity: copyOrder.RemainingQty,
            }
            ce.orderEngine.PlaceOrder(closeOrder)
        }
    }
}

Статистика провайдеров

Статистика — главный инструмент выбора провайдера. Должна быть честной и верифицированной (рассчитывается сервером, не передаётся провайдером).

CREATE MATERIALIZED VIEW provider_stats AS
SELECT
    p.user_id,
    p.display_name,
    -- Основные метрики
    COUNT(DISTINCT t.id) AS total_trades,
    COUNT(CASE WHEN t.pnl > 0 THEN 1 END)::float / 
        NULLIF(COUNT(DISTINCT t.id), 0) * 100 AS win_rate,
    SUM(t.pnl) AS total_pnl_usd,
    -- ROI за периоды
    SUM(CASE WHEN t.closed_at >= NOW() - INTERVAL '7 days' 
        THEN t.pnl_pct ELSE 0 END) AS roi_7d,
    SUM(CASE WHEN t.closed_at >= NOW() - INTERVAL '30 days' 
        THEN t.pnl_pct ELSE 0 END) AS roi_30d,
    -- Риск-метрики
    MIN(t.pnl_pct) AS max_loss_single_trade,
    MAX(dd.drawdown) AS max_drawdown,
    -- Sharpe Ratio (упрощённый)
    AVG(t.pnl_pct) / NULLIF(STDDEV(t.pnl_pct), 0) AS sharpe,
    -- Активность
    COUNT(DISTINCT f.user_id) AS active_followers,
    SUM(f.allocated_balance) AS total_aum
FROM providers p
JOIN trades t ON t.user_id = p.user_id AND t.is_copy_trade = false
LEFT JOIN drawdowns dd ON dd.provider_id = p.user_id
LEFT JOIN copy_relationships f ON f.provider_id = p.user_id AND f.status = 'active'
GROUP BY p.user_id, p.display_name;

REFRESH MATERIALIZED VIEW CONCURRENTLY provider_stats;  -- каждые 5 минут

Equity curve

Для каждого провайдера рассчитывается equity curve — история роста $10,000 гипотетического депозита. Это лучший визуальный индикатор стабильности результатов.

def calculate_equity_curve(trades: list[Trade], initial_equity: float = 10000) -> list[dict]:
    equity = initial_equity
    curve = [{'date': trades[0].opened_at.date(), 'equity': equity}]
    
    for trade in sorted(trades, key=lambda t: t.closed_at):
        pnl_usd = equity * (trade.pnl_pct / 100)
        equity += pnl_usd
        curve.append({
            'date': trade.closed_at.date(),
            'equity': round(equity, 2),
            'pnl_pct': round(trade.pnl_pct, 2),
        })
    
    return curve

Модель монетизации и распределение прибыли

Profit share расчёт (High Watermark)

High Watermark — стандартная модель для хедж-фондов и copy trading: провайдер получает profit share только с новых рекордных значений прибыли. Если капитал просел и восстановился до старого максимума — profit share не начисляется.

class ProfitShareCalculator:
    def calculate(self, follower_id: int, provider_id: int) -> Decimal:
        hwm = self.get_high_watermark(follower_id, provider_id)
        current_equity = self.get_follower_equity_for_provider(follower_id, provider_id)
        
        if current_equity <= hwm:
            return Decimal('0')  # нет новой прибыли — нет profit share
        
        new_profit = current_equity - hwm
        provider_share_pct = self.get_provider_share_pct(provider_id)  # например 20%
        platform_fee_pct = Decimal('2')  # 2% платформа берёт с profit share
        
        provider_earnings = new_profit * (provider_share_pct / 100)
        platform_earnings = provider_earnings * (platform_fee_pct / 100)
        
        # Обновляем high watermark
        self.update_high_watermark(follower_id, provider_id, current_equity)
        
        return provider_earnings - platform_earnings

Settlement расписание

Profit share рассчитывается еженедельно или ежемесячно. Settlement workflow:

  1. Snapshot всех equity позиций на дату расчёта
  2. Расчёт profit share для каждой пары (follower, provider)
  3. Перевод комиссий: у follower списывается, у provider начисляется
  4. Уведомления обеим сторонам
  5. Обновление high watermark

Risk controls для копировщиков

type CopyRiskControls struct {
    MaxLoss         Decimal  // -20%: автоотключение при просадке
    MaxOpenTrades   int      // максимум открытых сделок
    MaxPerTrade     Decimal  // % от allocated balance на одну сделку
    StopCopyOnClose bool     // останавливать ли копирование при выходе?
}

func (ce *CopyEngine) CheckFollowerRisk(follower Follower, newOrder Order) error {
    // Проверяем просадку
    currentDrawdown := ce.calculateCurrentDrawdown(follower.ID)
    if currentDrawdown.GreaterThan(follower.RiskControls.MaxLoss.Abs()) {
        ce.stopCopying(follower.ID, "max_loss_reached")
        return ErrMaxLossReached
    }
    
    // Проверяем количество открытых позиций
    openTrades := ce.countOpenCopyTrades(follower.ID)
    if openTrades >= follower.RiskControls.MaxOpenTrades {
        return ErrMaxOpenTradesReached
    }
    
    return nil
}

Лидерборд и discovery

Страница выбора провайдеров — критична для конверсии:

// Фильтры для лидерборда
interface LeaderboardFilters {
  period: '7d' | '30d' | '90d' | 'all';
  minAUM: number;
  minFollowers: number;
  maxDrawdown: number;
  riskLevel: 'low' | 'medium' | 'high';
  strategy: 'spot' | 'futures' | 'mixed';
}

// Карточка провайдера
interface ProviderCard {
  userId: string;
  displayName: string;
  avatar: string;
  roi30d: number;
  winRate: number;
  maxDrawdown: number;
  followers: number;
  aum: number;
  profitSharePct: number;
  equityCurve: EquityPoint[];  // mini sparkline chart
}

Регуляторные аспекты

Социальный трейдинг попадает под регулирование во многих юрисдикциях (провайдер де-факто управляет чужими средствами). Важно:

  • Юридическая консультация по целевой юрисдикции
  • Disclaimers: прошлые результаты не гарантируют будущих
  • Ограничения по суммам для нерегулируемых платформ

Сроки и стоимость

Компонент Срок
Copy engine (order routing) 4–6 недель
Position sizing алгоритмы 2–3 недели
Статистика провайдеров 3–4 недели
Profit share расчёт 2–3 недели
Лидерборд и discovery 3–4 недели
Risk controls для копировщиков 2–3 недели

Полная платформа социального трейдинга: 4–6 месяцев.