Overall Statistics
Total Trades
30
Average Win
0.61%
Average Loss
-0.23%
Compounding Annual Return
16.247%
Drawdown
1.200%
Expectancy
0.801
Net Profit
7.744%
Sharpe Ratio
3.122
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
2.60
Alpha
0.159
Beta
-0.049
Annual Standard Deviation
0.049
Annual Variance
0.002
Information Ratio
-0.078
Tracking Error
0.12
Treynor Ratio
-3.124
Total Fees
$82.29
/*
 * Swing Trading
 * Uses a filter to only detect significant swings
 * This algorithm is always in the market
 * An improvement to this algorithm would be to use the Livermore
 * approach and exit the market on the change in swing direction.
 * The next trade is only entered into when there is a peneration 
 * on the current swing move.  Thus
 *
 *
*/ 

using QuantConnect.Data.Market;
using QuantConnect.Data.Consolidators;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// Basic template algorithm simply initializes the date range and cash
    /// </summary>
    public class SwingTrade : QCAlgorithm
    {
        /// <summary>
        /// The security symbol under TradeBarConsolidator
        /// </summary>
        private string _symbol = "SPY";
        /// <summary>
        /// Percentage swing filter 
        /// </summary>
        private decimal PercentageSwing = 1.6m;
        /// <summary>
        /// Trend direction, -1 = up, 1 = down 
        /// </summary>
        private decimal _direction;
        /// <summary>
        /// first scan variable, sets the initial value of variables from the first TradeBar
        /// </summary>
        private bool FirstScan = true;
        /// <summary>
        /// Used to hold the current highs, lows and swing highs and lows
        /// </summary>
        private decimal CurrentHigh, CurrentLow, SwingHigh, SwingLow;
        


        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        public override void Initialize()
        {
            SetStartDate(2014, 1, 1);  //Set Start Date
            SetEndDate(2014, 6, 30);    //Set End Date
            SetCash(100000);             //Set Strategy Cash
            
            // Add security
            AddSecurity(SecurityType.Equity, _symbol, Resolution.Hour);
			
			// Setup Trade Bar Consolidator
            var joinedBar = new TradeBarConsolidator(TimeSpan.FromHours(24));
            joinedBar.DataConsolidated += NewBar;
            SubscriptionManager.AddConsolidator(_symbol, joinedBar);
			
			//Setup charting
			Chart plotter = new Chart("Swing", ChartType.Overlay);
            plotter.AddSeries(new Series("SPY", SeriesType.Line));
            plotter.AddSeries(new Series("Swing_Points", SeriesType.Line));
            //plotter.AddSeries(new Series("", SeriesType.Scatter));
            AddChart(plotter);
        }

        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new consolidated data point will be pumped in here.
        /// </summary>
        /// <param name="data">Slice object keyed by symbol containing the stock data</param>
        private void NewBar(object sender, TradeBar data)
        {
            var _swingfilter = Decimal.Divide(PercentageSwing, 100m);
            var _high = data.High;
            var _low = data.Low;
            var _close = data.Close;
            var _open = data.Open;
            
            if(FirstScan)
            {
                CurrentHigh = _high;
                CurrentLow = _low;
                SwingHigh = _high;
                SwingLow = _low;
                _direction = (_close > (_high + _low) / 2) ? -1m : 1m;
                //plot first swing point
                if(_direction == 1) 
                {
                	Plot("Swing", "Swing_Points", SwingHigh);
                }
                else
                {
                	Plot("Swing", "Swing_Points", SwingLow);
                }
                FirstScan = false;
                Debug("First scan finished");
                return;
            }
            
            ///Searches for a reversal then will search for a new high
            if(_direction == -1)
            {
                if(_low < (CurrentHigh - Decimal.Multiply(_swingfilter,CurrentHigh)))
                {
                    _direction = 1m;
                    SwingHigh = CurrentHigh;
                    CurrentLow = _low;
                    Plot("Swing", "Swing_Points", SwingHigh);
                    if (!Portfolio.Invested)
		            {
		                SetHoldings(_symbol, -0.25m);
		                Debug("Purchased Stock");
		            }
		             SetHoldings(_symbol, -0.5m);
                }
                else if (_high > CurrentHigh)
                {
                    CurrentHigh = _high;
                }

            }
            ///Searches for a reversal then will search for a new low
            else if (_direction == 1)
            {
                
                if (_high > (CurrentLow - Decimal.Multiply(_swingfilter, CurrentLow)))
                {
                    _direction = -1m;
                    SwingLow = CurrentLow;
                    CurrentHigh = _high;
                    Plot("Swing", "Swing_Points", SwingLow);
                    if (!Portfolio.Invested)
		            {
		                SetHoldings(_symbol, 0.25m);
		                Debug("Purchased Stock");
		            }
		             SetHoldings(_symbol, 0.5m);
                }
                else if (_low < CurrentLow)
                {
                    CurrentLow = _low;
                }
            }

            //Plotting
            Plot("Swing", "SPY", data.Close);
        }
        
        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        /// <param name="data">Slice object keyed by symbol containing the stock data</param>
        public void OnData(TradeBars data)
        {

        }
    }
}