PageRenderTime 28ms CodeModel.GetById 17ms app.highlight 8ms RepoModel.GetById 1ms 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
 18using System;
 19using System.Collections.Generic;
 20using System.ComponentModel;
 21using System.Globalization;
 22using Microsoft.Practices.Composite.Wpf.Commands;
 23using StockTraderRI.Infrastructure;
 24using StockTraderRI.Infrastructure.Interfaces;
 25using StockTraderRI.Infrastructure.Models;
 26using StockTraderRI.Modules.Position.Interfaces;
 27using StockTraderRI.Modules.Position.Models;
 28using StockTraderRI.Modules.Position.Properties;
 29
 30namespace StockTraderRI.Modules.Position.Orders
 31{
 32    public class OrderDetailsPresentationModel : IOrderDetailsPresentationModel, INotifyPropertyChanged, IDataErrorInfo
 33    {
 34        private readonly IAccountPositionService accountPositionService;
 35        private readonly IOrdersService ordersService;
 36        private TransactionInfo _transactionInfo;
 37        private int? _shares = 0;
 38        private OrderType _orderType = OrderType.Market;
 39        private decimal? _stopLimitPrice = 0;
 40        private TimeInForce _timeInForce;
 41
 42        private readonly IDictionary<string, string> errors = new Dictionary<string, string>();
 43        
 44        public OrderDetailsPresentationModel(IOrderDetailsView view, IAccountPositionService accountPositionService, IOrdersService ordersService)
 45        {
 46            View = view;
 47            this.accountPositionService = accountPositionService;
 48            this.ordersService = ordersService;
 49
 50            _transactionInfo = new TransactionInfo();
 51
 52            //use localizable enum descriptions
 53            AvailableOrderTypes = new List<ValueDescription<OrderType>>
 54                                        {
 55                                            new ValueDescription<OrderType>(OrderType.Limit, Resources.OrderType_Limit),
 56                                            new ValueDescription<OrderType>(OrderType.Market, Resources.OrderType_Market),
 57                                            new ValueDescription<OrderType>(OrderType.Stop, Resources.OrderType_Stop)
 58                                        };
 59
 60            AvailableTimesInForce = new List<ValueDescription<TimeInForce>>
 61                                          {
 62                                              new ValueDescription<TimeInForce>(TimeInForce.EndOfDay, Resources.TimeInForce_EndOfDay),
 63                                              new ValueDescription<TimeInForce>(TimeInForce.ThirtyDays, Resources.TimeInForce_ThirtyDays)
 64                                          };
 65
 66            View.Model = this;
 67            ValidateModel();
 68
 69            SubmitCommand = new DelegateCommand<object>(Submit, CanSubmit);
 70            CancelCommand = new DelegateCommand<object>(Cancel);
 71            SubmitCommand.IsActive = view.IsActive;
 72            CancelCommand.IsActive = view.IsActive;
 73
 74            view.IsActiveChanged += view_IsActiveChanged;
 75        }
 76
 77        public event EventHandler CloseViewRequested = delegate { };
 78        public IOrderDetailsView View { get; set; }
 79        public IList<ValueDescription<OrderType>> AvailableOrderTypes { get; set; }
 80        public IList<ValueDescription<TimeInForce>> AvailableTimesInForce { get; set; }
 81
 82        void OnPropertyChanged(string propertyName)
 83        {
 84            ValidateModel();
 85            SubmitCommand.RaiseCanExecuteChanged();
 86            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 87        }
 88
 89        public TransactionInfo TransactionInfo
 90        {
 91            get { return _transactionInfo; }
 92            set
 93            {
 94                _transactionInfo = value;
 95                OnPropertyChanged("TransactionType");
 96                OnPropertyChanged("TickerSymbol");
 97            }
 98        }
 99
100        public TransactionType TransactionType
101        {
102            get { return _transactionInfo.TransactionType; }
103            set
104            {
105                if (_transactionInfo.TransactionType != value)
106                {
107                    _transactionInfo.TransactionType = value;
108                    OnPropertyChanged("TransactionType");
109                }
110            }
111        }
112
113        public string TickerSymbol
114        {
115            get { return _transactionInfo.TickerSymbol; }
116            set
117            {
118                if (_transactionInfo.TickerSymbol != value)
119                {
120                    _transactionInfo.TickerSymbol = value;
121                    OnPropertyChanged("TickerSymbol");
122                }
123            }
124        }
125
126        public int? Shares
127        {
128            get { return _shares; }
129            set
130            {
131                if (_shares == null || _shares != value)
132                {
133                    _shares = value;
134                    OnPropertyChanged("Shares");
135                }
136            }
137        }
138
139        public OrderType OrderType
140        {
141            get { return _orderType; }
142            set
143            {
144                if (!value.Equals(_orderType))
145                {
146                    _orderType = value;
147                    OnPropertyChanged("OrderType");
148                }
149            }
150        }
151
152        public decimal? StopLimitPrice
153        {
154            get
155            {
156                return _stopLimitPrice;
157            }
158            set
159            {
160                if (_stopLimitPrice == null || value != _stopLimitPrice)
161                {
162                    _stopLimitPrice = value;
163                    OnPropertyChanged("StopLimitPrice");
164                }
165            }
166        }
167
168        public TimeInForce TimeInForce
169        {
170            get { return _timeInForce; }
171            set
172            {
173                if (value != _timeInForce)
174                {
175                    _timeInForce = value;
176                    OnPropertyChanged("TimeInForce");
177                }
178
179                _timeInForce = value;
180            }
181        }
182
183        public DelegateCommand<object> SubmitCommand { get; private set;}
184        public DelegateCommand<object> CancelCommand { get; private set;}
185
186        public bool HasErrors()
187        {
188            return (errors.Count > 0);
189        }
190
191        private void ValidateModel()
192        {
193            ClearErrors();
194            if (!Shares.HasValue || Shares <= 0)
195            {
196                this["Shares"] = Resources.InvalidSharesRange;
197            }
198            else if (TransactionType == TransactionType.Sell
199                && !HoldsEnoughShares(TickerSymbol, Shares))
200            {
201                this["Shares"] = String.Format(CultureInfo.InvariantCulture, Resources.NotEnoughSharesToSell, Shares);
202            }
203
204            if (!StopLimitPrice.HasValue || StopLimitPrice <= 0)
205            {
206                this["StopLimitPrice"] = Resources.InvalidStopLimitPrice;
207            }
208        }
209
210        #region IDataErrorInfo Members
211
212        public string Error
213        {
214            get { throw new NotImplementedException(); }
215        }
216
217        public string this[string columnName]
218        {
219            get
220            {
221                if (errors.ContainsKey(columnName))
222                    return errors[columnName];
223
224                return null;
225            }
226            set
227            {
228                errors[columnName] = value;
229            }
230        }
231
232        #endregion
233
234        internal void ClearErrors()
235        {
236            errors.Clear();
237        }
238
239        void view_IsActiveChanged(object sender, EventArgs e)
240        {
241            SubmitCommand.IsActive = View.IsActive;
242            CancelCommand.IsActive = View.IsActive;
243        }
244
245        bool CanSubmit(object parameter)
246        {
247            return !HasErrors();
248        }
249
250        private bool HoldsEnoughShares(string symbol, int? sharesToSell)
251        {
252            if (!sharesToSell.HasValue) return false;
253
254            foreach (AccountPosition accountPosition in accountPositionService.GetAccountPositions())
255            {
256                if (accountPosition.TickerSymbol.Equals(symbol, StringComparison.OrdinalIgnoreCase))
257                {
258                    if (accountPosition.Shares >= sharesToSell)
259                    {
260                        return true;
261                    }
262                    else
263                    {
264                        return false;
265                    }
266                }
267            }
268            return false;
269        }
270
271        void Submit(object parameter)
272        {
273            if (!CanSubmit(parameter))
274                throw new InvalidOperationException();
275
276            var order = new Order();
277            order.TransactionType = this.TransactionType;
278            order.OrderType = this.OrderType;
279            order.Shares = this.Shares.HasValue ? this.Shares.Value : 0;
280            order.StopLimitPrice = this.StopLimitPrice.HasValue ? this.StopLimitPrice.Value : 0;
281            order.TickerSymbol = this.TickerSymbol;
282            order.TimeInForce = this.TimeInForce;
283
284            ordersService.Submit(order);
285
286            CloseViewRequested(this, EventArgs.Empty);
287        }
288
289
290        void Cancel(object parameter)
291        {
292            CloseViewRequested(this, EventArgs.Empty);
293        }
294
295        public event PropertyChangedEventHandler PropertyChanged = delegate {};
296    }
297}