|
|
|
@ -1,9 +1,9 @@ |
|
|
|
{-# LANGUAGE DeriveGeneric #-} |
|
|
|
{-# LANGUAGE DeriveGeneric #-} |
|
|
|
|
|
|
|
{-# LANGUAGE FlexibleContexts #-} |
|
|
|
|
|
|
|
{-# LANGUAGE MultiWayIf #-} |
|
|
|
{-# LANGUAGE OverloadedStrings #-} |
|
|
|
{-# LANGUAGE OverloadedStrings #-} |
|
|
|
{-# LANGUAGE MultiWayIf #-} |
|
|
|
{-# LANGUAGE QuasiQuotes #-} |
|
|
|
{-# LANGUAGE FlexibleContexts #-} |
|
|
|
{-# LANGUAGE TypeApplications #-} |
|
|
|
{-# LANGUAGE TypeApplications #-} |
|
|
|
|
|
|
|
{-# LANGUAGE QuasiQuotes #-} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{-| |
|
|
|
{-| |
|
|
|
- Module : ATrade.RoboCom.Combinators |
|
|
|
- Module : ATrade.RoboCom.Combinators |
|
|
|
@ -67,20 +67,20 @@ module ATrade.RoboCom.Positions |
|
|
|
setStopLossAndTakeProfit |
|
|
|
setStopLossAndTakeProfit |
|
|
|
) where |
|
|
|
) where |
|
|
|
|
|
|
|
|
|
|
|
import GHC.Generics |
|
|
|
import GHC.Generics |
|
|
|
|
|
|
|
|
|
|
|
import ATrade.Types |
|
|
|
import ATrade.RoboCom.Monad |
|
|
|
import ATrade.RoboCom.Monad |
|
|
|
import ATrade.RoboCom.Types |
|
|
|
import ATrade.RoboCom.Types |
|
|
|
import ATrade.Types |
|
|
|
|
|
|
|
|
|
|
|
import Control.Monad |
|
|
|
import Control.Monad |
|
|
|
import Ether |
|
|
|
import Ether |
|
|
|
|
|
|
|
|
|
|
|
import Data.Aeson |
|
|
|
import Data.Aeson |
|
|
|
import qualified Data.Map as M |
|
|
|
import qualified Data.List as L |
|
|
|
import qualified Data.List as L |
|
|
|
import qualified Data.Map as M |
|
|
|
import qualified Data.Text as T |
|
|
|
import qualified Data.Text as T |
|
|
|
import Data.Time.Clock |
|
|
|
import Data.Time.Clock |
|
|
|
|
|
|
|
|
|
|
|
data PositionState = PositionWaitingOpenSubmission Order |
|
|
|
data PositionState = PositionWaitingOpenSubmission Order |
|
|
|
| PositionWaitingOpen |
|
|
|
| PositionWaitingOpen |
|
|
|
@ -93,20 +93,20 @@ data PositionState = PositionWaitingOpenSubmission Order |
|
|
|
deriving (Show, Eq, Generic) |
|
|
|
deriving (Show, Eq, Generic) |
|
|
|
|
|
|
|
|
|
|
|
data Position = Position { |
|
|
|
data Position = Position { |
|
|
|
posId :: T.Text, |
|
|
|
posId :: T.Text, |
|
|
|
posAccount :: T.Text, |
|
|
|
posAccount :: T.Text, |
|
|
|
posTicker :: TickerId, |
|
|
|
posTicker :: TickerId, |
|
|
|
posBalance :: Integer, |
|
|
|
posBalance :: Integer, |
|
|
|
posState :: PositionState, |
|
|
|
posState :: PositionState, |
|
|
|
posNextState :: Maybe PositionState, |
|
|
|
posNextState :: Maybe PositionState, |
|
|
|
posStopPrice :: Maybe Price, |
|
|
|
posStopPrice :: Maybe Price, |
|
|
|
posStopLimitPrice :: Maybe Price, |
|
|
|
posStopLimitPrice :: Maybe Price, |
|
|
|
posTakeProfitPrice :: Maybe Price, |
|
|
|
posTakeProfitPrice :: Maybe Price, |
|
|
|
posCurrentOrder :: Maybe Order, |
|
|
|
posCurrentOrder :: Maybe Order, |
|
|
|
posSubmissionDeadline :: Maybe UTCTime, |
|
|
|
posSubmissionDeadline :: Maybe UTCTime, |
|
|
|
posExecutionDeadline :: Maybe UTCTime, |
|
|
|
posExecutionDeadline :: Maybe UTCTime, |
|
|
|
posEntryTime :: Maybe UTCTime, |
|
|
|
posEntryTime :: Maybe UTCTime, |
|
|
|
posExitTime :: Maybe UTCTime |
|
|
|
posExitTime :: Maybe UTCTime |
|
|
|
} deriving (Show, Eq, Generic) |
|
|
|
} deriving (Show, Eq, Generic) |
|
|
|
|
|
|
|
|
|
|
|
posEqByIds :: Position -> Position -> Bool |
|
|
|
posEqByIds :: Position -> Position -> Bool |
|
|
|
@ -171,7 +171,7 @@ orderDeadline :: Maybe UTCTime -> UTCTime -> Bool |
|
|
|
orderDeadline maybeDeadline lastTs = |
|
|
|
orderDeadline maybeDeadline lastTs = |
|
|
|
case maybeDeadline of |
|
|
|
case maybeDeadline of |
|
|
|
Just deadline -> lastTs >= deadline |
|
|
|
Just deadline -> lastTs >= deadline |
|
|
|
Nothing -> False |
|
|
|
Nothing -> False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dispatchPosition :: (StateHasPositions s, MonadRobot m c s) => Event -> Position -> m Position |
|
|
|
dispatchPosition :: (StateHasPositions s, MonadRobot m c s) => Event -> Position -> m Position |
|
|
|
@ -249,7 +249,7 @@ dispatchPosition event pos = case posState pos of |
|
|
|
| otherwise -> case event of |
|
|
|
| otherwise -> case event of |
|
|
|
NewTick tick -> if |
|
|
|
NewTick tick -> if |
|
|
|
| datatype tick == LastTradePrice && stopLoss tick -> case posStopLimitPrice pos of |
|
|
|
| datatype tick == LastTradePrice && stopLoss tick -> case posStopLimitPrice pos of |
|
|
|
Nothing -> exitAtMarket pos "stop" |
|
|
|
Nothing -> exitAtMarket pos "stop" |
|
|
|
Just lim -> exitAtLimit 86400 lim pos "stop" |
|
|
|
Just lim -> exitAtLimit 86400 lim pos "stop" |
|
|
|
| datatype tick == LastTradePrice && takeProfit tick -> exitAtMarket pos "take_profit" |
|
|
|
| datatype tick == LastTradePrice && takeProfit tick -> exitAtMarket pos "take_profit" |
|
|
|
| otherwise -> return pos |
|
|
|
| otherwise -> return pos |
|
|
|
@ -285,7 +285,7 @@ dispatchPosition event pos = case posState pos of |
|
|
|
then do |
|
|
|
then do |
|
|
|
case posCurrentOrder pos of |
|
|
|
case posCurrentOrder pos of |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
Nothing -> doNothing |
|
|
|
Nothing -> doNothing |
|
|
|
return $ pos { posCurrentOrder = Nothing, posState = PositionOpen, posSubmissionDeadline = Nothing } -- TODO call TimeoutHandler if present |
|
|
|
return $ pos { posCurrentOrder = Nothing, posState = PositionOpen, posSubmissionDeadline = Nothing } -- TODO call TimeoutHandler if present |
|
|
|
else case event of |
|
|
|
else case event of |
|
|
|
OrderSubmitted order -> |
|
|
|
OrderSubmitted order -> |
|
|
|
@ -302,7 +302,7 @@ dispatchPosition event pos = case posState pos of |
|
|
|
then do |
|
|
|
then do |
|
|
|
case posCurrentOrder pos of |
|
|
|
case posCurrentOrder pos of |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
return $ pos { posState = PositionOpen, posSubmissionDeadline = Nothing, posExecutionDeadline = Nothing } -- TODO call TimeoutHandler if present |
|
|
|
return $ pos { posState = PositionOpen, posSubmissionDeadline = Nothing, posExecutionDeadline = Nothing } -- TODO call TimeoutHandler if present |
|
|
|
else case (event, posCurrentOrder pos) of |
|
|
|
else case (event, posCurrentOrder pos) of |
|
|
|
(OrderUpdate oid newstate, Just order) -> |
|
|
|
(OrderUpdate oid newstate, Just order) -> |
|
|
|
@ -381,7 +381,7 @@ getCurrentTicker = do |
|
|
|
maybeBars <- flip M.lookup bars . mainTicker <$> getConfig |
|
|
|
maybeBars <- flip M.lookup bars . mainTicker <$> getConfig |
|
|
|
case maybeBars of |
|
|
|
case maybeBars of |
|
|
|
Just b -> return $ bsBars b |
|
|
|
Just b -> return $ bsBars b |
|
|
|
_ -> return [] |
|
|
|
_ -> return [] |
|
|
|
|
|
|
|
|
|
|
|
getCurrentTickerSeries :: (ParamsHasMainTicker c, MonadRobot m c s) => m (Maybe BarSeries) |
|
|
|
getCurrentTickerSeries :: (ParamsHasMainTicker c, MonadRobot m c s) => m (Maybe BarSeries) |
|
|
|
getCurrentTickerSeries = do |
|
|
|
getCurrentTickerSeries = do |
|
|
|
@ -403,48 +403,48 @@ getAllActiveAndPendingPositions = L.filter |
|
|
|
where |
|
|
|
where |
|
|
|
isPositionWaitingOpenSubmission pos = case posState pos of |
|
|
|
isPositionWaitingOpenSubmission pos = case posState pos of |
|
|
|
PositionWaitingOpenSubmission _ -> True |
|
|
|
PositionWaitingOpenSubmission _ -> True |
|
|
|
_ -> False |
|
|
|
_ -> False |
|
|
|
|
|
|
|
|
|
|
|
onNewBarEvent :: (MonadRobot m c s) => Event -> (Bar -> m ()) -> m () |
|
|
|
onNewBarEvent :: (MonadRobot m c s) => Event -> (Bar -> m ()) -> m () |
|
|
|
onNewBarEvent event f = case event of |
|
|
|
onNewBarEvent event f = case event of |
|
|
|
NewBar bar -> f bar |
|
|
|
NewBar bar -> f bar |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onNewTickEvent :: (MonadRobot m c s) => Event -> (Tick -> m ()) -> m () |
|
|
|
onNewTickEvent :: (MonadRobot m c s) => Event -> (Tick -> m ()) -> m () |
|
|
|
onNewTickEvent event f = case event of |
|
|
|
onNewTickEvent event f = case event of |
|
|
|
NewTick tick -> f tick |
|
|
|
NewTick tick -> f tick |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onNewTickEventWithDatatype :: (MonadRobot m c s) => Event -> DataType -> (Tick -> m ()) -> m () |
|
|
|
onNewTickEventWithDatatype :: (MonadRobot m c s) => Event -> DataType -> (Tick -> m ()) -> m () |
|
|
|
onNewTickEventWithDatatype event dtype f = case event of |
|
|
|
onNewTickEventWithDatatype event dtype f = case event of |
|
|
|
NewTick tick -> when (datatype tick == dtype) $ f tick |
|
|
|
NewTick tick -> when (datatype tick == dtype) $ f tick |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onTimerFiredEvent :: (MonadRobot m c s) => Event -> (UTCTime -> m ()) -> m () |
|
|
|
onTimerFiredEvent :: (MonadRobot m c s) => Event -> (UTCTime -> m ()) -> m () |
|
|
|
onTimerFiredEvent event f = case event of |
|
|
|
onTimerFiredEvent event f = case event of |
|
|
|
TimerFired timer -> f timer |
|
|
|
TimerFired timer -> f timer |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onOrderSubmittedEvent :: (MonadRobot m c s) => Event -> (Order -> m ()) -> m () |
|
|
|
onOrderSubmittedEvent :: (MonadRobot m c s) => Event -> (Order -> m ()) -> m () |
|
|
|
onOrderSubmittedEvent event f = case event of |
|
|
|
onOrderSubmittedEvent event f = case event of |
|
|
|
OrderSubmitted order -> f order |
|
|
|
OrderSubmitted order -> f order |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onOrderUpdateEvent :: (MonadRobot m c s) => Event -> (OrderId -> OrderState -> m ()) -> m () |
|
|
|
onOrderUpdateEvent :: (MonadRobot m c s) => Event -> (OrderId -> OrderState -> m ()) -> m () |
|
|
|
onOrderUpdateEvent event f = case event of |
|
|
|
onOrderUpdateEvent event f = case event of |
|
|
|
OrderUpdate oid newstate -> f oid newstate |
|
|
|
OrderUpdate oid newstate -> f oid newstate |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onTradeEvent :: (MonadRobot m c s) => Event -> (Trade -> m ()) -> m () |
|
|
|
onTradeEvent :: (MonadRobot m c s) => Event -> (Trade -> m ()) -> m () |
|
|
|
onTradeEvent event f = case event of |
|
|
|
onTradeEvent event f = case event of |
|
|
|
NewTrade trade -> f trade |
|
|
|
NewTrade trade -> f trade |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
onActionCompletedEvent :: (MonadRobot m c s) => Event -> (Int -> Value -> m ()) -> m () |
|
|
|
onActionCompletedEvent :: (MonadRobot m c s) => Event -> (Int -> Value -> m ()) -> m () |
|
|
|
onActionCompletedEvent event f = case event of |
|
|
|
onActionCompletedEvent event f = case event of |
|
|
|
ActionCompleted tag v -> f tag v |
|
|
|
ActionCompleted tag v -> f tag v |
|
|
|
_ -> doNothing |
|
|
|
_ -> doNothing |
|
|
|
|
|
|
|
|
|
|
|
enterAtMarket :: (StateHasPositions s, ParamsHasMainTicker c, MonadRobot m c s) => T.Text -> Operation -> m Position |
|
|
|
enterAtMarket :: (StateHasPositions s, ParamsHasMainTicker c, MonadRobot m c s) => T.Text -> Operation -> m Position |
|
|
|
enterAtMarket signalName operation = do |
|
|
|
enterAtMarket signalName operation = do |
|
|
|
@ -567,7 +567,7 @@ exitAtLimit timeToCancel price position signalName = do |
|
|
|
inst <- seInstanceId <$> getEnvironment |
|
|
|
inst <- seInstanceId <$> getEnvironment |
|
|
|
case posCurrentOrder position of |
|
|
|
case posCurrentOrder position of |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
Just order -> cancelOrder (orderId order) |
|
|
|
Nothing -> doNothing |
|
|
|
Nothing -> doNothing |
|
|
|
submitOrder (closeOrder inst) |
|
|
|
submitOrder (closeOrder inst) |
|
|
|
appendToLog $ [st|exitAtLimit: %?, deadline: %?|] (posTicker position) (timeToCancel `addUTCTime` lastTs) |
|
|
|
appendToLog $ [st|exitAtLimit: %?, deadline: %?|] (posTicker position) (timeToCancel `addUTCTime` lastTs) |
|
|
|
modifyPosition (\pos -> |
|
|
|
modifyPosition (\pos -> |
|
|
|
|