3
3
module Bfx.Math
4
4
( tweakMoneyAmount ,
5
5
tweakQuotePerBase ,
6
- newCounterOrder ,
6
+ mkCounterOrder ,
7
7
CounterArgs (.. ),
8
8
CounterRates (.. ),
9
9
CounterExit (.. ),
@@ -43,37 +43,43 @@ tweakMoneyAmountRec tweak bos prev = do
43
43
then pure next
44
44
else tweakMoneyAmountRec (tweak + pip) bos prev
45
45
46
+ pip :: Ratio Natural
47
+ pip = 0.00000001
48
+
46
49
tweakQuotePerBase ::
47
50
( MonadThrow m
48
51
) =>
49
52
BuyOrSell ->
50
53
QuotePerBase ->
51
54
m QuotePerBase
52
- tweakQuotePerBase =
53
- tweakQuotePerBaseRec pip
55
+ tweakQuotePerBase bos rate =
56
+ tweakQuotePerBaseRec rate (* tweak)
57
+ where
58
+ tweak :: Ratio Natural
59
+ tweak =
60
+ case bos of
61
+ Buy -> 999 % 1000
62
+ Sell -> 1001 % 1000
54
63
55
64
tweakQuotePerBaseRec ::
56
65
( MonadThrow m
57
66
) =>
58
- Ratio Natural ->
59
- BuyOrSell ->
60
67
QuotePerBase ->
68
+ (Ratio Natural -> Ratio Natural ) ->
61
69
m QuotePerBase
62
- tweakQuotePerBaseRec tweak bos prev = do
63
- next <- roundQuotePerBase
64
- . QuotePerBase
65
- $ case bos of
66
- Buy -> unQuotePerBase prev - tweak
67
- Sell -> unQuotePerBase prev + tweak
70
+ tweakQuotePerBaseRec prev tweak = do
71
+ next <-
72
+ roundQuotePerBase
73
+ . QuotePerBase
74
+ . tweak
75
+ $ unQuotePerBase prev
68
76
if next /= prev
69
77
then pure next
70
- else tweakQuotePerBaseRec (tweak + pip) bos prev
71
-
72
- pip :: Ratio Natural
73
- pip = 0.00000001
78
+ else tweakQuotePerBaseRec prev $ tweak . tweak
74
79
75
80
data CounterArgs = CounterArgs
76
- { counterArgsEnterGrossBaseGain :: MoneyAmount ,
81
+ { counterArgsEnterBuyOrSell :: BuyOrSell ,
82
+ counterArgsEnterGrossBase :: MoneyAmount ,
77
83
counterArgsEnterQuotePerBase :: QuotePerBase ,
78
84
counterArgsRates :: CounterRates
79
85
}
@@ -87,9 +93,8 @@ data CounterArgs = CounterArgs
87
93
)
88
94
89
95
data CounterRates = CounterRates
90
- { counterRatesEnterBaseFee :: FeeRate ,
91
- counterRatesExitQuoteFee :: FeeRate ,
92
- counterRatesExitQuoteProfit :: ProfitRate
96
+ { counterRatesFee :: FeeRate ,
97
+ counterRatesProfit :: ProfitRate
93
98
}
94
99
deriving stock
95
100
( Eq ,
@@ -101,7 +106,8 @@ data CounterRates = CounterRates
101
106
)
102
107
103
108
data CounterExit = CounterExit
104
- { counterExitNetBaseLoss :: MoneyAmount ,
109
+ { counterExitBuyOrSell :: BuyOrSell ,
110
+ counterExitGrossBase :: MoneyAmount ,
105
111
counterExitQuotePerBase :: QuotePerBase
106
112
}
107
113
deriving stock
@@ -113,47 +119,75 @@ data CounterExit = CounterExit
113
119
Generic
114
120
)
115
121
116
- newCounterOrder :: (MonadThrow m ) => CounterArgs -> m CounterExit
117
- newCounterOrder args = do
118
- exitBase <- tweakMoneyAmount Sell exitBaseLoss
119
- exitPrice <- roundQuotePerBase exitRate
122
+ mkCounterOrder :: (MonadThrow m ) => CounterArgs -> m CounterExit
123
+ mkCounterOrder args = do
124
+ let exitBos = nextEnum enterBos
125
+ exitBase <-
126
+ tweakMoneyAmount exitBos exitGrossBase
127
+ exitRate <-
128
+ roundQuotePerBase
129
+ . QuotePerBase
130
+ $ unMoneyAmount exitGrossQuote
131
+ / unMoneyAmount exitBase
120
132
pure
121
133
CounterExit
122
- { counterExitNetBaseLoss = exitBase,
123
- counterExitQuotePerBase = exitPrice
134
+ { counterExitBuyOrSell = exitBos,
135
+ counterExitGrossBase = exitBase,
136
+ counterExitQuotePerBase = exitRate
124
137
}
125
138
where
126
- enterBaseGain :: MoneyAmount
127
- enterBaseGain =
128
- counterArgsEnterGrossBaseGain args
139
+ enterBos :: BuyOrSell
140
+ enterBos = counterArgsEnterBuyOrSell args
129
141
enterRate :: QuotePerBase
130
- enterRate =
131
- counterArgsEnterQuotePerBase args
132
- enterFee :: FeeRate
133
- enterFee =
134
- counterRatesEnterBaseFee $ counterArgsRates args
135
- exitFee :: FeeRate
136
- exitFee =
137
- counterRatesExitQuoteFee $ counterArgsRates args
138
- profRate :: ProfitRate
139
- profRate =
140
- counterRatesExitQuoteProfit $ counterArgsRates args
141
- exitBaseLoss :: MoneyAmount
142
- exitBaseLoss =
143
- MoneyAmount $ unMoneyAmount enterBaseGain * (1 - unFeeRate enterFee)
144
- enterQuoteLoss :: MoneyAmount
145
- enterQuoteLoss =
146
- MoneyAmount $ unMoneyAmount enterBaseGain * unQuotePerBase enterRate
147
- exitQuoteGain :: MoneyAmount
148
- exitQuoteGain =
142
+ enterRate = counterArgsEnterQuotePerBase args
143
+ enterBase :: MoneyAmount
144
+ enterBase = counterArgsEnterGrossBase args
145
+ enterNetLoss :: MoneyAmount
146
+ enterNetLoss =
147
+ MoneyAmount $ case enterBos of
148
+ Buy ->
149
+ -- Quote
150
+ unMoneyAmount enterBase
151
+ * unQuotePerBase enterRate
152
+ Sell ->
153
+ -- Base
154
+ unMoneyAmount enterBase
155
+ enterNetGain :: MoneyAmount
156
+ enterNetGain =
157
+ MoneyAmount $ case enterBos of
158
+ Buy ->
159
+ -- Base
160
+ unMoneyAmount enterBase
161
+ * (1 - unFeeRate feeRate)
162
+ Sell ->
163
+ -- Quote
164
+ unMoneyAmount enterBase
165
+ * unQuotePerBase enterRate
166
+ * (1 - unFeeRate feeRate)
167
+ exitGrossGain :: MoneyAmount
168
+ exitGrossGain =
169
+ --
170
+ -- Buy = Quote
171
+ -- Sell = Base
172
+ --
149
173
MoneyAmount
150
- $ (unMoneyAmount enterQuoteLoss * (1 + unProfitRate profRate))
151
- / (1 - unFeeRate exitFee)
152
- exitRate :: QuotePerBase
153
- exitRate =
154
- QuotePerBase
155
- $ unMoneyAmount exitQuoteGain
156
- / unMoneyAmount exitBaseLoss
174
+ $ unMoneyAmount enterNetLoss
175
+ * (1 + unProfitRate profitRate)
176
+ / (1 - unFeeRate feeRate)
177
+ exitGrossBase :: MoneyAmount
178
+ exitGrossBase =
179
+ case enterBos of
180
+ Buy -> enterNetGain
181
+ Sell -> exitGrossGain
182
+ exitGrossQuote :: MoneyAmount
183
+ exitGrossQuote =
184
+ case enterBos of
185
+ Buy -> exitGrossGain
186
+ Sell -> enterNetGain
187
+ feeRate :: FeeRate
188
+ feeRate = counterRatesFee $ counterArgsRates args
189
+ profitRate :: ProfitRate
190
+ profitRate = counterRatesProfit $ counterArgsRates args
157
191
158
192
roundMoneyAmount :: (MonadThrow m ) => MoneyAmount -> m MoneyAmount
159
193
roundMoneyAmount arg@ (MoneyAmount raw) =
0 commit comments