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.Windows.Media; using System.Threading.Tasks; 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.CMMomentum; using Position = MarketData.Generator.CMMomentum.Position; using TradeBlotter.UIUtils; using MarketData.Generator.Model; using MarketData.CNNProcessing; using System.Runtime.InteropServices.WindowsRuntime; using MarketData.Generator.Interface; namespace TradeBlotter.ViewModels { public class CMMomentumViewModel : WorkspaceViewModel { // generic section private const String DISPLAY_NAME = "Momentum Model"; private static int MAX_POSITIONS_FOR_UI=10; private bool busyIndicator = false; private String busyContent = null; private String initialPath = null; private String pathFileName = null; // momentum candidate section private ModelStatistics modelStatistics=null; private String selectedDate = null; private DateTime selectableDateStart = Utility.Epoch; private DateTime selectableDateEnd = Utility.Epoch; private ObservableCollection momentumCandidates = new ObservableCollection(); private CMCandidate 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 NVPDictionary nvpDictionary = null; private ObservableCollection nvpDictionaryKeys = null; private CMParams cmParams=null; private CMSessionParams sessionParams=null; private String selectedParameter = null; private CMPositionModelCollection positions=null; private CMPositionModel selectedPosition=null; private RelayCommand loadFileCommand; private RelayCommand reloadCommand; private RelayCommand monitorCommand; private ObservableCollection 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 CMMomentumViewModel(bool loadedFromParams = false) { PropertyChanged += OnMomentumViewModelPropertyChanged; base.DisplayName = DISPLAY_NAME; monitorIntervals = new ObservableCollection(); 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(); cmParams = new CMParams(); NVPCollection nvpCollection = cmParams.ToNVPCollection(); nvpDictionary = nvpCollection.ToDictionary(); List dictionaryKeys = new List(nvpDictionary.Keys); dictionaryKeys.Sort(); nvpDictionaryKeys = new ObservableCollection(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("Type", GetType().Namespace + "." + GetType().Name)); saveParams.Add(new KeyValuePair("PathFileName", pathFileName)); return saveParams; } public override void SetSaveParameters(SaveParameters saveParameters) { try { if(saveParameters.ContainsKey("PathFileName")) { pathFileName = (from KeyValuePair 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 CandidateMenuItems { get { ObservableCollection collection = new ObservableCollection(); 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 PositionsMenuItems { get { ObservableCollection collection = new ObservableCollection(); 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 "CMMomentum Model"; String fileName = Path.GetFileName(pathFileName); fileName = Utility.BetweenString(fileName, null, "."); return "CMMomentum 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 CMMomentum..."; Task workerTask = Task.Factory.StartNew(() => { int maxPositions=cmParams.MaxPositions; cmParams.MaxPositions=MAX_POSITIONS_FOR_UI; CMGeneratorResult cmGeneratorResult = CMMomentumGenerator.GenerateCMCandidates(Utility.ParseDate(selectedDate),Utility.ParseDate(selectedDate),cmParams,null); if(false == cmGeneratorResult.Success) { BusyContent = cmGeneratorResult.LastMessage; try{Thread.Sleep(5000);}catch(Exception){;} BusyIndicator=false; } else { cmParams.MaxPositions=maxPositions; momentumCandidates = new ObservableCollection(cmGeneratorResult.CMCandidates); } }); 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(); // return companyProfile.Description; } } 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 CMCandidate SelectedItem { get { return selectedItem; } set { if (value == selectedItem) return; selectedItem = value; base.OnPropertyChanged("SelectedItem"); } } public CMPositionModel SelectedPosition { get { return selectedPosition; } set { selectedPosition = value; base.OnPropertyChanged("SelectedPosition"); } } public String SelectedDate { get { return selectedDate; } set { selectedDate = value; base.OnPropertyChanged("SelectedDate"); } } public ObservableCollection AllItems { get { return momentumCandidates; } } public CMPositionModelCollection AllPositions { get { return positions; } } public ObservableCollection Parameters { get { return nvpDictionaryKeys; } } public ObservableCollection 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("Type", "TradeBlotter.ViewModels.MovingAverageViewModel")); saveParams.Add(new KeyValuePair("SelectedSymbol", symbol)); saveParams.Add(new KeyValuePair("SelectedWatchList", Constants.CONST_ALL)); saveParams.Add(new KeyValuePair("SelectedDayCount", "360")); saveParams.Add(new KeyValuePair("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(CMPositionModel selectedPosition) { Position clonedPosition=Position.Clone(selectedPosition.Position); IPurePosition changedPosition=ClosePositionDialogNoStop.Prompt("Close Position",clonedPosition); if(null==changedPosition) return; CMMomentumBacktest cmMomentumModel = new CMMomentumBacktest(); if (!cmMomentumModel.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}, Sell Date{1}, Current Price:{2}. Saved to {3}. A backup was created.", changedPosition.Symbol, changedPosition.SellDate.ToShortDateString(), Utility.FormatCurrency(changedPosition.CurrentPrice), pathFileName); MessageBox.Show(strMessage, "Close Position"); LoadSessionFile(); } public void EditPositionCommand(CMPositionModel selectedPosition) { Position clonedPosition=Position.Clone(selectedPosition.Position); IPurePosition changedPosition=EditPositionDialogNoStop.Prompt("Edit Position",clonedPosition); if(null==changedPosition) return; CMMomentumBacktest cmMomentumModel = new CMMomentumBacktest(); if (!cmMomentumModel.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 symbols = (from CMPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList(); foreach (String symbol in symbols) { var selectedPositions = (from CMPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position); foreach (CMPositionModel selectedPosition in selectedPositions) { Price price = PricingDA.GetPrice(symbol); if (null == price) continue; selectedPosition.CurrentPrice = price.Close; 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 symbols = (from CMPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList(); foreach (String symbol in symbols) { var selectedPositions = (from CMPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position); foreach (CMPositionModel 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() { 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 (!CMSessionManager.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() { BusyIndicator = true; BusyContent = $"Loading {Utility.GetFileNameNoExtension(pathFileName)}..."; Task workerTask = Task.Factory.StartNew(() => { try { if (!CMSessionManager.IsValidSessionFile(pathFileName)) return false; initialPath = Path.GetDirectoryName(pathFileName); sessionParams=CMSessionManager.RestoreSession(pathFileName); if (null == sessionParams) { MessageBox.Show(String.Format("Unable to open {0}", pathFileName)); pathFileName = null; return false; } modelStatistics=CMMomentumBacktest.GetModelStatistics(sessionParams); modelPerformanceSeries=CMMomentumBacktest.GetModelPerformance(sessionParams); cmParams = sessionParams.CMParams; NVPCollection nvpCollection = sessionParams.CMParams.ToNVPCollection(); nvpDictionary = nvpCollection.ToDictionary(); List dictionaryKeys = new List(nvpDictionary.Keys); dictionaryKeys.Sort(); nvpDictionaryKeys = new ObservableCollection(dictionaryKeys); selectedParameter = nvpDictionaryKeys[0]; positions = new CMPositionModelCollection(); 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=CMMomentumBacktest.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(); } } } }