Skip to content

Instantly share code, notes, and snippets.

@lexszero
Last active August 8, 2018 16:33
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save lexszero/c2999b20456d06c79561 to your computer and use it in GitHub Desktop.
Bitfinex margin trading calculator
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