/// <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(QCAlgorithm algorithm, IPortfolioTarget[] targets) { _targetsCollection.AddRange(targets); // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call if (_targetsCollection.Count > 0) { foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { var security = algorithm.Securities[target.Symbol]; // calculate remaining quantity to be ordered var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security); if (quantity != 0) { if (security.BuyingPowerModel.AboveMinimumOrderMarginPortfolioPercentage(security, quantity, algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage)) { algorithm.MarketOrder(security, quantity); } } } _targetsCollection.ClearFulfilled(algorithm); } }
public void OrderByMarginImpactDoesNotReturnTargetsForWhichUnorderedQuantityIsZeroBecauseOpenOrder() { var algorithm = new FakeAlgorithm(); var orderProcessor = new FakeOrderProcessor(); algorithm.Transactions.SetOrderProcessor(orderProcessor); var symbol = new Symbol(SecurityIdentifier.GenerateEquity(_symbol, Market.USA), _symbol); var equity = algorithm.AddEquity(symbol); equity.Cache.AddData(new TradeBar(DateTime.UtcNow, symbol, 1, 1, 1, 1, 1)); var collection = new PortfolioTargetCollection(); var target = new PortfolioTarget(symbol, 1); collection.Add(target); var openOrderRequest = new SubmitOrderRequest(OrderType.Market, symbol.SecurityType, symbol, 1, 0, 0, DateTime.UtcNow, ""); openOrderRequest.SetOrderId(1); var openOrderTicket = new OrderTicket(algorithm.Transactions, openOrderRequest); orderProcessor.AddOrder(new MarketOrder(symbol, 1, DateTime.UtcNow)); orderProcessor.AddTicket(openOrderTicket); var targets = collection.OrderByMarginImpact(algorithm); Assert.AreEqual(collection.Count, 1); Assert.IsTrue(targets.IsNullOrEmpty()); }
/// <summary> /// Submit orders for the specified portolio targets if the spread is tighter/equal to preset level /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="targets">The portfolio targets to be ordered</param> public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets) { // update the complete set of portfolio targets with the new targets _targetsCollection.AddRange(targets); // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call if (_targetsCollection.Count > 0) { foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { var symbol = target.Symbol; // calculate remaining quantity to be ordered var unorderedQuantity = OrderSizing.GetUnorderedQuantity(algorithm, target); if (unorderedQuantity != 0) { // get security object var security = algorithm.Securities[symbol]; // check order entry conditions if (PriceIsFavorable(security)) { algorithm.MarketOrder(symbol, unorderedQuantity); } } } _targetsCollection.ClearFulfilled(algorithm); } }
/// <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(); }
public void OrderByMarginImpactDoesNotReturnTargetsWithNoData() { var algorithm = new FakeAlgorithm(); var symbol = new Symbol(SecurityIdentifier.GenerateEquity(_symbol, Market.USA), _symbol); algorithm.AddEquity(symbol); var collection = new PortfolioTargetCollection(); var target = new PortfolioTarget(symbol, -1); collection.Add(target); var targets = collection.OrderByMarginImpact(algorithm); Assert.AreEqual(collection.Count, 1); Assert.IsTrue(targets.IsNullOrEmpty()); }
/// <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) { _targetsCollection.AddRange(targets); foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { var existing = algorithm.Securities[target.Symbol].Holdings.Quantity + algorithm.Transactions.GetOpenOrders(target.Symbol).Sum(o => o.Quantity); var quantity = target.Quantity - existing; if (quantity != 0) { algorithm.MarketOrder(target.Symbol, quantity); } } _targetsCollection.Clear(); }
/// <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(QCAlgorithm algorithm, IPortfolioTarget[] targets) { _targetsCollection.AddRange(targets); foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { var existing = algorithm.Securities[target.Symbol].Holdings.Quantity + algorithm.Transactions.GetOpenOrderTickets(target.Symbol) .Aggregate(0m, (d, ticket) => d + ticket.Quantity - ticket.QuantityFilled); var quantity = target.Quantity - existing; if (quantity != 0) { algorithm.MarketOrder(target.Symbol, quantity); } } _targetsCollection.ClearFulfilled(algorithm); }
public void OrderByMarginImpactDoesNotReturnTargetsForWhichUnorderdQuantityIsZeroBecauseTargetIsZero() { var algorithm = new FakeAlgorithm(); algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor()); var symbol = new Symbol(SecurityIdentifier.GenerateEquity(_symbol, Market.USA), _symbol); var equity = algorithm.AddEquity(symbol); equity.Cache.AddData(new TradeBar(DateTime.UtcNow, symbol, 1, 1, 1, 1, 1)); var collection = new PortfolioTargetCollection(); var target = new PortfolioTarget(symbol, 0); collection.Add(target); var targets = collection.OrderByMarginImpact(algorithm); Assert.AreEqual(collection.Count, 1); Assert.IsTrue(targets.IsNullOrEmpty()); }
/// <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(QCAlgorithm algorithm, IPortfolioTarget[] targets) { _targetsCollection.AddRange(targets); // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call if (_targetsCollection.Count > 0) { foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { // calculate remaining quantity to be ordered var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target); if (quantity != 0) { algorithm.MarketOrder(target.Symbol, quantity); } } _targetsCollection.ClearFulfilled(algorithm); } }
public void OrderByMarginImpactReturnsExpectedTargets() { var algorithm = new FakeAlgorithm(); algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor()); var symbol = new Symbol(SecurityIdentifier.GenerateEquity(_symbol, Market.USA), _symbol); var equity = algorithm.AddEquity(symbol); equity.Cache.AddData(new TradeBar(DateTime.UtcNow, symbol, 1, 1, 1, 1, 1)); var collection = new PortfolioTargetCollection(); var target = new PortfolioTarget(symbol, -1); collection.Add(target); var targets = collection.OrderByMarginImpact(algorithm); Assert.AreEqual(collection.Count, 1); Assert.AreEqual(targets.Count(), 1); Assert.AreEqual(targets.First(), target); }
/// <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(QCAlgorithm algorithm, IPortfolioTarget[] targets) { _targetsCollection.AddRange(targets); foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm)) { var openQuantity = algorithm.Transactions.GetOpenOrders(target.Symbol) .Sum(x => x.Quantity); var existing = algorithm.Securities[target.Symbol].Holdings.Quantity + openQuantity; var quantity = target.Quantity - existing; // Liquidate positions in Crude Oil ETF that is no longer part of the highest-correlation pair if (_previousSymbol != null && target.Symbol != _previousSymbol) { algorithm.Liquidate(_previousSymbol); } if (quantity != 0) { algorithm.MarketOrder(target.Symbol, quantity); _previousSymbol = target.Symbol; } } _targetsCollection.ClearFulfilled(algorithm); }