}// TryToStop() // // // ********************************************* // **** Filled() **** // ********************************************* public bool Filled(FillEventArgs eventArg) { bool isRepricingRequired = false; if (m_OrderEngine != null) { // Update Fills table with leg fill. Fill newFill = null; //m_OrderEngine.Filled(eventArg); // this is being depercated, in the meantime i am simply commenting out. // Prepare to write to fill database. string attributeString = string.Empty; DateTime localTime = StrategyHub.GetLocalTime(); UV.Lib.DatabaseReaderWriters.Queries.FillsQuery query = new Lib.DatabaseReaderWriters.Queries.FillsQuery(); // Pass the synthetic fill to the pricing engine. if (newFill != null) { // Take snapshot prior to filling strategy. attributeString = m_PricingEngine.GetFillAttributeString(); // get internal state of the pricing engine if it wants to send info with this fill. query.AddItemToWrite(this.SqlId, -1, localTime, m_Services.User, attributeString, newFill.Qty, newFill.Price); // here -1 means "strategy fill" // Inform the pricing engine for strategy fill. m_PricingEngine.Filled(newFill); // pass the fill to the pricing engine. m_PricingEngine.IsUpdateRequired = true; // mark as needing an update isRepricingRequired = true; // remember to call the strategy update method // Take snapshot of the state after filling strategy. attributeString = m_PricingEngine.GetFillAttributeString(); // get internal state of the pricing engine if it wants to send info with this fill. query.AddItemToWrite(this.SqlId, -1, localTime, m_Services.User, attributeString, newFill.Qty, newFill.Price); // here -1 means "strategy fill" attributeString = string.Empty; // if we have written the attribute, lets not write it again. } // Write leg fill to database. int instrumentSqlId = 0; // TODO: From eventArg.InstrumentName somehow determine the SQLID for this instrument. query.AddItemToWrite(SqlId, instrumentSqlId, localTime, m_Services.User, attributeString, eventArg.Fill.Qty, eventArg.Fill.Price); StrategyHub.RequestDatabaseWrite(query); } // Exit return(isRepricingRequired); }// Filled()
// // // // #endregion//Constructors #region no Properties // ***************************************************************** // **** Properties **** // ***************************************************************** // // // // // #endregion//Properties #region Public Methods // ***************************************************************** // **** Public Methods **** // ***************************************************************** // // ***************************************** // **** UpdateQuotes **** // ***************************************** /// <summary> /// Called regularly by the StrategyHub after it has allowed PricingEngines to update /// and possibly change their quotes. This method checks for quote changes, and /// sends them to the OrderEngine. /// Whenever the QuoteEngine's parameters are changed (and it would affect how we quote) /// we should call this method fith forceUpdate=true! /// <param name="forceUpdate">set to to force updating each side of quotes, as is done after fills.</param> /// </summary> public override void UpdateQuotes(bool forceUpdate = false) { if (m_IsQuoteEnabled == false) { // TODO: We could check to exit undistributed fills. return; } ValidateQuoteTables(); // Check whether QuoteTickSize has changed. if (ValidatePosition() == false) { this.IsQuoteEnabled = false; return; } DateTime now = ParentStrategy.StrategyHub.GetLocalTime(); List <Fill> fauxFills = null; List <Quote> fauxQuotesFilled = null; // Update graph if (m_IsGraphEnabled && m_FirstPriceEngine != null) { double bid = m_FirstPriceEngine.ImpliedMarket.Price[0][0]; double ask = m_FirstPriceEngine.ImpliedMarket.Price[1][0]; m_GraphEngine.AddPoint(m_GraphID, "Bid", bid); m_GraphEngine.AddPoint(m_GraphID, "Ask", ask); } for (int tradeSide = 0; tradeSide < 2; tradeSide++) { if (m_IsQuoteSideUpdateRequired[tradeSide] == false && forceUpdate == false) { continue; } // // Collect most aggressive non-zero quoters // int tradeSign = QTMath.MktSideToMktSign(tradeSide); int exitSide = QTMath.MktSideToOtherSide(tradeSide); bool isEntryAllowed = tradeSign * base.m_Position[tradeSide] < m_MaxPosition; // true if new entries allowed. int rawIPrice = 0; int realEntryQty = 0; int realExitQty = 0; List <Quote> simQuotes = m_QuoteListRecycling.Get(); simQuotes.Clear(); foreach (KeyValuePair <int, List <Quote> > kv in m_QuotesByPrice[tradeSide]) { foreach (Quote quote in kv.Value) { int qty; if (isEntryAllowed && quote.Reason == QuoteReason.Entry) { realEntryQty += quote.Qty; // collect real entry quote size } else if (base.m_FillQty[exitSide].TryGetValue(quote.PricingEngine, out qty) && qty != 0) { realExitQty += quote.Qty; // collect real exit quantity } else if (quote.Qty != 0) { simQuotes.Add(quote); // collect other quotes, which will be simulated filled. } } rawIPrice = -tradeSign * kv.Key; // price at this level if (realEntryQty != 0 || realExitQty != 0) { break; // stop, once we have found non-empty quote stop. } } // // Send real quotes. // int tradeId; bool isRealQuoteSent = false; int realTotalQty = realExitQty + realEntryQty; if (realTotalQty != 0) { // There is some non-zero (REAL) quantity to quote. // Constrain REAL quotes inside max position allowed: s*qty <= MaxPos - s*Pos int quoteQtyAllowed = Math.Max(0, m_MaxPosition - tradeSign * base.m_Position[tradeSide]); //always positive realTotalQty = tradeSign * Math.Min(quoteQtyAllowed, Math.Abs(realTotalQty)); if (realTotalQty != 0) { // We want to quote a real qty. int orderQty = realTotalQty + m_BuySellQty[tradeSide]; tradeId = ParentStrategy.m_OrderEngine.Quote(tradeSide, rawIPrice * m_QuoteTickSize, orderQty, string.Empty); isRealQuoteSent = true; if (m_IsGraphEnabled) { m_GraphEngine.AddPoint(m_GraphID, QTMath.MktSideToLongString(tradeSide), rawIPrice * m_QuoteTickSize); } } } if (!isRealQuoteSent) { // If in the above, we have not sent a real order, send a zero quote. int orderQty = m_BuySellQty[tradeSide]; tradeId = ParentStrategy.m_OrderEngine.Quote(tradeSide, rawIPrice * m_QuoteTickSize, orderQty, string.Empty); if (m_IsGraphEnabled) { m_GraphEngine.AddPoint(m_GraphID, QTMath.MktSideToLongString(tradeSide), double.NaN); } } // // Simulate quoting. // if (simQuotes.Count > 0) { foreach (Quote quote in simQuotes) { Fill fill; if (quote.Qty != 0 && FillModels.FillModel.TryFill(quote, out fill)) { if (fauxQuotesFilled == null) { // Only make these tables when we need them! fauxQuotesFilled = m_QuoteListRecycling.Get(); fauxFills = m_FillListRecycling.Get(); } fill.LocalTime = now; fill.ExchangeTime = now; fauxFills.Add(fill); fauxQuotesFilled.Add(quote); } } } simQuotes.Clear(); m_QuoteListRecycling.Recycle(simQuotes); m_IsQuoteSideUpdateRequired[tradeSide] = false; }//next side // // Report simulated fills. // if (fauxFills != null && fauxFills.Count > 0) { Log.BeginEntry(LogLevel.Minor, "Quote Simulating fills: "); for (int i = 0; i < fauxFills.Count; ++i) { Fill fill = fauxFills[i]; Quote quote = fauxQuotesFilled[i]; Log.AppendEntry("[{0} filled {1}] ", quote.PricingEngine.EngineName, fill); } Log.EndEntry(); UV.Lib.DatabaseReaderWriters.Queries.FillsQuery query = new Lib.DatabaseReaderWriters.Queries.FillsQuery(); // Process sim fills. for (int i = 0; i < fauxFills.Count; ++i) { Fill fill = fauxFills[i]; Quote quote = fauxQuotesFilled[i]; quote.Qty -= fill.Qty; string msgStr = quote.FillAttribution(); query.AddItemToWrite(ParentStrategy.SqlId, -1, now, m_FauxUser, quote.PricingEngine.EngineName, msgStr, fill.Qty, fill.Price); quote.PricingEngine.Filled(fill); } if (query != null) { ParentStrategy.StrategyHub.RequestDatabaseWrite(query); } fauxFills.Clear(); m_FillListRecycling.Recycle(fauxFills); fauxQuotesFilled.Clear(); m_QuoteListRecycling.Recycle(fauxQuotesFilled); } }//UpdateQuotes().