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