Overall Statistics
Total Trades
2005
Average Win
0.81%
Average Loss
-0.60%
Compounding Annual Return
376.633%
Drawdown
16.300%
Expectancy
0.281
Net Profit
393.229%
Sharpe Ratio
5.232
Probabilistic Sharpe Ratio
97.492%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
1.33
Alpha
3.398
Beta
-0.148
Annual Standard Deviation
0.64
Annual Variance
0.41
Information Ratio
4.567
Tracking Error
0.664
Treynor Ratio
-22.662
Total Fees
$8773.98
Estimated Strategy Capacity
$130000000.00
Lowest Capacity Asset
OEG XEEQU7AFNHPH
//Copyright HardingSoftware.com. Granted to the public domain.
//Use entirely at your own risk.
//This algorithm contains open source code from other sources,
//no claim is being made to such code.
//Do not remove this copyright notice.
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;

namespace QuantConnect.Algorithm.CSharp
{
    public class UniverseTemplate : QCAlgorithm
    {
		
		int TotalHighDollarVolumeStocks = 50;
		IDictionary<Symbol,SymbolData> HighDollarVolumeStocks = new Dictionary<Symbol, SymbolData>();
		int TotalStocksToHold = 5;
		Resolution Resolution = Resolution.Daily;
		int Period = 10;
		decimal Leverage = 0.99m;
		
        public override void Initialize()
        {
            UniverseSettings.Resolution = Resolution;

            SetStartDate(2020, 6, 02);
            SetCash(100000);

            AddUniverse(coarse =>
            {
            	return (from stock in coarse
            			orderby stock.DollarVolume descending  
            			select stock.Symbol).Take(TotalHighDollarVolumeStocks);
            });
        }

        public void OnData(TradeBars data)
        {
        	foreach(KeyValuePair<Symbol,SymbolData> kvp in HighDollarVolumeStocks){
        		if(data.ContainsKey(kvp.Key)){
        			TradeBar bar = data[kvp.Key];
        			HighDollarVolumeStocks[kvp.Key].Update(bar);
        			if(HighDollarVolumeStocks[kvp.Key].IsReady){
        				HighDollarVolumeStocks[kvp.Key].CalculateStochastic();
        				
        			}
        		}
        	}
        	List<SymbolData> stocksToHold = HighDollarVolumeStocks.Values.OrderByDescending(x => x.Stochastic).Take(TotalStocksToHold).ToList();
            
            

            foreach (var security in Portfolio.Values)
            {
            	if (Portfolio[security.Symbol].Invested)
            	{
	                if (stocksToHold.Exists(x => x.symbol == security.Symbol) == false)
	                {
	                    Liquidate(security.Symbol);
	                }
            	}
            }
            
            foreach (var security in stocksToHold)
            {
        		if (Portfolio[security.symbol].Quantity >= 0)
        		{
					SetHoldings(security.symbol, -Leverage / (decimal)TotalStocksToHold);
        		}
            }

        }
        public class SymbolData{
        	public Symbol symbol;
        	public decimal Stochastic;
        	public Maximum max = new Maximum(10);
        	public Minimum min = new Minimum(10);
        	public TradeBar current = null;
        	public bool IsReady = false;
        	public void Update(TradeBar bar){
        		current = bar;
        		max.Update(bar.Time,bar.High);
        		min.Update(bar.Time,bar.Low);
        		if(current!=null && max.IsReady && min.IsReady){
        			IsReady = true;
        		}
        		
        	}
        	public decimal CalculateStochastic(){
        		if(current!=null && max.IsReady && min.IsReady){
        			decimal low = min.Current.Value;
        			decimal high = max.Current.Value;
        			decimal close = current.Close;
        			Stochastic = 100m * (close - low) / (high - low);
        			
        		}
        		return Stochastic;
        	}
        	
        	
        }
		

        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            foreach (var security in changes.RemovedSecurities)
            {   
            	if (HighDollarVolumeStocks.ContainsKey(security.Symbol)){
            		HighDollarVolumeStocks.Remove(security.Symbol);
            	}
            }
            foreach (var security in changes.AddedSecurities)
            {
            	if (!HighDollarVolumeStocks.ContainsKey(security.Symbol)){
            	     	HighDollarVolumeStocks[security.Symbol] = new SymbolData();
            	     	HighDollarVolumeStocks[security.Symbol].symbol = security.Symbol;
            	     	var history = History(security.Symbol, 10, Resolution.Daily);
                        foreach (var bar in history) {
                            HighDollarVolumeStocks[security.Symbol].Update(bar);
                         }
            	}
            	
            }
        }
        
        
    }
}