138 lines
4.8 KiB
Ruby
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
|
|
#
|