/*
* 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 System.Linq.Expressions;
using NodaTime;
using NodaTime.TimeZones;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Interfaces;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Parameters;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Cfd;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Option;
using QuantConnect.Statistics;
using QuantConnect.Util;
using System.Collections.Concurrent;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Crypto;
using System.Net;
using QuantConnect.Algorithm.Framework.Alphas;
namespace QuantConnect.Algorithm
{
///
/// QC Algorithm Base Class - Handle the basic requirements of a trading algorithm,
/// allowing user to focus on event methods. The QCAlgorithm class implements Portfolio,
/// Securities, Transactions and Data Subscription Management.
///
public partial class QCAlgorithm : MarshalByRefObject, IAlgorithm
{
private readonly TimeKeeper _timeKeeper;
private LocalTimeKeeper _localTimeKeeper;
private DateTime _startDate; //Default start and end dates.
private DateTime _endDate; //Default end to yesterday
private RunMode _runMode = RunMode.Series;
private bool _locked;
private bool _liveMode;
private string _algorithmId = "";
private ConcurrentQueue _debugMessages = new ConcurrentQueue();
private ConcurrentQueue _logMessages = new ConcurrentQueue();
private ConcurrentQueue _errorMessages = new ConcurrentQueue();
//Error tracking to avoid message flooding:
private string _previousDebugMessage = "";
private string _previousErrorMessage = "";
private readonly SymbolPropertiesDatabase _symbolPropertiesDatabase;
///
/// Gets the market hours database in use by this algorithm
///
protected MarketHoursDatabase MarketHoursDatabase { get; }
// used for calling through to void OnData(Slice) if no override specified
private bool _checkedForOnDataSlice;
private Action _onDataSlice;
// set by SetBenchmark helper API functions
private Symbol _benchmarkSymbol = QuantConnect.Symbol.Empty;
// flips to true when the user
private bool _userSetSecurityInitializer = false;
// warmup resolution variables
private TimeSpan? _warmupTimeSpan;
private int? _warmupBarCount;
private Resolution? _warmupResolution;
private Dictionary _parameters = new Dictionary();
///
/// QCAlgorithm Base Class Constructor - Initialize the underlying QCAlgorithm components.
/// QCAlgorithm manages the transactions, portfolio, charting and security subscriptions for the users algorithms.
///
public QCAlgorithm()
{
Name = GetType().Name;
Status = AlgorithmStatus.Running;
// AlgorithmManager will flip this when we're caught up with realtime
IsWarmingUp = true;
//Initialise the Algorithm Helper Classes:
//- Note - ideally these wouldn't be here, but because of the DLL we need to make the classes shared across
// the Worker & Algorithm, limiting ability to do anything else.
//Initialise Start and End Dates:
_startDate = new DateTime(1998, 01, 01);
_endDate = DateTime.Now.AddDays(-1);
// intialize our time keeper with only new york
_timeKeeper = new TimeKeeper(_startDate, new[] { TimeZones.NewYork });
// set our local time zone
_localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork);
Settings = new AlgorithmSettings();
DefaultOrderProperties = new OrderProperties();
//Initialise Data Manager
SubscriptionManager = new SubscriptionManager(Settings, _timeKeeper);
Securities = new SecurityManager(_timeKeeper);
Transactions = new SecurityTransactionManager(this, Securities);
Portfolio = new SecurityPortfolioManager(Securities, Transactions, DefaultOrderProperties);
BrokerageModel = new DefaultBrokerageModel();
Notify = new NotificationManager(false); // Notification manager defaults to disabled.
//Initialise Algorithm RunMode to Series - Parallel Mode deprecated:
_runMode = RunMode.Series;
//Initialise to unlocked:
_locked = false;
// get exchange hours loaded from the market-hours-database.csv in /Data/market-hours
MarketHoursDatabase = MarketHoursDatabase.FromDataFolder();
// get symbol properties loaded from the symbol-properties-database.csv in /Data/symbol-properties
_symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder();
// universe selection
UniverseManager = new UniverseManager();
Universe = new UniverseDefinitions(this);
UniverseSettings = new UniverseSettings(Resolution.Minute, 2m, true, false, TimeSpan.FromDays(1));
// initialize our scheduler, this acts as a liason to the real time handler
Schedule = new ScheduleManager(Securities, TimeZone);
// initialize the trade builder
TradeBuilder = new TradeBuilder(FillGroupingMethod.FillToFill, FillMatchingMethod.FIFO);
SecurityInitializer = new BrokerageModelSecurityInitializer(new DefaultBrokerageModel(AccountType.Margin), SecuritySeeder.Null);
CandlestickPatterns = new CandlestickPatterns(this);
// initialize trading calendar
TradingCalendar = new TradingCalendar(Securities, MarketHoursDatabase);
OptionChainProvider = new EmptyOptionChainProvider();
FutureChainProvider = new EmptyFutureChainProvider();
}
///
/// Event fired when the algorithm generates insights
///
public event AlgorithmEvent InsightsGenerated;
///
/// Security collection is an array of the security objects such as Equities and FOREX. Securities data
/// manages the properties of tradeable assets such as price, open and close time and holdings information.
///
public SecurityManager Securities
{
get;
set;
}
///
/// Read-only dictionary containing all active securities. An active security is
/// a security that is currently selected by the universe or has holdings or open orders.
///
public IReadOnlyDictionary ActiveSecurities => UniverseManager.ActiveSecurities;
///
/// Portfolio object provieds easy access to the underlying security-holding properties; summed together in a way to make them useful.
/// This saves the user time by providing common portfolio requests in a single
///
public SecurityPortfolioManager Portfolio
{
get;
set;
}
///
/// Generic Data Manager - Required for compiling all data feeds in order, and passing them into algorithm event methods.
/// The subscription manager contains a list of the data feed's we're subscribed to and properties of each data feed.
///
public SubscriptionManager SubscriptionManager
{
get;
set;
}
///
/// Gets the brokerage model - used to model interactions with specific brokerages.
///
public IBrokerageModel BrokerageModel
{
get;
private set;
}
///
/// Gets the brokerage message handler used to decide what to do
/// with each message sent from the brokerage
///
public IBrokerageMessageHandler BrokerageMessageHandler
{
get;
set;
}
///
/// Notification Manager for Sending Live Runtime Notifications to users about important events.
///
public NotificationManager Notify
{
get;
set;
}
///
/// Gets schedule manager for adding/removing scheduled events
///
public ScheduleManager Schedule
{
get;
private set;
}
///
/// Gets or sets the current status of the algorithm
///
public AlgorithmStatus Status
{
get;
set;
}
///
/// Returns false since algorithms derived from this do not use the framework
///
public virtual bool IsFrameworkAlgorithm
{
get { return false; }
}
///
/// Gets an instance that is to be used to initialize newly created securities.
///
public ISecurityInitializer SecurityInitializer
{
get;
private set;
}
///
/// Gets the Trade Builder to generate trades from executions
///
public ITradeBuilder TradeBuilder
{
get;
private set;
}
///
/// Gets an instance to access the candlestick pattern helper methods
///
public CandlestickPatterns CandlestickPatterns
{
get;
private set;
}
///
/// Gets the date rules helper object to make specifying dates for events easier
///
public DateRules DateRules
{
get { return Schedule.DateRules; }
}
///
/// Gets the time rules helper object to make specifying times for events easier
///
public TimeRules TimeRules
{
get { return Schedule.TimeRules; }
}
///
/// Gets trading calendar populated with trading events
///
public TradingCalendar TradingCalendar
{
get;
private set;
}
///
/// Gets the user settings for the algorithm
///
public AlgorithmSettings Settings
{
get;
private set;
}
///
/// Gets the option chain provider, used to get the list of option contracts for an underlying symbol
///
public IOptionChainProvider OptionChainProvider { get; private set; }
///
/// Gets the future chain provider, used to get the list of future contracts for an underlying symbol
///
public IFutureChainProvider FutureChainProvider { get; private set; }
///
/// Gets the default order properties
///
public IOrderProperties DefaultOrderProperties { get; set; }
///
/// Public name for the algorithm as automatically generated by the IDE. Intended for helping distinguish logs by noting
/// the algorithm-id.
///
///
public string Name
{
get;
set;
}
///
/// Read-only value for current time frontier of the algorithm in terms of the
///
/// During backtesting this is primarily sourced from the data feed. During live trading the time is updated from the system clock.
public DateTime Time
{
get { return _localTimeKeeper.LocalTime; }
}
///
/// Current date/time in UTC.
///
public DateTime UtcTime
{
get { return _timeKeeper.UtcTime; }
}
///
/// Gets the time zone used for the property. The default value
/// is
///
public DateTimeZone TimeZone
{
get { return _localTimeKeeper.TimeZone; }
}
///
/// Value of the user set start-date from the backtest.
///
/// This property is set with SetStartDate() and defaults to the earliest QuantConnect data available - Jan 1st 1998. It is ignored during live trading
///
public DateTime StartDate
{
get
{
return _startDate;
}
}
///
/// Value of the user set start-date from the backtest. Controls the period of the backtest.
///
/// This property is set with SetEndDate() and defaults to today. It is ignored during live trading.
///
public DateTime EndDate
{
get
{
return _endDate;
}
}
///
/// Algorithm Id for this backtest or live algorithm.
///
/// A unique identifier for
public string AlgorithmId
{
get
{
return _algorithmId;
}
}
///
/// Control the server setup run style for the backtest: Automatic, Parallel or Series.
///
///
/// Series mode runs all days through one computer, allowing memory of the previous days.
/// Parallel mode runs all days separately which maximises speed but gives no memory of a previous day trading.
///
/// The RunMode enum propert is now obsolete. All algorithms will default to RunMode.Series for series backtests.
[Obsolete("The RunMode enum propert is now obsolete. All algorithms will default to RunMode.Series for series backtests.")]
public RunMode RunMode
{
get
{
return _runMode;
}
}
///
/// Boolean property indicating the algorithm is currently running in live mode.
///
/// Intended for use where certain behaviors will be enabled while the algorithm is trading live: such as notification emails, or displaying runtime statistics.
public bool LiveMode
{
get
{
return _liveMode;
}
}
///
/// Storage for debugging messages before the event handler has passed control back to the Lean Engine.
///
///
public ConcurrentQueue DebugMessages
{
get
{
return _debugMessages;
}
set
{
_debugMessages = value;
}
}
///
/// Storage for log messages before the event handlers have passed control back to the Lean Engine.
///
///
public ConcurrentQueue LogMessages
{
get
{
return _logMessages;
}
set
{
_logMessages = value;
}
}
///
/// Gets the run time error from the algorithm, or null if none was encountered.
///
public Exception RunTimeError { get; set; }
///
/// List of error messages generated by the user's code calling the "Error" function.
///
/// This method is best used within a try-catch bracket to handle any runtime errors from a user algorithm.
///
public ConcurrentQueue ErrorMessages
{
get
{
return _errorMessages;
}
set
{
_errorMessages = value;
}
}
///
/// Returns the current Slice object
///
public Slice CurrentSlice { get; private set; }
///
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
///
///
///
///
public virtual void Initialize()
{
//Setup Required Data
throw new NotImplementedException("Please override the Initialize() method");
}
///
/// Called by setup handlers after Initialize and allows the algorithm a chance to organize
/// the data gather in the Initialize method
///
public virtual void PostInitialize()
{
// if the benchmark hasn't been set yet, set it
if (Benchmark == null)
{
if (_benchmarkSymbol != null)
{
// if the requested benchmark symbol wasn't already added, then add it now
// we do a simple compare here for simplicity, also it avoids confusion over
// the desired market.
Security security;
if (!Securities.TryGetValue(_benchmarkSymbol, out security))
{
// add the security as an internal feed so the algorithm doesn't receive the data
security = CreateBenchmarkSecurity();
AddToUserDefinedUniverse(security);
}
// just return the current price
Benchmark = new SecurityBenchmark(security);
}
else
{
var start = StartDate;
var startingCapital = Portfolio.TotalPortfolioValue;
Benchmark = new FuncBenchmark(dt =>
{
var years = (dt - start).TotalDays / 365.25;
return startingCapital * (decimal) Math.Exp(0.02 * years);
});
}
}
// perform end of time step checks, such as enforcing underlying securities are in raw data mode
OnEndOfTimeStep();
}
///
/// Called when the algorithm has completed initialization and warm up.
///
public virtual void OnWarmupFinished()
{
}
///
/// Gets the parameter with the specified name. If a parameter
/// with the specified name does not exist, null is returned
///
/// The name of the parameter to get
/// The value of the specified parameter, or null if not found
public string GetParameter(string name)
{
string value;
return _parameters.TryGetValue(name, out value) ? value : null;
}
///
/// Gets a read-only dictionary with all current parameters
///
public IReadOnlyDictionary GetParameters()
{
return _parameters.ToReadOnlyDictionary();
}
///
/// Sets the parameters from the dictionary
///
/// Dictionary containing the parameter names to values
public void SetParameters(Dictionary parameters)
{
// save off a copy and try to apply the parameters
_parameters = parameters.ToDictionary();
try
{
ParameterAttribute.ApplyAttributes(parameters, this);
}
catch (Exception err)
{
Error("Error applying parameter values: " + err.Message);
}
}
///
/// Set the available data feeds in the
///
/// The different each supports
public void SetAvailableDataTypes(Dictionary> availableDataTypes)
{
foreach (var dataFeed in availableDataTypes)
{
SubscriptionManager.AvailableDataTypes[dataFeed.Key] = dataFeed.Value;
}
}
///
/// Sets the security initializer, used to initialize/configure securities after creation.
/// The initializer will be applied to all universes and manually added securities.
///
/// The security initializer
public void SetSecurityInitializer(ISecurityInitializer securityInitializer)
{
if (_locked)
{
throw new Exception("SetSecurityInitializer() cannot be called after algorithm initialization. " +
"When you use the SetSecurityInitializer() method it will apply to all universes and manually added securities.");
}
if (_userSetSecurityInitializer)
{
Debug("Warning: SetSecurityInitializer() has already been called, existing security initializers in all universes will be overwritten.");
}
// this flag will prevent calls to SetBrokerageModel from overwriting this initializer
_userSetSecurityInitializer = true;
SecurityInitializer = securityInitializer;
foreach (var universe in UniverseManager.Select(x => x.Value))
{
universe.SetSecurityInitializer(securityInitializer);
}
}
///
/// Sets the security initializer function, used to initialize/configure securities after creation.
/// The initializer will be applied to all universes and manually added securities.
///
/// The security initializer function
[Obsolete("This method is deprecated. Please use this overload: SetSecurityInitializer(Action securityInitializer)")]
public void SetSecurityInitializer(Action securityInitializer)
{
SetSecurityInitializer(new FuncSecurityInitializer(security => securityInitializer(security, false)));
}
///
/// Sets the security initializer function, used to initialize/configure securities after creation.
/// The initializer will be applied to all universes and manually added securities.
///
/// The security initializer function
public void SetSecurityInitializer(Action securityInitializer)
{
SetSecurityInitializer(new FuncSecurityInitializer(securityInitializer));
}
///
/// Sets the option chain provider, used to get the list of option contracts for an underlying symbol
///
/// The option chain provider
public void SetOptionChainProvider(IOptionChainProvider optionChainProvider)
{
OptionChainProvider = optionChainProvider;
}
///
/// Sets the future chain provider, used to get the list of future contracts for an underlying symbol
///
/// The future chain provider
public void SetFutureChainProvider(IFutureChainProvider futureChainProvider)
{
FutureChainProvider = futureChainProvider;
}
///
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
///
///
/// TradeBars bars = slice.Bars;
/// Ticks ticks = slice.Ticks;
/// TradeBar spy = slice["SPY"];
/// List{Tick} aaplTicks = slice["AAPL"]
/// Quandl oil = slice["OIL"]
/// dynamic anySymbol = slice[symbol];
/// DataDictionary{Quandl} allQuandlData = slice.Get{Quand}
/// Quandl oil = slice.Get{Quandl}("OIL")
///
/// The current slice of data keyed by symbol string
public virtual void OnData(Slice slice)
{
// as a default implementation, let's look for and call OnData(Slice) just in case a user forgot to use the override keyword
if (!_checkedForOnDataSlice)
{
_checkedForOnDataSlice = true;
var method = GetType().GetMethods()
.Where(x => x.Name == "OnData")
.Where(x => x.DeclaringType != typeof(QCAlgorithm))
.Where(x => x.GetParameters().Length == 1)
.FirstOrDefault(x => x.GetParameters()[0].ParameterType == typeof (Slice));
if (method == null)
{
return;
}
var self = Expression.Constant(this);
var parameter = Expression.Parameter(typeof (Slice), "data");
var call = Expression.Call(self, method, parameter);
var lambda = Expression.Lambda>(call, parameter);
_onDataSlice = lambda.Compile();
}
// if we have it, then invoke it
if (_onDataSlice != null)
{
_onDataSlice(slice);
}
}
///
/// Used to send data updates to algorithm framework models
///
/// The current data slice
public virtual void OnFrameworkData(Slice slice)
{
// NOP - overriden by QCAlgorithmFramework
}
///
/// Event fired each time the we add/remove securities from the data feed
///
/// Security additions/removals for this time step
public virtual void OnSecuritiesChanged(SecurityChanges changes)
{
}
///
/// Used to send security changes to algorithm framework models
///
/// Security additions/removals for this time step
public virtual void OnFrameworkSecuritiesChanged(SecurityChanges changes)
{
// NOP - overriden by QCAlgorithmFramework
}
//
// Event - v2.0 TRADEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting tradebar data.
//
//
//public void OnData(TradeBars data)
//{
//
//}
//
// Event - v2.0 QUOTEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting quotebar data.
//
//
//public void OnData(QuoteBars data)
//{
//
//}
//
// Event - v2.0 TICK EVENT HANDLER: (Pattern) Basic template for user to override when requesting tick data.
//
// List of Tick Data
//public void OnData(Ticks data)
//{
//
//}
//
// Event - v2.0 OPTIONCHAIN EVENT HANDLER: (Pattern) Basic template for user to override when requesting option data.
//
// List of Tick Data
//public void OnData(OptionChains data)
//{
//
//}
//
// Event - v2.0 SPLIT EVENT HANDLER: (Pattern) Basic template for user to override when inspecting split data.
//
// IDictionary of Split Data Keyed by Symbol String
//public void OnData(Splits data)
//{
//
//}
//
// Event - v2.0 DIVIDEND EVENT HANDLER: (Pattern) Basic template for user to override when inspecting dividend data
//
// IDictionary of Dividend Data Keyed by Symbol String
//public void OnData(Dividends data)
//{
//
//}
//
// Event - v2.0 DELISTING EVENT HANDLER: (Pattern) Basic template for user to override when inspecting delisting data
//
// IDictionary of Delisting Data Keyed by Symbol String
//public void OnData(Delistings data)
//
// Event - v2.0 SYMBOL CHANGED EVENT HANDLER: (Pattern) Basic template for user to override when inspecting symbol changed data
//
// IDictionary of SymbolChangedEvent Data Keyed by Symbol String
//public void OnData(SymbolChangedEvents data)
///
/// Margin call event handler. This method is called right before the margin call orders are placed in the market.
///
/// The orders to be executed to bring this algorithm within margin limits
public virtual void OnMarginCall(List requests)
{
}
///
/// Margin call warning event handler. This method is called when Portfolio.MarginRemaining is under 5% of your Portfolio.TotalPortfolioValue
///
public virtual void OnMarginCallWarning()
{
}
///
/// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
///
/// Method is called 10 minutes before closing to allow user to close out position.
public virtual void OnEndOfDay()
{
}
///
/// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
///
///
/// This method is left for backwards compatibility and is invoked via , if that method is
/// override then this method will not be called without a called to base.OnEndOfDay(string)
///
/// Asset symbol for this end of day event. Forex and equities have different closing hours.
public virtual void OnEndOfDay(string symbol)
{
}
///
/// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
///
/// Asset symbol for this end of day event. Forex and equities have different closing hours.
public virtual void OnEndOfDay(Symbol symbol)
{
OnEndOfDay(symbol.ToString());
}
///
/// End of algorithm run event handler. This method is called at the end of a backtest or live trading operation. Intended for closing out logs.
///
public virtual void OnEndOfAlgorithm()
{
}
///
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
///
/// Order event details containing details of the evemts
/// This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects
public virtual void OnOrderEvent(OrderEvent orderEvent)
{
}
///
/// Option assignment event handler. On an option assignment event for short legs the resulting information is passed to this method.
///
/// Option exercise event details containing details of the assignment
/// This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects
public virtual void OnAssignmentOrderEvent(OrderEvent assignmentEvent)
{
}
///
/// Brokerage message event handler. This method is called for all types of brokerage messages.
///
public virtual void OnBrokerageMessage(BrokerageMessageEvent messageEvent)
{
}
///
/// Brokerage disconnected event handler. This method is called when the brokerage connection is lost.
///
public virtual void OnBrokerageDisconnect()
{
}
///
/// Brokerage reconnected event handler. This method is called when the brokerage connection is restored after a disconnection.
///
public virtual void OnBrokerageReconnect()
{
}
///
/// Update the internal algorithm time frontier.
///
/// For internal use only to advance time.
/// Current datetime.
public void SetDateTime(DateTime frontier)
{
_timeKeeper.SetUtcDateTime(frontier);
}
///
/// Sets the time zone of the property in the algorithm
///
/// The desired time zone
public void SetTimeZone(string timeZone)
{
DateTimeZone tz;
try
{
tz = DateTimeZoneProviders.Tzdb[timeZone];
}
catch (DateTimeZoneNotFoundException)
{
throw new ArgumentException(string.Format("TimeZone with id '{0}' was not found. For a complete list of time zones please visit: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones", timeZone));
}
SetTimeZone(tz);
}
///
/// Sets the time zone of the property in the algorithm
///
/// The desired time zone
public void SetTimeZone(DateTimeZone timeZone)
{
if (_locked)
{
throw new Exception("Algorithm.SetTimeZone(): Cannot change time zone after algorithm running.");
}
if (timeZone == null) throw new ArgumentNullException("timeZone");
_timeKeeper.AddTimeZone(timeZone);
_localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(timeZone);
// the time rules need to know the default time zone as well
TimeRules.SetDefaultTimeZone(timeZone);
// reset the current time according to the time zone
SetDateTime(_startDate.ConvertToUtc(TimeZone));
}
///
/// Set the RunMode for the Servers. If you are running an overnight algorithm, you must select series.
/// Automatic will analyse the selected data, and if you selected only minute data we'll select series for you.
///
/// This method is now obsolete and has no replacement. All algorithms now run in Series mode.
/// Enum RunMode with options Series, Parallel or Automatic. Automatic scans your requested symbols and resolutions and makes a decision on the fastest analysis
[Obsolete("This method is now obsolete and has no replacement. All algorithms now run in Series mode.")]
public void SetRunMode(RunMode mode)
{
if (mode != RunMode.Parallel) return;
Debug("Algorithm.SetRunMode(): RunMode-Parallel Type has been deprecated. Series analysis selected instead");
}
///
/// Sets the brokerage to emulate in backtesting or paper trading.
/// This can be used for brokerages that have been implemented in LEAN
///
/// The brokerage to emulate
/// The account type (Cash or Margin)
public void SetBrokerageModel(BrokerageName brokerage, AccountType accountType = AccountType.Margin)
{
SetBrokerageModel(Brokerages.BrokerageModel.Create(brokerage, accountType));
}
///
/// Sets the brokerage to emulate in backtesting or paper trading.
/// This can be used to set a custom brokerage model.
///
/// The brokerage model to use
public void SetBrokerageModel(IBrokerageModel model)
{
BrokerageModel = model;
if (!_userSetSecurityInitializer)
{
// purposefully use the direct setter vs Set method so we don't flip the switch :/
SecurityInitializer = new BrokerageModelSecurityInitializer(model, SecuritySeeder.Null);
// update models on securities added earlier (before SetBrokerageModel is called)
foreach (var kvp in Securities)
{
var security = kvp.Value;
// save the existing leverage specified in AddSecurity,
// if Leverage needs to be set in a SecurityInitializer,
// SetSecurityInitializer must be called before SetBrokerageModel
var leverage = security.Leverage;
SecurityInitializer.Initialize(security);
// restore the saved leverage
security.SetLeverage(leverage);
}
}
}
///
/// Sets the implementation used to handle messages from the brokerage.
/// The default implementation will forward messages to debug or error
/// and when a occurs, the algorithm
/// is stopped.
///
/// The message handler to use
public void SetBrokerageMessageHandler(IBrokerageMessageHandler handler)
{
if (handler == null)
{
throw new ArgumentNullException("handler");
}
BrokerageMessageHandler = handler;
}
///
/// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
///
/// symbol to use as the benchmark
/// Is the symbol an equity, forex, base, etc. Default SecurityType.Equity
///
/// Must use symbol that is available to the trade engine in your data store(not strictly enforced)
///
[Obsolete("Symbol implicit operator to string is provided for algorithm use only.")]
public void SetBenchmark(SecurityType securityType, string symbol)
{
string market = Market.USA;
this.BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market);
_benchmarkSymbol = QuantConnect.Symbol.Create(symbol, securityType, market);
}
///
/// Sets the benchmark used for computing statistics of the algorithm to the specified symbol, defaulting to SecurityType.Equity
/// if the symbol doesn't exist in the algorithm
///
/// symbol to use as the benchmark
///
/// Overload to accept symbol without passing SecurityType. If symbol is in portfolio it will use that SecurityType, otherwise will default to SecurityType.Equity
///
public void SetBenchmark(string symbol)
{
// check existence
symbol = symbol.ToUpper();
var security = Securities.FirstOrDefault(x => x.Key.Value == symbol).Value;
_benchmarkSymbol = security == null
? QuantConnect.Symbol.Create(symbol, SecurityType.Equity, Market.USA)
: security.Symbol;
}
///
/// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
///
/// symbol to use as the benchmark
public void SetBenchmark(Symbol symbol)
{
_benchmarkSymbol = symbol;
}
///
/// Sets the specified function as the benchmark, this function provides the value of
/// the benchmark at each date/time requested
///
/// The benchmark producing function
public void SetBenchmark(Func benchmark)
{
Benchmark = new FuncBenchmark(benchmark);
}
///
/// Benchmark
///
/// Use Benchmark to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark
///
public IBenchmark Benchmark
{
get;
private set;
}
///
/// Set initial cash for the strategy while backtesting. During live mode this value is ignored
/// and replaced with the actual cash of your brokerage account.
///
/// Starting cash for the strategy backtest
/// Alias of SetCash(decimal)
public void SetCash(double startingCash)
{
SetCash((decimal)startingCash);
}
///
/// Set initial cash for the strategy while backtesting. During live mode this value is ignored
/// and replaced with the actual cash of your brokerage account.
///
/// Starting cash for the strategy backtest
/// Alias of SetCash(decimal)
public void SetCash(int startingCash)
{
SetCash((decimal)startingCash);
}
///
/// Set initial cash for the strategy while backtesting. During live mode this value is ignored
/// and replaced with the actual cash of your brokerage account.
///
/// Starting cash for the strategy backtest
public void SetCash(decimal startingCash)
{
if (!_locked)
{
Portfolio.SetCash(startingCash);
}
else
{
throw new Exception("Algorithm.SetCash(): Cannot change cash available after algorithm initialized.");
}
}
///
/// Set the cash for the specified symbol
///
/// The cash symbol to set
/// Decimal cash value of portfolio
/// The current conversion rate for the
public void SetCash(string symbol, decimal startingCash, decimal conversionRate)
{
if (!_locked)
{
Portfolio.SetCash(symbol, startingCash, conversionRate);
}
else
{
throw new Exception("Algorithm.SetCash(): Cannot change cash available after algorithm initialized.");
}
}
///
/// Set the start date for backtest.
///
/// Int starting date 1-30
/// Int month starting date
/// Int year starting date
///
/// Wrapper for SetStartDate(DateTime).
/// Must be less than end date.
/// Ignored in live trading mode.
///
public void SetStartDate(int year, int month, int day)
{
try
{
var start = new DateTime(year, month, day);
// We really just want the date of the start, so it's 12am of the requested day (first moment of the day)
start = start.Date;
SetStartDate(start);
}
catch (Exception err)
{
throw new Exception("Date Invalid: " + err.Message);
}
}
///
/// Set the end date for a backtest run
///
/// Int end date 1-30
/// Int month end date
/// Int year end date
/// Wrapper for SetEndDate(datetime).
///
public void SetEndDate(int year, int month, int day)
{
try
{
var end = new DateTime(year, month, day);
// we want the end date to be just before the next day (last moment of the day)
end = end.Date.AddDays(1).Subtract(TimeSpan.FromTicks(1));
SetEndDate(end);
}
catch (Exception err)
{
throw new Exception("Date Invalid: " + err.Message);
}
}
///
/// Set the algorithm id (backtestId or live deployId for the algorithmm).
///
/// String Algorithm Id
/// Intended for internal QC Lean Engine use only as a setter for AlgorihthmId
public void SetAlgorithmId(string algorithmId)
{
_algorithmId = algorithmId;
}
///
/// Set the start date for the backtest
///
/// Datetime Start date for backtest
/// Must be less than end date and within data available
///
public void SetStartDate(DateTime start)
{
// no need to set this value in live mode, will be set using the current time.
if (_liveMode) return;
//Round down
start = start.RoundDown(TimeSpan.FromDays(1));
//Validate the start date:
//1. Check range;
if (start < (new DateTime(1900, 01, 01)))
{
throw new Exception("Please select a start date after January 1st, 1900.");
}
//2. Check future date
var todayInAlgorithmTimeZone = DateTime.UtcNow.ConvertFromUtc(TimeZone).Date;
if (start > todayInAlgorithmTimeZone)
{
throw new Exception("Please select start date less than today");
}
//3. Check end date greater:
if (_endDate != new DateTime())
{
if (start > _endDate)
{
throw new Exception("Please select start date less than end date.");
}
}
//4. Check not locked already:
if (!_locked)
{
// this is only or backtesting
if (!LiveMode)
{
_startDate = start;
SetDateTime(_startDate.ConvertToUtc(TimeZone));
}
}
else
{
throw new Exception("Algorithm.SetStartDate(): Cannot change start date after algorithm initialized.");
}
}
///
/// Set the end date for a backtest.
///
/// Datetime value for end date
/// Must be greater than the start date
///
public void SetEndDate(DateTime end)
{
// no need to set this value in live mode, will be set using the current time.
if (_liveMode) return;
//Validate:
//1. Check Range:
if (end > DateTime.Now.Date.AddDays(-1))
{
end = DateTime.Now.Date.AddDays(-1);
}
//2. Check start date less:
if (_startDate != new DateTime())
{
if (end < _startDate)
{
throw new Exception("Please select end date greater than start date.");
}
}
//3. Make this at the very end of the requested date
end = end.RoundDown(TimeSpan.FromDays(1)).AddDays(1).AddTicks(-1);
//4. Check not locked already:
if (!_locked)
{
_endDate = end;
}
else
{
throw new Exception("Algorithm.SetEndDate(): Cannot change end date after algorithm initialized.");
}
}
///
/// Lock the algorithm initialization to avoid user modifiying cash and data stream subscriptions
///
/// Intended for Internal QC Lean Engine use only to prevent accidental manipulation of important properties
public void SetLocked()
{
_locked = true;
}
///
/// Gets whether or not this algorithm has been locked and fully initialized
///
public bool GetLocked()
{
return _locked;
}
///
/// Set live mode state of the algorithm run: Public setter for the algorithm property LiveMode.
///
public void SetLiveMode(bool live)
{
if (!_locked)
{
_liveMode = live;
Notify = new NotificationManager(live);
TradeBuilder.SetLiveMode(live);
if (live)
{
_startDate = DateTime.Today;
_endDate = QuantConnect.Time.EndOfTime;
}
}
}
///
/// Set the implementation to generate trades from executions and market price updates
///
public void SetTradeBuilder(ITradeBuilder tradeBuilder)
{
TradeBuilder = tradeBuilder;
TradeBuilder.SetLiveMode(LiveMode);
}
///
/// Add specified data to our data subscriptions. QuantConnect will funnel this data to the handle data routine.
///
/// MarketType Type: Equity, Commodity, Future, FOREX or Crypto
/// Symbol Reference for the MarketType
/// Resolution of the Data Required
/// When no data available on a tradebar, return the last data that was generated
/// Show the after market data as well
public Security AddSecurity(SecurityType securityType, string symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, bool extendedMarketHours = false)
{
return AddSecurity(securityType, symbol, resolution, fillDataForward, 0, extendedMarketHours);
}
///
/// Add specified data to required list. QC will funnel this data to the handle data routine.
///
/// MarketType Type: Equity, Commodity, Future, FOREX or Crypto
/// Symbol Reference for the MarketType
/// Resolution of the Data Required
/// When no data available on a tradebar, return the last data that was generated
/// Custom leverage per security
/// Extended market hours
/// AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution, bool fillDataForward, decimal leverage, bool extendedMarketHours)
public Security AddSecurity(SecurityType securityType, string symbol, Resolution resolution, bool fillDataForward, decimal leverage, bool extendedMarketHours)
{
return AddSecurity(securityType, symbol, resolution, null, fillDataForward, leverage, extendedMarketHours);
}
///
/// Set a required SecurityType-symbol and resolution for algorithm
///
/// MarketType Type: Equity, Commodity, Future, FOREX or Crypto
/// Symbol Representation of the MarketType, e.g. AAPL
/// Resolution of the MarketType required: MarketData, Second or Minute
/// The market the requested security belongs to, such as 'usa' or 'fxcm'
/// If true, returns the last available data even if none in that timeslice.
/// leverage for this security
/// ExtendedMarketHours send in data from 4am - 8pm, not used for FOREX
public Security AddSecurity(SecurityType securityType, string symbol, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours)
{
// if AddSecurity method is called to add an option or a future, we delegate a call to respective methods
if (securityType == SecurityType.Option)
{
return AddOption(symbol, resolution, market, fillDataForward, leverage);
}
if (securityType == SecurityType.Future)
{
return AddFuture(symbol, resolution, market, fillDataForward, leverage);
}
try
{
if (market == null)
{
if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market))
{
throw new Exception("No default market set for security type: " + securityType);
}
}
Symbol symbolObject;
if (!SymbolCache.TryGetSymbol(symbol, out symbolObject))
{
symbolObject = QuantConnect.Symbol.Create(symbol, securityType, market);
}
var security = SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, MarketHoursDatabase, _symbolPropertiesDatabase, SecurityInitializer,
symbolObject, resolution, fillDataForward, leverage, extendedMarketHours, false, false, LiveMode);
AddToUserDefinedUniverse(security);
return security;
}
catch (Exception err)
{
Error("Algorithm.AddSecurity(): " + err);
return null;
}
}
///
/// Creates and adds a new security to the algorithm
///
/// The equity ticker symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The equity's market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// True to send data during pre and post market sessions. Default is false
/// The new security
public Equity AddEquity(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m, bool extendedMarketHours = false)
{
return AddSecurity(SecurityType.Equity, ticker, resolution, market, fillDataForward, leverage, extendedMarketHours);
}
///
/// Creates and adds a new equity security to the algorithm
///
/// The underlying equity symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The equity's market, . Default is value null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Option AddOption(string underlying, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
{
if (market == null)
{
if (!BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Option, out market))
{
throw new Exception("No default market set for security type: " + SecurityType.Option);
}
}
Symbol canonicalSymbol;
var alias = "?" + underlying;
if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol))
{
canonicalSymbol = QuantConnect.Symbol.Create(underlying, SecurityType.Option, market, alias);
}
var marketHoursEntry = MarketHoursDatabase.GetEntry(market, underlying, SecurityType.Option);
var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(market, underlying, SecurityType.Option, CashBook.AccountCurrency);
var canonicalSecurity = (Option) SecurityManager.CreateSecurity(typeof(ZipEntryName), Portfolio, SubscriptionManager,
marketHoursEntry.ExchangeHours, marketHoursEntry.DataTimeZone, symbolProperties, SecurityInitializer, canonicalSymbol, resolution,
fillDataForward, leverage, false, false, false, LiveMode, true, false);
canonicalSecurity.IsTradable = false;
Securities.Add(canonicalSecurity);
// add this security to the user defined universe
Universe universe;
if (!UniverseManager.TryGetValue(canonicalSymbol, out universe) && _pendingUniverseAdditions.All(u => u.Configuration.Symbol != canonicalSymbol))
{
var settings = new UniverseSettings(resolution, leverage, true, false, TimeSpan.Zero);
universe = new OptionChainUniverse(canonicalSecurity, settings, SecurityInitializer, LiveMode);
_pendingUniverseAdditions.Add(universe);
}
return canonicalSecurity;
}
///
/// Creates and adds a new security to the algorithm
///
/// The futures contract symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The futures market, . Default is value null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Future AddFuture(string symbol, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
{
if (market == null)
{
if (!BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Future, out market))
{
throw new Exception("No default market set for security type: " + SecurityType.Future);
}
}
Symbol canonicalSymbol;
var alias = "/" + symbol;
if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol))
{
canonicalSymbol = QuantConnect.Symbol.Create(symbol, SecurityType.Future, market, alias);
}
var marketHoursEntry = MarketHoursDatabase.GetEntry(market, symbol, SecurityType.Future);
var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(market, symbol, SecurityType.Future, CashBook.AccountCurrency);
var canonicalSecurity = (Future)SecurityManager.CreateSecurity(typeof(ZipEntryName), Portfolio, SubscriptionManager,
marketHoursEntry.ExchangeHours, marketHoursEntry.DataTimeZone, symbolProperties, SecurityInitializer, canonicalSymbol, resolution,
fillDataForward, leverage, false, false, false, LiveMode, true, false);
canonicalSecurity.IsTradable = false;
Securities.Add(canonicalSecurity);
// add this security to the user defined universe
Universe universe;
if (!UniverseManager.TryGetValue(canonicalSymbol, out universe) && _pendingUniverseAdditions.All(u => u.Configuration.Symbol != canonicalSymbol))
{
var settings = new UniverseSettings(resolution, leverage, true, false, TimeSpan.Zero);
universe = new FuturesChainUniverse(canonicalSecurity, settings, SubscriptionManager, SecurityInitializer);
_pendingUniverseAdditions.Add(universe);
}
return canonicalSecurity;
}
///
/// Creates and adds a new single contract to the algorithm
///
/// The futures contract symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Future AddFutureContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m)
{
var future = (Future)SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, MarketHoursDatabase, _symbolPropertiesDatabase, SecurityInitializer,
symbol, resolution, fillDataForward, leverage, false, false, false, LiveMode);
AddToUserDefinedUniverse(future);
return future;
}
///
/// Creates and adds a new single contract to the algorithm
///
/// The option contract symbol
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Option AddOptionContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m)
{
var option = (Option)SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, MarketHoursDatabase, _symbolPropertiesDatabase, SecurityInitializer,
symbol, resolution, fillDataForward, leverage, false, false, false, LiveMode);
// add underlying if not present
var underlying = option.Symbol.Underlying;
Security equity;
if (!Securities.TryGetValue(underlying, out equity))
{
equity = AddEquity(underlying.Value, option.Resolution, underlying.ID.Market, false);
}
else if (equity.DataNormalizationMode != DataNormalizationMode.Raw)
{
Debug($"Warning: The {underlying.ToString()} equity security was set the raw price normalization mode to work with options.");
}
equity.SetDataNormalizationMode(DataNormalizationMode.Raw);
option.Underlying = equity;
AddToUserDefinedUniverse(option);
return option;
}
///
/// Creates and adds a new security to the algorithm
///
/// The currency pair
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The foreign exchange trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Forex AddForex(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
{
return AddSecurity(SecurityType.Forex, ticker, resolution, market, fillDataForward, leverage, false);
}
///
/// Creates and adds a new security to the algorithm
///
/// The currency pair
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Cfd AddCfd(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
{
return AddSecurity(SecurityType.Cfd, ticker, resolution, market, fillDataForward, leverage, false);
}
///
/// Creates and adds a new security to the algorithm
///
/// The currency pair
/// The of market data, Tick, Second, Minute, Hour, or Daily. Default is
/// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in
/// If true, returns the last available data even if none in that timeslice. Default is true
/// The requested leverage for this equity. Default is set by
/// The new security
public Crypto AddCrypto(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
{
return AddSecurity(SecurityType.Crypto, ticker, resolution, market, fillDataForward, leverage, false);
}
///
/// Removes the security with the specified symbol. This will cancel all
/// open orders and then liquidate any existing holdings
///
/// The symbol of the security to be removed
public bool RemoveSecurity(Symbol symbol)
{
Security security;
if (!Securities.TryGetValue(symbol, out security))
{
return false;
}
// cancel open orders
Transactions.CancelOpenOrders(security.Symbol);
// liquidate if invested
if (security.Invested)
{
Liquidate(security.Symbol);
}
// Clear cache
security.Cache.Reset();
// Mark security as not tradable
security.IsTradable = false;
if (symbol.IsCanonical())
{
// remove underlying equity data if it's marked as internal
var universe = UniverseManager.Select(x => x.Value).FirstOrDefault(x => x.Configuration.Symbol == symbol);
if (universe != null)
{
// remove underlying if not used by other universes
var otherUniverses = UniverseManager.Select(ukvp => ukvp.Value).Where(u => !ReferenceEquals(u, universe)).ToList();
if (symbol.HasUnderlying)
{
var underlying = Securities[symbol.Underlying];
if (!otherUniverses.Any(u => u.Members.ContainsKey(underlying.Symbol)))
{
RemoveSecurity(underlying.Symbol);
}
}
// remove child securities (option contracts for option chain universes) if not used in other universes
foreach (var child in universe.Members.Values)
{
if (!otherUniverses.Any(u => u.Members.ContainsKey(child.Symbol)))
{
RemoveSecurity(child.Symbol);
}
}
// finally, dispose and remove the canonical security from the universe manager
UniverseManager.Remove(symbol);
}
}
else
{
var universe = UniverseManager.Select(x => x.Value).OfType().FirstOrDefault(x => x.Members.ContainsKey(symbol));
if (universe != null)
{
universe.Remove(symbol);
// if we are removing the symbol which is also the benchmark, add it back as internal feed
if (symbol == _benchmarkSymbol)
{
Securities.Remove(symbol);
security = CreateBenchmarkSecurity();
AddToUserDefinedUniverse(security);
}
SubscriptionManager.HasCustomData = universe.Members.Any(x => x.Value.Subscriptions.Any(y => y.IsCustomData));
}
}
return true;
}
///
/// AddData a new user defined data source, requiring only the minimum config options.
/// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
///
/// Key/Symbol for data
/// Resolution of the data
/// The new
/// Generic type T must implement base data
public Security AddData(string symbol, Resolution resolution = Resolution.Minute)
where T : IBaseData, new()
{
//Add this new generic data as a tradeable security:
// Defaults:extended market hours" = true because we want events 24 hours,
// fillforward = false because only want to trigger when there's new custom data.
// leverage = 1 because no leverage on nonmarket data?
return AddData(symbol, resolution, fillDataForward: false, leverage: 1m);
}
///
/// AddData a new user defined data source, requiring only the minimum config options.
/// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
///
/// Key/Symbol for data
/// Resolution of the Data Required
/// When no data available on a tradebar, return the last data that was generated
/// Custom leverage per security
/// The new
/// Generic type T must implement base data
public Security AddData(string symbol, Resolution resolution, bool fillDataForward, decimal leverage = 1.0m)
where T : IBaseData, new()
{
return AddData(symbol, resolution, TimeZones.NewYork, fillDataForward, leverage);
}
///
/// AddData a new user defined data source, requiring only the minimum config options.
///
/// Key/Symbol for data
/// Resolution of the Data Required
/// Specifies the time zone of the raw data
/// When no data available on a tradebar, return the last data that was generated
/// Custom leverage per security
/// The new
/// Generic type T must implement base data
public Security AddData(string symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
where T : IBaseData, new()
{
//Add this custom symbol to our market hours database
var marketHoursDbEntry = MarketHoursDatabase.SetEntryAlwaysOpen(Market.USA, symbol, SecurityType.Base, timeZone);
//Add this to the data-feed subscriptions
var symbolObject = new Symbol(SecurityIdentifier.GenerateBase(symbol, Market.USA), symbol);
var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(Market.USA, symbol, SecurityType.Base, CashBook.AccountCurrency);
//Add this new generic data as a tradeable security:
var security = SecurityManager.CreateSecurity(typeof(T), Portfolio, SubscriptionManager, marketHoursDbEntry.ExchangeHours, marketHoursDbEntry.DataTimeZone,
symbolProperties, SecurityInitializer, symbolObject, resolution, fillDataForward, leverage, true, false, true, LiveMode);
AddToUserDefinedUniverse(security);
return security;
}
///
/// Send a debug message to the web console:
///
/// Message to send to debug console
///
///
public void Debug(string message)
{
if (!_liveMode && (message == "" || _previousDebugMessage == message)) return;
_debugMessages.Enqueue(message);
_previousDebugMessage = message;
}
///
/// Send a debug message to the web console:
///
/// Message to send to debug console
///
///
public void Debug(int message)
{
Debug(message.ToString());
}
///
/// Send a debug message to the web console:
///
/// Message to send to debug console
///
///
public void Debug(double message)
{
Debug(message.ToString());
}
///
/// Send a debug message to the web console:
///
/// Message to send to debug console
///
///
public void Debug(decimal message)
{
Debug(message.ToString());
}
///
/// Added another method for logging if user guessed.
///
/// String message to log.
///
///
public void Log(string message)
{
if (!_liveMode && message == "") return;
_logMessages.Enqueue(message);
}
///
/// Added another method for logging if user guessed.
///
/// Int message to log.
///
///
public void Log(int message)
{
Log(message.ToString());
}
///
/// Added another method for logging if user guessed.
///
/// Double message to log.
///
///
public void Log(double message)
{
Log(message.ToString());
}
///
/// Added another method for logging if user guessed.
///
/// Decimal message to log.
///
///
public void Log(decimal message)
{
Log(message.ToString());
}
///
/// Send a string error message to the Console.
///
/// Message to display in errors grid
///
///
public void Error(string message)
{
if (!_liveMode && (message == "" || _previousErrorMessage == message)) return;
_errorMessages.Enqueue(message);
_previousErrorMessage = message;
}
///
/// Send a int error message to the Console.
///
/// Message to display in errors grid
///
///
public void Error(int message)
{
Error(message.ToString());
}
///
/// Send a double error message to the Console.
///
/// Message to display in errors grid
///
///
public void Error(double message)
{
Error(message.ToString());
}
///
/// Send a decimal error message to the Console.
///
/// Message to display in errors grid
///
///
public void Error(decimal message)
{
Error(message.ToString());
}
///
/// Send a string error message to the Console.
///
/// Exception object captured from a try catch loop
///
///
public void Error(Exception error)
{
var message = error.Message;
if (!_liveMode && (message == "" || _previousErrorMessage == message)) return;
_errorMessages.Enqueue(message);
_previousErrorMessage = message;
}
///
/// Terminate the algorithm after processing the current event handler.
///
/// Exit message to display on quitting
public void Quit(string message = "")
{
Debug("Quit(): " + message);
Status = AlgorithmStatus.Stopped;
}
///
/// Set the Quit flag property of the algorithm.
///
/// Intended for internal use by the QuantConnect Lean Engine only.
/// Boolean quit state
///
public void SetQuit(bool quit)
{
if (quit)
{
Status = AlgorithmStatus.Stopped;
}
}
///
/// Converts the string 'ticker' symbol into a full object
/// This requires that the string 'ticker' has been added to the algorithm
///
/// The ticker symbol. This should be the ticker symbol
/// as it was added to the algorithm
/// The symbol object mapped to the specified ticker
public Symbol Symbol(string ticker)
{
return SymbolCache.GetSymbol(ticker);
}
///
/// Creates and adds a new to the algorithm
///
private T AddSecurity(SecurityType securityType, string ticker, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours)
where T : Security
{
if (market == null)
{
if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market))
{
throw new Exception("No default market set for security type: " + securityType);
}
}
Symbol symbol;
if (!SymbolCache.TryGetSymbol(ticker, out symbol))
{
symbol = QuantConnect.Symbol.Create(ticker, securityType, market);
}
var security = SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, MarketHoursDatabase, _symbolPropertiesDatabase, SecurityInitializer,
symbol, resolution, fillDataForward, leverage, extendedMarketHours, false, false, LiveMode);
AddToUserDefinedUniverse(security);
return (T)security;
}
///
/// Creates and returns a object to be used as the benchmark
///
private Security CreateBenchmarkSecurity()
{
// add the security as an internal feed so the algorithm doesn't receive the data
Resolution resolution;
if (_liveMode)
{
resolution = Resolution.Second;
}
else
{
// check to see if any universes arn't the ones added via AddSecurity
var hasNonAddSecurityUniverses = (
from universe in UniverseManager.Select(kvp => kvp.Value).Union(_pendingUniverseAdditions)
let config = universe.Configuration
let symbol = UserDefinedUniverse.CreateSymbol(config.SecurityType, config.Market)
where config.Symbol != symbol
select universe).Any();
resolution = hasNonAddSecurityUniverses ? UniverseSettings.Resolution : Resolution.Daily;
}
return SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, MarketHoursDatabase, _symbolPropertiesDatabase, SecurityInitializer, _benchmarkSymbol, resolution, true, 1m, false, true, false, LiveMode);
}
///
/// Set the historical data provider
///
/// Historical data provider
public void SetHistoryProvider(IHistoryProvider historyProvider)
{
if (historyProvider == null)
{
throw new ArgumentNullException("Algorithm.SetHistoryProvider(): Historical data provider cannot be null.");
}
HistoryProvider = historyProvider;
}
///
/// Set the runtime error
///
/// Represents error that occur during execution
public void SetRunTimeError(Exception exception)
{
if (exception == null)
{
throw new ArgumentNullException("Algorithm.SetRunTimeError(): Algorithm.RunTimeError cannot be set to null.");
}
RunTimeError = exception;
}
///
/// Set the state of a live deployment
///
/// Live deployment status
public void SetStatus(AlgorithmStatus status)
{
Status = status;
}
///
/// Downloads the requested resource as a .
/// The resource to download is specified as a containing the URI.
///
/// A string containing the URI to download
/// Defines header values to add to the request
/// The user name associated with the credentials
/// The password for the user name associated with the credentials
/// The requested resource as a
public string Download(string address, IEnumerable> headers = null, string userName = null, string password = null)
{
using (var client = new WebClient { Credentials = new NetworkCredential(userName, password) })
{
client.Proxy = WebRequest.GetSystemWebProxy();
if (headers != null)
{
foreach (var header in headers)
{
client.Headers.Add(header.Key, header.Value);
}
}
// Add a user agent header in case the requested URI contains a query.
client.Headers.Add("user-agent", "QCAlgorithm.Download(): User Agent Header");
return client.DownloadString(address);
}
}
///
/// Event invocator for the event
///
/// The collection of insights generaed at the current time step
protected virtual void OnInsightsGenerated(IEnumerable insights)
{
InsightsGenerated?.Invoke(this, new GeneratedInsightsCollection(UtcTime, insights));
}
///
/// Sets the current slice
///
/// The Slice object
public void SetCurrentSlice(Slice slice)
{
CurrentSlice = slice;
}
}
}