Разработка системы комиссий криптобиржи
Комиссионная структура — ключевой монетизационный инструмент биржи. Слишком высокие комиссии отгоняют трейдеров, слишком низкие — делают бизнес убыточным. Грамотная система даёт гибкость: привлекать крупных трейдеров скидками, удерживать маркет-мейкеров нулевыми или отрицательными комиссиями (rebate).
Модели комиссий
Maker-Taker модель
Стандарт для большинства современных CEX. Maker добавляет ликвидность (limit ордер, который не исполняется немедленно), taker убирает ликвидность (market ордер или limit, исполняющийся сразу).
- Maker fee: обычно 0.01–0.1% (ниже, иногда отрицательный — rebate)
- Taker fee: обычно 0.05–0.2%
Отрицательный maker fee (rebate) — биржа платит трейдеру за предоставление ликвидности. Так поступают Kraken, Binance для высококвалифицированных MM.
Volume-based тиры
type FeeTier struct {
MinVolume30d Decimal // USD объём за 30 дней
MakerFee Decimal // % (может быть отрицательным для rebate)
TakerFee Decimal // %
Label string
}
var DefaultTiers = []FeeTier{
{MinVolume30d: Decimal("0"), MakerFee: Decimal("0.10"), TakerFee: Decimal("0.20"), Label: "Regular"},
{MinVolume30d: Decimal("100000"), MakerFee: Decimal("0.08"), TakerFee: Decimal("0.16"), Label: "VIP 1"},
{MinVolume30d: Decimal("500000"), MakerFee: Decimal("0.05"), TakerFee: Decimal("0.12"), Label: "VIP 2"},
{MinVolume30d: Decimal("2000000"), MakerFee: Decimal("0.02"), TakerFee: Decimal("0.08"), Label: "VIP 3"},
{MinVolume30d: Decimal("10000000"), MakerFee: Decimal("0.00"), TakerFee: Decimal("0.05"), Label: "VIP 4"},
{MinVolume30d: Decimal("50000000"), MakerFee: Decimal("-0.01"), TakerFee: Decimal("0.03"), Label: "VIP 5"},
}
func (fs *FeeSystem) GetUserTier(userID int64) FeeTier {
volume30d := fs.db.GetUserVolume30d(userID)
var currentTier FeeTier = DefaultTiers[0]
for _, tier := range DefaultTiers {
if volume30d.GreaterThanOrEqual(tier.MinVolume30d) {
currentTier = tier
}
}
return currentTier
}
BNB/платформенный токен discount
Binance ввела стандарт: оплата комиссии платформенным токеном даёт скидку 25%.
func (fs *FeeSystem) CalculateFee(userID int64, tradeValue Decimal, side TakerMaker) FeeResult {
tier := fs.GetUserTier(userID)
baseFeeRate := tier.MakerFee
if side == Taker {
baseFeeRate = tier.TakerFee
}
baseFee := tradeValue.Mul(baseFeeRate.Div(Decimal("100")))
// Проверяем токен дисконт
if fs.userHasTokenBalance(userID) && fs.userPrefersTokenFee(userID) {
tokenDiscount := baseFee.Mul(Decimal("0.25"))
return FeeResult{
BaseFee: baseFee,
Discount: tokenDiscount,
FinalFee: baseFee.Sub(tokenDiscount),
PayInToken: true,
TokenAmount: fs.convertToToken(baseFee.Sub(tokenDiscount)),
}
}
return FeeResult{BaseFee: baseFee, FinalFee: baseFee}
}
Расчёт и применение комиссии при сделке
При каждом fill matching engine должен:
- Определить tier каждого участника
- Рассчитать комиссию
- Применить дисконты
- Списать комиссию с баланса
func (fe *FeeEngine) ProcessTrade(trade Trade) (FeeDeductions, error) {
takerFee := fe.Calculate(trade.TakerUserID, trade.Value, Taker)
makerFee := fe.Calculate(trade.MakerUserID, trade.Value, Maker)
// Taker получает base currency минус taker fee
takerReceives := trade.Quantity.Sub(takerFee.FinalFee.Div(trade.Price))
// Maker получает quote currency минус maker fee
makerReceives := trade.Value.Sub(makerFee.FinalFee)
// Если maker rebate (отрицательная комиссия) — начисляем бонус
if makerFee.FinalFee.IsNegative() {
makerReceives = trade.Value.Add(makerFee.FinalFee.Abs())
}
return FeeDeductions{
TakerDeduction: takerFee.FinalFee,
MakerDeduction: makerFee.FinalFee,
TakerReceives: takerReceives,
MakerReceives: makerReceives,
PlatformEarned: takerFee.FinalFee.Add(makerFee.FinalFee),
}, nil
}
Специальные комиссионные структуры
Промо-коды и реферальные скидки
type PromoCode struct {
Code string
DiscountPct Decimal
MaxUses int
ExpiresAt time.Time
UserID *int64 // nil = доступен всем
}
type ReferralProgram struct {
ReferrerRebatePct Decimal // % от комиссии рефери возвращается рефереру
RefereeDiscountPct Decimal // скидка на комиссии для приглашённого
MaxDepth int // уровни реферальной сети
}
Market Pair специфичные комиссии
Разные пары могут иметь разные комиссии:
- Стейблкоин пары (USDT/USDC): 0.01% — минимальные, высококонкурентный рынок
- Мем-коины: 0.3–0.5% — меньше конкуренции, биржа берёт больше
- Инсайдерские пары (собственный токен): 0% для маркет-мейкеров
func (fs *FeeSystem) GetPairFeeOverride(pair string) *FeeTier {
return fs.pairOverrides[pair] // nil если нет специальных условий
}
Мониторинг и аналитика
-- Доходы от комиссий по дням и парам
SELECT
DATE(t.created_at) AS date,
t.pair_id,
SUM(t.taker_fee) AS taker_revenue,
SUM(CASE WHEN t.maker_fee > 0 THEN t.maker_fee ELSE 0 END) AS maker_revenue,
SUM(CASE WHEN t.maker_fee < 0 THEN t.maker_fee ELSE 0 END) AS maker_rebates_paid,
SUM(t.taker_fee) + SUM(t.maker_fee) AS net_revenue,
COUNT(*) AS trade_count
FROM trades t
WHERE t.created_at >= NOW() - INTERVAL '30 days'
GROUP BY DATE(t.created_at), t.pair_id
ORDER BY date DESC;
Разработка полной системы комиссий с maker-taker моделью, volume тирами, токен дискаунтами и реферальной программой: 3–4 недели.







