Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0.805
Tracking Error
0.969
Treynor Ratio
0
Total Fees
$0.00
using MathNet.Numerics.Statistics;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
    public class ValueArea_AMT : QCAlgorithm
    {

		Resolution resolution = Resolution.Second;
		decimal ticks = 0.25m;

		decimal POC = 0m;
		decimal VAHigh = 0m;
		decimal VALow = 0m;

        public override void Initialize()
        {
            SetStartDate(2020, 3, 1);  //Set Start Date
            //SetEndDate(2020, 2, 7);
            SetCash(100000);             //Set Strategy Cash

            // Store symbol objects in List manually for now 
            Symbol spy = AddEquity("SPY", Resolution.Minute).Symbol;

			
			// Schedule calculate value area once per day
			Schedule.On(DateRules.EveryDay(), TimeRules.At(9, 0), () =>
            {
    			// History call stuck in some infinite loop on the 5th and 6th...
    			
    			// Get the last trading day's worth of bars @ minute resolution
    			var bars = History<TradeBar>(spy, 450, Resolution.Minute);
				var VA = ValueArea(bars);
				POC = VA.Item1;
				VAHigh = VA.Item2;
				VALow = VA.Item3;
				Debug("POC " + POC + " VAHigh " + VAHigh + " VALow " + VALow);
				
            });
            
            
        }
       
        public override void OnData(Slice data)
        {
	    	// Do something   
	    }
		
		public Tuple<decimal,decimal,decimal> ValueArea(IEnumerable<TradeBar> history)
    	{
            // Define minimum price interval (ticks)
            int interval = 2;
            IDictionary<decimal,decimal> intervalpricevol = new Dictionary<decimal,decimal>(); // empty dict
			
			// Strip out close and volume from history, zip into a collection 
			List<decimal> volumes = history.Select(x => x.Volume).ToList();
			List<decimal> closes = history.Select(x => x.Close).ToList();
    		
	        var pricevol = volumes
	        	.Zip(closes, (key, value) => new  { key, value })
	        	.ToLookup(x => x.key, x => x.value);

            decimal _hiclose = closes.Max();
	        decimal _loclose = closes.Min();

			decimal _indprice = _hiclose; //index slice for iterating through dict, from hi to lo
	
            // Turn pricevol ticks into a collection of intervals
            while (_indprice >= (_loclose - ticks))
            {
            	decimal _tickvol = 0m; // count er for volumes
            	
            	// loop through and find valid values
	            foreach(var pair in pricevol)
				{
					foreach (decimal value in pair)
	        		// Get total volume of prices in range
	        		if (value <= _indprice && value > (_indprice - ticks))
	        		{
	        			_tickvol += pair.Key;
	        		}
				}

				// add new vol/price pair to dict if vol not zero
				if (_tickvol != 0)
				{
    				intervalpricevol.Add(new KeyValuePair<decimal, decimal>(_tickvol, _indprice));
    			
				}
    			
        		
        		// re-index _indprice to one tick below
        		_indprice -= ticks; 
        		
			}
			//Debug("volume check " + (volumes.Sum() - intervalpricevol.Keys.Sum()));
			
			// Calculate POC
            POC = intervalpricevol[ intervalpricevol.Keys.Max() ];
            
            // counter for prices above and below POC 
			VAHigh = POC;
			VALow = POC;
            
            // counter for total, above and below volume
        	decimal _volumecounter = 0m;
    		decimal _prevabovevolume = 0m;
			decimal _prevbelowvolume = 0m;
			
			// Get total volume and * 0.70 to get Value Area threshold volume
			decimal _70_percent_lvl = volumes.Sum() * 0.7m;
            // loop through dictionary while volume counter < _70_percent_lvl
            while (_volumecounter < _70_percent_lvl)
            {
				// counters for total areas
				decimal _abovevolume = 0m;
    			decimal _belowvolume = 0m;
            	
            	// Iterate over entire dict to find volumes VALow< prices < VAHigh
	            foreach(KeyValuePair<decimal,decimal> pair in intervalpricevol)
				{	
				    // if volume of prices that trade above POC > below, add that slice to value area and v.v.
				    if (pair.Value > POC && pair.Value <= (VAHigh + ticks * interval) )
					{
						_abovevolume += pair.Key;
					}    
				    
				    if (pair.Value < POC && pair.Value >= (VALow - ticks * interval))
				    {
				    	_belowvolume += pair.Key;
				    }	
			    }	     
				
				// Compare slices and add the slice with greater volume to Value Area
			    if ((_abovevolume - _prevabovevolume) >= (_belowvolume - _prevbelowvolume))
		    	{
		    		VAHigh += ticks * interval;
		    		_volumecounter += (_abovevolume - _prevabovevolume);
					_prevabovevolume = _abovevolume;
		    	}	
			    else
			    {
			    	VALow -= ticks * interval;
			    	_volumecounter += (_belowvolume - _prevbelowvolume);
			    	_prevbelowvolume = _belowvolume;
			    }
            }
	        return Tuple.Create(POC,VAHigh, VALow);
    	}

	    
    }
}