using MarketData.Generator.CMTrend;
using MarketData.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MarketData
{
  /// <summary>
  /// This model is based on Mark Minervini 
  /// </summary>
  public static class CMTrendHelper
  {
    /// <summary>
    /// CMTSESSION /SESSIONFILE:{pathfilename}  
    /// </summary>
    public static void HandleCMTSession(CommandArgs commandArgs)
    {
      if (!commandArgs.Has("SESSIONFILE")) {MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Missing SESSIONFILE"));return;}
      CMTTrendModel trendModel=new CMTTrendModel();
      trendModel.DisplaySession(commandArgs.Coalesce<String>("SESSIONFILE"));
    }

    /// <summary>
    /// RUNCMTREND  /MODE:DAILY|BACKTEST|RUNTRENDTEMPLATE|ENTRYTEST /SYMBOL:{for mode ANALYZE,ENTRYTEST} /TRADEDATE:{for mode DAILY,RUNTRENDTEMPLATE) /STARTDATE:(for mode BACKTEST,ENTRYTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: /MAXOPENPOSITIONS: /MAXDAILYPOSITIONS: Runs Mark Minervini trend
    /// VALID ARGUMENTS FOR /MODE:BACKTEST ARE /SELLATENDOFSIMULATION: /STARTDATE: /ENDDATE: /SESSIONFILE: /MAXDAILYPOSITIONS: /MAXOPENPOSITIONS: /BENCHMARKMOVINGAVERAGEDAYS: /BENCHMARKMOVINGAVERAGEHORIZON
    /// VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /POSITIONRISKPERCENTDECIMAL: /ENTRYTYPE:OverExtended,MVP,PriceTrend,VolumeTrend,RVOL /USEPROFITMAXIMIZATION:{TRUE|FALSE} /USEPROFITMAXIMIZATIONEXPRESSION:{string}
    /// VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /POSITIONRISKPERCENTDECIMAL: /ENTRYTYPE:OverExtended,MVP,PriceTrend,VolumeTrend,RVOL /USEPROFITMAXIMIZATION:TRUE /USEPROFITMAXIMIZATIONEXPRESSION:\"R_THRESSHOLD=4;MAX_ATR=3;MAX_R=10;FACTOR=MAX_ATR/MAX_R;MULTIPLIER=MAX_ATR;IF(RMultiple>R_THRESSHOLD){MULTIPLIER=FACTOR*RMultiple;}\"
    /// VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /USEPOSITIONSIZINGSTRATEGY:{TRUE|FALSE} /USEPOSITIONSIZINGSTRATEGYSTRATEGY:{TotalRisk:EqualWeight,Formula} /USEPOSITIONSIZINGSTRATEGYFORMULA:{Formula}
    /// VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /USETRADEONLYSECTORS:{TRUE|FALSE} /USETRADEONLYSECTORSSECTORS:Healthcare,Technology,Basic Materials,Consumer Defensive,Industrials
    /// /BENCHMARKMOVINGAVERAGEDAYS: (i.e.) 200, 100, 55
    /// /BENCHMARKMOVINGAVERAGEHORIZON: (i.e.) 5
    /// </summary>
    /// <param name="commandArgs"></param>
    public static void HandleRunCMTrend(CommandArgs commandArgs)
    {
      String mode;

      if(!commandArgs.Has("MODE"))
      {
        if(!commandArgs.Has("MODE")) MDTrace.WriteLine(LogLevel.DEBUG,"MODE is a required paramater.");
        MDTrace.WriteLine(LogLevel.DEBUG,"RUNMMTREND  /MODE:DAILY|BACKTEST|RUNTRENDTEMPLATE|ANALYZE|DISPLAY|CLOSEPOSITION /SELLDATE:{CLOSEPOSITION}  /PRICE:{CLOSEPOSITION} /SYMBOL:{for mode ANALYZE,CLOSEPOSITION} /TRADEDATE:{for mode DAILY,RUNTRENDTEMPLATE,ANALYZE,CLOSEPOSITION) /STARTDATE:(for mode BACKTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: MAXOPENPOSITIONS: /MAXDAILYPOSITIONS: Runs Mark Minervini trend");
        return;
      }
      mode=commandArgs.Get<String>("MODE");
      if("ENTRYTEST".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("SYMBOL")||!commandArgs.Has("STARTDATE"))
        {
          if(!commandArgs.Contains("SYMBOL")) MDTrace.WriteLine(LogLevel.DEBUG,"SYMBOL is a required parameter when MODE=ENTRYTEST");
          if(!commandArgs.Contains("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"STARTDATE is a required parameter when MODE=ENTRYTEST");
          return;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.EntryTest(commandArgs.Get<String>("SYMBOL"),commandArgs.Get<DateTime>("STARTDATE"));
      }
      else if("CLOSEPOSITION".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("PURCHASEDATE,SYMBOL,SESSIONFILE,PRICE,SELLDATE"))
        {
          if(!commandArgs.Contains("PURCHASEDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"PURCHASEDATE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SYMBOL")) MDTrace.WriteLine(LogLevel.DEBUG,"SYMBOL is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("PRICE")) MDTrace.WriteLine(LogLevel.DEBUG,"PRICE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SELLDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"SELLDATE is a required parameter when MODE=CLOSEPOSITION");
          return;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.ClosePosition(commandArgs.Get<String>("SYMBOL"),commandArgs.Get<DateTime>("PURCHASEDATE"),commandArgs.Get<DateTime>("SELLDATE"),commandArgs.Get<double>("PRICE"),commandArgs.Get<String>("SESSIONFILE"));
      }
      else if("DAILY".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("TRADEDATE,SESSIONFILE"))
        {
          if(!commandArgs.Contains("TRADEDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"TRADEDATE is a required parameter when MODE=DAILY");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter when MODE=DAILY");
          return;
        }
        if(commandArgs.Contains("INITIALCASH")) cmtParams.InitialCash=commandArgs.Get<double>("INITIALCASH");
        if(commandArgs.Contains("MAXDAILYPOSITIONS")) cmtParams.MaxDailyPositions=commandArgs.Get<int>("MAXDAILYPOSITIONS");
        if(commandArgs.Contains("MAXOPENPOSITIONS")) cmtParams.MaxOpenPositions=commandArgs.Get<int>("MAXOPENPOSITIONS");

        if(commandArgs.Has("ONLYTRADESYMBOLS")) cmtParams.OnlyTradeSymbols=commandArgs.Get<String>("ONLYTRADESYMBOLS");

        if(commandArgs.Contains("POSITIONRISKPERCENTDECIMAL"))
        {
          cmtParams.PositionRiskPercentDecimal=commandArgs.Get<double>("POSITIONRISKPERCENTDECIMAL");
        }

        if(commandArgs.Contains("ENTRYTYPE"))
        {
          List<String> entryTypes=Utility.ToList(commandArgs.Get<String>("ENTRYTYPE"));
          List<String> constraints=new List<String> { "OVEREXTENDED","MVP","NARROWRANGE","MACD","PRICETREND","VOLUMETREND" };
          bool results=entryTypes.All(i => constraints.ContainsIgnoreCase(i));
          if(!results)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,"ENTRYTYPE must consist of one or more OVEREXTENDED, MVP, NarrowRange, MACD, PriceTrend, VolumeTrend");
            return;
          }
          cmtParams.EntryType=commandArgs.Get<String>("ENTRYTYPE");
        }
        CMTTrendModel trendModel=new CMTTrendModel();

				if(commandArgs.Contains("USETRADEONLYSECTORS"))
				{
					cmtParams.UseTradeOnlySectors=commandArgs.Get<bool>("USETRADEONLYSECTORS");
					if(cmtParams.UseTradeOnlySectors)
					{
						cmtParams.UseTradeOnlySectorsSectors=commandArgs.Get<String>("USETRADEONLYSECTORSSECTORS");
					}
				}
        CMTTrendModelResult result=trendModel.RunDaily(commandArgs.Get<DateTime>("TRADEDATE"),commandArgs.Get<String>("SESSIONFILE"),cmtParams);
      }
      else if("BACKTEST".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
				bool sellAtEndOfSimulation=true;
        if(!commandArgs.Has("STARTDATE,ENDDATE,SESSIONFILE"))
        {
          if(!commandArgs.Contains("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"STARTDATE is a required parameter");
          if(!commandArgs.Contains("ENDDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"ENDDATE is a required parameter");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter");
          return;
        } 

        CMTTrendModel trendModel=new CMTTrendModel();

				if(commandArgs.Contains("USETRADEONLYSECTORS"))
				{
					cmtParams.UseTradeOnlySectors=commandArgs.Get<bool>("USETRADEONLYSECTORS");
					if(cmtParams.UseTradeOnlySectors)
					{
						cmtParams.UseTradeOnlySectorsSectors=commandArgs.Get<String>("USETRADEONLYSECTORSSECTORS");
					}
				}

        if(commandArgs.Contains("USEPROFITMAXIMIZATION"))
        {
          cmtParams.UseProfitMaximization=commandArgs.Get<bool>("USEPROFITMAXIMIZATION");
          if(commandArgs.Contains("USEPROFITMAXIMIZATIONEXPRESSION"))
          {
            cmtParams.UseProfitMaximizationExpression=commandArgs.Get<String>("USEPROFITMAXIMIZATIONEXPRESSION");
          }
        }

        if(commandArgs.Contains("MAXDAILYPOSITIONS")) cmtParams.MaxDailyPositions=commandArgs.Get<int>("MAXDAILYPOSITIONS");
        if(commandArgs.Contains("MAXOPENPOSITIONS")) cmtParams.MaxOpenPositions=commandArgs.Get<int>("MAXOPENPOSITIONS");
        if(commandArgs.Contains("BENCHMARKMOVINGAVERAGEDAYS")) cmtParams.BenchmarkMovingAverageDays=commandArgs.Get<int>("BENCHMARKMOVINGAVERAGEDAYS");
        if(commandArgs.Contains("BENCHMARKMOVINGAVERAGEHORIZON")) cmtParams.BenchmarkMovingAverageHorizon=commandArgs.Get<int>("BENCHMARKMOVINGAVERAGEHORIZON");

        if(commandArgs.Has("ONLYTRADESYMBOLS")) cmtParams.OnlyTradeSymbols=commandArgs.Get<String>("ONLYTRADESYMBOLS");

        if(commandArgs.Contains("POSITIONRISKPERCENTDECIMAL"))
        {
          cmtParams.PositionRiskPercentDecimal=commandArgs.Get<double>("POSITIONRISKPERCENTDECIMAL");
        }

        if(commandArgs.Contains("ENTRYTYPE"))
        {
          List<String> entryTypes=Utility.ToList(commandArgs.Get<String>("ENTRYTYPE"));
          List<String> constraints=new List<String> { "OVEREXTENDED","MVP","NARROWRANGE","MACD","PRICETREND","VOLUMETREND" };
          bool results=entryTypes.All(i => constraints.ContainsIgnoreCase(i));
          if(!results)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,"ENTRYTYPE must consist of one or more OVEREXTENDED, MVP, NarrowRange, MACD, PriceTrend, VolumeTrend");
            return;
          }
          cmtParams.EntryType=commandArgs.Get<String>("ENTRYTYPE");
        }
				if(commandArgs.Contains("SELLATENDOFSIMULATION"))
				{
				  sellAtEndOfSimulation=commandArgs.Get<bool>("SELLATENDOFSIMULATION");
				}
        CMTTrendModelResult result=trendModel.RunBacktestMode(commandArgs.Get<DateTime>("STARTDATE"),commandArgs.Get<DateTime>("ENDDATE"),sellAtEndOfSimulation,commandArgs.Get<String>("SESSIONFILE"),cmtParams);
      }
      else if("DISPLAY".Equals(mode))
      {
        if(!commandArgs.Contains("SESSIONFILE")) { MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter"); return; }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.DisplaySession(commandArgs.Get<String>("SESSIONFILE"));
      }
      else if("RUNTRENDTEMPLATE".Equals(mode))
      {
        if(!commandArgs.Contains("TRADEDATE"))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"TRADEDATE is a required parameter when MODE=DAILY");
          return;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.RunTrendTemplate(commandArgs.Get<DateTime>("TRADEDATE"));
      }
      else
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"RUNCMTREND  /MODE:DAILY|BACKTEST /TRADEDATE:{for mode DAILY) /STARTDATE:(for mode BACKTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: /MAXPOSITIONS Runs Mark Minervini trend");
      }
      return;
    }
  }
}
