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); }
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); }
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); }
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); }
/// <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)); } }
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)); }
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)); }
/// <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>()); } }
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(); }
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)); }
/// <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); }
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); }
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); }
/// <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); }
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); } }
/// <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); }
public StopLimitOrder Create(StopLimitOrder item) { using (var db = new DataBaseContext()) { var order = db.StopLimitOrders.Add(item).Entity; db.SaveChanges(); return(order); } }
public void Reset() { MessageType = ClientToServerMessageTypeEnum.NotSet; LimitOrder.Reeset(); MarketOrder.Reset(); StopLimitOrder.Reeset(); DuoLimitOrder.Reset(); ClientId = -1; }
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); }
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); }
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); }
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); }
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); }
public void Reset() { ReceiverClientId = -1; MessageType = ServerToClientMessageTypeEnum.NotSet; Message = string.Empty; LimitOrder.Reeset(); LimitOrderList.Clear(); StopLimitOrderList.Clear(); Execution.Reset(); Level1.Reset(); StopLimitOrder.Reeset(); }
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); }
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); }
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); }
/// <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)); }
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); }
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; }
/// <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; }
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; }