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 System.Windows.Media;
using Forms=System.Windows.Forms;
using System.Threading;
using System.Windows;
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.CMTrend;
using Position=MarketData.Generator.CMTrend.Position;
using StopLimit=MarketData.MarketDataModel.StopLimit;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.ModelGenerators;
using MarketData.Generator.Interface;
using TradeBlotter.Extensions;

namespace TradeBlotter.ViewModels
{
  public class CMTTrendViewModel:WorkspaceViewModel
  {
    // generic section
    private const String DISPLAY_NAME="CMTrend 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<CMTCandidate> trendCandidates=new ObservableCollection<CMTCandidate>();
    private CMTCandidate 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 CMTParams configuration=null;
    private CMTSessionParams sessionParams;
    private String selectedParameter=null;
    private CMTPositionModelCollection positions=null;
    private CMTPositionModel 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 CMTTrendViewModel(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 CMTParams();
      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 DISPLAY_NAME;				
        String fileName=Path.GetFileName(pathFileName);
        fileName=Utility.BetweenString(fileName,null,".");
        return DISPLAY_NAME+" ("+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; }
    }
// ******************************************************************************************************************************************************
// *************************************************************** 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.";
        StringBuilder sb=new StringBuilder();
        String companyName=PricingDA.GetNameForSymbol(selectedPosition.Symbol);
        if(null!=companyName)sb.Append(companyName).Append("\n");
        CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedPosition.Symbol);
        if(null==companyProfile||null==companyProfile.Description||"".Equals(companyProfile.Description))sb.Append("No description found.");
        else sb.Append(companyProfile.Sector).Append("/").Append(companyProfile.Industry).Append("\n").Append(companyProfile.Description);
        return sb.ToString();
      }
    }
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
    public CMTCandidate SelectedItem
    {
      get
      {
        return selectedItem;
      }
      set
      {
        if(value==selectedItem) return;
        selectedItem=value;
        base.OnPropertyChanged("SelectedItem");
      }
    }
    public CMTPositionModel SelectedPosition
    {
      get { return selectedPosition; }
      set { selectedPosition=value; base.OnPropertyChanged("SelectedPosition"); }
    }
    public String SelectedDate
    {
      get { return selectedDate; }
      set
      {
        selectedDate=value;
        base.OnPropertyChanged("SelectedDate");
      }
    }
    public ObservableCollection<CMTCandidate> AllItems
    {
      get { return trendCandidates; }
    }
    public CMTPositionModelCollection 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();
      }
    }
    public String TradeableCashDescription
    {
      get
      {
        if(null==sessionParams) return "";
        StringBuilder sb=new StringBuilder();
        sb.Append("Risk parameters for next purchase.").Append("\n");
        sb.Append("Risk=C=(TotalRiskPercentDecimal * AvailableCash)").Append("\n");
        sb.Append(Utility.FormatCurrency(sessionParams.CMTParams.TotalRiskPercentDecimal*sessionParams.CashBalance)).Append("=(");
        sb.Append(Utility.FormatNumber(sessionParams.CMTParams.TotalRiskPercentDecimal,2));
        sb.Append(" * ");
        sb.Append(Utility.FormatCurrency(sessionParams.CashBalance)).Append(")").Append("\n\n");

        sb.Append("Approximate Exposure=C/PositionRiskPercentDecimal").Append("\n");
        sb.Append("Approximate Exposure=").Append(Utility.FormatCurrency(sessionParams.CMTParams.TotalRiskPercentDecimal*sessionParams.CashBalance)).Append("/").Append(Utility.FormatNumber(sessionParams.CMTParams.PositionRiskPercentDecimal,2)).Append("\n");
        sb.Append("Approximate Exposure=").Append(Utility.FormatCurrency((sessionParams.CMTParams.TotalRiskPercentDecimal*sessionParams.CashBalance)/sessionParams.CMTParams.PositionRiskPercentDecimal)).Append("\n");
        sb.Append("*based on $1.00/share purchase price.");
        return sb.ToString();
      }
    }
    public String NonTradeableCashDescription
    {
      get
      {
        if(null==sessionParams) return "";
        StringBuilder sb=new StringBuilder();
        sb.Append("Cash that is set aside and will not be used for purchases.");
        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 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()
    //{
    //  String strStopLimits=null;
    //  MarketData.MarketDataModel.StopLimits stopLimits=GetHistoricalStopLimitsMarketDataModel();
    //  StringBuilder sb=new StringBuilder();
    //  if(null!=stopLimits && 0!=stopLimits.Count)
    //  {
    //    sb.Append(",");
    //    NVPCollections nvpCollections=stopLimits.ToNVPCollections();
    //    sb.Append("StopHistoryCount").Append(",").Append(String.Format("{0}",nvpCollections.Count)).Append(",");
    //    for(int index=0;index<nvpCollections.Count;index++)
    //    {
    //      sb.Append(String.Format("StopHistory_{0}",index)).Append(",").Append(nvpCollections[index].ToString());
    //      if(index<nvpCollections.Count-1)sb.Append(",");
    //    }
    //  }
    //  strStopLimits=sb.ToString();
    //  SaveParameters saveParams=null;
    //  if(null!=strStopLimits)
    //  {
    //    sb=new StringBuilder();
    //    sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
    //    sb.Append(selectedPosition.Symbol).Append(",");
    //    sb.Append("SelectedWatchList,{All},SelectedDayCount,");
    //    sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
    //    sb.Append(String.IsNullOrEmpty(strStopLimits)?"":strStopLimits);
    //    saveParams=SaveParameters.Parse(sb.ToString());
    //  }
    //  else
    //  { 
    //    saveParams=SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,"+selectedPosition.Symbol+",SelectedWatchList,{All},SelectedDayCount,90");
    //  }
    //  saveParams.Referer=this;
    //  WorkspaceInstantiator.Invoke(saveParams);
    //}

    public void DisplayBollingerBandCommandPosition()
    {
      MarketData.MarketDataModel.StopLimits stopLimits = GetHistoricalStopLimitsMarketDataModel();

      StringBuilder sb = new StringBuilder();
      SaveParameters saveParams = null;
      sb = new StringBuilder();
      sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
      sb.Append(selectedPosition.Symbol).Append(",");
      sb.Append("SelectedWatchList,{All},SelectedDayCount,");
      sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
      saveParams = SaveParameters.Parse(sb.ToString());
      SaveParameters stopLimitParams = StopLimitsExtensions.FromStopLimits(stopLimits);
      saveParams.AddRange(stopLimitParams);
      saveParams.Referer=this;
      WorkspaceInstantiator.Invoke(saveParams);
    }

    private int GetDayCountSelectionForBollingerBands(CMTPositionModel selectedPosition)
    {
      DateGenerator dateGenerator=new DateGenerator();

      int daysBetween=dateGenerator.DaysBetween(selectedPosition.PurchaseDate,DateTime.Today);
      if(daysBetween<90)return 90;
      if(daysBetween<180)return 180;
      if(daysBetween<360)return 360;
      if(daysBetween<720)return 720;
      if(daysBetween<1440)return 1440;
      return 3600;
    }

    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 ClosePositionCommand(CMTPositionModel selectedPosition)
    {
      bool deleteStop=false;
      Position clonedPosition=Position.Clone(selectedPosition.Position);
      bool hasStopLimit=PortfolioDA.HasStopLimit(clonedPosition.Symbol);
      IPosition changedPosition=ClosePositionDialog.Prompt("Close Position",clonedPosition,hasStopLimit,ref deleteStop);
      if(null==changedPosition) return;
      CMTTrendModel mmTrendModel=new CMTTrendModel();
      if(!mmTrendModel.ClosePosition(changedPosition.Symbol,changedPosition.PurchaseDate,changedPosition.SellDate,changedPosition.CurrentPrice,pathFileName))
      {
        MessageBox.Show("Failed to close the position, check log for details.","Close Position");
       return;
      }
      if(deleteStop) PortfolioDA.DeleteStopLimit(changedPosition.Symbol);
      String strMessage=String.Format("Closed position for {0}, Purchase Date:{1}, Sell Date{2}, Current Price:{3}, Delete Stop:{4} to {5}.  A backup was created.",
      changedPosition.Symbol,changedPosition.PurchaseDate.ToShortDateString(),changedPosition.SellDate.ToShortDateString(),Utility.FormatCurrency(changedPosition.CurrentPrice),deleteStop,pathFileName);
      MessageBox.Show(strMessage,"Close Position");
      LoadSessionFile();
    }

    public void EditPositionCommand(CMTPositionModel selectedPosition)
    {
      Position clonedPosition=Position.Clone(selectedPosition.Position);
      IPosition changedPosition=EditPositionDialog.Prompt("Edit Position",clonedPosition);
      if(null==changedPosition) return;
      CMTTrendModel mmTrendModel=new CMTTrendModel();
      if(!mmTrendModel.EditPosition(changedPosition.Symbol,changedPosition.PurchaseDate,changedPosition.PurchasePrice,changedPosition.InitialStopLimit,changedPosition.TrailingStopLimit,pathFileName)) 
      {
        MessageBox.Show("Failed to edit the position, check log for details.","Edit Position");
        return;
      }
      if(!selectedPosition.TrailingStopLimit.Equals(changedPosition.TrailingStopLimit))
      {
        selectedPosition.TrailingStopLimit=changedPosition.TrailingStopLimit;
        selectedPosition.LastStopAdjustment=DateTime.Now.Date;
        StopLimit stopLimit=PortfolioDA.GetStopLimit(changedPosition.Symbol);
        if(null==stopLimit)
        {
          stopLimit=new StopLimit();
          stopLimit.Symbol=changedPosition.Symbol;
          stopLimit.StopType=StopLimitConstants.STOP_QUOTE;
          stopLimit.Shares=changedPosition.Shares;
        }
        stopLimit.StopPrice=changedPosition.TrailingStopLimit;
        PortfolioDA.InsertUpdateStopLimit(stopLimit);
      }
      selectedPosition.PurchaseDate=changedPosition.PurchaseDate;
      selectedPosition.PurchasePrice=changedPosition.PurchasePrice;
      selectedPosition.TrailingStopLimit=changedPosition.TrailingStopLimit;
      selectedPosition.InitialStopLimit=changedPosition.InitialStopLimit;
      String strMessage=String.Format("Edited Position for {0} Purchase Date:{1} Purchase Price:{2}, Trailing Stop:{3}. A backup was created.",
      selectedPosition.Symbol,selectedPosition.PurchaseDate.ToShortDateString(),Utility.FormatCurrency(selectedPosition.PurchasePrice),Utility.FormatCurrency(selectedPosition.TrailingStopLimit));
      MessageBox.Show(strMessage,"Edit Position");
    }
    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);
      }
    }
    // **************************************************************************************************************************************************************************
    // ********************************************************************** 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(true);
      RunPerformance();
    }
    private void UpdatePositionPrices(bool signalChangeEvent=true)
    {
      try
      {
        DateTime today=DateTime.Now;
        if(null==positions||0==positions.Count) return;
        List<String> symbols=(from CMTPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList();
        foreach(String symbol in symbols)
        {
          var selectedPositions=(from CMTPositionModel position in positions where position.IsActivePosition&&position.Symbol.Equals(symbol) select position);
          foreach(CMTPositionModel selectedPosition in selectedPositions)
          {
            Price price=PricingDA.GetPrice(symbol);
            if(null==price) continue;
            selectedPosition.CurrentPrice=price.Close;
            selectedPosition.CurrentPriceLow=price.Low;
            selectedPosition.LastUpdated=price.Date.Date<today.Date?price.Date:today;
            selectedPosition.EdgeRatio=EdgeRatioGenerator.CalculateEdgeRatio(symbol,selectedPosition.PurchaseDate,selectedPosition.PurchasePrice,price.Date).EdgeRatio;
          }
        }
        if(signalChangeEvent) positions.OnCollectionChanged();
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
		public void ReloadCommand()
		{
		  LoadSessionFile();
		}
    public void LoadFileCommand()
    {
      try
      {
        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(!CMTSessionManager.IsValidSessionFile(pathFileName))
        {
          MessageBox.Show(String.Format("Invalid session file '{0}'",pathFileName));
          pathFileName=null;
        }
        else LoadSessionFile();
      }
      catch(Exception exception)
      {
        System.Windows.MessageBox.Show(String.Format("Exception {0}",exception.ToString()),"Error",MessageBoxButton.OK,MessageBoxImage.Exclamation);
        return;
      }
    }
    public bool LoadSessionFile()
    {
      if(!CMTSessionManager.IsValidSessionFile(pathFileName)) return false;
      initialPath=Path.GetDirectoryName(pathFileName);
      sessionParams=CMTSessionManager.RestoreSession(pathFileName);
      if(null==sessionParams) { MessageBox.Show(String.Format("Unable to open {0}",pathFileName)); pathFileName=null; return false; }
      modelStatistics=CMTTrendModel.GetModelStatistics(sessionParams);
      configuration=sessionParams.CMTParams;
      NVPCollection nvpCollection=sessionParams.CMTParams.ToNVPCollection();
      nvpDictionary=nvpCollection.ToDictionary();
      nvpDictionaryKeys=new ObservableCollection<String>(nvpDictionary.Keys);
      selectedParameter=nvpDictionaryKeys[0];
      positions=new CMTPositionModelCollection();
      positions.Add(sessionParams.ActivePositions);
      positions.Add(sessionParams.AllPositions);
      trendCandidates=new ObservableCollection<CMTCandidate>();
      foreach(CMTCandidate candidate in sessionParams.Candidates)trendCandidates.Add(candidate);
      UpdatePositionPrices(true);
      RunPerformance();
      base.OnPropertyChanged("Parameters");
      base.OnPropertyChanged("SelectedParameter");
      base.OnPropertyChanged("ParameterValue");
      base.OnPropertyChanged("Title");
      base.OnPropertyChanged("DisplayName");
      base.OnPropertyChanged("AllPositions");
      base.OnPropertyChanged("CanMonitor");
      base.OnPropertyChanged("AllItems");
      base.OnPropertyChanged("CashBalance");
      base.OnPropertyChanged("NonTradeableCash");
      base.OnPropertyChanged("ModelExpectation");
      base.OnPropertyChanged("ExpectationColor");
      base.OnPropertyChanged("ExpectationDescription");
      base.OnPropertyChanged("TradeableCashDescription");
      base.OnPropertyChanged("NonTradeableCashDescription");
      return true;
    }
    private void RunPerformance()
    {
      if(null==sessionParams)return;
      modelPerformanceSeries=CMTTrendModel.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(" ");
          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();
      }
    }
// ****************************************************************************************************************************************************************
// *************************************************************************** T O O L T I P  C A L L O U T S *****************************************************
// ****************************************************************************************************************************************************************
    public String ToolTipRMultiple
    {
      get
      {
        if(null==selectedPosition)return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("RMultiple is based on original position setup.").Append("\n");
        sb.Append("Original Exposure=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice*selectedPosition.Shares)).Append("\n");
        sb.Append("Original R/Share=PurchasePrice-InitialStop").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("\n");
        sb.Append("Original Risk=Original R/Share*Shares").Append("\n");
        sb.Append(Utility.FormatCurrency((selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)*selectedPosition.Shares)).Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)).Append("*").Append(selectedPosition.Shares).Append("\n");
        sb.Append("RMultiple=(CurrentPrice-PurchasePrice)/(PurchasePrice-InitialStop)").Append("\n");
        sb.Append(selectedPosition.RMultipleAsString).Append("=").Append("(").Append(Utility.FormatCurrency(selectedPosition.CurrentPrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append(")");
        sb.Append("/").Append("(").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append(")");
        return sb.ToString();
      }
    }
    public String ToolTipTotalRiskExposure
    {
      get
      {
        if(null==selectedPosition)return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("Current Risk.  See RMultiple for initial risk assumptions.").Append("\n");
        sb.Append("[TotalRiskExposure]=([R/Share]*[Shares])").Append("\n");
        if(null==selectedPosition) return sb.ToString();
        sb.Append(Utility.FormatCurrency(selectedPosition.TotalRiskExposure)).Append("=(").Append(Utility.FormatCurrency(selectedPosition.R)).Append("*").Append(Utility.FormatNumber(selectedPosition.Shares,0)).Append(")");
        return sb.ToString();
      }
    }
    public String ToolTipR
    {
      get
      {
        if(null==selectedPosition)return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("Current R/Share.  See RMultiple for initial risk assumptions.").Append("\n");
        sb.Append("R/Share=TrailingStop>PurchasePrice?0.00:PurchasePrice-TrailingStop").Append("\n");
        if(selectedPosition.TrailingStopLimit>selectedPosition.PurchasePrice)
        {
          sb.Append(Utility.FormatCurrency(0)).Append("=").Append(Utility.FormatCurrency(0));
        }
        else
        {
          sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit>selectedPosition.PurchasePrice?0.00:selectedPosition.PurchasePrice-selectedPosition.TrailingStopLimit));
          sb.Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit));
        }
        return sb.ToString();
      }
    }
    public String ToolTipPriceLow
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[Low]=([CurrentLowPrice])").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.CurrentPriceLow)).Append("=").Append(Utility.FormatCurrency(selectedPosition.CurrentPriceLow));
        return sb.ToString();
      }
    }
    public String ToolTipPrice
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[Price]=([CurrentPrice])").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.CurrentPrice)).Append("=").Append(Utility.FormatCurrency(selectedPosition.CurrentPrice));
        return sb.ToString();
      }
    }
    public String ToolTipTrailingStop
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[TrailingStop]=([TrailingStopLimit])").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("\n");
        List<MarketData.Generator.Model.StopLimit> stopLimits=GetHistoricalStopLimits();
        if(selectedPosition.TrailingStopLimit > selectedPosition.PurchasePrice)
        {
          sb.Append("Riskless Gain").Append(" = ");
          sb.Append(String.Format("(Trailing Stop - Purchase Price) * Shares"));
          sb.Append("\n");
          sb.Append(String.Format("{0}",Utility.FormatCurrency((selectedPosition.TrailingStopLimit-selectedPosition.PurchasePrice)*selectedPosition.Shares)));
          sb.Append(String.Format("=({0}-{1})*{2}",Utility.FormatCurrency(selectedPosition.TrailingStopLimit),Utility.FormatCurrency(selectedPosition.PurchasePrice),Utility.FormatNumber(selectedPosition.Shares,3)));
          sb.Append("\n");
        }
        if(null!=stopLimits && 0!=stopLimits.Count)
        {
          sb.Append("Stop History").Append("\n");
          foreach(MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
          {
            sb.Append(String.Format("Analysis Date:{0} New Stop:{1} Previous Stop:{2}",Utility.DateTimeToStringMMSDDSYYYY(stopLimit.AnalysisDate),Utility.FormatCurrency(stopLimit.NewStop),Utility.FormatCurrency(stopLimit.PreviousStop)));
            sb.Append("\n");
          }
        }
        return sb.ToString();
      }
    }
    public String ToolTipInitialStop
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[InitialStop]=([InitialStopLimit])").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit));
        return sb.ToString();
      }
    }
    public String ToolTipPurchasePrice
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[PurchasePrice]=([PurchasePrice])").Append("\n");
        sb.Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice));
        return sb.ToString();
      }
    }
    public String ToolTipEdgeRatio
    {
      get
      {
        if(null==selectedPosition) return "Please select a position by clicking on a row.";
        StringBuilder sb=new StringBuilder();
        sb.Append("[EdgeRatio]=AVG(SUM(MFE/ATR(14)))/AVG(SUM(MAE/ATR(14)))").Append("\n");
        sb.Append("MFE=Maximum Favorable Excursion").Append("\n");
        sb.Append("MAE=Maximum Adverse Excursion").Append("\n");
        sb.Append("ATR=Average True Range.  14 days").Append("\n");
        if(selectedPosition.EdgeRatio<1.00)
        {
          sb.Append(String.Format("You can expect a further {0} units more of adverse volatility.",Utility.FormatNumber(1.00-selectedPosition.EdgeRatio,2)));
        }
        else
        {
          sb.Append(String.Format("You can expect a further {0} units more of favorable volatility.",Utility.FormatNumber(selectedPosition.EdgeRatio-1.00,2)));
        }
        return sb.ToString();
      }
    }
// ************************************************************************************************************************************************************************************************************
// This getter returns MMTrend specific stop limits to show in the tooltips
    public MarketData.Generator.Model.StopLimits GetHistoricalStopLimits()
    {
      if(null==sessionParams||null==selectedPosition) return null;
      MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.Symbol.Equals(selectedPosition.Symbol) select stopLimit).OrderByDescending(x => x.AnalysisDate).ToList());
      return stopLimits;
    }
// This getter returns non-model (MarketData.MarketDataModel) specific stop limits to pass along to the bollinger bands
    public MarketData.MarketDataModel.StopLimits GetHistoricalStopLimitsMarketDataModel()
    {
      if(null==sessionParams||null==selectedPosition) return null;
      DateGenerator dateGenerator=new DateGenerator();
      MarketData.MarketDataModel.StopLimits marketDataModelStopLimits=new MarketData.MarketDataModel.StopLimits();
      MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits(
        (from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.Symbol.Equals(selectedPosition.Symbol) 
          select stopLimit).OrderByDescending(x => x.AnalysisDate).ToList());

      MarketData.MarketDataModel.StopLimit initialStopLimit=new MarketData.MarketDataModel.StopLimit();
      initialStopLimit.Symbol=selectedPosition.Symbol;
      initialStopLimit.Shares=0;
      initialStopLimit.StopPrice=selectedPosition.InitialStopLimit;
      initialStopLimit.StopType=StopLimitConstants.STOP_QUOTE;
      initialStopLimit.EffectiveDate=dateGenerator.FindNextBusinessDay(selectedPosition.PurchaseDate);
      initialStopLimit.Active=1;
      marketDataModelStopLimits.Add(initialStopLimit);
      foreach(MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
      {
        MarketData.MarketDataModel.StopLimit marketDataModelStopLimit=new MarketData.MarketDataModel.StopLimit();
        marketDataModelStopLimit.Symbol=stopLimit.Symbol;
        marketDataModelStopLimit.Shares=0;
        marketDataModelStopLimit.StopPrice=stopLimit.NewStop;
        marketDataModelStopLimit.StopType=StopLimitConstants.STOP_QUOTE;
        marketDataModelStopLimit.EffectiveDate=stopLimit.AnalysisDate;
        marketDataModelStopLimit.Active=1;                  
        marketDataModelStopLimits.Add(marketDataModelStopLimit);
      }
      return marketDataModelStopLimits;
    }
  }
}


