| Overall Statistics |
|
Total Trades 16 Average Win 4.74% Average Loss -4.72% Compounding Annual Return 18.343% Drawdown 10.200% Expectancy 0.502 Net Profit 19.275% Sharpe Ratio 1.236 Loss Rate 25% Win Rate 75% Profit-Loss Ratio 1.00 Alpha 0.086 Beta 4.663 Annual Standard Deviation 0.145 Annual Variance 0.021 Information Ratio 1.098 Tracking Error 0.145 Treynor Ratio 0.038 Total Fees $51.09 |
namespace QuantConnect
{
/*
* Filter and Trigger template
*/
public class FilterAndTriggerAlgorithm : QCAlgorithm
{
string _symbol = "AAPL";
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(2018, 1, 1);
SetEndDate(DateTime.Now);
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;
}
}
if(Portfolio[_symbol].IsLong)
{
if(_Liquidate_Long()){
SetHoldings(_symbol,0);
Debug("Liquidating Long!");
_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)
{
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("Buying = rsi is bigger than 60: " + _rsi);
Plot("Plotter", "Sell - Stop Loss", _price);
return true;
}
else{
return false;
}
}
}
}