Files
TradeBlotter/ViewModels/TradeEntryViewModel..cs

448 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using MarketData;
using MarketData.MarketDataModel;
using MarketData.Helper;
using MarketData.DataAccess;
using MarketData.Utils;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
namespace TradeBlotter.ViewModels
{
public class TradeEntryViewModel : WorkspaceViewModel
{
private BlotterTradeModel trade = null;
private StopLimit stopLimit;
private readonly TradeRepository tradeRepository;
private RelayCommand saveCommand;
private String statusText="";
public TradeEntryViewModel(BlotterTradeModel trade,TradeRepository tradeRepository)
{
base.DisplayName="TradeEntry";
this.trade=trade;
this.tradeRepository=tradeRepository;
if(PortfolioDA.HasStopLimit(trade.Symbol)) stopLimit=PortfolioDA.GetStopLimit(trade.Symbol);
PropertyChanged+=OnTradeEntryViewModelPropertyChanged;
UpdateProperties();
}
public override SaveParameters GetSaveParameters()
{
return null;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
}
public override bool CanPersist()
{
return false;
}
public void SetActiveTrade(BlotterTradeModel trade)
{
this.trade = trade;
UpdateProperties();
}
private void UpdateProperties()
{
base.OnPropertyChanged("Symbol");
base.OnPropertyChanged("Price");
base.OnPropertyChanged("CompanyName");
base.OnPropertyChanged("TradeDate");
base.OnPropertyChanged("SelectedTradeType");
base.OnPropertyChanged("SelectedAccount");
base.OnPropertyChanged("SelectedStatus");
base.OnPropertyChanged("TradeId");
base.OnPropertyChanged("Shares");
base.OnPropertyChanged("Exposure");
base.OnPropertyChanged("AvailableCash");
}
private void OnTradeEntryViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if (eventArgs.PropertyName.Equals("Symbol"))
{
if(null!=trade && null!=trade.Symbol)
{
if(-1==trade.TradeId) // only suggest the price for a new trade (i.e.) a trade that has not yet been assigned a tradeid
{
Price price=PricingDA.GetPrice(trade.Symbol,trade.TradeDate);
if(null==price) price=PricingDA.GetPrice(trade.Symbol);
if(null!=price)trade.Price=price.Close;
base.OnPropertyChanged("Price");
}
String companyName = PricingDA.GetNameForSymbol(trade.Symbol);
if (null != companyName)
{
trade.CompanyName = companyName;
base.OnPropertyChanged("CompanyName");
}
}
}
else if (eventArgs.PropertyName.Equals("TradeDate"))
{
base.OnPropertyChanged("Price");
}
else if (eventArgs.PropertyName.Equals("SelectedAccount") || eventArgs.PropertyName.Equals("Shares") || eventArgs.PropertyName.Equals("Price") || eventArgs.PropertyName.Equals("SellPrice"))
{
base.OnPropertyChanged("AvailableCash");
}
}
public String TradeId
{
get { return -1==trade.TradeId?Constants.CONST_DASHES:trade.TradeId.ToString(); }
set { ;}
}
public List<String> TradeTypeOptions
{
get { return new List<String>() { "Buy", "Sell" }; }
}
// Buy/Sell
public String SelectedTradeType
{
get
{
if (null == trade.BuySell) return null;
else if (trade.BuySell.Equals("S")) return "Sell";
else if (trade.BuySell.Equals("B")) return "Buy";
else return null;
}
set
{
if(String.IsNullOrEmpty(value)) return;
trade.BuySell = value.Equals("Buy") ? "B" : "S";
if (trade.BuySell.Equals("B"))
{
trade.Status = "OPEN";
trade.SellPrice = double.NaN;
trade.SellDate = Utility.Epoch;
base.OnPropertyChanged("SellPrice");
base.OnPropertyChanged("SellDate");
}
else
{
trade.Status = "CLOSED";
}
base.OnPropertyChanged("SelectedStatus");
base.OnPropertyChanged("SelectedTradeType");
}
}
// ***************************************** A C C O U N T ***************************
public List<String> AccountOptions
{
get { return PortfolioDA.GetAccounts(); }
}
public String SelectedAccount
{
get
{
return null==trade.Account||trade.Account.Equals("") ? null : trade.Account;
}
set
{
trade.Account = value;
base.OnPropertyChanged("SelectedAccount");
}
}
//************************************************************************************
public List<String> TradeStatusOptions
{
get {return new List<String>(){"OPEN","CLOSED"}; }
}
public String SelectedStatus
{
get
{
return null==trade.Status||trade.Status.Equals("") ? null : trade.Status;
}
}
public DateTime TradeDate
{
get { return trade.TradeDate; }
set
{
trade.TradeDate = value;
Price price = null;
if (!Utility.IsEpoch(trade.TradeDate) && !trade.TradeDate.Date.Equals(DateTime.Now.Date))
{
price = PricingDA.GetPrice(trade.Symbol, trade.TradeDate);
}
else
{
price = MarketDataHelper.GetLatestPrice(trade.Symbol);
if (null == price) price = PricingDA.GetPrice(trade.Symbol);
}
if (null != price)
{
trade.Price = price.Close;
base.OnPropertyChanged("TradeDate");
}
}
}
public String Symbol
{
get { return trade.Symbol; }
set
{
trade.Symbol = value;
trade.Symbol = trade.Symbol.ToUpper();
base.OnPropertyChanged("Symbol");
}
}
public double Shares
{
get
{
return trade.Shares;
}
set
{
trade.Shares = value;
base.OnPropertyChanged("Shares");
base.OnPropertyChanged("Exposure");
}
}
public String CompanyName
{
get { return trade.CompanyName; }
set
{
trade.CompanyName = value;
base.OnPropertyChanged("CompanyName");
}
}
public String Exposure
{
get { return Utility.FormatCurrency(trade.Exposure); }
set { ;}
}
public String Price
{
get
{
return Utility.FormatPrice(trade.Price);
}
set
{
trade.Price = Utility.ParseCurrency(value);
base.OnPropertyChanged("Price");
base.OnPropertyChanged("Exposure");
}
}
public String StopLimit
{
get
{
if(null==stopLimit)return Constants.NA;
return Utility.FormatCurrency(stopLimit.StopPrice,2);
}
set
{
if(String.IsNullOrEmpty(value))stopLimit=null;
else
{
if(null==stopLimit)
{
stopLimit=new StopLimit();
stopLimit.Symbol=trade.Symbol;
stopLimit.StopType=StopLimitConstants.STOP_QUOTE;
}
stopLimit.StopPrice=Utility.ParseCurrency(value);
stopLimit.Active=1;
}
base.OnPropertyChanged("StopLimit");
}
}
public String SellPrice
{
get
{
return Utility.FormatPrice(trade.SellPrice);
}
set
{
if (!trade.Status.Equals("CLOSED")) return;
trade.SellPrice = Utility.ParseCurrency(value);
base.OnPropertyChanged("SellPrice");
}
}
public DateTime? SellDate
{
get
{
if (Utility.IsEpoch(trade.SellDate)) return null;
return trade.SellDate;
}
set
{
trade.SellDate = value.Value;
base.OnPropertyChanged("SellDate");
}
}
public String Commission
{
get
{
return Utility.FormatCurrency(trade.Commission);
}
set
{
trade.Commission = Utility.ParseCurrency(value);
}
}
public String Status
{
get
{
return statusText;
}
set
{
if(!String.IsNullOrEmpty(value))
{
statusText = value;
base.OnPropertyChanged("Status");
}
}
}
public String AvailableCash
{
get
{
double availableCash = CashDA.GetBalance();
if(null!=SelectedAccount)availableCash=CashDA.GetBalance(SelectedAccount);
if (null == trade.BuySell) return Utility.FormatCurrency(availableCash);
if(trade.BuySell.Equals("S") && double.IsNaN(trade.SellPrice) && double.IsNaN(trade.Shares))return Utility.FormatCurrency(availableCash);
if(trade.BuySell.Equals("B") && double.IsNaN(trade.Price) && double.IsNaN(trade.Shares)) return Utility.FormatCurrency(availableCash);
if(trade.BuySell.Equals("S")) availableCash += trade.SellPrice * trade.Shares;
if(trade.BuySell.Equals("B")) availableCash -= trade.Price * trade.Shares;
if (!double.IsNaN(trade.Commission)) availableCash -= trade.Commission;
return Utility.FormatCurrency(availableCash);
}
}
// *******************************************************************************************************
// ****************************************** S A V E C O M M A N D *************************************
// *******************************************************************************************************
public ICommand SaveCommand
{
get
{
if(saveCommand == null)
{
saveCommand = new RelayCommand(param => this.Save(),param => this.CanSave);
}
return saveCommand;
}
}
public void Save()
{
if (!tradeRepository.ContainsTrade(trade))
{
tradeRepository.AddTrade(trade);
WatchListDA.AddToWatchList(trade.Symbol);
base.OnPropertyChanged("TradeId");
base.OnPropertyChanged("DisplayName");
statusText = "Save completed.";
}
else
{
tradeRepository.UpdateTrade(trade);
statusText="Update completed.";
}
UpdateStopLimit();
base.OnPropertyChanged("Status");
}
private void UpdateStopLimit()
{
// if(null==stopLimit && PortfolioDA.HasStopLimit(trade.Symbol))PortfolioDA.DeleteStopLimit(trade.Symbol);
if(null==stopLimit)PortfolioDA.DeleteStopLimit(trade.Symbol);
else if(null!=stopLimit)PortfolioDA.InsertUpdateStopLimit(stopLimit);
}
public bool CanSave
{
get
{
try
{
DateGenerator dateGenerator=new DateGenerator();
if (null == trade.TradeDate || Utility.IsEpoch(trade.TradeDate))
{
statusText=String.Format("Invalid Trade Date.");
return false;
}
if (null == trade.BuySell || !(trade.BuySell.ToUpper().Equals("B") || trade.BuySell.ToUpper().Equals("S")))
{
statusText=String.Format("BuySell must contain either BUY or SELL.");
return false;
}
if (null == trade.Status || (!trade.Status.Equals("OPEN") && !trade.Status.Equals("CLOSED")))
{
statusText=String.Format("Status must contain either OPEN or CLOSED.");
return false;
}
if(null!=trade.Status&&(trade.Status.Equals("CLOSED")||trade.BuySell.ToUpper().Equals("S"))&&double.IsNaN(trade.SellPrice))
{
statusText="Close position requires a valid selling price.";
return false;
}
if(null!=trade.Status&&(trade.Status.Equals("CLOSED") || trade.BuySell.ToUpper().Equals("S")) && Utility.IsEpoch(trade.SellDate))
{
statusText="Close position requires a valid sell date.";
return false;
}
if(null!=trade.Status&&(trade.Status.Equals("OPEN")||trade.BuySell.ToUpper().Equals("B"))&&!Utility.IsEpoch(trade.SellDate))
{
statusText="An open position cannot contain a sell date.";
return false;
}
if(null==trade.Symbol)
{
statusText="A trade entry must contain a valid symbol.";
return false;
}
if (0 == trade.Shares)
{
statusText="A trade entry must contain a number of shares.";
return false;
}
if (null == trade.Account || "".Equals(trade.Account))
{
statusText="A trade entry must contain a valid account.";
return false;
}
if (0 == trade.Price)
{
statusText="A trade entry must contain a valid price that is greater than zero.";
return false;
}
if(!Utility.IsEpoch(trade.TradeDate) && !dateGenerator.IsMarketOpen(trade.TradeDate))
{
statusText=String.Format("Trade date must be a valid market date. {0} is a holiday or weekend. ",Utility.DateTimeToStringMMSDDSYYYY(trade.TradeDate));
return false;
}
if(!Utility.IsEpoch(trade.SellDate)&&!dateGenerator.IsMarketOpen(trade.SellDate))
{
statusText=String.Format("Sell date must be a valid market date. {0} is a holiday or weekend. ",Utility.DateTimeToStringMMSDDSYYYY(trade.SellDate));
return false;
}
statusText="Form is validated.";
return true;
}
catch(Exception exception)
{
statusText=exception.ToString();
return false;
}
finally
{
base.OnPropertyChanged("Status");
}
}
}
}
}