예제 #1
0
        public void PerformsStopLimitFillBuy()
        {
            var model    = new EquityTransactionModel();
            var order    = new StopLimitOrder(Symbol, 100, 101.5m, 101.75m, Noon, type: SecurityType.Equity);
            var config   = CreateTradeBarConfig(Symbol);
            var security = new Security(SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(), config, 1);

            security.SetLocalTimeKeeper(TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork));
            security.SetMarketPrice(new IndicatorDataPoint(Symbol, Noon, 100m));

            var fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbol, Noon, 102m));

            fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbol, Noon, 101.66m));

            fill = model.StopLimitFill(security, order);

            // this fills worst case scenario, so it's at the limit price
            Assert.AreEqual(order.Quantity, fill.FillQuantity);
            Assert.AreEqual(order.LimitPrice, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
        }
예제 #2
0
        public void ShouldNotMatchSellStopLimitOrderLowerThanMarket()
        {
            var executions = new List <INewExecution>();

            var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC");
            var matchAlgo           = new LimitOrderMatchingAlgorithm(new DateService());

            matchAlgo.AddExecutionsHandler(executions.Add);

            var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock.Object, orderBookBestBidAsk);

            var sellOrder1 = new LimitOrder("ABC", 10, 1161.8d, WayEnum.Sell, 9);

            book.AddLimitOrder(sellOrder1);

            var buyOrder1 = new LimitOrder("ABC", 10, 1161.7d, WayEnum.Buy, 9);

            book.AddLimitOrder(buyOrder1);

            var trigger = new BestPriceTrigger("ABC", 1160, WayEnum.Sell);

            trigger.SetTriggerAction(() =>
            {
                Console.WriteLine("Boom!");
                int i = 0;
            });

            var sellStopLimit = new StopLimitOrder("ABC", 1, 1160, 1160, WayEnum.Sell, 5, trigger);

            book.AddStopLimitOrder(sellStopLimit);

            Assert.AreEqual(0, executions.Count);
        }
예제 #3
0
        public StopLimitOrder StopLimitOrder(Instrument instrument, Side side, double qty, double limitPrice, double stopPrice)
        {
            StopLimitOrder stopLimitOrder = new StopLimitOrder(instrument, side, qty, limitPrice, stopPrice);

            base.Strategy.RegisterOrder(stopLimitOrder);
            return(stopLimitOrder);
        }
예제 #4
0
        public void PerformsStopLimitFillSell()
        {
            var model    = new EquityTransactionModel();
            var order    = new StopLimitOrder(Symbol, -100, 101.75m, 101.50m, DateTime.Now, type: SecurityType.Equity);
            var config   = new SubscriptionDataConfig(typeof(TradeBar), SecurityType.Equity, Symbol, Resolution.Minute, true, true, true, true, false, 0);
            var security = new Security(config, 1);

            security.SetMarketPrice(DateTime.Now, new IndicatorDataPoint(Symbol, DateTime.Now, 102m));

            var fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);
            Assert.AreEqual(OrderStatus.None, order.Status);

            security.SetMarketPrice(DateTime.Now, new IndicatorDataPoint(Symbol, DateTime.Now, 101m));

            fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);
            Assert.AreEqual(OrderStatus.None, order.Status);

            security.SetMarketPrice(DateTime.Now, new IndicatorDataPoint(Symbol, DateTime.Now, 101.66m));

            fill = model.StopLimitFill(security, order);

            // this fills worst case scenario, so it's at the limit price
            Assert.AreEqual(order.Quantity, fill.FillQuantity);
            Assert.AreEqual(order.LimitPrice, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
            Assert.AreEqual(OrderStatus.Filled, order.Status);
        }
예제 #5
0
 /// <summary>
 /// Wrapper for <see cref = "IFillModel.StopLimitFill(Security, StopLimitOrder)" /> in Python
 /// </summary>
 /// <param name="asset">Asset we're trading this order</param>
 /// <param name="order">Stop Limit Order to Check, return filled if true</param>
 /// <returns>Order fill information detailing the average price and quantity filled.</returns>
 public OrderEvent StopLimitFill(Security asset, StopLimitOrder order)
 {
     using (Py.GIL())
     {
         return(_model.StopLimitFill(asset, order));
     }
 }
예제 #6
0
        public void ValidateStopLimitOrders()
        {
            var oanda  = (OandaBrokerage)Brokerage;
            var symbol = Symbol;
            var quotes = oanda.GetRates(new List <string> {
                new OandaSymbolMapper().GetBrokerageSymbol(symbol)
            });

            // Buy StopLimit order below market (Oanda accepts this order but cancels it immediately)
            var stopPrice  = Convert.ToDecimal(quotes[0].bid - 0.5);
            var limitPrice = stopPrice + 0.0005m;
            var order      = new StopLimitOrder(symbol, 1, stopPrice, limitPrice, DateTime.Now);

            Assert.IsTrue(oanda.PlaceOrder(order));

            // Buy StopLimit order above market
            stopPrice  = Convert.ToDecimal(quotes[0].ask + 0.5);
            limitPrice = stopPrice + 0.0005m;
            order      = new StopLimitOrder(symbol, 1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));

            // Sell StopLimit order below market
            stopPrice  = Convert.ToDecimal(quotes[0].bid - 0.5);
            limitPrice = stopPrice - 0.0005m;
            order      = new StopLimitOrder(symbol, -1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));

            // Sell StopLimit order above market (Oanda accepts this order but cancels it immediately)
            stopPrice  = Convert.ToDecimal(quotes[0].ask + 0.5);
            limitPrice = stopPrice - 0.0005m;
            order      = new StopLimitOrder(symbol, -1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));
        }
예제 #7
0
        public async Task <OrderResponse> PlaceStopLimitOrderAsync(
            OrderSide side,
            ProductType productId,
            decimal size,
            decimal stopPrice,
            decimal limitPrice,
            bool postOnly  = true,
            Guid?clientOid = null)
        {
            var order = new StopLimitOrder
            {
                Side      = side,
                ProductId = productId,
                OrderType = OrderType.Limit,
                Price     = limitPrice,
                Size      = size,
                StopType  = side == OrderSide.Buy
                    ? StopType.Entry
                    : StopType.Loss,
                StopPrice = stopPrice,
                ClientOid = clientOid,
                PostOnly  = postOnly,
            };

            return(await PlaceOrderAsync(order));
        }
예제 #8
0
 /// <summary>
 /// Stop Limit Fill Model. Return an order event with the fill details.
 /// </summary>
 /// <param name="asset">Asset we're trading this order</param>
 /// <param name="order">Stop Limit Order to Check, return filled if true</param>
 /// <returns>Order fill information detailing the average price and quantity filled.</returns>
 public override OrderEvent StopLimitFill(Security asset, StopLimitOrder order)
 {
     using (Py.GIL())
     {
         return((_model.StopLimitFill(asset, order) as PyObject).GetAndDispose <OrderEvent>());
     }
 }
예제 #9
0
        private void MakeOrder(Side side, OrdType ordType)
        {
            Instrument instrument = (this.dgvQuotes.SelectedRows[0] as QuoteViewRow).Instrument;
            byte       route      = (byte)0;

            if (this.executionProvider is IMultiRouteExecutionProvider)
            {
                route = this.SelectedRoute;
            }
            OrderMiniBlotterForm orderMiniBlotterForm = new OrderMiniBlotterForm();

            orderMiniBlotterForm.Init(instrument, ordType, side, route);
            if (orderMiniBlotterForm.ShowDialog((IWin32Window)this) == DialogResult.OK)
            {
                SingleOrder singleOrder = null;
                switch (ordType)
                {
                case OrdType.Market:
                    singleOrder = new MarketOrder(this.executionProvider, this.portfolio, instrument, side, (double)orderMiniBlotterForm.Qty);
                    break;

                case OrdType.Limit:
                    singleOrder = new LimitOrder(this.executionProvider, this.portfolio, instrument, side, (double)orderMiniBlotterForm.Qty, orderMiniBlotterForm.LimitPrice);
                    break;

                case OrdType.Stop:
                    singleOrder = new StopOrder(this.executionProvider, this.portfolio, instrument, side, (double)orderMiniBlotterForm.Qty, orderMiniBlotterForm.StopPrice);
                    break;

                case OrdType.StopLimit:
                    singleOrder = new StopLimitOrder(this.executionProvider, this.portfolio, instrument, side, (double)orderMiniBlotterForm.Qty, orderMiniBlotterForm.LimitPrice, orderMiniBlotterForm.StopPrice);
                    break;
                }
                ((NewOrderSingle)singleOrder).TimeInForce = orderMiniBlotterForm.TimeInForce;
                ((FIXNewOrderSingle)singleOrder).Route    = (int)orderMiniBlotterForm.Route;
                singleOrder.Persistent = this.portfolio.Persistent;
                if (!((IProvider)this.executionProvider).IsConnected)
                {
                    bool flag = false;
                    if (MessageBox.Show(this, "Cannot send the order, because provider is not connected." + Environment.NewLine + "Do you want to connect to " + ((IProvider)this.executionProvider).Name + "?", "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        flag = true;
                        ((IProvider)this.executionProvider).Connect(15000);
                    }
                    if (flag && !((IProvider)this.marketDataProvider).IsConnected)
                    {
                        MessageBox.Show(this, "Unable to connect to " + this.marketDataProvider.Name, "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    }
                }
                if (((IProvider)this.executionProvider).IsConnected)
                {
                    singleOrder.Send();
                }
                if ((int)orderMiniBlotterForm.Route > 0)
                {
                    this.SelectedRoute = orderMiniBlotterForm.Route;
                }
            }
            orderMiniBlotterForm.Dispose();
        }
예제 #10
0
        public void PerformsStopLimitFillSell()
        {
            var model    = new ForexTransactionModel();
            var security = CreateSecurity();
            var order    = new StopLimitOrder(Symbols.USDJPY, -100, 101.75m, 101.50m, DateTime.Now, type: SecurityType.Forex);

            security.SetLocalTimeKeeper(TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork));
            security.SetMarketPrice(new IndicatorDataPoint(Symbols.USDJPY, DateTime.Now, 102m));

            var fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.USDJPY, DateTime.Now, 101m));

            fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.USDJPY, DateTime.Now, 101.66m));

            fill = model.StopLimitFill(security, order);

            // this fills worst case scenario, so it's at the limit price
            Assert.AreEqual(order.Quantity, fill.FillQuantity);
            Assert.AreEqual(order.LimitPrice, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
        }
        public void ValidateStopLimitOrders()
        {
            var oanda  = (OandaBrokerage)Brokerage;
            var symbol = Symbol;
            var quote  = oanda.GetRates(new OandaSymbolMapper().GetBrokerageSymbol(symbol));

            // Buy StopLimit order below market (Oanda accepts this order but cancels it immediately)
            var stopPrice  = quote.BidPrice - 0.5m;
            var limitPrice = stopPrice + 0.0005m;
            var order      = new StopLimitOrder(symbol, 1, stopPrice, limitPrice, DateTime.Now);

            Assert.IsTrue(oanda.PlaceOrder(order));

            // Buy StopLimit order above market
            stopPrice  = quote.AskPrice + 0.5m;
            limitPrice = stopPrice + 0.0005m;
            order      = new StopLimitOrder(symbol, 1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));

            // Sell StopLimit order below market
            stopPrice  = quote.BidPrice - 0.5m;
            limitPrice = stopPrice - 0.0005m;
            order      = new StopLimitOrder(symbol, -1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));

            // Sell StopLimit order above market (Oanda accepts this order but cancels it immediately)
            stopPrice  = quote.AskPrice + 0.5m;
            limitPrice = stopPrice - 0.0005m;
            order      = new StopLimitOrder(symbol, -1, stopPrice, limitPrice, DateTime.Now);
            Assert.IsTrue(oanda.PlaceOrder(order));
        }
예제 #12
0
        /// <summary>
        /// Default stop limit fill model implementation in base class security. (Stop Limit Order Type)
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="SecurityTransactionModel.LimitFill"/>
        /// <remarks>
        ///     There is no good way to model limit orders with OHLC because we never know whether the market has
        ///     gapped past our fill price. We have to make the assumption of a fluid, high volume market.
        ///
        ///     Stop limit orders we also can't be sure of the order of the H - L values for the limit fill. The assumption
        ///     was made the limit fill will be done with closing price of the bar after the stop has been triggered..
        /// </remarks>
        public virtual OrderEvent StopLimitFill(Security asset, StopLimitOrder order)
        {
            //Default order event to return.
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var fill    = new OrderEvent(order, utcTime, 0);

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

            //Get the range of prices in the last bar:
            var prices = GetPrices(asset, order.Direction);

            //Check if the Stop Order was filled: opposite to a limit order
            switch (order.Direction)
            {
            case OrderDirection.Buy:
                //-> 1.2 Buy Stop: If Price Above Setpoint, Buy:
                if (prices.High > order.StopPrice || order.StopTriggered)
                {
                    order.StopTriggered = true;

                    // Fill the limit order, using closing price of bar:
                    // Note > Can't use minimum price, because no way to be sure minimum wasn't before the stop triggered.
                    if (asset.Price < order.LimitPrice)
                    {
                        fill.Status    = OrderStatus.Filled;
                        fill.FillPrice = order.LimitPrice;
                    }
                }
                break;

            case OrderDirection.Sell:
                //-> 1.1 Sell Stop: If Price below setpoint, Sell:
                if (prices.Low < order.StopPrice || order.StopTriggered)
                {
                    order.StopTriggered = true;

                    // Fill the limit order, using minimum price of the bar
                    // Note > Can't use minimum price, because no way to be sure minimum wasn't before the stop triggered.
                    if (asset.Price > order.LimitPrice)
                    {
                        fill.Status    = OrderStatus.Filled;
                        fill.FillPrice = order.LimitPrice;     // Fill at limit price not asset price.
                    }
                }
                break;
            }

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

            return(fill);
        }
예제 #13
0
        public void PerformsStopLimitFillSell()
        {
            var model    = new SecurityTransactionModel();
            var order    = new StopLimitOrder(Symbols.SPY, -100, 101.75m, 101.50m, Noon);
            var config   = CreateTradeBarConfig(Symbols.SPY);
            var security = new Security(SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(), config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency));

            security.SetLocalTimeKeeper(TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork));
            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 102m));

            var fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 101m));

            fill = model.StopLimitFill(security, order);

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 101.66m));

            fill = model.StopLimitFill(security, order);

            // this fills worst case scenario, so it's at the limit price
            Assert.AreEqual(order.Quantity, fill.FillQuantity);
            Assert.AreEqual(order.LimitPrice, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
        }
예제 #14
0
        public StopLimitOrder StopLimitOrder(Instrument instrument, Side side, double qty, double limitPrice, double stopPrice)
        {
            StopLimitOrder stopLimitOrder = new StopLimitOrder(instrument, side, qty, limitPrice, stopPrice);

            this.Strategy.EB2iXBUSFK((SingleOrder)stopLimitOrder);
            return(stopLimitOrder);
        }
예제 #15
0
        /// <summary>
        /// Converts the specified Oanda order into a qc order.
        /// The 'task' will have a value if we needed to issue a rest call for the stop price, otherwise it will be null
        /// </summary>
        protected Order ConvertOrder(DataType.Order order)
        {
            Order qcOrder;

            switch (order.type)
            {
            case "limit":
                qcOrder = new LimitOrder();
                if (order.side == "buy")
                {
                    ((LimitOrder)qcOrder).LimitPrice = Convert.ToDecimal(order.lowerBound);
                }

                if (order.side == "sell")
                {
                    ((LimitOrder)qcOrder).LimitPrice = Convert.ToDecimal(order.upperBound);
                }

                break;

            case "stop":
                qcOrder = new StopLimitOrder();
                if (order.side == "buy")
                {
                    ((StopLimitOrder)qcOrder).LimitPrice = Convert.ToDecimal(order.lowerBound);
                }

                if (order.side == "sell")
                {
                    ((StopLimitOrder)qcOrder).LimitPrice = Convert.ToDecimal(order.upperBound);
                }
                break;

            case "marketIfTouched":
                //when market reaches the price sell at market.
                qcOrder = new StopMarketOrder {
                    Price = Convert.ToDecimal(order.price), StopPrice = Convert.ToDecimal(order.price)
                };
                break;

            case "market":
                qcOrder = new MarketOrder();
                break;

            default:
                throw new NotSupportedException("The Oanda order type " + order.type + " is not supported.");
            }
            qcOrder.Symbol       = order.instrument;
            qcOrder.Quantity     = ConvertQuantity(order);
            qcOrder.SecurityType = InstrumentSecurityTypeMap[order.instrument];
            qcOrder.Status       = OrderStatus.None;
            qcOrder.BrokerId.Add(order.id);
            qcOrder.Id            = order.id;
            qcOrder.Duration      = OrderDuration.Custom;
            qcOrder.DurationValue = XmlConvert.ToDateTime(order.expiry, XmlDateTimeSerializationMode.Utc);
            qcOrder.Time          = XmlConvert.ToDateTime(order.time, XmlDateTimeSerializationMode.Utc);

            return(qcOrder);
        }
예제 #16
0
        public async Task <Trading.OrderResult> PlaceOrder_SellStopLimit(
            Data.Format format, string symbol, int shares, decimal stopPrice, decimal limitPrice, TimeInForce timeInForce = TimeInForce.Gtc)
        {
            IAlpacaTradingClient trading = null;

            try {
                if (format == Data.Format.Live)
                {
                    if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Live_Secret))
                    {
                        return(Trading.OrderResult.Fail);
                    }

                    trading = Environments.Live.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Live_Key, Settings.API_Alpaca_Live_Secret));
                }
                else if (format == Data.Format.Paper)
                {
                    if (String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Key) || String.IsNullOrWhiteSpace(Settings.API_Alpaca_Paper_Secret))
                    {
                        return(Trading.OrderResult.Fail);
                    }

                    trading = Environments.Paper.GetAlpacaTradingClient(new SecretKey(Settings.API_Alpaca_Paper_Key, Settings.API_Alpaca_Paper_Secret));
                }

                // Prevents exceptions or unwanted behavior with Alpaca API
                var account = await trading.GetAccountAsync();

                if (trading == null || account == null ||
                    account.IsAccountBlocked || account.IsTradingBlocked ||
                    account.TradeSuspendedByUser)
                {
                    return(Trading.OrderResult.Fail);
                }

                // Prevents unintentionally short selling (selling into negative digits, the API interprets that as intent to short-sell)
                var positions = await trading.ListPositionsAsync();

                if (!positions.Any(p => p.Symbol == symbol))                // If there is no position for this symbol
                {
                    return(Trading.OrderResult.Fail);
                }

                var position = await trading.GetPositionAsync(symbol);      // If there were no position, this would throw an Exception!

                if (position == null || position.Quantity < shares)         // If the current position doesn't have enough shares
                {
                    return(Trading.OrderResult.Fail);
                }

                var order = await trading.PostOrderAsync(StopLimitOrder.Sell(symbol, shares, stopPrice, limitPrice).WithDuration(timeInForce));

                return(Trading.OrderResult.Success);
            } catch (Exception ex) {
                await Log.Error($"{MethodBase.GetCurrentMethod().DeclaringType}: {MethodBase.GetCurrentMethod().Name}", ex);

                return(Trading.OrderResult.Fail);
            }
        }
예제 #17
0
        /// <summary>
        /// Converts an Oanda order into a LEAN order.
        /// </summary>
        private Order ConvertOrder(JToken order)
        {
            var type = order["type"].ToString();

            Order qcOrder;

            var instrument   = order["instrument"].ToString();
            var id           = order["id"].ToString();
            var units        = order["units"].ConvertInvariant <decimal>();
            var createTime   = order["createTime"].ToString();
            var securityType = SymbolMapper.GetBrokerageSecurityType(instrument);
            var symbol       = SymbolMapper.GetLeanSymbol(instrument, securityType, Market.Oanda);
            var time         = GetTickDateTimeFromString(createTime);
            var quantity     = units;

            switch (type)
            {
            case "MARKET_IF_TOUCHED":
                var stopOrder = order.ToObject <MarketIfTouchedOrder>();
                qcOrder = new StopMarketOrder
                {
                    StopPrice = stopOrder.Price.ToDecimal()
                };
                break;

            case "LIMIT":
                var limitOrder = order.ToObject <OandaLimitOrder>();
                qcOrder = new LimitOrder(symbol, quantity, limitOrder.Price.ToDecimal(), time);
                break;

            case "STOP":
                var stopLimitOrder = order.ToObject <StopOrder>();
                var price          = stopLimitOrder.Price.ConvertInvariant <decimal>();
                var limitPrice     = stopLimitOrder.PriceBound.ConvertInvariant <decimal>();
                qcOrder = new StopLimitOrder(symbol, quantity, price, limitPrice, time);
                break;

            case "MARKET":
                qcOrder = new MarketOrder();
                break;

            default:
                throw new NotSupportedException(
                          "An existing " + type + " working order was found and is currently unsupported. Please manually cancel the order before restarting the algorithm.");
            }

            qcOrder.Status = OrderStatus.None;
            qcOrder.BrokerId.Add(id);

            var gtdTime = order["gtdTime"];

            if (gtdTime != null)
            {
                var expiry = GetTickDateTimeFromString(gtdTime.ToString());
                qcOrder.Properties.TimeInForce = TimeInForce.GoodTilDate(expiry);
            }

            return(qcOrder);
        }
예제 #18
0
 public StopLimitOrder Create(StopLimitOrder item)
 {
     using (var db = new DataBaseContext())
     {
         var order = db.StopLimitOrders.Add(item).Entity;
         db.SaveChanges();
         return(order);
     }
 }
예제 #19
0
 public void Reset()
 {
     MessageType = ClientToServerMessageTypeEnum.NotSet;
     LimitOrder.Reeset();
     MarketOrder.Reset();
     StopLimitOrder.Reeset();
     DuoLimitOrder.Reset();
     ClientId = -1;
 }
예제 #20
0
 public void Update(ClientToServerMessage other)
 {
     ClientId    = other.ClientId;
     MessageType = other.MessageType;
     LimitOrder.Update(other.LimitOrder);
     MarketOrder.Update(other.MarketOrder);
     StopLimitOrder.Update(other.StopLimitOrder);
     DuoLimitOrder.Update(other.DuoLimitOrder);
 }
예제 #21
0
        public void TestSendNumLotsZeroDefault()
        {
            var order = new StopLimitOrder(new SOrderParameters());

            using var monitoredOrder = order.Monitor();
            order.Send(15, 15, 0);
            monitoredOrder.Should().Raise("OrderSent")
            .WithArgs <OrderInfo>(info => info.Size == 100);
        }
예제 #22
0
        public void StopLimitOrderDoesNotFillUsingDataBeforeSubmitTime(decimal orderQuantity, decimal stopPrice, decimal limitPrice)
        {
            var time       = new DateTime(2018, 9, 24, 9, 30, 0);
            var timeKeeper = new TimeKeeper(time.ConvertToUtc(TimeZones.NewYork), TimeZones.NewYork);
            var symbol     = Symbol.Create("SPY", SecurityType.Equity, Market.USA);

            var config   = new SubscriptionDataConfig(typeof(TradeBar), symbol, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, true, true, false);
            var security = new Security(
                SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(),
                config,
                new Cash(Currencies.USD, 0, 1m),
                SymbolProperties.GetDefault(Currencies.USD),
                ErrorCurrencyConverter.Instance,
                RegisteredSecurityDataTypesProvider.Null,
                new SecurityCache()
                );

            security.SetLocalTimeKeeper(timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork));

            var tradeBar = new TradeBar(time, symbol, 290m, 292m, 289m, 291m, 12345);

            security.SetMarketPrice(tradeBar);

            time += TimeSpan.FromMinutes(1);
            timeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork));

            var fillForwardBar = (TradeBar)tradeBar.Clone(true);

            security.SetMarketPrice(fillForwardBar);

            var fillModel = new ImmediateFillModel();
            var order     = new StopLimitOrder(symbol, orderQuantity, stopPrice, limitPrice, time.ConvertToUtc(TimeZones.NewYork));

            var fill = fillModel.Fill(new FillModelParameters(
                                          security,
                                          order,
                                          new MockSubscriptionDataConfigProvider(config),
                                          Time.OneHour)).OrderEvent;

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            time += TimeSpan.FromMinutes(1);
            timeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork));

            tradeBar = new TradeBar(time, symbol, 290m, 292m, 289m, 291m, 12345);
            security.SetMarketPrice(tradeBar);

            fill = fillModel.StopLimitFill(security, order);

            Assert.AreEqual(orderQuantity, fill.FillQuantity);
            Assert.AreEqual(limitPrice, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
            Assert.AreEqual(0, fill.OrderFee.Value.Amount);
        }
예제 #23
0
        private Order ConvertOrder(IB.Order ibOrder, IB.Contract contract)
        {
            // this function is called by GetOpenOrders which is mainly used by the setup handler to
            // initialize algorithm state.  So the only time we'll be executing this code is when the account
            // has orders sitting and waiting from before algo initialization...
            // because of this we can't get the time accurately

            Order order;
            var   mappedSymbol = MapSymbol(contract);
            var   orderType    = ConvertOrderType(ibOrder.OrderType);

            switch (orderType)
            {
            case OrderType.Market:
                order = new MarketOrder(mappedSymbol,
                                        ibOrder.TotalQuantity,
                                        new DateTime() // not sure how to get this data
                                        );
                break;

            case OrderType.Limit:
                order = new LimitOrder(mappedSymbol,
                                       ibOrder.TotalQuantity,
                                       ibOrder.LimitPrice,
                                       new DateTime()
                                       );
                break;

            case OrderType.StopMarket:
                order = new StopMarketOrder(mappedSymbol,
                                            ibOrder.TotalQuantity,
                                            ibOrder.AuxPrice,
                                            new DateTime()
                                            );
                break;

            case OrderType.StopLimit:
                order = new StopLimitOrder(mappedSymbol,
                                           ibOrder.TotalQuantity,
                                           ibOrder.AuxPrice,
                                           ibOrder.LimitPrice,
                                           new DateTime()
                                           );
                break;

            default:
                throw new InvalidEnumArgumentException("orderType", (int)orderType, typeof(OrderType));
            }

            order.SecurityType = ConvertSecurityType(contract.SecurityType);
            order.BrokerId.Add(ibOrder.OrderId);

            return(order);
        }
예제 #24
0
        public void TestSendIgnoreNumLots()
        {
            var order = new StopLimitOrder(new SOrderParameters());

            using var monitoredOrder = order.Monitor();
            order.Send(20, 19, 99);
            monitoredOrder.Should().Raise("OrderSent")
            .WithArgs <OrderInfo>(info => info.ConditionPrice == 20)
            .WithArgs <OrderInfo>(info => info.Price == 19)
            .WithArgs <OrderInfo>(info => info.Size == 100);
        }
예제 #25
0
 public void Reset()
 {
     ReceiverClientId = -1;
     MessageType      = ServerToClientMessageTypeEnum.NotSet;
     Message          = string.Empty;
     LimitOrder.Reeset();
     LimitOrderList.Clear();
     StopLimitOrderList.Clear();
     Execution.Reset();
     Level1.Reset();
     StopLimitOrder.Reeset();
 }
예제 #26
0
        public void TestSendCustomNumLots()
        {
            var order = new StopLimitOrder(
                new SOrderParameters(Contracts.CreateUserSpecified(100), EOrderAction.Buy));

            using var monitoredOrder = order.Monitor();
            order.Send(17, 18, 25);
            monitoredOrder.Should().Raise("OrderSent")
            .WithArgs <OrderInfo>(info => info.ConditionPrice == 17)
            .WithArgs <OrderInfo>(info => info.Price == 18)
            .WithArgs <OrderInfo>(info => info.OrderAction == EOrderAction.Buy)
            .WithArgs <OrderInfo>(info => info.Size == 25);
        }
예제 #27
0
 public void Update(IServerToClientMessage other)
 {
     Reset();
     MessageType = other.MessageType;
     LimitOrder.Update(other.LimitOrder);
     LimitOrderList.AddRange(other.LimitOrderList);
     StopLimitOrderList.AddRange(other.StopLimitOrderList);
     Message          = other.Message;
     ReceiverClientId = other.ReceiverClientId;
     Execution.Update(other.Execution);
     Level1.Update(other.Level1);
     StopLimitOrder.Update(other.StopLimitOrder);
 }
예제 #28
0
        public void TestSendWithUserDefinedSize()
        {
            var order = new StopLimitOrder(new SOrderParameters(
                                               Contracts.CreateUserSpecified(50), EOrderAction.Sell));

            using var monitoredOrder = order.Monitor();
            order.Send(15, 14);
            monitoredOrder.Should().Raise("OrderSent")
            .WithArgs <OrderInfo>(info => info.ConditionPrice == 15)
            .WithArgs <OrderInfo>(info => info.Price == 14)
            .WithArgs <OrderInfo>(info => info.OrderAction == EOrderAction.Sell)
            .WithArgs <OrderInfo>(info => info.Size == 50);
        }
예제 #29
0
        /// <summary>
        /// Send a stop limit order to the transaction handler:
        /// </summary>
        /// <param name="symbol">String symbol for the asset</param>
        /// <param name="quantity">Quantity of shares for limit order</param>
        /// <param name="stopPrice">Stop price for this order</param>
        /// <param name="limitPrice">Limit price to fill this order</param>
        /// <param name="tag">String tag for the order (optional)</param>
        /// <returns>Order id</returns>
        public int StopLimitOrder(string symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "")
        {
            var error = PreOrderChecks(symbol, quantity, OrderType.StopLimit);

            if (error < 0)
            {
                return(error);
            }

            var order = new StopLimitOrder(symbol, quantity, stopPrice, limitPrice, Time, tag, Securities[symbol].Type);

            //Add the order and create a new order Id.
            return(Transactions.AddOrder(order));
        }
예제 #30
0
        public void PerformsStopLimitFillSell()
        {
            var model    = new ImmediateFillModel();
            var order    = new StopLimitOrder(Symbols.SPY, -100, 101.75m, 101.50m, Noon);
            var config   = CreateTradeBarConfig(Symbols.SPY);
            var security = new Security(
                SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(),
                config,
                new Cash(Currencies.USD, 0, 1m),
                SymbolProperties.GetDefault(Currencies.USD),
                ErrorCurrencyConverter.Instance,
                RegisteredSecurityDataTypesProvider.Null,
                new SecurityCache()
                );

            security.SetLocalTimeKeeper(TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork));
            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 102m));

            var fill = model.Fill(new FillModelParameters(
                                      security,
                                      order,
                                      new MockSubscriptionDataConfigProvider(config),
                                      Time.OneHour)).OrderEvent;

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 101m));

            fill = model.Fill(new FillModelParameters(
                                  security,
                                  order,
                                  new MockSubscriptionDataConfigProvider(config),
                                  Time.OneHour)).OrderEvent;

            Assert.AreEqual(0, fill.FillQuantity);
            Assert.AreEqual(0, fill.FillPrice);
            Assert.AreEqual(OrderStatus.None, fill.Status);

            security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, Noon, 101.66m));

            fill = model.StopLimitFill(security, order);

            // this fills worst case scenario, so it's at the limit price
            Assert.AreEqual(order.Quantity, fill.FillQuantity);
            Assert.AreEqual(security.Low, fill.FillPrice);
            Assert.AreEqual(OrderStatus.Filled, fill.Status);
        }
예제 #31
0
		public Order StopLimitOrder(Instrument instrument, OrderSide side, double qty, double limitPrice, double stopPrice, string text)
		{
			SingleOrder singleOrder;
			if (side == OrderSide.Buy)
			{
				singleOrder = new StopLimitOrder(instrument.instrument, Side.Buy, qty, limitPrice, stopPrice, text);
			}
			else
			{
				singleOrder = new StopLimitOrder(instrument.instrument, Side.Sell, qty, limitPrice, stopPrice, text);
			}
			singleOrder.Strategy = this.strategyName;
			Order order = new Order(singleOrder);
			order.Portfolio = this.portfolio;
			Map.OQ_SQ_Order[order] = singleOrder;
			Map.SQ_OQ_Order[singleOrder] = order;
			return order;
		}
예제 #32
0
        /// <summary>
        /// Default stop limit fill model implementation in base class security. (Stop Limit Order Type)
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="SecurityTransactionModel.LimitFill"/>
        /// <remarks>
        ///     There is no good way to model limit orders with OHLC because we never know whether the market has 
        ///     gapped past our fill price. We have to make the assumption of a fluid, high volume market.
        /// 
        ///     Stop limit orders we also can't be sure of the order of the H - L values for the limit fill. The assumption
        ///     was made the limit fill will be done with closing price of the bar after the stop has been triggered..
        /// </remarks>
        public virtual OrderEvent StopLimitFill(Security asset, StopLimitOrder order)
        {
            //Default order event to return.
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var fill = new OrderEvent(order, utcTime, 0);

            //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, order.Direction);

            //Check if the Stop Order was filled: opposite to a limit order
            switch (order.Direction)
            {
                case OrderDirection.Buy:
                    //-> 1.2 Buy Stop: If Price Above Setpoint, Buy:
                    if (maximumPrice > order.StopPrice || order.StopTriggered)
                    {
                        order.StopTriggered = true;

                        // Fill the limit order, using closing price of bar:
                        // Note > Can't use minimum price, because no way to be sure minimum wasn't before the stop triggered.
                        if (asset.Price < order.LimitPrice)
                        {
                            fill.Status = OrderStatus.Filled;
                            fill.FillPrice = order.LimitPrice;
                        }
                    }
                    break;

                case OrderDirection.Sell:
                    //-> 1.1 Sell Stop: If Price below setpoint, Sell:
                    if (minimumPrice < order.StopPrice || order.StopTriggered)
                    {
                        order.StopTriggered = true;

                        // Fill the limit order, using minimum price of the bar
                        // Note > Can't use minimum price, because no way to be sure minimum wasn't before the stop triggered.
                        if (asset.Price > order.LimitPrice)
                        {
                            fill.Status = OrderStatus.Filled;
                            fill.FillPrice = order.LimitPrice; // Fill at limit price not asset price.
                        }
                    }
                    break;
            }

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

            return fill;
        }
예제 #33
0
		public Order SellStopLimitOrder(double qty, double limitPrice, double stopPrice, string text)
		{
			SingleOrder singleOrder = new StopLimitOrder(this.sq_Instrument, Side.Sell, qty, limitPrice, stopPrice, text);
			singleOrder.Strategy = this.strategyName;
			Order order = new Order(singleOrder);
			order.Portfolio = this.portfolio;
			Map.OQ_SQ_Order[order] = singleOrder;
			Map.SQ_OQ_Order[singleOrder] = order;
			return order;
		}