public static bool InstrumentTypeToSecurityType(OQ.InstrumentType instrType, out IB.SecurityType secType) { secType = SecurityType.Undefined; switch (instrType) { case InstrumentType.Bond: secType = SecurityType.Bond; break; case InstrumentType.ETF: secType = SecurityType.Stock; break; case InstrumentType.FX: secType = SecurityType.Cash; break; case InstrumentType.FutOpt: secType = SecurityType.FutureOption; break; case InstrumentType.Futures: secType = SecurityType.Future; break; case InstrumentType.Index: secType = SecurityType.Index; break; case InstrumentType.Option: secType = SecurityType.Option; break; case InstrumentType.Stock: secType = SecurityType.Stock; break; case InstrumentType.MultiLeg: default: return false; } return true; }
public static bool FAAllocationMethodTOIBFAMethod(IB.FinancialAdvisorAllocationMethod ibFaMethod, out OQ.IBFaMethod oqFaMethod) { oqFaMethod = IBFaMethod.Undefined; switch (ibFaMethod) { case FinancialAdvisorAllocationMethod.AvailableEquity: oqFaMethod = IBFaMethod.AvailableEquity; break; case FinancialAdvisorAllocationMethod.EqualQuantity: oqFaMethod = IBFaMethod.EqualQuantity; break; case FinancialAdvisorAllocationMethod.NetLiquidity: oqFaMethod = IBFaMethod.NetLiq; break; case FinancialAdvisorAllocationMethod.PercentChange: oqFaMethod = IBFaMethod.PctChange; break; case FinancialAdvisorAllocationMethod.None: default: return false; } return true; }
public SrOrderInfo(OQ.Order oqorder, SrOrderInfoState state = SrOrderInfoState.New) { this.oqorder = oqorder; this.state = state; }
public DateTime SubmittedDate = DateTime.MaxValue; // form IB to Exchange #endregion Fields #region Constructors public SrOrder(OQ.Order oqorder) { this.oqorder = oqorder; }
public static bool OrderTypeToOrderType(IB.OrderType ibordertype, out OQ.OrderType oqordertype) { oqordertype = OQ.OrderType.Market; switch (ibordertype) { case IB.OrderType.Limit: case IB.OrderType.LimitOnClose: oqordertype = OQ.OrderType.Limit; break; case IB.OrderType.Market: oqordertype = OQ.OrderType.Market; break; case IB.OrderType.MarketOnClose: oqordertype = OQ.OrderType.MarketOnClose; break; case IB.OrderType.Stop: oqordertype = OQ.OrderType.Stop; break; case IB.OrderType.StopLimit: oqordertype = OQ.OrderType.StopLimit; break; case IB.OrderType.TrailingStop: oqordertype = OQ.OrderType.Trail; break; case IB.OrderType.TrailingStopLimit: oqordertype = OQ.OrderType.TrailLimit; break; default: case IB.OrderType.Volatility: case IB.OrderType.VolumeWeightedAveragePrice: case IB.OrderType.Scale: case IB.OrderType.Relative: case IB.OrderType.PeggedToMarket: case IB.OrderType.Default: case IB.OrderType.Empty: return false; } return true; }
public static bool OQTimeInForceToIBTimeInForce(OQ.TimeInForce oqtif, out IB.TimeInForce ibtif) { ibtif = IB.TimeInForce.Undefined; switch (oqtif) { case OQ.TimeInForce.Day: ibtif = IB.TimeInForce.Day; break; case OQ.TimeInForce.FOK: ibtif = IB.TimeInForce.FillOrKill; break; case OQ.TimeInForce.GTC: ibtif = IB.TimeInForce.GoodTillCancel; break; case OQ.TimeInForce.GTD: ibtif = IB.TimeInForce.GoodTillDate; break; case OQ.TimeInForce.OPG: ibtif = IB.TimeInForce.MarketOnOpen; break; case OQ.TimeInForce.ATC: case OQ.TimeInForce.GFS: case OQ.TimeInForce.GTX: case OQ.TimeInForce.IOC: default: return false; } return true; }
public static bool OrderStateToOrderStatus(IB.OrderStatus ibstatus, out OQ.OrderStatus status) { status = OQ.OrderStatus.New; switch (ibstatus) { case IB.OrderStatus.ApiCancelled: case IB.OrderStatus.Canceled: status = OQ.OrderStatus.Cancelled; break; case IB.OrderStatus.Inactive: case IB.OrderStatus.ApiPending: case IB.OrderStatus.PendingSubmit: case IB.OrderStatus.PreSubmitted: case IB.OrderStatus.Submitted: status = OQ.OrderStatus.PendingNew; break; case IB.OrderStatus.Filled: status = OQ.OrderStatus.Filled; break; case IB.OrderStatus.PartiallyFilled: status = OQ.OrderStatus.PartiallyFilled; break; case IB.OrderStatus.PendingCancel: status = OQ.OrderStatus.PendingCancel; break; default: case IB.OrderStatus.Unknown: return false; } return true; }
public static bool OQFAMethodTOIBFAMethod(OQ.IBFaMethod oqFaMethod, out IB.FinancialAdvisorAllocationMethod ibFaMethod) { ibFaMethod = FinancialAdvisorAllocationMethod.None; switch (oqFaMethod) { case IBFaMethod.AvailableEquity: ibFaMethod = FinancialAdvisorAllocationMethod.AvailableEquity; break; case IBFaMethod.EqualQuantity: ibFaMethod = FinancialAdvisorAllocationMethod.EqualQuantity; break; case IBFaMethod.NetLiq: ibFaMethod = FinancialAdvisorAllocationMethod.NetLiquidity; break; case IBFaMethod.PctChange: ibFaMethod = FinancialAdvisorAllocationMethod.PercentChange; break; case IBFaMethod.Undefined: ibFaMethod = FinancialAdvisorAllocationMethod.None; break; default: return false; } return true; }
public static bool OQOrderTypeToIBOrderType(OQ.OrderType oqtype, out IB.OrderType ibtype) { ibtype = IB.OrderType.Empty; switch (oqtype) { case OQ.OrderType.Limit: ibtype = IB.OrderType.Limit; break; case OQ.OrderType.Market: ibtype = IB.OrderType.Market; break; case OQ.OrderType.MarketOnClose: ibtype = IB.OrderType.MarketOnClose; break; case OQ.OrderType.Stop: ibtype = IB.OrderType.Stop; break; case OQ.OrderType.StopLimit: ibtype = IB.OrderType.StopLimit; break; case OQ.OrderType.Trail: ibtype = IB.OrderType.TrailingStop; break; case OQ.OrderType.TrailLimit: ibtype = IB.OrderType.TrailingStopLimit; break; default: return false; } return true; }
protected override void Send(OQ.Order order) { Send2(order); }
/// <summary> /// there is no Replace method available with the IB API so we do a cancel followed by a new Send /// all sorts of things may happen between the cancel and the send, so let's do this carefully. /// </summary> /// <param name="order"></param> /// <param name="newQty"></param> /// <param name="newPrice"></param> /// <param name="newStopPrice"></param> protected override void Replace(OQ.Order order, double newQty, double newPrice, double newStopPrice) { tStart("Replace OrderID=" + order.OrderID); if (!CheckTWS()) return; if (!IsConnected) { EmitError("Not connected."); return; } if (!workingOrders.ContainsKey(order.OrderID)) { error("order not found"); EmitReplaceReject(order, OQ.OrderStatus.Rejected, "unknown order"); } // check if newQty is still possible if (order.CumQty > newQty) { EmitReplaceReject(order, OQ.OrderStatus.Rejected, "can't change quantity below number of already filled shares"); return; } EmitPendingReplace(order); // add to list of orders tracked through the replace states workingOrders[order.OrderID].state = SrOrderInfoState.ReplaceCancel; workingOrders[order.OrderID].newQty = newQty; workingOrders[order.OrderID].newPrice = newPrice; workingOrders[order.OrderID].newStopPrice = newStopPrice; // 1. Cancel Order Cancel(order); tEnd("Replace OrderID=" + order.OrderID); }
protected override void Cancel(OQ.Order order) { if (!CheckTWS()) return; if (!IsConnected) { EmitError("Not connected."); return; } // TODO: TryParse int orderId = int.Parse(order.OrderID); ibclient.CancelOrder(orderId); }
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); }
private void ReportFill(OQ.Order oqorder, int filled, int remaining, double lastFillPrice) { //info("ReportFill: Order vor Fill " + oqorder.Instrument.Symbol // + " Id=" + oqorder.OrderID // + ", CumQty=" + oqorder.CumQty // + ", Qty=" + oqorder.Qty // + ", LastQty=" + oqorder.LastQty // + ", LeavesQty=" + oqorder.LeavesQty); // in order the current fill state is stored: // oqorder.Qty: overall/planne order size. does not change with fills // oqorder.CumQty: sum of all fills, increases with every fill after EmitFill: oqorder.CumQty == e.Filled // oqorder.LeavesQty: remaining shares after fill. oqorder.LeavesQty := Qty - CumQty int fillqty = filled - (int)Math.Round(oqorder.CumQty); if (fillqty > 0) { EmitFilled(oqorder, lastFillPrice, fillqty); if (fillqty != (int)Math.Round(oqorder.LastQty)) { error("Bad Fill State in order " + oqorder.Instrument.Symbol + ", OrderId=" + oqorder.OrderID + ": after fill: FillQty(" + fillqty + ") != OQ.LastQty(" + oqorder.LastQty + ")"); } } // check fill state if (filled != (int)Math.Round(oqorder.CumQty)) { error("Bad Fill State in order " + oqorder.Instrument.Symbol + ", OrderId=" + oqorder.OrderID + ": after fill: IB.Filled(" + filled + ") != OQ.CumQty(" + oqorder.CumQty + ")"); } if (remaining != (int)Math.Round(oqorder.LeavesQty)) { error("Bad Fill State in order " + oqorder.Instrument.Symbol + ", OrderId=" + oqorder.OrderID + ": after fill: IB.Remaining(" + remaining + ") != OQ.LeavesQty(" + oqorder.LeavesQty + ")"); } //info("ReportFill: Order nach Fill fillqty=" + fillqty + " " + oqorder.Instrument.Symbol // + " Id=" + oqorder.OrderID // + ", CumQty=" + oqorder.CumQty // + ", Qty=" + oqorder.Qty // + ", LastQty=" + oqorder.LastQty // + ", LeavesQty=" + oqorder.LeavesQty); }