//
        #endregion//Constructors


        #region no Properties
        // *****************************************************************
        // ****                     Properties                          ****
        // *****************************************************************
        //
        //
        #endregion//Properties


        #region Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        //
        /// <summary>
        /// This is the update method for this specialized stop book.
        /// The currently volatility must be passed in each time it is called.
        /// This is used for calculating the initial stop price from which we evolve towards
        /// the current price.
        /// </summary>
        /// <param name="currentVolatility"></param>
        public override void Update(double currentVolatility)
        { // do not call base class - this handles all needed functionality.
            base.StopBase = currentVolatility;
            if (m_StopSign != 0)
            {   // We are stopped.
                //
                // Check blocking timeout.
                //
                if (m_IsBlockingTimeOut)
                {
                    m_BlockingTimeOutRemaining -= 1;            // decrease countdown to timeout.
                    if (m_BlockingTimeOutRemaining <= 0)
                    {
                        if (IsLogWrite)
                        {
                            Log.NewEntry(LogLevel.Major, "StopRule: Blocking timed out. StopLoss for {1} returning to normal trading on {0} side."
                                         , QTMath.MktSignToString(m_StopSign), m_Name);
                        }
                        m_StopSign            = 0; // return to normal trading.
                        this.IsUpdateRequired = true;
                        base.BroadcastParameters();
                    }
                }
            }
        }
예제 #2
0
        //
        // *************************************************************
        // ****                      Quote()                       *****
        // *************************************************************
        //
        /// <summary>
        /// This sets the inner market price and qty for the trade.
        /// For now it assumes the strategy has only one OrderInstrument, which is always
        /// the case when we have an "ExecutionStrategy" deployed; eg, an autospreader.
        ///
        /// qty must be signed, negative for sell qty's
        ///
        /// This will validate all prices prior to setting them.
        /// </summary>
        /// <param name="tradeSide"></param>
        /// <param name="price"></param>
        /// <param name="qty">Signed qty</param>
        public void Quote(int tradeSide, double price, int qty)
        {
            if (qty != 0 && tradeSide != QTMath.MktSignToMktSide(qty))
            { // mismatch qty and sides
                Log.NewEntry(LogLevel.Warning, "Quote: tradeSide and side implied by qty sign do not match, rejecting quote update");
                return;
            }
            if (!m_IsLegSetUpComplete)
            { // we cant't even validate prices yet.
                Log.NewEntry(LogLevel.Major, "Quote: Market has not been intialized yet. Order's will not be sent until market is intialized");
                return;
            }

            price = price / m_PriceLeg.PriceMultiplier;             // convert from strat price to instrument price
            qty   = (int)(qty * Math.Abs(m_PriceLeg.Weight));       // convert from strat qty to instrument qty

            if (!QTMath.IsPriceEqual(m_StrategyWorkingPrice[tradeSide], price, m_InstrumentDetails.TickSize) || m_TotalDesiredQty[tradeSide] != qty)
            {     // price is different.
                if (m_RiskManager.ValidatePrices(price, tradeSide, m_PriceLeg.InstrumentName) || qty == 0)
                { // our prices are valid so we can save variables
                    m_StrategyWorkingPrice[tradeSide] = price;
                    m_TotalDesiredQty[tradeSide]      = qty;
                    Log.NewEntry(LogLevel.Major, "Quote:{4} Working {1} {0} @ {2} in {3}", // while this may be silly to log first, it is here for readability
                                 m_OpenSyntheticOrders[tradeSide].TradeReason,             // 0
                                 qty,                                                      // 1
                                 price,                                                    // 2
                                 m_InstrumentDetails.InstrumentName,                       //3
                                 m_ExecutionContainer.EngineContainerID);                  //4
                    Quote();                                                               // go ahead an update our orders
                }
            }
        }//Quote()
예제 #3
0
        }// CopyTo()

        //
        //
        //
        public override string ToString()
        {
            StringBuilder msg = new StringBuilder();

            msg.AppendFormat("#{0}: {1} {2} @ {3} ExecQty = {4}", this.OrderId, QTMath.MktSideToString(this.Side), this.Qty, this.Price, this.ExecutedQty);
            return(msg.ToString());
        }
예제 #4
0
        // *****************************************************************
        // ****                     Members                             ****
        // *****************************************************************
        //
        #endregion// members


        #region Constructors
        // *****************************************************************
        // ****                     Constructors                        ****
        // *****************************************************************
        //
        //
        //
        #endregion//Constructors


        #region no Properties
        // *****************************************************************
        // ****                     Properties                          ****
        // *****************************************************************
        //
        //
        #endregion//Properties


        #region Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        //
        /// <summary>
        /// Caller would like to check if a quote has been filled.  This implementation simply looks to see if
        /// we are on the market or have bettered it. If so, we then create a fill.
        /// </summary>
        /// <param name="quote"></param>
        /// <param name="fill"></param>
        /// <param name="tickRounding"></param>
        /// <returns></returns>
        public static bool TryFill(Quote quote, out Fill fill, double tickRounding = 0.0001)
        {
            fill = null;
            int    tradeSign      = QTMath.MktSideToMktSign(quote.Side);
            double sameSidePrice  = quote.PricingEngine.ImpliedMarket.Price[quote.Side][0];
            double otherSidePrice = quote.PricingEngine.ImpliedMarket.Price[QTMath.MktSideToOtherSide(quote.Side)][0];
            double orderPrice     = tickRounding * Math.Round(quote.RawPrice / tickRounding);

            if (tradeSign * (sameSidePrice - orderPrice) > 0)
            {   // We are outside market
                return(false);
            }
            else if (orderPrice >= otherSidePrice)
            {   // order has crossed market.  Fill it at market.
                fill              = new Fill();
                fill.LocalTime    = DateTime.Now;
                fill.ExchangeTime = DateTime.Now;
                fill.Price        = otherSidePrice;
                fill.Qty          = quote.Qty;
                return(true);
            }
            else
            {   // we are inside the market.
                fill              = new Fill();
                fill.LocalTime    = DateTime.Now;
                fill.ExchangeTime = DateTime.Now;
                fill.Price        = orderPrice;
                fill.Qty          = quote.Qty;
                return(true);
            }
        }
예제 #5
0
        // *****************************************************************
        // ****                     Private Methods                     ****
        // *****************************************************************
        //
        //
        //
        //**********************************************************
        //****             Update Market Prices()               ****
        //**********************************************************
        /// <summary>
        /// Called whenever the mkt changes.  Updates m_Prices[][] and m_Qtys[][].
        /// returns True if inside market has changed prices
        /// </summary>
        /// TODO: THIS NEEDS TO BE FIXED
        private bool UpdateMarketPrices(UV.Lib.BookHubs.Market market, List <int>[] MarketDepthChangedList)
        {
            bool isChanged = false;

            for (int side = 0; side < 2; ++side)
            {
                if (MarketDepthChangedList[side].Count == 0 || MarketDepthChangedList[side][0] > m_LeanableDepth[side] || MarketDepthChangedList[side][0] > m_OrderBookDepthMax)
                { // if no change on this side || top change is past our leanable depth || top change is past the depth we care about
                  //nothing to do here!
                }
                else
                {     // this is a price or qty change that we need to consider
                    if (MarketDepthChangedList[side][0] == 0 && !QTMath.IsPriceEqual(m_Market.Price[side][MarketDepthChangedList[side][0]], market.Price[side][0], InstrumentDetails.TickSize))
                    { // if this is a top of book price change!
                        isChanged = true;
                    }
                    foreach (int level in MarketDepthChangedList[side])
                    {     // Set new internal market from the depth changed back
                        if (level < m_OrderBookDepthMax)
                        { // we care about updates at this level
                            m_Market.Price[side][level] = market.Price[side][level];
                            m_Market.Qty[side][level]   = market.Qty[side][level];
                        }
                    }
                }
            }
            return(isChanged);
        }
예제 #6
0
        //
        //
        //
        //
        #endregion//Public Methods

        #region Private Methods
        // *****************************************************************
        // ****                     Private Methods                     ****
        // *****************************************************************
        //
        //
        // *****************************************************************
        // ****                     RunHedgeLogic()                     ****
        // *****************************************************************
        /// <summary>
        /// Called after Instrument_TickChanged to update hedge prices of
        /// orders under active management by the HedgeRuleManager.
        /// </summary>
        private void RunHedgeLogic()
        {
            double endingPrice;                                                                     // price we end up with after our rules are applied.
            double userDefinedWorstPrice;                                                           // price the user has defined as the worst possible price

            if (m_OrderBook.Count() == 0)
            {                                                                                 // we have no orders to manage
                m_isManagerActive = false;
                m_QuoterLeg.m_Market.MarketChanged -= new EventHandler(Market_MarketChanged); // subscribe to orders state changes for this leg.
                m_Log.NewEntry(LogLevel.Minor, "HedgeRuleManager : {0} has no orders to manage, Unsunbscribing from market", m_QuoterLeg.InstrumentDetails.InstrumentName);
                return;
            }
            else // we have orders and need to manage them
            {
                for (int mktSide = 0; mktSide < 2; ++mktSide)
                {                                                                 // each side of market
                    if (m_OrderBook.Count(mktSide) != 0)
                    {                                                             //we have orders on this side of the market
                        m_ActiveOrders.Clear();                                   // these can not be recycled since the hedger could still be holding an order.
                        m_OrderBook.GetOrdersBySide(mktSide, ref m_ActiveOrders); // populate all orders for this side of the market
                        foreach (int id in m_ActiveOrders.Keys)
                        {
                            if (m_ActiveOrders.TryGetValue(id, out tmpOrder))
                            { // we can find the order
                                int orderSign = QTMath.MktSideToMktSign(tmpOrder.Side);
                                if (!m_OrderIdToUserDefinedWorstPrice.ContainsKey(id))
                                {
                                    userDefinedWorstPrice = tmpOrder.PricePending + (orderSign * tmpOrder.TickSize * m_MaxPayUpTicks);
                                    m_OrderIdToUserDefinedWorstPrice.Add(id, userDefinedWorstPrice);
                                }
                                else
                                {
                                    userDefinedWorstPrice = m_OrderIdToUserDefinedWorstPrice[tmpOrder.Id];
                                }

                                endingPrice = tmpOrder.PricePending;                                                    // assume we have no change to start.
                                foreach (IHedgeRule rule in m_HedgeRules)
                                {                                                                                       // apply our hedge rules
                                    bool isContinue = rule.ApplyHedgeRule(endingPrice, tmpOrder.Side, out endingPrice); // hand the function the ending price and let it update it
                                    if (!isContinue)                                                                    // we want to execute our rule immediately
                                    {
                                        break;
                                    }
                                }

                                if ((endingPrice * orderSign) > userDefinedWorstPrice * orderSign)  // if our ending price is worse than worse price, reassing it.
                                {
                                    endingPrice = userDefinedWorstPrice;
                                }

                                if (!QTMath.IsPriceEqual(endingPrice, tmpOrder.PricePending, tmpOrder.TickSize))
                                {                                                           // our price has been changed
                                    m_Hedger.UpdateHedgerOrderPrice(tmpOrder, endingPrice); // call the hedger to change the order
                                }
                            }
                        } // end foreach
                    }     // end if
                }         // end mktside
            }             // end else
        }                 // RunHedgeLogic()
예제 #7
0
        }// AddBook()

        //
        //
        // *************************************************************
        // ****                      Quote()                        ****
        // *************************************************************
        //
        //
        /// <summary>
        /// This sets the inner market price and qty for the trade.
        /// For now it assumes the strategy has only one OrderInstrument, which is always
        /// the case when we have an "ExecutionStrategy" deployed; eg, an autospreader.
        ///
        /// qty must be signed, negative for sell qty's
        ///
        /// This will validate all prices prior to setting them.
        /// </summary>
        /// <param name="tradeSide"></param>
        /// <param name="price"></param>
        /// <param name="qty">Signed qty</param>
        /// <param name="aBook"></param>
        public void Quote(int tradeSide, double price, int qty, UV.Lib.BookHubs.Book aBook)
        {
            if (qty != 0 && tradeSide != QTMath.MktSignToMktSide(qty))
            { // mismatch qty and sides
                Log.NewEntry(LogLevel.Warning, "Quote: tradeSide and side implied by qty sign do not match, rejecting quote update");
                return;
            }
            if (!m_IsMarketReady)
            { // we cant't even validate prices yet.
                Log.NewEntry(LogLevel.Major, "Quote: Market has not been intialized yet. Order's will not be sent until market is intialized");
                return;
            }
            if (!QTMath.IsPriceEqual(m_StrategyWorkingPrice[tradeSide], price, m_InstrumentDetails.TickSize))
            {     // price is different.
                if (m_RiskManager.ValidatePrices(price, tradeSide, m_Instrument, aBook))
                { // our prices are valid so we can save variables
                    m_StrategyWorkingPrice[tradeSide] = price;
                    m_TotalDesiredQty[tradeSide]      = qty;
                }
            }
            else
            { // price hasn't changed so if it was already set
                m_TotalDesiredQty[tradeSide] = qty;
            }
            Quote();                                    // go ahead an update our orders
        }//Quote()
예제 #8
0
        }//RemoveQuoteFromListing()

        //
        //
        //
        // *************************************************
        // ****         ValidateQuoteTables()            ****
        // *************************************************
        /// <summary>
        ///
        /// </summary>
        protected void ValidateQuoteTables()
        {
            if (m_QuoteTickSize == ParentStrategy.m_OrderEngine.QuoteTickSize)
            {
                return;
            }
            // Accept new QuoteTickSize
            Log.NewEntry(LogLevel.Minor, "QuoteTickSize change detected for {0} {1} -> {2}. Rebuilding tables.", ParentStrategy.Name, m_QuoteTickSize, ParentStrategy.m_OrderEngine.QuoteTickSize);
            m_QuoteTickSize = ParentStrategy.m_OrderEngine.QuoteTickSize;

            // Rebuild the pricing Tables.
            for (int tradeSide = 0; tradeSide < 2; tradeSide++)
            {
                List <Quote> masterQuoteList = m_QuoteListRecycling.Get();     // get a list for all quotes!
                masterQuoteList.Clear();
                // Empty all quotes into our masterList.
                List <int> keyList = new List <int>();
                keyList.AddRange(m_QuotesByPrice[tradeSide].Keys);
                foreach (int priceKey in keyList)
                {
                    List <Quote> quoteList;
                    if (m_QuotesByPrice[tradeSide].TryGetValue(priceKey, out quoteList))
                    {
                        foreach (Quote quote in quoteList)
                        {
                            if (!masterQuoteList.Contains(quote))
                            {
                                masterQuoteList.Add(quote);
                            }
                        }
                        m_QuotesByPrice[tradeSide].Remove(priceKey);
                        quoteList.Clear();
                        m_QuoteListRecycling.Recycle(quoteList);
                    }
                }// next priceKey

                // Resort all the quotes in the masterList.
                int tradeSign = QTMath.MktSideToMktSign(tradeSide);
                foreach (Quote quote in masterQuoteList)
                {
                    quote.IPrice = tradeSign * (int)System.Math.Floor(tradeSign * quote.RawPrice / m_QuoteTickSize);
                    List <Quote> quoteList;
                    if (!m_QuotesByPrice[tradeSide].TryGetValue(quote.IPrice, out quoteList))
                    {
                        quoteList = m_QuoteListRecycling.Get();
                        quoteList.Clear();
                        m_QuotesByPrice[tradeSide].Add(quote.IPrice, quoteList);
                    }
                    if (quote.Reason == QuoteReason.Stop || quote.Reason == QuoteReason.Exit)
                    {
                        quoteList.Insert(0, quote);
                    }
                    else
                    {
                        quoteList.Add(quote);
                    }
                }
            }
        }// ValidateQuoteTables()
예제 #9
0
        }//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()
예제 #10
0
        }//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()
예제 #11
0
 //
 // ******************************************
 // ****       Get IPrice By Rank()       ****
 // ******************************************
 /// <summary>
 /// For a given "rank" of orders, try and get the corresponding iPrice
 /// for those orders.
 /// </summary>
 /// <param name="side"></param>
 /// <param name="rank"></param>
 /// <param name="iPrice"></param>
 /// <returns></returns>
 public bool TryGetIPriceByRank(int side, int rank, out int iPrice)
 {
     if (m_LiveOrders[side].TryGetIPriceByRank(rank, out iPrice))
     {
         iPrice = -QTMath.MktSideToMktSign(side) * iPrice;
         return(true);
     }
     return(false);
 }
예제 #12
0
        //
        // *************************************************
        // ****             Simulate Fills()            ****
        // *************************************************
        private void SimulateFills(List <int> marketInstrList)
        {
            Book aBook;

            if (m_Market.TryEnterReadBook(out aBook))
            {
                foreach (int instrId in marketInstrList)
                {
                    Market market = null;
                    if (!aBook.Instruments.TryGetValue(instrId, out market))
                    {
                        Log.NewEntry(LogLevel.Minor, "SimulateFills: Failed to obtain market for mkt instr ID {0}", instrId);
                        continue;
                    }

                    InstrumentName   instrName  = market.Name;
                    List <OrderBook> orderBooks = null;
                    if (m_SimOrderBooks.TryGetValue(instrName, out orderBooks))
                    {
                        double tickSize = m_ExecContainer.m_OrderInstruments[instrName].Details.TickSize;
                        foreach (OrderBook orderBook in orderBooks)
                        {   //
                            // Try to fill this order book.
                            //
                            for (int orderSide = 0; orderSide < 2; orderSide++)
                            {
                                int orderSign      = QTMath.MktSideToMktSign(orderSide);
                                int otherSide      = (orderSide + 1) % 2;
                                int ourMarketPrice = (int)Math.Round(market.Price[orderSide][0] / tickSize);
                                int oppMarketPrice = (int)Math.Round(market.Price[otherSide][0] / tickSize);
                                int orderRank      = 0;                 // only fill top for now
                                int orderPrice;
                                if (orderBook.TryGetIPriceByRank(orderSide, orderRank, out orderPrice))
                                {
                                    if ((oppMarketPrice - orderPrice) * orderSign <= 0)
                                    {   // filled by crossing market.
                                        m_OrdersWorkspace.Clear();
                                        orderBook.GetOrdersByRank(orderSide, orderRank, ref m_OrdersWorkspace);
                                        FillTheseOrders(ref m_OrdersWorkspace);
                                    }
                                    else if ((ourMarketPrice - orderPrice) * orderSign > 0)
                                    {   // We are below other orders in market
                                    }
                                    else
                                    {   // We are in the middle of the market (or on the top of book).
                                        //m_OrdersWorkspace.Clear();
                                        //orderBook.GetOrdersByRank(orderSide, orderRank, ref m_OrdersWorkspace);
                                        //FillTheseOrders( ref m_OrdersWorkspace );
                                    }
                                }
                            }
                        }
                    }
                }
                m_Market.ExitReadBook(aBook);
            } // if MarketBook obtained.
        }     // SimulateFills()
예제 #13
0
        //
        //
        #endregion//Constructors


        #region no Properties
        // *****************************************************************
        // ****                     Properties                          ****
        // *****************************************************************
        //
        //
        #endregion//Properties


        #region no Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        /// <summary>
        /// This overloading creates an true implied market involving multiple instruments.
        /// </summary>
        ///
        public void SetMarket(Book marketBook, List <PriceLeg> legs)
        {
            //
            // Inner market
            //
            for (int spreadSide = 0; spreadSide < 2; ++spreadSide)    // spread side, bid/ask
            {                                                         // bid = where we can sell the spread, ask = where we can buy it
                int spreadSign = QTMath.MktSideToMktSign(spreadSide); // bidside = +1, here!
                //
                // *** Inner market ****
                //
                int    spreadLevel = 0;                                                      // inner market for spread
                int    leg         = 0;                                                      // First leg
                Market instr       = marketBook.Instruments[legs[leg].MarketID];
                int    legSide     = QTMath.MktSignToMktSide(legs[leg].Weight * spreadSign); // pos --> bidSide, neg --> askSide
                double spreadPrice = legs[leg].PriceMultiplier * instr.Price[legSide][spreadLevel];
                int    spreadQty   = Convert.ToInt32(Math.Floor(instr.Qty[legSide][spreadLevel] / Math.Abs(legs[leg].Weight)));
                leg++;
                // Remaining legs > 0
                while (leg < legs.Count)
                {
                    instr        = marketBook.Instruments[legs[leg].MarketID];
                    legSide      = QTMath.MktSignToMktSide(legs[leg].Weight * spreadSign);
                    spreadPrice += legs[leg].PriceMultiplier * instr.Price[legSide][spreadLevel];
                    spreadQty    = Math.Min(spreadQty, Convert.ToInt32(Math.Floor(instr.Qty[legSide][spreadLevel] / Math.Abs(legs[leg].Weight))));
                    //spreadQtyImp = Math.Min(spreadQtyImp, Convert.ToInt32(Math.Floor(instr.QtyImp[legSide][spreadLevel] / Math.Abs(legs[leg].Weight))));
                    leg++;
                }//next leg
                // Set inner-market prices.
                this.Price[spreadSide][spreadLevel] = spreadPrice;
                this.Qty[spreadSide][spreadLevel]   = Math.Max(1, Math.Abs(spreadQty)) * Math.Sign(spreadQty); // todo: this could be zero.
                //this.QtyImp[spreadSide][spreadLevel] = spreadQtyImp;
                //this.QtyImp[spreadSide][spreadLevel] = Math.Max(1, Math.Abs(spreadQtyImp)) * Math.Sign(spreadQtyImp);
                //this.QtyImp[spreadSide][spreadLevel] = Math.Max(1, Math.Abs(spreadQtyImp));// *spreadSign;
                //
                // ****     Outer market    ****
                //
                if (legs.Count == 1)
                {
                    spreadLevel++;
                    leg   = 0;                              // First leg
                    instr = marketBook.Instruments[legs[leg].MarketID];
                    while (spreadLevel < instr.DeepestLevelKnown)
                    {
                        this.Price[spreadSide][spreadLevel] = instr.Price[spreadSide][spreadLevel] * legs[leg].PriceMultiplier;
                        this.Qty[spreadSide][spreadLevel]   = instr.Qty[spreadSide][spreadLevel]; // todo: fix.
                        spreadLevel++;
                    }//next spreadLevel
                }
                if (spreadLevel > this.DeepestLevelKnown)
                {
                    DeepestLevelKnown = spreadLevel;
                }
            } //next side
        }     //SetMarket().
예제 #14
0
        //
        protected string GetQueryForData(DatabaseInfo dataBase)
        {
            TableInfo.InstrumentsTableInfo instrumentTable = dataBase.Instruments;
            TableInfo.ExchangesTableInfo   exchangeTable   = dataBase.Exchanges;
            TableInfo.BarsTableInfo        barsTable       = dataBase.Bars;


            // Create a instrument expiry code.
            string expiryCode;

            if (!UV.Lib.Utilities.QTMath.TryConvertMonthYearToCodeY(InstrumentName.SeriesName, out expiryCode))
            {
                return(string.Empty);
            }
            // Create sub selection string to get instr ID from InstrumentName.
            StringBuilder subQuery   = new StringBuilder();
            int           instrSqlId = m_InstrumentQuery.Results[0].InstrumentId;

            subQuery.AppendFormat("{0}", instrSqlId);
            // Create the final query.
            string        desiredFields = "*";
            StringBuilder query         = new StringBuilder();

            query.AppendFormat("SELECT {0} FROM {1}", desiredFields, barsTable.TableNameFull);
            query.AppendFormat(" WHERE {0} = ({1})", barsTable.InstrumentID, subQuery);
            if (this.StartDate > DateTime.MinValue)
            {
                int    timestamp = (int)QTMath.DateTimeToEpoch(this.StartDate);
                string s         = timestamp.ToString();
                query.AppendFormat(" AND {0} >= {1}", barsTable.TimeStamp, s);
            }
            if (this.EndDate < DateTime.MaxValue)
            {
                int    timestamp = (int)QTMath.DateTimeToEpoch(this.EndDate);
                string s         = timestamp.ToString();
                query.AppendFormat(" AND {0} <= {1}", barsTable.TimeStamp, s);
            }
            query.AppendFormat(" AND {0} = 1", barsTable.SessionCode);  // currently we only want sessionCode = 1 for when products are trading
            query.AppendFormat(" ORDER BY {0}", barsTable.TimeStamp);

            if (this.StartDate == DateTime.MinValue)
            { // since our date time is unnasigned, lets reverse the order of our timestamps for this query so we get the proper number of rows
                query.AppendFormat(" DESC");
                m_IsReverseOrder = true;
            }

            if (this.MaxRows > 0)
            {
                query.AppendFormat(" LIMIT {0}", this.MaxRows);
            }
            query.Append(";");
            // Exit
            return(query.ToString());
        }// GetQuery();
예제 #15
0
        }//Quote()

        //
        //
        //
        //
        // *****************************************
        // ****         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 virtual 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();


            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 rawIPrice = 0;
                int totalQty  = 0;
                foreach (KeyValuePair <int, List <Quote> > kv in m_QuotesByPrice[tradeSide])
                {
                    foreach (Quote quote in kv.Value)
                    {
                        totalQty = totalQty + quote.Qty;
                    }

                    rawIPrice = -tradeSign * kv.Key;            // price at this level
                    if (totalQty != 0)
                    {
                        break;
                    }
                }

                //
                // Send quotes.
                //
                int tradeId;
                int quoteQtyAllowed = Math.Max(0, m_MaxPosition - tradeSign * m_Position[tradeSide]);//always positive
                totalQty = tradeSign * Math.Min(quoteQtyAllowed, Math.Abs(totalQty));
                int orderQty = totalQty + m_BuySellQty[tradeSide];
                tradeId = ParentStrategy.m_OrderEngine.Quote(tradeSide, rawIPrice * m_QuoteTickSize, orderQty, string.Empty);
            }
        }//UpdateQuotes().
예제 #16
0
        }//SetupBegin().

        //
        // *************************************************************
        // ****                    SetupComplete()                  ****
        // *************************************************************
        public override void SetupComplete()
        {
            base.SetupComplete();
            // if we create order books here we know risk is already listening for the events.
            if (!QTMath.IsNearEqual(m_PriceLeg.Weight, 1, .01))
            {
                Log.NewEntry(LogLevel.Error, "SingleLegExecutor: Does not have functionality for legs with weight greater than 1 implemented yet");
            }
            m_OrderBook                    = m_ExecutionListener.CreateOrderBook(m_PriceLeg.InstrumentName, m_DefaultAccount);
            m_OrderBook.OrderFilled       += new EventHandler(OrderBook_OrderFilled);
            m_OrderBook.OrderStateChanged += new EventHandler(OrderBook_OrderStateChanged);
        }
예제 #17
0
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        //
        //
        //
        // *********************************************************
        // ****                 Market_MarketChanged            ****
        // *********************************************************
        /// <summary>
        /// Called on every tick from the market.  Attempt was made to optimize this
        /// by filtering out times when we don't have a position to manage.  Additionally
        /// all calls that are not top of book are ignored.  Checks are created to watch for when market
        /// quantity crosses thresholds as this is what triggers the scratch event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        public void Market_MarketChanged(object sender, EventArgs eventArgs)
        {
            if (m_IPriceToPosition.Count == 0)
            {   // we are not actively managing a position, we dont care about market updates
                return;
            }

            if (m_Market.IsLastTickBestPriceChange)
            {                                  // this update was a best price change! we need to check everything to see if we need to scratch
                m_IPriceWorkSpaceList.Clear(); // use this list since TryScratchPosition removes keys from m_IPricePosition, we cannot iterate on it!

                foreach (KeyValuePair <int, int> kvPair in m_IPriceToPosition)
                {   // check each price we have a position at, if we need to scratch, then add it to our list of prices to scratch
                    if (IsScratchNeededAtIPrice(kvPair.Key))
                    {
                        m_IPriceWorkSpaceList.Add(kvPair.Key);
                    }
                }

                for (int i = 0; i < m_IPriceWorkSpaceList.Count; i++)
                {   // for every price we need to scratch
                    TryScratchPosition(m_IPriceWorkSpaceList[i], true);
                }

                // update our state variables with new market quantities!
                for (int side = 0; side < 2; ++side)
                {
                    m_WasInsideMarketQtyAboveThreshold[side] = m_Market.Qty[side][0] > m_ScratchThreshold;
                }
            }
            else
            {   // this could be a top of book qty change, lets check
                bool isMarketQtyOverThreshold;
                for (int side = 0; side < 2; ++side)
                {
                    if (m_Market.BestDepthUpdated[side] == 0)
                    {   // the last update on this side was top of market!
                        isMarketQtyOverThreshold = m_Market.Qty[side][0] > m_ScratchThreshold;
                        if ((m_IsActive & !isMarketQtyOverThreshold & m_WasInsideMarketQtyAboveThreshold[side]) |
                            (!m_IsActive & isMarketQtyOverThreshold & !m_WasInsideMarketQtyAboveThreshold[side]))
                        {   // we are actively scratching, the market is now under our threshold and it was previously above!
                            // OR we are passively scratching the market is now over our threshold and it was previously below!
                            int iPrice = QTMath.RoundToSafeIPrice(m_Market.Price[side][0], side, m_InstrumentDetails.TickSize);
                            if (IsScratchNeededAtIPrice(iPrice))
                            {   // this call will complete the checks and if returns true we actually need to scratch
                                TryScratchPosition(iPrice, true);
                            }
                        }
                        m_WasInsideMarketQtyAboveThreshold[side] = isMarketQtyOverThreshold;    // save new threshold state
                    }
                }
            }
        }
        //
        //
        //
        //
        #endregion//Public Methods


        #region Private Methods
        // *****************************************************************
        // ****                     Private Methods                     ****
        // *****************************************************************
        //
        /// <summary>
        /// Override to allow us to set our "Theta" or multiplier of the volatility for our
        /// initial stop
        /// </summary>
        /// <param name="signedQty"></param>
        /// <param name="fillPrice"></param>
        /// <param name="preFillPosition"></param>
        protected override void UpdateNewFill(int signedQty, double fillPrice, int preFillPosition)
        {
            //
            // Initial stop price:
            // StopPrice[0] = FillPrice - StopSign*Theta*Vol[0]
            //
            base.StopBaseMultiplier = m_TrailingStopTheta[QTMath.MktSignToMktSide(signedQty)];  // set our multiplier for this side to theta for this fill!
            base.UpdateNewFill(signedQty, fillPrice, preFillPosition);
            if (Position != 0 && m_GraphEngine != null)
            {
                m_GraphEngine.AddPoint(m_GraphId, m_StopCurvveName, NearestStopPrice);
                m_PlotUpdateCount = 0;
            }
        }
예제 #19
0
        }// ProcessUnwantedFills()

        //
        //
        // *************************************************
        // ****         RemoveQuoteFromListing()        ****
        // *************************************************
        protected void RemoveQuoteFromListing(int tradeSide, Quote quoteToRemove)
        {
            int          tradeSign = QTMath.MktSideToMktSign(tradeSide);
            int          priceKey  = -tradeSign * quoteToRemove.IPrice;
            List <Quote> quoteList;

            if (m_QuotesByPrice[tradeSide].TryGetValue(priceKey, out quoteList) && quoteList.Contains(quoteToRemove))
            {
                quoteList.Remove(quoteToRemove);
                quoteToRemove.IsPriceListed = false;
                if (quoteList.Count == 0)
                {   // There are no remaining quotes at this price level, so clear out the list.
                    m_QuotesByPrice[tradeSide].Remove(priceKey);
                    m_QuoteListRecycling.Recycle(quoteList);
                }
            }
            else
            {
                ParentStrategy.StrategyHub.Log.BeginEntry(LogLevel.Major, "Quote: {0} could not find quote {1}.  Searching for it...", ParentStrategy.Name, quoteToRemove);
                bool isFound = false;
                foreach (KeyValuePair <int, List <Quote> > kv in m_QuotesByPrice[tradeSide])
                {
                    if (kv.Value.Contains(quoteToRemove))
                    {
                        isFound = true;
                        Log.AppendEntry(" Found! Removed from list at priceKey={0} not QuotePriceKey={1}.", priceKey, quoteToRemove.IPrice);
                        Log.EndEntry();
                        priceKey = kv.Key;
                        kv.Value.Remove(quoteToRemove);
                        quoteToRemove.IsPriceListed = false;
                        break;
                    }
                }
                if (isFound)
                {
                    if (m_QuotesByPrice[tradeSide].TryGetValue(priceKey, out quoteList) && quoteList.Count == 0)
                    {
                        m_QuotesByPrice[tradeSide].Remove(priceKey);
                        m_QuoteListRecycling.Recycle(quoteList);
                    }
                }
                else
                {
                    Log.AppendEntry(" Not Found! Marking it as such.");
                    Log.EndEntry();
                    quoteToRemove.IsPriceListed = false;
                }
            }
        }//RemoveQuoteFromListing()
예제 #20
0
        //
        protected string GetQueryForEconomicTickers(DatabaseInfo dataBase)
        {
            TableInfo.EconomicDataTableInfo    economicTable   = dataBase.EconomicEvents;
            TableInfo.EconomicTickersTableInfo economicTickers = dataBase.EconomicTickers;
            // Create a instrument expiry code.
            string expiryCode;

            if (!UV.Lib.Utilities.QTMath.TryConvertMonthYearToCodeY(InstrumentName.SeriesName, out expiryCode))
            {
                return(string.Empty);
            }
            // Create sub selection string to get instr ID from InstrumentName.
            StringBuilder subQuery     = new StringBuilder();
            int           prodFamilyId = m_InstrumentQuery.Results[0].ProdFamilyId;

            subQuery.AppendFormat("{0}", prodFamilyId);
            // Create the final query.
            //select * from bbg.economicData where unixT>=%d and unixT<=%d and tickerId in (select tickerId from bbg.productTickers where prodFamilyId in (-1,33)) order by unixT asc
            string        desiredFields = "*";
            StringBuilder query         = new StringBuilder();

            query.AppendFormat("SELECT {0} FROM {1}", desiredFields, economicTable.TableNameFull);
            if (this.StartDate > DateTime.MinValue)
            {
                int    timestamp = (int)QTMath.DateTimeToEpoch(this.StartDate);
                string s         = timestamp.ToString();
                query.AppendFormat(" WHERE {0} >= {1}", economicTable.UnixTime, s);
            }
            if (this.EndDate < DateTime.MaxValue)
            {
                int    timestamp = (int)QTMath.DateTimeToEpoch(this.EndDate);
                string s         = timestamp.ToString();
                query.AppendFormat(" AND {0} <= {1}", economicTable.UnixTime, s);
            }

            query.AppendFormat(" AND {0} IN", economicTable.TickerId);
            query.AppendFormat(" (SELECT {0} FROM {1} where {2}", economicTable.TickerId, economicTickers.TableNameFull, economicTickers.ProdFamilyId);
            query.AppendFormat(" IN (-1,{0})) ORDER BY {1} ASC", prodFamilyId, economicTable.UnixTime);

            if (this.MaxRows > 0)
            {
                query.AppendFormat(" LIMIT {0}", this.MaxRows);
            }
            query.Append(";");
            // Exit
            return(query.ToString());
        }// GetQuery();
예제 #21
0
        //
        //
        //
        //
        #endregion//Properties


        #region Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        //
        // *****************************************
        // ****             Quote()             ****
        // *****************************************
        /// <summary>
        /// Method to request that an order be sent to the Execution hub at
        /// a particular price and qty.
        /// </summary>
        /// <param name="orderSide"></param>
        /// <param name="price"></param>
        /// <param name="qty"></param>
        /// <param name="quoteReason"></param>
        /// <returns>TradeId</returns>
        public int Quote(int orderSide, double price, int qty, string quoteReason)
        {
            m_EngineEventArgsForOrders[orderSide].DataObjectList.Clear();  //clear before each use!

            // Locate TradeEventArg to update.
            SyntheticOrder syntheticOrder = null;

            if (m_ActiveOrders[orderSide] == null)
            {   // There is currently no active trade, so create one.
                syntheticOrder             = SyntheticOrder.RequestNewOrder(++m_LastOrderId);
                syntheticOrder.Side        = orderSide;
                syntheticOrder.TradeReason = quoteReason;
                m_ActiveOrders[orderSide]  = syntheticOrder;          // store it as active trade
            }
            else
            {   // There is already an active trade, grab it.
                syntheticOrder = m_ActiveOrders[orderSide];
            }
            // Update quatities if they have changed.
            // TODO: implement various round-off schemes.
            int  tradeSign         = QTMath.MktSideToMktSign(orderSide);
            int  iPrice            = tradeSign * (int)System.Math.Floor(tradeSign * price / m_QuoteTickSize); // integerized price!
            bool isChangedFromPrev = qty != m_QuoteQtyPrev[orderSide] || (iPrice != m_QuoteIPricePrev[orderSide]) || quoteReason != m_QuoteReasonPrev[orderSide];

            if (isChangedFromPrev)
            {
                m_QuoteQtyPrev[orderSide]    = qty;
                m_QuoteIPricePrev[orderSide] = iPrice;
                m_QuoteReasonPrev[orderSide] = quoteReason;
                syntheticOrder.Price         = iPrice * m_QuoteTickSize;
                syntheticOrder.Qty           = qty;
                syntheticOrder.TradeReason   = quoteReason;

                m_EngineEventArgsForOrders[orderSide].DataObjectList.Add(syntheticOrder);       // add to event arg that is already set up.
                m_ExecutionHub.HubEventEnqueue(m_EngineEventArgsForOrders[orderSide].Copy());   // send off to remote exeuction
                m_StrategyHub.Log.NewEntry(Lib.Hubs.LogLevel.Major, "TradeEngine: {0} sent {1} ", m_Strategy.Name, syntheticOrder);
            }
            // Exit
            if (syntheticOrder == null)
            {
                return(-1);
            }
            else
            {
                return(syntheticOrder.OrderId);
            }
        }// Quote()
예제 #22
0
        }//SetupBegin().

        //
        // *************************************************************
        // ****                    SetupComplete()                  ****
        // *************************************************************
        public override void SetupComplete()
        {
            base.SetupComplete();
            if (!QTMath.IsNearEqual(m_PriceLeg.Weight, 1, .01))
            {
                Log.NewEntry(LogLevel.Error, "OrderEngine: Does not have functionality for legs with weight greater than 1 implemented yet");
            }
            m_OrderBook = m_OrderHub.CreateOrderBook(m_PriceLeg.InstrumentName);
            List <InstrumentName> instrList = new List <InstrumentName> {
                m_PriceLeg.InstrumentName
            };

            m_StrategyHub.SubscribeToMarketInstruments(instrList, m_Strategy);
            m_StrategyHub.SubscribeToFills(m_Strategy, m_OrderBook);
            m_StrategyHub.SubscribeToMajorOrderStatusEvents(m_Strategy, m_OrderBook);
            m_StrategyHub.SubscribeToOrderSubmitted(m_Strategy, m_OrderBook);
        }
예제 #23
0
        //
        //
        //
        #endregion//Constructors

        #region no Properties
        // *****************************************************************
        // ****                     Properties                          ****
        // *****************************************************************
        //
        //
        #endregion//Properties

        #region Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        // *************************************************
        // ****                 Try Add()               ****
        // *************************************************
        //
        /// <summary>
        /// Add new Fill to the fill book
        /// </summary>
        /// <param name="aFill"></param>
        /// <returns>false if add failed</returns>
        public bool TryAdd(Fill aFill)
        {
            int remainingQty = aFill.Qty;                                                   // variable to subtract fills from

            bool isAddOkay = m_FillPages[QTMath.MktSignToMktSide(aFill.Qty)].TryAdd(aFill); // Store the Fill

            m_Volume += Math.Abs(aFill.Qty);                                                // updated total volume

            // Allocate Fills against our open position/
            if (m_FillsOpen.Count == 0 || remainingQty * m_FillsOpen[0].Qty >= 0)
            {                                 // we have no opens fill OR the fill is on the same side so we adding to our position, or new position.
                Fill newFill = aFill.Clone(); // clone the fill so we can edit it
                m_FillsOpen.Add(newFill);     // add the fill to the "open" list
            }
            else
            {   // we have an opposing position so we need to cancel positions.
                double realPnL = 0.0;
                while (remainingQty != 0 && m_FillsOpen.Count > 0)
                {
                    Fill oldFill = m_FillsOpen[m_FillsOpen.Count - 1];
                    if ((oldFill.Qty + remainingQty) * remainingQty >= 0)
                    {                                                                             // Incoming qty kills old fill qty "Q0" entirely; so the transacting amount is Q0
                        realPnL      += -oldFill.Qty * oldFill.Price + oldFill.Qty * aFill.Price; // -Q0*P0 - (-Q0)*P
                        remainingQty += m_FillsOpen[m_FillsOpen.Count - 1].Qty;                   // Q = Q + Q0
                        m_FillsOpen.RemoveAt(m_FillsOpen.Count - 1);                              // remove entire old fill [P0,Q0]
                    }
                    else
                    {                                                                             // Old fill completely absorbs new fill qty "Q"; transacting amount is Q
                        realPnL     += remainingQty * oldFill.Price - remainingQty * aFill.Price; // -pnl = -(-Q)*P1 - Q*P
                        oldFill.Qty += remainingQty;                                              // reduce oldQty by amount transacted.
                        remainingQty = 0;                                                         // there is no quantity left.
                    }
                }
                if (remainingQty != 0)
                {                               // After cancelling out all levels of old fills, we still have some left!
                    Fill newFill = aFill.Clone();
                    newFill.Qty = remainingQty; // overwrite the quantity with remaining qty.
                    m_FillsOpen.Add(newFill);
                }
                m_RealizedGain += realPnL * m_ContractMultiplier;
            }

            UpdatePositionInfo();

            return(isAddOkay);
        }
예제 #24
0
        // *****************************************************************
        // ****                     Constructors                        ****
        // *****************************************************************
        //
        //
        //
        #endregion//Constructors


        #region no Properties
        // *****************************************************************
        // ****                     Properties                          ****
        // *****************************************************************
        //
        //
        #endregion//Properties


        #region Public Methods
        // *****************************************************************
        // ****                     Public Methods                      ****
        // *****************************************************************
        //
        //
        //
        // *************************************************************
        // ****               TryFindLegIDWithBestQtyRatio          ****
        // *************************************************************
        /// <summary>
        /// Caller would like to find the leg with the current best qty ratio for a given
        /// side of the market.  If side == Order.BidSide then we are looking for the leg
        /// with the highest BidQty / AskQty Ratio (lowest AskQty/BidQty Ratio).  If we are
        /// looking at side == Order.AskSide then we are looking for the leg with the highest
        /// AskQty / BidQty ratio (lower BidQty / AskQty) ratio.
        /// </summary>
        /// <param name="legIDs"></param>
        /// <param name="side"></param>
        /// <param name="bestLegID"></param>
        /// <returns>False if a "best" leg id is not found.  This has to be a problem with our markets</returns>
        public bool TryFindLegIDWithBestQtyRatio(List <int> legIDs, int side, out int bestLegID)
        {
            bestLegID = -1;
            int bestQtyRatio = -1;
            int qtyRatio;
            int oppSide = QTMath.MktSideToOtherSide(side);

            for (int leg = 0; leg < legIDs.Count; leg++)
            {
                qtyRatio = m_CurveLegs[leg].m_Market.Qty[side][0] / m_CurveLegs[leg].m_Market.Qty[oppSide][0];
                if (qtyRatio > bestQtyRatio)
                {   // this leg is our current best qty ratio!
                    bestQtyRatio = qtyRatio;
                    bestLegID    = leg;
                }
            }
            return(bestLegID != -1);
        }
예제 #25
0
        public double MinimumPriceTick = 1.0;                                          // smallest price between two adjacent tick prices for orders.



        #endregion// members


        #region Constructors
        // *****************************************************************
        // ****                     Constructors                        ****
        // *****************************************************************
        public OrderBook(OrderHub parentOrderHub, InstrumentName instrumentName)
        {
            this.m_InstrumentName = instrumentName;                             // store required vars
            this.m_ParentHub      = parentOrderHub;

            // Create Order tag format
            DateTime dt = DateTime.Now;
            string   s1 = string.Format("{0:yy}{1}{2}{3}{4}{5}_", dt, QTMath.GetMonthCode(dt), QTMath.GetBaseSixtyCode(dt.Day),
                                        QTMath.GetBaseSixtyCode(dt.Hour), QTMath.GetBaseSixtyCode(dt.Minute), QTMath.GetBaseSixtyCode(dt.Second));

            m_TagFormat = s1 + "{0}";                                           // Make certain this is unique.

            // Create books.
            m_ByPrice = new SortedDictionary <int, List <string> > [2];             // TODO: I think, for speed, use List<Order>?
            for (int side = 0; side < m_ByPrice.Length; ++side)
            {
                m_ByPrice[side] = new SortedDictionary <int, List <string> >();
            }
        }//constructor
예제 #26
0
        }//IsStopTriggered()

        //
        //
        //
        /// <summary>
        /// This must be called periodically to update things like volatility, blocking timeouts,
        /// etc.
        /// </summary>
        /// <param name="excessValue">The strategy excess value: (P - FairValue)</param>
        public virtual void Update(double excessValue)
        {
            if (m_StopSign != 0)
            {   // We are stopped.
                //
                // Check blocking timeout.
                //
                if (m_IsBlockingTimeOut)
                {
                    m_BlockingTimeOutRemaining -= 1;            // decrease countdown to timeout.
                    if (m_BlockingTimeOutRemaining <= 0)
                    {
                        if (IsLogWrite)
                        {
                            Log.NewEntry(LogLevel.Major, "StopRule: Blocking timed out. StopLoss for {1} returning to normal trading on {0} side."
                                         , QTMath.MktSignToString(m_StopSign), m_Name);
                        }
                        m_StopSign            = 0; // return to normal trading.
                        this.IsUpdateRequired = true;
                        BroadcastParameters();
                    }
                }
                //
                // Crossing fair value can also reset blocking.
                //
                // Example: Consider the price trending is upward and that we stopped out on a short
                // position, so m_StopSign = -1.  As the we continue to trend, the expectedReturn < 0.
                if (m_IsBlockingResetOnCrossing)
                {
                    if (excessValue * m_StopSign > 0)   // occurs when we cross to other side of fair value.
                    {
                        if (IsLogWrite)
                        {
                            Log.NewEntry(LogLevel.Major, "StopRule: Blocking halted because fair value crosssed. StopLoss for {1} returning to normal trading on {0} side."
                                         , QTMath.MktSignToString(m_StopSign), m_Name);
                        }
                        m_StopSign            = 0; // return to normal trading.
                        this.IsUpdateRequired = true;
                        BroadcastParameters();
                    }
                }
            } // if stopped.
        }     // Update().
예제 #27
0
        //
        #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]);
            }
        }
        //
        /// <summary>
        /// This override provides the implementation for the specialized EMA trailing
        /// stops.
        /// </summary>
        /// <param name="mktPrice"></param>
        protected override void UpdateTrailingStops(double mktPrice)
        {
            int posSign = Math.Sign(base.Position);
            int posSide = QTMath.MktSignToMktSide(posSign);

            m_PriceToDelete.Clear();                                                    // place to store old stop price.
            m_PriceToAdd.Clear();                                                       // place to store new stop price.
            // Check state of each stop price.
            for (int i = 0; i < m_StopPriceList.Count; ++i)                             // loop thru each stop-price in list.
            {
                //  Compute the new stop price for this level.
                //  Stop price evolution:
                //  StopPrice[Time1] = Alpha*StopPrice[Time0] + (1-Alpha)*MidPrice[Time1]
                //
                double alpha        = m_TrailingStopAlpha[posSide];
                double newStopPrice = m_StopPriceList[i] * alpha + (1 - alpha) * mktPrice;

                m_PriceToDelete.Add(m_StopPriceList[i]);
                m_PriceToAdd.Add(newStopPrice);
            }//next stop level i
            // Update our stop lists.
            for (int i = 0; i < m_PriceToAdd.Count; ++i)
            {
                double newStopPrice = m_PriceToAdd[i];
                if (!m_StopPriceList.Contains(newStopPrice))
                {
                    m_StopPriceList.Add(newStopPrice);
                    m_StopPriceQty.Add(newStopPrice, 0);                        // put a zero qty space holder.
                }
                double oldStopPrice = m_PriceToDelete[i];                       // original price to remove now.
                m_StopPriceList.Remove(oldStopPrice);
                m_StopPriceQty[newStopPrice] += m_StopPriceQty[oldStopPrice];
                m_StopPriceQty.Remove(oldStopPrice);
            }

            m_PlotUpdateCount++;
            if (Position != 0 && m_GraphEngine != null && m_PlotUpdateCount % m_PlotUpdateFrequency == 0)
            {
                m_GraphEngine.AddPoint(m_GraphId, m_StopCurvveName, NearestStopPrice);
            }
        }
예제 #29
0
        //
        //
        //
        //
        #endregion//Constructors


        #region Public Methods
        // *************************************
        // ****     AddItemToWrite()        ****
        // *************************************
        /// <summary>
        /// User calls this function to add a new signal item for later writing.
        /// TODO:
        ///     1) this is written like this so in future, we can recycle signal items
        ///         without the user having access to them.
        /// </summary>
        public void AddItemToWrite(int strategyId, int instrId, DateTime localTime, UV.Lib.Application.UserInfo user, string pricingEngineName, string attributeString, int qty = 0, double price = 0)
        {
            FillsQueryItem newItem = new FillsQueryItem();

            newItem.StrategyId        = strategyId;
            newItem.InstrumentId      = instrId;
            newItem.RunType           = user.RunType.ToString().ToLower();
            newItem.UserName          = user.UserName;
            newItem.PricingEngineName = pricingEngineName;

            newItem.TimeStamp = localTime;
            double utc = QTMath.DateTimeToEpoch(localTime.ToUniversalTime());

            newItem.UnixUTC      = (int)Math.Floor(utc);
            newItem.UnixMicroSec = (int)((utc - newItem.UnixUTC) * 1000000);

            newItem.Qty   = qty;
            newItem.Price = price;

            newItem.AttributeString = attributeString;

            this.m_ItemsToWrite.Add(newItem);
        }//AddItemToWrite()
예제 #30
0
        // *****************************************************************
        // ****                     Private Methods                     ****
        // *****************************************************************
        //
        //
        // *********************************************************
        // ****                IsScratchNeededAtIPrice          ****
        // *********************************************************
        /// <summary>
        /// Caller would like to check if a position from a  specific level needs to
        /// be scratched based on the parameters and our current market state.
        /// Notes : This could be optimized a bit for speed up purposes!
        /// </summary>
        /// <param name="iPrice"></param>
        /// <returns></returns>
        private bool IsScratchNeededAtIPrice(int iPrice)
        {
            int currentPos;

            if (!m_IPriceToPosition.TryGetValue(iPrice, out currentPos))     // we have no position to manage here!
            {
                return(false);
            }

            int posSide = QTMath.MktSignToMktSide(currentPos);  // find out which side our position is from
            int marketIPrice;

            if (m_IsActive)
            {   // if we are actively scratching
                // If i am long from the bid, i only care when the bid changes
                int posSign = QTMath.MktSideToMktSign(posSide);
                marketIPrice = (int)(m_Market.Price[posSide][0] / m_InstrumentDetails.TickSize);

                if (iPrice * posSign > marketIPrice * posSign | (marketIPrice == iPrice & m_Market.Qty[posSide][0] < m_ScratchThreshold))
                {   // market has gone through us, or quantity is now less than our threshold
                    return(true);
                }
            }
            else
            {   // we are passively scratching
                // if i am long from the bid, i only care when the ask price changes ( i am going to join when price goes sellers)
                int oppSide = QTMath.MktSideToOtherSide(posSide);
                int oppSign = QTMath.MktSideToMktSign(oppSide);
                marketIPrice = (int)(m_Market.Price[oppSide][0] / m_InstrumentDetails.TickSize);

                if (marketIPrice * oppSign > iPrice * oppSign | (marketIPrice == iPrice & m_Market.Qty[oppSide][0] > m_ScratchThreshold))
                {   // market has gone through us, or quantity is now less greater than our threshold
                    return(true);
                }
            }
            return(false);
        }