/// <summary>
        /// 处理本年度合约持仓限制
        /// </summary>
        /// <param name="code">合约代码</param>
        /// <param name="year">合约年</param>
        /// <param name="month">合约月</param>
        /// <param name="positionValueType">持仓限制类型</param>
        /// <returns>持仓限制</returns>
        private static PositionLimitValueInfo ProcessCurrentYear(string code, int year, int month, out Types.QHPositionValueType positionValueType)
        {
            DateTime now = DateTime.Now;

            positionValueType = Types.QHPositionValueType.Scales;


            //当前合约处于交割月
            if (month == now.Month)
            {
                return(ProcessDeliveryMonth(code, out positionValueType));
            }

            //当前合约还未到交割月
            if (month > now.Month)
            {
                return(ProcessNonDeliveryMonth(code, year, month, out positionValueType));
            }

            PositionLimitValueInfo info = new PositionLimitValueInfo();

            info.PositionValue    = -1;
            info.IsMinMultiple    = false;
            info.MinMultipleValue = 0;
            //return -1;
            return(info);
        }
        /// <summary>
        /// Desc: 获取超过最小交割量整数倍的记录
        /// Create by: 董鹏
        /// Create Date: 2010-02-03
        /// </summary>
        /// <param name="list">商品期货持仓实体列表</param>
        /// <param name="amtList">超量列表</param>
        /// <returns></returns>
        private List <QH_HoldAccountTableInfo> FindWillClosedContractNotModMinUnitLimit(List <QH_HoldAccountTableInfo> list, out Dictionary <int, decimal> dicAmount)
        {
            dicAmount = new Dictionary <int, decimal>();
            List <QH_HoldAccountTableInfo> listReturn = new List <QH_HoldAccountTableInfo>();

            LogHelper.WriteDebug("---->商品期货最小交割量整数倍限制验证");
            foreach (QH_HoldAccountTableInfo item in list)
            {
                //获取持仓限制
                try
                {
                    PositionLimitValueInfo posInfo = MCService.GetPositionLimit(item.Contract);
                    LogHelper.WriteDebug("-------->获取持仓限制,HistoryHoldAmount=" + item.HistoryHoldAmount + ",TodayHoldAmount=" + item.TodayHoldAmount + ",pLimit=" + posInfo.PositionValue + ",IsNoComputer=" + posInfo.IsNoComputer +
                                         ",IsMinMultiple=" + posInfo.IsMinMultiple + ",MinMultipleValue=" + posInfo.MinMultipleValue);
                    if (posInfo.IsMinMultiple)
                    {
                        if (item.HistoryHoldAmount % posInfo.MinMultipleValue > 0)
                        {
                            LogHelper.WriteDebug("-------->持仓超过最小交割量整数倍限制,UserAccountDistributeLogo=" + item.UserAccountDistributeLogo + ",Contract=" +
                                                 item.Contract + ",HistoryHoldAmount=" + item.HistoryHoldAmount + ",TodayHoldAmount=" + item.TodayHoldAmount + ",MinMultipleValue=" +
                                                 posInfo.MinMultipleValue + "HistoryHoldAmount % pLimit=" + (item.HistoryHoldAmount % posInfo.MinMultipleValue));
                            listReturn.Add(item);
                            dicAmount.Add(item.AccountHoldLogoId, (item.HistoryHoldAmount % posInfo.MinMultipleValue));
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteError(ex.Message, ex);
                }
            }
            return(listReturn);
        }
        /// <summary>
        /// 重写实现验证委托量最小倍数方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strMessage"></param>
        /// <returns></returns>
        public override bool Validate(MercantileFuturesOrderRequest request, ref string strMessage)
        {
            //如果是开仓返回true,直接验证通过,因为开仓的时候已经在内部有处理
            if (request.OpenCloseType == ReckoningCounter.Entity.Contants.Types.FutureOpenCloseType.OpenPosition)
            {
                return(true);
            }

            CM_BreedClass breedClass = MCService.CommonPara.GetBreedClassByBreedClassID(BreedClassID);

            bool result = true;

            if (breedClass != null && breedClass.BreedClassTypeID.HasValue)
            {
                int breedClassTypeID = breedClass.BreedClassTypeID.Value;
                int breedClassID     = breedClass.BreedClassID;
                //如果是股指期货直接返回true
                if (breedClassTypeID == (int)Types.BreedClassTypeEnum.StockIndexFuture)
                {
                    return(true);
                }

                //如果不是商品期货返回验证不通过
                if (breedClassTypeID != (int)Types.BreedClassTypeEnum.CommodityFuture)
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }

            PositionLimitValueInfo posInfo = MCService.GetPositionLimit(request.Code);

            //如果是最小交割单位的整数倍时
            if (posInfo.IsMinMultiple)
            {
                if (((decimal)request.OrderAmount) % posInfo.MinMultipleValue != 0)
                {
                    LogHelper.WriteDebug("===商品期货验证开仓最小交割单位倍数据: (request.OrderAmount % posInfo.MinMultipleValue)=(" + request.OrderAmount + " % " + posInfo.MinMultipleValue + ")=" + (((decimal)request.OrderAmount) % posInfo.MinMultipleValue));
                    strMessage = "GT-1354:[商品期货委托持久化]开仓持仓检查,持仓限制不是最小交割单位倍数";
                    result     = false;
                }
            }

            return(result);
        }
        /// <summary>
        /// 通过持仓限制列表和市场持仓量、持仓控制类型来获取具体的持仓限制
        /// </summary>
        /// <param name="limitValues">持仓限制列表</param>
        /// <param name="openInterest">市场持仓量</param>
        /// <param name="positionValueType">持仓限制类型</param>
        /// <returns>持仓限制</returns>
        private static PositionLimitValueInfo GetLimitByBailType(IList <QH_PositionLimitValue> limitValues, decimal openInterest, out Types.QHPositionValueType positionValueType)
        {
            PositionLimitValueInfo info = new PositionLimitValueInfo();

            switch (limitValues[0].PositionBailTypeID.Value)
            {
            //单边
            case (int)Types.QHPositionBailType.SinglePosition:
            {
                info = GetLimit(limitValues, openInterest / 2, out positionValueType);
                info.QHPositionBailType = Types.QHPositionBailType.SinglePosition;
                return(info);
            }

            //又边
            case (int)Types.QHPositionBailType.TwoPosition:
            {
                info = GetLimit(limitValues, openInterest, out positionValueType);
                info.QHPositionBailType = Types.QHPositionBailType.TwoPosition;
                return(info);
            }

            //按交易日天数据
            case (int)Types.QHPositionBailType.ByTradeDays:
            //按自然日天数据
            case (int)Types.QHPositionBailType.ByDays:
            {
                //如果是按天的话就先把当前系统日期的当前月中所有的交易日获取
                //然后对这些交易日再查询 (然而这里已经在获取管理中心数据缓存时已经转换过来,所以这里不用再转换,
                //因为缓存了的每次获取就不用再计算转换
                info = GetLimit(limitValues, DateTime.Now.Day, out positionValueType);
                info.QHPositionBailType = Types.QHPositionBailType.ByDays;
                return(info);
            }
            }

            positionValueType = Types.QHPositionValueType.Scales;


            info.PositionValue    = -1;
            info.IsMinMultiple    = false;
            info.MinMultipleValue = 0;
            //return -1;
            return(info);
        }
        /// <summary>
        /// Desc: 获取超过最大持仓量的记录
        /// Create by: 董鹏
        /// Create Date: 2010-02-03
        /// </summary>
        /// <param name="list">商品期货持仓实体列表</param>
        /// <param name="amtList">超量列表</param>
        /// <returns></returns>
        private List <QH_HoldAccountTableInfo> FindWillClosedContractOverMaxHoldLimit(List <QH_HoldAccountTableInfo> list, out Dictionary <int, decimal> dicAmount)
        {
            dicAmount = new Dictionary <int, decimal>();
            List <QH_HoldAccountTableInfo> listReturn = new List <QH_HoldAccountTableInfo>();

            LogHelper.WriteDebug("---->商品期货持仓限制验证");
            foreach (QH_HoldAccountTableInfo item in list)
            {
                //获取持仓限制
                try
                {
                    PositionLimitValueInfo posInfo = MCService.GetPositionLimit(item.Contract);
                    LogHelper.WriteDebug("-------->获取持仓限制,HistoryHoldAmount=" + item.HistoryHoldAmount + ",TodayHoldAmount=" + item.TodayHoldAmount + ",pLimit=" + posInfo.PositionValue + ",IsNoComputer=" + posInfo.IsNoComputer +
                                         ",IsMinMultiple=" + posInfo.IsMinMultiple + ",MinMultipleValue=" + posInfo.MinMultipleValue);
                    Decimal pLimit = posInfo.PositionValue;
                    if (pLimit < 0)
                    {
                        LogHelper.WriteDebug("-------->商品期货持仓限制验证,持仓限制小于0,不处理,pLimit=" + pLimit);
                        continue;
                    }
                    //持仓大于持仓限制
                    if (item.HistoryHoldAmount > pLimit)
                    {
                        LogHelper.WriteDebug("-------->持仓大于持仓限制,UserAccountDistributeLogo=" + item.UserAccountDistributeLogo + ",Contract=" +
                                             item.Contract + ",HistoryHoldAmount=" + item.HistoryHoldAmount + ",TodayHoldAmount=" + item.TodayHoldAmount + ",pLimit=" + pLimit + ",HistoryHoldAmount - pLimit=" + (item.HistoryHoldAmount - pLimit));
                        listReturn.Add(item);
                        dicAmount.Add(item.AccountHoldLogoId, item.HistoryHoldAmount - pLimit);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteError(ex.Message, ex);
                }
            }

            return(listReturn);
        }
        /// <summary>
        /// 通过持仓和保证金控制类型来获取具体的持仓限制
        /// </summary>
        /// <param name="values">持仓限制列表</param>
        /// <param name="findVal">类型值(持仓或者日期)</param>
        /// <param name="positionValueType">持仓限制取值类型(百分比还是值)</param>
        /// <returns>持仓限制</returns>
        ///
        private static PositionLimitValueInfo GetLimit(IList <QH_PositionLimitValue> values, decimal findVal, out Types.QHPositionValueType positionValueType)
        {
            QH_PositionLimitValue  limitValue = null;
            PositionLimitValueInfo info       = new PositionLimitValueInfo();

            info.PositionValue    = -1;
            info.IsMinMultiple    = false;
            info.MinMultipleValue = 0;

            foreach (QH_PositionLimitValue value in values)
            {
                if (CheckLimitFieldRange(findVal, value))
                {
                    limitValue = value;
                    break;
                }
            }

            positionValueType = Types.QHPositionValueType.Scales;
            if (limitValue == null)
            {
                //return -1;
                return(info);
            }

            positionValueType = (Types.QHPositionValueType)limitValue.PositionValueTypeID.Value;

            //如果有值即为要对本记录作最小交割单位倍数判断
            if (limitValue.MinUnitLimit.HasValue && limitValue.MinUnitLimit.Value != 0)
            {
                info.IsMinMultiple    = true;
                info.MinMultipleValue = (decimal)limitValue.MinUnitLimit.Value;
            }
            info.PositionValue = limitValue.PositionValue.Value;
            return(info);
        }
        /// <summary>
        /// 处理非交割月份的合约
        /// </summary>
        /// <param name="code">合约代码</param>
        /// <param name="year">合约年</param>
        /// <param name="month">合约月</param>
        /// <param name="positionValueType">持仓限制类型</param>
        /// <returns>保证金比例</returns>
        private static PositionLimitValueInfo ProcessNonDeliveryMonth(string code, int year, int month, out Types.QHPositionValueType positionValueType)
        {
            string errCode = "GT-8492";
            string errMsg  = "无法根据期货商品代码获取其对应的持仓限制。";


            IList <QH_PositionLimitValue> values = GetPositionLimitValues(code);

            if (values == null)
            {
                throw new VTException(errCode, errMsg);
            }

            IRealtimeMarketService service = RealTimeMarketUtil.GetRealMarketService(); //RealtimeMarketServiceFactory.GetService();
            //FutData futData = service.GetFutData(code);
            MerFutData merFutData = service.GetMercantileFutData(code);

            if (merFutData == null)
            {
                errMsg = "处理交割月合约保证金时无法获取行情-持仓限制。";
                throw new VTException(errCode, errMsg);
            }

            //持仓量
            decimal openInterest = (decimal)merFutData.OpenInterest;

            LogHelper.WriteDebug("非交割月份的合约当前获取到" + code + "行情持仓量:" + openInterest);

            //判断当前月份是那种交割月份类型
            Types.QHCFPositionMonthType monthType = FutureService.CheckMonthType(year, month, DateTime.Now);

            IList <QH_PositionLimitValue> limitValues;

            positionValueType = Types.QHPositionValueType.Scales;

            #region 交割月份前三个月
            //如果是前三
            if (monthType == Types.QHCFPositionMonthType.OnDeliAgoThreeMonth)
            {
                limitValues = FindLimitValuesByMonthType(values, monthType);

                //是前三
                if (limitValues.Count > 0)
                {
                    return(GetLimitByBailType(limitValues, openInterest, out positionValueType));
                }
                errMsg = "代码" + code + " 无法获取交割前三个月的对应的持仓限制列表参数正在以一般月份查询。";
                LogHelper.WriteDebug(errCode + errMsg);

                //否则就是一般月份
                limitValues = FindLimitValuesByMonthType(values, Types.QHCFPositionMonthType.GeneralMonth);
                if (limitValues.Count > 0)
                {
                    PositionLimitValueInfo generOnThree = GetLimitByBailType(limitValues, openInterest, out positionValueType);
                    if (generOnThree.PositionValue == -1)
                    {
                        generOnThree.IsNoComputer = true;
                    }
                    return(generOnThree);
                }
                errMsg = "代码" + code + " 无法获取交割月份前三个月的一般月份的对应的持仓限制列表参数。";
                LogHelper.WriteDebug(errCode + errMsg);
            }
            #endregion

            #region 交割月份前二个月
            //如果是前二
            if (monthType == Types.QHCFPositionMonthType.OnDeliAgoTwoMonth)
            {
                limitValues = FindLimitValuesByMonthType(values, monthType);

                //是前二
                if (limitValues.Count > 0)
                {
                    return(GetLimitByBailType(limitValues, openInterest, out positionValueType));
                }
                errMsg = "代码" + code + " 无法获取交割前两个月的对应的持仓限制列表参数。";
                LogHelper.WriteDebug(errCode + errMsg);
                //否则就是一般月份
                limitValues = FindLimitValuesByMonthType(values, Types.QHCFPositionMonthType.GeneralMonth);
                if (limitValues.Count > 0)
                {
                    PositionLimitValueInfo generOnDeliAgo = GetLimitByBailType(limitValues, openInterest, out positionValueType);
                    if (generOnDeliAgo.PositionValue == -1)
                    {
                        generOnDeliAgo.IsNoComputer = true;
                    }
                    return(generOnDeliAgo);
                }
                errMsg = "代码" + code + " 无法获取交割月份前两个月的一般月份的对应的持仓限制列表参数。";
                LogHelper.WriteDebug(errCode + errMsg);
            }
            #endregion

            #region 交割月份前一个月
            //如果是前一
            if (monthType == Types.QHCFPositionMonthType.OnDeliAgoMonth)
            {
                limitValues = FindLimitValuesByMonthType(values, monthType);

                //是前一
                if (limitValues.Count > 0)
                {
                    return(GetLimitByBailType(limitValues, openInterest, out positionValueType));
                }
                errMsg = "代码" + code + " 无法获取交割前一个月的对应的持仓限制列表参数正在以一般月份查询。";
                LogHelper.WriteDebug(errCode + errMsg);



                //否则就是一般月份
                limitValues = FindLimitValuesByMonthType(values, Types.QHCFPositionMonthType.GeneralMonth);
                if (limitValues.Count > 0)
                {
                    PositionLimitValueInfo generOnDeli = GetLimitByBailType(limitValues, openInterest, out positionValueType);
                    if (generOnDeli.PositionValue == -1)
                    {
                        generOnDeli.IsNoComputer = true;
                    }
                    return(generOnDeli);
                }
                errMsg = "代码" + code + " 无法获取交割月份前一个月的一般月份的对应的持仓限制列表参数。";
                LogHelper.WriteDebug(errCode + errMsg);
            }
            #endregion

            #region 交割月份一般月份
            //如果是一般月份
            if (monthType == Types.QHCFPositionMonthType.GeneralMonth)
            {
                limitValues = FindLimitValuesByMonthType(values, monthType);

                //是一般月份
                if (limitValues.Count > 0)
                {
                    PositionLimitValueInfo gener = GetLimitByBailType(limitValues, openInterest, out positionValueType);
                    if (gener.PositionValue == -1)
                    {
                        gener.IsNoComputer = true;
                    }
                    return(gener);
                }
                errMsg = "代码" + code + " 无法获取一般月份的对应的持仓限制列表参数。";
                LogHelper.WriteDebug(errCode + errMsg);
            }
            #endregion

            PositionLimitValueInfo info = new PositionLimitValueInfo();
            info.PositionValue    = -1;
            info.IsMinMultiple    = false;
            info.MinMultipleValue = 0;
            //return -1;
            return(info);
        }
        /// <summary>
        /// 获取合约持仓限制
        /// </summary>
        /// <param name="code">合约代码</param>
        /// <param name="positionValueType">持仓限制类型</param>
        /// <returns>持仓限制</returns>
        public static PositionLimitValueInfo GetFuturePostionLimit(string code, out Types.QHPositionValueType positionValueType)
        {
            string errCode = "GT-8491";
            string errMsg  = "期货商品代码不存在。";

            CM_Commodity commodity = MCService.CommonPara.GetCommodityByCommodityCode(code);

            if (commodity == null)
            {
                throw new VTException(errCode, errMsg);
            }

            errCode = "GT-8492";
            errMsg  = "无法根据期货商品代码获取其对应的持仓限制。";

            int year;
            int month;

            try
            {
                FutureService.GetAgreementTime(code, out year, out month);
            }
            catch (Exception ex)
            {
                throw new VTException(errCode, errMsg, ex);
            }


            DateTime now = DateTime.Now;

            errCode           = "GT-8493";
            errMsg            = code + "合约已经过期。";
            positionValueType = Types.QHPositionValueType.Scales;

            //合约已过期
            if (year < now.Year)
            {
                throw new VTException(errCode, errMsg);
            }

            //本年度合约
            if (year == now.Year)
            {
                //合约已过期
                if (month < now.Month)
                {
                    throw new VTException(errCode, errMsg);
                }

                return(ProcessCurrentYear(code, year, month, out positionValueType));
            }

            //下年度合约
            if (year > now.Year)
            {
                return(ProcessNextYear(code, year, month, out positionValueType));
            }
            PositionLimitValueInfo info = new PositionLimitValueInfo();

            info.PositionValue    = -1;
            info.IsMinMultiple    = false;
            info.MinMultipleValue = 0;
            //return -1;
            return(info);
        }