using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Threading.Tasks;
using Forms=System.Windows.Forms;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.IO;
using MarketData;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.Generator;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using System.Windows.Threading;
using MarketData.Generator.Momentum;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.Interface;
using Position = MarketData.Generator.Momentum.Position;

namespace TradeBlotter.ViewModels
{
  public class MomentumViewModel : WorkspaceViewModel
  {
// generic section
    private const String DISPLAY_NAME = "Momentum Model";
    private bool busyIndicator = false;
    private String busyContent=null;
    private String initialPath=null;
    private String pathFileName=null;

// momentum candidate section
    private String selectedDate = null;
    private DateTime selectableDateStart=Utility.Epoch;
    private DateTime selectableDateEnd=Utility.Epoch;
    private ObservableCollection<MomentumCandidate> momentumCandidates=new ObservableCollection<MomentumCandidate>();
    private MomentumCandidate selectedItem=null;
    private RelayCommand runCommand;
    private RelayCommand stochasticsCommand;
    private RelayCommand relativeStrengthCommand;
    private RelayCommand macdCommand;
    private RelayCommand bollingerBandCommand;
    private RelayCommand priceHistoryCommand;
    private RelayCommand stickerValuationCommand;
    private RelayCommand dcfValuationCommand;
    private RelayCommand dividendHistoryCommand;
    private RelayCommand analystRatingsCommand;
    private RelayCommand addToWatchListCommand;
    private RelayCommand removeFromWatchListCommand;
    private RelayCommand movingAverageCommand;
    private RelayCommand displayHistoricalCommand;
// session section
    private ModelStatistics modelStatistics=null;
    private NVPDictionary nvpDictionary=null;
    private ObservableCollection<String> nvpDictionaryKeys=null;
    private MGConfiguration configuration=null;
    private MGSessionParams sessionParams;
    private String selectedParameter=null;
    private MGPositionModelCollection positions=null;
    private MGPositionModel selectedPosition=null;
    private RelayCommand loadFileCommand;
    private RelayCommand reloadCommand;
    private RelayCommand monitorCommand;
    private ObservableCollection<String> monitorIntervals;
    private String selectedMonitorInterval;
    private bool monitorRunning=false;
    private DispatcherTimer dispatcherTimer = new DispatcherTimer(); 
    private RelayCommand stochasticsCommandPosition;
    private RelayCommand relativeStrengthCommandPosition;
    private RelayCommand macdCommandPosition;
    private RelayCommand bollingerBandCommandPosition;
    private RelayCommand priceHistoryCommandPosition;
    private RelayCommand stickerValuationCommandPosition;
    private RelayCommand dcfValuationCommandPosition;
    private RelayCommand dividendHistoryCommandPosition;
    private RelayCommand analystRatingsCommandPosition;
    private RelayCommand addToWatchListCommandPosition;
    private RelayCommand removeFromWatchListCommandPosition;
    private RelayCommand movingAverageCommandPosition;
    private RelayCommand displayHistoricalCommandPosition;
    private RelayCommand displayHeadlinesCommandPosition;
    private RelayCommand closePositionCommandPosition;
    private RelayCommand editPositionCommandPosition;
// chart plotter
    private bool showAsGainLoss=true;
    private bool isLegendVisible=false;
    private RelayCommand toggleReturnOrPercentCommand=null;  
    private ModelPerformanceSeries modelPerformanceSeries=null;

    public MomentumViewModel(bool loadedFromParams=false)
    {
      PropertyChanged += OnMomentumViewModelPropertyChanged;
      base.DisplayName = DISPLAY_NAME;
      monitorIntervals=new ObservableCollection<String>();
      monitorIntervals.Add("30");
      monitorIntervals.Add("60");
      monitorIntervals.Add("90");
      monitorIntervals.Add("120");
      selectedMonitorInterval=monitorIntervals[0];
      DateTime earliestPricingDate=PricingDA.GetEarliestDate();
      earliestPricingDate+=new TimeSpan(252,0,0,0);
      selectableDateStart=earliestPricingDate;
      selectableDateEnd=PricingDA.GetLatestDate();
      selectedDate=selectableDateEnd.ToShortDateString();
      configuration=new MGConfiguration();
      NVPCollection nvpCollection=configuration.ToNVPCollection();
      nvpDictionary=nvpCollection.ToDictionary();
      List<String> dictionaryKeys=new List<String>(nvpDictionary.Keys);
      dictionaryKeys.Sort();
      nvpDictionaryKeys=new ObservableCollection<String>(dictionaryKeys);
      selectedParameter=nvpDictionaryKeys[0];
      dispatcherTimer.Tick += DispatcherTimerTick;
      dispatcherTimer.Interval = new TimeSpan(0, 0, int.Parse(selectedMonitorInterval));
      base.OnPropertyChanged("MonitorIntervals");
      base.OnPropertyChanged("SelectedMonitorInterval");
      base.OnPropertyChanged("Parameters");
      base.OnPropertyChanged("SelectedParameter");
      base.OnPropertyChanged("ParameterValue");
    }
    protected override void OnDispose()
    {
      StopMonitor();
      base.OnDispose();
    }
// ******************************************************************************************** P E R S I S T E N C E ********************************************************************************************
    public override bool CanPersist()
    {
      return true;
    }
    public override SaveParameters GetSaveParameters()
    {
      SaveParameters saveParams = new SaveParameters();
      if (null == pathFileName) return null;
      saveParams.Add(new KeyValuePair<String, String>("Type",GetType().Namespace+"."+GetType().Name));
      saveParams.Add(new KeyValuePair<String, String>("PathFileName", pathFileName));
      return saveParams;    
    }
    public override void SetSaveParameters(SaveParameters saveParameters)
    {
      try
      {
        pathFileName = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("PathFileName") select item).FirstOrDefault().Value;
        if(!LoadSessionFile())pathFileName=null;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
      }
    }
// **************************************************************************************************************************************************************************
    public bool BusyIndicator
    {
      get { return busyIndicator; }
      set
      {
        busyIndicator = value;
        base.OnPropertyChanged("BusyIndicator");
      }
    }
    public String BusyContent
    {
      get{return busyContent;}
      set{busyContent=value;base.OnPropertyChanged("BusyContent");}
    }
// **************************************************************************************************************************************************************************
    public ObservableCollection<MenuItem> CandidateMenuItems
    {
      get
      {
        ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
        collection.Add(new MenuItem() { Text = "Display Bollinger Band", MenuItemClickedCommand = DisplayBollingerBand, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Dividend History", MenuItemClickedCommand = DisplayDividendHistory, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Sticker Valuation", MenuItemClickedCommand = DisplayStickerValuation, StaysOpenOnClick = false });
  			collection.Add(new MenuItem() { Text = "Display Historical", MenuItemClickedCommand = DisplayHistorical, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Stochastics", MenuItemClickedCommand = DisplayStochastics, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Relative Strength", MenuItemClickedCommand=DisplayRelativeStrength, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display MACD", MenuItemClickedCommand = DisplayMACD, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Price History", MenuItemClickedCommand = DisplayPriceHistory, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAverage, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Analyst Ratings", MenuItemClickedCommand = DisplayAnalystRatings, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuation, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchList, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchList, StaysOpenOnClick = false });
        return collection;
      }
    }
    public ObservableCollection<MenuItem> PositionsMenuItems
    {
      get
      {
        ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
        collection.Add(new MenuItem() { Text = "Display Bollinger Band", MenuItemClickedCommand = DisplayBollingerBandPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Headlines", MenuItemClickedCommand = DisplayHeadlinesPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Dividend History", MenuItemClickedCommand = DisplayDividendHistoryPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Sticker Valuation", MenuItemClickedCommand = DisplayStickerValuationPosition, StaysOpenOnClick = false });
  			collection.Add(new MenuItem() { Text = "Display Historical", MenuItemClickedCommand = DisplayHistoricalPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Stochastics", MenuItemClickedCommand = DisplayStochasticsPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Relative Strength", MenuItemClickedCommand=DisplayRelativeStrengthPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display MACD", MenuItemClickedCommand = DisplayMACDPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Price History", MenuItemClickedCommand = DisplayPriceHistoryPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAveragePosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display Analyst Ratings", MenuItemClickedCommand = DisplayAnalystRatingsPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuationPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchListPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchListPosition, StaysOpenOnClick = false });
        collection.Add(new MenuItem() { Text = "Close Position...",MenuItemClickedCommand = ClosePosition,StaysOpenOnClick=false });
        collection.Add(new MenuItem() { Text = "Edit Position...",MenuItemClickedCommand = EditPosition,StaysOpenOnClick=false });
        return collection;
      }
    }
    private void OnMomentumViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
    {
    }
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
    public override String DisplayName
    {
      get
      {
        if(null==pathFileName)return "Momentum Model";
        String fileName=Path.GetFileName(pathFileName);
        fileName=Utility.BetweenString(fileName,null,".");
        return "Momentum Model ("+fileName+")";      
      }
    }
    public override String Title
    {
      get 
      {
        return DisplayName;
      }
    }
    public DateTime SelectableDateStart
    {
      get{return selectableDateStart;}
      set{selectableDateStart=value;}
    }
    public DateTime SelectableDateEnd
    {
      get{return selectableDateEnd;}
      set{selectableDateEnd=value;}
    }
// ********************************************************************************************************************************************************************************
    private void Run()
    {
      try
      {
        if(null==selectedDate)return;
        BusyIndicator = true;
        BusyContent="Running Momentum...";
        Task workerTask = Task.Factory.StartNew(() =>
        {
          MGConfiguration localConfiguration=new MGConfiguration();
          localConfiguration.MaxPositions = int.Parse(nvpDictionary["MaxPositions"].Value);
          localConfiguration.HoldingPeriod = int.Parse(nvpDictionary["HoldingPeriod"].Value);
          MomentumCandidates candidates = MomentumGenerator.GenerateMomentumWithFallback(Utility.ParseDate(selectedDate), configuration == null ? localConfiguration : configuration);
          momentumCandidates=new ObservableCollection<MomentumCandidate>();
          foreach(MomentumCandidate momentumCandidate in candidates)momentumCandidates.Add(momentumCandidate);
        });
        workerTask.ContinueWith((continuation)=>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("AllItems");
          base.OnPropertyChanged("Title");
        });
      }
      finally
      {
      }
    }
// ******************************************************************************************************************************************************
// *************************************************************** T O O L T I P   C A L L O U T S ******************************************************
// *******************************************************************************************************************************************************
// Candidate
      public String CompanyDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedItem.Symbol);
          if(null==companyProfile || null==companyProfile.Description || "".Equals(companyProfile.Description))return "No description found.";
          StringBuilder sb=new StringBuilder();
          sb.Append(companyProfile.Sector).Append("/").Append(companyProfile.Industry).Append("\n").Append(companyProfile.Description);
          return sb.ToString();
        }
      }
      public String VelocityDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Velocity is the percentage range of the current price within the price history.";
        }
      }
      public String BetaDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "A beta of less than 1 means that the security is theoretically less volatile than the market. A beta of greater than 1 indicates that the security's price is theoretically more volatile than the market. For example, if a stock's beta is 1.2, it's theoretically 20% more volatile than the market.";
        }
      }
// Position
      public String CompanyDescriptionSelectedPosition
      {
        get
        {
          if(null== selectedPosition || null==selectedPosition.Symbol)return "No row selected.";
          CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedPosition.Symbol);
          if(null==companyProfile || null==companyProfile.Description || "".Equals(companyProfile.Description))return "No description found.";
          StringBuilder sb = new StringBuilder();
          sb.Append(companyProfile.Sector).Append("/").Append(companyProfile.Industry).Append("\n").Append(companyProfile.Description);
          return sb.ToString();
        }
      }
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
    public MomentumCandidate SelectedItem
    {
      get
      { 
        return selectedItem; 
      }
      set
      {
        if (value == selectedItem) return;
        selectedItem = value;
        base.OnPropertyChanged("SelectedItem");
      }
    }
    public MGPositionModel SelectedPosition
    {
      get{return selectedPosition;}
      set{selectedPosition=value;base.OnPropertyChanged("SelectedPosition");}
    }
    public String SelectedDate
    {
      get { return selectedDate; }
      set
      {
        selectedDate = value;
        base.OnPropertyChanged("SelectedDate");
      }
    }
    public ObservableCollection<MomentumCandidate> AllItems
    {
      get{return momentumCandidates;}
    }
    public MGPositionModelCollection AllPositions
    {
      get{return positions;}
    }
    public ObservableCollection<String> Parameters
    {
      get{return nvpDictionaryKeys;}
    }
    public ObservableCollection<String> MonitorIntervals
    {
      get{return monitorIntervals;}
    }
    public bool CanMonitor
    {
      get{return IsTradeFileLoaded;}
    }
    public String MonitorStatus
    {
      get{return monitorRunning?"Stop Monitor":"Start Monitor";}
    }
    public String SelectedMonitorInterval
    {
      get{return selectedMonitorInterval;}
      set{selectedMonitorInterval=value;base.OnPropertyChanged("SelectedMonitorInterval");}
    }
    public String SelectedParameter
    {
      get{return selectedParameter;}
      set{selectedParameter=value;base.OnPropertyChanged("SelectedParameter");base.OnPropertyChanged("ParameterValue");}
    }
    public String ParameterValue
    {
      get
      {
        if(null==nvpDictionary||null==nvpDictionaryKeys||null==selectedParameter)return null;
        return nvpDictionary[selectedParameter].Value;
      }
    }
    public String CashBalance
    {
      get
      {
        if(null==sessionParams) return "";
        return Utility.FormatCurrency(sessionParams.CashBalance);
      }
    }
    public String NonTradeableCash
    {
      get
      {
        if(null==sessionParams) return "";
        return Utility.FormatCurrency(sessionParams.NonTradeableCash);
      }
    }
    public String ModelExpectation
    {
      get
      {
        if(null==modelStatistics) return "";
        return Utility.FormatNumber(modelStatistics.Expectancy,2);
      }
    }
    public Brush ExpectationColor
    {
      get
      {
        if(null==modelStatistics) return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
        if(modelStatistics.Expectancy>0.00) return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
        return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
      }
    }
    public String ExpectationDescription
    {
      get
      {
        if(null==modelStatistics) return "";
        StringBuilder sb=new StringBuilder();
        sb.Append("Expectancy is (percentage of winning trades * average gain) / (percentage of losing trades * average loss).").Append("\n");
        sb.Append("Total Trades : ").Append(modelStatistics.TotalTrades).Append("\n");
        sb.Append("Winning Trades : ").Append(modelStatistics.WinningTrades).Append("\n");
        sb.Append("Losing Trades : ").Append(modelStatistics.LosingTrades).Append("\n");
        sb.Append("Winning Trades : ").Append(Utility.FormatNumber(modelStatistics.WinningTradesPercent,2)).Append("%").Append("\n");
        sb.Append("Losing Trades : ").Append(Utility.FormatNumber(modelStatistics.LosingTradesPercent,2)).Append("%").Append("\n");
        sb.Append("Average Winning Trade Gain : ").Append(Utility.FormatNumber(modelStatistics.AverageWinningTradePercentGain,2)).Append("%").Append("\n");
        sb.Append("Average Losing Trade Loss : ").Append(Utility.FormatNumber(modelStatistics.AverageLosingTradePercentLoss,2)).Append("%").Append("\n");
        sb.Append("Expectancy : ").Append(Utility.FormatNumber(modelStatistics.Expectancy,2)).Append("\n");
        sb.Append("\n");
        sb.Append("Maintain a positive Expectancy and you're a winner.");
        sb.Append("\n");
        sb.Append("The calculations are based on closed positions.");
        return sb.ToString();
      }
    }    
// *************************************************************************************************************************************************************
// *********************************************************************** I C O M M A N D  ********************************************************************
// *************************************************************************************************************************************************************
    public ICommand DisplayHistorical
    {
      get
      {
        if (displayHistoricalCommand == null)
        {
          displayHistoricalCommand = new RelayCommand(param => 
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HistoricalViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return displayHistoricalCommand;
      }
    }
    public ICommand RunCommand
    {
      get
      {
        if (runCommand == null)
        {
          runCommand = new RelayCommand(param => this.Run(), param => {return true;});
        }
        return runCommand;
      }
    }
    public ICommand DisplayMovingAverage
    {
      get
      {
        if (movingAverageCommand == null)
        {
          movingAverageCommand = new RelayCommand(param => this.DisplayMovingAverageCommand(selectedItem.Symbol), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }                      
        return movingAverageCommand;
      }
    }
    public ICommand DisplayAnalystRatings
    {
      get
      {
        if (analystRatingsCommand == null)
        {
          analystRatingsCommand = new RelayCommand(param => this.DisplayAnalystRatingsCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return analystRatingsCommand;
      }
    }
    public ICommand DisplayMACD
    {
      get
      {
        if (macdCommand == null)
        {
          macdCommand = new RelayCommand(param => this.DisplayMACDCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return macdCommand;
      }
    }
    public ICommand DisplayStochastics
    {
      get
      {
        if (stochasticsCommand == null)
        {
          stochasticsCommand = new RelayCommand(param => this.DisplayStochasticsCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return stochasticsCommand;
      }
    }
    public ICommand DisplayRelativeStrength
    {
      get
      {
        if (relativeStrengthCommand == null)
        {
          relativeStrengthCommand = new RelayCommand(param => this.DisplayRelativeStrengthCommand(), param => { return null != selectedItem && null!=selectedItem.Symbol; });
        }
        return relativeStrengthCommand;
      }
    }
    public ICommand DisplayStickerValuation
    {
      get
      {
        if (null == stickerValuationCommand)
        {
          stickerValuationCommand = new RelayCommand(param =>
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StickerPriceViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
        }
        return stickerValuationCommand;
      }
    }
    public ICommand DisplayDCFValuation
    {
      get
      {
        if (null == dcfValuationCommand)
        {
          dcfValuationCommand = new RelayCommand(param =>
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DCFValuationViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
        }
        return dcfValuationCommand;
      }
    }
    public ICommand DisplayPriceHistory
    {
      get
      {
        if (priceHistoryCommand == null)
        {
          priceHistoryCommand = new RelayCommand(param => this.DisplayPriceHistoryCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return priceHistoryCommand;
      }
    }
    public ICommand DisplayDividendHistory
    {
      get
      {
        if (dividendHistoryCommand == null)
        {
          dividendHistoryCommand = new RelayCommand(param => 
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendHistoryViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return dividendHistoryCommand;
      }
    }
    public void DisplayPriceHistoryCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.PricingViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public ICommand DisplayBollingerBand
    {
      get
      {
        if (bollingerBandCommand == null)
        {
          bollingerBandCommand = new RelayCommand(param => this.DisplayBollingerBandCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
        }
        return bollingerBandCommand;
      }
    }
    public ICommand AddToWatchList
    {
      get
      {
        if (addToWatchListCommand == null)
        {
          addToWatchListCommand = new RelayCommand(param => this.AddToWatchListCommand(selectedItem.Symbol),
            param => 
              {
                if(null==selectedItem || null==selectedItem.Symbol)return false;
                if (WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
                return true;
              });
        }
        return addToWatchListCommand;
      }
    }
    public ICommand RemoveFromWatchList
    {
      get
      {
        if (removeFromWatchListCommand == null)
        {
          removeFromWatchListCommand = new RelayCommand(param => this.RemoveFromWatchListCommand(selectedItem.Symbol),
            param => 
              {
                if(null==selectedItem || null==selectedItem.Symbol)return false;
                if (!WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
                return true;
              });
        }
        return removeFromWatchListCommand;
      }
    }
// *************************************************************************************************************************************************************
// **************************************************************** I C O M M A N D  P O S I T I O N ***********************************************************
// *************************************************************************************************************************************************************
    public ICommand DisplayHeadlinesPosition
    {
      get
      {
        if (null == displayHeadlinesCommandPosition)
        {
          displayHeadlinesCommandPosition = new RelayCommand(param =>
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HeadlinesViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,Valuations");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
        }
        return displayHeadlinesCommandPosition;
      }
    }
    public ICommand DisplayHistoricalPosition
    {
      get
      {
        if (displayHistoricalCommandPosition == null)
        {
          displayHistoricalCommandPosition = new RelayCommand(param => 
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HistoricalViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return displayHistoricalCommandPosition;
      }
    }
    public ICommand DisplayAnalystRatingsPosition
    {
      get
      {
        if (analystRatingsCommandPosition == null)
        {
          analystRatingsCommandPosition = new RelayCommand(param => this.DisplayAnalystRatingsCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return analystRatingsCommandPosition;
      }
    }
    public ICommand DisplayMovingAveragePosition
    {
      get
      {
        if (movingAverageCommandPosition == null)
        {
          movingAverageCommandPosition = new RelayCommand(param => this.DisplayMovingAverageCommand(selectedPosition.Symbol), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }                      
        return movingAverageCommandPosition;
      }
    }
    public ICommand DisplayMACDPosition
    {
      get
      {
        if (macdCommandPosition == null)
        {
          macdCommandPosition = new RelayCommand(param => this.DisplayMACDCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return macdCommandPosition;
      }
    }
    public ICommand DisplayStochasticsPosition
    {
      get
      {
        if (stochasticsCommandPosition == null)
        {
          stochasticsCommandPosition = new RelayCommand(param => this.DisplayStochasticsCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return stochasticsCommandPosition;
      }
    }
    public ICommand DisplayRelativeStrengthPosition
    {
      get
      {
        if (relativeStrengthCommandPosition == null)
        {
          relativeStrengthCommandPosition = new RelayCommand(param => this.DisplayRelativeStrengthCommandPosition(),param => { return null != selectedPosition && null!= selectedPosition.Symbol; });
        }
        return relativeStrengthCommandPosition;
      }
    }
    public ICommand DisplayStickerValuationPosition
    {
      get
      {
        if (null == stickerValuationCommandPosition)
        {
          stickerValuationCommandPosition= new RelayCommand(param =>
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StickerPriceViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
        }
        return stickerValuationCommandPosition;
      }
    }
    public ICommand DisplayDCFValuationPosition
    {
      get
      {
        if (null == dcfValuationCommandPosition)
        {
          dcfValuationCommandPosition = new RelayCommand(param =>
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DCFValuationViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
        }
        return dcfValuationCommandPosition;
      }
    }
    public ICommand DisplayPriceHistoryPosition
    {
      get
      {
        if (priceHistoryCommandPosition == null)
        {
          priceHistoryCommandPosition = new RelayCommand(param => this.DisplayPriceHistoryCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return priceHistoryCommandPosition;
      }
    }
    public ICommand DisplayDividendHistoryPosition
    {
      get
      {
        if (dividendHistoryCommandPosition == null)
        {
          dividendHistoryCommandPosition = new RelayCommand(param => 
          {
            SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendHistoryViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
            saveParams.Referer=this;
            WorkspaceInstantiator.Invoke(saveParams);
          }, param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return dividendHistoryCommandPosition;
      }
    }
    public ICommand DisplayBollingerBandPosition
    {
      get
      {
        if (bollingerBandCommandPosition == null)
        {
          bollingerBandCommandPosition = new RelayCommand(param => this.DisplayBollingerBandCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
        }
        return bollingerBandCommandPosition;
      }
    }
    public ICommand AddToWatchListPosition
    {
      get
      {
        if (addToWatchListCommandPosition == null)
        {
          addToWatchListCommandPosition = new RelayCommand(param => this.AddToWatchListCommand(selectedPosition.Symbol),
            param => 
              {
                if(null==selectedPosition || null==selectedPosition.Symbol)return false;
                if (WatchListDA.IsInWatchList(selectedPosition.Symbol)) return false;
                return true;
              });

        }
        return addToWatchListCommandPosition;
      }
    }
    public ICommand RemoveFromWatchListPosition
    {
      get
      {
        if (removeFromWatchListCommandPosition == null)
        {
          removeFromWatchListCommandPosition = new RelayCommand(param => this.RemoveFromWatchListCommand(selectedPosition.Symbol), param => 
              {
                if(null==selectedPosition || null==selectedPosition.Symbol)return false;
                if (!WatchListDA.IsInWatchList(selectedPosition.Symbol)) return false;
                return true;
              });
        }
        return removeFromWatchListCommandPosition;
      }
    }

    public ICommand ClosePosition
    {
      get
      {
        if(closePositionCommandPosition==null)
        {
          closePositionCommandPosition=new RelayCommand(param => this.ClosePositionCommand(selectedPosition),param =>
          {
            if(null==selectedPosition||null==selectedPosition.Symbol) return false;
            return true;
          });
        }
        return closePositionCommandPosition;
      }
    }
    public ICommand EditPosition
    {
      get
      {
        if(editPositionCommandPosition==null)
        {
          editPositionCommandPosition=new RelayCommand(param => this.EditPositionCommand(selectedPosition),param =>
          {
            if(null==selectedPosition||null==selectedPosition.Symbol||!Utility.IsEpoch(selectedPosition.SellDate)) return false;
            return true;
          });
        }
        return editPositionCommandPosition;
      }
    }
// *************************************************************************************************************************************************************
// ******************************************************************* I C O M M A N D   S E S S I O N *********************************************************
// *************************************************************************************************************************************************************
    public ICommand Reload
    {
      get
      {
        if(reloadCommand==null)
        {
          reloadCommand=new RelayCommand(param => this.ReloadCommand(),param => 
					{ 
					  return ReloadEnabled; 
					});
        }
        return reloadCommand;
      }
    }
		public bool ReloadEnabled
		{
		  get
			{
			  return !String.IsNullOrEmpty(pathFileName);
			}
		}
    public ICommand LoadFile
    {                                                                                                                       
      get
      {
        if (loadFileCommand == null)
        {
          loadFileCommand = new RelayCommand(param => this.LoadFileCommand(), param => { return true; });
        }
        return loadFileCommand;
      }
    }
    public ICommand Monitor
    {                                                                                                                       
      get
      {
        if (monitorCommand == null)
        {
          monitorCommand = new RelayCommand(param => this.MonitorCommand(), param => { return IsTradeFileLoaded; });
        }
        return monitorCommand;
      }
    }
    private bool IsTradeFileLoaded
    {
      get{return null==pathFileName?false:true;}
    }
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D  W O R K E R S  ********************************************************
// *************************************************************************************************************************************************************
    public void DisplayBollingerBandCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,360");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayAnalystRatingsCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayStochasticsCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StochasticsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayRelativeStrengthCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.RSIViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,60,SelectedRSIDayCount,3");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayMACDCommand()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MACDViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D  W O R K E R S  P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
    public void DisplayBollingerBandCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayAnalystRatingsCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayStochasticsCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StochasticsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayRelativeStrengthCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.RSIViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,60,SelectedRSIDayCount,3");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayMACDCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MACDViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void DisplayPriceHistoryCommandPosition()
    {
      SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.PricingViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
// ***************************************************************************************************************************************************************************
// ********************************************************************* G E N E R A L  W O R K E R S  ***********************************************************************
// ***************************************************************************************************************************************************************************
    public void DisplayMovingAverageCommand(String symbol)
    {
      SaveParameters saveParams=new SaveParameters();
      saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.MovingAverageViewModel"));
      saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", symbol));
      saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", Constants.CONST_ALL));
      saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", "360"));
      saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", "true"));
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }
    public void AddToWatchListCommand(String symbol)
    {
      if (WatchListDA.IsInWatchList(symbol))
      {
        System.Windows.MessageBox.Show("'"+symbol+"' is already in watchlist","Info", MessageBoxButton.OK,  MessageBoxImage.Information);
        return;
      }
      if (!WatchListDA.AddToWatchList(symbol))
      {
        System.Windows.MessageBox.Show("Error adding '"+symbol+"' to watchlist","Warning", MessageBoxButton.OK,  MessageBoxImage.Warning);
      }
      else
      {
        System.Windows.MessageBox.Show("Added '"+symbol+"'","Success", MessageBoxButton.OK,  MessageBoxImage.Information);
      }
    }
    public void RemoveFromWatchListCommand(String symbol)
    {
      if (!WatchListDA.IsInWatchList(symbol))
      {
        System.Windows.MessageBox.Show("'"+symbol+"' is not in watchlist","Info", MessageBoxButton.OK,  MessageBoxImage.Information);
        return;
      }
      if (!WatchListDA.RemoveFromWatchList(symbol))
      {
        System.Windows.MessageBox.Show("Error removing '"+symbol+"' from watchlist","Warning", MessageBoxButton.OK,  MessageBoxImage.Warning);
      }
      else
      {
        System.Windows.MessageBox.Show("Removed '"+symbol+"'","Success", MessageBoxButton.OK,  MessageBoxImage.Information);
      }
    }

    public void ClosePositionCommand(MGPositionModel selectedPosition)
    {
      Position clonedPosition=Position.Clone(selectedPosition.Position);
      IPurePosition changedPosition=ClosePositionDialogNoStop.Prompt("Close Position",clonedPosition);
      if(null==changedPosition) return;
      MomentumBacktest momentumModel = new MomentumBacktest();
      if (!momentumModel.ClosePosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.SellDate, changedPosition.CurrentPrice, pathFileName))
      {
        MessageBox.Show("Failed to close the position, check log for details.", "Close Position");
        return;
      }
      String strMessage = String.Format("Closed position for {0}, Purchase Date:{1}, Sell Date{2}, Current Price:{3}. Saved to {4}.  A backup was created.",
      changedPosition.Symbol, 
      changedPosition.PurchaseDate.ToShortDateString(), 
      changedPosition.SellDate.ToShortDateString(), 
      Utility.FormatCurrency(changedPosition.CurrentPrice), 
      pathFileName);
      MessageBox.Show(strMessage, "Close Position");
      LoadSessionFile();
    }

    public void EditPositionCommand(MGPositionModel selectedPosition)
    {
      Position clonedPosition=Position.Clone(selectedPosition.Position);
      IPurePosition changedPosition=EditPositionDialogNoStop.Prompt("Edit Position",clonedPosition);
      if(null==changedPosition) return;
      MomentumBacktest momentumModel = new MomentumBacktest();
      if (!momentumModel.EditPosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.PurchasePrice, pathFileName))
      {
        MessageBox.Show("Failed to edit the position, check log for details.", "Edit Position");
        return;
      }
      selectedPosition.PurchaseDate = changedPosition.PurchaseDate;
      selectedPosition.PurchasePrice = changedPosition.PurchasePrice;
      String strMessage = String.Format("Edited Position for {0} Purchase Date:{1} Purchase Price:{2}. A backup was created.",
        selectedPosition.Symbol,
        selectedPosition.PurchaseDate.ToShortDateString(),
        Utility.FormatCurrency(selectedPosition.PurchasePrice));
      MessageBox.Show(strMessage, "Edit Position");
      LoadSessionFile();
    }
// **************************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D  W O R K E R S  S E S S I O N ********************************************************
// ***************************************************************************************************************************************************************************
    public void MonitorCommand()
    {
      if(monitorRunning)StopMonitor();
      else StartMonitor();
    }

    private void StopMonitor()
    {
      if(!monitorRunning)return;
      dispatcherTimer.Stop();
      monitorRunning=false;
      base.OnPropertyChanged("MonitorStatus");
    }
    private void StartMonitor()
    {
      if(monitorRunning)return;
      dispatcherTimer.Start();
      monitorRunning=true;
      Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => { DispatcherTimerTick(null,null); }), DispatcherPriority.Normal);
      DispatcherTimerTick(null,null);
      base.OnPropertyChanged("MonitorStatus");
    }
    private void DispatcherTimerTick(object sender, EventArgs e)
    {
      UpdatePositionPrices(false);
      UpdatePositionRSI3(true);
      RunPerformance();
    }
    private void UpdatePositionPrices(bool change=true)
    {
      try
      {
        DateTime today=DateTime.Now;
        if(null==positions||0==positions.Count)return;
        List<String> symbols=(from MGPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList();
        foreach(String symbol in symbols)
        {
          var selectedPositions=(from MGPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position);
          foreach(MGPositionModel selectedPosition in selectedPositions)
          {
            Price price=PricingDA.GetPrice(symbol);
            if(null==price)continue;
            selectedPosition.CurrentPrice=price.Close;
            selectedPosition.Volume=price.Volume;
            selectedPosition.LastUpdated=price.Date.Date<today.Date?price.Date:today;
          }
        }
        if(change) positions.OnCollectionChanged();
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    private void UpdatePositionRSI3(bool change=true)
    {
      try
      {
        if(null==positions||0==positions.Count)return;
        List<String> symbols=(from MGPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList();
        foreach(String symbol in symbols)
        {
          var selectedPositions=(from MGPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position);
          foreach(MGPositionModel selectedPosition in selectedPositions)
          {
            RSICollection rsiCollection=RSIGenerator.GenerateRSI(symbol,30,3);
            if(null==rsiCollection||0==rsiCollection.Count)continue;
            selectedPosition.RSI3=rsiCollection[rsiCollection.Count-1].RSI;
          }
        }
        if(change)positions.OnCollectionChanged();
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
		public void ReloadCommand()
		{
		  LoadSessionFile();
		}
    public void LoadFileCommand()
    {
      Forms.OpenFileDialog openFileDialog=new Forms.OpenFileDialog();
      openFileDialog.Filter="text file (*.txt)|*.txt";
      openFileDialog.FilterIndex=0;
      openFileDialog.RestoreDirectory=false;
      if(null!=initialPath)openFileDialog.InitialDirectory=initialPath;
      else openFileDialog.InitialDirectory=Directory.GetCurrentDirectory();
      if(!Forms.DialogResult.OK.Equals(openFileDialog.ShowDialog()))return;
      pathFileName=openFileDialog.FileName;
      if(!MGSessionManager.IsValidSessionFile(pathFileName))
      {
        MessageBox.Show(String.Format("Invalid session file '{0}'",pathFileName));
        pathFileName=null;
      }
      else LoadSessionFile();
    }

    public bool LoadSessionFile()
    {
      BusyIndicator = true;
      BusyContent = $"Loading {Utility.GetFileNameNoExtension(pathFileName)}...";

      Task workerTask = Task.Factory.StartNew(() =>
      {
        try
        {
          if(!MGSessionManager.IsValidSessionFile(pathFileName))
          {
            MessageBox.Show(String.Format("'{0}' is not a valid model. IsValidSessionFile returned false.",pathFileName));
            pathFileName = null;
            return false;
          }
          initialPath=Path.GetDirectoryName(pathFileName);
          sessionParams=MGSessionManager.RestoreSession(pathFileName);
          if(null==sessionParams)
          { 
            MessageBox.Show(String.Format("Unable to open '{0}'.  Restore session failed.",pathFileName));
            pathFileName=null;
            return false;
          }
          modelStatistics=MomentumBacktest.GetModelStatistics(sessionParams);
          modelPerformanceSeries=MomentumBacktest.GetModelPerformance(sessionParams);
          configuration=sessionParams.Configuration;
          NVPCollection nvpCollection=sessionParams.Configuration.ToNVPCollection();
          nvpDictionary=nvpCollection.ToDictionary();
          List<String> dictionaryKeys=new List<String>(nvpDictionary.Keys);
          dictionaryKeys.Sort();
          nvpDictionaryKeys=new ObservableCollection<String>(dictionaryKeys);
          selectedParameter=nvpDictionaryKeys[0];
          positions=new MGPositionModelCollection();
          positions.Add(sessionParams.ActivePositions);
          positions.Add(sessionParams.AllPositions);
          UpdatePositionPrices(false);
          UpdatePositionRSI3(true);
          RunPerformance();
          return true;
        }
        catch(Exception exception)
        {
          System.Windows.MessageBox.Show(String.Format("Exception {0}",exception.ToString()),"Error",MessageBoxButton.OK,MessageBoxImage.Exclamation);
          return false;
        }
      });
      workerTask.ContinueWith(continuation =>
      {
        BusyIndicator=false;
        base.OnPropertyChanged("Parameters");
        base.OnPropertyChanged("SelectedParameter");
        base.OnPropertyChanged("ParameterValue");
        base.OnPropertyChanged("Title");
        base.OnPropertyChanged("DisplayName");
        base.OnPropertyChanged("AllPositions");
        base.OnPropertyChanged("CanMonitor");
        base.OnPropertyChanged("CashBalance");
        base.OnPropertyChanged("NonTradeableCash");
        base.OnPropertyChanged("ModelExpectation");
        base.OnPropertyChanged("ExpectationColor");
        base.OnPropertyChanged("ExpectationDescription");
      });
      return true;
    }

    private void RunPerformance()
    {
      if(null==sessionParams)return;
      modelPerformanceSeries=MomentumBacktest.GetModelPerformance(sessionParams);
      base.OnPropertyChanged("Data");
      base.OnPropertyChanged("GraphTitle");
    }
// ****************************************************************************  C H A R T  P L O T T E R *********************************************************
    public String LegendVisible
    {
      get
      {
        if(isLegendVisible) return "true";
        return "false";
      }
      set
      {
        isLegendVisible=Boolean.Parse(value);
        base.OnPropertyChanged("LegendVisible");
      }
    }
    public String PercentButtonText
    {
      get
      {
        if(!showAsGainLoss) return "Show $";
        else return "Show %";
      }
    }
    public ICommand ToggleReturnOrPercentCommand
    {
      get
      {
        if(toggleReturnOrPercentCommand==null)
        {
          toggleReturnOrPercentCommand=new RelayCommand(action =>
          {
            showAsGainLoss=!showAsGainLoss;
            base.OnPropertyChanged("Data");
            base.OnPropertyChanged("PercentButtonText");
            base.OnPropertyChanged("GraphTitle");
          },action => { return true; });
        }
        return toggleReturnOrPercentCommand;
      }
    }
    public CompositeDataSource Data
    {
      get
      {
        if(null==modelPerformanceSeries) return null;
        CompositeDataSource compositeDataSource=null;
        compositeDataSource=GainLossModel.GainLoss(modelPerformanceSeries,showAsGainLoss);
        return compositeDataSource;
      }
    }
    public String GraphTitle
    {
      get
      {
        if(null==sessionParams||null==modelPerformanceSeries) return "";
        StringBuilder sb=new StringBuilder();
        Positions allPositions=sessionParams.GetCombinedPositions();
        DateTime minDate=allPositions.Min(x => x.PurchaseDate);
        DateTime maxDate=PricingDA.GetLatestDate();

        if(modelPerformanceSeries.Count<2)
        {
          sb.Append(showAsGainLoss?"$ GainLoss":"% Return");
          sb.Append(" ");
          sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
          sb.Append(showAsGainLoss?Utility.FormatCurrency(modelPerformanceSeries[modelPerformanceSeries.Count-1].CumulativeGainLoss):Utility.FormatPercent(modelPerformanceSeries[modelPerformanceSeries.Count-1].CumProdMinusOne));
          return sb.ToString();
        }
        if(showAsGainLoss)
        {
          double latestGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-1].CumulativeGainLoss;
          double change=modelPerformanceSeries[modelPerformanceSeries.Count-1].GainLossDOD;
          sb.Append("$ GainLoss");
          sb.Append(" ");
          sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
          sb.Append(" ");
          sb.Append(Utility.FormatCurrency(latestGainLoss));
          sb.Append(",");
          sb.Append(" ");
          sb.Append(change>0.00?"+":"").Append(Utility.FormatCurrency(change));
        }
        else
        {
          double latestCumGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-1].CumProdMinusOne;
          double prevCumGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-2].CumProdMinusOne;
          double change=latestCumGainLoss-prevCumGainLoss;
          sb.Append("% Return");
          sb.Append(" ");
          sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
          sb.Append(" ");
          sb.Append(Utility.FormatPercent(latestCumGainLoss));
          sb.Append(",");
          sb.Append(" ");
          sb.Append(change>0.00?"+":"").Append(Utility.FormatPercent(change));
        }
        return sb.ToString();
      }
    }
  }
}

