Skip to main content

openpit/param/
fee.rs

1// Copyright The Pit Project Owners. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16// Please see https://github.com/openpitkit and the OWNERS file for details.
17
18use super::{define_signed_value_type, CashFlow, ParamKind, Pnl, PositionSize};
19
20define_signed_value_type!(
21    /// Fee amount.
22    ///
23    /// Can be negative when representing rebates or fee adjustments in reconciliation.
24    Fee,
25    ParamKind::Fee
26);
27
28impl Fee {
29    /// Converts fee into a negative P&L contribution.
30    pub fn to_pnl(self) -> Pnl {
31        Pnl::new(-self.to_decimal())
32    }
33
34    /// Converts fee into a position size for instruments where fees are paid in the base asset.
35    ///
36    /// The resulting position size is negative (representing an outflow) for positive fees,
37    /// and positive for fee rebates.
38    pub fn to_position_size(self) -> PositionSize {
39        PositionSize::new(-self.to_decimal())
40    }
41
42    /// Converts fee into a cash flow contribution (negates the fee amount).
43    pub fn to_cash_flow(self) -> CashFlow {
44        CashFlow::from_fee(self)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::Fee;
51    use crate::param::{CashFlow, Pnl, PositionSize};
52    use rust_decimal::Decimal;
53
54    fn d(value: &str) -> Decimal {
55        value
56            .parse()
57            .expect("decimal literal in tests must be valid")
58    }
59
60    #[test]
61    fn converts_to_negative_pnl() {
62        let fee = Fee::new(d("3.18"));
63
64        assert_eq!(fee.to_pnl(), Pnl::new(d("-3.18")));
65    }
66
67    #[test]
68    fn converts_to_position_size() {
69        let fee = Fee::new(d("2.5"));
70        let rebate = Fee::new(d("-2.5"));
71
72        assert_eq!(fee.to_position_size(), PositionSize::new(d("-2.5")));
73        assert_eq!(rebate.to_position_size(), PositionSize::new(d("2.5")));
74    }
75
76    #[test]
77    fn converts_to_cash_flow() {
78        let fee = Fee::new(d("3.18"));
79
80        assert_eq!(fee.to_cash_flow(), CashFlow::new(d("-3.18")));
81    }
82}