public event EventHandler HistoricFill;                               // Fired for each fill received (new or old).
 //
 //
 protected void OnHistoricFill(FillEventArgs eventArgs)
 {
     if (HistoricFill != null)
     {
         HistoricFill(this, eventArgs);
     }
 }// OnFilled()
        private void TT_FillListDownLoad(object sender, TradingTechnologies.TTAPI.FillBookDownloadEventArgs eventArgs)
        {
            bool isWriteLog = false;

            if (Log != null)
            {
                isWriteLog = Log.BeginEntry(LogLevel.Minor, "FillListener.TT_FillDownLoad: {0} {1} fills from {2}: ", Name, eventArgs.Fills.Count.ToString(), System.Threading.Thread.CurrentThread.Name);
            }
            foreach (TradingTechnologies.TTAPI.Fill fill in eventArgs.Fills)
            {
                if (m_LogAllFillPropertiesFromTT)
                {
                    WriteFillToLog(FillType.Historic.ToString(), fill);
                }
                FillEventArgs e = CreateFillEventArg(FillType.Historic, fill);
                if (isWriteLog)
                {
                    Log.AppendEntry("[{0} {1} {2}]", e.TTInstrumentKey, e.Fill, e.FillKey);
                }
                m_HistoricFills.Add(e);                             // alt approach: StatusChanged is triggered at end of download, HistoricFills passed to subscribers
                OnHistoricFill(e);                                  // otherwise, subscribers to this event can collect each historic fill.
            }
            if (Log != null)
            {
                Log.EndEntry();
            }
        }
 /// <summary>
 /// True if both instances seem to refer to the same fill event.
 /// </summary>
 /// <returns></returns>
 public bool IsSameAs(FillEventArgs other)
 {
     if (other == null)
     {
         return(false);
     }
     if (string.IsNullOrEmpty(this.FillKey) || string.IsNullOrEmpty(other.FillKey))
     {   // One or both are missing a unique fill key - bummer!
         if (!this.TTInstrumentKey.Equals(other.TTInstrumentKey))
         {
             return(false);
         }
         if (this.Type != other.Type)
         {
             return(false);
         }
         if (!this.Fill.IsSameAs(other.Fill))
         {
             return(false);
         }
         // They seem to be same!
         return(true);
     }
     else
     {
         return(this.FillKey.Equals(other.FillKey));
     }
 }
Exemple #4
0
        } // TryAdd()

        //
        //
        //
        // *************************************************************
        // ****                     Is Fill New()                   ****
        // *************************************************************
        /// <summary>
        /// This method examines a fill event and tries to determine whether or not the fill
        /// is known to this fill book, or is new.  If its not new, an explanation is returned as
        /// an RejectedFillEventArg.
        /// </summary>
        /// <param name="fillEventArgs"></param>
        /// <param name="rejectedEventArgs">Rejected fill: null when true, but can be null/not null when false</param>
        /// <returns>True if this fill seems to be new to our book.</returns>
        public new bool IsFillNew(FillEventArgs fillEventArgs, out RejectedFills.RejectedFillEventArgs rejectedEventArgs)
        {
            rejectedEventArgs = null;

            // Test purpose:(This should never appeared in the production code.
            //DateTime localAcceptDateTime = DateTime.Now.Date.AddHours(12);
            //if (fillEventArgs.Fill.LocalTime <= localAcceptDateTime)
            //{
            //    string msg = string.Format("Test purpose date time accepted only after {0}.", localAcceptDateTime);
            //    rejectedEventArgs = TriggerRejectionEvent(fillEventArgs, RejectedFills.RejectionReason.ExcessiveLateness, msg);
            //    return false;
            //}

            // Accept user adjusted fills always.
            if (fillEventArgs.Type == FillType.UserAdjustment)
            {
                return(true);
            }

            // Accept adjusted fills always.
            if (fillEventArgs.Type == FillType.Adjustment)
            {
                return(true);
            }

            // Exchange time stamp events.  (Note some fills like UserAdjusted fills don't have Exchange time stamps.)
            if (fillEventArgs.Fill.ExchangeTime.CompareTo(DateTime.MinValue) > 0)
            {
                // Reject if we have actually seen fill key before. We don't do this test right off because its slow.
                if (fillEventArgs.FillKey != null && m_RecentKeys.Contains(fillEventArgs.FillKey))
                {
                    string msg = string.Format("{0} already in book {1}.", fillEventArgs.FillKey, this.Name);
                    rejectedEventArgs = TriggerRejectionEvent(fillEventArgs, RejectedFills.RejectionReason.DuplicateKey, msg);
                    return(false);
                }

                TimeSpan ts = (fillEventArgs.Fill.ExchangeTime).Subtract(this.ExchangeTimeLast); // time since last fill.
                if (ts.TotalMilliseconds >= 0)                                                   // fills after the last fill are always reasonable.
                {
                    return(true);
                }
                else
                {
                    // Reject if fill is old.  That is, our book has more recent fills.
                    string msg = string.Format("Bad fill time {0}. Book last {1}. Earlier by {2} hours.", fillEventArgs.Fill.ExchangeTime.ToString(Strings.FormatDateTimeZone), base.ExchangeTimeLast.ToString(Strings.FormatDateTimeZone), ts.TotalHours.ToString("0.0"));
                    rejectedEventArgs = TriggerRejectionEvent(fillEventArgs, RejectedFills.RejectionReason.ExcessiveLateness, msg);
                    return(false);
                }
            }
            else
            {
                // Reject if fill does not have valid exchange time.
                string msg = string.Format("Invalid fill time {0}.", fillEventArgs.Fill.ExchangeTime.ToString(Strings.FormatDateTimeZone));
                rejectedEventArgs = TriggerRejectionEvent(fillEventArgs, RejectedFills.RejectionReason.ExcessiveLateness, msg);
                return(false);
            }

            // Can't find any reason to reject.
            //return true;
        }// IsFillAcceptable()
 public event EventHandler Filled;                               // Fired for each fill received (new or old).
 //
 //
 public void OnFilled(FillEventArgs eventArgs)
 {
     Log.NewEntry(LogLevel.Major, "FillListener: {0}", eventArgs);
     if (Filled != null)
     {
         Filled(this, eventArgs);
     }
 }// OnFilled()
        }// WriteFillToLog()

        //
        //
        // *************************************************************
        // ****             Create Fill EventArgs()                 ****
        // *************************************************************
        private FillEventArgs CreateFillEventArg(FillType fillType, TradingTechnologies.TTAPI.Fill ttFill)
        {
            int qty = 0;

            if (ttFill.BuySell == BuySell.Buy)
            {
                qty = ttFill.Quantity.ToInt();          // qty > 0 --> buy;
            }
            else if (ttFill.BuySell == BuySell.Sell)
            {
                qty = -ttFill.Quantity.ToInt();         // qty < 0 --> sell;
            }
            Misty.Lib.OrderHubs.Fill aFill = Misty.Lib.OrderHubs.Fill.Create(qty, ttFill.MatchPrice.ToDouble(), Log.GetTime(), ttFill.TransactionDateTime);
            FillEventArgs            e     = new FillEventArgs(ttFill.InstrumentKey, fillType, aFill);

            e.FillKey   = ttFill.FillKey;
            e.AccountID = ttFill.AccountName;
            return(e);
        }//CreateFillEventArg()
        /// <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))
            {
                Misty.Lib.OrderHubs.Fill aFill = Misty.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()
Exemple #8
0
        }//IsFillExistByExchangeTime()

        #endregion//Public Methods


        #region Private Methods
        // *****************************************************************
        // ****                     Private Methods                     ****
        // *****************************************************************
        //
        //
        //
        //
        private RejectedFills.RejectedFillEventArgs TriggerRejectionEvent(FillEventArgs rejectedFill, RejectedFills.RejectionReason reason, string rejectionMessage)
        {
            // Make sure this rejection is new.
            bool isDuplicate = false;
            int  n           = 0;

            while ((!isDuplicate) && n < m_RejectedFills.Count)
            {
                isDuplicate = rejectedFill.IsSameAs(m_RejectedFills[n].OriginalFillEventArg);
                n++;
            }

            RejectedFills.RejectedFillEventArgs rejectedEventArgs = new RejectedFills.RejectedFillEventArgs(this.Name, rejectedFill, reason, rejectionMessage);
            if (!isDuplicate)
            {                                                // Don't event if this is a duplicate rejection (previously rejected that is).
                //RejectedFills.RejectedFillEventArgs rejectedEventArgs = new RejectedFills.RejectedFillEventArgs(this.Name, rejectedFill, reason, rejectionMessage);
                this.m_RejectedFills.Add(rejectedEventArgs); // The storing of this rejection notification, is like triggering event.
                return(rejectedEventArgs);
            }
            else
            {
                return(rejectedEventArgs);                       // this is a rejection that we have already seen (in previous run, probably).
            }
        }
        }//SetConfirmMode()

        //
        #endregion//Private Methods


        #region Event Handlers
        // *****************************************************************
        // ****                     Event Handlers                     ****
        // *****************************************************************
        //
        //
        private void buttonSubmitFill_Click(object sender, EventArgs e)
        {
            if (m_IsConfirmMode)
            {   // The user has confirmed to send this.
                // Read numbers again
                bool isGoodToSendOrder = true;
                int  qty = 0;
                if (!Int32.TryParse(textBoxQty.Text, out qty))
                {
                    isGoodToSendOrder = false;
                }
                double price = 0;
                if (!Double.TryParse(textBoxPrice.Text, out price))
                {
                    isGoodToSendOrder = false;
                }

                if (isGoodToSendOrder)
                {
                    // Submit fill now
                    Misty.Lib.OrderHubs.Fill aFill = Misty.Lib.OrderHubs.Fill.Create();
                    aFill.Price     = price;
                    aFill.Qty       = qty;
                    aFill.LocalTime = Log.GetTime();


                    /*
                     * //Misty.Lib.Products.InstrumentBase instrBase = null;
                     * TradingTechnologies.TTAPI.InstrumentDetails details;
                     * if (m_CurrentInstrument != m_EmptyInstrument && m_Market.TryGetInstrumentDetails(m_CurrentInstrument, out details) && details != null && details.Key != null)
                     * {   // TODO: Somewhere around here a null exception was thrown.
                     *  if ( Log != null)
                     *      Log.NewEntry(Misty.Lib.Hubs.LogLevel.Major, "FormAddFills.SubmitFill_Click: Submitting fill request {0} or ForeignKey is null", m_CurrentInstrument);
                     *  TradingTechnologies.TTAPI.InstrumentKey instrKey = (TradingTechnologies.TTAPI.InstrumentKey)details.Key;
                     *  Ambre.TTServices.Fills.FillEventArgs fillEventArgs = new Ambre.TTServices.Fills.FillEventArgs(instrKey, Ambre.TTServices.Fills.FillType.UserAdjustment, aFill);
                     *  m_FillHub.HubEventEnqueue(fillEventArgs);
                     * }
                     * else if (Log != null)
                     *  Log.NewEntry(Misty.Lib.Hubs.LogLevel.Warning, "FormAddFills.SubmitFill_Click: Failed {0} or ForeignKey is null", m_CurrentInstrument);
                     */
                    TradingTechnologies.TTAPI.InstrumentKey instrumentKey;
                    if (m_CurrentInstrument != m_EmptyInstrument && m_FillHub.TryGetInstrumentKey(m_CurrentInstrument, out instrumentKey))
                    {   // TODO: Somewhere around here a null exception was thrown.
                        if (Log != null)
                        {
                            Log.NewEntry(Misty.Lib.Hubs.LogLevel.Major, "FormAddFills.SubmitFill_Click: Submitting fill request {0}.", m_CurrentInstrument);
                        }
                        Ambre.TTServices.Fills.FillEventArgs fillEventArgs = new Ambre.TTServices.Fills.FillEventArgs(instrumentKey, Ambre.TTServices.Fills.FillType.UserAdjustment, aFill);
                        m_FillHub.HubEventEnqueue(fillEventArgs);
                    }
                    else if (Log != null)
                    {
                        Log.NewEntry(Misty.Lib.Hubs.LogLevel.Warning, "FormAddFills.SubmitFill_Click: Failed {0} or ForeignKey is null", m_CurrentInstrument);
                    }


                    // REset the colors
                    textBoxQty.Text = string.Empty;                         // protection against user's adding fill twice.
                    SetConfirmMode(buttonSubmitFill, false, 0);             // reset colors and text on button
                }
            }
            else
            {
                bool isGood = true;
                int  qty    = 0;
                if (Int32.TryParse(textBoxQty.Text, out qty))
                {
                    textBoxQty.Text = string.Format("{0:+0;-0;0}", qty);
                }
                else
                {
                    textBoxQty.Text = "0";
                    isGood          = false;
                }
                double price = 0;
                if (Double.TryParse(textBoxPrice.Text, out price))
                {
                    textBoxPrice.Text = string.Format("{0}", price);
                }
                else
                {
                    textBoxPrice.Text = "";
                    isGood            = false;
                }
                // Set
                SetConfirmMode(buttonSubmitFill, isGood, qty);                            // set colors to "confirm" mode.
            }
        }
Exemple #10
0
        } // TryPeriodicBookDrop()

        //
        // *************************************************************
        // ****                   Drop Raw Fill()                   ****
        // *************************************************************
        public void DropFillEvent(FillEventArgs fillEventArg)
        {
            m_DropFills.RequestEnqueue(Misty.Lib.IO.Xml.Stringifiable.Stringify(fillEventArg));
        }
 public bool IsFillNew(FillEventArgs fillEventArgs, out RejectedFills.RejectedFillEventArgs rejectedEventArgs)
 {
     rejectedEventArgs = null;
     return(true);
 }
        }//ToString()

        //
        //
        //
        public bool TryAdd(FillEventArgs eventArg, out RejectedFills.RejectedFillEventArgs rejection)
        {
            rejection = null;
            return(true);
        }
Exemple #13
0
        // *****************************************************************
        // ****                     Try Add()                           ****
        // *****************************************************************
        /// <summary>
        /// A fill event is presented to the book for acceptance.  The fill event is checked for validity,
        /// and if good added to the book. If not, a rejection event argument is created for caller.
        /// </summary>
        /// <param name="eventArg">fill event argument</param>
        /// <param name="rejection">rejection event create if false is returned</param>
        /// <returns>true if fill can be accepted, false if not.</returns>
        public new bool TryAdd(FillEventArgs eventArg, out RejectedFills.RejectedFillEventArgs rejection)          // Add a key workd override.
        {
            rejection = null;
            InstrumentKey key = eventArg.TTInstrumentKey;

            if (this.IsFillNew(eventArg, out rejection))
            {
                // Add fill to book
                Misty.Lib.OrderHubs.Fill aFill = eventArg.Fill;
                base.Add(aFill);
                // Update fill identification tables
                if (m_RecentKeys == null)
                {
                    m_RecentKeys = new RejectedFills.RecentKeyList();
                }
                if (!string.IsNullOrEmpty(eventArg.FillKey))
                {
                    m_RecentKeys.Add(eventArg.FillKey);
                }
                // Process rejections that are now accepted.
                if (eventArg.Type == FillType.UserAdjustment)
                {
                    int n = 0;
                    while (n < m_RejectedFills.Count)
                    {
                        if (m_RejectedFills[n].OriginalFillEventArg.IsSameAs(eventArg))
                        {
                            m_RejectedFills.RemoveAt(n);
                            break;
                        }
                        n++;
                    }
                }

                return(true);
            }
            else
            {
                return(false);
            }


            /*
             * if (eventArg.Type == FillType.Historic || eventArg.Type == FillType.InitialPosition)
             * {   // If a fill is historic or initial, it needs to be verified that we have not already
             *  // incorporated this fill into our book in the past.
             *  // Other fills are blindly accepted since they should not have been seen before.
             *  if (this.IsFillNew(eventArg, out rejection))
             *  {
             *      base.Add(aFill);
             *      if (m_RecentKeys == null)
             *          m_RecentKeys = new RejectedFills.RecentKeyList();
             *      m_RecentKeys.Add(eventArg.FillKey);
             *  }
             *  else
             *  {
             *      return false;
             *  }
             * }
             * else
             * {   // Other kinds of fills; including "New" and "UserAdjustments" are always accepted as they
             *  // come in.
             *  base.Add(aFill);
             *  if (m_RecentKeys == null)
             *      m_RecentKeys = new RejectedFills.RecentKeyList();
             *  m_RecentKeys.Add(eventArg.FillKey);
             * }
             * return true;
             */
        } // TryAdd()
Exemple #14
0
 /// <summary>
 /// Dropping for all Raw fill events.
 /// </summary>
 public void EnqueueArchiveFill(FillEventArgs fillEventArg)
 {
     m_FillWriter.RequestEnqueue(Stringifiable.Stringify(fillEventArg, m_StringifyOverrideTable));
 }