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