Esempio n. 1
0
        /// <summary>
        /// Performs application of an OrderEvent to the portfolio
        /// </summary>
        /// <param name="portfolio">The algorithm's portfolio</param>
        /// <param name="security">The fill's security</param>
        /// <param name="fill">The order event fill object to be applied</param>
        public override void ProcessFill(SecurityPortfolioManager portfolio, Security security, OrderEvent fill)
        {
            var cfd = (Cfd) security;

            var quoteCurrency = cfd.QuoteCurrencySymbol;

            var quoteCash = portfolio.CashBook[quoteCurrency];

            //Get the required information from the vehicle this order will affect
            var closedPosition = false;
            var isLong = security.Holdings.IsLong;
            var isShort = security.Holdings.IsShort;

            //Make local decimals to avoid any rounding errors from int multiplication
            var averageHoldingsPrice = security.Holdings.AveragePrice;
            var quantityHoldings = (decimal)security.Holdings.Quantity;
            var absoluteHoldingsQuantity = security.Holdings.AbsoluteQuantity;

            var lastTradeProfit = 0m;

            try
            {
                //Update the Vehicle approximate total sales volume.
                var saleValueInQuoteCurrency = fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity) * cfd.ContractMultiplier;
                var saleValue = saleValueInQuoteCurrency * quoteCash.ConversionRate;
                security.Holdings.AddNewSale(saleValue);

                //Get the Fee for this Order - Update the Portfolio Cash Balance: Remove Transaction Fees.
                var feeThisOrder = Math.Abs(fill.OrderFee);
                security.Holdings.AddNewFee(feeThisOrder);
                portfolio.CashBook[CashBook.AccountCurrency].AddAmount(-feeThisOrder);

                // Apply the funds using the current settlement model
                security.SettlementModel.ApplyFunds(portfolio, security, fill.UtcTime, quoteCurrency, -fill.FillQuantity * fill.FillPrice * cfd.ContractMultiplier);

                //Calculate & Update the Last Trade Profit;
                if (isLong && fill.Direction == OrderDirection.Sell)
                {
                    //Closing up a long position
                    if (quantityHoldings >= fill.AbsoluteFillQuantity)
                    {
                        //Closing up towards Zero -- this is in the quote currency
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * fill.AbsoluteFillQuantity * cfd.ContractMultiplier;
                    }
                    else
                    {
                        //Closing up to Neg/Short Position (selling more than we have) - Only calc profit on the stock we have to sell.
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * quantityHoldings * cfd.ContractMultiplier;
                    }
                    closedPosition = true;
                }
                else if (isShort && fill.Direction == OrderDirection.Buy)
                {
                    //Closing up a short position.
                    if (absoluteHoldingsQuantity >= fill.FillQuantity)
                    {
                        //Reducing the stock we have, and enough stock on hand to process order.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * fill.AbsoluteFillQuantity * cfd.ContractMultiplier;
                    }
                    else
                    {
                        //Increasing stock holdings, short to positive through zero, but only calc profit on stock we Buy.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * absoluteHoldingsQuantity * cfd.ContractMultiplier;
                    }
                    closedPosition = true;
                }


                if (closedPosition)
                {
                    // convert the compute profit into the account currency
                    lastTradeProfit *= quoteCash.ConversionRate;

                    //Update Vehicle Profit Tracking:
                    security.Holdings.AddNewProfit(lastTradeProfit);
                    security.Holdings.SetLastTradeProfit(lastTradeProfit);
                    portfolio.AddTransactionRecord(security.LocalTime.ConvertToUtc(security.Exchange.TimeZone), lastTradeProfit - 2 * feeThisOrder);
                }


                //UPDATE HOLDINGS QUANTITY, AVG PRICE:
                //Currently NO holdings. The order is ALL our holdings.
                if (quantityHoldings == 0)
                {
                    //First transaction just subtract order from cash and set our holdings:
                    averageHoldingsPrice = fill.FillPrice;
                    quantityHoldings = fill.FillQuantity;
                }
                else if (isLong)
                {
                    //If we're currently LONG on the stock.
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Update the Holding Average Price: Total Value / Total Quantity:
                            averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (fill.FillQuantity * fill.FillPrice)) / (quantityHoldings + fill.FillQuantity);
                            //Add the new quantity:
                            quantityHoldings += fill.FillQuantity;
                            break;

                        case OrderDirection.Sell:
                            quantityHoldings += fill.FillQuantity; //+ a short = a subtraction
                            if (quantityHoldings < 0)
                            {
                                //If we've now passed through zero from selling stock: new avg price:
                                averageHoldingsPrice = fill.FillPrice;
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;
                    }
                }
                else if (isShort)
                {
                    //We're currently SHORTING the stock: What is the new position now?
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Buying when we're shorting moves to close position:
                            quantityHoldings += fill.FillQuantity;
                            if (quantityHoldings > 0)
                            {
                                //If we were short but passed through zero, new average price is what we paid. The short position was closed.
                                averageHoldingsPrice = fill.FillPrice;
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;

                        case OrderDirection.Sell:
                            //We are increasing a Short position:
                            //E.g.  -100 @ $5, adding -100 @ $10: Avg: $7.5
                            //      dAvg = (-500 + -1000) / -200 = 7.5
                            averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (fill.FillQuantity * fill.FillPrice)) / (quantityHoldings + fill.FillQuantity);
                            quantityHoldings += fill.FillQuantity;
                            break;
                    }
                }
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            //Set the results back to the vehicle.
            security.Holdings.SetHoldings(averageHoldingsPrice, Convert.ToInt32(quantityHoldings));
        }
        public override void ProcessFill(SecurityPortfolioManager portfolio, Security security, OrderEvent fill)
        {
            // split the symbol into base and quote currencies

            string baseCurrency;
            string quoteCurrency;

            Forex.DecomposeCurrencyPair(security.Symbol, out baseCurrency, out quoteCurrency);

            // e.g. EUR GBP

            // EUR
            var baseCash = portfolio.CashBook[baseCurrency];
            // GBP
            var quoteCash = portfolio.CashBook[quoteCurrency];

            //Get the required information from the vehicle this order will affect
            var closedPosition = false;
            var isLong         = security.Holdings.IsLong;
            var isShort        = security.Holdings.IsShort;

            //Make local decimals to avoid any rounding errors from int multiplication
            var averageHoldingsPrice     = security.Holdings.AveragePrice;
            var quantityHoldings         = (decimal)security.Holdings.Quantity;
            var absoluteHoldingsQuantity = security.Holdings.AbsoluteQuantity;

            var lastTradeProfit = 0m;

            try
            {
                //Update the Vehicle approximate total sales volume.
                var saleValueInQuoteCurrency = fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity);
                var saleValue = saleValueInQuoteCurrency * quoteCash.ConversionRate;
                security.Holdings.AddNewSale(saleValue);

                //Get the Fee for this Order - Update the Portfolio Cash Balance: Remove Transaction Fees.
                var order = new MarketOrder(security.Symbol, fill.FillQuantity, security.Time, type: security.Type)
                {
                    Price = fill.FillPrice
                };
                var feeThisOrder = Math.Abs(security.TransactionModel.GetOrderFee(security, order));
                security.Holdings.AddNewFee(feeThisOrder);
                portfolio.CashBook[CashBook.AccountCurrency].Quantity -= feeThisOrder;

                baseCash.Quantity  += fill.FillQuantity;
                quoteCash.Quantity -= fill.FillQuantity * fill.FillPrice;

                //Calculate & Update the Last Trade Profit;
                if (isLong && fill.Direction == OrderDirection.Sell)
                {
                    //Closing up a long position
                    if (quantityHoldings >= fill.AbsoluteFillQuantity)
                    {
                        //Closing up towards Zero -- this is in the quote currency
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * fill.AbsoluteFillQuantity;
                    }
                    else
                    {
                        //Closing up to Neg/Short Position (selling more than we have) - Only calc profit on the stock we have to sell.
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * quantityHoldings;
                    }
                    closedPosition = true;
                }
                else if (isShort && fill.Direction == OrderDirection.Buy)
                {
                    //Closing up a short position.
                    if (absoluteHoldingsQuantity >= fill.FillQuantity)
                    {
                        //Reducing the stock we have, and enough stock on hand to process order.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * fill.AbsoluteFillQuantity;
                    }
                    else
                    {
                        //Increasing stock holdings, short to positive through zero, but only calc profit on stock we Buy.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * absoluteHoldingsQuantity;
                    }
                    closedPosition = true;
                }


                if (closedPosition)
                {
                    // convert the compute profit into the account currency
                    lastTradeProfit *= quoteCash.ConversionRate;

                    //Update Vehicle Profit Tracking:
                    security.Holdings.AddNewProfit(lastTradeProfit);
                    security.Holdings.SetLastTradeProfit(lastTradeProfit);
                    portfolio.AddTransactionRecord(security.Time, lastTradeProfit - 2 * feeThisOrder);
                }


                //UPDATE HOLDINGS QUANTITY, AVG PRICE:
                //Currently NO holdings. The order is ALL our holdings.
                if (quantityHoldings == 0)
                {
                    //First transaction just subtract order from cash and set our holdings:
                    averageHoldingsPrice = fill.FillPrice;
                    quantityHoldings     = fill.FillQuantity;
                }
                else if (isLong)
                {
                    //If we're currently LONG on the stock.
                    switch (fill.Direction)
                    {
                    case OrderDirection.Buy:
                        //Update the Holding Average Price: Total Value / Total Quantity:
                        averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (fill.FillQuantity * fill.FillPrice)) / (quantityHoldings + fill.FillQuantity);
                        //Add the new quantity:
                        quantityHoldings += fill.FillQuantity;
                        break;

                    case OrderDirection.Sell:
                        quantityHoldings += fill.FillQuantity;     //+ a short = a subtraction
                        if (quantityHoldings < 0)
                        {
                            //If we've now passed through zero from selling stock: new avg price:
                            averageHoldingsPrice = fill.FillPrice;
                        }
                        else if (quantityHoldings == 0)
                        {
                            averageHoldingsPrice = 0;
                        }
                        break;
                    }
                }
                else if (isShort)
                {
                    //We're currently SHORTING the stock: What is the new position now?
                    switch (fill.Direction)
                    {
                    case OrderDirection.Buy:
                        //Buying when we're shorting moves to close position:
                        quantityHoldings += fill.FillQuantity;
                        if (quantityHoldings > 0)
                        {
                            //If we were short but passed through zero, new average price is what we paid. The short position was closed.
                            averageHoldingsPrice = fill.FillPrice;
                        }
                        else if (quantityHoldings == 0)
                        {
                            averageHoldingsPrice = 0;
                        }
                        break;

                    case OrderDirection.Sell:
                        //We are increasing a Short position:
                        //E.g.  -100 @ $5, adding -100 @ $10: Avg: $7.5
                        //      dAvg = (-500 + -1000) / -200 = 7.5
                        averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (fill.FillQuantity * fill.FillPrice)) / (quantityHoldings + fill.FillQuantity);
                        quantityHoldings    += fill.FillQuantity;
                        break;
                    }
                }
            }
            catch (Exception err)
            {
                Log.Error("ForexPortfolioManager.ProcessFill(orderEvent): " + err.Message);
            }

            //Set the results back to the vehicle.
            security.Holdings.SetHoldings(averageHoldingsPrice, Convert.ToInt32(quantityHoldings));
        }
        /// <summary>
        /// Performs application of an OrderEvent to the portfolio
        /// </summary>
        /// <param name="portfolio">The algorithm's portfolio</param>
        /// <param name="security">The fill's security</param>
        /// <param name="fill">The order event fill object to be applied</param>
        public virtual void ProcessFill(SecurityPortfolioManager portfolio, Security security, OrderEvent fill)
        {
            var quoteCash = security.QuoteCurrency;

            //Get the required information from the vehicle this order will affect
            var isLong = security.Holdings.IsLong;
            var isShort = security.Holdings.IsShort;
            var closedPosition = false;
            //Make local decimals to avoid any rounding errors from int multiplication
            var quantityHoldings = (decimal)security.Holdings.Quantity;
            var absoluteHoldingsQuantity = security.Holdings.AbsoluteQuantity;
            var averageHoldingsPrice = security.Holdings.AveragePrice;

            try
            {
                // apply sales value to holdings in the account currency
                var saleValueInQuoteCurrency = fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity) * security.SymbolProperties.ContractMultiplier;
                var saleValue = saleValueInQuoteCurrency * quoteCash.ConversionRate;
                security.Holdings.AddNewSale(saleValue);

                // subtract transaction fees from the portfolio (assumes in account currency)
                var feeThisOrder = Math.Abs(fill.OrderFee);
                security.Holdings.AddNewFee(feeThisOrder);
                portfolio.CashBook[CashBook.AccountCurrency].AddAmount(-feeThisOrder);

                // apply the funds using the current settlement model
                security.SettlementModel.ApplyFunds(portfolio, security, fill.UtcTime, quoteCash.Symbol, -fill.FillQuantity * fill.FillPrice * security.SymbolProperties.ContractMultiplier);
                if (security.Type == SecurityType.Forex)
                {
                    // model forex fills as currency swaps
                    var forex = (Forex.Forex) security;
                    security.SettlementModel.ApplyFunds(portfolio, security, fill.UtcTime, forex.BaseCurrencySymbol, fill.FillQuantity);
                }
                
                // did we close or open a position further?
                closedPosition = isLong && fill.Direction == OrderDirection.Sell
                             || isShort && fill.Direction == OrderDirection.Buy;

                // calculate the last trade profit
                if (closedPosition)
                {
                    // profit = (closed sale value - cost)*conversion to account currency
                    // closed sale value = quantity closed * fill price       BUYs are deemed negative cash flow
                    // cost = quantity closed * average holdings price        SELLS are deemed positive cash flow
                    var absoluteQuantityClosed = Math.Min(fill.AbsoluteFillQuantity, absoluteHoldingsQuantity);
                    var closedSaleValueInQuoteCurrency = Math.Sign(-fill.FillQuantity)*fill.FillPrice*absoluteQuantityClosed;
                    var closedCost = Math.Sign(-fill.FillQuantity)*absoluteQuantityClosed*averageHoldingsPrice;
                    var conversionFactor = security.QuoteCurrency.ConversionRate*security.SymbolProperties.ContractMultiplier;
                    var lastTradeProfit = (closedSaleValueInQuoteCurrency - closedCost)*conversionFactor;

                    //Update Vehicle Profit Tracking:
                    security.Holdings.AddNewProfit(lastTradeProfit);
                    security.Holdings.SetLastTradeProfit(lastTradeProfit);
                    portfolio.AddTransactionRecord(security.LocalTime.ConvertToUtc(security.Exchange.TimeZone), lastTradeProfit - 2*feeThisOrder);
                }

                //UPDATE HOLDINGS QUANTITY, AVG PRICE:
                //Currently NO holdings. The order is ALL our holdings.
                if (quantityHoldings == 0)
                {
                    //First transaction just subtract order from cash and set our holdings:
                    averageHoldingsPrice = fill.FillPrice;
                    quantityHoldings = fill.FillQuantity;
                }
                else if (isLong)
                {
                    //If we're currently LONG on the stock.
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Update the Holding Average Price: Total Value / Total Quantity:
                            averageHoldingsPrice = ((averageHoldingsPrice*quantityHoldings) + (fill.FillQuantity*fill.FillPrice))/(quantityHoldings + fill.FillQuantity);
                            //Add the new quantity:
                            quantityHoldings += fill.FillQuantity;
                            break;

                        case OrderDirection.Sell:
                            quantityHoldings += fill.FillQuantity; //+ a short = a subtraction
                            if (quantityHoldings < 0)
                            {
                                //If we've now passed through zero from selling stock: new avg price:
                                averageHoldingsPrice = fill.FillPrice;
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;
                    }
                }
                else if (isShort)
                {
                    //We're currently SHORTING the stock: What is the new position now?
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Buying when we're shorting moves to close position:
                            quantityHoldings += fill.FillQuantity;
                            if (quantityHoldings > 0)
                            {
                                //If we were short but passed through zero, new average price is what we paid. The short position was closed.
                                averageHoldingsPrice = fill.FillPrice;
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;

                        case OrderDirection.Sell:
                            //We are increasing a Short position:
                            //E.g.  -100 @ $5, adding -100 @ $10: Avg: $7.5
                            //      dAvg = (-500 + -1000) / -200 = 7.5
                            averageHoldingsPrice = ((averageHoldingsPrice*quantityHoldings) + (fill.FillQuantity*fill.FillPrice))/(quantityHoldings + fill.FillQuantity);
                            quantityHoldings += fill.FillQuantity;
                            break;
                    }
                }
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            //Set the results back to the vehicle.
            security.Holdings.SetHoldings(averageHoldingsPrice, Convert.ToInt32(quantityHoldings));
        }
Esempio n. 4
0
        /// <summary>
        /// Performs application of an OrderEvent to the portfolio
        /// </summary>
        /// <param name="portfolio">The algorithm's portfolio</param>
        /// <param name="security">The fill's security</param>
        /// <param name="fill">The order event fill object to be applied</param>
        public virtual void ProcessFill(SecurityPortfolioManager portfolio, Security security, OrderEvent fill)
        {
            //Get the required information from the vehicle this order will affect
            var isLong = security.Holdings.IsLong;
            var isShort = security.Holdings.IsShort;
            var closedPosition = false;
            //Make local decimals to avoid any rounding errors from int multiplication
            var quantityHoldings = (decimal)security.Holdings.Quantity;
            var absoluteHoldingsQuantity = security.Holdings.AbsoluteQuantity;
            var averageHoldingsPrice = security.Holdings.AveragePrice;

            var lastTradeProfit = 0m;

            try
            {
                //Update the Vehicle approximate total sales volume.
                security.Holdings.AddNewSale(fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity));

                //Get the Fee for this Order - Update the Portfolio Cash Balance: Remove Transacion Fees.
                var order = new MarketOrder(security.Symbol, fill.FillQuantity, security.LocalTime.ConvertToUtc(security.Exchange.TimeZone), type: security.Type) {Price = fill.FillPrice, Status = OrderStatus.Filled};
                var feeThisOrder = Math.Abs(security.TransactionModel.GetOrderFee(security, order));
                security.Holdings.AddNewFee(feeThisOrder);
                portfolio.CashBook[CashBook.AccountCurrency].Quantity -= feeThisOrder;

                //Calculate & Update the Last Trade Profit
                if (isLong && fill.Direction == OrderDirection.Sell)
                {
                    //Closing up a long position
                    if (quantityHoldings >= fill.AbsoluteFillQuantity)
                    {
                        //Closing up towards Zero.
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * fill.AbsoluteFillQuantity;

                        //New cash += profitLoss + costOfAsset/leverage.
                        portfolio.CashBook[CashBook.AccountCurrency].Quantity += lastTradeProfit + ((averageHoldingsPrice * fill.AbsoluteFillQuantity));
                    }
                    else
                    {
                        //Closing up to Neg/Short Position (selling more than we have) - Only calc profit on the stock we have to sell.
                        lastTradeProfit = (fill.FillPrice - averageHoldingsPrice) * quantityHoldings;

                        //New cash += profitLoss + costOfAsset/leverage.
                        portfolio.CashBook[CashBook.AccountCurrency].Quantity += lastTradeProfit + ((averageHoldingsPrice * quantityHoldings));
                    }
                    closedPosition = true;
                }
                else if (isShort && fill.Direction == OrderDirection.Buy)
                {
                    //Closing up a short position.
                    if (absoluteHoldingsQuantity >= fill.FillQuantity)
                    {
                        //Reducing the stock we have, and enough stock on hand to process order.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * fill.AbsoluteFillQuantity;

                        //New cash += profitLoss + costOfAsset/leverage.
                        portfolio.CashBook[CashBook.AccountCurrency].Quantity += lastTradeProfit + ((averageHoldingsPrice * fill.AbsoluteFillQuantity));
                    }
                    else
                    {
                        //Increasing stock holdings, short to positive through zero, but only calc profit on stock we Buy.
                        lastTradeProfit = (averageHoldingsPrice - fill.FillPrice) * absoluteHoldingsQuantity;

                        //New cash += profitLoss + costOfAsset/leverage.
                        portfolio.CashBook[CashBook.AccountCurrency].Quantity += lastTradeProfit + ((averageHoldingsPrice * absoluteHoldingsQuantity));
                    }
                    closedPosition = true;
                }

                if (closedPosition)
                {
                    //Update Vehicle Profit Tracking:
                    security.Holdings.AddNewProfit(lastTradeProfit);
                    security.Holdings.SetLastTradeProfit(lastTradeProfit);
                    portfolio.AddTransactionRecord(security.LocalTime.ConvertToUtc(security.Exchange.TimeZone), lastTradeProfit - 2 * feeThisOrder);
                }

                //UPDATE HOLDINGS QUANTITY, AVG PRICE:
                //Currently NO holdings. The order is ALL our holdings.
                if (quantityHoldings == 0)
                {
                    //First transaction just subtract order from cash and set our holdings:
                    averageHoldingsPrice = fill.FillPrice;
                    quantityHoldings = fill.FillQuantity;
                    portfolio.CashBook[CashBook.AccountCurrency].Quantity -= (fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity));
                }
                else if (isLong)
                {
                    //If we're currently LONG on the stock.
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Update the Holding Average Price: Total Value / Total Quantity:
                            averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (fill.FillQuantity * fill.FillPrice)) / (quantityHoldings + (decimal)fill.FillQuantity);
                            //Add the new quantity:
                            quantityHoldings += fill.FillQuantity;
                            //Subtract this order from cash:
                            portfolio.CashBook[CashBook.AccountCurrency].Quantity -= (fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity));
                            break;

                        case OrderDirection.Sell:
                            quantityHoldings += fill.FillQuantity; //+ a short = a subtraction
                            if (quantityHoldings < 0)
                            {
                                //If we've now passed through zero from selling stock: new avg price:
                                averageHoldingsPrice = fill.FillPrice;
                                portfolio.CashBook[CashBook.AccountCurrency].Quantity -= (fill.FillPrice * Math.Abs(quantityHoldings));
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;
                    }
                }
                else if (isShort)
                {
                    //We're currently SHORTING the stock: What is the new position now?
                    switch (fill.Direction)
                    {
                        case OrderDirection.Buy:
                            //Buying when we're shorting moves to close position:
                            quantityHoldings += fill.FillQuantity;
                            if (quantityHoldings > 0)
                            {
                                //If we were short but passed through zero, new average price is what we paid. The short position was closed.
                                averageHoldingsPrice = fill.FillPrice;
                                portfolio.CashBook[CashBook.AccountCurrency].Quantity -= (fill.FillPrice * Math.Abs(quantityHoldings));
                            }
                            else if (quantityHoldings == 0)
                            {
                                averageHoldingsPrice = 0;
                            }
                            break;

                        case OrderDirection.Sell:
                            //We are increasing a Short position:
                            //E.g.  -100 @ $5, adding -100 @ $10: Avg: $7.5
                            //      dAvg = (-500 + -1000) / -200 = 7.5
                            averageHoldingsPrice = ((averageHoldingsPrice * quantityHoldings) + (Convert.ToDecimal(fill.FillQuantity) * fill.FillPrice)) / (quantityHoldings + (decimal)fill.FillQuantity);
                            quantityHoldings += fill.FillQuantity;
                            portfolio.CashBook[CashBook.AccountCurrency].Quantity -= (fill.FillPrice * Convert.ToDecimal(fill.AbsoluteFillQuantity));
                            break;
                    }
                }
            }
            catch (Exception err)
            {
                Log.Error("SecurityPortfolioModel.ProcessFill(): " + err.Message);
            }

            //Set the results back to the vehicle.
            security.Holdings.SetHoldings(averageHoldingsPrice, Convert.ToInt32(quantityHoldings));
        }