using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MarketData.Utils;
using MarketData.Numerical;

namespace MarketData.MarketDataModel
{
  public class BollingerBandElementsByDate : Dictionary<DateTime, BollingerBandElement>
  {
    public BollingerBandElementsByDate()
    {
    }
  }
  public class BollingerBands : BollingerBandElements 
  {
    public BollingerBands()
    {
    }
    public BollingerBands(List<BollingerBandElement> bollingerBandElements)
    {
      foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement);
    }
    public static String GetHeader(int movingAverageDays=20)
    {
      StringBuilder sb = new StringBuilder();
      sb.Append("Date,Symbol,Open,High,Low,Close,Volume,SMA(").Append(movingAverageDays).Append("),StDev(").Append(movingAverageDays).Append("),K,L,K-1,L+1");
      return sb.ToString();
    }
    public BollingerBandElementsByDate GetBollingerBandElementsByDate()
    {
      BollingerBandElementsByDate bollingerBandElementsByDate = new BollingerBandElementsByDate();
      for (int index = 0; index < Count; index++)
      {
        BollingerBandElement bollingerBandElement = this[index];
        if (!bollingerBandElementsByDate.ContainsKey(bollingerBandElement.Date)) bollingerBandElementsByDate.Add(bollingerBandElement.Date, bollingerBandElement);
      }
      return bollingerBandElementsByDate;
    }
  }
// **********************************************************************************
  public class BollingerBandElements : List<BollingerBandElement>
  {
    public BollingerBandElements()
    {
    }
    public BollingerBandElements(List<BollingerBandElement> bollingerBandElements)
    {
      foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement);
    }
		public LeastSquaresResult LeastSquaresFitClose()
		{
			double[] closingPrices=(from BollingerBandElement bollingerBandElement in this select bollingerBandElement.Close).ToList().ToArray();
			LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(closingPrices);
			return leastSquaresResult;
		}
  }
  public class BollingerBandElement
  {                                                                                 
    private DateTime date;
    private String symbol;
    private double open;
    private double high;
    private double low;
    private double close;
    private long volume;
    private double smaN;
    private double stdevN;
    private double k;
    private double l;
    private double kl1;
    private double lp1;

    public BollingerBandElement()
    {
    }
    public DateTime Date
    {
      get { return date; }
      set { date = value; }
    }
    public String Symbol
    {
      get { return symbol; }
      set { symbol = value; }
    }
    public double Open
    {
      get { return open; }
      set { open = value; }
    }
    public double High
    {
      get { return high; }
      set { high = value; }
    }
    public double Low
    {
      get { return low; }
      set { low = value; }
    }
    public double Close
    {
      get { return close; }
      set { close = value; }
    }
    public double SMAN
    {
      get { return smaN; }
      set { smaN = value; }
    }
    public double StDevN
    {
      get { return stdevN; }
      set { stdevN = value; }
    }
    public long Volume
    {
      get { return volume; }
      set { volume = value; }
    }
    public double K
    {
      get { return k; }
      set { k = value; }
    }
    public double L
    {
      get { return l; }
      set { l = value; }
    }
    public double KL1
    {
      get { return kl1; }
      set { kl1 = value; }
    }
    public double LP1
    {
      get { return lp1; }
      set { lp1 = value; }
    }
    public override String ToString()
    {
      StringBuilder sb = new StringBuilder();
      sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(",");
      sb.Append(Symbol).Append(",");
      sb.Append(Open).Append(",");
      sb.Append(High).Append(",");
      sb.Append(Low).Append(",");
      sb.Append(Close).Append(",");
      sb.Append(Volume).Append(",");
      sb.Append(SMAN).Append(",");
      sb.Append(StDevN).Append(",");
      sb.Append(K).Append(",");
      sb.Append(L).Append(",");
      sb.Append(KL1).Append(",");
      sb.Append(LP1);
      return sb.ToString();
    }
  }
}
