// // // protected void OnSyntheticSpreadFilled(FillEventArgs fillEventArgs) { if (this.SyntheticSpreadFilled != null) { this.SyntheticSpreadFilled(this, fillEventArgs); } }
// // // ************************************* // **** TryProcessFill **** // ************************************* /// <summary> /// Caller would like to process a confirmed fill from the exchange /// False only if the order isn't found. /// </summary> /// <param name="fillEvent"></param> /// <returns></returns> public bool TryProcessFill(FillEventArgs fillEvent) { Order orderToModify; if (m_OrdersById.TryGetValue(fillEvent.OrderId, out orderToModify)) { orderToModify.ExecutedQty += fillEvent.Fill.Qty; if (fillEvent.isComplete) { orderToModify.ChangesPending = false; m_ParentOrderBook.TryDelete(fillEvent.OrderId); // this will set state. } // Trigger fill event fillEvent.OrderBookID = m_ParentOrderBook.BookID; // assign the correct id now that we know it. fillEvent.OrderReason = orderToModify.OrderReason; // also pass along tag. m_ParentOrderBook.OnOrderFilled(fillEvent); // fire fill event for my subscribers // Trigger order state change OrderEventArgs orderEvent = new OrderEventArgs(); orderEvent.Order = orderToModify; orderEvent.Fill = fillEvent.Fill; orderEvent.OrderBookID = m_ParentOrderBook.BookID; m_ParentOrderBook.OnOrderStateChanged(orderEvent); return(true); } return(false); }
// // // // // ******************************************************* // **** OrderBook_OrderFilled() **** // ******************************************************* /// <summary> /// Called when an order in the hedge order book has been filled. /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> private void OrderBook_OrderFilled(object sender, EventArgs eventArgs) { FillEventArgs fillEventArgs = (FillEventArgs)eventArgs; Fill fill = fillEventArgs.Fill; int internalLegId = m_Spreader.m_InstrumentToInternalId[fillEventArgs.InstrumentName]; int stratSign = Math.Sign(fill.Qty * m_Spreader.m_LegRatios[internalLegId]); int stratSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(stratSign); // Update my IsLegHung status bool prevHungState = m_IsLegHung[stratSide]; // Keep prev state so we know it has changed. m_IsLegHung[stratSide] = false; m_Spreader.AddHedgeFill(stratSide, internalLegId, fill); // this needs to get updated prior to us trigger OnCompletelyFilled int legSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(m_Spreader.m_LegRatios[m_InternalLegId] * stratSign); if (m_OrderBook.Count(legSide) != 0) { m_IsLegHung[stratSide] = true; // we have no outstanding hedge orders } else { OnCompletelyFilled(fillEventArgs); } }
// /// <summary> /// After any order status updated and after we have already updated our quoting orders, /// this event is fired first before all others. /// </summary> public void OnOrderFilled(FillEventArgs fillEventArgs) { if (this.OrderFilled != null) { this.OrderFilled(this, fillEventArgs); } }
public void OrderFilledEventHandler(object sender, EventArgs args) { FillEventArgs filledOrders = (FillEventArgs)args; Logger.WriteLog("Order filled"); var filledOrder = filledOrders.filledOrder; //reset the order retry count OrderRetriedCount = 0; OrderStartingPrice = 0; //Logger.WriteLog(string.Format("Order id: {0} has been filled", filledOrder.OrderId)); NotifyOrderUpdateListener(new OrderUpdateEventArgs { side = filledOrder.Side, filledAtPrice = filledOrder.Price, Message = string.Format("Order id: {0} has been filled", filledOrder.OrderId), OrderId = filledOrder.OrderId, fillFee = filledOrder.Fee, fillSize = filledOrder.Size, ProductName = filledOrder.ProductId }); }
// // // // #endregion//Private Methods #region Event Handlers // ***************************************************************** // **** Event Handlers **** // ***************************************************************** // // // ******************************************************* // **** Hedger_OrdersCompletelyFilled() **** // ******************************************************* private void Hedger_CompletelyFilled(object sender, EventArgs eventArgs) { FillEventArgs fillEventArgs = (FillEventArgs)eventArgs; // Get information about who was filled. int legId; if (!m_InstrumentToId.TryGetValue(fillEventArgs.InstrumentName, out legId)) { return; } Fill fill = fillEventArgs.Fill; int stratSign = Math.Sign(fill.Qty * m_Quoter.m_LegRatios[legId]); int stratSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(stratSign); // Update my IsHung status bool prevHungState = m_IsSratHung[stratSide]; m_IsSratHung[stratSide] = false; for (int leg = 0; leg < m_Hedgers.Count; ++leg) { if (m_Hedgers[leg].m_IsLegHung[stratSide]) // hang flags for each instrument are divided by side of the strategy not the instrumetn. { m_IsSratHung[stratSide] = true; break; } } if (prevHungState != m_IsSratHung[stratSide]) // if we have changed states { m_Quoter.OnQuoterStateChange(); // we need to update the quoter. OnHangStateChanged(); // and call our subscribers. } }
} // default constructor for IStringifiable public RejectedFillEventArgs(InstrumentName name, FillEventArgs rejectedFill, RejectionReason reason, string rejectionMessage) { this.m_Name = name; this.Reason = reason; this.Message = rejectionMessage; this.OriginalFillEventArg = rejectedFill; }
}//Quote() // // // // // #endregion//private Methods #region IOrderEngine Implementation // // // ************************************************************* // **** Filled() **** // ************************************************************* // /// <summary> /// Called by the StrategyHub when it received a fillEventArg from an OrderBook /// that this engine subscribed to. /// </summary> /// <param name="fillEventArgs"></param> /// <returns>null is no fill is generated.</returns> public Fill Filled(FillEventArgs fillEventArgs) { m_FillBook.TryAdd(fillEventArgs.Fill); int fillSide = QTMath.MktSignToMktSide(fillEventArgs.Fill.Qty); m_StrategyPosition[fillSide] += fillEventArgs.Fill.Qty; m_RiskManager.Filled(fillEventArgs); // make sure our risk manager knows return(fillEventArgs.Fill); // pass fill through to other engines. }//Filled()
}//Quote() // // // // // #endregion//private Methods #region IOrderEngine Implementation // // // ************************************************************* // **** Filled() **** // ************************************************************* // /// <summary> /// Called by the StrategyHub when it received a fillEventArg from an OrderBook /// that this engine subscribed to. /// </summary> /// <param name="fillEventArgs"></param> /// <returns>null is no fill is generated.</returns> public Fill Filled(FillEventArgs fillEventArgs) { m_FillBook.TryAdd(fillEventArgs.Fill); int fillSide = QTMath.MktSignToMktSide(fillEventArgs.Fill.Qty); m_StrategyPosition[fillSide] += fillEventArgs.Fill.Qty; fillEventArgs.Fill.Price = fillEventArgs.Fill.Price * m_PriceLeg.PriceMultiplier; return(fillEventArgs.Fill); // pass fill through to other engines. }//Filled()
public void AddSubElement(IStringifiable subElement) { Type type = subElement.GetType(); if (type == typeof(FillEventArgs)) { this.OriginalFillEventArg = (FillEventArgs)subElement; } }
// ***************************************************************** // **** Event Handlers **** // ***************************************************************** // // // *********************************************************** // **** OrderBook_OrderFilled() **** // *********************************************************** // public virtual void OrderBook_OrderFilled(object sender, EventArgs eventArgs) { FillEventArgs fillEventArgs = (FillEventArgs)eventArgs; UVFill fill = fillEventArgs.Fill; if (UpdateAndCheckTotalFillCounts(fill) | PnLCheck()) { // Take the fill and update our counts and PnL, checking both. FlagRiskEvents(); } }
// ***************************************************************** // **** Event Handlers **** // ***************************************************************** // // *********************************************************** // **** OrderBook_OrderFilled() **** // *********************************************************** // public override void OrderBook_OrderFilled(object sender, EventArgs eventArgs) { FillEventArgs fillEventArgs = (FillEventArgs)eventArgs; Fill fill = fillEventArgs.Fill; if (UpdateAndCheckTotalFillCounts(fill) | UpdateAndCheckSpreaderPnL() | CheckLegPositions()) { // Take the fill and update our counts and PnL, checking both. FlagRiskEvents(); } }
// // public virtual SyntheticFill GenerateSyntheticFill(int stratSide) { SyntheticFill newSyntheticFill = new SyntheticFill(); newSyntheticFill.InstrumentName = m_SyntheticInstrumentName; newSyntheticFill.Qty = (int)(m_pendingFillQtys[m_SmallestLegIndex] / m_SmallestLegRatio); // just a starting point // First lets try and find the fill qty. Since we have our array of pendingFills we should be // able to divide all legs by the smallest leg, and find the smallest whole number from that // which will be our fillqty. for (int i = 0; i < m_pendingFillQtys.Length; ++i) { int possibleSyntheticQty = (int)(m_pendingFillQtys[i] / (long)m_LegRatios[i]); // we are looking to make sure we are going to take the largest number of COMPLETE fills if (Math.Abs(possibleSyntheticQty) < Math.Abs(newSyntheticFill.Qty)) { newSyntheticFill.Qty = possibleSyntheticQty; } } // we should theoretically now have them correct fill qty. // we now need to work on price, while we do this we can remove fills from our list to ensure they // aren't used more than once. for (int leg = 0; leg < m_LegRatios.Length; ++leg) { // Find which side int legSide = UV.Lib.Utilities.QTMath.MktSignToMktSide(UV.Lib.Utilities.QTMath.MktSideToMktSign(stratSide) * m_LegRatios[leg]); // find the qty we need to remove from the fill int qtyToRemove = (int)(m_LegRatios[leg] * newSyntheticFill.Qty); // find the average pricing for those fills we are removing double legAvgPrice = m_FillBooks[leg].m_FillPages[legSide].GetAveragePricing(qtyToRemove); // remove them and if false we probably have an issue so lets not report the fill. if (!m_FillBooks[leg].m_FillPages[legSide].DequeueQty(qtyToRemove, ref newSyntheticFill.LegFills)) { break; } // we need to multiply the average price times the leg multiplier legAvgPrice = m_LegPriceMultipliers[leg] * legAvgPrice; // assign this legs price to our spread price we will report. newSyntheticFill.Price += legAvgPrice; } // okay we have a synthetic fill with everything but a timestamp, lets take the current timestamp newSyntheticFill.LocalTime = newSyntheticFill.ExchangeTime = DateTime.Now; // trigger the event of synthetic fills. FillEventArgs e = new FillEventArgs(); e.Fill = newSyntheticFill; OnSyntheticSpreadFilled(e); return(newSyntheticFill); }
}// PriceListener_ProcessMarketEvents // // private void FillListener_Filled(object sender, EventArgs eventArg) { if (eventArg is FillEventArgs) { DateTime now = Log.GetTime(); FillEventArgs e = (FillEventArgs)eventArg; InstrumentName instrumentName; if (m_Key2Name.TryGetValue(e.TTInstrumentKey, out instrumentName)) { string s = string.Format("{0},{1},Fill,{2}", now.ToString(Strings.FormatDateTimeZone), instrumentName, e.Fill.ToString()); m_Writer.RequestEnqueue(s); Console.WriteLine(s); } } }
// // // // ************************************* // **** TryProcessFill() **** // ************************************* // /// <summary> /// Called by the execution listener when an order is filled. /// This method will update state, and send out events. /// </summary> /// <param name="fillEventArgs"></param> /// <returns></returns> public bool TryProcessFill(FillEventArgs fillEventArgs) { int bookId; if (m_OrderIDToBookMap.TryGetValue(fillEventArgs.OrderId, out bookId)) { OrderBook orderBook; if (m_OrderBooks.TryGetValue(bookId, out orderBook)) { // we have this order book if (orderBook.IsReady) { return(orderBook.TryProcessFill(fillEventArgs)); } } } return(false); }
// #endregion //IOrderEngine Implementation #region Event Handlers // ***************************************************************** // **** Event Handlers **** // ***************************************************************** // // // // ***************************************************************** // **** OrderBook_OrderFilled() **** // ***************************************************************** private void OrderBook_OrderFilled(object sender, EventArgs eventArgs) { FillEventArgs fillEventArgs = (FillEventArgs)eventArgs; m_FillBook.TryAdd(fillEventArgs.Fill); int fillSide = QTMath.MktSignToMktSide(fillEventArgs.Fill.Qty); m_StrategyPosition[fillSide] += fillEventArgs.Fill.Qty; fillEventArgs.Fill.Price = fillEventArgs.Fill.Price * m_PriceLeg.PriceMultiplier; Quote(); // this will update our orders now that we got filled, and resubmit if we are dripping etc.. // // Create a synthetic fill to pass back to the strategy. // if (m_OpenSyntheticOrders[fillSide] != null) { SyntheticFill newSyntheticFill = SyntheticFill.CreateSyntheticFillFromFill(fillEventArgs.Fill); m_OpenSyntheticOrders[fillSide].m_SyntheticFills.Add(newSyntheticFill); m_ExecutionContainer.SendSyntheticOrderToRemote(m_OpenSyntheticOrders[fillSide]); } }
}// 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()
private static void InputOnFilled(object sender, FillEventArgs e) { _output?.Write(e.Buffer, e.Offset, e.Count); }
private void InputOnFilled(object?sender, FillEventArgs e) { Output?.Write(e.Buffer, e.Offset, e.Count); }
// // // ************************************************* // **** TryProcessFill() **** // ************************************************* public bool TryProcessFill(FillEventArgs fillEventArgs) { return(m_LiveOrders[QTMath.MktSignToMktSide(fillEventArgs.Fill.Qty)].TryProcessFill(fillEventArgs)); }
private static void InputOnFilled(object sender, FillEventArgs e) { _ringBuffer.Enqueue(e.Buffer); }
// ***************************************************************** // **** Properties **** // ***************************************************************** // // #endregion//Properties #region Public Methods // ***************************************************************** // **** Public Methods **** // ***************************************************************** // // // // // // /// <summary> /// This function reads all lines in the audit trail file, generating fill event args and store them. /// In addition to that, it also collect the last most recent fill information and update the position for the next step. /// </summary> /// <param name="startDateTime"></param> /// <param name="endDateTime"></param> /// <returns></returns> public bool TryReadAuditTrailFills(DateTime startDateTime, DateTime endDateTime, AuditTrailFillHub auditTrailFillHub) { // This method will load the audit trail fills from TT given start and end date time automatically. // The results will be added to the audit trail fills dictionary. // It will also construct the fill hub name by user dictionary. // Get the target audit trail files to read. The file name format is AuditLog_yyyy-mm-dd_N. DateTime startDate; DateTime endDate; startDate = startDateTime.Subtract(startDateTime.TimeOfDay); while (startDate.DayOfWeek == DayOfWeek.Saturday || startDate.DayOfWeek == DayOfWeek.Sunday) { startDate = startDate.AddDays(-1); } endDate = endDateTime.Subtract(endDateTime.TimeOfDay).AddDays(1); while (endDate.DayOfWeek == DayOfWeek.Saturday || endDate.DayOfWeek == DayOfWeek.Sunday) { endDate = endDate.AddDays(1); } if (!System.IO.Directory.Exists(m_AuditTrailPath)) { System.IO.Directory.CreateDirectory(m_AuditTrailPath); } string pattern = "AuditLog*.mdb"; List <string> fileList = new List <string>(); List <string> targetFileList = new List <string>(); List <string> targetTableList = new List <string>(); List <DateTime> targetDateList = new List <DateTime>(); fileList.AddRange(System.IO.Directory.GetFiles(m_AuditTrailPath, pattern)); int dateDelimiterStart; int dateDelimiterEnd; DateTime fileDate = DateTime.MinValue; string fileDateString; // Loop through the file collection and choose the desired files. foreach (string fileName in fileList) { dateDelimiterEnd = fileName.LastIndexOf("_"); dateDelimiterStart = fileName.LastIndexOf("_", dateDelimiterEnd - 1); if (dateDelimiterStart < fileName.Length && dateDelimiterEnd < fileName.Length) { fileDateString = fileName.Substring(dateDelimiterStart + 1, dateDelimiterEnd - dateDelimiterStart - 1); if (DateTime.TryParseExact(fileDateString, "yyyy-MM-dd", null, System.Globalization.DateTimeStyles.None, out fileDate)) { if (startDate <= fileDate && fileDate <= endDate) { Log.NewEntry(LogLevel.Minor, "Include the file name:{0}.", fileName); targetFileList.Add(fileName); targetTableList.Add(fileDate.ToString("MMMdd")); targetDateList.Add(fileDate); } else { Log.NewEntry(LogLevel.Major, "Exclude the file name:{0}.", fileName); continue; } } else { Log.NewEntry(LogLevel.Major, "There is problem in parsing file date string:{0}.", fileDateString); continue; } } else { Log.NewEntry(LogLevel.Major, "There is problem in parsing file name:{0}.", fileName); continue; } } // Build the connections and load data from the file collection. m_FillEventArgsList.Clear(); bool isBadRow; List <InstrumentKey> instrumentKeyList = new List <InstrumentKey>(); bool readAllFillAccounts = false; if (auditTrailFillHub.HubName == string.Empty) { readAllFillAccounts = true; } for (int fileIndex = 0; fileIndex < targetFileList.Count; ++fileIndex) { // Read from the audit file. List <List <object> > dataCollections = new List <List <object> >(); if (AccessReader.TryReadAccessFile(targetFileList[fileIndex], targetTableList[fileIndex], out dataCollections)) { // Get the information from the output. All the values are in object type. int rowNumber = dataCollections.Count; for (int rowIndex = 0; rowIndex < rowNumber; ++rowIndex) { isBadRow = false; // The valid data types are explored in detail by test program. string localTimeStamp = (string)dataCollections[rowIndex][ObjectListSchema.LocalTimeStamp]; string exchangeName = (string)dataCollections[rowIndex][ObjectListSchema.ExchangeName]; string orderStatus = (string)dataCollections[rowIndex][ObjectListSchema.OrderStatus]; string orderAction = (string)dataCollections[rowIndex][ObjectListSchema.OrderAction]; string orderSide = (string)dataCollections[rowIndex][ObjectListSchema.OrderSide]; int orderQty = (int)dataCollections[rowIndex][ObjectListSchema.OrderQty]; string product = (string)dataCollections[rowIndex][ObjectListSchema.Product]; string contract = (string)dataCollections[rowIndex][ObjectListSchema.Contract]; string orderPrice = (string)dataCollections[rowIndex][ObjectListSchema.OrderPrice]; string accountName = (string)dataCollections[rowIndex][ObjectListSchema.AccountName]; string userName = (string)dataCollections[rowIndex][ObjectListSchema.UserName]; string exchangeTime = (string)dataCollections[rowIndex][ObjectListSchema.ExchangeTime]; string exchangeDate = (string)dataCollections[rowIndex][ObjectListSchema.ExchangeDate]; string tradeSource = (string)dataCollections[rowIndex][ObjectListSchema.TradeSource]; string ttOrderKey = (string)dataCollections[rowIndex][ObjectListSchema.TTOrderKey]; string ttSeriesKey = (string)dataCollections[rowIndex][ObjectListSchema.TTSeriesKey]; // Check whether the account is desired. if (!readAllFillAccounts && !accountName.Equals(m_FillHubName)) { continue; } // Check whether the exchange name includes AlgoSE sub string. if (exchangeName.Contains(m_ExchangeName_AlgoSE)) { continue; } // Check whether it is a fill event. if (!orderAction.Equals(m_Action_Fill) && !orderAction.Equals(m_Action_PartialFill)) { continue; } // Check whether it is a OK status. if (!orderStatus.Equals(m_OrderStatus_OK)) { continue; } // Check whether the product type is future. if (product.Equals(m_Product_AutoSpreader)) { continue; } // Check whether the contract string contains Calendar string to avoid duplicate fills. foreach (string specialString in m_Contract_Special) { if (contract.Contains(specialString)) { isBadRow = true; if (exchangeName.Contains("TOCOM") && specialString.Equals("/") && isBadRow) { isBadRow = false; } break; } } if (isBadRow) { continue; } // Try parse some necessary variables. DateTime localDateTimeValid = DateTime.MinValue; DateTime exchangeTimeValid = DateTime.MinValue; DateTime exchangeDateValid = DateTime.MinValue; double fillPrice = double.NaN; if (!DateTime.TryParseExact(localTimeStamp, "HH:mm:ss.fff", null, System.Globalization.DateTimeStyles.None, out localDateTimeValid)) { Log.NewEntry(LogLevel.Major, "Failed to parse the utc time of {0}.", localTimeStamp); continue; } if (!DateTime.TryParseExact(exchangeTime, "HH:mm:ss.fff", null, System.Globalization.DateTimeStyles.None, out exchangeTimeValid)) { Log.NewEntry(LogLevel.Major, "Failed to parse the exchange time of {0}.", exchangeTime); continue; } if (!DateTime.TryParseExact(exchangeDate, "ddMMMyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out exchangeDateValid)) { Log.NewEntry(LogLevel.Major, "Failed to parse the exchange time of {0}.", exchangeDate); continue; } if (!double.TryParse(orderPrice, out fillPrice)) { Log.NewEntry(LogLevel.Major, "Failed to parse the order price of {0}.", orderPrice); continue; } localDateTimeValid = targetDateList[fileIndex].Add(localDateTimeValid.TimeOfDay); exchangeTimeValid = exchangeDateValid.Add(exchangeTimeValid.TimeOfDay); // Edit the market. int validEndIndex = exchangeName.LastIndexOf("-"); if (validEndIndex >= 0) { exchangeName = exchangeName.Substring(0, validEndIndex); } // Create fill. Fill fill = new Fill(); fill.ExchangeTime = exchangeTimeValid; //TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(m_LocalTimeZoneString); //DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(localDateTimeValid, localTimeZone); fill.LocalTime = localDateTimeValid; fill.Price = fillPrice; fill.Qty = orderSide.Equals(m_OrderSide_Buy) ? orderQty : (orderSide.Equals(m_OrderSide_Sell) ? -orderQty : 0); // Create fill event args. InstrumentKey instrumentKey = new InstrumentKey(exchangeName, TradingTechnologies.TTAPI.ProductType.Future, product, ttSeriesKey); FillEventArgs fillEventArgs = new FillEventArgs(); fillEventArgs.Fill = fill; fillEventArgs.AccountID = accountName; //fillEventArgs.FillKey = ttOrderKey; fillEventArgs.Type = FillType.Historic; fillEventArgs.TTInstrumentKey = instrumentKey; // Add the instrument key to the list. if (startDateTime.AddSeconds(-3) <= localDateTimeValid && localDateTimeValid <= endDateTime.AddSeconds(3)) { if (!TTConvert.CheckExistenceOfInstrumentKey(instrumentKeyList, instrumentKey)) { instrumentKeyList.Add(instrumentKey); } // Add the fill event args to the list. string rowInfo = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}.", localTimeStamp, exchangeName, orderStatus, orderAction, orderSide, orderQty, product, contract, orderPrice, accountName, userName, exchangeTime, exchangeDate, tradeSource, ttOrderKey, ttSeriesKey); Log.NewEntry(LogLevel.Minor, "Record:{0}", rowInfo); m_FillEventArgsList.Add(fillEventArgs); } } } else { Log.NewEntry(LogLevel.Major, "Failed to read access file with name:{0}.", targetFileList[fileIndex]); continue; } Log.NewEntry(LogLevel.Minor, "Complete reading access file with name:{0}.", targetFileList[fileIndex]); } // Get the last local time of fill for each instrument in initial fill hub. m_NeededBookInstrumentList.Clear(); //foreach (InstrumentKey ttKeyInWaitList in auditTrailFillHub.InitialWaitDictionary.Keys) //{ // // These fills that do not have books will be requested to create new books if possible. To ensure they have books, create them if necessary here. // if (!auditTrailFillHub.TryCheckExistenceOfInstrumentKey(ttKeyInWaitList) && !TTConvert.CheckExistenceOfInstrumentKey(neededBookInstrumentList, ttKeyInWaitList)) // { // neededBookInstrumentList.Add(ttKeyInWaitList); // } //} // For the fills from the audit trail files, also get instruments that need books. foreach (InstrumentKey instrumentKeyInAuditTrail in instrumentKeyList) { if (!auditTrailFillHub.TryCheckExistenceOfInstrumentKey(instrumentKeyInAuditTrail) && !TTConvert.CheckExistenceOfInstrumentKey(m_NeededBookInstrumentList, instrumentKeyInAuditTrail)) { m_NeededBookInstrumentList.Add(instrumentKeyInAuditTrail); } } // Clear all trades in the waiting list because they are all included in the audit trail files. auditTrailFillHub.InitialWaitDictionary.Clear(); // Create books if necessary. // The instrument that need book creation is those got from FillEventArgs from drop file and the new fills listened in the audit trail file. // It is crucial to get all the books ready before updating positions. foreach (InstrumentKey key in m_NeededBookInstrumentList) { OrderHubRequest creatFillBookRequest = new OrderHubRequest(OrderHubRequest.RequestType.RequestCreateFillBook); creatFillBookRequest.Data = new object[1]; creatFillBookRequest.Data[0] = key; auditTrailFillHub.HubEventEnqueue(creatFillBookRequest); } Log.NewEntry(LogLevel.Minor, "Complete loading audit trail fills."); return(true); }