/* * 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 QuantConnect.Scheduling; namespace QuantConnect { /// /// Provides access to the and extension methods supporting /// public static class IsolatorLimitResultProvider { /// /// Provides access to a null implementation of /// public static readonly IIsolatorLimitResultProvider Null = new NullIsolatorLimitResultProvider(); /// /// Convenience method for invoking a scheduled event's Scan method inside the /// public static void Consume( this IIsolatorLimitResultProvider isolatorLimitProvider, ScheduledEvent scheduledEvent, DateTime scanTimeUtc, TimeMonitor timeMonitor ) { // perform initial filtering to prevent starting a task when not necessary if (scheduledEvent.NextEventUtcTime > scanTimeUtc) { return; } var timeProvider = RealTimeProvider.Instance; isolatorLimitProvider.Consume(timeProvider, () => scheduledEvent.Scan(scanTimeUtc), timeMonitor); } /// /// Executes the provided code block and while the code block is running, continually consume from /// the limit result provided one token each minute. This function allows the code to run for the /// first full minute without requesting additional time from the provider. Following that, every /// minute an additional one minute will be requested from the provider. /// /// /// This method exists to support scheduled events, and as such, intercepts any errors raised via the /// provided code and wraps them in a . If in the future this is /// usable elsewhere, consider refactoring to handle the errors in a different fashion. /// public static void Consume( this IIsolatorLimitResultProvider isolatorLimitProvider, ITimeProvider timeProvider, Action code, TimeMonitor timeMonitor ) { var consumer = new TimeConsumer { IsolatorLimitProvider = isolatorLimitProvider, TimeProvider = timeProvider }; timeMonitor.Add(consumer); code(); consumer.Finished = true; } private sealed class NullIsolatorLimitResultProvider : IIsolatorLimitResultProvider { private static readonly IsolatorLimitResult OK = new IsolatorLimitResult(TimeSpan.Zero, string.Empty); public void RequestAdditionalTime(int minutes) { } public IsolatorLimitResult IsWithinLimit() { return OK; } public bool TryRequestAdditionalTime(int minutes) { return true; } } } }