/* * 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.Concurrent; using System.Collections.Generic; using Python.Runtime; namespace QuantConnect.Notifications { /// /// Local/desktop implementation of messaging system for Lean Engine. /// public class NotificationManager { private const int RateLimit = 30; private int _count; private DateTime _resetTime; private readonly bool _liveMode; private readonly object _sync = new object(); /// /// Public access to the messages /// public ConcurrentQueue Messages { get; set; } /// /// Initialize the messaging system /// public NotificationManager(bool liveMode) { _count = 0; _liveMode = liveMode; Messages = new ConcurrentQueue(); // start counting reset time based on first invocation of NotificationManager _resetTime = default(DateTime); } /// /// Send an email to the address specified for live trading notifications. /// /// Subject of the email /// Message body, up to 10kb /// Data attachment (optional) /// Email address to send to /// Optional email headers to use public bool Email(string address, string subject, string message, string data, PyObject headers) { return Email(address, subject, message, data, headers.ConvertToDictionary()); } /// /// Send an email to the address specified for live trading notifications. /// /// Subject of the email /// Message body, up to 10kb /// Data attachment (optional) /// Email address to send to /// Optional email headers to use public bool Email(string address, string subject, string message, string data = "", Dictionary headers = null) { if (!Allow()) { return false; } var email = new NotificationEmail(address, subject, message, data, headers); Messages.Enqueue(email); return true; } /// /// Send an SMS to the phone number specified /// /// Phone number to send to /// Message to send public bool Sms(string phoneNumber, string message) { if (!Allow()) { return false; } var sms = new NotificationSms(phoneNumber, message); Messages.Enqueue(sms); return true; } /// /// Place REST POST call to the specified address with the specified DATA. /// /// Endpoint address /// Data to send in body JSON encoded (optional) public bool Web(string address, object data = null) { if (!Allow()) { return false; } var web = new NotificationWeb(address, data); Messages.Enqueue(web); return true; } /// /// Maintain a rate limit of the notification messages per hour send of roughly 20 messages per hour. /// /// True when running in live mode and under the rate limit private bool Allow() { if (!_liveMode) { return false; } lock (_sync) { var now = DateTime.UtcNow; if (now > _resetTime) { _count = 0; // rate limiting set at 30/hour _resetTime = now.Add(TimeSpan.FromHours(1)); } if (_count < RateLimit) { _count++; return true; } return false; } } } }