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
NaN
Beta
NaN
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
NaN
Tracking Error
NaN
Treynor Ratio
NaN
Total Fees
$0.00
namespace QuantConnect 
{   
	using System;
	using System.Linq;
	using QuantConnect.Data.Market;
	using QuantConnect.Indicators;
	using QuantConnect.Orders;
	using QuantConnect.Securities;
	using QuantConnect.Util;
    /*
    *   QuantConnect University: Full Basic Template:
    *
    *   The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
    *   We have explained some of these here, but the full algorithm can be found at:
    *   https://github.com/QuantConnect/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
    */
    public class InstantaneousTrendAlgorithm : QCAlgorithm
    {
    	private DateTime _startDate = new DateTime(2015, 8, 19);
        private DateTime _endDate = new DateTime(2015, 8, 25);
        private decimal _portfolioAmount = 22000;

        private string symbol = "AAPL";
        
        private int barcount = 0;

        private RollingWindow<IndicatorDataPoint> Price;
        private InstantaneousTrend trend;
        private RollingWindow<IndicatorDataPoint> trendHistory;
        private RollingWindow<IndicatorDataPoint> trendTrigger;

        // Strategy
        private InstantTrendStrategy iTrendStrategy;
        private bool shouldSellOutAtEod = true;
        private int orderId = 0;
        private int tradesize;

        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
			
            //Initialize dates
            SetStartDate(_startDate);
            SetEndDate(_endDate);
            SetCash(_portfolioAmount);

            //Add as many securities as you like. All the data will be passed into the event handler:
            AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);

            // Indicators
            Price = new RollingWindow<IndicatorDataPoint>(14);      // The price history

            // ITrend
            trend = new InstantaneousTrend(7);
            trendHistory = new RollingWindow<IndicatorDataPoint>(14);
            trendTrigger = new RollingWindow<IndicatorDataPoint>(14);

            // The ITrendStrategy
            iTrendStrategy = new InstantTrendStrategy(symbol, 14, this);
            iTrendStrategy.ShouldSellOutAtEod = shouldSellOutAtEod;
        }

        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {   
            barcount++;

            // Add the history for the bar
            var time = data.Time;
            Price.Add(idp(time, (data[symbol].Close + data[symbol].Open) / 2));

            // Update the indicators
            trend.Update(idp(time, Price[0].Value));
            trendHistory.Add(idp(time, trend.Current.Value)); //add last iteration value for the cycle
            trendTrigger.Add(idp(time, trend.Current.Value));
            if (barcount == 1)
            {
                tradesize = (int)(Portfolio.Cash / Convert.ToInt32(Price[0].Value + 1));
            }

            // iTrendStrategy starts on bar 3 because it uses trendHistory[0] - trendHistory[3]
            if (barcount < 7 && barcount > 2)
            {
                trendHistory[0].Value = (Price[0].Value + 2 * Price[1].Value + Price[2].Value) / 4;
            }

            if (barcount > 2)
            {
                trendTrigger[0].Value = 2 * trendHistory[0].Value - trendHistory[2].Value;
            }

            Strategy(data);
            
            if (data.Time.Hour == 16)
            {
                trend.Reset();
                trendHistory.Reset();
                trendTrigger.Reset();
                barcount = 0;
                Plot("Strategy Equity", "Portfolio", Portfolio.TotalPortfolioValue);
            }
        }
                /// <summary>
        /// Run the strategy associated with this algorithm
        /// </summary>
        /// <param name="data">TradeBars - the data received by the OnData event</param>
        private void Strategy(TradeBars data)
        {
            string comment = string.Empty;
            #region "Strategy Execution"

            if (SellOutEndOfDay(data))
            {
                iTrendStrategy.Barcount = barcount;  // for debugging

                // if there were limit order tickets to cancel, wait a bar to execute the strategy
                if (!CanceledUnfilledLimitOrder())
                    comment = iTrendStrategy.ExecuteStrategy(data, tradesize, trend.Current, trendTrigger[0]);
            }

            #endregion

        }
        /// <summary>
        /// If the order did not fill within one bar, cancel it and assume the market moved away from the limit order
        /// </summary>
        private bool CanceledUnfilledLimitOrder()
        {
            #region "Unfilled Limit Orders"

            bool retval = false;
            var tickets = Transactions.GetOrderTickets(t => !t.Status.IsClosed());
            if (tickets != null && tickets.Any())
            {
                foreach (var ticket in tickets)
                {
                    ticket.Cancel();
                    retval = true;
                }
            }
            #endregion

            return retval;
        }

        /// <summary>
        /// Handle order events
        /// </summary>
        /// <param name="orderEvent">the order event</param>
        public override void OnOrderEvent(OrderEvent orderEvent)
        {
            base.OnOrderEvent(orderEvent);
            ProcessOrderEvent(orderEvent);
        }
        /// <summary>
        /// Local processing of the order event
        /// </summary>
        /// <param name="orderEvent">OrderEvent - the order event</param>
        private void ProcessOrderEvent(OrderEvent orderEvent)
        {
            orderId = orderEvent.OrderId;
            var tickets = Transactions.GetOrderTickets(t => t.OrderId == orderId);
            if (tickets.Any())
            {
                foreach (OrderTicket ticket in tickets)
                {
                    var status = ticket.Status;
                    if (ticket.Status == OrderStatus.Canceled)
                    {
                        iTrendStrategy.orderFilled = false;
                    }
                    if (ticket.Status == OrderStatus.Filled)
                    {
                        iTrendStrategy.orderFilled = true;

                        if (Portfolio[orderEvent.Symbol].Invested)
                        {
                            iTrendStrategy.nEntryPrice = orderEvent.FillPrice;
                        }
                    }
                }
            }
        }        
		public bool SellOutEndOfDay(TradeBars data)
        {
            if (shouldSellOutAtEod)
            {
                if (data.Time.Hour == 15 && data.Time.Minute > 49 || data.Time.Hour == 16)
                {
                    if (Portfolio[symbol].IsLong)
                    {
                        Sell(symbol, Portfolio[symbol].AbsoluteQuantity);
                    }
                    if (Portfolio[symbol].IsShort)
                    {
                        Buy(symbol, Portfolio[symbol].AbsoluteQuantity);
                    }
                    return false;
                }
            }
            return true;
        }


        /// <summary>
        /// Convenience function which creates an IndicatorDataPoint
        /// </summary>
        /// <param name="time">DateTime - the bar time for the IndicatorDataPoint</param>
        /// <param name="value">decimal - the value for the IndicatorDataPoint</param>
        /// <returns>a new IndicatorDataPoint</returns>
        /// <remarks>I use this function to shorten the a Add call from 
        /// new IndicatorDataPoint(data.Time, value)
        /// Less typing.</remarks>
        private IndicatorDataPoint idp(DateTime time, decimal value)
        {
            return new IndicatorDataPoint(time, value);
        }

    
    }
}
namespace QuantConnect {

	using System;
    /// <summary>
    /// InstanteaousTrend Indicator
    /// </summary>
    public class InstantaneousTrend : WindowIndicator<IndicatorDataPoint>
    {
        // the alpha for the formula
        private readonly decimal a = 0.5m;
        private readonly int _period;
        private readonly RollingWindow<IndicatorDataPoint> _trend;
        private readonly RollingWindow<IndicatorDataPoint> _price;
        private int barcount;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="period"></param>
        public InstantaneousTrend(string name, int period)
            : base(name, period)
        {

            // InstantaneousTrend history
            _trend = new RollingWindow<IndicatorDataPoint>(period);
            _price = new RollingWindow<IndicatorDataPoint>(period);
            _period = period;
            barcount = 0;
        }
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="period">int - the number of periods in the indicator warmup</param>
        public InstantaneousTrend(int period)
            : this("CCy" + period, period)
        {
        }

        /// <summary>
        ///     Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady
        {
            get { return _trend.IsReady; }
        }

        /// <summary>
        /// Calculates the next value for the ITrend
        /// </summary>
        /// <param name="window">the window for this indicator</param>
        /// <param name="input">the latest price to input into the trend</param>
        /// <returns>the computed value</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
        {
            // for convenience
            var time = input.Time;
            _price.Add(input);

            if (barcount < _period)
            {
                _trend.Add(input);
            }
            else
            {
                // Calc the low pass filter _trend value and add it to the _trend
                var lfp = (a - ((a / 2) * (a / 2))) * input.Value + ((a * a) / 2) * _price[1].Value
                     - (a - (3 * (a * a) / 4)) * _price[2].Value + 2 * (1 - a) * _trend[0].Value
                     - ((1 - a) * (1 - a)) * _trend[1].Value;
                _trend.Add(idp(time, lfp));
            }

            barcount++;
            return _trend[0].Value;
        }
        /// <summary>
        /// Factory function which creates an IndicatorDataPoint
        /// </summary>
        /// <param name="time">DateTime - the bar time for the IndicatorDataPoint</param>
        /// <param name="value">decimal - the value for the IndicatorDataPoint</param>
        /// <returns>a new IndicatorDataPoint</returns>
        /// <remarks>I use this function to shorten the a Add call from 
        /// new IndicatorDataPoint(data.Time, value)
        /// Less typing.</remarks>
        private IndicatorDataPoint idp(DateTime time, decimal value)
        {
            return new IndicatorDataPoint(time, value);
        }

    }

}
namespace QuantConnect {
	using System;
	using QuantConnect.Data.Market;
	using QuantConnect.Indicators;
	using QuantConnect.Orders;
	/// <summary>
    /// From Ehlers Cybernetics page 27 on Trading the trend
    /// </summary>
    public class InstantTrendStrategy
    {
        /// <summary>
        /// The entry price for the latest trade
        /// </summary>
        public decimal nEntryPrice { get; set; }
        public int Barcount { get; set; }

        private bool bReverseTrade = false;
        private string _symbol { get; set; }
        private decimal RevPct = 1.0025m;
        private decimal RngFac = .35m;
        private decimal nLimitPrice = 0;
        private int nStatus = 0;
        private int xOver = 0;
        private RollingWindow<IndicatorDataPoint> trendHistory;

        /// <summary>
        /// Flag to determine if the algo should go flat overnight.
        /// </summary>
        public bool ShouldSellOutAtEod;

        /// <summary>
        /// the Algorithm being run.
        /// </summary>
        public QCAlgorithm _algorithm;

        /// <summary>
        /// The flag as to whether the order has been filled.
        /// </summary>
        public Boolean orderFilled { get; set; }


        /// <summary>
        /// Constructor initializes the symbol and period of the RollingWindow
        /// </summary>
        /// <param name="symbol">string - ticker symbol</param>
        /// <param name="period">int - the period of the Trend History Rolling Window</param>
        /// <param name="algorithm"></param>
        public InstantTrendStrategy(string symbol, int period, QCAlgorithm algorithm)
        {
            _symbol = symbol;
            trendHistory = new RollingWindow<IndicatorDataPoint>(period);
            _algorithm = algorithm;
            orderFilled = true;
        }


        /// <summary>
        /// Executes the Instant Trend strategy
        /// </summary>
        /// <param name="data">TradeBars - the current OnData</param>
        /// <param name="tradesize"></param>
        /// <param name="trendCurrent">IndicatorDataPoint - the current trend value trend</param>
        /// <param name="triggerCurrent">IndicatorDataPoint - the current trigger</param>
        public string ExecuteStrategy(TradeBars data, int tradesize, IndicatorDataPoint trendCurrent, IndicatorDataPoint triggerCurrent)
        {
            OrderTicket ticket;
            string comment = string.Empty;

            trendHistory.Add(trendCurrent);
            nStatus = 0;

            if (_algorithm.Portfolio[_symbol].IsLong) nStatus = 1;
            if (_algorithm.Portfolio[_symbol].IsShort) nStatus = -1;
            if (!trendHistory.IsReady)
            {
                return "Trend Not Ready";
            }

            if (!SellOutEndOfDay(data))
            {
                #region "Strategy Execution"

                bReverseTrade = false;
                try
                {
                    var nTrig = 2 * trendHistory[0].Value - trendHistory[2].Value;
                    if (nStatus == 1 && nTrig < (nEntryPrice / RevPct)){
                        comment = string.Format("Long Reverse to short. Close < {0} / {1}", nEntryPrice, RevPct);
                        ticket = ReverseToShort();
                        orderFilled = ticket.OrderId > 0;
                        bReverseTrade = true;
                    }
                    else
                    {
                        if (nStatus == -1 && nTrig > (nEntryPrice * RevPct))
                        {
                            comment = string.Format("Short Reverse to Long. Close > {0} * {1}", nEntryPrice, RevPct);
                            ticket = ReverseToLong();
                            orderFilled = ticket.OrderId > 0;
                            bReverseTrade = true;
                        }
                    }
                    if (!bReverseTrade)
                    {
                        if (nTrig > trendHistory[0].Value)
                        {
                            if (xOver == -1 && nStatus != 1)
                            {
                                if (!orderFilled)
                                {
                                    ticket = _algorithm.Buy(_symbol, tradesize);
                                    comment = string.Format("Enter Long after cancel trig xover price up");
                                }
                                else
                                {
                                    nLimitPrice = Math.Max(data[_symbol].Low, (data[_symbol].Close - (data[_symbol].High - data[_symbol].Low) * RngFac));
                                    ticket = _algorithm.LimitOrder(_symbol, tradesize, nLimitPrice, "Long Limit");
                                    comment = string.Format("Enter Long Limit trig xover price up", nLimitPrice);
                                }
                            }
                            if (comment.Length == 0)
                                comment = "Trigger over Trend";
                            xOver = 1;
                        }
                        else
                        {
                            if (nTrig < trendHistory[0].Value)
                            {
                                if (xOver == 1 && nStatus != -1)
                                {
                                    if (!orderFilled)
                                    {
                                        ticket = _algorithm.Sell(_symbol, tradesize);
                                        comment = string.Format("Enter Short after cancel trig xunder price down");
                                    }
                                    else
                                    {
                                        nLimitPrice = Math.Min(data[_symbol].High, (data[_symbol].Close + (data[_symbol].High - data[_symbol].Low) * RngFac));
                                        ticket = _algorithm.LimitOrder(_symbol, -tradesize, nLimitPrice, "Short Limit");
                                        comment = string.Format("Enter Short Limit at {0} trig xover price down", nLimitPrice);
                                    }
                                }
                                if (comment.Length == 0)
                                    comment = "Trigger under trend";
                                xOver = -1;
                            }
                        }
                    }

                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                }
                #endregion
            }
            return comment;
        }
        private OrderTicket ReverseToLong()
        {
            nLimitPrice = 0;
            nStatus = 1;
            return _algorithm.Buy(_symbol, _algorithm.Portfolio[_symbol].Quantity * 2);
        }

        private OrderTicket ReverseToShort()
        {
            nLimitPrice = 0;
            nStatus = -1;
            return _algorithm.Sell(_symbol, _algorithm.Portfolio[_symbol].Quantity * 2);
        }
        private bool SellOutEndOfDay(TradeBars data)
        {
            if (ShouldSellOutAtEod)
            {
                if (data.Time.Hour == 15 && data.Time.Minute > 55 || data.Time.Hour == 16)
                {
                    if (_algorithm.Portfolio[_symbol].IsLong)
                    {
                        _algorithm.Sell(_symbol, _algorithm.Portfolio[_symbol].AbsoluteQuantity);
                    }
                    if (_algorithm.Portfolio[_symbol].IsShort)
                    {
                        _algorithm.Buy(_symbol, _algorithm.Portfolio[_symbol].AbsoluteQuantity);
                    }

                    return true;
                }
            }
            return false;
        }
    }

}