public void GtdSameDayTimeInForceCryptoOrderExpiresAtMidnightUtc() { var utcTime = new DateTime(2018, 4, 27, 10, 0, 0); var security = new Crypto( SecurityExchangeHours.AlwaysOpen(TimeZones.Utc), new Cash(Currencies.USD, 0, 1m), new SubscriptionDataConfig( typeof(QuoteBar), Symbols.BTCUSD, Resolution.Minute, TimeZones.Utc, TimeZones.Utc, true, true, true ), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); var localTimeKeeper = new LocalTimeKeeper(utcTime, TimeZones.Utc); security.SetLocalTimeKeeper(localTimeKeeper); var timeInForce = TimeInForce.GoodTilDate(new DateTime(2018, 4, 27)); var orderProperties = new OrderProperties { TimeInForce = timeInForce }; var order = new LimitOrder(Symbols.BTCUSD, 10, 100, utcTime, "", orderProperties); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); var fill1 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.PartiallyFilled, OrderDirection.Buy, order.LimitPrice, 3, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); var fill2 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.Filled, OrderDirection.Buy, order.LimitPrice, 7, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); localTimeKeeper.UpdateTime(utcTime.AddHours(14).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); localTimeKeeper.UpdateTime(utcTime.AddHours(14)); Assert.IsTrue(timeInForce.IsOrderExpired(security, order)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); }
/// <summary> /// Sends a new Limit Order Request to 'Order Execution Server' /// </summary> /// <param name="orderDetails">Contains limit order information</param> public void LimitOrderRequest(OrderDetails orderDetails) { // Get new Order ID orderDetails.ID = _orderExecutionService.GetOrderId(); // Create Limit Order object to be sent to 'Order Execution Service' LimitOrder limitOrder = OrderMessage.GenerateLimitOrder(orderDetails.ID, orderDetails.Security, orderDetails.Side, orderDetails.Quantity, orderDetails.Price, orderDetails.Provider); limitOrder.OrderTif = OrderTif.GTC; // Send Reques to Server _orderExecutionService.SendOrder(limitOrder); }
public async Task RegisterLinkedLimitOrders(LimitOrder order1, LimitOrder order2) { await HandleCommonStuff(order1); await HandleCommonStuff(order2); order2.LinkedLimitOrder = order1.Id; order1.LinkedLimitOrder = order2.Id; await _ordersRepository.RegisterOrderAsync(order1); await _ordersRepository.RegisterOrderAsync(order2); await _orderExecuter.Execute(); }
public ActionResult BuyLimitOrder(string currencyname, string buyamount, string buyatprice) { var userId = User.Identity.GetUserId(); var db = new SiteDbContext(); var user = db.Users.Find(userId); decimal BuyAmount = decimal.Parse(buyamount, CultureInfo.InvariantCulture); decimal BuyAtPrice = decimal.Parse(buyatprice, CultureInfo.InvariantCulture); if (BuyAmount == 0 || BuyAtPrice == 0 || BuyAtPrice < 0 || BuyAmount < 0) { return(View("Index")); } var TotalOrderBtcCost = BuyAmount * BuyAtPrice; var Coins = CoinValues.GetValues().ToList(); if (Coins.Where(c => c.Name.Contains(currencyname)).Count() == 0) { return(View("TradePage")); } if (TotalOrderBtcCost > user.Balance) { return(View("TradePage")); } LimitOrder order = new LimitOrder() { User = user, Amount = BuyAmount, Currency = currencyname, AtPrice = BuyAtPrice, OrderType = "Buy", OrderDate = DateTime.Now }; db.LimitOrders.Add(order); user.Balance -= TotalOrderBtcCost; db.SaveChanges(); var Data = Newtonsoft.Json.JsonConvert.SerializeObject(new { UserBtc = user.Balance, UserUsd = user.Balance * CoinValues.GetBtcValue().Price }); return(Json(Data, JsonRequestBehavior.AllowGet)); }
public void DayTimeInForceEquityOrderExpiresAtMarketClose() { var utcTime = new DateTime(2018, 4, 27, 10, 0, 0).ConvertToUtc(TimeZones.NewYork); var security = new Equity( SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(), new SubscriptionDataConfig( typeof(TradeBar), Symbols.SPY, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, true, true, true ), new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); var localTimeKeeper = new LocalTimeKeeper(utcTime, TimeZones.NewYork); security.SetLocalTimeKeeper(localTimeKeeper); var timeInForce = TimeInForce.Day; var orderProperties = new OrderProperties { TimeInForce = timeInForce }; var order = new LimitOrder(Symbols.SPY, 10, 100, utcTime, "", orderProperties); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); var fill1 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.PartiallyFilled, OrderDirection.Buy, order.LimitPrice, 3, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); var fill2 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.Filled, OrderDirection.Buy, order.LimitPrice, 7, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); localTimeKeeper.UpdateTime(utcTime.AddHours(6).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); localTimeKeeper.UpdateTime(utcTime.AddHours(6)); Assert.IsTrue(timeInForce.IsOrderExpired(security, order)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); }
public void LimitSellOrderRequiresBaseCurrencyInPortfolio() { _portfolio.SetCash(0); _portfolio.CashBook["BTC"].SetAmount(0.5m); // 0.5 BTC in portfolio, can sell 0.5 BTC at any price var order = new LimitOrder(_btcusd.Symbol, -0.5m, 10000m, DateTime.UtcNow); Assert.IsTrue(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order).IsSufficient); // 0.5 BTC in portfolio, cannot sell 0.6 BTC at any price order = new LimitOrder(_btcusd.Symbol, -0.6m, 10000m, DateTime.UtcNow); Assert.IsFalse(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order).IsSufficient); }
private void CreateLimitOrder(Trade trade) { var newLimitOrder = new LimitOrder(trade); if (_limitOrderList == null) { _limitOrderList = new List <LimitOrder>(); } _limitOrderList.Add(newLimitOrder); //Send updated List<LimitOrder> to listeners in MainViewModel Messenger.Default.Send <LimitOrderMessage>(new LimitOrderMessage(_limitOrderList, false)); }
private void testBinanceFuture() { /* web de referencia: * https://github.com/fman42/FutureBinanceAPI * */ var Api_Clave = "e3a7d6025708b6c3008c2cb56b209d9a4a180d8af9869533c0fe55719b88da5b"; var API_secreta = "8c6e0568ab0a2d3a9340486b602c87805ccdd1863bee0c4e8060f6959a35e85e"; AuthClient authClient = new AuthClient(Api_Clave, API_secreta, true); // el parametro True indica que usa la testnet. TickerEndPoint Ticker = new TickerEndPoint(authClient); var GetPrice = Task.Run(async() => await Ticker.GetPriceTickerAsync(TraidingPair.BTCUSDT)); GetPrice.Wait(); /* OBTIENE EL PRECIO */ OrderEndPoint order = new OrderEndPoint(authClient); // Create an order endpoint decimal Precio = decimal.Round(GetPrice.Result.Price * Convert.ToDecimal("0,98"), 2); decimal Cantidad = Convert.ToDecimal("0,001"); /* ESTABLE EL APALANCAMIENTO */ TradeEndPoint trade = new TradeEndPoint(authClient); // Create a trade endpoint var setLeverage = Task.Run(async() => await trade.SetLeverageAsync(TraidingPair.BTCUSDT, 25)); // Set 25 leverage for BTCUSDT setLeverage.Wait(); var setMargin = Task.Run(async() => await trade.SetMarginTypeAsync(TraidingPair.BTCUSDT, MarginType.CROSSED)); setMargin.Wait(); /* GENERA LA ORDEN */ LimitOrder limitOrder = new LimitOrder(TraidingPair.BTCUSDT, Side.SELL, Cantidad, Precio, TimeInForceType.GTC); var limitOrderResult = Task.Run(async() => await order.SetAsync(limitOrder)); limitOrderResult.Wait(); /* CANCELA LA ORDEN */ var cancelOrderResult = Task.Run(async() => await order.CancelAsync(TraidingPair.BTCUSDT, limitOrderResult.Result.OrderId)); cancelOrderResult.Wait(); var aaa = 1; aaa = aaa + 2; }
public async Task <OrderResponse> PutLimitOrder(SideType side, ProductType productType, decimal price, decimal size, Guid?clientId, bool?postOnly) { var order = new LimitOrder { Side = side, Price = price, Size = size, ProductType = productType.EnumToString(), ClientGuid = clientId, PostOnly = postOnly }; return(await SendPostRequest <OrderResponse>(Constants.RestUrl.Orders, order)); }
/// <summary> /// Publishes limit order message /// </summary> public void PublishLimitOrder(LimitOrder limitOrder) { try { // Message to be published IMessage <LimitOrder> message = new Message <LimitOrder>(limitOrder); // Publish message _easyNetQBus.Publish(_easyNetQExchange, _limitOrderQueueRoutingKey, true, false, message); } catch (Exception exception) { Logger.Error(exception, _type.FullName, "PublishLimitOrder"); } }
/// <summary> /// Send a 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="limitPrice">Limit price to fill this order</param> /// <param name="tag">String tag for the order (optional)</param> /// <returns>Order id</returns> public int LimitOrder(string symbol, int quantity, decimal limitPrice, string tag = "") { var error = PreOrderChecks(symbol, quantity, OrderType.Limit); if (error < 0) { return(error); } var order = new LimitOrder(symbol, quantity, limitPrice, Time, tag, Securities[symbol].Type); //Add the order and create a new order Id. return(Transactions.AddOrder(order)); }
/// <summary> /// Handles New Limit Order Request messages from Applications /// </summary> /// <param name="limitOrder">TradeHub Limit Order</param> /// <param name="appId">Unique Application ID</param> public void LimitOrderRequestReceived(LimitOrder limitOrder, string appId) { try { if (Logger.IsDebugEnabled) { Logger.Debug( "New Limit Order request received from: " + appId + limitOrder.OrderID + " for: " + limitOrder.OrderExecutionProvider, _type.FullName, "LimitOrderRequestReceived"); } IOrderExecutionProvider orderExecutionProvider; if (_providersMap.TryGetValue(limitOrder.OrderExecutionProvider, out orderExecutionProvider)) { ILimitOrderProvider limitOrderProvider = orderExecutionProvider as ILimitOrderProvider; if (limitOrderProvider != null) { // Modify Order ID by appending Application ID in the front limitOrder.OrderID = appId + "|" + limitOrder.OrderID; // Register Market Order Events RegisterLimitOrderEvents(limitOrderProvider); // Send Limit Order to Execution Provider limitOrderProvider.SendLimitOrder(limitOrder); } else { if (Logger.IsInfoEnabled) { Logger.Info("Requested provider doesn't support Limit Orders", _type.FullName, "LimitOrderRequestReceived"); } } } else { if (Logger.IsInfoEnabled) { Logger.Info( "Order Execution Provider module not available for: " + limitOrder.OrderExecutionProvider, _type.FullName, "LimitOrderRequestReceived"); } } } catch (Exception exception) { Logger.Error(exception, _type.FullName, "LimitOrderRequestReceived"); } }
/* * private bool IsUnknownOrderID(KeyValuePair<long, TradierOrder> x) * { * // we don't have it in our local cache * return !_cachedOpenOrdersByTradierOrderID.ContainsKey(x.Key) * // the transaction happened after we initialized, make sure they're in the same time zone * && x.Value.TransactionDate.ToUniversalTime() > _initializationDateTime.ToUniversalTime() * // we don't have a record of it in our last 10k filled orders * && !_filledTradierOrderIDs.Contains(x.Key); * } * * private void ProcessPotentiallyUpdatedOrder(TradierCachedOpenOrder cachedOrder, TradierOrder updatedOrder) * { * // check for fills or status changes, for either fire a fill event * if (updatedOrder.RemainingQuantity != cachedOrder.Order.RemainingQuantity || ConvertStatus(updatedOrder.Status) != ConvertStatus(cachedOrder.Order.Status)) || { || var qcOrder = _orderProvider.GetOrderByBrokerageId(updatedOrder.Id); || qcOrder.PriceCurrency = "USD"; || const int orderFee = 0; || var fill = new OrderEvent(qcOrder, DateTime.UtcNow, orderFee, "Tradier Fill Event") || { || Status = ConvertStatus(updatedOrder.Status), || // this is guaranteed to be wrong in the event we have multiple fills within our polling interval, || // we're able to partially cope with the fill quantity by diffing the previous info vs current info || // but the fill price will always be the most recent fill, so if we have two fills with 1/10 of a second || // we'll get the latter fill price, so for large orders this can lead to inconsistent state || FillPrice = updatedOrder.LastFillPrice, || FillQuantity = (int)(updatedOrder.QuantityExecuted - cachedOrder.Order.QuantityExecuted) || }; || || // flip the quantity on sell actions || if (IsShort(updatedOrder.Direction)) || { || fill.FillQuantity *= -1; || } || || if (!cachedOrder.EmittedOrderFee) || { || cachedOrder.EmittedOrderFee = true; || var security = _securityProvider.GetSecurity(qcOrder.Symbol); || fill.OrderFee = security.FeeModel.GetOrderFee(security, qcOrder); || } || || // if we filled the order and have another contingent order waiting, submit it || ContingentOrderQueue contingent; || if (fill.Status == OrderStatus.Filled && _contingentOrdersByQCOrderID.TryGetValue(qcOrder.Id, out contingent)) || { || // prevent submitting the contingent order multiple times || if (_contingentReentranceGuardByQCOrderID.Add(qcOrder.Id)) || { || var order = contingent.Next(); || if (order == null || contingent.Contingents.Count == 0) || { || // we've finished with this contingent order || _contingentOrdersByQCOrderID.TryRemove(qcOrder.Id, out contingent); || } || // fire this off in a task so we don't block this thread || if (order != null) || { || // if we have a contingent that needs to be submitted then we can't respect the 'Filled' state from the order || // because the QC order hasn't been technically filled yet, so mark it as 'PartiallyFilled' || fill.Status = OrderStatus.PartiallyFilled; || || Task.Run(() => || { || try || { || Log.Trace("TradierBrokerage.SubmitContingentOrder(): Submitting contingent order for QC id: " + qcOrder.Id); || || var response = TradierPlaceOrder(order); || if (response.Errors.Errors.IsNullOrEmpty()) || { || // add the new brokerage id for retrieval later || qcOrder.BrokerId.Add(response.Order.Id.ToString()); || } || else || { || // if we failed to place this order I don't know what to do, we've filled the first part || // and failed to place the second... strange. Should we invalidate the rest of the order?? || Log.Error("TradierBrokerage.SubmitContingentOrder(): Failed to submit contingent order."); || var message = string.Format("{0} Failed submitting contingent order for QC id: {1} Filled Tradier Order id: {2}", qcOrder.Symbol, qcOrder.Id, updatedOrder.Id); || OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "ContingentOrderFailed", message)); || OnOrderEvent(new OrderEvent(qcOrder, DateTime.UtcNow, orderFee) { Status = OrderStatus.Canceled }); || } || } || catch (Exception err) || { || Log.Error(err); || OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "ContingentOrderError", "An error ocurred while trying to submit an Tradier contingent order: " + err)); || OnOrderEvent(new OrderEvent(qcOrder, DateTime.UtcNow, orderFee) { Status = OrderStatus.Canceled }); || } || finally || { || _contingentReentranceGuardByQCOrderID.Remove(qcOrder.Id); || } || }); || } || } || } || || OnOrderEvent(fill); || } || || // remove from open orders since it's now closed || if (OrderIsClosed(updatedOrder)) || { || _filledTradierOrderIDs.Add(updatedOrder.Id); || _cachedOpenOrdersByTradierOrderID.TryRemove(updatedOrder.Id, out cachedOrder); || } ||} || ||private void UpdateCachedOpenOrder(long key, TradierOrder updatedOrder) ||{ || TradierCachedOpenOrder cachedOpenOrder; || if (_cachedOpenOrdersByTradierOrderID.TryGetValue(key, out cachedOpenOrder)) || { || cachedOpenOrder.Order = updatedOrder; || } || else || { || _cachedOpenOrdersByTradierOrderID[key] = new TradierCachedOpenOrder(updatedOrder); || } ||} */ #endregion #region Conversion routines /// <summary> /// Converts the specified tradier 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(Anonymous8 order) { Order qcOrder; qcOrder = new LimitOrder() { LimitPrice = (decimal)order.LimitPrice }; //TODO /* * switch (order.OrderType) * { * case Type2 * qcOrder = new LimitOrder { LimitPrice = order.Price }; * break; * case TradierOrderType.Market: * qcOrder = new MarketOrder(); * break; * case TradierOrderType.StopMarket: * qcOrder = new StopMarketOrder { StopPrice = GetOrder(order.Id).StopPrice }; * break; * case TradierOrderType.StopLimit: * qcOrder = new StopLimitOrder { LimitPrice = order.Price, StopPrice = GetOrder(order.Id).StopPrice }; * break; * * //case TradierOrderType.Credit: * //case TradierOrderType.Debit: * //case TradierOrderType.Even: * default: * throw new NotImplementedException("The Tradier order type " + order.Type + " is not implemented."); * } */ qcOrder.Symbol = _symbolMapper.GetLeanSymbol(order.Symbol, order.AssetType);// Symbol.Create(order.Symbol, SecurityType.Equity, Market.USA); qcOrder.Quantity = ConvertQuantity(order); qcOrder.Status = ConvertStatus(order.Status); qcOrder.Id = Int32.Parse(order.OrderID.ToString()); //qcOrder.BrokerId.Add(order.OrderID.ToString()); //qcOrder.ContingentId = qcOrder.Properties.TimeInForce = ConvertDuration(order.Duration); /*var orderByBrokerageId = _orderProvider.GetOrderByBrokerageId(order.OrderID.ToString()); * if (orderByBrokerageId != null) * { * qcOrder.Id = orderByBrokerageId.Id; * } */ qcOrder.Time = DateTime.Parse(order.TimeStamp); //TransactionDate; return(qcOrder); }
public async Task PlaceLimitOrderAsync(LimitOrder limitOrder) { var model = new LimitOrderModel { AssetPairId = limitOrder.AssetPairId, CancelPreviousOrders = false, ClientId = _walletId, Id = Guid.NewGuid().ToString(), OrderAction = limitOrder.TradeType.ToOrderAction(), Price = (double)limitOrder.Price, Volume = (double)limitOrder.Volume, }; limitOrder.ExternalId = model.Id; MeResponseModel response; try { response = await _matchingEngineClient.PlaceLimitOrderAsync(model, new CancellationTokenSource(Consts.MatchingEngineTimeout).Token); } catch (Exception exception) { _log.Error(exception, "An error occurred during creating limit orders", new { request = $"data: {model.ToJson()}" }); throw; } if (response == null) { throw new Exception("ME response is null"); } if (response.Status == MeStatusCodes.Ok) { _log.Info("ME place limit order response", new { response = $"data: {response.ToJson()}" }); limitOrder.Error = LimitOrderError.None; } else { _log.Warning("ME place limit order response unsuccessful code.", context: new { response = $"data: {response.ToJson()}" }); limitOrder.Error = response.Status.ToOrderError(); limitOrder.ErrorMessage = limitOrder.Error != LimitOrderError.Unknown ? response.Message : !string.IsNullOrEmpty(response.Message) ? response.Message : "Unknown error"; } }
public void LimitOrderDoesNotFillUsingDataBeforeSubmitTime(decimal orderQuantity, 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(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency), ErrorCurrencyConverter.Instance ); 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 LimitOrder(symbol, orderQuantity, limitPrice, time.ConvertToUtc(TimeZones.NewYork)); var fill = fillModel.LimitFill(security, order); 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.LimitFill(security, order); Assert.AreEqual(orderQuantity, fill.FillQuantity); Assert.AreEqual(limitPrice, fill.FillPrice); Assert.AreEqual(OrderStatus.Filled, fill.Status); Assert.AreEqual(0, fill.OrderFee); }
public async Task OnlyBelowMinimumLimitOrdersAreReplacedWhenMixedWithAboveMinimumOrders(string marketId, long selectionId, Side side, double size, double price) { var limitOrder = new LimitOrder(selectionId, side, price, size); var aboveMinOrder = new LimitOrder(1, Side.Back, 2, 10); await _orderService.Place(marketId, new List <LimitOrder> { limitOrder, aboveMinOrder }); var cancelInstruction = $"{{\"marketId\":\"{marketId}\",\"instructions\":[{limitOrder.ToBelowMinimumCancelInstruction()}]}}"; var replaceInstruction = $"{{\"marketId\":\"{marketId}\",\"instructions\":[{limitOrder.ToBelowMinimumReplaceInstruction()}]}}"; Assert.Equal(cancelInstruction, _exchange.SentParameters["cancelOrders"]); Assert.Equal(replaceInstruction, _exchange.SentParameters["replaceOrders"]); }
public void LimitOrderTestCase() { bool isConnected = false; bool newArrived = false; bool executionArrived = false; var manualLogonEvent = new ManualResetEvent(false); var manualNewEvent = new ManualResetEvent(false); var manualExecutionEvent = new ManualResetEvent(false); LimitOrder limitOrder = new LimitOrder(Constants.OrderExecutionProvider.Simulated); limitOrder.OrderID = "AA"; _orderExecutionProvider.LogonArrived += delegate(string obj) { isConnected = true; Console.WriteLine("Logon Received"); _orderExecutionProvider.SendLimitOrder(limitOrder); manualLogonEvent.Set(); }; _orderExecutionProvider.NewArrived += delegate(Order obj) { newArrived = true; Console.WriteLine("New Received"); manualNewEvent.Set(); }; _orderExecutionProvider.ExecutionArrived += delegate(Execution obj) { executionArrived = true; Console.WriteLine("Execution Received"); manualExecutionEvent.Set(); }; _orderExecutionProvider.Start(); manualLogonEvent.WaitOne(30000, false); manualNewEvent.WaitOne(300000, false); manualExecutionEvent.WaitOne(300000, false); Assert.AreEqual(true, isConnected, "Is Execution Order Provider connected"); Assert.AreEqual(true, newArrived, "New arrived"); Assert.AreEqual(true, executionArrived, "Execution arrived"); }
/// <summary> /// Adds new LimitOrder to list /// If validation of order is successful it sends NewArrived Message. /// In case of failure it sends sends rejection. /// </summary> public void NewLimitOrderArrived(LimitOrder limitOrder) { try { if (ValidateMarketOrder(limitOrder)) { var order = new Order(limitOrder.OrderID, limitOrder.OrderSide, limitOrder.OrderSize, limitOrder.OrderTif, limitOrder.OrderCurrency, limitOrder.Security, limitOrder.OrderExecutionProvider); if (Logger.IsInfoEnabled) { Logger.Info("New Arrived :" + order, _type.FullName, "NewLimitOrderArrived"); } if (NewArrived != null) { NewArrived.Invoke(order); } // Execute Limit Order ExecuteLimitOrder(limitOrder); //// Add to List //_limitOrders.Add(limitOrder); } else { Rejection rejection = new Rejection(limitOrder.Security, OrderExecutionProvider.SimulatedExchange) { OrderId = limitOrder.OrderID, DateTime = DateTime.Now, RejectioReason = "Invaild Price Or Size" }; if (Logger.IsInfoEnabled) { Logger.Info("Rejection :" + rejection, _type.FullName, "NewLimitOrderArrived"); } if (LimitOrderRejection != null) { LimitOrderRejection.Invoke(rejection); } } } catch (Exception exception) { Logger.Error(exception, _type.FullName, "NewLimitOrderArrived"); } }
public void Fill_RegularLiquidity() { Broker broker = new Broker(); const string s = "SPY"; OrderImpl limitBuy = new LimitOrder(s, true, 1, 133m); OrderImpl limitSell = new LimitOrder(s, false, 2, 133.5m); OrderImpl stopBuy = new StopOrder(s, true, 3, 135.70m); OrderImpl stopSell = new StopOrder(s, false, 4, 135.75m); broker.SendOrderStatus(limitBuy); broker.SendOrderStatus(limitSell); broker.SendOrderStatus(stopBuy); broker.SendOrderStatus(stopSell); // OHLC for 6/21/2012 on SPY TickImpl openingTick = TickImpl.NewTrade(s, Util.ToTLDate(DateTime.Now), Util.TL2FT(9, 30, 00), 135.67m, 10670270, "NYS"); TickImpl endMornTick = TickImpl.NewTrade(s, Util.ToTLDate(DateTime.Now), Util.TL2FT(12, 00, 00), 135.78m, 10670270, "NYS"); TickImpl endLunchTick = TickImpl.NewTrade(s, Util.ToTLDate(DateTime.Now), Util.TL2FT(14, 15, 00), 132.33m, 10670270, "NYS"); TickImpl closingTick = TickImpl.NewTrade(s, Util.ToTLDate(DateTime.Now), Util.TL2FT(16, 00, 00), 132.44m, 10670270, "NYS"); broker.Execute(openingTick); broker.Execute(endMornTick); broker.Execute(endLunchTick); broker.Execute(closingTick); List <Trade> trades = broker.GetTradeList(); Assert.IsTrue(trades.Count == 4); foreach (Trade trade in trades) { if (trade.xsize == 1) { Assert.AreEqual(132.33m, trade.xprice); } else if (trade.xsize == 2) { Assert.AreEqual(132.33m, trade.xprice); } else if (trade.xsize == 3) { Assert.AreEqual(135.78m, trade.xprice); } else if (trade.xsize == 4) { Assert.AreEqual(135.78m, trade.xprice); } } }
private static void MakerOnly_orders_of_same_side_never_match(Side side) { var quantity = 1; var price = 10000; var secondAndThirdPrice = price + 1; var market = new Market(Currency.BTC, Currency.USD); foreach (var exchange in BasicTests.CreateExchangesOfDifferentTypes()) { var orderBook = exchange[market]; var firstLimitOrder = new LimitOrder(new OrderInfo(Guid.NewGuid(), side, quantity), price); SendOrder(exchange, firstLimitOrder, market); var secondLimitOrder = new LimitOrder(new OrderInfo(Guid.NewGuid(), side, quantity), secondAndThirdPrice); SendOrder(exchange, secondLimitOrder, market); var thirdLimitOrder = new LimitOrder(new OrderInfo(Guid.NewGuid(), side, quantity), secondAndThirdPrice); SendOrder(exchange, thirdLimitOrder, market); var allLimitOrdersSent = new List <LimitOrder> { firstLimitOrder, secondLimitOrder, thirdLimitOrder }; var orderBookAgain = exchange[market]; Assert.That(orderBookAgain[side.Other()].Count(), Is.EqualTo(0)); var ourSide = new List <LimitOrder>(); var orderBookThisSide = orderBookAgain[side]; while (true) { try { var tip = orderBookThisSide.Tip.Value; ourSide.Add(tip); orderBookThisSide = orderBookThisSide.Tail.Value; } catch { break; } } LimitOrders.AssertAreSameOrdersRegardlessOfOrder(allLimitOrdersSent, ourSide); } }
public void CreateLimitOrder_IfAllParametersAreOk_VerifyLimitOrderIsCreated() { LimitOrder limitOrder = OrderMessage.GenerateLimitOrder(new Security() { Symbol = "AAPL" }, OrderSide.BUY, 10, 100, OrderExecutionProvider.SimulatedExchange); Assert.NotNull(limitOrder); Assert.IsNotNullOrEmpty(limitOrder.OrderID); Assert.AreEqual(limitOrder.OrderSide, OrderSide.BUY); Assert.AreEqual(limitOrder.OrderSize, 10); Assert.AreEqual(limitOrder.LimitPrice, 100); Assert.AreEqual(limitOrder.OrderExecutionProvider, OrderExecutionProvider.SimulatedExchange); }
/// <summary> /// Methord Fired when Limit Order Arrived. /// </summary> /// <param name="obj"></param> private void LimitOrderArrived(LimitOrder obj) { try { if (Logger.IsInfoEnabled) { Logger.Info(obj.ToString(), _type.FullName, "LimitOrderArrived"); } _simulateLimitOrder.NewLimitOrderArrived(obj); } catch (Exception exception) { Logger.Error(exception, _type.FullName, "LimitOrderArrived"); } }
/// <summary> /// Creates new Limit Order including unique OrderID /// </summary> /// <param name="security">Contains symbol info on which to trade</param> /// <param name="orderSide">Order side</param> /// <param name="orderSize">Size of the given order</param> /// <param name="limitPrice">Limit price for the given order</param> /// <param name="orderExecutionProvider">Name of the ordeer execution provider</param> /// <returns>TradeHub LimitOrder Object</returns> public static LimitOrder GenerateLimitOrder(Security security, string orderSide, int orderSize, decimal limitPrice, string orderExecutionProvider) { ValidateBasicOrderParameters(security, orderSide, orderSize, orderExecutionProvider); ValidateLimitOrderPrice(limitPrice); LimitOrder limitOrder = new LimitOrder(orderExecutionProvider) { OrderID = Guid.NewGuid().ToString(), Security = security, OrderSize = orderSize, OrderSide = orderSide, LimitPrice = limitPrice }; return(limitOrder); }
public async Task BelowMinimumLimitOrdersArePlacedWithReference(string marketId, long selectionId, Side side, double size, double price, string reference) { var limitOrder = new LimitOrder(selectionId, side, price, size); await _orderService.Place(marketId, new List <LimitOrder> { limitOrder }, reference); var placeInstruction = $"{{\"marketId\":\"{marketId}\",\"customerStrategyRef\":\"{reference}\",\"instructions\":[{limitOrder.ToInstruction()}]}}"; var cancelInstruction = $"{{\"marketId\":\"{marketId}\",\"instructions\":[{limitOrder.ToBelowMinimumCancelInstruction()}]}}"; var replaceInstruction = $"{{\"marketId\":\"{marketId}\",\"customerStrategyRef\":\"{reference}\",\"instructions\":[{limitOrder.ToBelowMinimumReplaceInstruction()}]}}"; Assert.Equal(placeInstruction, _exchange.SentParameters["placeOrders"]); Assert.Equal(cancelInstruction, _exchange.SentParameters["cancelOrders"]); Assert.Equal(replaceInstruction, _exchange.SentParameters["replaceOrders"]); }
public async Task DoNotPlaceOrdersOfZeroSize() { var validOrder = new LimitOrder(1, Side.Lay, 2.5, 9.99); var orders = new List <LimitOrder> { validOrder, new LimitOrder(2, Side.Back, 2.5, 0), }; await _orderService.Place("1.2345", orders); var expected = $"{{\"marketId\":\"1.2345\",\"instructions\":[{validOrder.ToInstruction()}]}}"; Assert.Equal(expected, _exchange.SentParameters["placeOrders"]); }
/// <summary> /// Sends Limit Order on the given Order Execution Provider /// </summary> /// <param name="limitOrder">TradeHub LimitOrder</param> public void SendLimitOrder(LimitOrder limitOrder) { try { if (Logger.IsInfoEnabled) { Logger.Info("Sending Limit Order on Blackwood." + limitOrder, _type.FullName, "SendLimitOrder"); } OrderSide tempSide = BlackwoodTypeConvertor.OrderSideConvertor.GetBlackwoodOrderSide(limitOrder.OrderSide); TIMEOUT tempTimeout = BlackwoodTypeConvertor.OrderTifConvertor.GetBlackwoodOrderTif(limitOrder.OrderTif); if (tempSide.Equals(ORDER_SIDE.NONE)) { Logger.Info("Invalid Order Side", _type.FullName, "SendLimitOrder"); return; } // NOTE: FFED_ID is fixed to ARCA according to StockTrader code // Create Blackwood Order //BWOrder bwOrder = new BWOrder(_session, limitOrder.Security.Symbol, tempSide, // (uint)limitOrder.OrderSize, (double)limitOrder.LimitPrice, 0, // ORDER_TYPE.LIMIT, (int)tempTimeout, FEED_ID.ARCA, false, // (uint)limitOrder.OrderSize); BWOrder bwOrder = new BWOrder(_session, limitOrder.Security.Symbol, tempSide, (uint)limitOrder.OrderSize, (double)limitOrder.LimitPrice, 0, OrderType.LIMIT, (int)tempTimeout, FeedId.ARCA, false, (uint)limitOrder.OrderSize); // Send Order to gateway bwOrder.Send(); // Update Local IDs Map _localToBlackwoodIdsMap.TryAdd(limitOrder.OrderID, bwOrder.ClientOrderID.ToString()); // Update BW-Orders Map _bwOrders.TryAdd(bwOrder.ClientOrderID.ToString(), bwOrder); if (Logger.IsDebugEnabled) { Logger.Debug("BW-Order ID: " + bwOrder.OrderID + " | BW-ClientOrder ID: " + bwOrder.ClientOrderID, _type.FullName, "SendLimitOrder"); } } catch (Exception exception) { Logger.Error(exception, _type.FullName, "SendLimitOrder"); } }
public void BookShouldRemoveSlotWhenOrderIsFilled() { var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var book = new OrderBook("ABC", limitOrderMatchingAlgorithmMock.Object, marketOrderMatchingAlgorithmMock.Object, orderBookBestBidAsk); var buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 9); book.AddLimitOrder(buyOrder); Assert.IsTrue(book.PriceSlots.ContainsKey(90)); Assert.AreEqual(buyOrder, book.PriceSlots[90].BuyOrders[0]); buyOrder.Modify(0); Assert.IsFalse(book.PriceSlots.ContainsKey(90)); }
public void DeserializesLimitOrder(Symbols.SymbolsKey key) { var expected = new LimitOrder(Symbols.Lookup(key), 100, 210.10m, new DateTime(2015, 11, 23, 17, 15, 37), "now") { Id = 12345, Price = 209.03m, ContingentId = 123456, BrokerId = new List <string> { "727", "54970" } }; var actual = TestOrderType(expected); Assert.AreEqual(expected.LimitPrice, actual.LimitPrice); }
public void ShouldRegisterModifyEventHandlerAndReceiveModifyEvent() { var newOrder = new LimitOrder("ABC", 10, 99.22d, WayEnum.Buy, 3); newOrder.RegisterModifyNotificationHandler((order, oldQuantity, oldPrice) => { Assert.AreEqual(newOrder, order); Assert.AreEqual(11, order.Quantity); Assert.AreEqual(88.44d, order.Price); Assert.AreEqual(10, oldQuantity); Assert.AreEqual(99.22d, oldPrice); }); newOrder.Modify(11, 88.44d); }
public void LimitBuyOrderIncludesFees() { _portfolio.SetCash(20000); _btcusd.FeeModel = new ConstantFeeModel(50); // Available cash = 20000, cannot buy 2 BTC at 10000 because of order fee var order = new LimitOrder(_btcusd.Symbol, 2m, 10000m, DateTime.UtcNow); Assert.IsFalse(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order)); // deposit another 50 USD _portfolio.CashBook["USD"].AddAmount(50); // now the order is allowed Assert.IsTrue(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order)); }
public Order SellLimitOrder(double qty, double limitPrice, string text) { SingleOrder singleOrder = new LimitOrder(this.sq_Instrument, Side.Sell, qty, limitPrice, 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; }
public Order LimitOrder(Instrument instrument, OrderSide side, double qty, double limitPrice, string text) { SingleOrder singleOrder; if (side == OrderSide.Buy) { singleOrder = new LimitOrder(instrument.instrument, Side.Buy, qty, limitPrice, text); } else { singleOrder = new LimitOrder(instrument.instrument, Side.Sell, qty, limitPrice, 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 limit order fill model in the base security class. /// </summary> /// <param name="asset">Security asset we're filling</param> /// <param name="order">Order packet to model</param> /// <returns>Order fill information detailing the average price and quantity filled.</returns> /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/> /// <seealso cref="MarketFill(Security, MarketOrder)"/> public virtual OrderEvent LimitFill(Security asset, LimitOrder order) { //Initialise; 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); //-> Valid Live/Model Order: switch (order.Direction) { case OrderDirection.Buy: //Buy limit seeks lowest price if (minimumPrice < order.LimitPrice) { //Set order fill: fill.Status = OrderStatus.Filled; // fill at the worse price this bar or the limit price, this allows far out of the money limits // to be executed properly fill.FillPrice = Math.Min(maximumPrice, order.LimitPrice); } break; case OrderDirection.Sell: //Sell limit seeks highest price possible if (maximumPrice > order.LimitPrice) { fill.Status = OrderStatus.Filled; // fill at the worse price this bar or the limit price, this allows far out of the money limits // to be executed properly fill.FillPrice = Math.Max(minimumPrice, order.LimitPrice); } break; } // assume the order completely filled if (fill.Status == OrderStatus.Filled) { fill.FillQuantity = order.Quantity; fill.OrderFee = asset.FeeModel.GetOrderFee(asset, order); } return fill; }