Exemplo n.º 1
0
        /// <summary>
        /// Calculate the order quantity to achieve target-percent holdings.
        /// </summary>
        /// <param name="symbol">Security object we're asking for</param>
        /// <param name="target">Target percentag holdings, this is an unlevered value, so 
        /// if you have 2x leverage and request 100% holdings, it will utilize half of the 
        /// available margin</param>
        /// <returns>Order quantity to achieve this percentage</returns>
        public int CalculateOrderQuantity(Symbol symbol, decimal target)
        {
            var security = Securities[symbol];
            var price = security.Price;

            // can't order it if we don't have data
            if (price == 0) return 0;

            // this is the value in dollars that we want our holdings to have
            var targetPortfolioValue = target*Portfolio.TotalPortfolioValue;
            var quantity = security.Holdings.Quantity;
            var currentHoldingsValue = price*quantity;

            // remove directionality, we'll work in the land of absolutes
            var targetOrderValue = Math.Abs(targetPortfolioValue - currentHoldingsValue);
            var direction = targetPortfolioValue > currentHoldingsValue ? OrderDirection.Buy : OrderDirection.Sell;

            // define lower and upper thresholds for the iteration
            var lowerThreshold = targetOrderValue - price/2;
            var upperThreshold = targetOrderValue + price/2;

            // continue iterating while  we're still not within the specified thresholds
            var iterations = 0;
            var orderQuantity = 0;
            decimal orderValue = 0;
            while ((orderValue < lowerThreshold || orderValue > upperThreshold) && iterations < 10)
            {
                // find delta from where we are to where we want to be
                var delta = targetOrderValue - orderValue;
                // use delta value to compute a change in quantity required
                var deltaQuantity = (int)(delta / price);

                orderQuantity += deltaQuantity;

                // recompute order fees
                var order = new MarketOrder(security.Symbol, orderQuantity, UtcTime, type: security.Type);
                var fee = security.TransactionModel.GetOrderFee(security, order);

                orderValue = Math.Abs(order.GetValue(price)) + fee;

                // we need to add the fee in as well, even though it's not value, it's still a cost for the transaction
                // and we need to account for it to be sure we can make the trade produced by this method, imagine
                // set holdings 100% with 1x leverage, but a high fee structure, it quickly becomes necessary to include
                // otherwise the result of this function will be inactionable.

                iterations++;
            }

            // add directionality back in
            return (direction == OrderDirection.Sell ? -1 : 1) * orderQuantity;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Calculate the order quantity to achieve target-percent holdings.
        /// </summary>
        /// <param name="symbol">Security object we're asking for</param>
        /// <param name="target">Target percentag holdings, this is an unlevered value, so 
        /// if you have 2x leverage and request 100% holdings, it will utilize half of the 
        /// available margin</param>
        /// <returns>Order quantity to achieve this percentage</returns>
        public int CalculateOrderQuantity(Symbol symbol, decimal target)
        {
            var security = Securities[symbol];
            var price = security.Price;

            // can't order it if we don't have data
            if (price == 0) return 0;

            // if targeting zero, simply return the negative of the quantity
            if (target == 0) return -security.Holdings.Quantity;

            // this is the value in dollars that we want our holdings to have
            var targetPortfolioValue = target*Portfolio.TotalPortfolioValue;
            var quantity = security.Holdings.Quantity;
            var currentHoldingsValue = price*quantity;

            // remove directionality, we'll work in the land of absolutes
            var targetOrderValue = Math.Abs(targetPortfolioValue - currentHoldingsValue);
            var direction = targetPortfolioValue > currentHoldingsValue ? OrderDirection.Buy : OrderDirection.Sell;

            // determine the unit price in terms of the account currency
            var unitPrice = new MarketOrder(symbol, 1, UtcTime).GetValue(security);

            // calculate the total margin available
            var marginRemaining = Portfolio.GetMarginRemaining(symbol, direction);
            if (marginRemaining <= 0) return 0;

            // continue iterating while we do not have enough margin for the order
            decimal marginRequired;
            decimal orderValue;
            decimal orderFees;
            var feeToPriceRatio = 0;

            // compute the initial order quantity
            var orderQuantity = (int)(targetOrderValue / unitPrice);
            var iterations = 0;

            do
            {
                // decrease the order quantity
                if (iterations > 0)
                {
                    // if fees are high relative to price, we reduce the order quantity faster
                    if (feeToPriceRatio > 0)
                        orderQuantity -= feeToPriceRatio;
                    else
                        orderQuantity--;
                }

                // generate the order
                var order = new MarketOrder(security.Symbol, orderQuantity, UtcTime);
                orderValue = order.GetValue(security);
                orderFees = security.FeeModel.GetOrderFee(security, order);
                feeToPriceRatio = (int)(orderFees / unitPrice);

                // calculate the margin required for the order
                marginRequired = security.MarginModel.GetInitialMarginRequiredForOrder(security, order);

                iterations++;

            } while (orderQuantity > 0 && (marginRequired > marginRemaining || orderValue + orderFees > targetOrderValue));

            // add directionality back in
            return (direction == OrderDirection.Sell ? -1 : 1) * orderQuantity;
        }