using System.Windows.Documents; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Ioc; using Muchinfo.MTPClient.Data; 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.Collections.Generic; using System.Linq; using System.Timers; using System.Windows; using Direction = Muchinfo.MTPClient.Data.Enums.Direction; namespace Muchinfo.MTPClient.Account.ViewModels { public class AccountManagerViewModel : ViewModelBase { #region 字段 private const int c_Interval = 5000; //定时器取数据时间 private IOrderService _orderService; private ILoginService _loginService; private bool _isBusyFlag = false; //是否在取会员账号信息 private int _showDialogCount = 0; //连续超过多少次超时才弹出超时对话框计数器 private const int c_showdialog = 10; //计数常量 private IGoodsService _goodsService; private ISystemService _systemService; private static object _lockObj=new object(); private int interval; //定时器触发间隔 private Timer _memberTimer; //会员账号信息定时器 #endregion private bool _isMemberTrade ; /// /// 是否是要监控会员 交易员 /// public bool IsMemberTrade { get { return _isMemberTrade; } } #region 构造函数 /// /// /// public AccountManagerViewModel() { _systemService = SimpleIoc.Default.GetInstance(); _goodsService = SimpleIoc.Default.GetInstance(); _orderService = SimpleIoc.Default.GetInstance(); _loginService = SimpleIoc.Default.GetInstance(); interval = ApplicationParameter.MemberMonitorTick <= 0 ? c_Interval : ApplicationParameter.MemberMonitorTick * 1000; ////注册消息 InitRegisterMsg(); InitUpdateTradeInfo(); } /// /// 初始化注册消息 /// private void InitRegisterMsg() { MessengerHelper.DefaultRegister(this, MessengerTokens.MemberRolesToken, (val) => { _isMemberTrade = val; lock (_lockObj) { if (val) { SimpleIoc.Default.GetInstance().QueryMarketTypeStatus(MarketTypeStatusSuccess, null); } } }); ////交易端的信息是否要更新 MessengerHelper.DefaultRegister(this, MessengerTokens.MemberTraderUpdate, (val) => { if (IsMemberTrade&&_memberTimer!=null) { if (!val) { ////所有市场收市 _memberTimer.Stop(); } else { if (!_memberTimer.Enabled) { _memberTimer.Start(); } } } }); MessengerHelper.DefaultRegister(this, MessengerTokens.UpdateAccountCommand, CalcuatePLWithoutQuote); MessengerHelper.DefaultRegister(this, MessengerTokens.HolderUpdate, (e) => { InitUpdateTradeInfo(); }); // 委托单成交通知 //MessengerHelper.DefaultUnregister(this, MessengerTokens.ShowMOOrdersByCapitalAccount); //MessengerHelper.DefaultRegister(this, MessengerTokens.ShowMOOrdersByCapitalAccount, (e) => //{ // InitUpdateTradeInfo(); //}); ////注册实时行情消息 MessengerHelper.QuoteRegister>(this, MessengerTokens.ReceiveRealTimeQuote, (quoteList) => { if (UserManager.CurrentTradeAccount == null) return; if (quoteList == null || !quoteList.Any()) return; foreach (var item in quoteList) { if (item == null) continue; //更新盈亏 // var goodsPips = UserManager.GetTraderGoodsPips(UserManager.CurrentTradeAccount.TradeCode, item.GoodsCode); UpdateFloatPL(item); } MessengerHelper.DefaultSend(UserManager.CurrentTradeAccount, MessengerTokens.UpdateAccountFloatPL); }); //单据成交时需重新计算盈亏 MessengerHelper.DefaultRegister(this, MessengerTokens.OrderNotify, (e) => { InitUpdateTradeInfo(); }); } void MarketTypeStatusSuccess(List marketList) { if (marketList != null && marketList.Any()) { foreach (var marketTypeProperty in marketList) { if (CacheManager.MarketStatus.ContainsKey(marketTypeProperty.markettypeid)) { CacheManager.MarketStatus[marketTypeProperty.markettypeid] = marketTypeProperty.Inreckon; } } if (_memberTimer == null) { _memberTimer = new Timer(); _memberTimer.Interval = interval; _memberTimer.Elapsed += _memberTimer_Elapsed; } var allMarketType = CacheManager.MarketStatus.Values.Any((status) => status == (int)MarketStatus.MarketOpen); if (allMarketType) { if (!_memberTimer.Enabled) { _memberTimer.Start(); } } } } void _memberTimer_Elapsed(object sender, ElapsedEventArgs e) { if (IsMemberTrade) { if (!_isBusyFlag) { _isBusyFlag = true; ////_orderService.GetMemberAmountPosition(UserManager.CurrentTradeAccount); //if (UserManager.CurrentTradeAccount != null && UserManager.CurrentTradeAccount.FundsAccounts.Any()) //{ // _orderService.QueryMemberMonitor(UserManager.CurrentTradeAccount.FundsAccounts[0].AccountId, QuerySuccess, QueryErrorFunc); //} //else //{ // LogInfoHelper.WriteInfo("请求会员监控信息:会员资金账号不存在 "); //} } } else { _memberTimer.Stop(); } } public void QuerySuccess(List successAction) { _isBusyFlag = false; _memberTimer.Interval = interval; _showDialogCount = 0; //收到回应时重置 if (successAction != null && successAction.Count > 0) { UserManager.CurrentTradeAccount.MemberPositions = successAction[0].MemberPositions; if ((AccountStatus)successAction[0].AccountStatus != AccountStatus.None) ////从风控显示数据 { var funds = UserManager.CurrentTradeAccount.FundsAccounts[0]; successAction[0].Balance = funds.Balance; UserManager.CurrentTradeAccount.MemberAccountInfo = successAction[0]; MessengerHelper.DefaultSend(successAction, MessengerTokens.MemberAccountUpdate); } else { ////从数据库中显示资金信息 if (UserManager.CurrentTradeAccount.FundsAccounts != null && UserManager.CurrentTradeAccount.FundsAccounts.Any()) { var funds = UserManager.CurrentTradeAccount.FundsAccounts[0]; var memberInfo = new MemberAccountInfo(); memberInfo.UsedMargin = funds.UsedMargin ; memberInfo.FloatPL = funds.FloatPL ; memberInfo.NetWorth = funds.CurrentNetWorth ; memberInfo.AvailMargin = funds.AvailMargin; memberInfo.MemberPositions = successAction[0].MemberPositions; memberInfo.Balance = funds.Balance ; memberInfo.Rate = funds.RiskRatio; memberInfo.AccountStatus = UserManager.CurrentTradeAccount.AccountStatus;//账户状态 UserManager.CurrentTradeAccount.MemberAccountInfo = memberInfo; memberInfo.MemberPositions = successAction[0].MemberPositions; MessengerHelper.DefaultSend(new List() { memberInfo }, MessengerTokens.MemberAccountUpdate); } } } } private void QueryErrorFunc(ErrorEntity error) { _isBusyFlag = false; _memberTimer.Interval = interval; LogInfoHelper.WriteInfo(string.Format("请求会员风控信息错误({0}){1}", error.ReturnCode, error.ReturnDesc)); //Application.Current.Dispatcher.BeginInvoke(new Action(() => //{ // ErrorManager.ShowReturnError(error, Client_Resource.UI2014_Tips, true); //})); } /// /// 初始化交易数据 /// private void InitUpdateTradeInfo() { var queryCommonParams = new List(); var accountid = UserManager.CurrentTradeAccount.LoginID; //if (UserManager.CurrentTradeAccount.FundsAccounts!=null && UserManager.CurrentTradeAccount.FundsAccounts.Any()) //{ // accountid = UserManager.CurrentTradeAccount.FundsAccounts[0].AccountId; //} queryCommonParams.Add(new QueryCommonParam() { ParamKey = "accountId", ParamValue = accountid + string.Empty }); //初始化持仓单 _loginService.LoginQuerySearch(Convert.ToUInt64(UserManager.CurrentTradeAccount.LoginID), LoginQueryType.TAAccountList, QueryHoldOrderCallBack, null); //_orderService.QueryHoldingDetails(QueryStatement.SearchMarketHoldOrder, queryCommonParams, QueryHoldOrderCallBack, null); } /// /// 查询持仓成功回调 /// /// 持仓内容 private void QueryHoldOrderCallBack(AccountBaseInfoModel holdOrders) { ////获取当前的持仓 CalcuatePLWithoutQuote(""); //MessengerHelper.DefaultSend(UserManager.CurrentTradeAccount, MessengerTokens.HolderRefresh); MessengerHelper.DefaultSend(UserManager.CurrentTradeAccount, MessengerTokens.UpdateAccountFloatPL); } #endregion #region 方法 /// /// 没有行情时计算浮盈 /// private void CalcuatePLWithoutQuote(string msg) { var quoteGoodses = CacheManager.CacheGoodsBaseInfos.Where((item)=>item.GoodsId!=0); //_goodsService.GetGoodsInfoListByExchangeId(UserManager.CurrentTradeAccount.ExchangeId); if (quoteGoodses != null && quoteGoodses.Any()) { var dicGoods = quoteGoodses.ToDictionary((good) => good.GoodsId); UpdateFloatPL(dicGoods); } } /// s /// 更新当前持仓商品的平仓价,浮动盈亏 /// /// 行情商品 private void UpdateFloatPL(Dictionary quoteGoodsDic) { // holdingReports = new ObservableCollection(); if (UserManager.CurrentTradeAccount == null) { return; } var holdingReports = UserManager.CacheOpenOrders(UserManager.CurrentTradeAccount); if (holdingReports == null) return; foreach (var openOrder in holdingReports) { if (openOrder.MarketType == eTradeMode.TRADEMODE_SALE) ////发售的市值 { openOrder.CurrentAmount = openOrder.HoldAmount; } if (!quoteGoodsDic.ContainsKey(openOrder.GoodsId) ) { continue; } var orderGoods = quoteGoodsDic[openOrder.GoodsId]; SetHorderClosePrice(openOrder,orderGoods); ////竞价盈亏 //openOrder.ClosePrice = openOrder.QuoteGoods.GoodsParameters.TradeMode == TradeModeType.BidGoods // ? orderGoods.CurrentPrice // : openOrder.ClosePrice; openOrder.PLFloat = FloatPLExpressions.OrderDetailFloatPL(openOrder, orderGoods); openOrder.CurrentAmount = FloatPLExpressions.CalcHoldAmount(openOrder, orderGoods); //(openOrder.ClosePrice - openOrder.HoldingPrice) * openOrder.Lot * orderFlag //* openOrder.QuoteGoods.GoodsParameters.AgreeUnit; if (ApplicationParameter.IsShowSumPL == 1) { openOrder.SumFloatPL = FloatPLExpressions.CalcOrderDetailSumPL(openOrder); } } if (UserManager.CurrentTradeAccount != null && UserManager.CurrentTradeAccount.FundsAccounts != null && UserManager.CurrentTradeAccount.FundsAccounts.Any()) { decimal payPL, marginPL; FloatPLExpressions.CalcFullPayPLWithSumPL(holdingReports, out payPL, out marginPL); UserManager.CurrentTradeAccount.FundsAccounts[0].FloatPL = Math.Round(marginPL, 2); UserManager.CurrentTradeAccount.FundsAccounts[0].PayNetWorth = holdingReports.Sum((item) => item.CurrentAmount); } } /// s /// 更新当前持仓商品的平仓价,浮动盈亏 /// /// 行情商品 private void UpdateFloatPL(QuoteGoods quoteGoods) { LogInfoHelper.WriteInfo("更新当前持仓商品的平仓价,浮动盈亏" + quoteGoods.GoodsClassName + quoteGoods.GoodsCode + DateTime.Now.ToString()); if (UserManager.CurrentTradeAccount == null) { return; } var holdingReports = UserManager.CacheOpenOrders(UserManager.CurrentTradeAccount); ; if (holdingReports != null) { var openOrders = holdingReports.Where((order) => order.GoodsId == quoteGoods.GoodsId); foreach (var openOrder in openOrders) { SetHorderClosePrice(openOrder, quoteGoods); ////竞价盈亏 //openOrder.ClosePrice = openOrder.QuoteGoods.GoodsParameters.TradeMode == TradeModeType.BidGoods // ? quoteGoods.CurrentPrice // : openOrder.ClosePrice; // } //todo:可计算浮动盈亏 openOrder.PLFloat = FloatPLExpressions.OrderDetailFloatPL(openOrder, quoteGoods); openOrder.CurrentAmount = FloatPLExpressions.CalcHoldAmount(openOrder, quoteGoods); if (ApplicationParameter.IsShowSumPL==1) { openOrder.SumFloatPL = FloatPLExpressions.CalcOrderDetailSumPL(openOrder); } //(openOrder.ClosePrice - openOrder.HoldingPrice) * openOrder.Lot * orderFlag //* openOrder.QuoteGoods.GoodsParameters.AgreeUnit; } if (UserManager.CurrentTradeAccount != null && UserManager.CurrentTradeAccount.FundsAccounts != null && UserManager.CurrentTradeAccount.FundsAccounts.Any()) { decimal payPL, marginPL; FloatPLExpressions.CalcFullPayPLWithSumPL(holdingReports, out payPL, out marginPL); UserManager.CurrentTradeAccount.FundsAccounts[0].FloatPL = Math.Round(marginPL, 2); UserManager.CurrentTradeAccount.FundsAccounts[0].FloatPL = Math.Round(marginPL, 2); UserManager.CurrentTradeAccount.FundsAccounts[0].PayNetWorth = holdingReports.Sum((item) => item.CurrentAmount); } } } /// /// 设置持仓的最新价() /// /// 持仓单 /// 持仓商品 private void SetHorderClosePrice(HoldingOrder holdingOrder, QuoteGoods orderGoods) { if (orderGoods != null ) { switch (orderGoods.TradeMode) { case eTradeMode.TRADEMODE_MARKETMAKE: if (holdingOrder.Direction == Direction.Ask) { holdingOrder.ClosePrice = orderGoods.BidPrice; holdingOrder.ContrayClosePrice = orderGoods.AskPrice; } else { holdingOrder.ClosePrice = orderGoods.AskPrice; holdingOrder.ContrayClosePrice = orderGoods.BidPrice; } break; case eTradeMode.TRADEMODE_BIDDING: ///竞价盈亏 holdingOrder.ClosePrice = orderGoods.CurrentPrice == 0 ? orderGoods.LastClose : orderGoods.CurrentPrice; break; case eTradeMode.TRADEMODE_SALE: holdingOrder.ClosePrice = holdingOrder.HoldingPrice; ////发售用持仓价来算市值 break; case eTradeMode.TRADEMODE_BIDDINGMARKETMAKE: ///竞价盈亏 holdingOrder.ClosePrice = orderGoods.CurrentPrice == 0 ? orderGoods.LastClose : orderGoods.CurrentPrice; break; default: break; } } else { ///竞价盈亏 holdingOrder.ClosePrice = orderGoods.CurrentPrice == 0 ? orderGoods.LastClose : orderGoods.CurrentPrice; } } #endregion /// /// Cleanups this instance. /// public override void Cleanup() { ////取消注册消息 base.Cleanup(); MessengerHelper.QuoteUnregister(this); } } }