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

namespace MarketData.MarketDataModel
{
  public class ModelPerformanceSeries : List<ModelPerformanceItem>
  {
    public ModelPerformanceSeries()
    {
    }
    public ModelPerformanceSeries(List<ModelPerformanceItem> modelPerformanceItemList)
    {
      foreach(ModelPerformanceItem modelPerformanceItem in modelPerformanceItemList) Add(modelPerformanceItem);
    }
    public void CalculatePerformance()
    {
      for(int index=0;index<this.Count;index++)
      {
        ModelPerformanceItem currentModelPerformanceItem=this[index];
        ModelPerformanceItem prevModelPerformanceItem=0==index?null:this[index-1];
        if(null==prevModelPerformanceItem)
        {
          currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD;
          if(0==currentModelPerformanceItem.Exposure)currentModelPerformanceItem.R=0;
          else currentModelPerformanceItem.R=(currentModelPerformanceItem.MarketValue-currentModelPerformanceItem.Exposure)/currentModelPerformanceItem.Exposure;
          currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
          currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR;
          currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
        }
        else
        {
          currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD+prevModelPerformanceItem.CumulativeGainLoss;
          if(0==currentModelPerformanceItem.Exposure)currentModelPerformanceItem.R=0;
          else currentModelPerformanceItem.R=prevModelPerformanceItem.Exposure.Equals(currentModelPerformanceItem.Exposure)?(currentModelPerformanceItem.MarketValue-prevModelPerformanceItem.MarketValue)/prevModelPerformanceItem.MarketValue:0;
          currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
          currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR*prevModelPerformanceItem.CumProd;
          currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
        }
      }
    }
  }
  public class ModelPerformanceItem
  {
    public DateTime Date { get; set; }
    public double Exposure { get; set; }           // This is the exposure on a given day.
    public double MarketValue { get; set; }        // This is the MarketValue on a given day
    public double GainLossDOD { get; set; }        // This is the gain loss change from day to day
    public double GainLoss { get; set; }           // This is the gain loss on the given day
    public double CumulativeGainLoss{get;set;}     // This is the cumulative gain loss.  The last item in the series contains the cumulative amount gained or lost.
    public double R{get;set;}                      // This is the period Return.  (MV[n]-MV[n-1])/MV[n-1]
    public double OnePlusR{get;set;}               // (R+1)
    public double CumProd{get;set;}                // (R+1)*(R+1).....
    public double CumProdMinusOne{get;set;}        // subtract 1 from CumProd to get a decimal return.  Each item in the series represents a cumulative return for that date.  The final element contains the cumulative return for the entire series
    public bool ClosedPositions{get;set;}          // inidcates if any positions closed on this date
    public ModelPerformanceItem()
    {
    }
    public static String Header()
    {
      StringBuilder sb=new StringBuilder();
      sb.Append("Date,Exposure,MarketValue,GainLossDOD,GainLoss,CumulativeGainLoss,R,OnePlusR,CumProd,CumProdMinusOne,ClosedPositions");
      return sb.ToString();
    }
    public override String ToString()
    {
      StringBuilder sb=new StringBuilder();
      sb.Append(Utility.AddQuotes(Utility.DateTimeToStringMMSDDSYYYY(Date))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(Exposure))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(MarketValue))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(GainLossDOD))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(GainLoss))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(CumulativeGainLoss))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatPercent(R,2))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatNumber(OnePlusR,2))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatNumber(CumProd,2))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatPercent(CumProdMinusOne,3))).Append(",");
      sb.Append(Utility.AddQuotes(ClosedPositions.ToString()));
      return sb.ToString();
    }
  }
}
