Files
Dena/app/models/trading_fee.rb
2026-08-13 19:50:53 +03:30

138 lines
4.8 KiB
Ruby

# encoding: UTF-8
# frozen_string_literal: true
# A trading fee schedule is a complete listing of maker and taker fees.
#
# E.g
# +-----------+---------+---------+---------+---------------------+---------------------+
# | market_id | group | maker | taker | created_at | updated_at |
# +-----------+---------+---------+---------+---------------------+---------------------+
# | any | any | 0.0012 | 0.0012 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# | any | vip-0 | 0.0011 | 0.0011 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# | btcusd | any | 0.0011 | 0.0011 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# | btcusd | vip-0 | 0.001 | 0.001 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# | btcusd | vip-1 | 0.0009 | 0.001 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# | btcusd | vip-2 | 0.0007 | 0.0009 | 2019-07-31 13:41:00 | 2019-07-31 13:41:00 |
# +-----------+---------+---------+---------+---------------------+---------------------+
#
# for member with unspecified group and market
# maker fee will be 0.12%;
# taker fee will be 0.12%;
# for member with group vip-0 and with unspecified market
# maker fee will be 0.11%;
# taker fee will be 0.11%;
# for member with market btcusd and with unspecified group
# maker fee will be 0.11%;
# taker fee will be 0.11%;
# for member with group vip-0 and for market btcusd
# maker fee will be 0.1%;
# taker fee will be 0.1%;
# for member with group vip-1 and for market btcusd
# maker fee will be 0.09%;
# taker fee will be 0.1%;
# for member with group vip-2 and for market btcusd
# maker fee will be 0.07%;
# taker fee will be 0.09%;
#
class TradingFee < ApplicationRecord
# == Constants ============================================================
# For fee we define static precision - 4.
FEE_PRECISION = 6
MIN_FEE = 0
MAX_FEE = 0.5
# Default value for group name and market_id in TradingFee table;
ANY = 'any'
# == Attributes ===========================================================
# == Extensions ===========================================================
# == Relationships ========================================================
belongs_to :market, optional: true
# == Validations ==========================================================
validates :group,
presence: true,
uniqueness: { scope: :market_id }
validates :maker,
:taker,
presence: true,
numericality: { greater_than_or_equal_to: MIN_FEE,
less_than_or_equal_to: MAX_FEE }
validates :market_id,
presence: true,
inclusion: { in: ->(_fs){ Market.ids.append(ANY) } }
validates :maker, :taker, precision: { less_than_or_eq_to: FEE_PRECISION }
# == Scopes ===============================================================
# == Callbacks ============================================================
before_create { self.group = self.group.strip.downcase }
after_commit :wipe_cache
# == Class Methods ========================================================
class << self
# Get trading fee for specific order that based on member group and market_id.
# TradingFee record selected with the next priorities:
# 1. both group and market_id match
# 2. group match
# 3. market_id match
# 4. both group and market_id are 'any'
# 5. default (zero fees)
def for(group:, market_id:)
TradingFee
.where(market_id: [market_id, ANY], group: [group, ANY])
.max_by { |fs| fs.weight } || TradingFee.new
end
end
# == Instance Methods =====================================================
# Trading fee suitability expressed in weight.
# Trading fee with the greatest weight selected.
# Group match has greater weight then market_id match.
# E.g. Order for member with group 'vip-0' and market_id 'btcusd'
# (group == 'vip-0' && market_id == 'btcusd') >
# (group == 'vip-0' && market_id == 'any') >
# (group == 'any' && market_id == 'btcusd') >
# (group == 'any' && market_id == 'any')
def weight
(group == 'any' ? 0 : 10) + (market_id == 'any' ? 0 : 1)
end
def wipe_cache
Rails.cache.delete_matched("trading_fees*")
end
end
# == Schema Information
# Schema version: 20201125134745
#
# Table name: trading_fees
#
# id :bigint not null, primary key
# market_id :string(20) default("any"), not null
# group :string(32) default("any"), not null
# maker :decimal(7, 6) default(0.0), not null
# taker :decimal(7, 6) default(0.0), not null
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_trading_fees_on_group (group)
# index_trading_fees_on_market_id (market_id)
# index_trading_fees_on_market_id_and_group (market_id,group) UNIQUE
#