public void SetAttributes(Dictionary <string, string> attributes) { InstrumentKey instrumentKey; bool boolValue = false; foreach (string key in attributes.Keys) { if (key.Equals("Name")) { Name = attributes[key]; } else if (key.Equals("FilterInstrumentKey") && TTConvert.TryCreateInstrumentKey(attributes[key], out instrumentKey)) { this.FilterByInstrument(instrumentKey); this.m_FilterType = FilterType.Instrument; } else if (key.Equals("FilterAccount")) { this.FilterByAccount(attributes[key]); this.m_FilterType = FilterType.Account; } else if (key.Equals("LogAllFills") && bool.TryParse(attributes[key], out boolValue)) { this.m_LogAllFillPropertiesFromTT = boolValue; } } }
}//ProcessMarketCatalogUpdate() // // ***************************************************************** // **** ProcessProductCatalogUpdate() **** // ***************************************************************** /// <summary> /// TT sent us a ProductCatalogUpdate event. Update our list of internal products. /// Called by hub thread. /// </summary> /// <param name="eventArg"></param> private void ProcessProductCatalogUpdate(ProductCatalogUpdatedEventArgs eventArg) { List <Misty.Lib.Products.Product> productList = new List <MistyProds.Product>(); foreach (Product ttProduct in eventArg.Added) // loop thru each ttProduct found in event. { Misty.Lib.Products.Product ourProduct; if (TTConvert.TryConvert(ttProduct, out ourProduct)) // Create one of our product objects for each. { // Success! productList.Add(ourProduct); Log.NewEntry(LogLevel.Minor, "ProcessProductCatalogUpdate: Found product {0} -> {1}. ", ttProduct.Name, ourProduct); if (!m_Products.ContainsKey(ttProduct.Key)) { m_Products.Add(ttProduct.Key, ttProduct); // store the actual TT product. lock (m_ProductMapLock) { m_ProductMap.Add(ourProduct, ttProduct.Key); // my product --> productKey map m_ProductMapKey.Add(ttProduct.Key, ourProduct); // product key --> my product map } } else { Log.NewEntry(LogLevel.Warning, "ProcessProductCatalogUpdate: Received duplicate product! Received {0} <--> {1}", ttProduct.Name, ourProduct); } } else { // Since products include server name, there should never be two duplicates! Log.NewEntry(LogLevel.Minor, "ProcessProductCatalogUpdate: Unknown product type {0}. ", ttProduct.Name); } } // Fire the event to our subscribers. OnMarketFoundResource(productList); // TODO: Send all products, all for this server, or just the new ones? }//ProcessProductCatalogUpdate()
} //InstrumentCatalog_InstrumentsUpdated() // // private void InstrumentLookup_InstrumentUpdated(object sender, InstrumentLookupSubscriptionEventArgs eventArgs) { if (eventArgs.Instrument != null && eventArgs.Error == null) { MistyProd.InstrumentName instrName; Instrument ttInstrument = eventArgs.Instrument; if (TTConvert.TryConvert(ttInstrument, out instrName)) { // Success in converting to our internal naming scheme. InstrumentDetails details; if (m_InstrumentDetails.TryGetValue(instrName, out details)) { // This instrument was already added! if (!ttInstrument.Key.Equals(details.Key)) { Log.NewEntry(LogLevel.Warning, "{0}: Instrument {1} found before with non-unique key {2}!", this.Name, instrName.FullName, instrName.SeriesName); } else { Log.NewEntry(LogLevel.Warning, "{0}: Instrument {1} found before and keys match! Good.", this.Name, instrName.FullName); } } else { m_KeyToInstruments.Add(ttInstrument.Key, instrName); m_InstrumentDetails.Add(instrName, ttInstrument.InstrumentDetails); Log.NewEntry(LogLevel.Minor, "{0}: Instruments found {1} <---> {2}.", this.Name, instrName, ttInstrument.Key.ToString()); } } else { // Failed to convert TT instrument to a Misty Instrument. // This happens because either their name is too confusing to know what it is. // Or, more likely, we are set to ignore the product type (options, equity, swaps). Log.NewEntry(LogLevel.Warning, "{0}: Instrument creation failed for {1}.", this.Name, ttInstrument.Key.ToString()); } OnInstrumentsFound(); } else if (eventArgs.IsFinal) { // Instrument was not found and TTAPI has given up on looking. if (eventArgs.Instrument != null) { Log.NewEntry(LogLevel.Warning, "{0}: TTAPI gave up looking for {1}.", this.Name, eventArgs.Instrument.Key.ToString()); } else { Log.NewEntry(LogLevel.Warning, "{0}: TTAPI gave up looking for something. ", this.Name, eventArgs.RequestInfo.ToString()); } } }//InstrumentLookup_Callback()
public void SetAttributes(Dictionary <string, string> attributes) { InstrumentName name; InstrumentKey ttkey; foreach (string key in attributes.Keys) { if (key.Equals("Name") && InstrumentName.TryDeserialize(attributes["Name"], out name)) { this.Name = name; } else if (key.Equals("Key") && TTConvert.TryCreateInstrumentKey(attributes["Key"], out ttkey)) { this.Key = ttkey; } } }
} //ProcessAJob() // // #endregion// private methods #region TT Callback Event Handlers // ***************************************************************************** // **** TT Callback Event Handlers **** // ***************************************************************************** /// <summary> /// Using TT's dispatcher model, the thread in these methods is my local thread. /// </summary> private void InstrumentCatalog_InstrumentsUpdated(object sender, InstrumentCatalogUpdatedEventArgs eventArgs) { if (m_isDisposing) { return; } if (eventArgs.Error != null) { Log.NewEntry(LogLevel.Warning, "{0}: Error in instrument catalog {1}.", this.Name, eventArgs.Error.Message); return; } // foreach (Instrument ttInstrument in eventArgs.Added) { MistyProd.InstrumentName instrName; if (TTConvert.TryConvert(ttInstrument, out instrName)) { // Success in converting to our internal type. InstrumentDetails details; if (m_InstrumentDetails.TryGetValue(instrName, out details)) { // This instrument was already added! if (!ttInstrument.Key.Equals(details.Key)) { Log.NewEntry(LogLevel.Warning, "{0}: Instrument {1} found before with non-unique key {2}!", this.Name, instrName.FullName, instrName.SeriesName); } else { Log.NewEntry(LogLevel.Warning, "{0}: Instrument {1} found before and keys match! Good.", this.Name, instrName.FullName); } } else { m_KeyToInstruments.Add(ttInstrument.Key, instrName); m_InstrumentDetails.Add(instrName, ttInstrument.InstrumentDetails); Log.NewEntry(LogLevel.Minor, "{0}: Instruments found {1} <---> {2}.", this.Name, instrName, ttInstrument.Key.ToString()); } } else { // Failed to convert TT instrument to a Misty Instrument. // This happens because either their name is too confusing to know what it is. // Or, more likely, we are set to ignore the product type (options, equity, swaps). Log.NewEntry(LogLevel.Warning, "{0}: Instrument creation failed for {1}.", ttInstrument.Key.ToString()); } } // next instr added OnInstrumentsFound(); // Trigger event for subscribers } //InstrumentCatalog_InstrumentsUpdated()
/// <summary> /// Creates a fill event from the pair-wise info in drop. /// Allowed keys: /// Time - the time the drop was made. /// LocalFillTime - local time fill was received. /// </summary> /// <param name="pairs"></param> /// <returns></returns> private FillEventArgs CreateFillEvent(Dictionary <string, string> pairs) { string sQty; string sPrice; if (pairs.TryGetValue("Qty", out sQty) && pairs.TryGetValue("Price", out sPrice)) { UV.Lib.OrderHubs.Fill aFill = UV.Lib.OrderHubs.Fill.Create(); aFill.Qty = Convert.ToInt32(sQty); aFill.Price = Convert.ToDouble(sPrice); // Extract fill times. if (pairs.ContainsKey("LocalFillTime")) { aFill.LocalTime = Convert.ToDateTime(pairs["LocalFillTime"]); // use fill time, if available. } else { aFill.LocalTime = Convert.ToDateTime(pairs["Time"]); // else use last drop time- legacy approach } // Extract TT's instrument key. InstrumentKey key; string sForeignKey; if (pairs.TryGetValue("ForeignKey", out sForeignKey) && TTConvert.TryCreateInstrumentKey(sForeignKey, out key)) { FillEventArgs e = new FillEventArgs(key, FillType.InitialPosition, aFill); return(e); // success! } else { Log.NewEntry(LogLevel.Error, "Failed to recreate instrument key from {0}.", sForeignKey); return(null); } } else { Log.NewEntry(LogLevel.Error, "Failed to create a fill event"); return(null); } }// CreateFillEvent()
public void SetAttributes(Dictionary <string, string> attributes) { this.Fill = new UV.Lib.OrderHubs.Fill(); ((IStringifiable)this.Fill).SetAttributes(attributes); FillType type; TradingTechnologies.TTAPI.InstrumentKey ttInstrumentKey; foreach (string key in attributes.Keys) { if (key == "Type" && Enum.TryParse <FillType>(attributes[key], out type)) { this.Type = type; } else if (key == "InstrumentKey" && TTConvert.TryCreateInstrumentKey(attributes[key], out ttInstrumentKey)) { this.TTInstrumentKey = ttInstrumentKey; } else if (key == "FillKey") { this.FillKey = attributes[key]; } } }
// ***************************************************************** // **** 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); }
}//StoreOrder() // // // #endregion // order update handlers #region Private Methods // ***************************************************************** // **** Private Methods **** // ***************************************************************** // // // // // ***************************************************** // **** Try Create New Book() **** // ***************************************************** private bool TryCreateNewBook(TT.InstrumentKey ttKey, out OrderBookTT book) { book = null; InstrumentName name; TT.InstrumentDetails details; if (m_Market.TryLookupInstrument(ttKey, out name) && m_Market.TryLookupInstrumentDetails(name, out details)) { // Market knows this instrument already. Log.BeginEntry(LogLevel.Minor, "TryCreateNewBook: Creating book."); book = new OrderBookTT(this, name); // Create book. double minTickSize = Convert.ToDouble(details.TickSize.Numerator) / Convert.ToDouble(details.TickSize.Denominator); book.MinimumPriceTick = minTickSize; if (m_Books.TryAdd(book.m_InstrumentName, book)) { m_TTKey2Name.TryAdd(ttKey, book.m_InstrumentName); Log.AppendEntry(" New book created {0}.", book); Log.EndEntry(); return(true); } else { Log.AppendEntry(" Failed to add book to Books."); Log.EndEntry(); return(false); } } else { // Market doesnt know this instrument yet. Log.NewEntry(LogLevel.Minor, "TryCreateNewBook: Market instrument unknown. Requesting details from market for {0}.", TTConvert.ToString(ttKey)); m_Market.RequestInstruments(ttKey); // request to look it up. return(false); } }//TryCreateNewBook()