| Overall Statistics |
|
Total Trades 12 Average Win 1.35% Average Loss -1.93% Compounding Annual Return -0.914% Drawdown 3.800% Expectancy -0.151 Net Profit -1.819% Sharpe Ratio -0.32 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 0.70 Alpha -0.062 Beta 2.657 Annual Standard Deviation 0.028 Annual Variance 0.001 Information Ratio -1.048 Tracking Error 0.028 Treynor Ratio -0.003 Total Fees $22.37 |
namespace QuantConnect
{
/*
* Filter and Trigger template
*/
public class FilterAndTriggerAlgorithm : QCAlgorithm
{
string _symbol = "SPY";
private int _kPeriod = 14;
private int _dPeriod = 3;
RelativeStrengthIndex _rsi;
ExponentialMovingAverage _ema, _ema_long, _ema_long_bottom;
MovingAverageConvergenceDivergence _macd;
Stochastic _sto;
RollingWindow<IndicatorDataPoint> _window;
decimal _price;
decimal _short_price, _long_price;
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
//#5 - Stock Plotter with Trades
Chart plotter = new Chart("Plotter");
plotter.AddSeries(new Series("Price", SeriesType.Line, index:0));
plotter.AddSeries(new Series("50MA", SeriesType.Line, index:0));
plotter.AddSeries(new Series("Buy", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Sell", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Buy - Liquidate", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Sell - Liquidate", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Buy - Stop Loss", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Sell - Stop Loss", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("RSI", SeriesType.Line, index:1));
AddChart(plotter);
//Initialize
SetStartDate(2017, 1, 1);
SetEndDate(2019, 1, 1);
SetCash(100000);
_short_price = 0.0m;
_long_price = 0.0m;
//Add as many securities as you like. All the data will be passed into the event handler:
AddSecurity(SecurityType.Equity, _symbol, Resolution.Daily);
//Set up Indicators:
_rsi = RSI(_symbol, 14, MovingAverageType.Simple, Resolution.Daily);
_sto = STO(_symbol, 14, _kPeriod, _dPeriod);
_ema_long = EMA(_symbol, 14, Resolution.Daily);
_ema_long_bottom = EMA(_symbol, 50, Resolution.Daily);
_window = new RollingWindow<IndicatorDataPoint>(2);
// Here is where the RollingWindow is updated with the latest RSI observation.
_rsi.Updated += (object sender, IndicatorDataPoint updated) =>
{
_window.Add(updated);
};
}
public void OnData(TradeBars data)
{
if (!_ema_long.IsReady) return;
if (!_window.IsReady) return;
if (!_rsi.IsReady) return;
if (!_sto.IsReady) return;
_price = data[_symbol].Close;
//Debug("short_price " + _short_price + " long_price: " + _long_price + " short difference: " + (_short_price - _price) + " long difference: " + (_long_price - _price));
// If filter is positive
if (Filter())
{
// If we have a trigger, go long
if(Trigger_long()){
//Order function places trades: enter the string symbol and the quantity you want:
SetHoldings(_symbol, 1);
_long_price = _price;
StopMarketOrder(_symbol, -1 * Portfolio[_symbol].Quantity, _price * .98m);
Debug("Trigger Long!");
}
}
// If filter is negative
else{
// If we have a trigger, go short
if(Trigger_short()){
//Order function places trades: enter the string symbol and the quantity you want:
SetHoldings(_symbol, -1);
_short_price = _price;
StopMarketOrder(_symbol, -1 * Portfolio[_symbol].Quantity, _price * .98m);
Debug("Trigger short!");
}
}
if(Portfolio[_symbol].IsShort)
{
if(_Liquidate_Short()){
SetHoldings(_symbol,0);
Debug("Liquidating Short!");
_short_price = 0.0m;
}
else if(_Short_Stop())
{
SetHoldings(_symbol,0);
Debug("Short Stop Loss!");
_short_price = 0.0m;
}
}
if(Portfolio[_symbol].IsLong)
{
if(_Liquidate_Long()){
SetHoldings(_symbol,0);
Debug("Liquidating Long!");
_long_price = 0.0m;
}
else if(_Long_Stop())
{
SetHoldings(_symbol,0);
Debug("Long Stop Loss!");
_long_price = 0.0m;
}
}
// if(_Short_Stop())
// {
// SetHoldings(_symbol,0);
// Debug("Short Stop Loss!");
// _short_price = 0.0m;
// }
// if(_Long_Stop())
// {
// SetHoldings(_symbol,0);
// Debug("Long Stop Loss!");
// _long_price = 0.0m;
// }
Plot("Plotter", "Price", _price);
Plot("Plotter", "50MA", _ema_long);
Plot("Plotter", "RSI", _rsi);
}
public bool Filter()
{
if(_price > _ema_long){
//Debug("Filter Positive = EMA long and price: " + _ema_long + _price);
return true;
}
else{
//Debug("Filter Negative = EMA long and price: " + _ema_long + _price);
return false;
}
}
public bool Trigger_long()
{
if(_rsi > 35 && _window[1] < 35){
Plot("Plotter", "Buy", _price);
//Debug("Triggering = rsi exceeded 20: " + _rsi);
return true;
}
else{
//Debug("NOT Triggering = rsi didn't exceeded 20: " + _rsi);
return false;
}
}
public bool Trigger_short()
{
if(_rsi < 65 && _window[1] > 65){
Plot("Plotter", "Sell", _price);
//Debug("Triggering = rsi exceeded 20: " + _rsi);
return true;
}
else{
//Debug("NOT Triggering = rsi didn't exceeded 20: " + _rsi);
return false;
}
}
public bool _Liquidate_Short()
{
if(_rsi < 40){
Plot("Plotter", "Buy - Liquidate", _price);
Debug("Selling = rsi is smaller than 40: " + _rsi);
return true;
}
else{
//Debug("NOT Selling = rsi didn't exceed 65: " + _rsi);
return false;
}
}
public bool _Liquidate_Long()
{
if(_rsi > 60){
Plot("Plotter", "Sell - Liquidate", _price);
Debug("Buying = rsi is bigger than 60: " + _rsi);
return true;
}
else{
//Debug("NOT Buying = rsi isn''t smaller than 25: " + _rsi);
return false;
}
}
public bool _Short_Stop()
{
if(Portfolio[_symbol].IsShort && (this._short_price - this._price) < -1m * this._short_price * .02m)
{
Debug(" (this._short_price - this._price) " + (this._short_price - this._price) + " -1m * this._short_price * .02m" + -1m * this._short_price * .02m);
Plot("Plotter", "Buy - Stop Loss", _price);
return true;
}
else{
return false;
}
}
public bool _Long_Stop()
{
if(Portfolio[_symbol].IsLong && (this._long_price - this._price) > this._long_price * .02m)
{
Debug("this._long_price - this._price " + (this._long_price - this._price) + " this._long_price * .02m " + this._long_price * .02m);
Plot("Plotter", "Sell - Stop Loss", _price);
return true;
}
else{
return false;
}
}
}
}