Files
TradeBlotter/ViewModels/MomentumViewModel.cs

1358 lines
58 KiB
C#

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Threading.Tasks;
using Forms=System.Windows.Forms;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.IO;
using MarketData;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.Generator;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using System.Windows.Threading;
using MarketData.Generator.Momentum;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.Interface;
using Position = MarketData.Generator.Momentum.Position;
namespace TradeBlotter.ViewModels
{
public class MomentumViewModel : WorkspaceViewModel
{
// generic section
private const String DISPLAY_NAME = "Momentum Model";
private bool busyIndicator = false;
private String busyContent=null;
private String initialPath=null;
private String pathFileName=null;
// momentum candidate section
private String selectedDate = null;
private DateTime selectableDateStart=Utility.Epoch;
private DateTime selectableDateEnd=Utility.Epoch;
private ObservableCollection<MomentumCandidate> momentumCandidates=new ObservableCollection<MomentumCandidate>();
private MomentumCandidate selectedItem=null;
private RelayCommand runCommand;
private RelayCommand stochasticsCommand;
private RelayCommand relativeStrengthCommand;
private RelayCommand macdCommand;
private RelayCommand bollingerBandCommand;
private RelayCommand priceHistoryCommand;
private RelayCommand stickerValuationCommand;
private RelayCommand dcfValuationCommand;
private RelayCommand dividendHistoryCommand;
private RelayCommand analystRatingsCommand;
private RelayCommand addToWatchListCommand;
private RelayCommand removeFromWatchListCommand;
private RelayCommand movingAverageCommand;
private RelayCommand displayHistoricalCommand;
// session section
private ModelStatistics modelStatistics=null;
private NVPDictionary nvpDictionary=null;
private ObservableCollection<String> nvpDictionaryKeys=null;
private MGConfiguration configuration=null;
private MGSessionParams sessionParams;
private String selectedParameter=null;
private MGPositionModelCollection positions=null;
private MGPositionModel selectedPosition=null;
private RelayCommand loadFileCommand;
private RelayCommand reloadCommand;
private RelayCommand monitorCommand;
private ObservableCollection<String> monitorIntervals;
private String selectedMonitorInterval;
private bool monitorRunning=false;
private DispatcherTimer dispatcherTimer = new DispatcherTimer();
private RelayCommand stochasticsCommandPosition;
private RelayCommand relativeStrengthCommandPosition;
private RelayCommand macdCommandPosition;
private RelayCommand bollingerBandCommandPosition;
private RelayCommand priceHistoryCommandPosition;
private RelayCommand stickerValuationCommandPosition;
private RelayCommand dcfValuationCommandPosition;
private RelayCommand dividendHistoryCommandPosition;
private RelayCommand analystRatingsCommandPosition;
private RelayCommand addToWatchListCommandPosition;
private RelayCommand removeFromWatchListCommandPosition;
private RelayCommand movingAverageCommandPosition;
private RelayCommand displayHistoricalCommandPosition;
private RelayCommand displayHeadlinesCommandPosition;
private RelayCommand closePositionCommandPosition;
private RelayCommand editPositionCommandPosition;
// chart plotter
private bool showAsGainLoss=true;
private bool isLegendVisible=false;
private RelayCommand toggleReturnOrPercentCommand=null;
private ModelPerformanceSeries modelPerformanceSeries=null;
public MomentumViewModel(bool loadedFromParams=false)
{
PropertyChanged += OnMomentumViewModelPropertyChanged;
base.DisplayName = DISPLAY_NAME;
monitorIntervals=new ObservableCollection<String>();
monitorIntervals.Add("30");
monitorIntervals.Add("60");
monitorIntervals.Add("90");
monitorIntervals.Add("120");
selectedMonitorInterval=monitorIntervals[0];
DateTime earliestPricingDate=PricingDA.GetEarliestDate();
earliestPricingDate+=new TimeSpan(252,0,0,0);
selectableDateStart=earliestPricingDate;
selectableDateEnd=PricingDA.GetLatestDate();
selectedDate=selectableDateEnd.ToShortDateString();
configuration=new MGConfiguration();
NVPCollection nvpCollection=configuration.ToNVPCollection();
nvpDictionary=nvpCollection.ToDictionary();
List<String> dictionaryKeys=new List<String>(nvpDictionary.Keys);
dictionaryKeys.Sort();
nvpDictionaryKeys=new ObservableCollection<String>(dictionaryKeys);
selectedParameter=nvpDictionaryKeys[0];
dispatcherTimer.Tick += DispatcherTimerTick;
dispatcherTimer.Interval = new TimeSpan(0, 0, int.Parse(selectedMonitorInterval));
base.OnPropertyChanged("MonitorIntervals");
base.OnPropertyChanged("SelectedMonitorInterval");
base.OnPropertyChanged("Parameters");
base.OnPropertyChanged("SelectedParameter");
base.OnPropertyChanged("ParameterValue");
}
protected override void OnDispose()
{
StopMonitor();
base.OnDispose();
}
// ******************************************************************************************** P E R S I S T E N C E ********************************************************************************************
public override bool CanPersist()
{
return true;
}
public override SaveParameters GetSaveParameters()
{
SaveParameters saveParams = new SaveParameters();
if (null == pathFileName) return null;
saveParams.Add(new KeyValuePair<String, String>("Type",GetType().Namespace+"."+GetType().Name));
saveParams.Add(new KeyValuePair<String, String>("PathFileName", pathFileName));
return saveParams;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
try
{
pathFileName = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("PathFileName") select item).FirstOrDefault().Value;
if(!LoadSessionFile())pathFileName=null;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
}
}
// **************************************************************************************************************************************************************************
public bool BusyIndicator
{
get { return busyIndicator; }
set
{
busyIndicator = value;
base.OnPropertyChanged("BusyIndicator");
}
}
public String BusyContent
{
get{return busyContent;}
set{busyContent=value;base.OnPropertyChanged("BusyContent");}
}
// **************************************************************************************************************************************************************************
public ObservableCollection<MenuItem> CandidateMenuItems
{
get
{
ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
collection.Add(new MenuItem() { Text = "Display Bollinger Band", MenuItemClickedCommand = DisplayBollingerBand, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Dividend History", MenuItemClickedCommand = DisplayDividendHistory, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Sticker Valuation", MenuItemClickedCommand = DisplayStickerValuation, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Historical", MenuItemClickedCommand = DisplayHistorical, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Stochastics", MenuItemClickedCommand = DisplayStochastics, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Relative Strength", MenuItemClickedCommand=DisplayRelativeStrength, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display MACD", MenuItemClickedCommand = DisplayMACD, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Price History", MenuItemClickedCommand = DisplayPriceHistory, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAverage, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Analyst Ratings", MenuItemClickedCommand = DisplayAnalystRatings, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuation, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchList, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchList, StaysOpenOnClick = false });
return collection;
}
}
public ObservableCollection<MenuItem> PositionsMenuItems
{
get
{
ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
collection.Add(new MenuItem() { Text = "Display Bollinger Band", MenuItemClickedCommand = DisplayBollingerBandPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Headlines", MenuItemClickedCommand = DisplayHeadlinesPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Dividend History", MenuItemClickedCommand = DisplayDividendHistoryPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Sticker Valuation", MenuItemClickedCommand = DisplayStickerValuationPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Historical", MenuItemClickedCommand = DisplayHistoricalPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Stochastics", MenuItemClickedCommand = DisplayStochasticsPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Relative Strength", MenuItemClickedCommand=DisplayRelativeStrengthPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display MACD", MenuItemClickedCommand = DisplayMACDPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Price History", MenuItemClickedCommand = DisplayPriceHistoryPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAveragePosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display Analyst Ratings", MenuItemClickedCommand = DisplayAnalystRatingsPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuationPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchListPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchListPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Close Position...",MenuItemClickedCommand = ClosePosition,StaysOpenOnClick=false });
collection.Add(new MenuItem() { Text = "Edit Position...",MenuItemClickedCommand = EditPosition,StaysOpenOnClick=false });
return collection;
}
}
private void OnMomentumViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
}
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
public override String DisplayName
{
get
{
if(null==pathFileName)return "Momentum Model";
String fileName=Path.GetFileName(pathFileName);
fileName=Utility.BetweenString(fileName,null,".");
return "Momentum Model ("+fileName+")";
}
}
public override String Title
{
get
{
return DisplayName;
}
}
public DateTime SelectableDateStart
{
get{return selectableDateStart;}
set{selectableDateStart=value;}
}
public DateTime SelectableDateEnd
{
get{return selectableDateEnd;}
set{selectableDateEnd=value;}
}
// ********************************************************************************************************************************************************************************
private void Run()
{
try
{
if(null==selectedDate)return;
BusyIndicator = true;
BusyContent="Running Momentum...";
Task workerTask = Task.Factory.StartNew(() =>
{
MGConfiguration localConfiguration=new MGConfiguration();
localConfiguration.MaxPositions = int.Parse(nvpDictionary["MaxPositions"].Value);
localConfiguration.HoldingPeriod = int.Parse(nvpDictionary["HoldingPeriod"].Value);
MomentumCandidates candidates = MomentumGenerator.GenerateMomentumWithFallback(Utility.ParseDate(selectedDate), configuration == null ? localConfiguration : configuration);
momentumCandidates=new ObservableCollection<MomentumCandidate>();
foreach(MomentumCandidate momentumCandidate in candidates)momentumCandidates.Add(momentumCandidate);
});
workerTask.ContinueWith((continuation)=>
{
BusyIndicator = false;
base.OnPropertyChanged("AllItems");
base.OnPropertyChanged("Title");
});
}
finally
{
}
}
// ******************************************************************************************************************************************************
// *************************************************************** T O O L T I P C A L L O U T S ******************************************************
// *******************************************************************************************************************************************************
// Candidate
public String CompanyDescription
{
get
{
if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedItem.Symbol);
if(null==companyProfile || null==companyProfile.Description || "".Equals(companyProfile.Description))return "No description found.";
StringBuilder sb=new StringBuilder();
sb.Append(companyProfile.Sector).Append("/").Append(companyProfile.Industry).Append("\n").Append(companyProfile.Description);
return sb.ToString();
}
}
public String VelocityDescription
{
get
{
if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
return "Velocity is the percentage range of the current price within the price history.";
}
}
public String BetaDescription
{
get
{
if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
return "A beta of less than 1 means that the security is theoretically less volatile than the market. A beta of greater than 1 indicates that the security's price is theoretically more volatile than the market. For example, if a stock's beta is 1.2, it's theoretically 20% more volatile than the market.";
}
}
// Position
public String CompanyDescriptionSelectedPosition
{
get
{
if(null== selectedPosition || null==selectedPosition.Symbol)return "No row selected.";
CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedPosition.Symbol);
if(null==companyProfile || null==companyProfile.Description || "".Equals(companyProfile.Description))return "No description found.";
StringBuilder sb = new StringBuilder();
sb.Append(companyProfile.Sector).Append("/").Append(companyProfile.Industry).Append("\n").Append(companyProfile.Description);
return sb.ToString();
}
}
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
// ****************************************************************************************************************************************************************
public MomentumCandidate SelectedItem
{
get
{
return selectedItem;
}
set
{
if (value == selectedItem) return;
selectedItem = value;
base.OnPropertyChanged("SelectedItem");
}
}
public MGPositionModel SelectedPosition
{
get{return selectedPosition;}
set{selectedPosition=value;base.OnPropertyChanged("SelectedPosition");}
}
public String SelectedDate
{
get { return selectedDate; }
set
{
selectedDate = value;
base.OnPropertyChanged("SelectedDate");
}
}
public ObservableCollection<MomentumCandidate> AllItems
{
get{return momentumCandidates;}
}
public MGPositionModelCollection AllPositions
{
get{return positions;}
}
public ObservableCollection<String> Parameters
{
get{return nvpDictionaryKeys;}
}
public ObservableCollection<String> MonitorIntervals
{
get{return monitorIntervals;}
}
public bool CanMonitor
{
get{return IsTradeFileLoaded;}
}
public String MonitorStatus
{
get{return monitorRunning?"Stop Monitor":"Start Monitor";}
}
public String SelectedMonitorInterval
{
get{return selectedMonitorInterval;}
set{selectedMonitorInterval=value;base.OnPropertyChanged("SelectedMonitorInterval");}
}
public String SelectedParameter
{
get{return selectedParameter;}
set{selectedParameter=value;base.OnPropertyChanged("SelectedParameter");base.OnPropertyChanged("ParameterValue");}
}
public String ParameterValue
{
get
{
if(null==nvpDictionary||null==nvpDictionaryKeys||null==selectedParameter)return null;
return nvpDictionary[selectedParameter].Value;
}
}
public String CashBalance
{
get
{
if(null==sessionParams) return "";
return Utility.FormatCurrency(sessionParams.CashBalance);
}
}
public String NonTradeableCash
{
get
{
if(null==sessionParams) return "";
return Utility.FormatCurrency(sessionParams.NonTradeableCash);
}
}
public String ModelExpectation
{
get
{
if(null==modelStatistics) return "";
return Utility.FormatNumber(modelStatistics.Expectancy,2);
}
}
public Brush ExpectationColor
{
get
{
if(null==modelStatistics) return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
if(modelStatistics.Expectancy>0.00) return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
return UIUtils.BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
}
}
public String ExpectationDescription
{
get
{
if(null==modelStatistics) return "";
StringBuilder sb=new StringBuilder();
sb.Append("Expectancy is (percentage of winning trades * average gain) / (percentage of losing trades * average loss).").Append("\n");
sb.Append("Total Trades : ").Append(modelStatistics.TotalTrades).Append("\n");
sb.Append("Winning Trades : ").Append(modelStatistics.WinningTrades).Append("\n");
sb.Append("Losing Trades : ").Append(modelStatistics.LosingTrades).Append("\n");
sb.Append("Winning Trades : ").Append(Utility.FormatNumber(modelStatistics.WinningTradesPercent,2)).Append("%").Append("\n");
sb.Append("Losing Trades : ").Append(Utility.FormatNumber(modelStatistics.LosingTradesPercent,2)).Append("%").Append("\n");
sb.Append("Average Winning Trade Gain : ").Append(Utility.FormatNumber(modelStatistics.AverageWinningTradePercentGain,2)).Append("%").Append("\n");
sb.Append("Average Losing Trade Loss : ").Append(Utility.FormatNumber(modelStatistics.AverageLosingTradePercentLoss,2)).Append("%").Append("\n");
sb.Append("Expectancy : ").Append(Utility.FormatNumber(modelStatistics.Expectancy,2)).Append("\n");
sb.Append("\n");
sb.Append("Maintain a positive Expectancy and you're a winner.");
sb.Append("\n");
sb.Append("The calculations are based on closed positions.");
return sb.ToString();
}
}
// *************************************************************************************************************************************************************
// *********************************************************************** I C O M M A N D ********************************************************************
// *************************************************************************************************************************************************************
public ICommand DisplayHistorical
{
get
{
if (displayHistoricalCommand == null)
{
displayHistoricalCommand = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HistoricalViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return displayHistoricalCommand;
}
}
public ICommand RunCommand
{
get
{
if (runCommand == null)
{
runCommand = new RelayCommand(param => this.Run(), param => {return true;});
}
return runCommand;
}
}
public ICommand DisplayMovingAverage
{
get
{
if (movingAverageCommand == null)
{
movingAverageCommand = new RelayCommand(param => this.DisplayMovingAverageCommand(selectedItem.Symbol), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return movingAverageCommand;
}
}
public ICommand DisplayAnalystRatings
{
get
{
if (analystRatingsCommand == null)
{
analystRatingsCommand = new RelayCommand(param => this.DisplayAnalystRatingsCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return analystRatingsCommand;
}
}
public ICommand DisplayMACD
{
get
{
if (macdCommand == null)
{
macdCommand = new RelayCommand(param => this.DisplayMACDCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return macdCommand;
}
}
public ICommand DisplayStochastics
{
get
{
if (stochasticsCommand == null)
{
stochasticsCommand = new RelayCommand(param => this.DisplayStochasticsCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return stochasticsCommand;
}
}
public ICommand DisplayRelativeStrength
{
get
{
if (relativeStrengthCommand == null)
{
relativeStrengthCommand = new RelayCommand(param => this.DisplayRelativeStrengthCommand(), param => { return null != selectedItem && null!=selectedItem.Symbol; });
}
return relativeStrengthCommand;
}
}
public ICommand DisplayStickerValuation
{
get
{
if (null == stickerValuationCommand)
{
stickerValuationCommand = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StickerPriceViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedItem && null!=selectedItem.Symbol; });
}
return stickerValuationCommand;
}
}
public ICommand DisplayDCFValuation
{
get
{
if (null == dcfValuationCommand)
{
dcfValuationCommand = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DCFValuationViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedItem && null!=selectedItem.Symbol; });
}
return dcfValuationCommand;
}
}
public ICommand DisplayPriceHistory
{
get
{
if (priceHistoryCommand == null)
{
priceHistoryCommand = new RelayCommand(param => this.DisplayPriceHistoryCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return priceHistoryCommand;
}
}
public ICommand DisplayDividendHistory
{
get
{
if (dividendHistoryCommand == null)
{
dividendHistoryCommand = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendHistoryViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return dividendHistoryCommand;
}
}
public void DisplayPriceHistoryCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.PricingViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public ICommand DisplayBollingerBand
{
get
{
if (bollingerBandCommand == null)
{
bollingerBandCommand = new RelayCommand(param => this.DisplayBollingerBandCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
}
return bollingerBandCommand;
}
}
public ICommand AddToWatchList
{
get
{
if (addToWatchListCommand == null)
{
addToWatchListCommand = new RelayCommand(param => this.AddToWatchListCommand(selectedItem.Symbol),
param =>
{
if(null==selectedItem || null==selectedItem.Symbol)return false;
if (WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
return true;
});
}
return addToWatchListCommand;
}
}
public ICommand RemoveFromWatchList
{
get
{
if (removeFromWatchListCommand == null)
{
removeFromWatchListCommand = new RelayCommand(param => this.RemoveFromWatchListCommand(selectedItem.Symbol),
param =>
{
if(null==selectedItem || null==selectedItem.Symbol)return false;
if (!WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
return true;
});
}
return removeFromWatchListCommand;
}
}
// *************************************************************************************************************************************************************
// **************************************************************** I C O M M A N D P O S I T I O N ***********************************************************
// *************************************************************************************************************************************************************
public ICommand DisplayHeadlinesPosition
{
get
{
if (null == displayHeadlinesCommandPosition)
{
displayHeadlinesCommandPosition = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HeadlinesViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,Valuations");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
}
return displayHeadlinesCommandPosition;
}
}
public ICommand DisplayHistoricalPosition
{
get
{
if (displayHistoricalCommandPosition == null)
{
displayHistoricalCommandPosition = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HistoricalViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return displayHistoricalCommandPosition;
}
}
public ICommand DisplayAnalystRatingsPosition
{
get
{
if (analystRatingsCommandPosition == null)
{
analystRatingsCommandPosition = new RelayCommand(param => this.DisplayAnalystRatingsCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return analystRatingsCommandPosition;
}
}
public ICommand DisplayMovingAveragePosition
{
get
{
if (movingAverageCommandPosition == null)
{
movingAverageCommandPosition = new RelayCommand(param => this.DisplayMovingAverageCommand(selectedPosition.Symbol), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return movingAverageCommandPosition;
}
}
public ICommand DisplayMACDPosition
{
get
{
if (macdCommandPosition == null)
{
macdCommandPosition = new RelayCommand(param => this.DisplayMACDCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return macdCommandPosition;
}
}
public ICommand DisplayStochasticsPosition
{
get
{
if (stochasticsCommandPosition == null)
{
stochasticsCommandPosition = new RelayCommand(param => this.DisplayStochasticsCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return stochasticsCommandPosition;
}
}
public ICommand DisplayRelativeStrengthPosition
{
get
{
if (relativeStrengthCommandPosition == null)
{
relativeStrengthCommandPosition = new RelayCommand(param => this.DisplayRelativeStrengthCommandPosition(),param => { return null != selectedPosition && null!= selectedPosition.Symbol; });
}
return relativeStrengthCommandPosition;
}
}
public ICommand DisplayStickerValuationPosition
{
get
{
if (null == stickerValuationCommandPosition)
{
stickerValuationCommandPosition= new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StickerPriceViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
}
return stickerValuationCommandPosition;
}
}
public ICommand DisplayDCFValuationPosition
{
get
{
if (null == dcfValuationCommandPosition)
{
dcfValuationCommandPosition = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DCFValuationViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedPosition && null!=selectedPosition.Symbol; });
}
return dcfValuationCommandPosition;
}
}
public ICommand DisplayPriceHistoryPosition
{
get
{
if (priceHistoryCommandPosition == null)
{
priceHistoryCommandPosition = new RelayCommand(param => this.DisplayPriceHistoryCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return priceHistoryCommandPosition;
}
}
public ICommand DisplayDividendHistoryPosition
{
get
{
if (dividendHistoryCommandPosition == null)
{
dividendHistoryCommandPosition = new RelayCommand(param =>
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendHistoryViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return dividendHistoryCommandPosition;
}
}
public ICommand DisplayBollingerBandPosition
{
get
{
if (bollingerBandCommandPosition == null)
{
bollingerBandCommandPosition = new RelayCommand(param => this.DisplayBollingerBandCommandPosition(), param => { return null != selectedPosition && null != selectedPosition.Symbol; });
}
return bollingerBandCommandPosition;
}
}
public ICommand AddToWatchListPosition
{
get
{
if (addToWatchListCommandPosition == null)
{
addToWatchListCommandPosition = new RelayCommand(param => this.AddToWatchListCommand(selectedPosition.Symbol),
param =>
{
if(null==selectedPosition || null==selectedPosition.Symbol)return false;
if (WatchListDA.IsInWatchList(selectedPosition.Symbol)) return false;
return true;
});
}
return addToWatchListCommandPosition;
}
}
public ICommand RemoveFromWatchListPosition
{
get
{
if (removeFromWatchListCommandPosition == null)
{
removeFromWatchListCommandPosition = new RelayCommand(param => this.RemoveFromWatchListCommand(selectedPosition.Symbol), param =>
{
if(null==selectedPosition || null==selectedPosition.Symbol)return false;
if (!WatchListDA.IsInWatchList(selectedPosition.Symbol)) return false;
return true;
});
}
return removeFromWatchListCommandPosition;
}
}
public ICommand ClosePosition
{
get
{
if(closePositionCommandPosition==null)
{
closePositionCommandPosition=new RelayCommand(param => this.ClosePositionCommand(selectedPosition),param =>
{
if(null==selectedPosition||null==selectedPosition.Symbol) return false;
return true;
});
}
return closePositionCommandPosition;
}
}
public ICommand EditPosition
{
get
{
if(editPositionCommandPosition==null)
{
editPositionCommandPosition=new RelayCommand(param => this.EditPositionCommand(selectedPosition),param =>
{
if(null==selectedPosition||null==selectedPosition.Symbol||!Utility.IsEpoch(selectedPosition.SellDate)) return false;
return true;
});
}
return editPositionCommandPosition;
}
}
// *************************************************************************************************************************************************************
// ******************************************************************* I C O M M A N D S E S S I O N *********************************************************
// *************************************************************************************************************************************************************
public ICommand Reload
{
get
{
if(reloadCommand==null)
{
reloadCommand=new RelayCommand(param => this.ReloadCommand(),param =>
{
return ReloadEnabled;
});
}
return reloadCommand;
}
}
public bool ReloadEnabled
{
get
{
return !String.IsNullOrEmpty(pathFileName);
}
}
public ICommand LoadFile
{
get
{
if (loadFileCommand == null)
{
loadFileCommand = new RelayCommand(param => this.LoadFileCommand(), param => { return true; });
}
return loadFileCommand;
}
}
public ICommand Monitor
{
get
{
if (monitorCommand == null)
{
monitorCommand = new RelayCommand(param => this.MonitorCommand(), param => { return IsTradeFileLoaded; });
}
return monitorCommand;
}
}
private bool IsTradeFileLoaded
{
get{return null==pathFileName?false:true;}
}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S ********************************************************
// *************************************************************************************************************************************************************
public void DisplayBollingerBandCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,360");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayAnalystRatingsCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayStochasticsCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StochasticsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayRelativeStrengthCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.RSIViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,60,SelectedRSIDayCount,3");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayMACDCommand()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MACDViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
public void DisplayBollingerBandCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayAnalystRatingsCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayStochasticsCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StochasticsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayRelativeStrengthCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.RSIViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,60,SelectedRSIDayCount,3");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayMACDCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MACDViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void DisplayPriceHistoryCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.PricingViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
// ***************************************************************************************************************************************************************************
// ********************************************************************* G E N E R A L W O R K E R S ***********************************************************************
// ***************************************************************************************************************************************************************************
public void DisplayMovingAverageCommand(String symbol)
{
SaveParameters saveParams=new SaveParameters();
saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.MovingAverageViewModel"));
saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", symbol));
saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", Constants.CONST_ALL));
saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", "360"));
saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", "true"));
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
public void AddToWatchListCommand(String symbol)
{
if (WatchListDA.IsInWatchList(symbol))
{
System.Windows.MessageBox.Show("'"+symbol+"' is already in watchlist","Info", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
if (!WatchListDA.AddToWatchList(symbol))
{
System.Windows.MessageBox.Show("Error adding '"+symbol+"' to watchlist","Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
}
else
{
System.Windows.MessageBox.Show("Added '"+symbol+"'","Success", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
public void RemoveFromWatchListCommand(String symbol)
{
if (!WatchListDA.IsInWatchList(symbol))
{
System.Windows.MessageBox.Show("'"+symbol+"' is not in watchlist","Info", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
if (!WatchListDA.RemoveFromWatchList(symbol))
{
System.Windows.MessageBox.Show("Error removing '"+symbol+"' from watchlist","Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
}
else
{
System.Windows.MessageBox.Show("Removed '"+symbol+"'","Success", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
public void ClosePositionCommand(MGPositionModel selectedPosition)
{
Position clonedPosition=Position.Clone(selectedPosition.Position);
IPurePosition changedPosition=ClosePositionDialogNoStop.Prompt("Close Position",clonedPosition);
if(null==changedPosition) return;
MomentumBacktest momentumModel = new MomentumBacktest();
if (!momentumModel.ClosePosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.SellDate, changedPosition.CurrentPrice, pathFileName))
{
MessageBox.Show("Failed to close the position, check log for details.", "Close Position");
return;
}
String strMessage = String.Format("Closed position for {0}, Purchase Date:{1}, Sell Date{2}, Current Price:{3}. Saved to {4}. A backup was created.",
changedPosition.Symbol,
changedPosition.PurchaseDate.ToShortDateString(),
changedPosition.SellDate.ToShortDateString(),
Utility.FormatCurrency(changedPosition.CurrentPrice),
pathFileName);
MessageBox.Show(strMessage, "Close Position");
LoadSessionFile();
}
public void EditPositionCommand(MGPositionModel selectedPosition)
{
Position clonedPosition=Position.Clone(selectedPosition.Position);
IPurePosition changedPosition=EditPositionDialogNoStop.Prompt("Edit Position",clonedPosition);
if(null==changedPosition) return;
MomentumBacktest momentumModel = new MomentumBacktest();
if (!momentumModel.EditPosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.PurchasePrice, pathFileName))
{
MessageBox.Show("Failed to edit the position, check log for details.", "Edit Position");
return;
}
selectedPosition.PurchaseDate = changedPosition.PurchaseDate;
selectedPosition.PurchasePrice = changedPosition.PurchasePrice;
String strMessage = String.Format("Edited Position for {0} Purchase Date:{1} Purchase Price:{2}. A backup was created.",
selectedPosition.Symbol,
selectedPosition.PurchaseDate.ToShortDateString(),
Utility.FormatCurrency(selectedPosition.PurchasePrice));
MessageBox.Show(strMessage, "Edit Position");
LoadSessionFile();
}
// **************************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S S E S S I O N ********************************************************
// ***************************************************************************************************************************************************************************
public void MonitorCommand()
{
if(monitorRunning)StopMonitor();
else StartMonitor();
}
private void StopMonitor()
{
if(!monitorRunning)return;
dispatcherTimer.Stop();
monitorRunning=false;
base.OnPropertyChanged("MonitorStatus");
}
private void StartMonitor()
{
if(monitorRunning)return;
dispatcherTimer.Start();
monitorRunning=true;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => { DispatcherTimerTick(null,null); }), DispatcherPriority.Normal);
DispatcherTimerTick(null,null);
base.OnPropertyChanged("MonitorStatus");
}
private void DispatcherTimerTick(object sender, EventArgs e)
{
UpdatePositionPrices(false);
UpdatePositionRSI3(true);
RunPerformance();
}
private void UpdatePositionPrices(bool change=true)
{
try
{
DateTime today=DateTime.Now;
if(null==positions||0==positions.Count)return;
List<String> symbols=(from MGPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList();
foreach(String symbol in symbols)
{
var selectedPositions=(from MGPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position);
foreach(MGPositionModel selectedPosition in selectedPositions)
{
Price price=PricingDA.GetPrice(symbol);
if(null==price)continue;
selectedPosition.CurrentPrice=price.Close;
selectedPosition.Volume=price.Volume;
selectedPosition.LastUpdated=price.Date.Date<today.Date?price.Date:today;
}
}
if(change) positions.OnCollectionChanged();
}
catch(Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
}
}
private void UpdatePositionRSI3(bool change=true)
{
try
{
if(null==positions||0==positions.Count)return;
List<String> symbols=(from MGPositionModel position in positions where position.IsActivePosition select position.Symbol).Distinct().ToList();
foreach(String symbol in symbols)
{
var selectedPositions=(from MGPositionModel position in positions where position.IsActivePosition && position.Symbol.Equals(symbol) select position);
foreach(MGPositionModel selectedPosition in selectedPositions)
{
RSICollection rsiCollection=RSIGenerator.GenerateRSI(symbol,30,3);
if(null==rsiCollection||0==rsiCollection.Count)continue;
selectedPosition.RSI3=rsiCollection[rsiCollection.Count-1].RSI;
}
}
if(change)positions.OnCollectionChanged();
}
catch(Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
}
}
public void ReloadCommand()
{
LoadSessionFile();
}
public void LoadFileCommand()
{
Forms.OpenFileDialog openFileDialog=new Forms.OpenFileDialog();
openFileDialog.Filter="text file (*.txt)|*.txt";
openFileDialog.FilterIndex=0;
openFileDialog.RestoreDirectory=false;
if(null!=initialPath)openFileDialog.InitialDirectory=initialPath;
else openFileDialog.InitialDirectory=Directory.GetCurrentDirectory();
if(!Forms.DialogResult.OK.Equals(openFileDialog.ShowDialog()))return;
pathFileName=openFileDialog.FileName;
if(!MGSessionManager.IsValidSessionFile(pathFileName))
{
MessageBox.Show(String.Format("Invalid session file '{0}'",pathFileName));
pathFileName=null;
}
else LoadSessionFile();
}
public bool LoadSessionFile()
{
BusyIndicator = true;
BusyContent = $"Loading {Utility.GetFileNameNoExtension(pathFileName)}...";
Task workerTask = Task.Factory.StartNew(() =>
{
try
{
if(!MGSessionManager.IsValidSessionFile(pathFileName))
{
MessageBox.Show(String.Format("'{0}' is not a valid model. IsValidSessionFile returned false.",pathFileName));
pathFileName = null;
return false;
}
initialPath=Path.GetDirectoryName(pathFileName);
sessionParams=MGSessionManager.RestoreSession(pathFileName);
if(null==sessionParams)
{
MessageBox.Show(String.Format("Unable to open '{0}'. Restore session failed.",pathFileName));
pathFileName=null;
return false;
}
modelStatistics=MomentumBacktest.GetModelStatistics(sessionParams);
modelPerformanceSeries=MomentumBacktest.GetModelPerformance(sessionParams);
configuration=sessionParams.Configuration;
NVPCollection nvpCollection=sessionParams.Configuration.ToNVPCollection();
nvpDictionary=nvpCollection.ToDictionary();
List<String> dictionaryKeys=new List<String>(nvpDictionary.Keys);
dictionaryKeys.Sort();
nvpDictionaryKeys=new ObservableCollection<String>(dictionaryKeys);
selectedParameter=nvpDictionaryKeys[0];
positions=new MGPositionModelCollection();
positions.Add(sessionParams.ActivePositions);
positions.Add(sessionParams.AllPositions);
UpdatePositionPrices(false);
UpdatePositionRSI3(true);
RunPerformance();
return true;
}
catch(Exception exception)
{
System.Windows.MessageBox.Show(String.Format("Exception {0}",exception.ToString()),"Error",MessageBoxButton.OK,MessageBoxImage.Exclamation);
return false;
}
});
workerTask.ContinueWith(continuation =>
{
BusyIndicator=false;
base.OnPropertyChanged("Parameters");
base.OnPropertyChanged("SelectedParameter");
base.OnPropertyChanged("ParameterValue");
base.OnPropertyChanged("Title");
base.OnPropertyChanged("DisplayName");
base.OnPropertyChanged("AllPositions");
base.OnPropertyChanged("CanMonitor");
base.OnPropertyChanged("CashBalance");
base.OnPropertyChanged("NonTradeableCash");
base.OnPropertyChanged("ModelExpectation");
base.OnPropertyChanged("ExpectationColor");
base.OnPropertyChanged("ExpectationDescription");
});
return true;
}
private void RunPerformance()
{
if(null==sessionParams)return;
modelPerformanceSeries=MomentumBacktest.GetModelPerformance(sessionParams);
base.OnPropertyChanged("Data");
base.OnPropertyChanged("GraphTitle");
}
// **************************************************************************** C H A R T P L O T T E R *********************************************************
public String LegendVisible
{
get
{
if(isLegendVisible) return "true";
return "false";
}
set
{
isLegendVisible=Boolean.Parse(value);
base.OnPropertyChanged("LegendVisible");
}
}
public String PercentButtonText
{
get
{
if(!showAsGainLoss) return "Show $";
else return "Show %";
}
}
public ICommand ToggleReturnOrPercentCommand
{
get
{
if(toggleReturnOrPercentCommand==null)
{
toggleReturnOrPercentCommand=new RelayCommand(action =>
{
showAsGainLoss=!showAsGainLoss;
base.OnPropertyChanged("Data");
base.OnPropertyChanged("PercentButtonText");
base.OnPropertyChanged("GraphTitle");
},action => { return true; });
}
return toggleReturnOrPercentCommand;
}
}
public CompositeDataSource Data
{
get
{
if(null==modelPerformanceSeries) return null;
CompositeDataSource compositeDataSource=null;
compositeDataSource=GainLossModel.GainLoss(modelPerformanceSeries,showAsGainLoss);
return compositeDataSource;
}
}
public String GraphTitle
{
get
{
if(null==sessionParams||null==modelPerformanceSeries) return "";
StringBuilder sb=new StringBuilder();
Positions allPositions=sessionParams.GetCombinedPositions();
DateTime minDate=allPositions.Min(x => x.PurchaseDate);
DateTime maxDate=PricingDA.GetLatestDate();
if(modelPerformanceSeries.Count<2)
{
sb.Append(showAsGainLoss?"$ GainLoss":"% Return");
sb.Append(" ");
sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
sb.Append(showAsGainLoss?Utility.FormatCurrency(modelPerformanceSeries[modelPerformanceSeries.Count-1].CumulativeGainLoss):Utility.FormatPercent(modelPerformanceSeries[modelPerformanceSeries.Count-1].CumProdMinusOne));
return sb.ToString();
}
if(showAsGainLoss)
{
double latestGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-1].CumulativeGainLoss;
double change=modelPerformanceSeries[modelPerformanceSeries.Count-1].GainLossDOD;
sb.Append("$ GainLoss");
sb.Append(" ");
sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
sb.Append(" ");
sb.Append(Utility.FormatCurrency(latestGainLoss));
sb.Append(",");
sb.Append(" ");
sb.Append(change>0.00?"+":"").Append(Utility.FormatCurrency(change));
}
else
{
double latestCumGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-1].CumProdMinusOne;
double prevCumGainLoss=modelPerformanceSeries[modelPerformanceSeries.Count-2].CumProdMinusOne;
double change=latestCumGainLoss-prevCumGainLoss;
sb.Append("% Return");
sb.Append(" ");
sb.Append("(").Append(minDate.ToShortDateString()).Append("-").Append(maxDate.ToShortDateString()).Append(")");
sb.Append(" ");
sb.Append(Utility.FormatPercent(latestCumGainLoss));
sb.Append(",");
sb.Append(" ");
sb.Append(change>0.00?"+":"").Append(Utility.FormatPercent(change));
}
return sb.ToString();
}
}
}
}