Init
This commit is contained in:
413
ViewModels/RiskProfileViewModel.cs
Normal file
413
ViewModels/RiskProfileViewModel.cs
Normal file
@@ -0,0 +1,413 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.MarketDataModel;
|
||||
using TradeBlotter.Command;
|
||||
using TradeBlotter.Cache;
|
||||
using TradeBlotter.Model;
|
||||
using Telerik.Charting;
|
||||
using Telerik.Windows.Controls.Charting;
|
||||
using MarketData;
|
||||
using MarketData.ValueAtRisk;
|
||||
using MarketData.Utils;
|
||||
using System.Windows.Controls;
|
||||
using TradeBlotter.UIUtils;
|
||||
|
||||
namespace TradeBlotter.ViewModels
|
||||
{
|
||||
public class CategoricalDataPointWithDesc : CategoricalDataPoint
|
||||
{
|
||||
public String CustomLabel { get; set; }
|
||||
}
|
||||
|
||||
public class RiskProfileViewModel : WorkspaceViewModel
|
||||
{
|
||||
private PortfolioTrades portfolioTrades = null;
|
||||
private List<CategoricalDataPointWithDesc> betaContributionDataPoints = null;
|
||||
private List<CategoricalDataPointWithDesc> betaDataPoints = null;
|
||||
private PortfolioHoldingsWithBeta portfolioHoldingsWithBeta = null;
|
||||
|
||||
private List<CategoricalDataPointWithDesc> sharpeRatioContributionDataPoints = null;
|
||||
private List<CategoricalDataPointWithDesc> sharpeRatioSharpeRatioDataPoints = null;
|
||||
private PortfolioHoldingsWithSharpeRatio portfolioHoldingsWithSharpeRatio = null;
|
||||
|
||||
// Command Targets
|
||||
private RelayCommand resetCommand;
|
||||
private RelayCommand proformaAddPositionCommand;
|
||||
private RelayCommand chooseDateCommand;
|
||||
private RelayCommand chooseDateLostFocusCommand;
|
||||
|
||||
private String selectedAccount = Constants.CONST_ALL;
|
||||
private bool busyIndicator = false;
|
||||
|
||||
private List<DateTime> openTradeDates;
|
||||
private List<CalendarDateRange> blackoutDates;
|
||||
private DateTime selectedDate;
|
||||
private DateTime displayDate;
|
||||
private bool isCalendarOpen = false;
|
||||
|
||||
public RiskProfileViewModel()
|
||||
{
|
||||
base.DisplayName = "Risk Profile";
|
||||
BusyIndicator = true;
|
||||
portfolioTrades = PortfolioDA.GetTrades();
|
||||
openTradeDates = PortfolioTrades.GetOpenTradeDates();
|
||||
GetBlackoutDates();
|
||||
selectedDate = openTradeDates[0];
|
||||
displayDate = selectedDate;
|
||||
PropertyChanged += OnViewModelPropertyChanged;
|
||||
SelectedAccount = Constants.CONST_ALL;
|
||||
BusyIndicator = false;
|
||||
}
|
||||
private void GetBlackoutDates()
|
||||
{
|
||||
DateGenerator dateGenerator = new DateGenerator();
|
||||
blackoutDates=new List<CalendarDateRange>();
|
||||
Dictionary<DateTime,DateTime> openTradeDatesDict = new Dictionary<DateTime, DateTime>();
|
||||
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDatesActual(openTradeDates[0], openTradeDates[openTradeDates.Count - 1]);
|
||||
foreach(DateTime openTradeDate in openTradeDates)if(!openTradeDatesDict.ContainsKey(openTradeDate))openTradeDatesDict.Add(openTradeDate,openTradeDate);
|
||||
foreach(DateTime historicalDate in historicalDates)if(!openTradeDatesDict.ContainsKey(historicalDate))blackoutDates.Add(new CalendarDateRange(historicalDate,historicalDate));
|
||||
}
|
||||
public override SaveParameters GetSaveParameters()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override void SetSaveParameters(SaveParameters saveParameters)
|
||||
{
|
||||
}
|
||||
public override String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Constants.CONST_ALL.Equals(selectedAccount)) return base.DisplayName + " - " + selectedAccount;
|
||||
return base.DisplayName;
|
||||
}
|
||||
}
|
||||
public override bool CanPersist()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
protected override void OnDispose()
|
||||
{
|
||||
}
|
||||
public bool BusyIndicator
|
||||
{
|
||||
get
|
||||
{
|
||||
return busyIndicator;
|
||||
}
|
||||
set
|
||||
{
|
||||
busyIndicator = value;
|
||||
base.OnPropertyChanged("BusyIndicator");
|
||||
}
|
||||
}
|
||||
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.PropertyName.Equals("SelectedAccount") || eventArgs.PropertyName.Equals("Accounts"))
|
||||
{
|
||||
BusyIndicator = true;
|
||||
Task workerTask = Task.Factory.StartNew(() =>
|
||||
{
|
||||
portfolioTrades = PortfolioDA.GetOpenTradesAsOf(selectedDate);
|
||||
portfolioTrades = portfolioTrades.RemoveClosedTradesWhereClosedOn(selectedDate);
|
||||
CreateBetaContribution(portfolioTrades,selectedDate);
|
||||
CreateSharpeRatioContribution(portfolioTrades,selectedDate);
|
||||
});
|
||||
workerTask.ContinueWith((continuation) =>
|
||||
{
|
||||
BusyIndicator = false;
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioSharpeRatio");
|
||||
base.OnPropertyChanged("CartesianChartDataBetaContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataBeta");
|
||||
base.OnPropertyChanged("TitleBetaContribution");
|
||||
base.OnPropertyChanged("TitleSharpeRationContribution");
|
||||
base.OnPropertyChanged("BetaDescription");
|
||||
});
|
||||
}
|
||||
else if (eventArgs.PropertyName.Equals("SelectedDate"))
|
||||
{
|
||||
BusyIndicator = true;
|
||||
Task workerTask = Task.Factory.StartNew(() =>
|
||||
{
|
||||
portfolioTrades = PortfolioDA.GetOpenTradesAsOf(selectedDate);
|
||||
portfolioTrades = portfolioTrades.RemoveClosedTradesWhereClosedOn(selectedDate);
|
||||
CreateBetaContribution(portfolioTrades, selectedDate);
|
||||
CreateSharpeRatioContribution(portfolioTrades, selectedDate);
|
||||
});
|
||||
workerTask.ContinueWith((continuation) =>
|
||||
{
|
||||
BusyIndicator = false;
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioSharpeRatio");
|
||||
base.OnPropertyChanged("CartesianChartDataBetaContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataBeta");
|
||||
base.OnPropertyChanged("TitleBetaContribution");
|
||||
base.OnPropertyChanged("TitleSharpeRationContribution");
|
||||
base.OnPropertyChanged("BetaDescription");
|
||||
});
|
||||
}
|
||||
}
|
||||
private void CreateBetaContribution(PortfolioTrades portfolioTrades, DateTime analysisDate)
|
||||
{
|
||||
PortfolioTrades accountTrades = GetAccountTrades();
|
||||
PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(accountTrades, 5, analysisDate);
|
||||
|
||||
betaContributionDataPoints = new List<CategoricalDataPointWithDesc>();
|
||||
betaDataPoints = new List<CategoricalDataPointWithDesc>();
|
||||
|
||||
portfolioHoldingsWithBeta = new PortfolioHoldingsWithBeta(portfolioHoldings, analysisDate);
|
||||
portfolioHoldingsWithBeta = new PortfolioHoldingsWithBeta((from PortfolioHoldingWithBeta portfolioHoldingWithBeta in portfolioHoldingsWithBeta select portfolioHoldingWithBeta).OrderByDescending(x => x.BetaContribution).ToList());
|
||||
foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in portfolioHoldingsWithBeta)
|
||||
{
|
||||
CategoricalDataPointWithDesc categoricalDataPoint = new CategoricalDataPointWithDesc();
|
||||
categoricalDataPoint.Category = portfolioHoldingWithBeta.Symbol;
|
||||
categoricalDataPoint.Value = double.IsNaN(portfolioHoldingWithBeta.BetaContribution)?double.NaN:double.Parse(Utility.FormatNumber(portfolioHoldingWithBeta.BetaContribution*100, 2));
|
||||
categoricalDataPoint.CustomLabel = "cR=" + Utility.FormatPercent(portfolioHoldingWithBeta.BetaContribution);
|
||||
betaContributionDataPoints.Add(categoricalDataPoint);
|
||||
}
|
||||
foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in portfolioHoldingsWithBeta)
|
||||
{
|
||||
CategoricalDataPointWithDesc categoricalDataPoint = new CategoricalDataPointWithDesc();
|
||||
categoricalDataPoint.Category = portfolioHoldingWithBeta.Symbol;
|
||||
categoricalDataPoint.Value = double.IsNaN(portfolioHoldingWithBeta.Beta) ? double.NaN : double.Parse(Utility.FormatNumber(portfolioHoldingWithBeta.Beta * 100.00, 2));
|
||||
categoricalDataPoint.CustomLabel = "b="+Utility.FormatNumber(portfolioHoldingWithBeta.Beta,2);
|
||||
betaDataPoints.Add(categoricalDataPoint);
|
||||
}
|
||||
}
|
||||
private void CreateSharpeRatioContribution(PortfolioTrades portfolioTrades,DateTime analysisDate)
|
||||
{
|
||||
PortfolioTrades accountTrades = GetAccountTrades();
|
||||
PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(accountTrades, 5, analysisDate);
|
||||
sharpeRatioContributionDataPoints = new List<CategoricalDataPointWithDesc>();
|
||||
sharpeRatioSharpeRatioDataPoints = new List<CategoricalDataPointWithDesc>();
|
||||
portfolioHoldingsWithSharpeRatio = new PortfolioHoldingsWithSharpeRatio(portfolioHoldings,analysisDate);
|
||||
portfolioHoldingsWithSharpeRatio = new PortfolioHoldingsWithSharpeRatio((from PortfolioHoldingWithSharpeRatio portfolioHoldingWithSharpeRatio in portfolioHoldingsWithSharpeRatio select portfolioHoldingWithSharpeRatio).OrderByDescending(x => x.SharpeRatioContribution).ToList());
|
||||
foreach (PortfolioHoldingWithSharpeRatio portfolioHoldingWithSharpeRatio in portfolioHoldingsWithSharpeRatio)
|
||||
{
|
||||
CategoricalDataPointWithDesc categoricalDataPoint = new CategoricalDataPointWithDesc();
|
||||
categoricalDataPoint.Category = portfolioHoldingWithSharpeRatio.Symbol;
|
||||
categoricalDataPoint.Value = double.IsNaN(portfolioHoldingWithSharpeRatio.SharpeRatioContribution)?double.NaN:double.Parse(Utility.FormatNumber(portfolioHoldingWithSharpeRatio.SharpeRatioContribution*100, 2));
|
||||
categoricalDataPoint.CustomLabel = "cR=" + Utility.FormatPercent(portfolioHoldingWithSharpeRatio.SharpeRatioContribution);
|
||||
sharpeRatioContributionDataPoints.Add(categoricalDataPoint);
|
||||
}
|
||||
foreach (PortfolioHoldingWithSharpeRatio portfolioHoldingWithSharpeRatio in portfolioHoldingsWithSharpeRatio)
|
||||
{
|
||||
CategoricalDataPointWithDesc categoricalDataPoint = new CategoricalDataPointWithDesc();
|
||||
categoricalDataPoint.Category = portfolioHoldingWithSharpeRatio.Symbol;
|
||||
categoricalDataPoint.Value = double.IsNaN(portfolioHoldingWithSharpeRatio.SharpeRatio) ? double.NaN : double.Parse(Utility.FormatNumber(portfolioHoldingWithSharpeRatio.SharpeRatio * 100.00, 2));
|
||||
categoricalDataPoint.CustomLabel = "sR="+Utility.FormatNumber(portfolioHoldingWithSharpeRatio.SharpeRatio,2);
|
||||
sharpeRatioSharpeRatioDataPoints.Add(categoricalDataPoint);
|
||||
}
|
||||
}
|
||||
public PortfolioTrades GetAccountTrades()
|
||||
{
|
||||
if (Constants.CONST_ALL.Equals(selectedAccount)) return portfolioTrades;
|
||||
return portfolioTrades.FilterAccount(selectedAccount);
|
||||
}
|
||||
// ***************************************************************************************************************************************************
|
||||
// ************************************************************* C H A R T I N G C O L L E C T I O N S *********************************************
|
||||
// ***************************************************************************************************************************************************
|
||||
public ObservableCollection<CategoricalDataPoint> CartesianChartDataBetaContribution
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == betaContributionDataPoints) return null;
|
||||
return new ObservableCollection<CategoricalDataPoint>(betaContributionDataPoints);
|
||||
}
|
||||
}
|
||||
public ObservableCollection<CategoricalDataPoint> CartesianChartDataBeta
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == betaDataPoints) return null;
|
||||
return new ObservableCollection<CategoricalDataPoint>(betaDataPoints);
|
||||
}
|
||||
}
|
||||
public ObservableCollection<CategoricalDataPoint> CartesianChartDataSharpeRatioContribution
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == sharpeRatioContributionDataPoints) return null;
|
||||
return new ObservableCollection<CategoricalDataPoint>(sharpeRatioContributionDataPoints);
|
||||
}
|
||||
}
|
||||
public ObservableCollection<CategoricalDataPoint> CartesianChartDataSharpeRatioSharpeRatio
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == sharpeRatioSharpeRatioDataPoints) return null;
|
||||
return new ObservableCollection<CategoricalDataPoint>(sharpeRatioSharpeRatioDataPoints);
|
||||
}
|
||||
}
|
||||
public List<String> Accounts
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == portfolioTrades)
|
||||
{
|
||||
portfolioTrades = PortfolioDA.GetOpenTradesAsOf(selectedDate);
|
||||
portfolioTrades = portfolioTrades.RemoveClosedTradesWhereClosedOn(selectedDate);
|
||||
}
|
||||
List<String> accounts = portfolioTrades.Accounts;
|
||||
accounts.Insert(0, Constants.CONST_ALL);
|
||||
return accounts;
|
||||
}
|
||||
}
|
||||
public String TitleBetaContribution
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("Beta Contribution - ");
|
||||
sb.Append(String.Format("{0}",selectedDate.ToShortDateString())).Append(" ");
|
||||
if (Constants.CONST_ALL.Equals(selectedAccount)) sb.Append("All Accounts ");
|
||||
else sb.Append("Account ").Append(selectedAccount);
|
||||
sb.Append(" (beta=");
|
||||
if (null != portfolioHoldingsWithBeta) sb.Append(Utility.FormatNumber(portfolioHoldingsWithBeta.PortfolioBeta));
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
public String TitleSharpeRationContribution
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("Sharpe Ratio (Contribution to Risk Adjusted Return) - ");
|
||||
sb.Append(String.Format("{0}",selectedDate.ToShortDateString())).Append(" ");
|
||||
if (Constants.CONST_ALL.Equals(selectedAccount)) sb.Append("All Accounts ");
|
||||
else sb.Append("Account ").Append(selectedAccount);
|
||||
sb.Append(" (Sharpe Ratio=");
|
||||
if (null != portfolioHoldingsWithSharpeRatio) sb.Append(Utility.FormatNumber(portfolioHoldingsWithSharpeRatio.TotalSharpeRatio));
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
public String BetaDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == portfolioHoldingsWithBeta) return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("This portfolio is expected to rise or fall by a multiple of ").Append(Utility.FormatNumber(portfolioHoldingsWithBeta.PortfolioBeta,3));
|
||||
sb.Append(" or ").Append(Utility.FormatCurrency(.01 * portfolioHoldingsWithBeta.PortfolioBeta * portfolioHoldingsWithBeta.Exposure)).Append("");
|
||||
sb.Append(" for every 1% of market movement. ** weight / beta contribution / beta **");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
//*****************************************************************************************************************************************************************
|
||||
// ******************************************************************* I C O M M A N D **************************************************************************
|
||||
//*****************************************************************************************************************************************************************
|
||||
public ICommand ResetCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == resetCommand)
|
||||
{
|
||||
resetCommand = new RelayCommand(param =>
|
||||
{
|
||||
selectedDate = displayDate=openTradeDates[0];
|
||||
base.OnPropertyChanged("SelectedDate");
|
||||
base.OnPropertyChanged("DisplayDate");
|
||||
}, param => { return true; });
|
||||
}
|
||||
return resetCommand;
|
||||
}
|
||||
}
|
||||
public ICommand ChooseDateCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == chooseDateCommand)
|
||||
{
|
||||
chooseDateCommand = new RelayCommand(param =>
|
||||
{
|
||||
isCalendarOpen = !isCalendarOpen;
|
||||
base.OnPropertyChanged("IsCalendarOpen");
|
||||
}, param => { return true; });
|
||||
}
|
||||
return chooseDateCommand;
|
||||
}
|
||||
}
|
||||
public ICommand ProformaAddPositionCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == proformaAddPositionCommand)
|
||||
{
|
||||
proformaAddPositionCommand = new RelayCommand(param =>
|
||||
{
|
||||
portfolioTrades=ProformaAddPositionDialog.Prompt("Proforma Add Position", SelectedAccount, SelectedDate, portfolioTrades);
|
||||
CreateBetaContribution(portfolioTrades, selectedDate);
|
||||
CreateSharpeRatioContribution(portfolioTrades, selectedDate);
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataSharpeRatioSharpeRatio");
|
||||
base.OnPropertyChanged("CartesianChartDataBetaContribution");
|
||||
base.OnPropertyChanged("CartesianChartDataBeta");
|
||||
base.OnPropertyChanged("TitleBetaContribution");
|
||||
base.OnPropertyChanged("TitleSharpeRationContribution");
|
||||
base.OnPropertyChanged("BetaDescription");
|
||||
}, param => { return true; });
|
||||
}
|
||||
return proformaAddPositionCommand;
|
||||
}
|
||||
}
|
||||
//*****************************************************************************************************************************************************************
|
||||
// ************************************************************************** A C C O U N T *********************************************************************
|
||||
//*****************************************************************************************************************************************************************
|
||||
public String SelectedAccount
|
||||
{
|
||||
get { return selectedAccount; }
|
||||
set
|
||||
{
|
||||
selectedAccount = value;
|
||||
isCalendarOpen = false;
|
||||
base.OnPropertyChanged("IsCalendarOpen");
|
||||
base.OnPropertyChanged("SelectedAccount");
|
||||
}
|
||||
}
|
||||
//*****************************************************************************************************************************************************************
|
||||
// ******************************************************************* C A L E N D A R M A N A G E M E N T *****************************************************
|
||||
//*****************************************************************************************************************************************************************
|
||||
public bool IsCalendarOpen
|
||||
{
|
||||
get { return isCalendarOpen; }
|
||||
set { isCalendarOpen = value; base.OnPropertyChanged("IsCalendarOpen"); }
|
||||
}
|
||||
public DateTime SelectedDate
|
||||
{
|
||||
get{return selectedDate;}
|
||||
set { isCalendarOpen = false; selectedDate = value; displayDate = value; base.OnPropertyChanged("IsCalendarOpen"); base.OnPropertyChanged("DisplayDate"); base.OnPropertyChanged("SelectedDate"); }
|
||||
}
|
||||
public DateTime DisplayDateStart
|
||||
{
|
||||
get{return openTradeDates[openTradeDates.Count-1];}
|
||||
}
|
||||
public DateTime DisplayDateEnd
|
||||
{
|
||||
get{return openTradeDates[0];}
|
||||
}
|
||||
public DateTime DisplayDate
|
||||
{
|
||||
get { return displayDate; }
|
||||
set { displayDate = value;base.OnPropertyChanged("DisplayDate");}
|
||||
}
|
||||
public List<CalendarDateRange> BlackoutDates
|
||||
{
|
||||
get
|
||||
{
|
||||
return blackoutDates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user