Skip to content

Instantly share code, notes, and snippets.

@miklcct
Created September 5, 2019 14:08
Show Gist options
  • Save miklcct/6e56b8d528c7f3cdbf3031148b6185f0 to your computer and use it in GitHub Desktop.
Save miklcct/6e56b8d528c7f3cdbf3031148b6185f0 to your computer and use it in GitHub Desktop.
I-Access trading fee
import System.IO
import Text.Printf
round' :: (RealFrac a, Integral b) => a -> b
round' x = truncate (x + 0.5)
roundAmount :: (RealFrac a) => a -> a
roundAmount x = fromIntegral ((round' (x * 100)) :: Integer) / 100
inputItem :: (Read a) => String -> IO a
inputItem description = do
putStr description
getLine >>= return . read
outputItem :: String -> Double -> IO ()
outputItem description value = do
putStr description
printf "%.2f\n" value
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
price <- inputItem "Price: " :: IO Double
n_shares <- inputItem "Shares bought/sold: " :: IO Int
dutiable <- inputItem "Stamp-dutiable (0 or 1): " :: IO Int
let sell = n_shares < 0
n_shares_abs = abs n_shares
amount = roundAmount (price * fromIntegral n_shares_abs)
duty = fromIntegral $ ceiling (amount / 1000) * dutiable
trading_fee = roundAmount (amount * 0.00005)
levy = roundAmount (amount * 0.000027)
settlement = max (roundAmount (amount * 0.00005)) 2.0
tariff = 0.5
system_fee = 0.5
total = duty + trading_fee + levy + settlement + tariff + system_fee
putStr "Action: "
putStrLn (if sell then "Sell" else "Buy")
putStr "Number of shares: "
print n_shares_abs
_ <- sequence $ map (uncurry outputItem) [("Transaction amount: ", amount),
("Stamp duty: ", duty),
("Trading fee: ", trading_fee),
("SFC levy: ", levy),
("Clearing fee: ", settlement),
("HKEx trading tariff: ", tariff),
("ISSnet system fee: ", system_fee) ]
putStrLn ""
_ <- sequence $ map (uncurry outputItem) [("Total fee: ", total),
("Settlement amount: ", amount * (if sell then 1 else -1) - total)]
return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment