예제 #1
0
        /// <summary>
        /// Process fill to adjust position
        /// Returns null if this fill does not close anything, thus not creating a trade
        /// TODO: protect from misuse (internal)?
        /// TODO: set creation of trades in the tradecomposite logic for extensibility
        /// </summary>
        /// <param name="fill"></param>
        /// <returns></returns>
        public Trade Adjust(Fill fill)
        {
            //Set last modified
            LastModifiedUtc = fill.UtcTime;

            //Some cleaning up
            ClearOldPrices();

            //Some information holders
            Fill[] opened = new Fill[0];
            Fill[] closed = { fill };

            //Check  if we have no position at all
            if (IsFlat)
            {
                _fills.Clear();
                _fills.Add(fill);
            }

            //Check current position if we might have flipped it
            else if (fill.Direction != Direction && fill.FillQuantity >= UnsignedQuantity)
            {
                //Get open fill
                opened = _fills.ToArray();

                //Get closed fill
                closed = new [] { Fill.AdjustedFill(fill, fill.FillPrice, UnsignedQuantity) };

                //Set new fill
                _fills.Clear();
                fill = Fill.AdjustedFill(fill, fill.FillPrice, fill.FillQuantity - UnsignedQuantity);
                _fills.Add(fill);

                //Return trade
                return(new Trade(_fundId, _displayCurrency, opened, closed, GetPrice(true, opened.Union(closed)), GetPrice(false, opened.Union(closed))));
            }

            //Check if we are adding to an existing position (FIFO)
            else if (fill.Direction == Direction)
            {
                _fills.Add(fill);
                return(null);
            }

            //Else we need to adjust according to fill and remove current fills from this position (FIFO)
            decimal     sizeneeded = fill.FillQuantity;
            List <Fill> opening    = new List <Fill>();

            for (int i = _fills.Count - 1; i >= 0; i--)
            {
                //Get items
                var currentfill = _fills[i];
                if (currentfill.FillQuantity > sizeneeded)
                {
                    //We need to split it
                    decimal leftover = currentfill.FillQuantity - sizeneeded;
                    _fills[i]   = Fill.AdjustedFill(currentfill, currentfill.FillPrice, leftover);
                    currentfill = Fill.AdjustedFill(currentfill, currentfill.FillPrice, sizeneeded);
                }
                else
                {
                    //Remove this fill
                    _fills.RemoveAt(i);
                }

                //Add to currently closing fill
                opening.Add(currentfill);
                sizeneeded -= currentfill.FillQuantity;

                //Check if we are ok
                if (sizeneeded == 0)
                {
                    break;
                }
            }

            //Return this filled trade
            opened = opening.ToArray();
            return(new Trade(_fundId, _displayCurrency, opened, closed, GetPrice(true, opened.Union(closed)), GetPrice(false, opened.Union(closed))));
        }