Bitfinex margin trading calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad.State | |
import Text.Printf | |
initiallyRequired = 0.3 | |
maintenanceRequired = 0.15 | |
takerFee = 0.002 | |
type Amount = Double | |
type Price = Double | |
data Position = Position Amount Price | |
instance Show Position where | |
show (Position a p) = printf "%.2f @ %.2f" a p | |
positionProfit p1 (Position a p0) = a * (p1-p0) | |
(Position a1 p1) |+| (Position a2 p2) = Position (a1+a2) ((a1*p1+a2*p2)/(a1+a2)) | |
data Account = Account Amount Position | |
instance Show Account where | |
show a@(Account bal pos) = printf "Balance: %.2f\nPosition: %s (liq at %.2f)" | |
bal (show pos) (liquidationPrice a) :: String | |
liquidationPrice :: Account -> Price | |
liquidationPrice (Account bal (Position a p)) = (1+maintenanceRequired)*p-bal/a | |
maxAmount :: Account -> Price -> Amount | |
maxAmount (Account bal _) p = ((1-takerFee)/p/initiallyRequired) * bal | |
trade :: Price -> Amount -> State Account () | |
trade p a = do | |
Account bal pos <- get | |
put $ Account (bal - (abs a*p*takerFee)) (pos |+| Position a p) | |
close :: Price -> State Account () | |
close p = do | |
Account bal pos@(Position a _) <- get | |
put $ Account (bal + (positionProfit p pos) - (abs a*p*takerFee)) (Position 0 0) | |
buy :: Price -> Amount -> State Account () | |
buy p a = trade p a | |
sell :: Price -> Amount -> State Account () | |
sell p a = trade p (-a) | |
buyAll :: Price -> State Account () | |
buyAll p = get >>= \a -> buy p (maxAmount a p) | |
sellAll :: Price -> State Account () | |
sellAll p = get >>= \a -> sell p (maxAmount a p) | |
-- reopen will close position and open new one in same direction | |
reopen :: Price -> State Account () | |
reopen p = do | |
Account _ (Position a _) <- get | |
close p | |
if a > 0 then buyAll p else sellAll p | |
-- turnaround will close position and open new one in opposite direction | |
turnaround :: Price -> State Account () | |
turnaround p = do | |
Account _ (Position a _) <- get | |
close p | |
if a > 0 then sellAll p else buyAll p | |
-- inital account state | |
now = Account 1035.72 (Position 7.3 342.27) | |
{- or initial account state as result of some actions | |
now = execState (do | |
buy 361.49 9.3 | |
reopen 370 | |
) $ Account 1044.49 (Position 0 0) | |
-} | |
-- call like this: | |
-- estimate $ buy 330 1 >> turnaround 340 >> close 320 >> buyAll 330 | |
estimate = (flip execState) now |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment