Files
TradeBlotter/ViewModels/BlotterViewModel.cs

381 lines
13 KiB
C#

using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Windows;
using System.Linq;
using System.Text;
using MarketData;
using MarketData.Utils;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.UIUtils;
using TradeBlotter.Cache;
using System.Windows.Forms;
using MarketData.MarketDataModel;
using TradeBlotter.Model;
using MarketData.Cache;
namespace TradeBlotter.ViewModels
{
public delegate void EditHandler(int tradeId); // so we can post the event back up to the main window
public delegate void DeleteHandler(int tradeId); // so we can post the event back up to the main window
public class BlotterViewModel : WorkspaceViewModel
{
private static readonly String LOADING_TRADES = "Loading Trades...";
private static readonly String REFRESHING_PRICES = "Refreshing Prices...";
private readonly TradeRepository tradeRepository;
private PortfolioTrades portfolioTrades;
double annualYieldAmt=double.NaN;
double annualYieldPcnt=double.NaN;
private RelayCommand refreshCommand;
private RelayCommand deleteCommand;
private RelayCommand editCommand;
private EditHandler editHandler;
private DeleteHandler deleteHandler;
private TradeViewModel selectedItem = null;
private bool busyIndicator = false;
private String busyContent = LOADING_TRADES;
private bool gridChanged = false;
public BlotterViewModel(TradeRepository tradeRepository,EditHandler editHandler,DeleteHandler deleteHandler)
{
this.editHandler = editHandler;
this.deleteHandler = deleteHandler;
base.DisplayName = "TradeView";
this.tradeRepository = tradeRepository;
this.CreateAllTrades();
tradeRepository.TradeAdded += this.OnTradeAddedToRepository;
}
public override SaveParameters GetSaveParameters()
{
return null;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
}
public override bool CanPersist()
{
return false;
}
protected override void OnDispose()
{
}
public ObservableCollection<TradeViewModel> AllTrades
{
get; private set;
}
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 TradeViewModel SelectedItem
{
get
{
return selectedItem;
}
set
{
selectedItem = value;
foreach (TradeViewModel tvm in this.AllTrades)
{
tvm.IsSelected = false;
}
if (null != selectedItem) selectedItem.IsSelected = true;
}
}
private void CreateAllTrades()
{
BusyIndicator = true;
Task workerTask=Task.Factory.StartNew(() =>
{
LoadPortfolioTrades();
List<BlotterTradeModel> repositoryTrades=tradeRepository.GetTrades();
repositoryTrades=repositoryTrades.OrderByDescending(x=>x.TradeDate).ThenBy(x=>x.TradeId).ToList();
List<TradeViewModel> all = (from trade in repositoryTrades select new TradeViewModel(trade, tradeRepository)).ToList();
double totalMarketValue = 0;
foreach (TradeViewModel tradeViewModel in all)
{
if (!tradeViewModel.IsOpen) continue;
totalMarketValue += Utility.ParseCurrency(tradeViewModel.MarketValue);
}
foreach (TradeViewModel tradeViewModel in all)
{
tradeViewModel.Weight = Utility.FormatPercent(Utility.ParseCurrency(tradeViewModel.MarketValue) / totalMarketValue);
tradeViewModel.PropertyChanged += this.OnTradeViewModelPropertyChanged;
}
this.AllTrades = new ObservableCollection<TradeViewModel>(all);
this.AllTrades.CollectionChanged += this.OnCollectionChanged;
});
workerTask.ContinueWith((continuation) =>
{
BusyIndicator = false;
base.OnPropertyChanged("AllTrades");
base.OnPropertyChanged("TotalExposure");
base.OnPropertyChanged("TotalMarketValue");
base.OnPropertyChanged("TotalGainLoss");
base.OnPropertyChanged("TotalReturn");
base.OnPropertyChanged("TotalGainLossAll");
base.OnPropertyChanged("TotalReturnAll");
base.OnPropertyChanged("AnnualDividendYieldAmt");
base.OnPropertyChanged("AnnualDividendYieldPcnt");
});
}
public void LoadPortfolioTrades()
{
portfolioTrades=PortfolioDA.GetOpenTrades();
double weightAdjustedDividendYield=portfolioTrades.GetWeightAdjustedDividendYield();
double exposure=portfolioTrades.Exposure();
annualYieldAmt=weightAdjustedDividendYield*exposure;
annualYieldPcnt=weightAdjustedDividendYield;
}
public String TotalExposure
{
get
{
if (null == this.AllTrades) return null;
var openTrades = from trade in this.AllTrades where trade.IsOpen select trade;
return Utility.FormatCurrency(openTrades.Sum(trade => Utility.ParseCurrency(trade.Exposure)));
}
}
public String TotalMarketValue
{
get
{
if (null == this.AllTrades) return null;
var openTrades = from trade in this.AllTrades where trade.IsOpen select trade;
return Utility.FormatCurrency(openTrades.Sum(trade => Utility.ParseCurrency(trade.MarketValue)));
}
}
public String TotalGainLoss
{
get
{
if (null == this.AllTrades) return null;
var openTrades = from trade in this.AllTrades where trade.IsOpen select trade;
return Utility.FormatCurrency(openTrades.Sum(trade => Utility.ParseCurrency(trade.MarketValue) - Utility.ParseCurrency(trade.Exposure)));
}
}
public String TotalReturn
{
get
{
if (null == this.AllTrades) return null;
var openTrades = from trade in this.AllTrades where trade.IsOpen select trade;
double totalExposure = openTrades.Sum(trade => trade.Price * trade.Shares);
double totalMarketValue = openTrades.Sum(trade => Utility.ParseCurrency(trade.CurrentPrice) * trade.Shares);
return Utility.FormatPercent((totalMarketValue-totalExposure)/totalExposure);
}
}
public String TotalGainLossAll
{
get
{
if (null == this.AllTrades) return null;
var allTrades = from trade in this.AllTrades select trade;
double totalExposure = allTrades.Sum(trade => trade.Price * trade.Shares);
double totalMarketValue = allTrades.Sum(trade => Utility.ParseCurrency((trade.IsOpen ? trade.CurrentPrice : trade.SellPrice)) * trade.Shares);
return Utility.FormatCurrency(totalMarketValue - totalExposure);
}
}
public String TotalReturnAll
{
get
{
if (null == this.AllTrades) return null;
var allTrades = from trade in this.AllTrades select trade;
double totalExposure = allTrades.Sum(trade => trade.Price * trade.Shares);
double totalMarketValue = allTrades.Sum(trade => Utility.ParseCurrency((trade.IsOpen?trade.CurrentPrice:trade.SellPrice))* trade.Shares);
return Utility.FormatPercent((totalMarketValue - totalExposure) / totalExposure);
}
}
public String AnnualDividendYieldPcnt
{
get
{
return Utility.FormatPercent(annualYieldPcnt);
}
}
public String AnnualDividendYieldAmt
{
get
{
return Utility.FormatCurrency(annualYieldAmt);
}
}
private void OnTradeAddedToRepository(Object sender, TradeAddedEventArgs e)
{
var viewModel = new TradeViewModel(e.NewTrade, tradeRepository);
this.AllTrades.Add(viewModel);
}
private void OnTradeViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (TradeViewModel tradeVM in e.NewItems)
tradeVM.PropertyChanged += this.OnTradeViewModelPropertyChanged;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (TradeViewModel tradeVM in e.OldItems)
tradeVM.PropertyChanged -= this.OnTradeViewModelPropertyChanged;
}
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)return "No description found.";
return companyProfile.Description;
}
}
// **************************************************************************************************************************
// ******************************************************** R E F R E S H ***************************************************
// **************************************************************************************************************************
public bool GridChanged
{
get { return gridChanged; }
set { gridChanged = value; base.OnPropertyChanged("GridChanged"); }
}
private void Refresh()
{
BusyContent = REFRESHING_PRICES;
BusyIndicator = true;
Dispatcher uiDispatcher = Dispatcher.CurrentDispatcher; // get the UI dispatcher
Task workerTask = Task.Factory.StartNew(() =>
{
GBPriceCache.GetInstance().Clear();
foreach (TradeViewModel tvm in this.AllTrades)
{
tvm.Invalidate();
}
});
workerTask.ContinueWith((continuation) =>
{
BusyIndicator = false;
BusyContent = LOADING_TRADES;
uiDispatcher.Invoke((MethodInvoker)delegate()
{
foreach (TradeViewModel tvm in this.AllTrades)
{
tvm.Validate();
}
});
base.OnPropertyChanged("TotalMarketValue");
base.OnPropertyChanged("TotalGainLoss");
base.OnPropertyChanged("TotalReturn");
GridChanged = !GridChanged;
});
}
private bool CanRefresh
{
get { return true; }
}
public ICommand RefreshCommand
{
get
{
if (refreshCommand == null)
{
refreshCommand = new RelayCommand(param => this.Refresh(), param => this.CanRefresh);
}
return refreshCommand;
}
}
// **************************************************************************************************************************
// ******************************************************** E D I T ***************************************************
// **************************************************************************************************************************
private void Edit()
{
TradeViewModel tvmSelected = null;
foreach (TradeViewModel tvm in this.AllTrades)
{
if (tvm.IsSelected) tvmSelected = tvm;
}
if (null == tvmSelected || null==editHandler) return;
editHandler(tvmSelected.TradeId);
}
private bool CanEdit
{
get
{
return selectedItem == null ? false : true;
}
}
public ICommand EditCommand
{
get
{
if (editCommand == null)
{
editCommand = new RelayCommand(param => this.Edit(), param => this.CanEdit);
}
return editCommand;
}
}
// **************************************************************************************************************************
// ******************************************************** D E L E T E ***************************************************
// **************************************************************************************************************************
private void Delete()
{
TradeViewModel tvmToRemove=null;
foreach (TradeViewModel tvm in this.AllTrades)
{
if (tvm.IsSelected) { tvmToRemove = tvm; break; }
}
if (null == tvmToRemove) return;
string messageBoxText = "This operation cannot be undone, confirm delete trade_id("+tvmToRemove.TradeId+")";
string caption = "eNavigator";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;
if(MessageBoxResult.Yes!=System.Windows.MessageBox.Show(messageBoxText, caption, button, icon))return;
tradeRepository.Remove(tvmToRemove.TradeId);
this.AllTrades.Remove(tvmToRemove);
base.OnPropertyChanged("TotalMarketValue");
base.OnPropertyChanged("TotalGainLoss");
base.OnPropertyChanged("TotalReturn");
if (null != deleteHandler) deleteHandler(tvmToRemove.TradeId);
}
private bool CanDelete
{
get { return true; }
}
public ICommand DeleteCommand
{
get
{
if (deleteCommand == null)
{
deleteCommand = new RelayCommand(param => this.Delete(), param => this.CanDelete);
}
return deleteCommand;
}
}
}
}