/// <summary>
        /// Get the Slippage approximation for this order:
        /// </summary>
        public virtual decimal GetSlippageApproximation(Security security, Order order)
        {
            //Return 0 by default
            decimal slippage = 0;

            //For FOREX, the slippage is the Bid/Ask Spread for Tick, and an approximation for the
            switch (security.Resolution)
            {
            case Resolution.Minute:
            case Resolution.Second:
                //Get the last data packet:
                TradeBar lastBar = (TradeBar)security.GetLastData();
                //Assume slippage is 1/10,000th of the price
                slippage = lastBar.Value * 0.0001m;
                break;

            case Resolution.Tick:
                Tick lastTick = (Tick)security.GetLastData();
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    //We're buying, assume slip to Asking Price.
                    slippage = Math.Abs(order.Price - lastTick.AskPrice);
                    break;

                case OrderDirection.Sell:
                    //We're selling, assume slip to the bid price.
                    slippage = Math.Abs(order.Price - lastTick.BidPrice);
                    break;
                }
                break;
            }
            return(slippage);
        }
示例#2
0
        /// <summary>
        /// Get the slippage approximation for this order
        /// </summary>
        /// <returns>Decimal value of the slippage approximation</returns>
        /// <seealso cref="Order"/>
        public override decimal GetSlippageApproximation(Security security, Order order)
        {
            //Return 0 by default
            decimal slippage = 0;
            //For FOREX, the slippage is the Bid/Ask Spread for Tick, and an approximation for TradeBars
            switch (security.Resolution)
            {
                case Resolution.Minute:
                case Resolution.Second:
                    //Get the last data packet:
                    //Assume slippage is 1/10,000th of the price
                    slippage = security.GetLastData().Value * 0.0001m;
                    break;

                case Resolution.Tick:
                    var lastTick = (Tick)security.GetLastData();
                    switch (order.Direction)
                    {
                        case OrderDirection.Buy:
                            //We're buying, assume slip to Asking Price.
                            slippage = Math.Abs(order.Price - lastTick.AskPrice);
                            break;

                        case OrderDirection.Sell:
                            //We're selling, assume slip to the bid price.
                            slippage = Math.Abs(order.Price - lastTick.BidPrice);
                            break;
                    }
                    break;
            }
            return slippage;
        }
        /// <summary>
        /// The percentage of the holding's absolute cost that must be held in free cash in order to avoid a margin call
        /// </summary>
        protected virtual decimal GetMaintenanceMarginRequirement(Security security, decimal holdingValue)
        {
            if (security == null ||
                security.GetLastData() == null ||
                holdingValue == 0m)
            {
                return(0m);
            }

            var symbol    = security.Symbol;
            var date      = security.GetLastData().Time.Date;
            var marginReq = GetCurrentMarginRequirements(symbol, date);

            return(marginReq.MaintenanceOvernight / holdingValue);
        }
示例#4
0
        /// <summary>
        /// Slippage Model. Return a decimal cash slippage approximation on the order.
        /// </summary>
        public override decimal GetSlippageApproximation(Security asset, Order order)
        {
            var lastData = asset.GetLastData();
            if (lastData == null) return 0;

            return lastData.Value*_slippagePercent;
        }
        /// <summary>
        /// Check if the price MarketDataed to our limit price yet:
        /// </summary>
        /// <param name="security">Asset we're working with</param>
        /// <param name="order">Limit order in market</param>
        public virtual OrderEvent LimitFill(Security security, Order order)
        {
            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;
            var     fill = new OrderEvent(order);

            try
            {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled)
                {
                    return(fill);
                }
                //Depending on the resolution, return different data types:
                BaseData marketData = security.GetLastData();

                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                }
                else
                {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order:
                if (order.Direction == OrderDirection.Buy)
                {
                    //Buy limit seeks lowest price
                    if (marketDataMinPrice < order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                    }
                }
                else if (order.Direction == OrderDirection.Sell)
                {
                    //Sell limit seeks highest price possible
                    if (marketDataMaxPrice > order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                    }
                }

                //Fill price
                if (order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled)
                {
                    fill.FillQuantity = order.Quantity;
                    fill.FillPrice    = order.Price;
                    fill.Status       = order.Status;
                }
            }
            catch (Exception err)
            {
                Log.Error("ForexTransactionModel.TransOrderDirection.LimitFill(): " + err.Message);
            }
            return(fill);
        }
        /// <summary>
        /// Check if the price MarketDataed to our limit price yet:
        /// </summary>
        /// <param name="security">Asset we're working with</param>
        /// <param name="order">Limit order in market</param>
        public virtual void LimitFill(Security security, ref Order order)
        {
            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;

            try {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled)
                {
                    return;
                }

                //Calculate the model slippage: e.g. 0.01c
                decimal slip = GetSlippageApproximation(security, order);

                //Depending on the resolution, return different data types:
                BaseData marketData = security.GetLastData();

                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                }
                else
                {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order:
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    //Buy limit seeks lowest price
                    if (marketDataMinPrice < order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                        order.Price  = security.Price;
                        order.Price += slip;
                    }
                    break;

                case OrderDirection.Sell:
                    //Sell limit seeks highest price possible
                    if (marketDataMaxPrice > order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                        order.Price  = security.Price;
                        order.Price -= slip;
                    }
                    break;
                }

                //Round off:
                order.Price = Math.Round(order.Price, 2);
            } catch (Exception err) {
                Log.Error("Equity.TransOrderDirection.LimitFill(): " + err.Message);
            }
        }
示例#7
0
        /// <summary>
        /// The percentage of an order's absolute cost that must be held in free cash in order to place the order
        /// </summary>
        protected virtual decimal GetInitialMarginRequirement(Security security, decimal holdingValue)
        {
            var symbol    = security.Symbol;
            var date      = security.GetLastData().Time.Date;
            var marginReq = GetCurrentMarginRequirements(symbol, date);

            return(marginReq.InitialOvernight / holdingValue);
        }
        /// <summary>
        /// Gets the margin currently alloted to the specified holding
        /// </summary>
        /// <param name="security">The security to compute maintenance margin for</param>
        /// <returns>The maintenance margin required for the </returns>
        public virtual decimal GetMaintenanceMargin(Security security)
        {
            if (security?.GetLastData() == null || security.Holdings.HoldingsCost == 0m)
            {
                return(0m);
            }

            var symbol    = security.Symbol;
            var date      = security.GetLastData().Time.Date;
            var marginReq = GetCurrentMarginRequirements(symbol, date);

            return(marginReq.MaintenanceOvernight * Math.Sign(security.Holdings.HoldingsCost));
        }
 /// <summary>
 /// Determines if the exchange is open using the current time of the asset
 /// </summary>
 private static bool IsExchangeOpen(Security asset)
 {
     if (!asset.Exchange.DateTimeIsOpen(asset.LocalTime))
     {
         // if we're not open at the current time exactly, check the bar size, this handle large sized bars (hours/days)
         var currentBar = asset.GetLastData();
         if (!asset.Exchange.IsOpenDuringBar(currentBar.Time, currentBar.EndTime, false))
         {
             return(false);
         }
     }
     return(true);
 }
示例#10
0
        /// <summary>
        /// Slippage Model. Return a decimal cash slippage approximation on the order.
        /// </summary>
        public virtual decimal GetSlippageApproximation(Security asset, Order order)
        {
            var lastData = asset.GetLastData();
            var lastTick = lastData as Tick;

            // if we have tick data use the spread
            if (lastTick != null)
            {
                return (lastTick.AskPrice - lastTick.BidPrice) / 2;
            }

            return 0m;
        }
示例#11
0
        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="minimumPrice">Minimum price in the last data bar</param>
        /// <param name="maximumPrice">Minimum price in the last data bar</param>
        public virtual void DataMinMaxPrices(Security asset, out decimal minimumPrice, out decimal maximumPrice)
        {
            var marketData = asset.GetLastData();

            if (marketData.DataType == MarketDataType.TradeBar)
            {
                minimumPrice = ((TradeBar)marketData).Low;
                maximumPrice = ((TradeBar)marketData).High;
            }
            else
            {
                minimumPrice = marketData.Value;
                maximumPrice = marketData.Value;
            }
        }
示例#12
0
        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="minimumPrice">Minimum price in the last data bar</param>
        /// <param name="maximumPrice">Minimum price in the last data bar</param>
        public virtual void DataMinMaxPrices(Security asset, out decimal minimumPrice, out decimal maximumPrice)
        {
            var marketData = asset.GetLastData();

            var tradeBar = marketData as TradeBar;
            if (tradeBar != null)
            {
                minimumPrice = tradeBar.Low;
                maximumPrice = tradeBar.High;
            }
            else
            {
                minimumPrice = marketData.Value;
                maximumPrice = marketData.Value;
            }
        }
        //LIMIT FILL MODEL:
        public virtual void LimitFill(Security security, ref Order order)
        {
            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;

            try
            {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled) return;

                //Depending on the resolution, return different data types:
                Futures contract = security.GetLastData() as Futures;

                if (contract == null)
                {
                    //Shouldnt happen.
                }

                marketDataMinPrice = contract.Low;
                marketDataMaxPrice = contract.High;

                //Valid Live/Model Order:
                if (order.Direction == OrderDirection.Buy)
                {
                    //Buy limit seeks lowest price
                    if (marketDataMinPrice < order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                    }

                }
                else if (order.Direction == OrderDirection.Sell)
                {
                    //Sell limit seeks highest price possible
                    if (marketDataMaxPrice > order.Price)
                    {
                        order.Status = OrderStatus.Filled;
                    }
                }
            }
            catch (Exception err)
            {
                algo.Error("CustomTransactionModel.TransOrderDirection.LimitFill():" + err.Message);
            }
        }
示例#14
0
        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="minimumPrice">Minimum price in the last data bar</param>
        /// <param name="maximumPrice">Minimum price in the last data bar</param>
        public virtual void DataMinMaxPrices(Security asset, out decimal minimumPrice, out decimal maximumPrice)
        {
            var marketData = asset.GetLastData();

            var tradeBar = marketData as TradeBar;

            if (tradeBar != null)
            {
                minimumPrice = tradeBar.Low;
                maximumPrice = tradeBar.High;
            }
            else
            {
                minimumPrice = marketData.Value;
                maximumPrice = marketData.Value;
            }
        }
示例#15
0
        /// <summary>
        /// Returns true if the brokerage would be able to execute this order at this time assuming
        /// market prices are sufficient for the fill to take place. This is used to emulate the 
        /// brokerage fills in backtesting and paper trading. For example some brokerages may not perform
        /// executions during extended market hours. This is not intended to be checking whether or not
        /// the exchange is open, that is handled in the Security.Exchange property.
        /// </summary>
        /// <param name="security">The security being ordered</param>
        /// <param name="order">The order to test for execution</param>
        /// <returns>True if the brokerage would be able to perform the execution, false otherwise</returns>
        public override bool CanExecuteOrder(Security security, Order order)
        {
            EquityExchange.SetLocalDateTimeFrontier(security.Exchange.LocalTime);

            var cache = security.GetLastData();
            if (cache == null)
            {
                return false;
            }

            // tradier doesn't support after hours trading
            if (!EquityExchange.IsOpenDuringBar(cache.Time, cache.EndTime, false))
            {
                return false;
            }
            return true;
        }
示例#16
0
        /// <summary>
        /// Slippage Model. Return a decimal cash slippage approximation on the order.
        /// </summary>
        public virtual decimal GetSlippageApproximation(Security asset, Order order)
        {
            var lastData = asset.GetLastData();
            var lastTick = lastData as Tick;

            // if we have tick data use the spread
            if (lastTick != null)
            {
                if (order.Direction == OrderDirection.Buy)
                {
                    //We're buying, assume slip to Asking Price.
                    return Math.Abs(order.Price - lastTick.AskPrice);
                }
                if (order.Direction == OrderDirection.Sell)
                {
                    //We're selling, assume slip to the bid price.
                    return Math.Abs(order.Price - lastTick.BidPrice);
                }
            }

            return 0m;
        }
        /// <summary>
        /// Check if the price MarketDataed to our limit price yet:
        /// </summary>
        /// <param name="security">Asset we're working with</param>
        /// <param name="order">Limit order in market</param>
        public virtual OrderEvent LimitFill(Security security, Order order)
        {
            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;
            var fill = new OrderEvent(order);

            try {
                //If its cancelled don't need anymore checks:
                if (fill.Status == OrderStatus.Canceled) return fill;

                //Depending on the resolution, return different data types:
                BaseData marketData = security.GetLastData();

                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                } else {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order:
                switch (order.Direction)
                {
                    case OrderDirection.Buy:
                        //Buy limit seeks lowest price
                        if (marketDataMinPrice < order.Price)
                        {
                            //Set order fill:
                            order.Status = OrderStatus.Filled;
                            order.Price = security.Price;
                        }
                        break;
                    case OrderDirection.Sell:
                        //Sell limit seeks highest price possible
                        if (marketDataMaxPrice > order.Price)
                        {
                            order.Status = OrderStatus.Filled;
                            order.Price = security.Price;
                        }
                        break;
                }

                if (order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled)
                {
                    fill.FillQuantity = order.Quantity;
                    fill.FillPrice = security.Price;
                    fill.Status = order.Status;
                }
            }
            catch (Exception err)
            {
                Log.Error("SecurityTransactionModel.TransOrderDirection.LimitFill(): " + err.Message);
            }
            return fill;
        }
示例#18
0
        /// <summary>
        /// Default market fill model for the base security class. Fills at the last traded price.
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill informaton detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="LimitFill(Security, LimitOrder)"/>
        public virtual OrderEvent MarketFill(Security asset, MarketOrder order)
        {
            //Default order event to return.
            var fill = new OrderEvent(order);

            if (order.Status == OrderStatus.Canceled) return fill;

            // make sure the exchange is open before filling
            var currentBar = asset.GetLastData();
            if (!asset.Exchange.IsOpenDuringBar(currentBar.Time, currentBar.EndTime, false)) return fill;

            try
            {
                //Order [fill]price for a market order model is the current security price.
                order.Price = asset.Price;
                order.Status = OrderStatus.Filled;

                //Calculate the model slippage: e.g. 0.01c
                var slip = GetSlippageApproximation(asset, order);

                //Apply slippage
                switch (order.Direction)
                {
                    case OrderDirection.Buy:
                        order.Price += slip;
                        break;
                    case OrderDirection.Sell:
                        order.Price -= slip;
                        break;
                }

                //For backtesting, we assuming the order is 100% filled on first attempt.
                fill.FillPrice = order.Price;
                fill.FillQuantity = order.Quantity;
                fill.Status = order.Status;
            }
            catch (Exception err)
            {
                Log.Error("SecurityTransactionModel.MarketFill(): " + err.Message);
            }

            return fill;
        }
示例#19
0
        /// <summary>
        /// Default limit order fill model in the base security class.
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill informaton detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="MarketFill(Security, MarketOrder)"/>
        public OrderEvent LimitFill(Security asset, LimitOrder order)
        {
            //Initialise;
            var fill = new OrderEvent(order);

            try
            {
                //If its cancelled don't need anymore checks:
                if (fill.Status == OrderStatus.Canceled)
                {
                    return(fill);
                }

                //Depending on the resolution, return different data types:
                var marketData = asset.GetLastData();

                decimal marketDataMinPrice;
                decimal marketDataMaxPrice;
                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                }
                else
                {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order:
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    //Buy limit seeks lowest price
                    if (marketDataMinPrice < order.LimitPrice)
                    {
                        //Set order fill:
                        order.Status = OrderStatus.Filled;
                        order.Price  = asset.Price;
                    }
                    break;

                case OrderDirection.Sell:
                    //Sell limit seeks highest price possible
                    if (marketDataMaxPrice > order.LimitPrice)
                    {
                        order.Status = OrderStatus.Filled;
                        order.Price  = asset.Price;
                    }
                    break;
                }

                if (order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled)
                {
                    fill.FillQuantity = order.Quantity;
                    fill.FillPrice    = asset.Price;
                    fill.Status       = order.Status;
                }
            }
            catch (Exception err)
            {
                Log.Error("SecurityTransactionModel.LimitFill(): " + err.Message);
            }
            return(fill);
        }
示例#20
0
        /// <summary>
        /// Default stop fill model implementation in base class security. (Stop Market Order Type)
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill informaton detailing the average price and quantity filled.</returns>
        /// <seealso cref="MarketFill(Security, MarketOrder)"/>
        /// <seealso cref="LimitFill(Security, LimitOrder)"/>
        public virtual OrderEvent StopMarketFill(Security asset, StopMarketOrder order)
        {
            //Default order event to return.
            var fill = new OrderEvent(order);

            // make sure the exchange is open before filling
            var currentBar = asset.GetLastData();
            if (!asset.Exchange.IsOpenDuringBar(currentBar.Time, currentBar.EndTime, false)) return fill;

            try
            {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled) return fill;

                //Get the range of prices in the last bar:
                decimal minimumPrice;
                decimal maximumPrice;
                DataMinMaxPrices(asset, out minimumPrice, out maximumPrice);

                //Calculate the model slippage: e.g. 0.01c
                var slip = GetSlippageApproximation(asset, order);

                //Check if the Stop Order was filled: opposite to a limit order
                switch (order.Direction)
                {
                    case OrderDirection.Sell:
                        //-> 1.1 Sell Stop: If Price below setpoint, Sell:
                        if (minimumPrice < order.StopPrice)
                        {
                            order.Status = OrderStatus.Filled;
                            // Assuming worse case scenario fill - fill at lowest of the stop & asset price.
                            order.Price = Math.Min(order.StopPrice, asset.Price - slip);
                        }
                        break;

                    case OrderDirection.Buy:
                        //-> 1.2 Buy Stop: If Price Above Setpoint, Buy:
                        if (maximumPrice > order.StopPrice)
                        {
                            order.Status = OrderStatus.Filled;
                            // Assuming worse case scenario fill - fill at highest of the stop & asset price.
                            order.Price = Math.Max(order.StopPrice, asset.Price + slip);
                        }
                        break;
                }

                if (order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled)
                {
                    fill.FillQuantity = order.Quantity;
                    fill.FillPrice = order.Price;        //we picked the correct fill price above, just respect it here
                    fill.Status = order.Status;
                }
            }
            catch (Exception err)
            {
                Log.Error("SecurityTransactionModel.StopMarketFill(): " + err.Message);
            }

            return fill;
        }
示例#21
0
        /// <summary>
        /// Market on Open Fill Model. Return an order event with the fill details
        /// </summary>
        /// <param name="asset">Asset we're trading with this order</param>
        /// <param name="order">Order to be filled</param>
        /// <returns>Order fill informaton detailing the average price and quantity filled.</returns>
        public OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder order)
        {
            var fill = new OrderEvent(order);

            if (order.Status == OrderStatus.Canceled)
            {
                return(fill);
            }

            try
            {
                // MOO should never fill on the same bar or on stale data
                // Imagine the case where we have a thinly traded equity, ASUR, and another liquid
                // equity, say SPY, SPY gets data every minute but ASUR, if not on fill forward, maybe
                // have large gaps, in which case the currentBar.EndTime will be in the past
                // ASUR  | | |      [order]        | | | | | | |
                //  SPY  | | | | | | | | | | | | | | | | | | | |
                var currentBar     = asset.GetLastData();
                var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone);
                if (currentBar == null || localOrderTime >= currentBar.EndTime)
                {
                    return(fill);
                }

                // if the MOO was submitted during market the previous day, wait for a day to turn over
                if (asset.Exchange.DateTimeIsOpen(localOrderTime) && localOrderTime.Date == asset.LocalTime.Date)
                {
                    return(fill);
                }

                // wait until market open
                // make sure the exchange is open before filling
                if (!IsExchangeOpen(asset))
                {
                    return(fill);
                }

                order.Price  = asset.Open;
                order.Status = OrderStatus.Filled;

                //Calculate the model slippage: e.g. 0.01c
                var slip = GetSlippageApproximation(asset, order);

                //Apply slippage
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    order.Price += slip;
                    break;

                case OrderDirection.Sell:
                    order.Price -= slip;
                    break;
                }

                //For backtesting, we assuming the order is 100% filled on first attempt.
                fill.FillPrice    = order.Price;
                fill.FillQuantity = order.Quantity;
                fill.Status       = order.Status;
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            return(fill);
        }
示例#22
0
        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="minimumPrice">Minimum price in the last data bar</param>
        /// <param name="maximumPrice">Minimum price in the last data bar</param>
        /// <param name="direction">The order direction, decides whether to pick bid or ask</param>
        public virtual void DataMinMaxPrices(Security asset, out decimal minimumPrice, out decimal maximumPrice, OrderDirection direction)
        {
            var tick = asset.Cache.GetData<Tick>();
            if (tick != null)
            {
                var price = tick.Value;
                if (direction == OrderDirection.Sell && tick.BidPrice != 0)
                {
                    price = tick.BidPrice;
                }
                else if (direction == OrderDirection.Buy && tick.AskPrice != 0)
                {
                    price = tick.AskPrice;
                }
                minimumPrice = maximumPrice = price;
                return;
            }

            var quoteBar = asset.Cache.GetData<QuoteBar>();
            if (quoteBar != null)
            {
                var bar = direction == OrderDirection.Sell ? quoteBar.Ask : quoteBar.Bid;
                minimumPrice = quoteBar.Low;
                maximumPrice = quoteBar.High;
                if (bar != null)
                {
                    if (bar.High != 0) maximumPrice = bar.High;
                    if (bar.Low != 0) minimumPrice = bar.Low;
                }
                return;
            }

            var tradeBar = asset.Cache.GetData<TradeBar>();
            if (tradeBar != null)
            {
                minimumPrice = tradeBar.Low;
                maximumPrice = tradeBar.High;
                return;
            }

            var lastData = asset.GetLastData();
            var lastBar = lastData as IBar;
            if (lastBar != null)
            {
                minimumPrice = lastBar.Low;
                maximumPrice = lastBar.High;
                return;
            }

            minimumPrice = maximumPrice = asset.Price;
        }
示例#23
0
 /// <summary>
 /// Determines if the exchange is open using the current time of the asset
 /// </summary>
 private static bool IsExchangeOpen(Security asset)
 {
     if (!asset.Exchange.DateTimeIsOpen(asset.LocalTime))
     {
         // if we're not open at the current time exactly, check the bar size, this handle large sized bars (hours/days)
         var currentBar = asset.GetLastData();
         if (asset.LocalTime.Date != currentBar.EndTime.Date || !asset.Exchange.IsOpenDuringBar(currentBar.Time, currentBar.EndTime, false))
         {
             return false;
         }
     }
     return true;
 }
示例#24
0
        /// <summary>
        /// Market on Open Fill Model. Return an order event with the fill details
        /// </summary>
        /// <param name="asset">Asset we're trading with this order</param>
        /// <param name="order">Order to be filled</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        public OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder order)
        {
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var fill = new OrderEvent(order, utcTime, 0);

            if (order.Status == OrderStatus.Canceled) return fill;

            // MOO should never fill on the same bar or on stale data
            // Imagine the case where we have a thinly traded equity, ASUR, and another liquid
            // equity, say SPY, SPY gets data every minute but ASUR, if not on fill forward, maybe
            // have large gaps, in which case the currentBar.EndTime will be in the past
            // ASUR  | | |      [order]        | | | | | | |
            //  SPY  | | | | | | | | | | | | | | | | | | | |
            var currentBar = asset.GetLastData();
            var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone);
            if (currentBar == null || localOrderTime >= currentBar.EndTime) return fill;

            // if the MOO was submitted during market the previous day, wait for a day to turn over
            if (asset.Exchange.DateTimeIsOpen(localOrderTime) && localOrderTime.Date == asset.LocalTime.Date)
            {
                return fill;
            }

            // wait until market open
            // make sure the exchange is open before filling
            if (!IsExchangeOpen(asset)) return fill;

            fill.FillPrice = asset.Open;
            fill.Status = OrderStatus.Filled;

            //Calculate the model slippage: e.g. 0.01c
            var slip = asset.SlippageModel.GetSlippageApproximation(asset, order);

            //Apply slippage
            switch (order.Direction)
            {
                case OrderDirection.Buy:
                    fill.FillPrice += slip;
                    break;
                case OrderDirection.Sell:
                    fill.FillPrice -= slip;
                    break;
            }

            // assume the order completely filled
            if (fill.Status == OrderStatus.Filled)
            {
                fill.FillQuantity = order.Quantity;
                fill.OrderFee = asset.FeeModel.GetOrderFee(asset, order);
            }

            return fill;
        }
示例#25
0
        /// <summary>
        /// Market on Open Fill Model. Return an order event with the fill details
        /// </summary>
        /// <param name="asset">Asset we're trading with this order</param>
        /// <param name="order">Order to be filled</param>
        /// <returns>Order fill informaton detailing the average price and quantity filled.</returns>
        public OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder order)
        {
            var fill = new OrderEvent(order);

            if (order.Status == OrderStatus.Canceled) return fill;

            try
            {
                // MOO should never fill on the same bar or on stale data
                // Imagine the case where we have a thinly traded equity, ASUR, and another liquid
                // equity, say SPY, SPY gets data every minute but ASUR, if not on fill forward, maybe
                // have large gaps, in which case the currentBar.EndTime will be in the past
                // ASUR  | | |      [order]        | | | | | | |
                //  SPY  | | | | | | | | | | | | | | | | | | | |
                var currentBar = asset.GetLastData();
                var localOrderTime = order.Time.ConvertTo(TimeZones.Utc, asset.Exchange.TimeZone);
                if (localOrderTime >= currentBar.EndTime) return fill;

                // if the MOO was submitted during market the previous day, wait for a day to turn over
                if (asset.Exchange.DateTimeIsOpen(localOrderTime) && localOrderTime.Date == asset.LocalTime.Date)
                {
                    return fill;
                }

                // wait until market open
                // make sure the exchange is open before filling
                if (!IsExchangeOpen(asset)) return fill;

                order.Price = asset.Open;
                order.Status = OrderStatus.Filled;

                //Calculate the model slippage: e.g. 0.01c
                var slip = GetSlippageApproximation(asset, order);

                //Apply slippage
                switch (order.Direction)
                {
                    case OrderDirection.Buy:
                        order.Price += slip;
                        break;
                    case OrderDirection.Sell:
                        order.Price -= slip;
                        break;
                }

                //For backtesting, we assuming the order is 100% filled on first attempt.
                fill.FillPrice = order.Price;
                fill.FillQuantity = order.Quantity;
                fill.Status = order.Status;
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            return fill;
        }
示例#26
0
        /// <summary>
        /// Check if the price MarketDataed to our limit price yet:
        /// </summary>
        /// <param name="security">Asset we're working with</param>
        /// <param name="order">Limit order in market</param>
        public virtual void LimitFill(Security security, ref Order order) {

            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;

            try {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled) return;

                //Calculate the model slippage: e.g. 0.01c
                decimal slip = GetSlippageApproximation(security, order);

                //Depending on the resolution, return different data types:
                BaseData marketData = security.GetLastData();

                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                } else {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order: 
                switch (order.Direction)
                {
                    case OrderDirection.Buy:
                        //Buy limit seeks lowest price
                        if (marketDataMinPrice < order.Price) {
                            order.Status = OrderStatus.Filled;
                            order.Price = security.Price;
                            order.Price += slip;
                        }
                        break;
                    case OrderDirection.Sell:
                        //Sell limit seeks highest price possible
                        if (marketDataMaxPrice > order.Price) {
                            order.Status = OrderStatus.Filled;
                            order.Price = security.Price;
                            order.Price -= slip;
                        }
                        break;
                }

                //Round off:
                order.Price = Math.Round(order.Price, 2);

            } catch (Exception err) {
                Log.Error("Equity.TransOrderDirection.LimitFill(): " + err.Message);
            }
        }
示例#27
0
        /// <summary>
        /// Get the minimum and maximum price for this security in the last bar:
        /// </summary>
        /// <param name="asset">Security asset we're checking</param>
        /// <param name="direction">The order direction, decides whether to pick bid or ask</param>
        private Prices GetPrices(Security asset, OrderDirection direction)
        {
            var low = asset.Low;
            var high = asset.High;
            var open = asset.Open;
            var close = asset.Close;
            var current = asset.Price;

            if (direction == OrderDirection.Hold)
            {
                return new Prices(current, open, high, low, close);
            }

            var tick = asset.Cache.GetData<Tick>();
            if (tick != null)
            {
                return new Prices(current, open, high, low, close);
            }

            var quoteBar = asset.Cache.GetData<QuoteBar>();
            if (quoteBar != null)
            {
                var bar = direction == OrderDirection.Sell ? quoteBar.Bid : quoteBar.Ask;
                if (bar != null)
                {
                    return new Prices(bar);
                }
            }

            var tradeBar = asset.Cache.GetData<TradeBar>();
            if (tradeBar != null)
            {
                return new Prices(tradeBar);
            }

            var lastData = asset.GetLastData();
            var lastBar = lastData as IBar;
            if (lastBar != null)
            {
                return new Prices(lastBar);
            }

            return new Prices(current, open, high, low, close);
        }
示例#28
0
        /// <summary>
        /// Check if the price MarketDataed to our limit price yet:
        /// </summary>
        /// <param name="security">Asset we're working with</param>
        /// <param name="order">Limit order in market</param>
        public virtual void LimitFill(Security security, ref Order order) {

            //Initialise;
            decimal marketDataMinPrice = 0;
            decimal marketDataMaxPrice = 0;

            try {
                //If its cancelled don't need anymore checks:
                if (order.Status == OrderStatus.Canceled) return;

                //Depending on the resolution, return different data types:
                BaseData marketData = security.GetLastData();

                if (marketData.DataType == MarketDataType.TradeBar)
                {
                    marketDataMinPrice = ((TradeBar)marketData).Low;
                    marketDataMaxPrice = ((TradeBar)marketData).High;
                } else {
                    marketDataMinPrice = marketData.Value;
                    marketDataMaxPrice = marketData.Value;
                }

                //-> Valid Live/Model Order: 
                if (order.Direction == OrderDirection.Buy) {
                    //Buy limit seeks lowest price
                    if (marketDataMinPrice < order.Price) {
                        order.Status = OrderStatus.Filled;
                    }

                } else if (order.Direction == OrderDirection.Sell) {
                    //Sell limit seeks highest price possible
                    if (marketDataMaxPrice > order.Price) {
                        order.Status = OrderStatus.Filled;
                    }
                }
            } catch (Exception err) {
                Log.Error("ForexTransactionModel.TransOrderDirection.LimitFill(): " + err.Message);
            }
        }