예제 #1
0
 /// <summary>
 /// Returned an ordered enumerable where position reducing orders are executed first
 /// and the remaining orders are executed in decreasing order value.
 /// Will NOT return targets for securities that have no data yet.
 /// Will NOT return targets for which current holdings + open orders quantity, sum up to the target quantity
 /// </summary>
 /// <param name="algorithm">The algorithm instance</param>
 public IEnumerable <IPortfolioTarget> OrderByMarginImpact(IAlgorithm algorithm)
 {
     if (Count == 0)
     {
         // shortcut for performance
         return(Enumerable.Empty <IPortfolioTarget>());
     }
     return(_targets
            .Select(x => x.Value)
            .Where(x => {
         var security = algorithm.Securities[x.Symbol];
         return security.HasData &&
         Math.Abs(OrderSizing.GetUnorderedQuantity(algorithm, x)) >= security.SymbolProperties.LotSize;
     })
            .Select(x => new {
         PortfolioTarget = x,
         TargetQuantity = x.Quantity,
         ExistingQuantity = algorithm.Portfolio[x.Symbol].Quantity
                            + algorithm.Transactions.GetOpenOrderTickets(x.Symbol)
                            .Aggregate(0m, (d, t) => d + t.Quantity - t.QuantityFilled),
         Price = algorithm.Securities[x.Symbol].Price
     })
            .Select(x => new {
         PortfolioTarget = x.PortfolioTarget,
         OrderValue = Math.Abs((x.TargetQuantity - x.ExistingQuantity) * x.Price),
         IsReducingPosition = x.ExistingQuantity != 0 && Math.Abs(x.TargetQuantity) < Math.Abs(x.ExistingQuantity)
     })
            .OrderByDescending(x => x.IsReducingPosition)
            .ThenByDescending(x => x.OrderValue)
            .Select(x => x.PortfolioTarget));
 }
예제 #2
0
        public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
        {
            var orders = targets.GroupBy(t => t.Symbol)
                         .Select(
                g => new
            {
                Symbol   = g.Key,
                Quantity = g.Sum(x => OrderSizing.GetUnorderedQuantity(algorithm, x))
            }
                )
                         .Where(order =>
                                algorithm.Securities[order.Symbol].HasData &&
                                order.Quantity != 0);

            foreach (var order in orders)
            {
                var tickets = DoExecute(algorithm, order.Symbol, order.Quantity);

                foreach (var ticket in tickets)
                {
                    ticket.OrderClosed
                    .WaitOneAsync()
                    .ContinueWith(
                        task =>
                    {
                        if (task.Result)
                        {
                            algorithm.Debug($"{algorithm.Time} - ({ticket.OrderId}) {ticket.QuantityFilled} share of {ticket.Symbol} is filled @{ticket.AverageFillPrice}.");
                        }
                    }
                        );
                }
            }
        }
예제 #3
0
        public void AdjustByLotSize(decimal quantity, decimal expected)
        {
            var algo     = new AlgorithmStub();
            var security = algo.AddEquity(Symbols.SPY.Value);

            var result = OrderSizing.AdjustByLotSize(security, quantity);

            Assert.AreEqual(expected, result);
        }
예제 #4
0
        public void GetOrderSizeForPercentVolume()
        {
            var algo     = new AlgorithmStub();
            var security = algo.AddFutureContract(Symbols.Future_CLF19_Jan2019);

            security.SetMarketPrice(new TradeBar {
                Value = 250, Volume = 10
            });

            var result = OrderSizing.GetOrderSizeForPercentVolume(security, 0.5m, 100);

            Assert.AreEqual(5, result);
        }
예제 #5
0
        public void GetUnorderedQuantityHoldingsNoOrders(decimal holdings, decimal target, decimal expected)
        {
            var algo = new AlgorithmStub();

            algo.Transactions.SetOrderProcessor(new FakeOrderProcessor());
            var security = algo.AddFutureContract(Symbols.Future_CLF19_Jan2019);

            security.SetMarketPrice(new TradeBar {
                Value = 250
            });
            security.Holdings.SetHoldings(250, holdings);

            var result = OrderSizing.GetUnorderedQuantity(algo,
                                                          new PortfolioTarget(Symbols.Future_CLF19_Jan2019, target));

            Assert.AreEqual(expected, result);
        }
예제 #6
0
        public void GetOrderSizeForMaximumValue(decimal maximumOrderValue, decimal target, decimal expected)
        {
            var algo     = new AlgorithmStub();
            var security = algo.AddFutureContract(Symbols.Future_CLF19_Jan2019);

            security.SetMarketPrice(new TradeBar {
                Value = 250
            });

            var result = OrderSizing.GetOrderSizeForMaximumValue(security, maximumOrderValue, target);

            var expectedCalculated = maximumOrderValue / (security.Price * security.SymbolProperties.ContractMultiplier);

            expectedCalculated -= expectedCalculated % security.SymbolProperties.LotSize;

            Assert.AreEqual(Math.Min(expectedCalculated, Math.Abs(target)) * Math.Sign(target), result);
            Assert.AreEqual(expected, result);
        }
예제 #7
0
        public void GetUnorderedQuantityHoldingsOpenOrders(decimal holdings, decimal target, decimal filledQuantity, decimal expected)
        {
            var algo           = new AlgorithmStub();
            var orderProcessor = new FakeOrderProcessor();
            var orderRequest   = new SubmitOrderRequest(
                OrderType.Market,
                SecurityType.Future,
                Symbols.Future_CLF19_Jan2019,
                filledQuantity * 2,
                250,
                250,
                new DateTime(2020, 1, 1),
                "Pepe"
                );

            var order  = Order.CreateOrder(orderRequest);
            var ticket = new OrderTicket(algo.Transactions, orderRequest);

            ticket.SetOrder(order);

            ticket.AddOrderEvent(new OrderEvent(1,
                                                Symbols.Future_CLF19_Jan2019,
                                                new DateTime(2020, 1, 1),
                                                OrderStatus.Filled,
                                                filledQuantity > 0 ? OrderDirection.Buy : OrderDirection.Sell,
                                                250,
                                                filledQuantity,
                                                OrderFee.Zero));

            orderProcessor.AddTicket(ticket);
            algo.Transactions.SetOrderProcessor(orderProcessor);
            var security = algo.AddFutureContract(Symbols.Future_CLF19_Jan2019);

            security.SetMarketPrice(new TradeBar {
                Value = 250
            });
            security.Holdings.SetHoldings(250, holdings);

            var result = OrderSizing.GetUnorderedQuantity(algo,
                                                          new PortfolioTarget(Symbols.Future_CLF19_Jan2019, target));

            Assert.AreEqual(expected, result);
        }