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