Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio NaN Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio NaN Tracking Error NaN Treynor Ratio NaN |
namespace QuantConnect.Indicators { /// <summary> /// Represents a forward-only in time time series filter /// </summary> public interface IIndicator { /// <summary> /// Gets a name for this indicator /// </summary> string Name { get; } /// <summary> /// Gets a flag indicating when this indicator is ready and fully initialized /// </summary> bool IsReady { get; } /// <summary> /// Gets the current state of this indicator. If the state has not been updated /// then the time on the value will equal DateTime.MinValue. /// </summary> DataPoint<decimal> Value { get; } /// <summary> /// Gets the number of samples processed by this indicator /// </summary> int Samples { get; } /// <summary> /// Updates the state of this indicator with the given value and returns true /// if this indicator is ready, false otherwise /// </summary> /// <param name="input">The value to use to update this indicator</param> /// <returns>True if this indicator is ready, false otherwise</returns> bool Update(DataPoint<decimal> input); /// <summary> /// Resets this indicator to its initial state /// </summary> void Reset(); } }
using System; using System.Collections.Generic; namespace QuantConnect.Indicators { /// <summary> /// Provides static methods for creating DataPoint instances. These are purely /// for convenience of the call site /// </summary> public static class DataPoint { /// <summary> /// Creates a new instance of a DataPoint with the specified data /// </summary> /// <typeparam name="T">The type of data</typeparam> /// <param name="time"></param> /// <param name="value"></param> /// <returns></returns> public static DataPoint<T> Create<T>(DateTime time, T value) { // this method provides some type inference convience so we need not specify the type parameter return new DataPoint<T>(time, value); } /// <summary> /// Provides a default value for a DataPoint /// </summary> /// <typeparam name="T">The type of data</typeparam> /// <returns>The default DataPoint</returns> public static DataPoint<T> Default<T>() { return new DataPoint<T>(DateTime.MinValue, default(T)); } } /// <summary> /// Represents a piece of data at a specific time /// </summary> /// <typeparam name="T">The type of data</typeparam> public struct DataPoint<T> : IEquatable<DataPoint<T>> { /// <summary> /// Gets the data /// </summary> public T Data { get; private set; } /// <summary> /// Gets the time associated wth this data /// </summary> public DateTime Time { get; private set; } /// <summary> /// Initializes a new instance of the DataPoint type using the specified time/data /// </summary> /// <param name="time">The time this data was produced</param> /// <param name="data">The data</param> public DataPoint(DateTime time, T data) : this() { Time = time; Data = data; } /// <summary> /// Indicates whether the current object is equal to another object of the same type. /// </summary> /// <returns> /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false. /// </returns> /// <param name="other">An object to compare with this object.</param> public bool Equals(DataPoint<T> other) { return EqualityComparer<T>.Default.Equals(Data, other.Data) && Time.Equals(other.Time); } /// <summary> /// Returns a string representation of this DataPoint instance using ISO8601 formatting for the date /// </summary> /// <returns> /// A <see cref="T:System.String" /> containing a fully qualified type name. /// </returns> /// <filterpriority>2</filterpriority> public override string ToString() { return string.Format("{0} - {1}", Time.ToString("s"), Data); } /// <summary> /// Indicates whether this instance and a specified object are equal. /// </summary> /// <returns> /// true if <paramref name="obj" /> and this instance are the same type and represent the same value; otherwise, false. /// </returns> /// <param name="obj">Another object to compare to. </param> /// <filterpriority>2</filterpriority> public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; return obj is DataPoint<T> && Equals((DataPoint<T>) obj); } /// <summary> /// Returns the hash code for this instance. /// </summary> /// <returns> /// A 32-bit signed integer that is the hash code for this instance. /// </returns> /// <filterpriority>2</filterpriority> public override int GetHashCode() { unchecked { return (EqualityComparer<T>.Default.GetHashCode(Data)*397) ^ Time.GetHashCode(); } } /// <summary> /// Compares the two specified data points for equality, returning true /// if the times and data both compare equal /// </summary> /// <returns> /// True if the two instances' time and data compare equal /// </returns> /// <param name="left">The DataPoint instance on the left of the operator</param> /// <param name="right">The DataPoint instance on the right of the operator</param> public static bool operator ==(DataPoint<T> left, DataPoint<T> right) { return left.Equals(right); } /// <summary> /// Compares the two specified data points for equality, returning true /// if the times and data both compare differently /// </summary> /// <returns> /// True if the two instances' time and data compare differently /// </returns> /// <param name="left">The DataPoint instance on the left of the operator</param> /// <param name="right">The DataPoint instance on the right of the operator</param> public static bool operator !=(DataPoint<T> left, DataPoint<T> right) { return !(left == right); } } }
using QuantConnect.Models; namespace QuantConnect.Indicators { /// <summary> /// Represents a type capable of pulling data out of more complex data types for input /// into the IIndicator infrastructure /// </summary> public interface IIndicatorDataSource { /// <summary> /// Gets whether or not this IndicatorDataSource can process the specified object /// </summary> bool CanProcess(BaseData data); /// <summary> /// Gets the value to be piped to an indicator from the source object. This source object type must /// match the DataSourceType /// </summary> /// <param name="data">The source instance to pull data from (Tick, TradeBar, custom data)</param> /// <returns>The value to be piped to an indicator</returns> decimal GetValue(BaseData data); } }
using System; using QuantConnect.Models; namespace QuantConnect.Indicators { /// <summary> /// Provides a means of defining what type and how to select data for an indicator /// </summary> public class IndicatorDataSource<T> : IIndicatorDataSource where T : BaseData { /// <summary> /// Defines how to pull data from instances of T /// </summary> private readonly Func<T, decimal> _selector; /// <summary> /// Defines how often we'll update an indicator /// </summary> private readonly TimeSpan _span; /// <summary> /// Specifies the last time we selected data /// </summary> private DateTime _lastProcessedDataTime; /// <summary> /// Initializes a new instance of the IndicatorDataSource class that uses the /// specified selector to pull data from instances of T /// </summary> /// <param name="selector">Func used to select data from instances of T</param> /// <param name="span">Defines how often we 'CanProcess' data</param> public IndicatorDataSource(Func<T, decimal> selector, TimeSpan span) { _span = span; _selector = selector; } /// <summary> /// Gets whether or not this IndicatorDataSource can process the specified object /// </summary> public bool CanProcess(BaseData data) { return data is T && (data.Time - _lastProcessedDataTime) >= _span; } /// <summary> /// Gets the value to be piped to an indicator from the source object. This source object type must /// match the DataSourceType /// </summary> /// <param name="data">The source instance to pull data from (Tick, TradeBar, custom data)</param> /// <returns>The value to be piped to an indicator</returns> public decimal GetValue(BaseData data) { if (!(data is T)) { string message = string.Format("CustomIndicatorDataSource received incorrect type. Expected {0} but received {1}", typeof (T).FullName, data.GetType().FullName ); throw new ArgumentException(message); } _lastProcessedDataTime = data.Time; return _selector((T) data); } } }
using System.Collections.Generic; using System.Linq; using QuantConnect.Models; namespace QuantConnect.Indicators { /// <summary> /// Provides methods for maintaining a collection of indicators defined /// against a single symbol /// </summary> public class IndicatorCollection { private readonly Dictionary<string, IndicatorWithSource> _indicators; /// <summary> /// Gets the symbol these indicators are defined against /// </summary> public string Symbol { get; private set; } /// <summary> /// Initializes a new instance of the IndicatorCollection for the specified symbol /// </summary> /// <param name="symbol"></param> public IndicatorCollection(string symbol) { Symbol = symbol; _indicators = new Dictionary<string, IndicatorWithSource>(); } /// <summary> /// Gets the indicator with the specified name /// </summary> /// <param name="name">The name of the indicator to get</param> /// <returns>The indicator with the specified name, or throws if none exists</returns> public IIndicator this[string name] { get { return _indicators[name].Indicator; } } /// <summary> /// Adds the specified indicator to this collection and will use /// </summary> /// <param name="indicator">The indicator to add to this collection</param> /// <param name="indicatorDataSource">Defines how this indicator will be auto-updated, if at all</param> public void Add(IIndicator indicator, IIndicatorDataSource indicatorDataSource) { var indicatorWithSource = new IndicatorWithSource(indicator, indicatorDataSource); _indicators.Add(indicator.Name, indicatorWithSource); } /// <summary> /// Updates indicators in this collection with the specified data. Only indicators whose IndicatorDataSource /// returns true from the CanProcess call will be updated. /// </summary> /// <param name="data">The data used to update the indicators</param> public void Update(BaseData data) { // loop through all of our indicators and update the ones who can process this data foreach (IndicatorWithSource item in _indicators.Values.Where(x => x.DataSource.CanProcess(data))) { decimal value = item.DataSource.GetValue(data); item.Indicator.Update(DataPoint.Create(data.Time, value)); } } /// <summary> /// Small structure to join an IIndicator and an IndicatorDataSource /// </summary> private class IndicatorWithSource { /// <summary> /// Gets the data source for the indicator /// </summary> public readonly IIndicatorDataSource DataSource; /// <summary> /// Gets the indicator /// </summary> public readonly IIndicator Indicator; public IndicatorWithSource(IIndicator indicator, IIndicatorDataSource dataSource) { Indicator = indicator; DataSource = dataSource; } } } }
using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Models; namespace QuantConnect.Indicators { /// <summary> /// Provides methods for managing an algorithm's auto-update indicators /// </summary> public class IndicatorManager { // provides a map from symbol -> indicator collection private readonly Dictionary<string, IndicatorCollection> _indicators; /// <summary> /// Gets the IndicatorCollection instance used to manage the indicators for the specified symbol. /// This is a get or create operation /// </summary> /// <param name="symbol">The symbol</param> /// <returns>The IndicatorCollection associated with the specified symbol</returns> public IndicatorCollection this[string symbol] { get { IndicatorCollection collection; if (!_indicators.TryGetValue(symbol, out collection)) { collection = new IndicatorCollection(symbol); _indicators[symbol] = collection; } return collection; } } /// <summary> /// Initializes a new empty IndicatorManager /// </summary> public IndicatorManager() { _indicators = new Dictionary<string, IndicatorCollection>(); } /// <summary> /// Adds a new indicator for the specified symbol using the selector to pull data from a TradeBar instance /// </summary> /// <param name="symbol">The symbol to attach this indicator to</param> /// <param name="indicator">The indicator</param> /// <param name="selector">Func used to select data from the TradeBar and pipe into the indicator</param> /// <param name="timeSpan">Defines how often to update this indicator</param> public void AddTradeBarIndicator(string symbol, IIndicator indicator, Func<TradeBar, decimal> selector, TimeSpan timeSpan) { IndicatorCollection collection = this[symbol]; var dataSource = new IndicatorDataSource<TradeBar>(selector, timeSpan); collection.Add(indicator, dataSource); } // define the warning so we remember to do this #warning AddTickIndicator and AddCustomDataIndicator functions need to be implemented /// <summary> /// Updates indicators who should be updated from this data basic on their registered IIndicatorDataSource /// </summary> /// <param name="data">TradeBar data</param> public void UpdateTradeBarIndicators(IDictionary<string, TradeBar> data) { // loop through all our IndicatorCollection instances foreach (var item in _indicators) { TradeBar bar; string symbol = item.Key; if (data.TryGetValue(symbol, out bar)) { // if we have data, let the collection update on it // it will only update indicators whose CanProcess function returns true item.Value.Update(bar); } } } /// <summary> /// Updates indicators who should be updated from this data basic on their registered IIndicatorDataSource /// </summary> /// <param name="data">Tick data</param> public void UpdateTickIndicators(IDictionary<string, Tick> data) { // loop through all our IndicatorCollection instances foreach (var item in _indicators) { Tick tick; string symbol = item.Key; if (data.TryGetValue(symbol, out tick)) { // if we have data, let the collection update on it // it will only update indicators whose CanProcess function returns true item.Value.Update(tick); } } } /// <summary> /// Updates indicators who should be updated from this data basic on their registered IIndicatorDataSource /// </summary> /// <param name="data">Custom data type</param> public void UpdateCustomIndicators(BaseData data) { // loop through all our IndicatorCollection instances matching the symbol foreach (var item in _indicators.Where(x => x.Key == data.Symbol)) { // if we have data, let the collection update on it // it will only update indicators whose CanProcess function returns true item.Value.Update(data); } } } }
using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; using QuantConnect.Indicators; namespace QuantConnect { // this class contains edits that can be made to the QCAlgorithm type // to enable auto updating indicators, the only thing we're missing here // is intercepting the calls to OnData( ... ) which may need to be done // somewhere else depending on who is pumping the data to the IAlgorithm // instances public partial class AutoUpdatingIndicators { public override void Initialize() { SetStartDate(2014, 08, 01); SetEndDate(2014, 12, 05); // this creates an EMA and adds it to the IndicatorManager // using defaults of 1 day update interval and using closing prices EMA("SPY", 3); // this creates an EMA and adds it to the IndicatorManager // using a 2 day update interval and the low price, we also override the name // of the indicator to deconflict with the other SPY EMA3 // an important note realized during testing, we may want a way to say '2 bars' // since a 2 day ema as defined like this ends up with double points over weekends, // imagine one sample is on a friday, well the next will be monday, but typically // a 2 day span we would expect it more as '2 bars' or '2 trading days' not '2 calendar days' EMA("SPY", 3, TimeSpan.FromDays(2), x => x.Low, "2day EMA3"); // we can even define indicators on computed values! Here we define an indicator on // the average of OHLC data EMA("SPY", 9, TimeSpan.FromDays(1), x => (x.Open + x.High + x.Low + x.Close)/4); AddSecurity(SecurityType.Equity, "SPY"); } private DateTime last = DateTime.MinValue; public void OnData(TradeBars data) { // whomever calls OnData( ... ) could make this function call to IndicatorManager // note that we update this on every bar, but the IndicatorCollection // has data that tells it when it should actually call update on each // indicator IndicatorManager.UpdateTradeBarIndicators(data); TradeBar bar; if (data.TryGetValue("SPY", out bar) && bar.Time.Date != last.Date) { last = bar.Time; Plot("SPY", "Price", bar.Close); Plot("SPY", "EMA3", IndicatorManager["SPY"]["EMA3"].Value.Data); Plot("SPY", "EMA9 Avg OHLC", IndicatorManager["SPY"]["EMA9"].Value.Data); Plot("SPY", "2day EMA3", IndicatorManager["SPY"]["2day EMA3"].Value.Data); } } } }
using System; namespace QuantConnect.Indicators { /// <summary> /// Represents the basic functionality of conforming to the IIndicator interface invariants /// </summary> public abstract class IndicatorBase : IIndicator { /// <summary> /// the most recent time data was given to this indicator /// </summary> private DateTime _previous; /// <summary> /// Initializes a new instance of the IndicatorBase class using the specified name. /// </summary> /// <param name="name">The name of this indicator</param> protected IndicatorBase(string name) { Name = name; } /// <summary> /// Gets a name for this indicator /// </summary> public string Name { get; private set; } /// <summary> /// Gets a flag indicating when this indicator is ready and fully initialized /// </summary> public abstract bool IsReady { get; } /// <summary> /// Gets the current state of this indicator. If the state has not been updated /// then the time on the value will equal DateTime.MinValue. /// </summary> public DataPoint<decimal> Value { get; private set; } /// <summary> /// Gets the number of samples processed by this indicator /// </summary> public int Samples { get; private set; } /// <summary> /// Updates the state of this indicator with the given value and returns true /// if this indicator is ready, false otherwise /// </summary> /// <param name="input">The value to use to update this indicator</param> /// <returns>True if this indicator is ready, false otherwise</returns> public bool Update(DataPoint<decimal> input) { if (input.Time < _previous) { // if we receive a time in the past, throw throw new ArgumentException("This is a forward only indicator."); } if (input.Time != _previous) { // if the time isn't the current time, then it must be future, // compute a new value and update our previous time Samples++; _previous = input.Time; decimal nextValue = ComputeNextValue(Value, input); Value = DataPoint.Create(input.Time, nextValue); } // this is when _previous==time and we've already computed // so do nothing and return IsReady // else { } return IsReady; } /// <summary> /// Resets this indicator to its initial state /// </summary> public virtual void Reset() { Value = DataPoint.Create(DateTime.MinValue, default(decimal)); } /// <summary> /// Computes the next value of this indicator from the given state /// </summary> /// <param name="previousValue">The most recent value of this indicator</param> /// <param name="input">The input given to the indicator</param> /// <returns>A new value for this indicator</returns> protected abstract decimal ComputeNextValue(DataPoint<decimal> previousValue, DataPoint<decimal> input); } }
namespace QuantConnect.Indicators { /// <summary> /// Represents the traditional exponential moving average indicator (EMA) /// </summary> public class ExponentialMovingAverage : IndicatorBase { private readonly decimal _k; private readonly int _period; public ExponentialMovingAverage(string name, int period) : base(name) { _period = period; _k = 2 / ((decimal)period + 1); } public override bool IsReady { get { return Samples >= _period; } } protected override decimal ComputeNextValue(DataPoint<decimal> previousValue, DataPoint<decimal> input) { // our first data point just return identity if (Samples == 1) { return input.Data; } return input.Data * _k + previousValue.Data * (1 - _k); } } }
using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; using QuantConnect.Indicators; namespace QuantConnect { // this class contains edits that can be made to the QCAlgorithm type // to enable auto updating indicators, the only thing we're missing here // is intercepting the calls to OnData( ... ) which may need to be done // somewhere else depending on who is pumping the data to the IAlgorithm // instances public partial class AutoUpdatingIndicators : QuantConnect.QCAlgorithm { /// <summary> /// Gets the IndicatorManager /// </summary> public IndicatorManager IndicatorManager { get; set; } public AutoUpdatingIndicators() : base() { IndicatorManager = new IndicatorManager(); } /// <summary> /// Creates a new simple moving average indicator for the specified symbol /// and period. You can optionally specify the update period (defaults to 1 day), /// and can also specify the source data (defaults to Close) /// </summary> public ExponentialMovingAverage EMA(string symbol, int period, TimeSpan? span = null, Func<TradeBar, decimal> valueSelector = null, string name = null) { // resolve default values span = span ?? TimeSpan.FromDays(1); valueSelector = valueSelector ?? (x => x.Close); name = name ?? string.Format("EMA{0}", period); var ema = new ExponentialMovingAverage(name, period); IndicatorManager.AddTradeBarIndicator(symbol, ema, valueSelector, span.Value); return ema; } } }