using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Ioc; using Muchinfo.MTPClient.Data; using Muchinfo.MTPClient.Data.DTO; using Muchinfo.MTPClient.Data.Enums; using Muchinfo.MTPClient.Data.Model; using Muchinfo.MTPClient.Data.Model.Account; using Muchinfo.MTPClient.Infrastructure.Cache; using Muchinfo.MTPClient.Infrastructure.Helpers; using Muchinfo.MTPClient.Infrastructure.MessageBox; using Muchinfo.MTPClient.Infrastructure.Utilities; using Muchinfo.MTPClient.IService; using Muchinfo.MTPClient.Resources; using Muchinfo.WPF.Controls.Windows; using System; using System.Linq; //---------------------------------------------------------------- //Module Name: $safeprojectname$ //Purpose: //CopyRight: Muchinfo //History: //---------------------------------------------------------------- //DateTime 2016/2/2 16:45:23 //Author //Description Create //---------------------------------------------------------------- using System.Timers; using System.Windows; namespace Muchinfo.MTPClient.Trade.ViewModels { public class QuickOrderViewModel : ViewModelBase { private QuoteGoods _currentGoods; private IGoodsService _igoodsService; /// /// 当前商品 /// public QuoteGoods CurrentGoods { get { return _currentGoods; } set { Set(() => CurrentGoods, ref _currentGoods, value); } } public QuickOrderViewModel() { ////todo:注册改变当前商品消息 MessengerHelper.DefaultRegister(this, MessengerTokens.SelectGoodsChange, SelectGoodsChange); MessengerHelper.DefaultRegister(this, MessengerTokens.QuickSell, QuickSellCommand); MessengerHelper.DefaultRegister(this, MessengerTokens.QuickBuy, QuickBuyCommand); _igoodsService = SimpleIoc.Default.GetInstance(); } private const decimal c_LotBit = 0.01m; //数量的小数位数 /// /// 正在加载中 /// private bool _isBusy; public bool IsBusy { get { return _isBusy; } set { Set(() => IsBusy, ref _isBusy, value); } } private bool _canOpenMarket; public bool CanOpenMarket { get { return _canOpenMarket; } set { Set(() => CanOpenMarket, ref _canOpenMarket, value); } } private decimal _lot; /// /// 建仓手数 /// public decimal Lot { get { return _lot; } set { Set(() => Lot, ref _lot, value); RaisePropertyChanged(() => ShowMessage); } } public string ShowMessage { get { var returnString = ""; if (Lot % c_LotBit != 0) returnString = Client_Resource.Trade_OnlyTwoDecimalPlaces; if (this._currentGoods != null) { var minLots = _igoodsService.GetGoodsParamerRule((int)_currentGoods.GoodsId, _currentGoods.TradeMode, GoodsTradeConts.MINOPENTRADEQTY); var maxLots = _igoodsService.GetGoodsParamerRule((int)_currentGoods.GoodsId, _currentGoods.TradeMode, GoodsTradeConts.MAXOPENTRADEQTY); if (minLots != null && Lot < minLots.FeeValue) { returnString = string.Format(Client_Resource.Lot_Open_UpOfMinOpenLot, minLots.FeeValue); } else if (maxLots != null && Lot > maxLots.FeeValue) { returnString = string.Format(Client_Resource.Lot_Open_DownOfMaxOpenLot, maxLots.FeeValue); } else if (minLots != null && minLots.FeeValue != 0 && Lot % minLots.FeeValue != 0) { returnString = string.Format(Client_Resource.Trade_LotCountIncorrect, minLots.FeeValue); } } else { returnString = Client_Resource.Select_Goods_Error; } if (Lot <= 0) { returnString = Client_Resource.Lot_Vailed_MustUpOfZero; } return returnString; } } private Visibility _market_AllownPubsVisiable = Visibility.Collapsed; public Visibility Market_AllownPubsVisiable { get { return _market_AllownPubsVisiable; } set { Set(() => Market_AllownPubsVisiable, ref _market_AllownPubsVisiable, value); } } private decimal _maxLost; /// /// 单笔建仓最大数量 /// public decimal MaxLot { get { return _maxLost; } set { Set(() => MaxLot, ref _maxLost, value); } } /// /// 市价建买 /// public RelayCommand BuyCommand { get { return new RelayCommand(() => { QuickBuy(); }); } } /// /// 市价建卖 /// public RelayCommand SellCommand { get { return new RelayCommand(QuickSell); } } /// /// 快捷卖单消息 /// /// The goods. private void QuickSellCommand(QuoteGoodsDTO goods) { //改变当前商品 SelectGoodsChange(goods); //改变数量 Lot = goods.Lot; //内部卖逻辑 QuickSell(); } /// /// 快捷下买单消息 /// /// The goods. private void QuickBuyCommand(QuoteGoodsDTO goods) { //改变当前商品 SelectGoodsChange(goods); //改变数量 Lot = goods.Lot; //内部买逻辑 QuickBuy(); } /// /// 选择商品改变 /// /// The goods. private void SelectGoodsChange(QuoteGoodsDTO goods) { var quoteGoods = CacheManager.CacheGoodsBaseInfos.FirstOrDefault((item) => item.Symbol == goods.Symbol); CurrentGoods = quoteGoods; if (goods != null) { //todo:赋值MaxLot //MaxLot = goods.GoodsParameters.MaxOpenNumber; Lot = goods.Lot; } CanOpenMarket = true; } /// /// 内部卖逻辑 /// private void QuickSell() { // OpenCloseMode = OpenCloseMode.BUILDTYPE_CLOSE; CanOpenMarket = false; string errorMsg = ""; if (VailedFormData(out errorMsg, Direction.Ask)) { string preViewMessage = Client_Resource.Warning_Order_confirm + Environment.NewLine + "\r\n"; //if (_currentGoods.GoodsParameters.TradeMode != eTradeMode.TRADEMODE_MARKETMAKE) //{ // preViewMessage = @"您确认要限价下单吗?" + Environment.NewLine + "\r\n"; //} preViewMessage += Client_Resource.QuickOrderViewModel_Goods + _currentGoods.GoodsParameters.GoodsName + Environment.NewLine; preViewMessage += Client_Resource.QuickOrderViewModel_Direction + Client_Resource.Content_SellOut + Environment.NewLine; if (_currentGoods.TradeMode == eTradeMode.TRADEMODE_MARKETMAKE) { preViewMessage += Client_Resource.QuickOrderViewModel_Price + _currentGoods.AskPrice + Environment.NewLine; } //else //{ // var currentPrice = decimal.Zero; // //竞价、混合=》默认限价下单【取值:最新价OR昨结算价】20160725-Idea from qiang // if (_currentGoods.CurrentPrice != decimal.Zero) // { // currentPrice = _currentGoods.CurrentPrice; // } // else // { // currentPrice = _currentGoods.LastSettlement; // } // preViewMessage += "价 格:" + currentPrice + Environment.NewLine; //} preViewMessage += Client_Resource.QuickOrderViewModel_Qty + Lot + Environment.NewLine; if (MessageBoxHelper.ShowQuestion(preViewMessage, Client_Resource.APP_Tips) == MessageBoxResult.Yes) //if (MessageBoxHelper.ShowQuestion(Client_Resource.Warning_Order_confirm, Client_Resource.APP_Tips) == MessageBoxResult.Yes) { try { InitTimer(); PostOrder(Direction.Ask); CanOpenMarket = true; } finally { CanOpenMarket = true; DisposeTimer(); } } else { CanOpenMarket = true; } } else { MessageBoxHelper.ShowInfo(errorMsg, Client_Resource.MessageBox_Error_Title); CanOpenMarket = true; } } /// /// 内部买逻辑 /// private void QuickBuy() { CanOpenMarket = false; string errorMsg = ""; if (VailedFormData(out errorMsg, Direction.Bid)) { string preViewMessage = Client_Resource.WarningOpen + Environment.NewLine + "\r\n"; //if (_currentGoods.GoodsParameters.TradeMode != eTradeMode.TRADEMODE_MARKETMAKE) //{ // preViewMessage = @"您确认要限价{0}建仓吗?" + Environment.NewLine + "\r\n"; //} preViewMessage += Client_Resource.QuickOrderViewModel_Goods + _currentGoods.GoodsParameters.GoodsName + Environment.NewLine; preViewMessage += Client_Resource.QuickOrderViewModel_Direction + Client_Resource.Content_Purchase + Environment.NewLine; if (_currentGoods.TradeMode == eTradeMode.TRADEMODE_MARKETMAKE) { preViewMessage += Client_Resource.QuickOrderViewModel_Price + _currentGoods.BidPrice + Environment.NewLine; } //else //{ // var currentPrice = decimal.Zero; // //竞价、混合=》默认限价下单【取值:最新价OR昨结算价】20160725-Idea from qiang // if (_currentGoods.CurrentPrice!=decimal.Zero) // { // currentPrice = _currentGoods.CurrentPrice; // } // else // { // currentPrice = _currentGoods.LastSettlement; // } // preViewMessage += "价 格:" + currentPrice + Environment.NewLine; //} preViewMessage += Client_Resource.QuickOrderViewModel_Qty + Lot + Environment.NewLine; //if (MessageBoxHelper.ShowQuestion(string.Format(Client_Resource.WarningOpen, Client_Resource.Content_Purchase), Client_Resource.WarningOpenPrompt) == MessageBoxResult.Yes) if (MessageBoxHelper.ShowQuestion(string.Format(preViewMessage, Client_Resource.Content_Purchase), Client_Resource.WarningOpenPrompt) == MessageBoxResult.Yes) { try { InitTimer(); PostOrder(Direction.Bid); } finally { CanOpenMarket = true; DisposeTimer(); } } else { CanOpenMarket = true; } } else { MessageBoxHelper.ShowInfo(errorMsg, Client_Resource.MessageBox_Error_Title); CanOpenMarket = true; } } /// /// 验证表单数据是否正确 /// /// /// private bool VailedFormData(out string errorMsg, Direction direction) { if (CurrentGoods == null ||string.IsNullOrWhiteSpace((_currentGoods.Name))) { errorMsg = Client_Resource.Select_Goods_Error; ; return false; } if ((CurrentGoods.ContainsGoodsSrc & (int)GoodsFromScr.Trade) != (int)GoodsFromScr.Trade) ////浏览的商品 { errorMsg = string.Format(Client_Resource.Goods_WithOutTrade_Power, CurrentGoods.Name); return false; } #region MyRegion if (Lot % c_LotBit != 0) { errorMsg = Client_Resource.Trade_OnlyTwoDecimalPlaces; return false; } if (this._currentGoods != null) { var minLots = _igoodsService.GetGoodsParamerRule((int)_currentGoods.GoodsId, _currentGoods.TradeMode, GoodsTradeConts.MINOPENTRADEQTY); var maxLots = _igoodsService.GetGoodsParamerRule((int)_currentGoods.GoodsId, _currentGoods.TradeMode, GoodsTradeConts.MAXOPENTRADEQTY); if (_currentGoods.GoodsParameters.MoneyMode == eMoneyMode.MONEYMODE_PAY && direction == Direction.Ask) { #region //全额商品区分买入卖出方向 var holdingOrders = UserManager.GetCacheOrders(); if (holdingOrders == null || !holdingOrders.Any()) { errorMsg = Client_Resource.Quick_OrderHasNoHolds; return false; } var holds = holdingOrders.Where((item) => item.GoodsId == CurrentGoods.GoodsParameters.GoodsId && item.Direction == Direction.Bid).ToList(); if (holds == null || !holds.Any()) { errorMsg = Client_Resource.Quick_OrderHasNoHolds; return false; } else { //最大数量=持仓汇总-冻结寸头 var tempMaxLot = (int)(holds.Sum((item) => item.Lot-item.LockQty) - holds.FirstOrDefault().PositionFzQty); //全额商品-下单数量是否大于持仓数量 if (Lot > tempMaxLot) { errorMsg =string.Format( Client_Resource.Lot_Close_DownOfMaxOpenLot,tempMaxLot); return false; } } #endregion } else { #region //非全额商品 买入卖出都只有建仓模式 if (minLots != null && Lot < minLots.FeeValue) { errorMsg = string.Format(Client_Resource.Lot_Open_UpOfMinOpenLot, minLots.FeeValue); return false; } else if (maxLots != null && Lot > maxLots.FeeValue) { errorMsg = string.Format(Client_Resource.Lot_Open_DownOfMaxOpenLot, maxLots.FeeValue); return false; } #endregion } if (minLots != null && minLots.FeeValue != 0 && Lot % minLots.FeeValue != 0) { errorMsg = string.Format(Client_Resource.Trade_LotCountIncorrect, minLots.FeeValue); return false; } } else { errorMsg = Client_Resource.Select_Goods_Error; return false; } if (Lot <= 0) { errorMsg = Client_Resource.Lot_Vailed_MustUpOfZero; return false; } #endregion errorMsg = string.Empty; return true; } /// /// 发送下单消息 /// /// 返回下单错误码 private void PostOrder(Direction direction) { var entrustOrder = new NewEntrustOrder() { GoodsId = (uint)this._currentGoods.GoodsParameters.GoodsId, AccountType = UserManager.CurrentTradeAccount.AccountType, BuyOrSell = direction, EntrustQuantity = Lot, OperaterId = UserManager.CurrentTradeAccount.AccountId, BuildType = OpenCloseMode.BUILDTYPE_OPEN, EntrurstTime = ApplicationParameter.ServerTimeNow, PriceMode = ePriceMode.PRICEMODE_MARKET, CurrentGoods = this.CurrentGoods, GoodsCode = this.CurrentGoods.GoodsCode, MemberAreaId = UserManager.CurrentTradeAccount.MemberAreaId, ValidType = ExpirationType.Today, MarketId = this.CurrentGoods.MarketID, TradeMode = CurrentGoods.TradeMode, LoginID = UserManager.CurrentTradeAccount.AccountId, AccountId = UserManager.CurrentTradeAccount.FundsAccountId, OrderFlag = (uint)OrderMethods.NormalOrder, OrderFormType = eOrderFormType.Commom, }; var allowPips = _igoodsService.GetGoodsParamerRule((int)_currentGoods.GoodsId, _currentGoods.TradeMode, GoodsTradeConts.AllowPips); if (_currentGoods.GoodsParameters.MoneyMode == eMoneyMode.MONEYMODE_PAY && direction == Direction.Ask) { entrustOrder.BuildType = OpenCloseMode.BUILDTYPE_CLOSE; } //Edit by DK 20160725 //竞价、混合=》默认限价下单【取值:最新价OR昨结算价】-Idea from qiang //if (_currentGoods.GoodsParameters.TradeMode != eTradeMode.TRADEMODE_MARKETMAKE) //{ // entrustOrder.PriceMode = ePriceMode.PRICEMODE_LIMIT; // if (_currentGoods.CurrentPrice != decimal.Zero) // { // entrustOrder.EntrustPrice = _currentGoods.CurrentPrice; // } // else // { // entrustOrder.EntrustPrice = _currentGoods.LastSettlement; // } //} //todo:默认点差 entrustOrder.AllowTradeSub = allowPips == null ? 0 : allowPips.FeeValue;//ApplicationParameter.AllowTradeSub; //点差只能设置整数 var orderService = SimpleIoc.Default.GetInstance(); //if (UserManager.CurrentTradeAccount.FundsAccounts.Any() && // UserManager.CurrentTradeAccount.FundsAccounts[0] != null) //{ // entrustOrder.AccountId = UserManager.CurrentTradeAccount.FundsAccounts[0].AccountId; //} //else //{ // entrustOrder.AccountId = UserManager.CurrentTradeAccount.AccountId; //} if (_currentGoods.GoodsParameters == null) { MessageBoxHelper.ShowInfo(Client_Resource.APP_Tips, Client_Resource.QuickOrder_ParamersError); } else { switch (_currentGoods.TradeMode) { case eTradeMode.TRADEMODE_MARKETMAKE: entrustOrder.EntrustPrice = direction == Direction.Bid ? _currentGoods.BidPrice : _currentGoods.AskPrice; entrustOrder.OrderMode = OrderMode.InValid; entrustOrder.CurtQuotePrice = entrustOrder.EntrustPrice; orderService.MakeMarketEntrustOrder(entrustOrder, EntrurstSuccessCallBack, EntrurstErrorCallBack); break; case eTradeMode.TRADEMODE_BIDDING: entrustOrder.EntrustPrice = 0; entrustOrder.OrderMode = OrderMode.STD; entrustOrder.CurtQuotePrice = entrustOrder.EntrustPrice; // entrustOrder.TradeCloseMode = TradeCloseMode.IsVailed; orderService.BidMarketEntrustOrder(entrustOrder, EntrurstSuccessCallBack, EntrurstErrorCallBack); break; case eTradeMode.TRADEMODE_BIDDINGMARKETMAKE: entrustOrder.EntrustPrice = 0; entrustOrder.OrderMode = OrderMode.InValid; entrustOrder.CurtQuotePrice = entrustOrder.EntrustPrice; // entrustOrder.TradeCloseMode = TradeCloseMode.IsVailed; orderService.MixMarketEntrustOrder(entrustOrder, EntrurstSuccessCallBack, EntrurstErrorCallBack); break; case eTradeMode.TRADEMODE_ENTRUST_HEDGE: entrustOrder.CurtQuotePrice = direction == Direction.Ask ? _currentGoods.BidPrice : _currentGoods.AskPrice; entrustOrder.ChannelPriceMode = ChannelPriceMode.MarketPrice; orderService.ChannelEntrustOrder(entrustOrder, EntrurstSuccessCallBack, EntrurstErrorCallBack); break; default: var message = string.Format(Client_Resource.QuickOrder_TradeModeError, _currentGoods.TradeMode); MessageBoxHelper.ShowInfo(Client_Resource.APP_Tips, message); break; } } } /// /// 提交成功返回 /// /// private void EntrurstSuccessCallBack(OrderDetail order) { //更新相应的单据 MessengerHelper.DefaultSend(UserManager.CurrentTradeAccount, MessengerTokens.OrderNoticeToken); Application.Current.Dispatcher.BeginInvoke(new Action(() => { MessageBoxHelper.ShowSuccess(Client_Resource.Order_Success_Result, Client_Resource.Open_MessageBox_Title); IsBusy = false; })); } /// /// 委托失败返回 /// /// private void EntrurstErrorCallBack(ErrorEntity errorEntity) { Application.Current.Dispatcher.BeginInvoke(new Action(() => { ErrorManager.ShowReturnError(errorEntity, Client_Resource.UI2014_Tips, true); IsBusy = false; })); } #region 设置下单倒数定时器 private string _busyTips; /// /// 服务忙提示 /// public string BusyTips { get { return _busyTips; } set { Set(() => BusyTips, ref _busyTips, value); } } private Timer _timer; //下单计时 private int _countTime; //倒计时时间 private bool _isOrderVisible = false; /// /// 是否显示快速下单 /// public bool IsOrderVisible { get { return _isOrderVisible; } set { Set(() => IsOrderVisible, ref _isOrderVisible, value); } } /// /// 初始化下单计时时间 /// private void InitTimer() { _countTime = ApplicationParameter.ServerTimeOut; this._timer = new Timer(1000); this._timer.AutoReset = true; this._timer.Elapsed += _timer_Elapsed; this._timer.Start(); IsOrderVisible = true; BusyTips = string.Format(Client_Resource.Busy_Summit_Wait, _countTime); } /// /// /// /// /// void _timer_Elapsed(object sender, ElapsedEventArgs e) { _countTime--; BusyTips = string.Format(Client_Resource.Busy_Summit_Wait, _countTime); } /// /// 清除计时器 /// private void DisposeTimer() { this._timer.Stop(); this._timer.Elapsed -= _timer_Elapsed; this._timer.Close(); IsOrderVisible = false; } #endregion } }