@@ -8,37 +8,34 @@ module Bfx.Math
8
8
)
9
9
where
10
10
11
- import Data.Ratio.Rounding (dpRound , sdRound )
12
11
import Functora.Money
13
12
import Functora.Prelude
13
+ import Functora.Round (dpRound , sdRound )
14
14
15
15
roundMoneyAmount :: (MonadThrow m ) => MoneyAmount -> m MoneyAmount
16
- roundMoneyAmount arg@ (MoneyAmount raw) =
17
- if raw >= 0 && rounded >= 0
18
- then pure $ MoneyAmount rounded
19
- else throwString $ " Rounding error for " <> inspect @ String arg
20
- where
21
- rounded =
22
- unsafeFrom @ Rational @ (Ratio Natural )
23
- . roundMoneyAmountRat
24
- $ from @ (Ratio Natural ) @ Rational raw
16
+ roundMoneyAmount prev = do
17
+ next <-
18
+ either throw (pure . MoneyAmount )
19
+ . tryFrom @ Fix @ FixNonNeg
20
+ . dpRound 8
21
+ . unFixNonNeg
22
+ $ unMoneyAmount prev
23
+ if prev >= 0 && next >= 0
24
+ then pure next
25
+ else throwString $ " Rounding error for " <> inspect @ Text prev
25
26
26
27
roundQuotePerBase :: (MonadThrow m ) => QuotePerBase -> m QuotePerBase
27
- roundQuotePerBase arg@ (QuotePerBase raw) =
28
- if raw > 0 && rounded > 0
29
- then pure $ QuotePerBase rounded
30
- else throwString $ " Rounding error for " <> inspect @ String arg
31
- where
32
- rounded =
33
- unsafeFrom @ Rational @ (Ratio Natural )
34
- . roundQuotePerBaseRat
35
- $ from @ (Ratio Natural ) @ Rational raw
36
-
37
- roundMoneyAmountRat :: Rational -> Rational
38
- roundMoneyAmountRat = dpRound 8
39
-
40
- roundQuotePerBaseRat :: Rational -> Rational
41
- roundQuotePerBaseRat = sdRound 5 . dpRound 8
28
+ roundQuotePerBase prev = do
29
+ next <-
30
+ either throw (pure . QuotePerBase )
31
+ . tryFrom @ Fix @ FixNonNeg
32
+ . sdRound 5
33
+ . dpRound 8
34
+ . unFixNonNeg
35
+ $ unQuotePerBase prev
36
+ if prev > 0 && next > 0
37
+ then pure next
38
+ else throwString $ " Rounding error for " <> inspect @ Text prev
42
39
43
40
tweakMoneyAmount ::
44
41
( MonadThrow m
@@ -52,22 +49,20 @@ tweakMoneyAmount =
52
49
tweakMoneyAmountRec ::
53
50
( MonadThrow m
54
51
) =>
55
- Ratio Natural ->
52
+ MoneyAmount ->
56
53
BuyOrSell ->
57
54
MoneyAmount ->
58
55
m MoneyAmount
59
56
tweakMoneyAmountRec tweak bos prev = do
60
57
next <-
61
- roundMoneyAmount
62
- . MoneyAmount
63
- $ case bos of
64
- Buy -> unMoneyAmount prev + tweak
65
- Sell -> unMoneyAmount prev - tweak
58
+ roundMoneyAmount $ case bos of
59
+ Buy -> prev + tweak
60
+ Sell -> prev - tweak
66
61
if next /= prev
67
62
then pure next
68
63
else tweakMoneyAmountRec (tweak + pip) bos prev
69
64
70
- pip :: Ratio Natural
65
+ pip :: MoneyAmount
71
66
pip = 0.00000001
72
67
73
68
tweakQuotePerBase ::
@@ -79,24 +74,20 @@ tweakQuotePerBase ::
79
74
tweakQuotePerBase bos rate =
80
75
tweakQuotePerBaseRec rate (* tweak)
81
76
where
82
- tweak :: Ratio Natural
77
+ tweak :: QuotePerBase
83
78
tweak =
84
79
case bos of
85
- Buy -> 999 % 1000
86
- Sell -> 1001 % 1000
80
+ Buy -> 0. 999
81
+ Sell -> 1.001
87
82
88
83
tweakQuotePerBaseRec ::
89
84
( MonadThrow m
90
85
) =>
91
86
QuotePerBase ->
92
- (Ratio Natural -> Ratio Natural ) ->
87
+ (QuotePerBase -> QuotePerBase ) ->
93
88
m QuotePerBase
94
89
tweakQuotePerBaseRec prev tweak = do
95
- next <-
96
- roundQuotePerBase
97
- . QuotePerBase
98
- . tweak
99
- $ unQuotePerBase prev
90
+ next <- roundQuotePerBase $ tweak prev
100
91
if next /= prev
101
92
then pure next
102
93
else tweakQuotePerBaseRec prev $ tweak . tweak
0 commit comments