Overall Statistics
Total Trades
139
Average Win
1.69%
Average Loss
-1.85%
Compounding Annual Return
6.300%
Drawdown
53.900%
Expectancy
0.276
Net Profit
84.318%
Sharpe Ratio
0.415
Loss Rate
33%
Win Rate
67%
Profit-Loss Ratio
0.91
Alpha
0.081
Beta
-0.069
Annual Standard Deviation
0.191
Annual Variance
0.037
Information Ratio
0.216
Tracking Error
0.301
Treynor Ratio
-1.158
Total Fees
$249.58
using System;
using QuantConnect.Orders;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;

namespace QuantConnect.RsiMovingAverage
{
	public partial class RsiMovingAverageAlgorithm
	{

		bool IsExitSignal(decimal currentPrice)
		{
			if (!rsi.IsReady || currentOrder == null || !currentOrder.Status.IsFill())
			{
				return false;
			}

			var elapsedTime = Time - purchaseDate;
			var isPastHoldPeriod = elapsedTime >= holdPeriod;

			var marketInversion = isShortPosition ? IsLongSignal() : IsShortSignal();

			return marketInversion;// || isPastHoldPeriod;
		}

		bool IsLongSignal()
		{
			return IsUptrend() && IsOverSold();
		}

		bool IsShortSignal()
		{
			return IsDowntrend() && IsOverBought();
		}

		bool IsDowntrend()
		{
			if (!shortMovingAverage.IsReady || !longMovingAverage.IsReady) 
			{
				return false;
			}

			return shortMovingAverage < longMovingAverage;
		}

		bool IsOverBought()
		{
			if (!rsi.IsReady)
			{
				return false;
			}

			return rsi > 92.5m;
		}

		bool IsUptrend()
		{
			if (!shortMovingAverage.IsReady || !longMovingAverage.IsReady) 
			{
				return false;
			}

			return shortMovingAverage > longMovingAverage;
		}


		bool IsOverSold()
		{
			if (!rsi.IsReady)
			{
				return false;
			}

			return rsi < 7.5m;
		}
	}

}
using System;
using QuantConnect.Orders;

namespace QuantConnect.RsiMovingAverage
{
	public partial class RsiMovingAverageAlgorithm
	{
		int GetPositionSize(decimal currentPrice)
		{
			// Fixed Fractional Position Sizing
			// N = M * R / | p_0 - p_1 | = M * R / S_i
			var S_i = 0.02m * currentPrice;
			var N = Portfolio.Cash * 0.02m / S_i;
			return (int)Math.Floor(N);
		}

		void EnterLong(decimal currentPrice)
		{
			int quantity = GetPositionSize(currentPrice);

			currentOrder = Buy(symbol, quantity);
			profitTarget = LimitOrder(symbol, -quantity, currentPrice * 1.02m);
			stopLoss = StopMarketOrder(symbol, -quantity, currentPrice * 0.98m);

			highPrice = lowPrice = currentPrice;
			isShortPosition = false;
			purchaseDate = Time;
		}

		void EnterShort(decimal currentPrice)
		{
			int quantity = GetPositionSize(currentPrice);

			currentOrder = Sell(symbol, quantity);
			profitTarget = LimitOrder(symbol, quantity, currentPrice * 0.98m);
			stopLoss = StopMarketOrder(symbol, quantity, currentPrice * 1.02m);

			highPrice = lowPrice = currentPrice;
			isShortPosition = true;
			purchaseDate = Time;
		}

		void ExitMarket()
		{
			var quantity = Portfolio[symbol].Quantity;

			if (profitTarget != null)
			{
				profitTarget.Cancel();
			}

			if (stopLoss != null)
			{
				stopLoss.Cancel();
			}

			if (isShortPosition)
			{
				currentOrder = Buy(symbol, quantity);
			}
			else
			{
				currentOrder = Sell(symbol, quantity);
			}
		}

		void UpdateStopLoss(decimal currentPrice)
		{
			var newHigh = currentPrice > highPrice;
			var newLow = currentPrice < lowPrice;
			if (newHigh)
			{
				highPrice = currentPrice;
			}

			if (newLow)
			{
				lowPrice = currentPrice;
			}

			if (isShortPosition && newLow)
			{
				//stopLoss.Update(new UpdateOrderFields{ StopPrice = currentPrice * 1.02m });
			}

			if (!isShortPosition && newHigh)
			{
				//stopLoss.Update(new UpdateOrderFields{ StopPrice = currentPrice * 0.98m });
			}
		}

		public override void OnOrderEvent(OrderEvent orderEvent)
		{
			if (!orderEvent.Status.IsClosed())
			{
				return;
			}
			var filledOrderId = orderEvent.OrderId;

			if (profitTarget != null && stopLoss != null)
			{
				if (profitTarget.OrderId == filledOrderId)// && stopLoss.Status.IsOpen())
				{
					Log(Time+": Cancelling stop loss");

					stopLoss.Cancel();
				}

				if (stopLoss.OrderId == filledOrderId)// && profitTarget.Status.IsOpen())
				{
					Log(Time+": Cancelling profit target");
					profitTarget.Cancel();
				}
			}

			base.OnOrderEvent(orderEvent);
		}

	}
}
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using System;
using QuantConnect.Orders;
using QuantConnect.Data.Market;

namespace QuantConnect.RsiMovingAverage
{   
	public partial class RsiMovingAverageAlgorithm : QCAlgorithm
	{
		string symbol = "SPY";
		//		string symbol = "C"; 
		//		string symbol = "SBUX";
		//		string symbol = "MSFT";

		SimpleMovingAverage shortMovingAverage;
		SimpleMovingAverage longMovingAverage;

		RelativeStrengthIndex rsi;

		DateTime purchaseDate;

		TimeSpan holdPeriod;

		OrderTicket currentOrder;
		OrderTicket profitTarget;
		OrderTicket stopLoss;

		decimal highPrice = decimal.MinValue;
		decimal lowPrice = decimal.MaxValue;

		bool isShortPosition;

		public override void Initialize() 
		{
			SetStartDate(2000, 1, 1);   
			SetEndDate(2010, 1, 1);

			SetCash(25000);

			AddSecurity(SecurityType.Equity, symbol, Resolution.Daily);

			shortMovingAverage = SMA(symbol, 50, Resolution.Daily);
			longMovingAverage = SMA(symbol, 200, Resolution.Daily);

			rsi = RSI(symbol, 2,  MovingAverageType.Simple, Resolution.Daily);

			holdPeriod = TimeSpan.FromDays(5);
		}

		public void OnData(TradeBars data)
		{
			var currentOrderIsFilled = true;
			if (currentOrder != null)
			{
				currentOrderIsFilled = currentOrder.Status.IsFill();
			}

			var inMarket = Portfolio.Securities[symbol].HoldStock;
			if (stopLoss != null)
			{
				inMarket = inMarket && stopLoss.Status.IsOpen();
			}
			if (profitTarget != null)
			{
				inMarket = inMarket && profitTarget.Status.IsOpen();
			}

			var currentPrice = data[symbol].Price;
			if (currentOrderIsFilled && !inMarket)
			{
				TryEnterMarket(currentPrice);
			}
			else if (currentOrderIsFilled && inMarket)
			{
				TryExitMarket(currentPrice);
			}
		}

		private void TryEnterMarket(decimal currentPrice)
		{
			if (IsLongSignal())
			{
				EnterLong(currentPrice);
			}
			else if (IsShortSignal())
			{
				EnterShort(currentPrice);
			}
		}

		private void TryExitMarket(decimal currentPrice)
		{
			if (IsExitSignal(currentPrice))
			{
				ExitMarket();
				highPrice = decimal.MinValue;
				lowPrice = decimal.MaxValue;
			}
			else
			{
				UpdateStopLoss(currentPrice);
			}
		}


	}
}