Browse Source

New type Price

master
Denis Tereshkin 8 years ago
parent
commit
ce6db1e1d0
  1. 1
      libatrade.cabal
  2. 37
      src/ATrade/Price.hs
  3. 2
      src/ATrade/Types.hs
  4. 4
      test/ArbitraryInstances.hs
  5. 12
      test/TestTypes.hs

1
libatrade.cabal

@ -17,6 +17,7 @@ library
hs-source-dirs: src hs-source-dirs: src
ghc-options: -Wincomplete-patterns ghc-options: -Wincomplete-patterns
exposed-modules: ATrade.Types exposed-modules: ATrade.Types
, ATrade.Price
, ATrade.QuoteSource.Client , ATrade.QuoteSource.Client
, ATrade.QuoteSource.Server , ATrade.QuoteSource.Server
, ATrade.Broker.Client , ATrade.Broker.Client

37
src/ATrade/Price.hs

@ -0,0 +1,37 @@
{-# LANGUAGE MultiWayIf #-}
module ATrade.Price (
Price(..),
fromDouble,
toDouble
) where
import Data.Int
data Price = Price {
priceQuants :: !Int64
} deriving (Eq, Show, Ord)
giga :: Int64
giga = 1000000000
instance Num Price where
a + b = Price {
priceQuants = priceQuants a + priceQuants b }
a * b = Price {
priceQuants = (priceQuants a * priceQuants b) `div` giga }
abs a = a { priceQuants = abs (priceQuants a) }
signum a = a { priceQuants = signum (priceQuants a)}
fromInteger int = Price { priceQuants = giga * fromInteger int}
negate a = a { priceQuants = negate (priceQuants a) }
toDouble :: Price -> Double
toDouble p = fromIntegral (priceQuants p) / fromIntegral giga
fromDouble :: Double -> Price
fromDouble d = Price { priceQuants = truncate (d * fromIntegral giga) }

2
src/ATrade/Types.hs

@ -163,7 +163,7 @@ data Bar = Bar {
barLow :: !Decimal, barLow :: !Decimal,
barClose :: !Decimal, barClose :: !Decimal,
barVolume :: !Integer barVolume :: !Integer
} deriving (Show, Eq) } deriving (Show, Eq, Generic)
data SignalId = SignalId { data SignalId = SignalId {
strategyId :: T.Text, strategyId :: T.Text,

4
test/ArbitraryInstances.hs

@ -11,8 +11,10 @@ import Test.Tasty.QuickCheck as QC
import Test.QuickCheck.Instances hiding (Text) import Test.QuickCheck.Instances hiding (Text)
import ATrade.Types import ATrade.Types
import ATrade.Price as P
import ATrade.Broker.Protocol import ATrade.Broker.Protocol
import Data.Int
import Data.Decimal import Data.Decimal
import Data.Scientific import Data.Scientific
import Data.Time.Clock import Data.Time.Clock
@ -117,3 +119,5 @@ instance Arbitrary BrokerServerResponse where
| t == 3 -> ResponseNotifications <$> arbitrary | t == 3 -> ResponseNotifications <$> arbitrary
| t == 4 -> ResponseError <$> arbitrary | t == 4 -> ResponseError <$> arbitrary
instance Arbitrary P.Price where
arbitrary = P.Price <$> arbitrary

12
test/TestTypes.hs

@ -11,6 +11,7 @@ import Test.Tasty.QuickCheck as QC
import Test.Tasty.HUnit import Test.Tasty.HUnit
import ATrade.Types import ATrade.Types
import ATrade.Price as P
import ArbitraryInstances import ArbitraryInstances
import Data.Aeson import Data.Aeson
@ -32,6 +33,8 @@ properties = testGroup "Types" [
, testOrderStateSerialization , testOrderStateSerialization
, testOrderSerialization , testOrderSerialization
, testTradeSerialization , testTradeSerialization
, testPrice1
, testPrice2
] ]
testTickSerialization = QC.testProperty "Deserialize serialized tick" testTickSerialization = QC.testProperty "Deserialize serialized tick"
@ -80,3 +83,12 @@ testTradeSerialization = QC.testProperty "Deserialize serialized Trade"
(\v -> case (decode . encode $ v :: Maybe Trade) of (\v -> case (decode . encode $ v :: Maybe Trade) of
Just s -> s == v Just s -> s == v
Nothing -> False) Nothing -> False)
testPrice1 = QC.testProperty "fromDouble . toDouble $ Price"
(\p -> let newp = (P.fromDouble . P.toDouble) p in
(abs (priceQuants newp - priceQuants p) < 1000))
testPrice2 = QC.testProperty "toDouble . fromDouble $ Price" $
QC.forAll (arbitrary `suchThat` (< 1000000000)) (\d -> let newd = (P.toDouble . P.fromDouble) d in
(abs (newd - d) < 0.000001))

Loading…
Cancel
Save