| 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;
}
}
}