use crate::{prelude::Side, types::Order};
#[derive(Clone)]
pub struct CommonFees {
maker_fee: f64,
taker_fee: f64,
}
impl CommonFees {
pub fn new(maker_fee: f64, taker_fee: f64) -> Self {
Self {
maker_fee,
taker_fee,
}
}
}
#[derive(Clone)]
pub struct DirectionalFees {
common_fees: CommonFees,
buyer_fee: f64,
seller_fee: f64,
}
impl DirectionalFees {
pub fn new(common_fees: CommonFees, buyer_fee: f64, seller_fee: f64) -> Self {
Self {
common_fees,
buyer_fee,
seller_fee,
}
}
}
pub trait FeeModel {
fn amount(&self, order: &Order, amount: f64) -> f64;
}
#[derive(Clone)]
pub struct TradingValueFeeModel<Fees> {
fees: Fees,
}
impl<Fees> TradingValueFeeModel<Fees> {
pub fn new(fees: Fees) -> Self {
Self { fees }
}
}
impl FeeModel for TradingValueFeeModel<CommonFees> {
fn amount(&self, order: &Order, amount: f64) -> f64 {
if order.maker {
self.fees.maker_fee * amount
} else {
self.fees.taker_fee * amount
}
}
}
impl FeeModel for TradingValueFeeModel<DirectionalFees> {
fn amount(&self, order: &Order, amount: f64) -> f64 {
match (order.maker, order.side) {
(true, Side::Buy) => (self.fees.common_fees.maker_fee + self.fees.buyer_fee) * amount,
(false, Side::Buy) => (self.fees.common_fees.taker_fee + self.fees.buyer_fee) * amount,
(true, Side::Sell) => (self.fees.common_fees.maker_fee + self.fees.seller_fee) * amount,
(false, Side::Sell) => {
(self.fees.common_fees.taker_fee + self.fees.seller_fee) * amount
}
_ => unreachable!(),
}
}
}
#[derive(Clone)]
pub struct TradingQtyFeeModel<Fees> {
fees: Fees,
}
impl<Fees> TradingQtyFeeModel<Fees> {
pub fn new(fees: Fees) -> Self {
Self { fees }
}
}
impl FeeModel for TradingQtyFeeModel<CommonFees> {
fn amount(&self, order: &Order, _amount: f64) -> f64 {
if order.maker {
self.fees.maker_fee * order.exec_qty
} else {
self.fees.taker_fee * order.exec_qty
}
}
}
impl FeeModel for TradingQtyFeeModel<DirectionalFees> {
fn amount(&self, order: &Order, amount: f64) -> f64 {
match (order.maker, order.side) {
(true, Side::Buy) => {
self.fees.common_fees.maker_fee * order.exec_qty + self.fees.buyer_fee * amount
}
(false, Side::Buy) => {
self.fees.common_fees.taker_fee * order.exec_qty + self.fees.buyer_fee * amount
}
(true, Side::Sell) => {
self.fees.common_fees.maker_fee * order.exec_qty + self.fees.seller_fee * amount
}
(false, Side::Sell) => {
self.fees.common_fees.taker_fee * order.exec_qty + self.fees.seller_fee * amount
}
_ => unreachable!(),
}
}
}
#[derive(Clone)]
pub struct FlatPerTradeFeeModel<Fees> {
fees: Fees,
}
impl<Fees> FlatPerTradeFeeModel<Fees> {
pub fn new(fees: Fees) -> Self {
Self { fees }
}
}
impl FeeModel for FlatPerTradeFeeModel<CommonFees> {
fn amount(&self, order: &Order, _amount: f64) -> f64 {
if order.maker {
self.fees.maker_fee
} else {
self.fees.taker_fee
}
}
}