// ***************************************************************** // **** Public Methods **** // ***************************************************************** // // // ***************************************************** // **** SubmitToHedger **** // ***************************************************** /// <summary> /// Hedge Manager will call this method asking the hedger to take care of hedging. /// </summary> /// <param name="instr"></param> /// <param name="qty">signed qty for hedge order</param> /// <param name="price"></param> public void SubmitToHedger(ExecutionEngines.OrderEngines.SpreaderLeg instr, int qty, double price) { if (!instr.Equals(m_SpreaderLeg)) { // check that we are submitting to the correct instrument m_Log.NewEntry(LogLevel.Error, "Hedger.SubmitToHedger: Wrong Instrument Has Been Submitted To Hedger"); return; } int stratSign = Math.Sign(qty * m_Spreader.m_LegRatios[m_InternalLegId]); int stratSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(stratSign); if (m_SpreaderLeg.IsMarketGood) { // make sure the market is okay before we send an order. Order hedgeOrder; int orderSign = Math.Sign(qty); int orderSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(orderSign); price += orderSign * m_PayUpTicks * m_SpreaderLeg.InstrumentDetails.TickSize; // if we are using negative pay up ticks we should hedge a better price int iPrice = orderSign * (int)System.Math.Floor(orderSign * price / m_SpreaderLeg.InstrumentDetails.TickSize); // integerized price, using "safe" rounding m_Spreader.m_ExecutionListener.TryCreateOrder(instr.m_PriceLeg.InstrumentName, orderSide, (int)(price / m_SpreaderLeg.InstrumentDetails.TickSize), qty, out hedgeOrder); hedgeOrder.OrderTIF = m_defaultTIF; hedgeOrder.UserDefinedTag = m_NextOrderId; // we are tagging each order so when we modify it we can identify the original order it stemmed from. hedgeOrder.OrderTag = string.Format("{0}:Hedge-{1}", m_Spreader.m_ExecutionContainer.EngineContainerID, m_Spreader.m_OpenSyntheticOrders[stratSide].TradeReason); m_Spreader.m_ExecutionListener.TrySubmitOrder(m_OrderBook.BookID, hedgeOrder); m_HedgeRuleManager.ManageHedgeOrders(); m_Spreader.m_RiskManager.m_TotalNumberOfQuotes++; // increment to count all quotes. } m_IsLegHung[stratSide] = true; // we have submitted a new hedge order and until we get the fill we can assume we are in a hung state m_NextOrderId++; // increment our uniquie hedge count } // SubmitToHedger()
// /// <summary> /// At this point we know all the linkages between engines should be complete. Therefore we can find our hedgers for each leg. /// </summary> public override void SetupComplete() { base.SetupComplete(); if (m_Quoter != null) { m_UnhedgedPartialCount = new double[m_Quoter.m_SpreaderLegs.Count]; // partial count for each instrument. m_PayUpTicks = new int[m_Quoter.m_SpreaderLegs.Count]; m_UseGTCHedge = m_Quoter.m_UseGTCHedge; // allow user to send GTC hedges if desired. if (m_UseGTCHedge) { m_defaultTIF = OrderTIF.GTC; // set our default to GTC } else { m_defaultTIF = OrderTIF.GTD; // set our default to GTD } m_QuoterLegs = new List <ExecutionEngines.OrderEngines.SpreaderLeg>(); m_Hedgers = new List <Hedger>(); for (int leg = 0; leg < m_Quoter.m_SpreaderLegs.Count; ++leg) { // add a hedger for each instrument. ExecutionEngines.OrderEngines.SpreaderLeg quoteLeg = m_Quoter.m_SpreaderLegs[leg]; m_Hedgers.Add(quoteLeg.m_Hedger); // add our new hedger to the list of hedgers m_InstrumentToId.Add(quoteLeg.m_PriceLeg.InstrumentName, m_QuoterLegs.Count); m_QuoterLegs.Add(quoteLeg); quoteLeg.m_Hedger.UseGTCHedge = m_UseGTCHedge; // assign default TIF to our hedger for this leg. quoteLeg.m_Hedger.CompletelyFilled += new EventHandler(Hedger_CompletelyFilled); // susbsribe to events for a hedger being completely filled. } UseGTCHedge = m_UseGTCHedge; } else { throw new Exception("HedgeManager Couldn't Find Quoter"); } }
// ***************************************************************** // **** Public Methods **** // ***************************************************************** // // public virtual void HedgeFill(int quoteInstrId, Fill aFill) { // Get information about quote leg ExecutionEngines.OrderEngines.SpreaderLeg quoteLeg = m_QuoterLegs[quoteInstrId]; int quoteFillQty = aFill.Qty; double quoteFillPrice = aFill.Price; double currentAggressiblePrices = 0; bool isAggressible = false; int[] neededHedgeQty = CalculateNeededHegeQty(quoteInstrId, quoteFillQty); // get our hedge QTY array int stratSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(Math.Sign(quoteFillQty * quoteLeg.m_PriceLeg.Weight)); // find what side of the spread we got filled on if (m_IsSratHung[stratSide] == false) // fire event for our hang state changing. { m_IsSratHung[stratSide] = true; // We are not hedged on this side. OnHangStateChanged(); } double stratPrice = m_Quoter.m_StrategyWorkingPrice[stratSide]; // find what price we are working in the spread if (m_QuoterLegs.Count > 2) // if we are working than 2 or more legs { //we need to check the pricing to see if our prices are still at market. for (int i = 0; i < m_QuoterLegs.Count; i++) { // iterate through other legs to see what pricing we can pick up if we agress if (i == quoteInstrId) //we already are filled here so this price is already known { continue; } currentAggressiblePrices += m_QuoterLegs[i].m_PriceLeg.PriceMultiplier * m_QuoterLegs[i].m_LeanablePrices[UV.Lib.Utilities.QTMath.MktSignToMktSide(stratSide * m_QuoterLegs[i].m_PriceLeg.Weight)]; } // so now we have the price WITHOUT the "quote" leg that we are filled on. So we add // that in and now we can compare the price we can get now with the price we wanted. currentAggressiblePrices += (quoteFillPrice * quoteLeg.m_PriceLeg.PriceMultiplier); if (stratSide == UV.Lib.Utilities.QTMath.BidSide) { isAggressible = currentAggressiblePrices <= stratPrice; } else { isAggressible = currentAggressiblePrices >= stratPrice; } } // Find Hedge Prices and Send Hedge Orders for (int hedgeLegId = 0; hedgeLegId < m_QuoterLegs.Count; hedgeLegId++) { //iterate through each instrument if (hedgeLegId == quoteInstrId) // no need to hedge our quote instrument { continue; } int hedgeQty = neededHedgeQty[hedgeLegId]; // find the qty we need to sell if (hedgeQty != 0) { int orderSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(hedgeQty); int leanSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(hedgeQty * -1); ExecutionEngines.OrderEngines.SpreaderLeg hedgeLeg = m_QuoterLegs[hedgeLegId]; double hedgePrice = 0; if (m_QuoterLegs.Count == 2) { // if our spread is 2 legged we can be very explicit with the pricing hedgePrice = (stratPrice - (quoteFillPrice * quoteLeg.m_PriceLeg.PriceMultiplier)) / hedgeLeg.m_PriceLeg.PriceMultiplier; // without pay up ticks } else { // we have to do something a bit more creative since we have more than 2 legs. // calculate for more than 2 legs // three possbile cases. // 1. the price we want we can get. send hedge orders immediately // 2. we can get a price BETTER than what we want. send hedge orders immediately // 3. we can get only a worse price than the one we want so we need adjust our hedges if (isAggressible) { // situation 1 or 2 hedgePrice = m_QuoterLegs[hedgeLegId].m_LeanablePrices[leanSide]; } else {// TODO: create logic in regards to dealing with three legged hangs. hedgePrice = m_QuoterLegs[hedgeLegId].m_LeanablePrices[leanSide]; } } m_Hedgers[hedgeLegId].SubmitToHedger(hedgeLeg, hedgeQty, hedgePrice); // submit our hedge orders. } } }