/*
* 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.UniverseSelection;
using QuantConnect.Interfaces;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Statistics;
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 _quit;
private bool _liveMode;
private string _algorithmId = "";
private List _debugMessages = new List();
private List _logMessages = new List();
private List _errorMessages = new List();
//Error tracking to avoid message flooding:
private string _previousDebugMessage = "";
private string _previousErrorMessage = "";
private bool _sentNoDataError = false;
private readonly SecurityExchangeHoursProvider _exchangeHoursProvider;
// 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 = Symbol.Empty;
private SecurityType _benchmarkSecurityType;
// warmup resolution variables
private TimeSpan? _warmupTimeSpan;
private int? _warmupBarCount;
///
/// QCAlgorithm Base Class Constructor - Initialize the underlying QCAlgorithm components.
/// QCAlgorithm manages the transactions, portfolio, charting and security subscriptions for the users algorithms.
///
public QCAlgorithm()
{
// 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);
//Initialise Data Manager
SubscriptionManager = new SubscriptionManager(_timeKeeper);
Securities = new SecurityManager(_timeKeeper);
Transactions = new SecurityTransactionManager(Securities);
Portfolio = new SecurityPortfolioManager(Securities, Transactions);
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
_exchangeHoursProvider = SecurityExchangeHoursProvider.FromDataFolder();
// universe selection
Universes = new List();
UniverseSettings = new SubscriptionSettings(Resolution.Minute, 2m, true, false);
// 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);
}
///
/// 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;
}
///
/// 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;
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 the Trade Builder to generate trades from executions
///
public TradeBuilder TradeBuilder
{
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; }
}
///
/// 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;
}
}
///
/// Gets the current universe selector, or null if no selection is to be performed
///
public List Universes
{
get; private set;
}
///
/// Gets the subscription settings to be used when adding securities via universe selection
///
public SubscriptionSettings UniverseSettings
{
get; private set;
}
///
/// Storage for debugging messages before the event handler has passed control back to the Lean Engine.
///
///
public List DebugMessages
{
get
{
return _debugMessages;
}
set
{
_debugMessages = value;
}
}
///
/// Storage for log messages before the event handlers have passed control back to the Lean Engine.
///
///
public List 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 List ErrorMessages
{
get
{
return _errorMessages;
}
set
{
_errorMessages = value;
}
}
///
/// 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 Intitialize() method");
}
///
/// Called by setup handlers after Initialize and allows the algorithm a chance to organize
/// the data gather in the Initialize method
///
public void PostInitialize()
{
// if the benchmark hasn't been set yet, set it
if (Benchmark == null)
{
// apply the default benchmark if it hasn't been set
if (_benchmarkSymbol == Symbol.Empty)
{
_benchmarkSymbol = new Symbol("SPY");
_benchmarkSecurityType = SecurityType.Equity;
}
// if the requested benchmark system wasn't already added, then add it now
Security security;
if (!Securities.TryGetValue(_benchmarkSymbol, out security))
{
// add the security as an internal feed so the algorithm doesn't receive the data
var resolution = _liveMode ? Resolution.Second : Resolution.Daily;
var market = _benchmarkSecurityType == SecurityType.Forex ? "fxcm" : "usa";
security = SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, _exchangeHoursProvider, _benchmarkSecurityType, _benchmarkSymbol, resolution, market, true, 1m, false, true, false);
Securities.Add(_benchmarkSymbol, security);
}
// just return the current price
Benchmark = new SecurityBenchmark(security);
}
}
///
/// 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);
}
}
///
/// Event fired each time the we add/remove securities from the data feed
///
///
public virtual void OnSecuritiesChanged(SecurityChanges changes)
{
}
//
// 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 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 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 Portoflio.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).
///
/// 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.Permtick);
}
///
/// 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)
{
}
///
/// 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);
}
///
/// 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
public void SetBrokerageModel(BrokerageName brokerage)
{
switch (brokerage)
{
case BrokerageName.Default:
BrokerageModel = new DefaultBrokerageModel();
break;
case BrokerageName.InteractiveBrokersBrokerage:
BrokerageModel = new InteractiveBrokersBrokerageModel();
break;
case BrokerageName.TradierBrokerage:
BrokerageModel = new TradierBrokerageModel();
break;
default:
throw new ArgumentOutOfRangeException("brokerage", brokerage, null);
}
}
///
/// 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, option, forex, etc. Default SecurityType.Equity
///
/// Must use symbol that is available to the trade engine in your data store(not strictly enforced)
///
public void SetBenchmark(SecurityType securityType, Symbol symbol)
{
_benchmarkSymbol = symbol;
_benchmarkSecurityType = securityType;
}
///
/// 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(Symbol symbol)
{
_benchmarkSymbol = symbol;
_benchmarkSecurityType = SecurityType.Equity;
}
///
/// 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;
//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 end date greater:
if (_endDate != new DateTime())
{
if (start > _endDate)
{
throw new Exception("Please select start date less than end date.");
}
}
//3. Round up and subtract one tick:
start = start.RoundDown(TimeSpan.FromDays(1));
//3. 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;
}
}
}
///
/// Sets the current universe selector for the algorithm. This will be executed on day changes
///
/// The universe selector
public void SetUniverse(Universe selector)
{
Universes.Clear();
Universes.Add(selector);
}
///
/// Sets the current universe selector for the algorithm. This will be executed on day changes
///
/// Defines an initial coarse selection
public void SetUniverse(Func, IEnumerable> coarse)
{
var symbol = CoarseFundamental.CreateUniverseSymbol("usa");
var config = new SubscriptionDataConfig(typeof(CoarseFundamental), SecurityType.Equity, symbol, Resolution.Daily, Market.USA, TimeZones.NewYork, false, false, true);
SetUniverse(new FuncUniverse(config, UniverseSettings, selectionData => coarse(selectionData.OfType())));
}
///
/// Set the maximum number of assets allowable to ensure good memory usage / avoid linux killing job.
///
/// Maximum number of minute level assets the live mode can support with selected server
/// Maximum number of second level assets the live mode can support with selected server
/// /// Maximum number of tick level assets the live mode can support with selected server
/// Sets the live behaviour of the algorithm including the selected server (ram) limits.
public void SetAssetLimits(int minuteLimit = 500, int secondLimit = 100, int tickLimit = 30)
{
if (!_locked)
{
Securities.SetLimits(minuteLimit, secondLimit, tickLimit);
}
}
///
/// Add specified data to our data subscriptions. QuantConnect will funnel this data to the handle data routine.
///
/// MarketType Type: Equity, Commodity, Future or FOREX
/// 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 void AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, bool extendedMarketHours = false)
{
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 or FOREX
/// 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 void AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution, bool fillDataForward, decimal leverage, bool extendedMarketHours)
{
AddSecurity(securityType, symbol, resolution, null, fillDataForward, leverage, extendedMarketHours);
}
///
/// Set a required SecurityType-symbol and resolution for algorithm
///
/// SecurityType Enum: Equity, Commodity, FOREX or Future
/// 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 void AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours)
{
if (_locked)
{
throw new Exception("Algorithm.AddSecurity(): Cannot add another security after algorithm running.");
}
try
{
var security = SecurityManager.CreateSecurity(Portfolio, SubscriptionManager, _exchangeHoursProvider,
securityType, symbol, resolution, market,
fillDataForward, leverage, extendedMarketHours, false, false);
//Add the symbol to Securities Manager -- manage collection of portfolio entities for easy access.
Securities.Add(security.Symbol, security);
}
catch (Exception err)
{
Error("Algorithm.AddSecurity(): " + err.Message);
}
}
///
/// 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
/// Generic type T must implement base data
public void AddData(Symbol symbol, Resolution resolution = Resolution.Minute)
where T : BaseData, new()
{
if (_locked) return;
//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?
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
/// Generic type T must implement base data
public void AddData(Symbol symbol, Resolution resolution, bool fillDataForward, decimal leverage = 1.0m)
where T : BaseData, new()
{
if (_locked) 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
/// Generic type T must implement base data
public void AddData(Symbol symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
where T : BaseData, new()
{
if (_locked) return;
//Add this to the data-feed subscriptions
var config = SubscriptionManager.Add(typeof(T), SecurityType.Base, symbol, resolution, "usa", timeZone, true, fillDataForward, true, false);
var exchangeHours = _exchangeHoursProvider.GetExchangeHours(config);
//Add this new generic data as a tradeable security:
var security = new Security(exchangeHours, config, leverage);
Securities.Add(symbol, 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.Add(message);
_previousDebugMessage = message;
}
///
/// Added another method for logging if user guessed.
///
/// String message to log.
///
///
public void Log(string message)
{
if (!_liveMode && message == "") return;
_logMessages.Add(message);
}
///
/// 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.Add(message);
_previousErrorMessage = message;
}
///
/// 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.Add(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);
_quit = true;
}
///
/// 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)
{
_quit = quit;
}
///
/// Get the quit state of the algorithm
///
/// Boolean true if set to quit event loop.
/// Intended for internal use by the QuantConnect Lean Engine only.
///
///
public bool GetQuit()
{
return _quit;
}
}
}