/* * 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.Threading; using QuantConnect.Interfaces; namespace QuantConnect.Lean.Engine.Results { /// /// Monitors and reports the progress of a backtest /// public class BacktestProgressMonitor { private const int ProcessedDaysCountInvalid = 0; private const int ProcessedDaysCountValid = 1; private readonly ITimeKeeper _timeKeeper; private readonly DateTime _startUtcTime; private int _processedDays; private int _isProcessedDaysCountValid; /// /// Gets the total days the algorithm will run /// public int TotalDays { get; private set; } /// /// Gets the current days the algorithm has been running for /// public int ProcessedDays { get { if (Interlocked.CompareExchange(ref _isProcessedDaysCountValid, ProcessedDaysCountValid, ProcessedDaysCountInvalid) == ProcessedDaysCountInvalid) { try { // We use 'int' so it's thread safe _processedDays = (int)(_timeKeeper.UtcTime - _startUtcTime).TotalDays; } catch (OverflowException) { } } return _processedDays; } } /// /// Gets the current progress of the backtest /// public decimal Progress { get { return Math.Min((decimal)ProcessedDays / TotalDays, 0.999m); } } /// /// Creates a new instance /// /// The time keeper to use /// The end UTC time public BacktestProgressMonitor(ITimeKeeper timeKeeper, DateTime endUtcTime) { _timeKeeper = timeKeeper; _startUtcTime = _timeKeeper.UtcTime; TotalDays = Convert.ToInt32((endUtcTime.Date - _startUtcTime.Date).TotalDays) + 1; } /// /// Invalidates the processed days count value so it gets recalculated next time it is needed /// public void InvalidateProcessedDays() { Interlocked.Exchange(ref _isProcessedDaysCountValid, ProcessedDaysCountInvalid); } } }