using MarketData.Generator.MovingAverage;
using MarketData.MarketDataModel;
using MarketData.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MarketData.Generator.ModelGenerators
{
// Calculates Volatility as 3x Average True Range
  public class VolatilityGenerator
  {
    public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays=10)
    {
      return CalculateVolatility(symbol,date,movingAverageDays,3.00);
    }
    public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays,double atrMultiplier)
    {
      double volatility=double.NaN;
      DateGenerator dateGenerator=new DateGenerator();
      Dictionary<DateTime,double> trueRangeCollectionByDate=new Dictionary<DateTime,double>();
      List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(date,(movingAverageDays+1)*2);      // most recent date in lowest index, we need to generate (items+1)
      for(int dateIndex=0;dateIndex<historicalDates.Count;dateIndex++)
      {
        DateTime historicalDate=historicalDates[dateIndex];
        TrueRangeResult trueRangeResult=TrueRangeGenerator.GenerateAverageTrueRange(symbol,historicalDate);
        if(null==trueRangeResult)continue;
        trueRangeCollectionByDate.Add(historicalDate,trueRangeResult.AverageTrueRange);
      }
      if(movingAverageDays>trueRangeCollectionByDate.Count) return volatility;
      historicalDates=new List<DateTime>(trueRangeCollectionByDate.Keys.OrderByDescending(x=>x.Date));
      Prices prices=new Prices();
      foreach(DateTime historicalDate in historicalDates)
      {
        Price price=new Price();
        price.Symbol=symbol;
        price.Date=historicalDate;
        price.Close=trueRangeCollectionByDate[historicalDate];
        prices.Add(price);
      }
      DMAPrices emaPrices=MovingAverageGenerator.GenerateExponentialMovingAverage(prices,movingAverageDays);
      if(null==emaPrices||0==emaPrices.Count)return volatility;
      volatility=emaPrices[0].AVGPrice*atrMultiplier;
      return volatility;
    }

  }
}
