Overall Statistics
Total Trades
1
Average Win
115.06%
Average Loss
0%
Compounding Annual Return
13.612%
Drawdown
18.800%
Expectancy
0
Net Profit
115.057%
Sharpe Ratio
0.824
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
-0.025
Beta
0.953
Annual Standard Deviation
0.173
Annual Variance
0.03
Information Ratio
-1.844
Tracking Error
0.018
Treynor Ratio
0.15
using System;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;

namespace QuantConnect.Algorithm.Examples
{
    public class CustomDataIndicators : QCAlgorithm
    {
        private string SPY_QuandlCode = "YAHOO/INDEX_SPY";

        ExponentialMovingAverage emaClose;
        ExponentialMovingAverage emaLow;
        ExponentialMovingAverage emaHigh;

        public override void Initialize()
        {
            // set up our analysis span
            SetStartDate(2009, 01, 01);
            SetEndDate(2015, 01, 01);

            // request SPY data - the data feed does daily, so pick that too
            AddData<Quandl>(SPY_QuandlCode, Resolution.Daily);

            // create our consolidator, this will produce a 10 day bar.
            var quandlConsolidator = new DynamicTradeBarConsolidator<Quandl>(10, TimeSpan.FromDays(1));

            // this indicator is going to be a 5 period EMA, where the period is 10 days
            emaClose = new ExponentialMovingAverage("EMA5_Close", 5);

            // register our indicator with our custom consolidator, this allows it to receive automatic updates
            // the x => x.Value is a selector that picks which data goes into our emaClose,
            // in this case, Value is an alias for Close, so we're sending Closing data
            // into our consolidator
            RegisterIndicator(SPY_QuandlCode, emaClose, quandlConsolidator, x => x.Value);

            // we could just as easily register to one of the dynamic properties with a caste
            emaLow = new ExponentialMovingAverage("EMA5_Low", 5);
            RegisterIndicator(SPY_QuandlCode, emaLow, quandlConsolidator, x => ((TradeBar)x).Low);

            // we can do the same for High
            emaHigh = new ExponentialMovingAverage("EMA5_High", 5);
            RegisterIndicator(SPY_QuandlCode, emaHigh, quandlConsolidator, x => ((TradeBar)x).High);
        }

        public void OnData(Quandl data)
        {
            if (!Portfolio.HoldStock)
            {
                // without this line the plot doesn't show up in the ui
                Plot(SPY_QuandlCode, emaClose.Name, data.Value);
                SetHoldings(SPY_QuandlCode, 0.95);
                return;
            }

            // don't start plotting until we've received at least one data point in the indicator
            if (emaClose == 0m) return;

            // plot our results
            Plot(SPY_QuandlCode, emaClose, emaLow, emaHigh);
        }
    }

    /// <summary>
    /// Define a wrapper around the basic trade bar consolidator to handle the mapping
    /// between dynamic OHLCV types and TradeBar
    /// </summary>
    public class DynamicTradeBarConsolidator<T> : DataConsolidator<T>
        where T : BaseData
    {
        private readonly SequentialConsolidator _consolidator;

        public DynamicTradeBarConsolidator(int numberOfPeriods, TimeSpan period)
        {
            // this is the consolidator we're wrapping, we're basically going to make him do all the work.
            // the first parameter will produce bars at a given time resolution
            // the second parameter will produce bars at a given number of bars passed
            // this allows us to create a 5-day bar correctly, since really we want 10 trading
            // days to pass, not just 10 calendar days.
            var first = new TradeBarConsolidator(period);
            var second = new TradeBarConsolidator(numberOfPeriods);
            _consolidator = new SequentialConsolidator(first, second);

            // due to a bugg in SequentialConsolidator we need to attach to the second (see commit cff6d3b)
            //_consolidator.DataConsolidated += (sender, consolidated) =>

            // when our internal consolidator fires we want to call this consolidator's event as well,
            // since users are going to subscribe to those (DynamicTradeBarConsolidator.DataConsolidated)
            second.DataConsolidated += (sender, consolidated) =>
            {
                OnDataConsolidated(consolidated);
            };
        }

        public override Type OutputType
        {
            get { return typeof(TradeBar); }
        }

        public override void Update(T data)
        {
            // we're going to take out unknown, dynamic data and assume it has
            // OHLCV defined on it. If not, this will throw exceptions.

            var dynamicData = data as dynamic;
            var dataAsTradeBar = new TradeBar
            {
                Time = data.Time,
                Open = dynamicData.Open,
                High = dynamicData.High,
                Low = dynamicData.Low,
                Close = dynamicData.Close,
                Volume = (long)dynamicData.Volume // we parse everything as decimal, so convert to long here
                // "Adjusted Close" is also a property
            };

            // pass our trade bar data through to the underlying trade bar consolidator
            _consolidator.Update(dataAsTradeBar);
        }
    }
}