}//TryChangeOrderPriceAndQty() // // ********************************************* // **** Try Process Order Update Request() **** // ********************************************* // /// <summary> /// Called by an external thread to process an update request for one /// of our orders. /// </summary> /// <param name="orderUpdateReq"></param> /// <returns></returns> public virtual bool TryProcessOrderUpdateRequest(EventArgs orderUpdateReq) { bool isSuccess = false; if (orderUpdateReq is RequestEventArg <OrderRequestType> ) { RequestEventArg <OrderRequestType> request = (RequestEventArg <OrderRequestType>)orderUpdateReq; InstrumentName instrName = (InstrumentName)request.Data[0]; OrderInstrument orderInstr; if (m_OrderInstruments.TryGetValue(instrName, out orderInstr)) { // we found the order instrument //orderInstr.ProcessRequest(request); isSuccess = true; } else { Log.NewEntry(LogLevel.Warning, "TryProcessOrderUpdateRequest: Order Instrument for {0} not found", instrName); } if (request.Data.Count > 3 && request.Data[3] is Order) // this mean an order is attached to this request. { m_OrderRecycleFactory.Recycle((Order)request.Data[3]); // recycle it here prior to recycling the request } m_OrderRequests.Recycle(request); // recycle all requests } return(isSuccess); }
}// HubEventHandler() // // // ********************************************************************* // **** Process Write Now() **** // ********************************************************************* /// <summary> /// Force a write of the contents of the message queue to the output file now. /// </summary> private void ProcessFlushNow() { if (string.IsNullOrEmpty(this.FilePath) || m_WriteQueue.Count == 0) { return; } if (Log != null) { Log.NewEntry(LogLevel.Minor, "{0}.ProcessFlushNow: ", this.m_HubName); } try { using (System.IO.StreamWriter writer = new System.IO.StreamWriter(this.FilePath, true, Encoding.ASCII)) { DropQueueWriterEventArgs e; while (m_WriteQueue.TryDequeue(out e)) { writer.WriteLine(e.Message); m_Factory.Recycle(e); } writer.Close(); }//using StreamWriter } catch (Exception e) { if (Log != null) { Log.NewEntry(LogLevel.Error, "{0}: Exception writing to drop file. {1}", this.m_HubName, e.Message); } } }// ProcessWriteNow().
// // #endregion//Constructors #region no Properties // ***************************************************************** // **** Properties **** // ***************************************************************** // // #endregion//Properties #region Public Methods // ***************************************************************** // **** Public Methods **** // ***************************************************************** // // // // ************************************************* // **** SendMessage() **** // ************************************************* /// <summary> /// Simple method to send a Message to a specific ServiceManager /// on a specific socket conversation. /// </summary> /// <param name="conversationId">Conversation to send message on, -1 means all conversations.</param> /// <param name="msg"></param> /// <returns></returns> public bool SendMessage(int conversationId, Message msg) { string s = string.Format("{0}\n", Stringifiable.Stringify(msg, null, false)); m_Messages.Recycle(msg); if (conversationId >= 0) { return(m_Socket.Send(s, conversationId)); } else { return(m_Socket.Send(s)); } }
// // #endregion//Constructors #region Hub Event Handler Overrides // ***************************************************************** // **** Hub Event Handler **** // ***************************************************************** // // // // // ******************************************************* // **** HubEvent Handler **** // ******************************************************* protected override void HubEventHandler(EventArgs[] eventArgList) { foreach (EventArgs eventArg in eventArgList) { Type eArgType = eventArg.GetType(); if (eArgType == typeof(DataHubRequest)) { DataHubRequest requestArg = (DataHubRequest)eventArg; switch (requestArg.Request) { case RequestCode.ServiceStateChange: // Process this! break; case RequestCode.Connect: // Process this! break; case RequestCode.RequestProductsToRecord: ProcessProductsToRecord(requestArg); break; default: Log.NewEntry(LogLevel.Error, "HubEventHandler: DataHubRequest {0} not implemented", requestArg.ToString()); break; }//switch(Request) m_RequestFactory.Recycle(requestArg); } else if (eArgType == typeof(FoundServiceEventArg)) { ProcessFoundResources((FoundServiceEventArg)eventArg); } else if (eArgType == typeof(DatabaseWriterEventArgs)) { Log.NewEntry(LogLevel.Major, "Write Completed {0}", eArgType.ToString()); } else if (eArgType == typeof(MarketStatusChangedEventArg)) { ProcessMarketStatusChangedEvent((MarketStatusChangedEventArg)eventArg); } else if (eArgType == typeof(DatabaseWriterHub.WriteStatusEventArgs)) { Log.NewEntry(LogLevel.Major, "Write Status {0}", eArgType.ToString()); } else { // unknown event. Log.NewEntry(LogLevel.Error, "Unknown event type {0}", eArgType.ToString()); } } }//end HubEvent
}// MarketInstrumentChanged() // // // // // ***************************************************** // **** Process Synthetic Order() **** // ***************************************************** /// <summary> /// Process fills from Strategy to PricingEngines. /// </summary> /// <param name="syntheticOrder"></param> /// <param name="newFills"></param> /// <returns>True if update required</returns> public virtual bool ProcessSyntheticOrder(SyntheticOrder syntheticOrder, List <Fill> newFills) { if (newFills == null || newFills.Count == 0) { return(false); } // Collect all fills into work spaces. Log.BeginEntry(LogLevel.Major, "Quote.ProcessSynthOrder: {0} Fills=", ParentStrategy.Name); w_NewFills[0].Clear(); w_NewFills[1].Clear(); foreach (Fill fill in newFills) { int tradeSide = QTMath.MktSignToMktSide(fill.Qty); w_NewFills[tradeSide].Add(fill); m_BuySellQty[tradeSide] += fill.Qty; // this records the raw fills as they come in. Log.AppendEntry(" [{0}]", fill); } int[] position = new int[2]; // this will be updated during allocation of fills. m_Position.CopyTo(position, 0); Log.AppendEntry(". "); // Prepare entry for database write. DateTime localTime = ParentStrategy.StrategyHub.GetLocalTime(); UV.Lib.DatabaseReaderWriters.Queries.FillsQuery query = new Lib.DatabaseReaderWriters.Queries.FillsQuery(); // ----------------------------------------------------- // Pass: distribute fills to stops // ----------------------------------------------------- for (int tradeSide = 0; tradeSide < 2; ++tradeSide) { int exitingSide = QTMath.MktSideToActiveMktSide(tradeSide); if (w_NewFills[tradeSide].Count == 0 || m_FillQty[exitingSide].Count == 0) { continue; } List <Quote> exitList = m_QuoteListRecycling.Get(); // get empty list. exitList.Clear(); foreach (KeyValuePair <PricingEngine, int> kv in m_FillQty[exitingSide]) { Quote quote; if (m_Quotes[tradeSide].TryGetValue(kv.Key, out quote) && quote.Reason == QuoteReason.Stop && quote.Qty != 0) { exitList.Add(quote); } } if (exitList.Count > 0) { Log.AppendEntry(" Distribute to {0} stop quoters:", exitList.Count); DistributeFillsToQuoters(ref w_NewFills[tradeSide], ref exitList, ref query, ref w_DistributedFills, ref position); Log.AppendEntry(". "); } exitList.Clear(); m_QuoteListRecycling.Recycle(exitList); }//next tradeSide // ----------------------------------------------------- // Pass: distribute fills to quoters who want them. // ----------------------------------------------------- for (int tradeSide = 0; tradeSide < 2; ++tradeSide) { if (w_NewFills[tradeSide].Count == 0) { continue; } int exitingSide = QTMath.MktSideToOtherSide(tradeSide); int tradeSign = QTMath.MktSideToMktSign(tradeSide); List <Quote> quotesToFill = m_QuoteListRecycling.Get(); // get empty lists for entry quotes. Log.AppendEntry(" Distribute to working quoters"); List <int> iPriceKeys = new List <int>(m_QuotesByPrice[tradeSide].Keys); int priceLevel = 0; while (w_NewFills[tradeSide].Count > 0 && priceLevel < iPriceKeys.Count) { // On each interation, update our "pos" so we know the remaining qty. int allowedEntryQty = tradeSign * Math.Max(0, m_MaxPosition - Math.Abs(position[tradeSide])); // Load entry/exit quoters for this price level. Log.AppendEntry(" lvl={0}/{1}:", priceLevel, iPriceKeys.Count); quotesToFill.Clear(); List <Quote> quotes = null; if (m_QuotesByPrice[tradeSide].TryGetValue(iPriceKeys[priceLevel], out quotes)) { foreach (Quote quote in quotes) { if (quote.Qty != 0) { quotesToFill.Add(quote); } } } if (quotesToFill.Count > 0) { Log.AppendEntry(" Filling ({0}):", quotesToFill.Count); DistributeFillsToQuoters(ref w_NewFills[tradeSide], ref quotesToFill, ref query, ref w_DistributedFills, ref position); } // priceLevel++; }// next price level // Clean up. quotesToFill.Clear(); m_QuoteListRecycling.Recycle(quotesToFill); Log.AppendEntry(" Finished."); if (w_NewFills[tradeSide].Count > 0) { Log.AppendEntry(" {0} fills remaining.", w_NewFills[tradeSide].Count); } else { Log.AppendEntry(" No fills remain."); } }//tradeSide // ----------------------------------------------------- // Start emergency processing! // ----------------------------------------------------- if (w_NewFills[0].Count > 0 || w_NewFills[1].Count > 0) { Log.AppendEntry(" Process unwanted fills!"); ProcessUnwantedFills(ref w_NewFills, ref w_DistributedFills); } Log.EndEntry(); // end logging for us now, before we call other methods. // ----------------------------------------------------- // Distribute these fills now. // ----------------------------------------------------- if (query != null && query.Count != 0) { ParentStrategy.StrategyHub.RequestDatabaseWrite(query); // submit all the queries } foreach (KeyValuePair <Quote, List <Fill> > kv in w_DistributedFills) { int fillQty = 0; double fillPrice = 0; foreach (Fill fill in kv.Value) { fillQty += fill.Qty; fillPrice = fill.Price; // TODO: this should be ave fill price } int tradeSide = QTMath.MktSignToMktSide(fillQty); int exitSide = QTMath.MktSideToOtherSide(tradeSide); if (fillQty == 0) { continue; } // Update our position counting. int openPos = 0; if (m_FillQty[exitSide].TryGetValue(kv.Key.PricingEngine, out openPos)) { // This is an exit (since this PricingEngine has open position on other side of mkt). openPos += fillQty; // Update real position table. if (openPos * fillQty <= 0) { m_FillQty[exitSide].Remove(kv.Key.PricingEngine);// complete exit, possibly a side flip } if (openPos != 0) { // There is a new position (on other side of mkt). int posSide = QTMath.MktSignToMktSide(openPos); m_FillQty[posSide][kv.Key.PricingEngine] = openPos; } } else { // This is an entry! // Update real position table. if (m_FillQty[tradeSide].ContainsKey(kv.Key.PricingEngine)) { m_FillQty[tradeSide][kv.Key.PricingEngine] += fillQty; // add to this engines position. } else { m_FillQty[tradeSide].Add(kv.Key.PricingEngine, fillQty); // store this engines position. } } // Trigger the pricing engine filled event! foreach (Fill fill in kv.Value) { kv.Key.PricingEngine.Filled(fill); } }// next filled Quote. // Update total sum Log.BeginEntry(LogLevel.Major, "Quote.ProcessSynthOrder {0} Summary: ", ParentStrategy.Name); for (int tradeSide = 0; tradeSide < 2; tradeSide++) { // Add up the current position. int pos = 0; foreach (KeyValuePair <PricingEngine, int> kv in m_FillQty[tradeSide]) { pos += kv.Value; } m_Position[tradeSide] = pos; // Write some logging. Log.AppendEntry(" {0}-side:", QTMath.MktSideToLongString(tradeSide)); Log.AppendEntry(" Pos={0:+0;-0;0}", m_Position[tradeSide]); foreach (KeyValuePair <PricingEngine, int> kv in m_FillQty[tradeSide]) { Log.AppendEntry(" [{1:+0;-0;0} {0}]", kv.Key.EngineName, kv.Value); } Log.AppendEntry(" TotalQty={0}", m_BuySellQty[tradeSide]); // Log undistributed fills too. if (m_UndistributedFills[tradeSide].Count > 0) { Log.AppendEntry(" Undistributed {0}-fills:", QTMath.MktSideToLongString(tradeSide)); foreach (Fill fill in m_UndistributedFills[tradeSide]) { Log.AppendEntry(" {0}", fill); } } }// next tradeSide Log.AppendEntry(" |MaxPos|={0}.", m_MaxPosition); Log.EndEntry(); // // Clean up work spaces // foreach (KeyValuePair <Quote, List <Fill> > kv in w_DistributedFills) { kv.Value.Clear(); m_FillListRecycling.Recycle(kv.Value); } w_DistributedFills.Clear(); // Quoters and their fills to distribute. return(true); }// ProcessSyntheticOrder()