Overall Statistics
Total Trades
990
Average Win
2.05%
Average Loss
-1.92%
Compounding Annual Return
31.304%
Drawdown
32.900%
Expectancy
0.306
Net Profit
383.701%
Sharpe Ratio
1.037
Loss Rate
37%
Win Rate
63%
Profit-Loss Ratio
1.07
Alpha
0.23
Beta
0.056
Annual Standard Deviation
0.228
Annual Variance
0.052
Information Ratio
0.508
Tracking Error
0.25
Treynor Ratio
4.26
Total Fees
$0.00
namespace QuantConnect 
{  
    public class ForexAlgorithm : QCAlgorithm
    {
    	public string[] symbols = {"AUDUSD","EURAUD","EURCAD","EURGBP","EURJPY","EURNZD","EURUSD","GBPUSD","NZDUSD","USDCAD","USDJPY"};
    	
    	private Dictionary<string, RelativeStrengthIndex> rsi = new Dictionary<string, RelativeStrengthIndex>();
    	private Dictionary<string, ExponentialMovingAverage> srsi = new Dictionary<string, ExponentialMovingAverage>();
    	
    	AverageTrueRange ATR;
    	public decimal ATRL;
    	public decimal ATRS;
    	
    	public decimal EPL;
    	public decimal EPS;
    	
    	public DateTime EntryTimeL;
    	public DateTime EntryTimeS;
    	
    	RollingWindow<decimal>eu;
    	RollingWindow<bool>Long;
    	RollingWindow<bool>Short;
    	public bool open;
    	
		public override void Initialize() 
        {
            SetStartDate(2016, 1, 1);
            SetEndDate(DateTime.Now);
            SetCash(10000);
            
            foreach (var symbol in symbols)
            {
            	AddSecurity(SecurityType.Forex, symbol, Resolution.Hour);
            	rsi[symbol]=RSI(symbol,14, MovingAverageType.Wilders,Resolution.Hour);
            	srsi[symbol]=new ExponentialMovingAverage(20).Of(rsi[symbol]);
            	SetWarmup(1005);
            }
            ATR = ATR("EURUSD",20,MovingAverageType.Wilders,Resolution.Hour);
            eu = new RollingWindow<decimal>(1005);
            Long = new RollingWindow<bool>(5);
            Short = new RollingWindow<bool>(5);
        }
        public decimal MA_Simple(int period, int ii) {
    			if (period != 0 && ii > period) {
        			decimal summ = 0;
        			for (int i = 0; i <= period; i++) {
            			summ = summ + eu[i];
        		}
        			summ = summ / period;
        			return summ;
    		} else return -1;
		}
        public void OnData(QuoteBars data) 
        {
        	if (!ATR.IsReady) return;
        	if (!(ATR>0)) return;
        	var qty = Math.Floor(Portfolio.TotalPortfolioValue*2);
        	var stopDistL = 8*ATRL;
        	var stopDistS = 8*ATRS;
        	var holdTime = 42;
        	
        	var currentPrice = data["EURUSD"].Price;
        	
        	var EURAUD = srsi["EURAUD"];
        	var EURCAD = srsi["EURCAD"];
        	var EURGBP = srsi["EURGBP"];
        	var EURJPY = srsi["EURJPY"];
        	var EURNZD = srsi["EURNZD"];
        	var EURUSD = srsi["EURUSD"];
        	
        	var AUDUSD = srsi["AUDUSD"];
        	var GBPUSD = srsi["GBPUSD"];
        	var NZDUSD = srsi["NZDUSD"];
        	
        	var USDJPY = srsi["USDJPY"];
        	var USDCAD = srsi["USDCAD"];
        	var USDAUD = 100-AUDUSD;
        	var USDEUR = 100-EURUSD;
        	var USDGBP = 100-GBPUSD;
        	var USDNZD = 100-NZDUSD;
        	
        	var eurIndex = (EURAUD+EURCAD+EURGBP+EURJPY+EURNZD+EURUSD+EURUSD+EURUSD)/8;
            var usdIndex = (USDAUD+USDCAD+USDGBP+USDJPY+USDNZD+USDEUR+USDEUR+USDEUR)/8;
           
            var EU = eurIndex-usdIndex;
            eu.Add(EU);
            if(!eu.IsReady) return;
			
           var midline = MA_Simple(1000,1001);
            
            var lag = (eu[0]+eu[1]+eu[2]+eu[3])/4;
            
            var a = eu[0]>lag;
            
            var CrossAbove = a;
            var CrossBelow = !a;
            
            var BelowMid = EU < midline;
            var AboveMid = EU > midline;
            
            var longCondition = CrossAbove && BelowMid;
            var shortCondition = CrossBelow && AboveMid;
            
            Long.Add(longCondition);
            if (!Long.IsReady) return;
            Short.Add(shortCondition);
            if (!Short.IsReady) return;
            
            var Buy = Long[0] && !Long[1];
            var Sell = Short[0] && !Short[1];
            
            if (Portfolio["EURUSD"].IsLong && Buy)
            {
            	MarketOrder("EURUSD", qty, false, "Adding Long EURUSD");
            	EPL = data["EURUSD"].Price;
            	EntryTimeL = Time;
            	ATRL = ATR;
            }
            if (!Portfolio["EURUSD"].IsLong && Buy)
            {
            	if (Portfolio.Invested)
            	{
            		SetHoldings("EURUSD", 0, false, "Clear EURUSD");
            	}
            	MarketOrder("EURUSD", qty, false, "Initial Long EURUSD");
            	EntryTimeL = Time;
            	EPL = data["EURUSD"].Price;
            	ATRL = ATR;
            }
            var timeExit = (Time - EntryTimeL) >= TimeSpan.FromHours(holdTime);
            var stopL = EPL - data["EURUSD"].Price >= stopDistL;
            if (Portfolio["EURUSD"].IsLong && (timeExit||stopL))
            {
            	SetHoldings("EURUSD", 0, false, "Close EURUSD");
            	if (timeExit)
            	{
            		Log("Closed long due to time");
            	}
            	if(stopL)
            	{
            		Log("Closed long due to stop out");
            	}
            }
            
            if (Portfolio["EURUSD"].IsShort && Sell)
            {
            	MarketOrder("EURUSD", -qty, false, "Adding Short EURUSD");
            	EPS = data["EURUSD"].Price;
            	EntryTimeS = Time;
            	ATRS = ATR;
            }
            if (!Portfolio["EURUSD"].IsShort && Sell)
            {
            	if (Portfolio.Invested)
            	{
            		SetHoldings("EURUSD", 0, false, "Clear EURUSD");
            	}
            	MarketOrder("EURUSD", -qty, false, "Initial Short EURUSD");
            	EntryTimeS = Time;
            	EPS = data["EURUSD"].Price;
            	ATRS = ATR;
            }
            var timeExit1 = (Time - EntryTimeS) >= TimeSpan.FromHours(holdTime);
            var stopS = data["EURUSD"].Price-EPS >= stopDistS;
            if (Portfolio["EURUSD"].IsShort && (timeExit1||stopS))
            {
            	SetHoldings("EURUSD", 0, false, "Close EURUSD");
            	if (timeExit1)
            	{
            		Log("Closed short due to time");
            	}
            	if(stopS)
            	{
            		Log("Closed short due to stop out");
            	}
            }
        }
    }
}