private void AcceptOrder(int orderId, IB.Contract contract, IB.Order order) { int filled = 0; int remaining = order.TotalQuantity; // Accept mockIBClient.Raise(ib => ib.OrderStatus += null, new OrderStatusEventArgs(orderId, IB.OrderStatus.Submitted, filled, remaining, (decimal)order.LimitPrice, 333333, 0, (decimal)0.0, order.ClientId, "")); }
public bool MatchOrders(IB.Order expected, IB.Order actual) { Assert.AreEqual(expected.Account, actual.Account, "Order.Account"); Assert.AreEqual(expected.Action, actual.Action, "Order.Action"); Assert.AreEqual(expected.ClientId, actual.ClientId, "Order.ClientId"); Assert.AreEqual(expected.OcaGroup, actual.OcaGroup, "Order.OcaGroup"); Assert.AreEqual(expected.OrderId, actual.OrderId, "Order.OrderId"); Assert.AreEqual(expected.TotalQuantity, actual.TotalQuantity, "Order.TotalQuantity"); Assert.AreEqual((double)expected.LimitPrice, (double)actual.LimitPrice, 0.05, "Order.LimitPrice"); Assert.AreEqual((double)expected.AuxPrice, (double)actual.AuxPrice, 0.005, "Order.AuxPrice"); Assert.AreEqual(expected.Tif, actual.Tif, "Order.Tif"); Assert.AreEqual(expected.OrderType, actual.OrderType, "Order.OrderType"); return(true); }
public void SendTest() { // Arrange OQ.Order order = CreateOQOrder(456); // Accept and Fill Order mockIBClient.Setup(ib => ib.PlaceOrder(It.IsAny<int>(), It.IsAny<IB.Contract>(), It.IsAny<IB.Order>())) .Callback((int id, IB.Contract ctr, IB.Order ord) => AcceptAndFillOrder(id, ctr, ord)); target.Send(order); // Act // info PlaceOrder string expected_text = @"PlaceOrder.ID=42, Orderref=, Symbol=OQOQ, Action=Buy, Size=456, OrderType=Limit, limit price=12.34, Aux price=45.57."; logger.Verify(log => log.AddLog(LoggerLevel.Information, It.IsRegex(expected_text))); // expected contract Contract exp_contract = new Contract(); exp_contract.Currency = "CHF"; exp_contract.Exchange = "Brasil"; exp_contract.SecurityType = SecurityType.Stock; exp_contract.Symbol = "OQOQ"; // expected order IB.Order exp_iborder = new IB.Order(); exp_iborder.Account = "U111"; exp_iborder.ClientId = 9876; // must come from Settings exp_iborder.OcaGroup = "MyOCA"; exp_iborder.OrderId = 42; exp_iborder.TotalQuantity = 456; exp_iborder.Action = ActionSide.Buy; exp_iborder.AuxPrice = (decimal)45.57; exp_iborder.LimitPrice = (decimal)12.34; exp_iborder.Tif = Krs.Ats.IBNet96.TimeInForce.GoodTillCancel; exp_iborder.OrderType = OrderType.Limit; mockIBClient.Verify(ib => ib.PlaceOrder(42, It.Is<IB.Contract>(ctr => MatchContracts(exp_contract, ctr)), It.Is<IB.Order>(ord => MatchOrders(exp_iborder, ord)))); // check Info returned in OQ.Order Assert.AreEqual("42", order.OrderID); Assert.AreEqual("9876", order.ClientID); // from Settings / StingrayOQ.ClientId Property // ibclient_OrderStatus logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* ibclient_OrderStatus.*"))); logger.Verify(log => log.AddLog(LoggerLevel.Information, "ibclient_OrderStatus: received from TWS ID: 42, ClientID: 9876, Filled: 0, Remaining: 456, Status: Submitted")); // OnOrderAccepted logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* OnOrderAccepted"))); userProvider.Verify(up => up.EmitAccepted(It.Is<OQ.Order>(ord => ord.OrderID == "42"))); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* OnOrderAccepted"))); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* ibclient_OrderStatus.*"))); // OnOrderFilled logger.Verify(log => log.AddLog(LoggerLevel.Information, "ibclient_OrderStatus: received from TWS ID: 42, ClientID: 9876, Filled: 456, Remaining: 0, Status: Filled")); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* OnOrderFilled"))); userProvider.Verify(up => up.EmitFilled(It.Is<OQ.Order>(ord => ord.OrderID == "42"), 12.34, 456)); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* OnOrderFilled"))); // never saw an error? logger.Verify(log => log.AddLog(LoggerLevel.Error, It.IsAny<string>()), Times.Never(), "unexpected error log"); }
public void SendTest() { // Arrange OQ.Order order = CreateOQOrder(456); // Accept and Fill Order mockIBClient.Setup(ib => ib.PlaceOrder(It.IsAny <int>(), It.IsAny <IB.Contract>(), It.IsAny <IB.Order>())) .Callback((int id, IB.Contract ctr, IB.Order ord) => AcceptAndFillOrder(id, ctr, ord)); target.Send(order); // Act // info PlaceOrder string expected_text = @"PlaceOrder.ID=42, Orderref=, Symbol=OQOQ, Action=Buy, Size=456, OrderType=Limit, limit price=12.34, Aux price=45.57."; logger.Verify(log => log.AddLog(LoggerLevel.Information, It.IsRegex(expected_text))); // expected contract Contract exp_contract = new Contract(); exp_contract.Currency = "CHF"; exp_contract.Exchange = "Brasil"; exp_contract.SecurityType = SecurityType.Stock; exp_contract.Symbol = "OQOQ"; // expected order IB.Order exp_iborder = new IB.Order(); exp_iborder.Account = "U111"; exp_iborder.ClientId = 9876; // must come from Settings exp_iborder.OcaGroup = "MyOCA"; exp_iborder.OrderId = 42; exp_iborder.TotalQuantity = 456; exp_iborder.Action = ActionSide.Buy; exp_iborder.AuxPrice = (decimal)45.57; exp_iborder.LimitPrice = (decimal)12.34; exp_iborder.Tif = Krs.Ats.IBNet96.TimeInForce.GoodTillCancel; exp_iborder.OrderType = OrderType.Limit; mockIBClient.Verify(ib => ib.PlaceOrder(42, It.Is <IB.Contract>(ctr => MatchContracts(exp_contract, ctr)), It.Is <IB.Order>(ord => MatchOrders(exp_iborder, ord)))); // check Info returned in OQ.Order Assert.AreEqual("42", order.OrderID); Assert.AreEqual("9876", order.ClientID); // from Settings / StingrayOQ.ClientId Property // ibclient_OrderStatus logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* ibclient_OrderStatus.*"))); logger.Verify(log => log.AddLog(LoggerLevel.Information, "ibclient_OrderStatus: received from TWS ID: 42, ClientID: 9876, Filled: 0, Remaining: 456, Status: Submitted")); // OnOrderAccepted logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* OnOrderAccepted"))); userProvider.Verify(up => up.EmitAccepted(It.Is <OQ.Order>(ord => ord.OrderID == "42"))); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* OnOrderAccepted"))); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* ibclient_OrderStatus.*"))); // OnOrderFilled logger.Verify(log => log.AddLog(LoggerLevel.Information, "ibclient_OrderStatus: received from TWS ID: 42, ClientID: 9876, Filled: 456, Remaining: 0, Status: Filled")); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("START.* OnOrderFilled"))); userProvider.Verify(up => up.EmitFilled(It.Is <OQ.Order>(ord => ord.OrderID == "42"), 12.34, 456)); logger.Verify(log => log.AddLog(LoggerLevel.Detail, It.IsRegex("END.* OnOrderFilled"))); // never saw an error? logger.Verify(log => log.AddLog(LoggerLevel.Error, It.IsAny <string>()), Times.Never(), "unexpected error log"); }
private void Send2(OQ.Order order, double newQty = double.NaN, double newPrice = double.NaN, double newStopPrice = double.NaN) { if (!CheckTWS()) return; if (!IsConnected) { EmitError("Not connected."); return; } // check Account if(activeAccounts.Count > 1) { if(string.IsNullOrWhiteSpace(order.Account)) { throw new Exception("no account specified"); } } int orderId; Contract contract = new Contract(); IB.Order iborder = new IB.Order(); // OrderId int nextId; lock (private_lock) { nextId = nextValidId; nextValidId++; } iborder.OrderId = nextId; // Order Attributes iborder.Account = order.Account; IB.ActionSide ibaction; if (!Helpers.OrderSideToActionSide(order.Side, out ibaction)) // Buy / Sell { error("unknown order side in Order " + order.Instrument.Symbol); return; } iborder.Action = ibaction; if (!double.IsNaN(newStopPrice)) iborder.AuxPrice = (decimal) newStopPrice; else iborder.AuxPrice = (decimal)order.StopPrice; // stop orders only iborder.ClientId = ClientId; IB.FinancialAdvisorAllocationMethod faMethod; if (order.IB.FaMethod == IBFaMethod.Undefined) // use Order Defaults form Settings { iborder.FAMethod = FAMethod; iborder.FAGroup = FAGroup; iborder.FAPercentage = FAPercentage; iborder.FAProfile = FAProfile; } else { if (!Helpers.OQFAMethodTOIBFAMethod(order.IB.FaMethod, out faMethod)) { error("bad FA allocation method in order " + order.Instrument.Symbol); } iborder.FAMethod = faMethod; iborder.FAGroup = order.IB.FaGroup; iborder.FAPercentage = order.IB.FaPercentage.ToString(); iborder.FAProfile = order.IB.FaProfile; OQ.IBFaMethod oqfamethod; if (!Helpers.FAAllocationMethodTOIBFAMethod(iborder.FAMethod, out oqfamethod)) { error("unknown FA allocation method in settings"); } order.IB.FaMethod = oqfamethod; order.IB.FaGroup = iborder.FAGroup; if (iborder.FAPercentage == "") order.IB.FaPercentage = 0.0; else order.IB.FaPercentage = double.Parse(iborder.FAPercentage, CultureInfo.InvariantCulture); order.IB.FaProfile = order.IB.FaProfile; } // iborder.GoodAfterTime = order.StrategyPrice?? // iborder.GoodTillDate = order.ExpireTime; iborder.Hidden = order.IB.Hidden; if (!double.IsNaN(newPrice)) iborder.LimitPrice = (decimal)newPrice; else iborder.LimitPrice = (decimal)order.Price; // iborder.MinQty // iborder.NbboPriceCap // = order.IB.DisplaySize; iborder.OcaGroup = order.OCAGroup; IB.OrderType ibtype; if (!Helpers.OQOrderTypeToIBOrderType(order.Type, out ibtype)) { error("bad order type in order " + order.Instrument.Symbol); return; } iborder.OrderType = ibtype; // iborder.Origin // iborder.OutsideRth = order.??? // iborder.OverridePercentageConstraints = ??? // iborder.ParentId // iborder.PercentOffset // iborder.PermId // iborder.ReferencePriceType // iborder.Rule80A // iborder.StartingPrice // iborder.StockRangeLower // iborder.StockRangeUpper // iborder.StockRefPrice // iborder.SweepToFill IB.TimeInForce ibtif; if (!Helpers.OQTimeInForceToIBTimeInForce(order.TimeInForce, out ibtif)) { error("unknown time in force in order " + order.Instrument.Symbol); return; } iborder.Tif = ibtif; if (!double.IsNaN(newQty)) iborder.TotalQuantity = (int) Math.Round(newQty); else iborder.TotalQuantity = (int)Math.Round(order.Qty); // iborder.TrailStopPrice = order.??? iborder.Transmit = AutoTransmit; // iborder.TriggerMethod // iborder.Volatility // iborder.VolatilityType // iborder.WhatIf // Contract // contract.ComboLegs // contract.ComboLegsDescription // contract.ContractId contract.Currency = order.Instrument.Currency; contract.Exchange = order.Instrument.Exchange; contract.Expiry = order.Instrument.Maturity.ToString("yyyyMM"); // YYYYMM // contract.IncludeExpired // contract.LocalSymbol contract.Multiplier = order.Instrument.Factor.ToString(); // contract.PrimaryExchange // contract.Right // contract.SecId IB.SecurityType secType; if (!Helpers.InstrumentTypeToSecurityType(order.Instrument.Type, out secType)) { error("bad instrument type in order " + order.Instrument.Symbol); } contract.SecurityType = secType; contract.Strike = order.Instrument.Strike; contract.Symbol = order.Instrument.Symbol; // contract.UnderlyingComponent // parse advanced order attributes if (!string.IsNullOrWhiteSpace(order.Text)) { string[] fields = order.Text.Split(';'); foreach(string field in fields) { if (!field.Contains("=") && !field.Contains(":")) continue; string[] nameval = field.Split(new char[] {'=', ':'}); string name = nameval[0].Trim().ToLower(); string value = nameval[1].Trim(); switch(name) { case "orderref": iborder.OrderRef = value; break; default: error("unknown name \"" + name + "\" in text of order " + order.Instrument.Symbol); break; } } } // send to TWS info("PlaceOrder(" + "ID=" + iborder.OrderId.ToString() + ", Orderref=" + (iborder.OrderRef ?? "") + ", Symbol=" + contract.Symbol + ", Action=" + iborder.Action.ToString() + ", Size=" + iborder.TotalQuantity.ToString() + ", OrderType=" + iborder.OrderType.ToString() + ", limit price=" + iborder.LimitPrice.ToString() + ", Aux price=" + iborder.AuxPrice.ToString() + ")"); // Set Infos back to OQ.Order order.OrderID = iborder.OrderId.ToString(); order.ClientID = iborder.ClientId.ToString(); // Remember active orders workingOrders[iborder.OrderId.ToString()] = new SrOrderInfo(order); // finally send to broker ibclient.PlaceOrder(iborder.OrderId, contract, iborder); }