Overall Statistics
//Copyright HardingSoftware.com, 2018.
//Granted to the public domain.
//Use entirely at your own risk.
namespace QuantConnect 
{   
    public class MultiCoinFramework : QCAlgorithm
    {
    	string tickersString ="TVIX,LABD,UGAZ";
    	
    	//string tickersString ="BTCUSD,ETHUSD,LTCUSD";
    	
    	decimal changes1Ratio=-1.0m; //The influence of change upon fitness.
    	decimal changes2Ratio=-0.4m; //The influence of change in change upon fitness.
    	int emaOfChanges1Length=24; //The length of the change indicator.
		int emaOfChanges2Length=24; //The length of the change in change indicator.
		decimal leverage=1m;
		
		int historyLength=2;
		int changes1Length=5;
		int changes2Length=5;
		Resolution resolution=Resolution.Hour;
		List<StockData> stockDatas = new List<StockData>();
		string stockHeld="";
		
        public override void Initialize() 
        {
            SetStartDate(2010, 3, 1); 
            //SetEndDate(2017, 3, 11);
            SetCash(100000);
			string[] tickers = tickersString.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string ticker in tickers)
			{
				//Symbol symbol = QuantConnect.Symbol.Create(ticker, SecurityType.Crypto, Market.GDAX);
				Symbol symbol = QuantConnect.Symbol.Create(ticker, SecurityType.Equity, Market.USA);
				//AddCrypto(symbol, resolution);
				AddEquity(ticker, resolution);
				StockData stockData=new StockData();
				stockData.Ticker=ticker;
				stockData.emaOfChanges1Indicator = new ExponentialMovingAverage(emaOfChanges1Length);
            	stockData.emaOfChanges2Indicator = new ExponentialMovingAverage(emaOfChanges2Length);
				stockDatas.Add(stockData);
			}
        }

        public override void OnData(Slice data) 
        {
        	foreach (StockData stockData in stockDatas)
        	{
        		
        		if (data.ContainsKey(stockData.Ticker) && data[stockData.Ticker] == null) 
        		{
        			Log(Time +  " " + stockData.Ticker);
        		}
        		
        		if (data.ContainsKey(stockData.Ticker) && data[stockData.Ticker] != null) 
        		{
        			Log(stockData.Ticker + " 1");
		        	stockData.history.Add(data[stockData.Ticker].Close);
		        	if (stockData.history.Count>historyLength)
		        	{
		        		stockData.history.RemoveAt(0);
		        	}
					if (stockData.history.Count>=2)
					{
						if (stockData.history[stockData.history.Count-2]!=0)
						{
							decimal change=(stockData.history.Last()-stockData.history[stockData.history.Count-2])/stockData.history[stockData.history.Count-2];
							stockData.changes1History.Add(change);
							if (stockData.changes1History.Count>changes1Length)
							{
								stockData.changes1History.RemoveAt(0);
							}
						}
					}
					Log(stockData.Ticker + " 2");
					if (stockData.changes1History.Count>=2)
					{
						decimal change=stockData.changes1History.Last()-stockData.changes1History[stockData.changes1History.Count-2];
						stockData.changes2History.Add(change);
						if (stockData.changes2History.Count>changes2Length)
						{
							stockData.changes2History.RemoveAt(0);
						}
					}
					if (stockData.changes1History.Count>0)
					{
						stockData.emaOfChanges1Indicator.Update(Time,stockData.changes1History.Last());
					}
					if (stockData.changes2History.Count>0)
					{
						stockData.emaOfChanges2Indicator.Update(Time,stockData.changes2History.Last());
					}
					Log(stockData.Ticker + " 3");
					stockData.Fitness=changes1Ratio*stockData.emaOfChanges1Indicator+changes2Ratio*stockData.emaOfChanges2Indicator;
        		}
        	}
			Log(" 4");
    	    var q1 = from x in stockDatas
    			orderby x.Fitness descending
    			select x;
        	
        	List<StockData> q2=q1.ToList();
        	if (q2.Count>0)		
        	{
        		StockData selectedStockData=q2.First();
        		if (selectedStockData.Ticker != stockHeld)
        		{
        			Liquidate();
        			SetHoldings(selectedStockData.Ticker, - leverage);
					stockHeld=selectedStockData.Ticker;
        		}

        	}
        	Log(" 5");
        }
        
        class StockData
        {
        	public string Ticker;
			public List<decimal> history=new List<decimal>();
			public List<decimal> changes1History=new List<decimal>();
			public List<decimal> changes2History=new List<decimal>();
			public ExponentialMovingAverage emaOfChanges1Indicator;
			public ExponentialMovingAverage emaOfChanges2Indicator;
			public decimal Fitness;
        }
        
    }
}
namespace QuantConnect {

    //
    //	Make sure to change "BasicTemplateAlgorithm" to your algorithm class name, and that all
    //	files use "public partial class" if you want to split up your algorithm namespace into multiple files.
    //

    //public partial class BasicTemplateAlgorithm : QCAlgorithm, IAlgorithm
    //{
    //  Extension functions can go here...(ones that need access to QCAlgorithm functions e.g. Debug, Log etc.)
    //}

    //public class Indicator 
    //{
    //  ...or you can define whole new classes independent of the QuantConnect Context
    //}
    
    /*
    Framework Description


The framework allows experimentation with, and utilization of, two fundamental properties. 
Those properties are trend and curvature of price. 
For example you may wish to select instruments that have been trending downwards and curving upwards, 
or some other mix of trend and curvature. The changes1Ratio variable determines the influence of trend. 
A positive changes1Ratio will increase the tendency to select instruments that have been trending upwards, 
a negative changes1Ratio will increase the tendency to select instruments that have been trending downwards.  
The changes2Ratio variable determines the influence of curvature. 
A positive changes2Ratio variable will increase the tendency to select instruments with a price that has been curving upwards. 
A negative changes2Ratio will increase the tendency to select instruments with a price that has been curving downwards. 
You can also set either the changes1Ratio or changes2Ratio variable to zero. This will eliminate the influence of that variable. 
So if you just want to select based upon trend with no regards to the curvature you would set the changes2Ratio to zero. 
Magnitude has the obvious effect. 
A large magnitude of changes1Ratio combined with a small magnitude of changes2Ratio will produce an algorithm that mostly considers trend with regards to instrument selection. 
Both the trend and curvature considerations are exponential in nature. So more recent events will have a higher influence upon selection than older events.
 

The emaOfChanges1Indicator indicator is the primary indicator of trend. 
It holds an exponential moving average of the changes in price. 
You can change it's length by adjusting the emaOfChanges1Length variable. 
The emaOfChanges2Indicator indicator is the primary indicator of curvature. 
It holds an exponential moving average of the change in change of price. 
You can change it's length by adjusting the emaOfChanges2Length variable.
 */

}