public void ValidateLimitOrders() { var orderEventTracker = new ConcurrentBag <OrderEvent>(); var alpaca = (AlpacaBrokerage)Brokerage; var symbol = Symbol; var lastPrice = GetLastPrice(symbol.Value); EventHandler <OrderEvent> orderStatusChangedCallback = (s, e) => { orderEventTracker.Add(e); }; alpaca.OrderStatusChanged += orderStatusChangedCallback; // Buy Limit order above market - should be filled immediately var limitPrice = lastPrice + 0.5m; var order = new LimitOrder(symbol, 1, limitPrice, DateTime.UtcNow); OrderProvider.Add(order); Assert.IsTrue(alpaca.PlaceOrder(order)); Thread.Sleep(10000); alpaca.OrderStatusChanged -= orderStatusChangedCallback; Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Submitted), 1); Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Filled), 1); }
public void ValidateMarketOrders() { var orderEventTracker = new ConcurrentBag <OrderEvent>(); var oanda = (OandaBrokerage)Brokerage; var symbol = Symbol; EventHandler <OrderEvent> orderStatusChangedCallback = (s, e) => { orderEventTracker.Add(e); }; oanda.OrderStatusChanged += orderStatusChangedCallback; const int numberOfOrders = 100; Parallel.For(0, numberOfOrders, (i) => { var order = new MarketOrder(symbol, 100, DateTime.Now); OrderProvider.Add(order); Assert.IsTrue(oanda.PlaceOrder(order)); Assert.IsTrue(order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled); var orderr = new MarketOrder(symbol, -100, DateTime.UtcNow); OrderProvider.Add(orderr); Assert.IsTrue(oanda.PlaceOrder(orderr)); Assert.IsTrue(orderr.Status == OrderStatus.Filled || orderr.Status == OrderStatus.PartiallyFilled); }); // We want to verify the number of order events with OrderStatus.Filled sent Thread.Sleep(4000); oanda.OrderStatusChanged -= orderStatusChangedCallback; Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Submitted), numberOfOrders * 2); Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Filled), numberOfOrders * 2); }
public void ValidateMarketOrders() { var orderEventTracker = new ConcurrentBag <OrderEvent>(); var alpaca = (AlpacaBrokerage)Brokerage; var symbol = Symbol; EventHandler <OrderEvent> orderStatusChangedCallback = (s, e) => { orderEventTracker.Add(e); }; alpaca.OrderStatusChanged += orderStatusChangedCallback; const int numberOfOrders = 2; for (var i = 0; i < numberOfOrders; i++) { var order = new MarketOrder(symbol, 10, DateTime.UtcNow); OrderProvider.Add(order); Console.WriteLine("Buy Order"); alpaca.PlaceOrder(order); var orderr = new MarketOrder(symbol, -10, DateTime.UtcNow); OrderProvider.Add(orderr); Console.WriteLine("Sell Order"); alpaca.PlaceOrder(orderr); } // We want to verify the number of order events with OrderStatus.Filled sent Thread.Sleep(14000); alpaca.OrderStatusChanged -= orderStatusChangedCallback; Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Submitted), numberOfOrders * 2); Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Filled), numberOfOrders * 2); }
public void ValidateLimitOrders() { var orderEventTracker = new ConcurrentBag <OrderEvent>(); var oanda = (OandaBrokerage)Brokerage; var symbol = Symbol; var quote = oanda.GetRates(new OandaSymbolMapper().GetBrokerageSymbol(symbol)); EventHandler <OrderEvent> orderStatusChangedCallback = (s, e) => { orderEventTracker.Add(e); }; oanda.OrderStatusChanged += orderStatusChangedCallback; // Buy Limit order below market var limitPrice = quote.BidPrice - 0.5m; var order = new LimitOrder(symbol, 1, limitPrice, DateTime.Now); OrderProvider.Add(order); Assert.IsTrue(oanda.PlaceOrder(order)); // update Buy Limit order with no changes Assert.IsTrue(oanda.UpdateOrder(order)); // move Buy Limit order above market order.LimitPrice = quote.AskPrice + 0.5m; Assert.IsTrue(oanda.UpdateOrder(order)); oanda.OrderStatusChanged -= orderStatusChangedCallback; Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Submitted), 1); Assert.AreEqual(orderEventTracker.Count(x => x.Status == OrderStatus.Filled), 1); }
/// <summary> /// Places the specified order with the brokerage and wait until we get the <paramref name="expectedStatus"/> back via an OrderStatusChanged event. /// This function handles adding the order to the <see cref="IOrderProvider"/> instance as well as incrementing the order ID. /// </summary> /// <param name="order">The order to be submitted</param> /// <param name="expectedStatus">The status to wait for</param> /// <param name="secondsTimeout">Maximum amount of time to wait for <paramref name="expectedStatus"/></param> /// <param name="allowFailedSubmission">Allow failed order submission</param> /// <returns>The same order that was submitted.</returns> protected Order PlaceZerodhaOrderWaitForStatus(Order order, OrderStatus expectedStatus = OrderStatus.Filled, double secondsTimeout = 10.0, bool allowFailedSubmission = false) { var requiredStatusEvent = new ManualResetEvent(false); var desiredStatusEvent = new ManualResetEvent(false); EventHandler <OrderEvent> brokerageOnOrderStatusChanged = (sender, args) => { // no matter what, every order should fire at least one of these if (args.Status == OrderStatus.Submitted || args.Status == OrderStatus.Invalid) { Log.Trace(""); Log.Trace("SUBMITTED: " + args); Log.Trace(""); requiredStatusEvent.Set(); } // make sure we fire the status we're expecting if (args.Status == expectedStatus) { Log.Trace(""); Log.Trace("EXPECTED: " + args); Log.Trace(""); desiredStatusEvent.Set(); } }; Brokerage.OrderStatusChanged += brokerageOnOrderStatusChanged; OrderProvider.Add(order); if (!Brokerage.PlaceOrder(order) && !allowFailedSubmission) { Assert.Fail("Brokerage failed to place the order: " + order); } requiredStatusEvent.WaitOneAssertFail((int)(1000 * secondsTimeout), "Expected every order to fire a submitted or invalid status event"); desiredStatusEvent.WaitOneAssertFail((int)(1000 * secondsTimeout), "OrderStatus " + expectedStatus + " was not encountered within the timeout. Order Id:" + order.Id); Brokerage.OrderStatusChanged -= brokerageOnOrderStatusChanged; return(order); }
/// <summary> /// This is used to ensure each test starts with a clean, known state. /// </summary> protected void LiquidateZerodhaHoldings() { Log.Trace(""); Log.Trace("LIQUIDATE HOLDINGS"); Log.Trace(""); var holdings = Brokerage.GetAccountHoldings(); foreach (var holding in holdings) { if (holding.Quantity == 0) { continue; } Log.Trace("Liquidating: " + holding); var order = new MarketOrder(holding.Symbol, -holding.Quantity, DateTime.UtcNow, properties: orderProperties); _orderProvider.Add(order); PlaceZerodhaOrderWaitForStatus(order, OrderStatus.Filled); } }
public void PartialFills() { var manualResetEvent = new ManualResetEvent(false); var qty = 1000000m; var remaining = qty; var sync = new object(); Brokerage.OrderStatusChanged += (sender, orderEvent) => { lock (sync) { remaining -= orderEvent.FillQuantity; Console.WriteLine("Remaining: " + remaining + " FillQuantity: " + orderEvent.FillQuantity); if (orderEvent.Status == OrderStatus.Filled) { manualResetEvent.Set(); } } }; // pick a security with low, but some, volume var symbol = Symbols.EURUSD; var order = new MarketOrder(symbol, qty, DateTime.UtcNow) { Id = 1 }; OrderProvider.Add(order); Brokerage.PlaceOrder(order); // pause for a while to wait for fills to come in manualResetEvent.WaitOne(2500); manualResetEvent.WaitOne(2500); manualResetEvent.WaitOne(2500); Console.WriteLine("Remaining: " + remaining); Assert.AreEqual(0, remaining); }
private IBrokerage InitializeBrokerage() { Log.Trace(""); Log.Trace("- INITIALIZING BROKERAGE -"); Log.Trace(""); var brokerage = CreateBrokerage(OrderProvider, SecurityProvider); brokerage.Connect(); if (!brokerage.IsConnected) { Assert.Fail("Failed to connect to brokerage"); } Log.Trace(""); Log.Trace("GET OPEN ORDERS"); Log.Trace(""); foreach (var openOrder in brokerage.GetOpenOrders()) { OrderProvider.Add(openOrder); } Log.Trace(""); Log.Trace("GET ACCOUNT HOLDINGS"); Log.Trace(""); foreach (var accountHolding in brokerage.GetAccountHoldings()) { // these securities don't need to be real, just used for the ISecurityProvider impl, required // by brokerages to track holdings SecurityProvider[accountHolding.Symbol] = CreateSecurity(accountHolding.Symbol); } brokerage.OrderStatusChanged += (sender, args) => { Log.Trace(""); Log.Trace("ORDER STATUS CHANGED: " + args); Log.Trace(""); // we need to keep this maintained properly if (args.Status == OrderStatus.Filled || args.Status == OrderStatus.PartiallyFilled) { Log.Trace("FILL EVENT: " + args.FillQuantity + " units of " + args.Symbol.ToString()); Security security; if (_securityProvider.TryGetValue(args.Symbol, out security)) { var holding = _securityProvider[args.Symbol].Holdings; holding.SetHoldings(args.FillPrice, holding.Quantity + args.FillQuantity); } else { _securityProvider[args.Symbol] = CreateSecurity(args.Symbol); _securityProvider[args.Symbol].Holdings.SetHoldings(args.FillPrice, args.FillQuantity); } Log.Trace("--HOLDINGS: " + _securityProvider[args.Symbol]); // update order mapping var order = _orderProvider.GetOrderById(args.OrderId); order.Status = args.Status; } }; return(brokerage); }