Files
2026-07-13 13:02:50 +08:00

273 lines
13 KiB
C#

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Tests.Common.Securities;
namespace QuantConnect.Tests.Engine.DataFeeds
{
[TestFixture]
public class PendingRemovalsManagerTests
{
private static readonly DateTime Noon = new DateTime(2015, 11, 2, 12, 0, 0);
private static readonly TimeKeeper TimeKeeper = new TimeKeeper(Noon.ConvertToUtc(TimeZones.NewYork), new[] { TimeZones.NewYork });
[Test]
public void ReturnedRemoved_Add()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
var result = pendingRemovals.TryRemoveMember(member, universe);
Assert.IsTrue(result.Any());
Assert.AreEqual(universe, result.First().Universe);
Assert.AreEqual(security, result.First().Security);
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Values.Count());
}
[Test]
public void ReturnedRemoved_Check()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
orderProvider.AddOrder(new LimitOrder(security.Symbol, 1, 1, DateTime.UtcNow));
pendingRemovals.TryRemoveMember(member, universe);
orderProvider.Clear();
var result = pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe);
Assert.IsTrue(result.Any());
Assert.AreEqual(universe, result.First().Universe);
Assert.AreEqual(security, result.First().Security);
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Values.Count());
}
[Test]
public void WontRemoveBecauseOfUnderlying()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var equity = CreateSecurity(Symbols.SPY);
var member = new Universe.Member(Noon, equity, false);
var equityOption = CreateSecurity(Symbols.SPY_C_192_Feb19_2016);
// we add an order of the equity option
orderProvider.AddOrder(new LimitOrder(equityOption.Symbol, 1, 1, DateTime.UtcNow));
using var universe = new TestUniverse();
universe.AddMember(DateTime.UtcNow, equity, false);
universe.AddMember(DateTime.UtcNow, equityOption, false);
// we try to remove the equity
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(equity, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseOpenOrder_Add()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
orderProvider.AddOrder(new LimitOrder(security.Symbol, 1, 1, DateTime.UtcNow));
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseOpenOrder_Check()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
orderProvider.AddOrder(new LimitOrder(security.Symbol, 1, 1, DateTime.UtcNow));
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseHoldings_Add()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
security.Holdings.SetHoldings(10, 10);
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseHoldings_Check()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
security.Holdings.SetHoldings(10, 10);
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseTarget_Add()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
security.Holdings.Target = new PortfolioTarget(security.Symbol, 10);
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontRemoveBecauseTarget_Check()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
security.Holdings.Target = new PortfolioTarget(security.Symbol, 10);
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
[Test]
public void WontBeReturnedBecauseReSelected()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
using var universe = new TestUniverse();
orderProvider.AddOrder(new LimitOrder(security.Symbol, 1, 1, DateTime.UtcNow));
pendingRemovals.TryRemoveMember(member, universe);
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(
new HashSet<Symbol> { security.Symbol}, universe).Any());
// internally it was removed because it was reselected
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(0, pendingRemovals.PendingRemovals.Values.Count());
}
[Test]
public void WontRemoveBecauseUnsettledFunds()
{
var orderProvider = new FakeOrderProcessor();
var pendingRemovals = new PendingRemovalsManager(orderProvider);
using var universe = new TestUniverse();
var security = SecurityTests.GetSecurity();
var member = new Universe.Member(Noon, security, false);
security.SetSettlementModel(new DelayedSettlementModel(1, TimeSpan.FromHours(8)));
var securities = new SecurityManager(TimeKeeper);
var transactions = new SecurityTransactionManager(null, securities);
var portfolio = new SecurityPortfolioManager(securities, transactions, new AlgorithmSettings());
security.SettlementModel.ApplyFunds(new ApplyFundsSettlementModelParameters(portfolio, security, TimeKeeper.UtcTime.Date.AddDays(1),
new CashAmount(1000, Currencies.USD), null));
Assert.IsNull(pendingRemovals.TryRemoveMember(member, universe));
Assert.IsFalse(pendingRemovals.CheckPendingRemovals(new HashSet<Symbol>(), universe).Any());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Keys.Count());
Assert.AreEqual(1, pendingRemovals.PendingRemovals.Values.Count());
Assert.AreEqual(universe, pendingRemovals.PendingRemovals.Keys.First());
Assert.AreEqual(security, pendingRemovals.PendingRemovals.Values.First().First().Security);
}
private class TestUniverse : Universe
{
public TestUniverse()
: base(SecurityTests.CreateTradeBarConfig())
{
}
public override IEnumerable<Symbol> SelectSymbols(DateTime utcTime, BaseDataCollection data)
{
throw new NotImplementedException();
}
}
private static Security CreateSecurity(Symbol symbol)
{
return new Security(symbol,
SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
new Cash(Currencies.USD, 0, 1m),
SymbolProperties.GetDefault(Currencies.USD),
ErrorCurrencyConverter.Instance,
RegisteredSecurityDataTypesProvider.Null,
new SecurityCache()
);
}
}
}