PageRenderTime 25ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/V1/trunk/Source/StockTraderRI/StockTraderRI.Modules.Position/Orders/OrderDetailsPresentationModel.cs

#
C# | 297 lines | 239 code | 41 blank | 17 comment | 28 complexity | 5afcd3aa5d9f8bc2d81e640addb6a6d2 MD5 | raw file
  1. //===============================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation
  4. //===============================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===============================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===============================================================================
  17. using System;
  18. using System.Collections.Generic;
  19. using System.ComponentModel;
  20. using System.Globalization;
  21. using Microsoft.Practices.Composite.Wpf.Commands;
  22. using StockTraderRI.Infrastructure;
  23. using StockTraderRI.Infrastructure.Interfaces;
  24. using StockTraderRI.Infrastructure.Models;
  25. using StockTraderRI.Modules.Position.Interfaces;
  26. using StockTraderRI.Modules.Position.Models;
  27. using StockTraderRI.Modules.Position.Properties;
  28. namespace StockTraderRI.Modules.Position.Orders
  29. {
  30. public class OrderDetailsPresentationModel : IOrderDetailsPresentationModel, INotifyPropertyChanged, IDataErrorInfo
  31. {
  32. private readonly IAccountPositionService accountPositionService;
  33. private readonly IOrdersService ordersService;
  34. private TransactionInfo _transactionInfo;
  35. private int? _shares = 0;
  36. private OrderType _orderType = OrderType.Market;
  37. private decimal? _stopLimitPrice = 0;
  38. private TimeInForce _timeInForce;
  39. private readonly IDictionary<string, string> errors = new Dictionary<string, string>();
  40. public OrderDetailsPresentationModel(IOrderDetailsView view, IAccountPositionService accountPositionService, IOrdersService ordersService)
  41. {
  42. View = view;
  43. this.accountPositionService = accountPositionService;
  44. this.ordersService = ordersService;
  45. _transactionInfo = new TransactionInfo();
  46. //use localizable enum descriptions
  47. AvailableOrderTypes = new List<ValueDescription<OrderType>>
  48. {
  49. new ValueDescription<OrderType>(OrderType.Limit, Resources.OrderType_Limit),
  50. new ValueDescription<OrderType>(OrderType.Market, Resources.OrderType_Market),
  51. new ValueDescription<OrderType>(OrderType.Stop, Resources.OrderType_Stop)
  52. };
  53. AvailableTimesInForce = new List<ValueDescription<TimeInForce>>
  54. {
  55. new ValueDescription<TimeInForce>(TimeInForce.EndOfDay, Resources.TimeInForce_EndOfDay),
  56. new ValueDescription<TimeInForce>(TimeInForce.ThirtyDays, Resources.TimeInForce_ThirtyDays)
  57. };
  58. View.Model = this;
  59. ValidateModel();
  60. SubmitCommand = new DelegateCommand<object>(Submit, CanSubmit);
  61. CancelCommand = new DelegateCommand<object>(Cancel);
  62. SubmitCommand.IsActive = view.IsActive;
  63. CancelCommand.IsActive = view.IsActive;
  64. view.IsActiveChanged += view_IsActiveChanged;
  65. }
  66. public event EventHandler CloseViewRequested = delegate { };
  67. public IOrderDetailsView View { get; set; }
  68. public IList<ValueDescription<OrderType>> AvailableOrderTypes { get; set; }
  69. public IList<ValueDescription<TimeInForce>> AvailableTimesInForce { get; set; }
  70. void OnPropertyChanged(string propertyName)
  71. {
  72. ValidateModel();
  73. SubmitCommand.RaiseCanExecuteChanged();
  74. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  75. }
  76. public TransactionInfo TransactionInfo
  77. {
  78. get { return _transactionInfo; }
  79. set
  80. {
  81. _transactionInfo = value;
  82. OnPropertyChanged("TransactionType");
  83. OnPropertyChanged("TickerSymbol");
  84. }
  85. }
  86. public TransactionType TransactionType
  87. {
  88. get { return _transactionInfo.TransactionType; }
  89. set
  90. {
  91. if (_transactionInfo.TransactionType != value)
  92. {
  93. _transactionInfo.TransactionType = value;
  94. OnPropertyChanged("TransactionType");
  95. }
  96. }
  97. }
  98. public string TickerSymbol
  99. {
  100. get { return _transactionInfo.TickerSymbol; }
  101. set
  102. {
  103. if (_transactionInfo.TickerSymbol != value)
  104. {
  105. _transactionInfo.TickerSymbol = value;
  106. OnPropertyChanged("TickerSymbol");
  107. }
  108. }
  109. }
  110. public int? Shares
  111. {
  112. get { return _shares; }
  113. set
  114. {
  115. if (_shares == null || _shares != value)
  116. {
  117. _shares = value;
  118. OnPropertyChanged("Shares");
  119. }
  120. }
  121. }
  122. public OrderType OrderType
  123. {
  124. get { return _orderType; }
  125. set
  126. {
  127. if (!value.Equals(_orderType))
  128. {
  129. _orderType = value;
  130. OnPropertyChanged("OrderType");
  131. }
  132. }
  133. }
  134. public decimal? StopLimitPrice
  135. {
  136. get
  137. {
  138. return _stopLimitPrice;
  139. }
  140. set
  141. {
  142. if (_stopLimitPrice == null || value != _stopLimitPrice)
  143. {
  144. _stopLimitPrice = value;
  145. OnPropertyChanged("StopLimitPrice");
  146. }
  147. }
  148. }
  149. public TimeInForce TimeInForce
  150. {
  151. get { return _timeInForce; }
  152. set
  153. {
  154. if (value != _timeInForce)
  155. {
  156. _timeInForce = value;
  157. OnPropertyChanged("TimeInForce");
  158. }
  159. _timeInForce = value;
  160. }
  161. }
  162. public DelegateCommand<object> SubmitCommand { get; private set;}
  163. public DelegateCommand<object> CancelCommand { get; private set;}
  164. public bool HasErrors()
  165. {
  166. return (errors.Count > 0);
  167. }
  168. private void ValidateModel()
  169. {
  170. ClearErrors();
  171. if (!Shares.HasValue || Shares <= 0)
  172. {
  173. this["Shares"] = Resources.InvalidSharesRange;
  174. }
  175. else if (TransactionType == TransactionType.Sell
  176. && !HoldsEnoughShares(TickerSymbol, Shares))
  177. {
  178. this["Shares"] = String.Format(CultureInfo.InvariantCulture, Resources.NotEnoughSharesToSell, Shares);
  179. }
  180. if (!StopLimitPrice.HasValue || StopLimitPrice <= 0)
  181. {
  182. this["StopLimitPrice"] = Resources.InvalidStopLimitPrice;
  183. }
  184. }
  185. #region IDataErrorInfo Members
  186. public string Error
  187. {
  188. get { throw new NotImplementedException(); }
  189. }
  190. public string this[string columnName]
  191. {
  192. get
  193. {
  194. if (errors.ContainsKey(columnName))
  195. return errors[columnName];
  196. return null;
  197. }
  198. set
  199. {
  200. errors[columnName] = value;
  201. }
  202. }
  203. #endregion
  204. internal void ClearErrors()
  205. {
  206. errors.Clear();
  207. }
  208. void view_IsActiveChanged(object sender, EventArgs e)
  209. {
  210. SubmitCommand.IsActive = View.IsActive;
  211. CancelCommand.IsActive = View.IsActive;
  212. }
  213. bool CanSubmit(object parameter)
  214. {
  215. return !HasErrors();
  216. }
  217. private bool HoldsEnoughShares(string symbol, int? sharesToSell)
  218. {
  219. if (!sharesToSell.HasValue) return false;
  220. foreach (AccountPosition accountPosition in accountPositionService.GetAccountPositions())
  221. {
  222. if (accountPosition.TickerSymbol.Equals(symbol, StringComparison.OrdinalIgnoreCase))
  223. {
  224. if (accountPosition.Shares >= sharesToSell)
  225. {
  226. return true;
  227. }
  228. else
  229. {
  230. return false;
  231. }
  232. }
  233. }
  234. return false;
  235. }
  236. void Submit(object parameter)
  237. {
  238. if (!CanSubmit(parameter))
  239. throw new InvalidOperationException();
  240. var order = new Order();
  241. order.TransactionType = this.TransactionType;
  242. order.OrderType = this.OrderType;
  243. order.Shares = this.Shares.HasValue ? this.Shares.Value : 0;
  244. order.StopLimitPrice = this.StopLimitPrice.HasValue ? this.StopLimitPrice.Value : 0;
  245. order.TickerSymbol = this.TickerSymbol;
  246. order.TimeInForce = this.TimeInForce;
  247. ordersService.Submit(order);
  248. CloseViewRequested(this, EventArgs.Empty);
  249. }
  250. void Cancel(object parameter)
  251. {
  252. CloseViewRequested(this, EventArgs.Empty);
  253. }
  254. public event PropertyChangedEventHandler PropertyChanged = delegate {};
  255. }
  256. }