Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid termination on empty live cash balance #7581

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Brokerages/Brokerage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public virtual bool PerformCashSync(IAlgorithm algorithm, DateTime currentTimeUt

Log.Trace("Brokerage.PerformCashSync(): Sync cash balance");

var balances = new List<CashAmount>();
List<CashAmount> balances = null;
try
{
balances = GetCashBalance();
Expand All @@ -470,7 +470,8 @@ public virtual bool PerformCashSync(IAlgorithm algorithm, DateTime currentTimeUt
Log.Error(err, "Error in GetCashBalance:");
}

if (balances.Count == 0)
// empty cash balance is valid, if there was No error/exception
if (balances == null)
{
Log.Trace("Brokerage.PerformCashSync(): No cash balances available, cash sync not performed");
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,42 @@ public void ProcessSynchronousEventsShouldPerformCashSyncOnlyAtExpectedTime()
Assert.AreEqual(0, brokerage.GetCashBalanceCallCount);
}

[Test]
public void EmptyCashBalanceIsValid()
{
var mock = new Mock<TestBrokerage>
{
CallBase = true
};
var cashBalance = mock.Setup(m => m.GetCashBalance()).Returns(new List<CashAmount>());
mock.Setup(m => m.IsConnected).Returns(true);
mock.Setup(m => m.ShouldPerformCashSync(It.IsAny<DateTime>())).Returns(true);

var brokerage = mock.Object;
Assert.IsTrue(brokerage.IsConnected);

var algorithm = new QCAlgorithm();
var marketHoursDatabase = MarketHoursDatabase.FromDataFolder();
var symbolPropertiesDataBase = SymbolPropertiesDatabase.FromDataFolder();
var securityService = new SecurityService(algorithm.Portfolio.CashBook, marketHoursDatabase, symbolPropertiesDataBase, algorithm, RegisteredSecurityDataTypesProvider.Null, new SecurityCacheProvider(algorithm.Portfolio));
algorithm.Securities.SetSecurityService(securityService);
algorithm.SetLiveMode(true);
algorithm.SetFinishedWarmingUp();

var transactionHandler = new TestBrokerageTransactionHandler();
var resultHandler = new TestResultHandler();
transactionHandler.Initialize(algorithm, brokerage, resultHandler);

// Advance current time UTC so cash sync is performed
transactionHandler.TestCurrentTimeUtc = transactionHandler.TestCurrentTimeUtc.AddDays(2);

transactionHandler.ProcessSynchronousEvents();

resultHandler.Exit();

mock.VerifyAll();
}

[Test]
public void DoesNotLoopEndlesslyIfGetCashBalanceAlwaysThrows()
{
Expand Down
5 changes: 4 additions & 1 deletion Tests/Engine/Setup/BrokerageSetupHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,10 @@ public TestBrokerageFactory() : base(typeof(TestBrokerage))
public override void Dispose() { }
}

internal class TestBrokerage : Brokerage
/// <summary>
/// Public so that mock can access it
/// </summary>
public class TestBrokerage : Brokerage
{
public override bool IsConnected { get; } = true;
public int GetCashBalanceCallCount;
Expand Down