Exemplo n.º 1
0
        /// <summary>
        /// Immediately submits orders for the specified portfolio targets.
        /// </summary>
        /// <param name="algorithm">The algorithm instance</param>
        /// <param name="targets">The portfolio targets to be ordered</param>
        public override void Execute(QCAlgorithmFramework algorithm, IPortfolioTarget[] targets)
        {
            //So target.Quantity represents the ABSOLUTE holding value in the portfolio (usually based on indicator magnitude)
            // - the execution model should seek to bring the portfolio in line with it.
            _targetsCollection.AddRange(targets);

            foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
            {
                //only care about derivatives
                if (!target.Symbol.HasUnderlying)
                {
                    continue;
                }

                var existing = algorithm.Securities[target.Symbol].Holdings.Quantity
                               + algorithm.Transactions.GetOpenOrders(target.Symbol).Sum(o => o.Quantity);

                decimal quantity = target.Quantity - existing;

                if (quantity != 0)
                {
                    if (target.Quantity == 0)
                    {
                        //CLOSING a position, we want to do so immediately
                        //TODO: maybe skew it?
                        algorithm.MarketOrder(target.Symbol, quantity);
                    }
                    else if (MinutesTilClose(algorithm) <= 30)
                    {
                        algorithm.MarketOrder(target.Symbol, target.Quantity);
                    }
                    else
                    {
                        //Adding or entering new position
                        QuoteBar quote = algorithm.CurrentSlice[target.Symbol];
                        algorithm.LimitOrder(target.Symbol, quantity, Math.Round(quote.Bid.Close + (quote.Ask.Close - quote.Bid.Close) / 2, 2));
                    }
                }
            }

            //TODO: try resubmitting the order to closer to the spread as time goes by before cancelling/market ordering

            //convert to market order within 30 mins
            foreach (var order in algorithm.Transactions.GetOpenOrders(o => (algorithm.CurrentSlice.Time - o.CreatedTime).TotalMinutes >= 30))
            {
                algorithm.Transactions.CancelOrder(order.Id);
                algorithm.MarketOrder(order.Symbol, order.Quantity);
            }

            _targetsCollection.Clear();
        }