using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Utils;
using MarketData.Numerical;

namespace MarketData.Numerical
{
  public class SharpeRatioGenerator
  {
    private SharpeRatioGenerator()
    {
    }
    public static double GenerateSharpeRatio(String symbol, DateTime startDate, int months = 12)
    {
      try
      {
        DateGenerator dateGenerator = new DateGenerator();
        Prices prices = Prices.GetMonthlyPrices(symbol, startDate, months);
        if (null == prices || 0 == prices.Count) return double.NaN;
        double riskFreeRate = YieldCurveDA.GetRiskFreeRate(dateGenerator.GetCurrMonthStart(prices[0].Date)) / 100.00;
        float[] returns = prices.GetReturns();
        double averageReturn = Numerics.Mean(ref returns);
        double riskPremium = averageReturn - riskFreeRate;
        double volatility = Numerics.Volatility(ref returns);
        double sharpeRatio = (averageReturn - riskFreeRate) / volatility;
        return sharpeRatio;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
        return double.NaN;
      }
    }
    public static PortfolioHoldingWithSharpeRatio GenerateSharpeRatio(PortfolioHoldingWithSharpeRatio portfolioHoldingWithSharpeRatio, DateTime startDate, int months = 12)
    {
      try
      {
        DateGenerator dateGenerator = new DateGenerator();
        Prices prices = Prices.GetMonthlyPrices(portfolioHoldingWithSharpeRatio.Symbol, startDate, months);
        if (null == prices || 0 == prices.Count)
        {
          portfolioHoldingWithSharpeRatio.SharpeRatio = double.NaN;
          portfolioHoldingWithSharpeRatio.AverageReturn = double.NaN;
          portfolioHoldingWithSharpeRatio.RiskPremium = double.NaN;
          portfolioHoldingWithSharpeRatio.Volatility = double.NaN;
          return portfolioHoldingWithSharpeRatio;
        }
        double riskFreeRate = YieldCurveDA.GetRiskFreeRate(dateGenerator.GetCurrMonthStart(prices[0].Date)) / 100.00;
        float[] returns = prices.GetReturns();
        double averageReturn = Numerics.Mean(ref returns);
        double riskPremium = averageReturn - riskFreeRate;
        double volatility = Numerics.Volatility(ref returns);
        double sharpeRatio = (averageReturn - riskFreeRate) / volatility;
        portfolioHoldingWithSharpeRatio.SharpeRatio = sharpeRatio;
        portfolioHoldingWithSharpeRatio.AverageReturn = averageReturn;
        portfolioHoldingWithSharpeRatio.RiskPremium = riskPremium;
        portfolioHoldingWithSharpeRatio.Volatility = volatility;
        return portfolioHoldingWithSharpeRatio;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
        portfolioHoldingWithSharpeRatio.SharpeRatio = double.NaN;
        portfolioHoldingWithSharpeRatio.AverageReturn = double.NaN;
        portfolioHoldingWithSharpeRatio.RiskPremium = double.NaN;
        portfolioHoldingWithSharpeRatio.Volatility = double.NaN;
        return portfolioHoldingWithSharpeRatio;
      }
    }
  }
}
