public void PerformsMarketOnCloseUsingClosingPrice() { var reference = new DateTime(2015, 06, 05, 15, 0, 0); // before market close var model = new SecurityTransactionModel(); var order = new MarketOnCloseOrder(Symbols.SPY, 100, reference); 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)); var time = reference; TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time, Symbols.SPY, 1m, 2m, 0.5m, 1.33m, 100)); var fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(0, fill.FillQuantity); // market closes after 60min, so this is just before market Close time = reference.AddMinutes(59); TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time, Symbols.SPY, 1.33m, 2.75m, 1.15m, 1.45m, 100)); fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(0, fill.FillQuantity); // market closes time = reference.AddMinutes(60); TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time, Symbols.SPY, 1.45m, 2.0m, 1.1m, 1.40m, 100)); fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(order.Quantity, fill.FillQuantity); Assert.AreEqual(security.Close, fill.FillPrice); }
/// <summary> /// Wrapper for <see cref = "IFillModel.MarketOnCloseFill(Security, MarketOnCloseOrder)" /> in Python /// </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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { using (Py.GIL()) { return(_model.MarketOnCloseFill(asset, order)); } }
public void PerformsMarketOnCloseUsingClosingPrice() { var reference = DateTime.Today.AddHours(15);// before market close var model = new SecurityTransactionModel(); var order = new MarketOnCloseOrder(Symbol, SecurityType.Equity, 100, reference, 1m); var config = new SubscriptionDataConfig(typeof(TradeBar), SecurityType.Equity, Symbol, Resolution.Minute, true, true, true, true, false, 0); var security = new Security(config, 1) { Exchange = new EquityExchange() }; var time = reference; security.SetMarketPrice(time, new TradeBar(time, Symbol, 1m, 2m, 0.5m, 1.33m, 100)); var fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(0, fill.FillQuantity); // market closes after 60min, so this is just before market Close time = reference.AddMinutes(59); security.SetMarketPrice(time, new TradeBar(time, Symbol, 1.33m, 2.75m, 1.15m, 1.45m, 100)); fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(0, fill.FillQuantity); // market closes time = reference.AddMinutes(60); security.SetMarketPrice(time, new TradeBar(time, Symbol, 1.45m, 2.0m, 1.1m, 1.40m, 100)); fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(order.Quantity, fill.FillQuantity); Assert.AreEqual(security.Close, fill.FillPrice); }
/// <summary> /// Market on Close 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 override OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { using (Py.GIL()) { return((_model.MarketOnCloseFill(asset, order) as PyObject).GetAndDispose <OrderEvent>()); } }
/// <summary> /// Market on Close 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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var orderFee = GetOrderFee(asset, order); var fill = new OrderEvent(order, utcTime, orderFee); if (order.Status == OrderStatus.Canceled) { return(fill); } try { var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return(fill); } fill.FillPrice = asset.Close; fill.Status = OrderStatus.Filled; //Calculate the model slippage: e.g. 0.01c var slip = 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; } } catch (Exception err) { Log.Error(err); } return(fill); }
/// <summary> /// Market on Close 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 virtual OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { if (asset.Exchange.Hours.IsMarketAlwaysOpen) { throw new InvalidOperationException($"Market never closes for this symbol {asset.Symbol}, can no submit a {nameof(OrderType.MarketOnClose)} order."); } var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var fill = new OrderEvent(order, utcTime, OrderFee.Zero); if (order.Status == OrderStatus.Canceled) { return(fill); } var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return(fill); } // make sure the exchange is open/normal market hours before filling if (!IsExchangeOpen(asset, false)) { return(fill); } fill.FillPrice = GetPricesCheckingPythonWrapper(asset, order.Direction).Close; 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; // assume the order completely filled fill.FillQuantity = order.Quantity; break; case OrderDirection.Sell: fill.FillPrice -= slip; // assume the order completely filled fill.FillQuantity = order.Quantity; break; } return(fill); }
public void PerformsMarketOnCloseUsingClosingPrice() { var reference = new DateTime(2015, 06, 05, 15, 0, 0); // before market close var model = new ImmediateFillModel(); var order = new MarketOnCloseOrder(Symbols.SPY, 100, reference); 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)); var time = reference; TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time - config.Increment, Symbols.SPY, 1m, 2m, 0.5m, 1.33m, 100, config.Increment)); var fill = model.Fill(new FillModelParameters( security, order, new MockSubscriptionDataConfigProvider(config), Time.OneHour)).OrderEvent; Assert.AreEqual(0, fill.FillQuantity); // market closes after 60min, so this is just before market Close time = reference.AddMinutes(59); TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time - config.Increment, Symbols.SPY, 1.33m, 2.75m, 1.15m, 1.45m, 100, config.Increment)); fill = model.Fill(new FillModelParameters( security, order, new MockSubscriptionDataConfigProvider(config), Time.OneHour)).OrderEvent; Assert.AreEqual(0, fill.FillQuantity); // market closes time = reference.AddMinutes(60); TimeKeeper.SetUtcDateTime(time.ConvertToUtc(TimeZones.NewYork)); security.SetMarketPrice(new TradeBar(time - config.Increment, Symbols.SPY, 1.45m, 2.0m, 1.1m, 1.40m, 100, config.Increment)); fill = model.MarketOnCloseFill(security, order); Assert.AreEqual(order.Quantity, fill.FillQuantity); Assert.AreEqual(security.Close, fill.FillPrice); }
/// <summary> /// Market on Close 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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var fill = new OrderEvent(order, utcTime, 0); if (order.Status == OrderStatus.Canceled) { return(fill); } var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return(fill); } // make sure the exchange is open/normal market hours before filling if (!IsExchangeOpen(asset, false)) { return(fill); } fill.FillPrice = GetPrices(asset, order.Direction).Close; 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); }
/// <summary> /// Market on close order implementation: Send a market order when the exchange closes /// </summary> /// <param name="symbol">The symbol to be ordered</param> /// <param name="quantity">The number of shares to required</param> /// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param> /// <returns>The order ID</returns> public int MarketOnClose(string symbol, int quantity, string tag = "") { var error = PreOrderChecks(symbol, quantity, OrderType.MarketOnClose); if (error < 0) { return(error); } var security = Securities[symbol]; var order = new MarketOnCloseOrder(symbol, security.Type, quantity, Time, security.Price, tag); return(Transactions.AddOrder(order)); }
public void DeserializesMarketOnCloseOrder(Symbols.SymbolsKey key) { var expected = new MarketOnCloseOrder(Symbols.Lookup(key), 100, new DateTime(2015, 11, 23, 17, 15, 37), "now") { Id = 12345, Price = 209.03m, ContingentId = 123456, BrokerId = new List <string> { "727", "54970" } }; TestOrderType(expected); }
public void DeserializesMarketOnCloseOrder() { var expected = new MarketOnCloseOrder(Symbols.SPY, SecurityType.Equity, 100, new DateTime(2015, 11, 23, 17, 15, 37), "now") { Id = 12345, Price = 209.03m, ContingentId = 123456, BrokerId = new List <long> { 727, 54970 } }; TestOrderType(expected); }
/// <summary> /// Market on Close 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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var fill = new OrderEvent(order); if (order.Status == OrderStatus.Canceled) { return(fill); } try { var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return(fill); } order.Price = asset.Close; 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); }
/// <summary> /// Market on Close Fill Model. Return an order event with the fill details /// </summary> /// <param name="security">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 MarketOnCloseFill(Security security, MarketOnCloseOrder order) { var fill = new OrderEvent(order); if (fill.Status == OrderStatus.Canceled) { return(fill); } try { // wait until market closes if (security.Exchange.ExchangeOpen) { return(fill); } order.Price = security.Close; order.Status = OrderStatus.Filled; //Calculate the model slippage: e.g. 0.01c var slip = GetSlippageApproximation(security, 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); }
public OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var fill = new OrderEvent(order, utcTime, 0); if (order.Status == OrderStatus.Canceled) { return(fill); } var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); if (asset.LocalTime < nextMarketClose) { return(fill); } fill.FillPrice = GetPrices(asset, order.Direction).Close; fill.Status = OrderStatus.Filled; var slip = asset.SlippageModel.GetSlippageApproximation(asset, order); switch (order.Direction) { case OrderDirection.Buy: fill.FillPrice += slip; break; case OrderDirection.Sell: fill.FillPrice -= slip; break; } if (fill.Status == OrderStatus.Filled) { fill.FillQuantity = order.Quantity; fill.OrderFee = asset.FeeModel.GetOrderFee(asset, order); } return(fill); }
public override OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { MarketOnCloseFillWasCalled = true; return(base.MarketOnCloseFill(asset, order)); }
/// <summary> /// Create pending order based on order ticket /// </summary> /// <param name="ticket"></param> /// <returns></returns> public PendingOrder CreateOrder(OrderTicket ticket) { //Get correct ticket information if (ticket.Type != OrderTicketType.Submit) { return(null); } //Get new order ticket if (!(ticket is SubmitOrderTicket norderticket)) { ticket.SetResponse(OrderTicketResponse.Error(ticket.OrderId, OrderTicketResponseErrorCode.ProcessingError, "Incorrect ticket type received")); return(null); } //Check order type based on input Order order; switch (norderticket.OrderType) { case OrderType.Limit: order = new LimitOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.LimitPrice, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; case OrderType.Market: order = new MarketOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; case OrderType.StopMarket: order = new StopMarketOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.StopPrice, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; case OrderType.StopLimit: order = new StopLimitOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.LimitPrice, norderticket.StopPrice, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; case OrderType.MarketOnOpen: order = new MarketOnOpenOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; case OrderType.MarketOnClose: order = new MarketOnCloseOrder(norderticket.Security, norderticket.FundId, norderticket.Quantity, norderticket.CreatedUtc, norderticket.ExchangeName, norderticket.Comment) { InternalId = _portfolio.OrderTicketHandler.GetNextInternalOrderId() }; break; default: ticket.SetResponse(OrderTicketResponse.Error(ticket.OrderId, OrderTicketResponseErrorCode.ProcessingError, $"Unknown order type {norderticket.OrderType} supplied")); return(null); } //Check if order type is supported bool issupported; try { issupported = _brokerModel.IsOrderTypeSupported(order.Type); } catch (Exception exc) { _log.Error(exc, $"Could not execute brokermodel function IsOrderTypeSupported due to exception"); throw exc; } //Create pending order return(new PendingOrder(_portfolio, ticket.FundId, order, norderticket.Comment, norderticket.Security.LastTickEventUtc, issupported)); }
/// <summary> /// Market on Close 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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var fill = new OrderEvent(order, utcTime, 0); if (order.Status == OrderStatus.Canceled) return fill; var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return fill; } fill.FillPrice = asset.Close; 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; }
public OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { MarketOnCloseFillWasCalled = true; return(orderEvent); }
/// <summary> /// Market on Close 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 virtual OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone); var fill = new OrderEvent(order, utcTime, OrderFee.Zero); if (order.Status == OrderStatus.Canceled) { return(fill); } var localOrderTime = order.Time.ConvertFromUtc(asset.Exchange.TimeZone); var nextMarketClose = asset.Exchange.Hours.GetNextMarketClose(localOrderTime, false); // wait until market closes after the order time if (asset.LocalTime < nextMarketClose) { return(fill); } var subscribedTypes = GetSubscribedTypes(asset); if (subscribedTypes.Contains(typeof(Tick))) { var primaryExchangeCode = ((Equity)asset).PrimaryExchange.Code; var officialClose = (uint)(TradeConditionFlags.Regular | TradeConditionFlags.OfficialClose); var closingPrints = (uint)(TradeConditionFlags.Regular | TradeConditionFlags.ClosingPrints); var trades = asset.Cache.GetAll <Tick>() .Where(x => x.TickType == TickType.Trade && x.Price > 0) .OrderBy(x => x.EndTime).ToList(); // Get the last valid (non-zero) tick of trade type from an close market var tick = trades .Where(x => !string.IsNullOrWhiteSpace(x.SaleCondition)) .LastOrDefault(x => x.ExchangeCode == primaryExchangeCode && (x.ParsedSaleCondition == officialClose || x.ParsedSaleCondition == closingPrints)); // If there is no OfficialClose or ClosingPrints in the current list of trades, // we will wait for the next up to 1 minute before accepting the last tick without flags // We will give priority to trade then use quote to get the timestamp // If there are only quotes, we will need to test for the tick type before we assign the fill price if (tick == null) { tick = trades.LastOrDefault() ?? asset.Cache.GetAll <Tick>().LastOrDefault(); if (Parameters.ConfigProvider.GetSubscriptionDataConfigs(asset.Symbol).IsExtendedMarketHours()) { fill.Message = "No trade with the OfficialClose or ClosingPrints flag within the 1-minute timeout."; if ((tick?.EndTime - nextMarketClose)?.TotalMinutes < 1) { return(fill); } } else { fill.Message = "No trade with the OfficialClose or ClosingPrints flag for data that does not include extended market hours."; } fill.Message += $" Fill with last {tick.TickType} data."; } if (tick?.TickType == TickType.Trade) { fill.FillPrice = tick.Price; } } // make sure the exchange is open/normal market hours before filling // It will return true if the last bar opens before the market closes else if (!IsExchangeOpen(asset, false)) { return(fill); } else if (subscribedTypes.Contains(typeof(TradeBar))) { fill.FillPrice = asset.Cache.GetData <TradeBar>()?.Close ?? 0; } else { fill.Message = $"Warning: No trade information available at {asset.LocalTime.ToStringInvariant()} {asset.Exchange.TimeZone}, order filled using Quote data"; } // Calculate the model slippage: e.g. 0.01c var slip = asset.SlippageModel.GetSlippageApproximation(asset, order); var bestEffortMessage = ""; // If there is no trade information, get the bid or ask, then apply the slippage switch (order.Direction) { case OrderDirection.Buy: if (fill.FillPrice == 0) { fill.FillPrice = GetBestEffortAskPrice(asset, order.Time, out bestEffortMessage); fill.Message += bestEffortMessage; } fill.FillPrice += slip; break; case OrderDirection.Sell: if (fill.FillPrice == 0) { fill.FillPrice = GetBestEffortBidPrice(asset, order.Time, out bestEffortMessage); fill.Message += bestEffortMessage; } fill.FillPrice -= slip; break; } // assume the order completely filled fill.FillQuantity = order.Quantity; fill.Status = OrderStatus.Filled; return(fill); }
/// <summary> /// Market on Close 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 MarketOnCloseFill(Security asset, MarketOnCloseOrder order) { return(_fillModel.MarketOnCloseFill(asset, order)); }