Skip to content

Commit 2050cf8

Browse files
committed
bfx wip
1 parent c759e41 commit 2050cf8

File tree

5 files changed

+130
-70
lines changed

5 files changed

+130
-70
lines changed

pub/bfx/src/Bfx.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,16 +371,17 @@ mkSubmitCounterOrder submit env id0 rates opts = do
371371
case orderBuyOrSell remOrder of
372372
Buy | orderStatus remOrder == Executed -> do
373373
counter <-
374-
newCounterOrder
374+
mkCounterOrder
375375
CounterArgs
376-
{ counterArgsEnterGrossBaseGain =
376+
{ counterArgsEnterBuyOrSell = Buy,
377+
counterArgsEnterGrossBase =
377378
orderBaseAmount remOrder,
378379
counterArgsEnterQuotePerBase =
379380
orderRate remOrder,
380381
counterArgsRates =
381382
rates
382383
}
383-
let exitAmt = counterExitNetBaseLoss counter
384+
let exitAmt = counterExitGrossBase counter
384385
let exitRate = counterExitQuotePerBase counter
385386
currentRate <-
386387
marketAveragePrice

pub/bfx/src/Bfx/Math.hs

Lines changed: 89 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Bfx.Math
44
( tweakMoneyAmount,
55
tweakQuotePerBase,
6-
newCounterOrder,
6+
mkCounterOrder,
77
CounterArgs (..),
88
CounterRates (..),
99
CounterExit (..),
@@ -43,37 +43,43 @@ tweakMoneyAmountRec tweak bos prev = do
4343
then pure next
4444
else tweakMoneyAmountRec (tweak + pip) bos prev
4545

46+
pip :: Ratio Natural
47+
pip = 0.00000001
48+
4649
tweakQuotePerBase ::
4750
( MonadThrow m
4851
) =>
4952
BuyOrSell ->
5053
QuotePerBase ->
5154
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
5463

5564
tweakQuotePerBaseRec ::
5665
( MonadThrow m
5766
) =>
58-
Ratio Natural ->
59-
BuyOrSell ->
6067
QuotePerBase ->
68+
(Ratio Natural -> Ratio Natural) ->
6169
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
6876
if next /= prev
6977
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
7479

7580
data CounterArgs = CounterArgs
76-
{ counterArgsEnterGrossBaseGain :: MoneyAmount,
81+
{ counterArgsEnterBuyOrSell :: BuyOrSell,
82+
counterArgsEnterGrossBase :: MoneyAmount,
7783
counterArgsEnterQuotePerBase :: QuotePerBase,
7884
counterArgsRates :: CounterRates
7985
}
@@ -87,9 +93,8 @@ data CounterArgs = CounterArgs
8793
)
8894

8995
data CounterRates = CounterRates
90-
{ counterRatesEnterBaseFee :: FeeRate,
91-
counterRatesExitQuoteFee :: FeeRate,
92-
counterRatesExitQuoteProfit :: ProfitRate
96+
{ counterRatesFee :: FeeRate,
97+
counterRatesProfit :: ProfitRate
9398
}
9499
deriving stock
95100
( Eq,
@@ -101,7 +106,8 @@ data CounterRates = CounterRates
101106
)
102107

103108
data CounterExit = CounterExit
104-
{ counterExitNetBaseLoss :: MoneyAmount,
109+
{ counterExitBuyOrSell :: BuyOrSell,
110+
counterExitGrossBase :: MoneyAmount,
105111
counterExitQuotePerBase :: QuotePerBase
106112
}
107113
deriving stock
@@ -113,47 +119,75 @@ data CounterExit = CounterExit
113119
Generic
114120
)
115121

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
120132
pure
121133
CounterExit
122-
{ counterExitNetBaseLoss = exitBase,
123-
counterExitQuotePerBase = exitPrice
134+
{ counterExitBuyOrSell = exitBos,
135+
counterExitGrossBase = exitBase,
136+
counterExitQuotePerBase = exitRate
124137
}
125138
where
126-
enterBaseGain :: MoneyAmount
127-
enterBaseGain =
128-
counterArgsEnterGrossBaseGain args
139+
enterBos :: BuyOrSell
140+
enterBos = counterArgsEnterBuyOrSell args
129141
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+
--
149173
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
157191

158192
roundMoneyAmount :: (MonadThrow m) => MoneyAmount -> m MoneyAmount
159193
roundMoneyAmount arg@(MoneyAmount raw) =

pub/bfx/test/Bfx/MathSpec.hs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,52 @@ import Functora.Prelude
1111
import Test.Hspec
1212

1313
spec :: Spec
14-
spec =
15-
it "newCounterOrder" $ do
14+
spec = do
15+
it "mkCounterOrder/Buy" $ do
1616
let rates =
1717
CounterRates
18-
{ counterRatesEnterBaseFee = FeeRate 0.001,
19-
counterRatesExitQuoteFee = FeeRate 0.001,
20-
counterRatesExitQuoteProfit = ProfitRate 0.01
18+
{ counterRatesFee = FeeRate 0.001,
19+
counterRatesProfit = ProfitRate 0.01
2120
}
2221
let args =
2322
CounterArgs
24-
{ counterArgsEnterGrossBaseGain = MoneyAmount 0.2,
23+
{ counterArgsEnterBuyOrSell = Buy,
24+
counterArgsEnterGrossBase = MoneyAmount 0.2,
2525
counterArgsEnterQuotePerBase = QuotePerBase 5,
2626
counterArgsRates = rates
2727
}
28-
exit <- newCounterOrder args
28+
exit <- mkCounterOrder args
2929
exit
3030
`shouldBe` CounterExit
31-
{ -- Deduct fee and pip:
31+
{ counterExitBuyOrSell = Sell,
32+
-- Deduct fee and pip:
3233
-- 0.2 * 0.999 - 0.00000001
33-
counterExitNetBaseLoss = MoneyAmount 0.19979999,
34+
counterExitGrossBase = MoneyAmount 0.19979999,
3435
-- Add profit and fee:
3536
-- ((0.2 * 5) * (1 + 0.01) / (1 - 0.001)) / 0.19979999
3637
counterExitQuotePerBase = QuotePerBase 5.0601
3738
}
39+
it "mkCounterOrder/Sell" $ do
40+
let rates =
41+
CounterRates
42+
{ counterRatesFee = FeeRate 0.001,
43+
counterRatesProfit = ProfitRate 0.01
44+
}
45+
let args =
46+
CounterArgs
47+
{ counterArgsEnterBuyOrSell = Sell,
48+
counterArgsEnterGrossBase = MoneyAmount 0.2,
49+
counterArgsEnterQuotePerBase = QuotePerBase 5,
50+
counterArgsRates = rates
51+
}
52+
exit <- mkCounterOrder args
53+
exit
54+
`shouldBe` CounterExit
55+
{ counterExitBuyOrSell = Buy,
56+
-- Add profit, deduct fee and add pip:
57+
-- ((0.2 * (1 + 0.01)) / (1 - 0.001)) + 0.00000001
58+
counterExitGrossBase = MoneyAmount 0.20220221,
59+
-- Deduct fee and divide by base:
60+
-- (0.2 * 5 * (1 - 0.001)) / 0.20220221
61+
counterExitQuotePerBase = QuotePerBase 4.9406
62+
}

pub/bfx/test/BfxSpec.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,8 @@ spec = before sysEnv $ do
108108
env
109109
(OrderId 0)
110110
CounterRates
111-
{ counterRatesEnterBaseFee = FeeRate 0,
112-
counterRatesExitQuoteFee = FeeRate 0,
113-
counterRatesExitQuoteProfit = ProfitRate 0
111+
{ counterRatesFee = FeeRate 0,
112+
counterRatesProfit = ProfitRate 0
114113
}
115114
SubmitOrder.optsPostOnly
116115
res `shouldSatisfy` isLeft

pub/functora/src/sql/Functora/Sql.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import Database.Esqueleto.Legacy as X
6262
max_,
6363
min_,
6464
notIn,
65+
not_,
6566
nothing,
6667
offset,
6768
on,

0 commit comments

Comments
 (0)