/// <summary> /// 更新用户仓位信息包含股票和期货 /// 该函数按照WorkThread的周期执行 /// </summary> /// <param name="info">输入用户信息</param> /// <returns>用户仓位信息</returns> public static AccountInfo UpdateAccountList(UserInfo info) { string alias = info.alias.Trim(); //获取全部持仓,该值会拆分成CC_Stock_records 和 CC_Future_records List <CC_TAOLI_TABLE> CC_records = new List <CC_TAOLI_TABLE>(); if (CCDictionary.Keys.Contains(alias)) { CC_records = CCDictionary[alias]; } //获取股票持仓 List <CC_TAOLI_TABLE> CC_Stock_records = (from item in CC_records where item.CC_TYPE == "49" && item.CC_USER == alias select item).ToList(); //获取期货持仓 List <CC_TAOLI_TABLE> CC_Future_records = (from item in CC_records where item.CC_TYPE == "1" && item.CC_USER == alias select item).ToList(); //获取风控预冻结资金 List <RiskFrozenInfo> Risk_Frozen_records = new List <RiskFrozenInfo>(); if (RiskFrozenDictionary.Keys.Contains(alias)) { Risk_Frozen_records = RiskFrozenDictionary[alias]; } //获取股票委托冻结资金 double Entrust_frozen = 0; List <ERecord> Erecords = new List <ERecord>(); //获取委托持仓 EntrustRecord.GetUserAccountInfo(alias, out Entrust_frozen, out Erecords); //内存股票账户,记录其中的可用资金,股票成本,冻结资金不随行情改变,直接使用 StockAccountTable stockAccount = StockAccountDictionary[alias]; //股票可用资金 //1. 经过风控股票买入时改变,从减少可用资金,增加风控冻结资金; //2. 经过持仓股票卖出时改变,减少股票成本,增加股票可用资金 // 股票可用资金,不会因行情改变而改变 double stock_balance = Convert.ToDouble(stockAccount.Balance.Trim()); //股票成本 double stock_cost = Convert.ToDouble(stockAccount.StockValue.Trim()); //冻结资金 (委托冻结资金 + 风控冻结资金) double stock_frozen_value = 0; foreach (ERecord record in Erecords) { stock_frozen_value += record.Amount * record.OrderPrice; } foreach (RiskFrozenInfo record in Risk_Frozen_records) { if (record.Type == "S" || record.Type == "s") { stock_frozen_value += Convert.ToDouble(record.FrozenCost); } } //计算股票市值 double market_value = 0; //股票盈亏 double stock_earning = 0; foreach (CC_TAOLI_TABLE item in CC_Stock_records) { double price = 0; if (MarketPrice.market.Keys.Contains(item.CC_CODE.Trim())) { price = MarketPrice.market[item.CC_CODE.Trim()] / 10000; } else { price = Convert.ToDouble(item.CC_BUY_PRICE); } if (price != 0) { //存在最新市值,采用最新市值计算 market_value += (Convert.ToInt32(item.CC_AMOUNT) * price); //知道最新市值才能求盈亏 stock_earning += (price - Convert.ToDouble(item.CC_BUY_PRICE)) * Convert.ToInt32(item.CC_AMOUNT); } else { //未找到最新市值,用成交价计算 market_value += (Convert.ToInt32(item.CC_AMOUNT) * Convert.ToDouble(item.CC_BUY_PRICE)); } } //股票权益 (可用资金 + 股票市值 + 冻结资金量) double stock_total = stock_balance + market_value + stock_frozen_value; //内存期货账户,记录其中的平仓盈亏,静态权益,保证金,期货冻结资金不随行情改变,直接使用 FutureAccountTable futureAccount = FutureAccountDictionary[alias]; //静态权益 double static_intrests = Convert.ToDouble(futureAccount.StatisInterests.Trim()); //平仓盈亏 double offset_gain = Convert.ToDouble(futureAccount.OffsetGain.Trim()); //保证金 double cash_deposit = Convert.ToDouble(futureAccount.CashDeposit.Trim()); //期货冻结保证金 double frozen_cash_deposit = 0; foreach (RiskFrozenInfo record in Risk_Frozen_records) { if (record.Type == "F" || record.Type == "F") { frozen_cash_deposit += Convert.ToDouble(record.FrozenCost) * AccountPARA.Factor(record.Code) * AccountPARA.MarginValue; } } //期货对应股票市值 double future_stock_marketvalue = 0; //持仓盈亏 double opsition_gain = 0; foreach (CC_TAOLI_TABLE item in CC_Future_records) { double fprice = 0; if (MarketPrice.market.Keys.Contains(item.CC_CODE.Trim())) { fprice = MarketPrice.market[item.CC_CODE.Trim()] / 10000; } else { fprice = Convert.ToDouble(item.CC_BUY_PRICE); } if (item.CC_DIRECTION == TradeOrientationAndFlag.FutureTradeDirectionBuy) { if (fprice != 0) { //期货买入仓位 //没有实时行情信息,无需再运行持仓盈亏 opsition_gain += (fprice - Convert.ToDouble(item.CC_BUY_PRICE)) * Convert.ToInt32(item.CC_AMOUNT) * AccountPARA.Factor(item.CC_CODE); //存在实时行情,用期货行情计算期货对应股票市值 future_stock_marketvalue += (AccountPARA.Factor(item.CC_CODE) * Convert.ToInt32(item.CC_AMOUNT) * fprice); } else { //不存在实时行情,用成交价格计算期货对应股票市值 future_stock_marketvalue += (AccountPARA.Factor(item.CC_CODE) * Convert.ToInt32(item.CC_AMOUNT) * Convert.ToDouble(item.CC_BUY_PRICE)); } } else if (item.CC_DIRECTION == TradeOrientationAndFlag.FutureTradeDirectionSell) { if (fprice != 0) { //期货买入仓位 //没有实时行情信息,无需再运行持仓盈亏 opsition_gain += (Convert.ToDouble(item.CC_BUY_PRICE) - fprice) * Convert.ToInt32(item.CC_AMOUNT) * AccountPARA.Factor(item.CC_CODE); //存在实时行情,用期货行情计算期货对应股票市值 future_stock_marketvalue -= (AccountPARA.Factor(item.CC_CODE) * Convert.ToInt32(item.CC_AMOUNT) * fprice); } else { //不存在实时行情,用成交价格计算期货对应股票市值 future_stock_marketvalue -= (AccountPARA.Factor(item.CC_CODE) * Convert.ToInt32(item.CC_AMOUNT) * Convert.ToDouble(item.CC_BUY_PRICE)); } } } //动态权益 (静态权益 + 平仓盈亏 + 持仓盈亏) double dynamic_interests = static_intrests + offset_gain + opsition_gain; //可用资金 (动态权益 - 保证金) double expendableFund = dynamic_interests - cash_deposit; //期货风险度 (占用保证金 / 动态权益) double future_risk = cash_deposit / dynamic_interests; //更新股票资金Dictionary lock (StockAccountDictionary) { StockAccountDictionary[alias].Balance = stock_balance.ToString(); StockAccountDictionary[alias].Earning = stock_earning.ToString(); StockAccountDictionary[alias].MarketValue = market_value.ToString(); StockAccountDictionary[alias].StockFrozenValue = stock_frozen_value.ToString(); StockAccountDictionary[alias].StockValue = stock_cost.ToString(); StockAccountDictionary[alias].Total = stock_total.ToString(); StockAccountDictionary[alias].UpdateTime = DateTime.Now; } //更新期货资金Dictionary lock (FutureAccountDictionary) { FutureAccountDictionary[alias].CashDeposit = cash_deposit.ToString(); FutureAccountDictionary[alias].DynamicInterests = dynamic_interests.ToString(); FutureAccountDictionary[alias].ExpendableFund = expendableFund.ToString(); FutureAccountDictionary[alias].FrozenValue = frozen_cash_deposit.ToString(); FutureAccountDictionary[alias].OffsetGain = offset_gain.ToString(); FutureAccountDictionary[alias].OpsitionGain = opsition_gain.ToString(); FutureAccountDictionary[alias].StatisInterests = static_intrests.ToString(); FutureAccountDictionary[alias].UpdateTime = DateTime.Now; } //返回账户信息 AccountInfo accinfo = new AccountInfo(); accinfo.positions = new List <AccountPosition>(); accinfo.entrusts = new List <AccountEntrust>(); accinfo.riskFrozenInfo = new List <RiskFrozenInfo>(); accinfo.account = stock_balance.ToString(); accinfo.alias = alias; accinfo.balance = stock_balance.ToString(); accinfo.cost = stock_cost.ToString(); accinfo.earning = stock_earning.ToString(); foreach (ERecord item in Erecords) { accinfo.entrusts.Add(new AccountEntrust() { code = item.Code, dealAmount = item.DealAmount.ToString(), dealMoney = item.DealFrezonMoney.ToString(), exchange = item.ExchangeId, requestAmount = item.Amount.ToString(), requestPrice = item.OrderPrice.ToString(), direction = item.Direction.ToString(), orderRef = item.OrderRef.ToString(), orderSysRef = item.SysOrderRef.ToString() }); } accinfo.faccount = expendableFund.ToString(); accinfo.fbond = cash_deposit.ToString(); accinfo.fincome = (opsition_gain + offset_gain).ToString(); accinfo.frisk = (future_risk * 100).ToString() + "%"; accinfo.frozen = frozen_cash_deposit.ToString(); accinfo.fstockvalue = future_stock_marketvalue.ToString(); accinfo.fvalue = dynamic_interests.ToString(); accinfo.name = info.name; foreach (CC_TAOLI_TABLE item in CC_Stock_records) { accinfo.positions.Add(new AccountPosition() { amount = item.CC_AMOUNT.ToString(), code = item.CC_CODE, direction = item.CC_DIRECTION, name = item.CC_USER, price = item.CC_BUY_PRICE.ToString(), type = item.CC_TYPE }); } foreach (CC_TAOLI_TABLE item in CC_Future_records) { accinfo.positions.Add(new AccountPosition() { amount = item.CC_AMOUNT.ToString(), code = item.CC_CODE, direction = item.CC_DIRECTION, name = item.CC_USER, price = item.CC_BUY_PRICE.ToString(), type = item.CC_TYPE }); } accinfo.risk_exposure = "0"; accinfo.riskFrozenInfo = new List <RiskFrozenInfo>(); foreach (RiskFrozenInfo record in Risk_Frozen_records) { accinfo.riskFrozenInfo.Add(record); } accinfo.value = market_value.ToString(); return(accinfo); }
private static void WorkThread() { while (true) { Thread.Sleep(1000); if (DateTime.Now.Second % 2 == 0) { //计划每5s刷新资金账户情况 List <UserInfo> users = DBAccessLayer.GetUser(); if (users == null) { return; } foreach (UserInfo info in users) { List <RISK_TABLE> risks = DBAccessLayer.GetRiskRecord(info.alias); int count = 0; if (risks.Count > 0) { List <TMRiskInfo> riskinfos = new List <TMRiskInfo>(); foreach (RISK_TABLE risk in risks) { count++; if (count > 10) { break; } riskinfos.Add(new TMRiskInfo() { code = risk.code, hand = risk.amount.ToString(), price = risk.price.ToString(), orientation = risk.orientation, time = risk.time.ToString(), strategy = "00", user = risk.alias, errinfo = risk.err }); } TradeMonitor.Instance.updateRiskList(info.alias, JsonConvert.SerializeObject(riskinfos), JsonConvert.SerializeObject(riskmonitor.riskPara)); } if (info.userRight == 3) { List <AccountInfo> accounts = new List <AccountInfo>(); foreach (KeyValuePair <string, AccountInfo> pair in AccountInfoDictionary) { accounts.Add(pair.Value); } TradeMonitor.Instance.updateAuditInfo(accounts); //审计员没有风控和持仓信息 continue; } AccountInfo acc = UpdateAccountList(info); if (AccountInfoDictionary.Keys.Contains(info.alias)) { lock (AccountInfoDictionary) { AccountInfoDictionary[info.alias] = acc; } } else { AccountInfoDictionary.Add(info.alias, acc); } if (info.userRight == 2) { //交易员显示个人账户信息 AccountCalculate.Instance.updateAccountInfo(info.alias, JsonConvert.SerializeObject(acc), false); //更新用户交易列表视图 List <DL_TAOLI_TABLE> Deal_records = DBAccessLayer.GetUserDeals(info.alias); if (Deal_records == null) { Deal_records = new List <DL_TAOLI_TABLE>(); } TradeMonitor.Instance.updateTradeList(info.alias, JsonConvert.SerializeObject(Deal_records)); //更新持仓列表视图 TradeMonitor.Instance.updateOrderList(info.alias, null); TradeMonitor.Instance.updateCCList(info.alias, acc.positions); } else if (info.userRight == 1) { //管理员显示所有用户账户信息 AccountCalculate.Instance.updateAccountInfo(info.alias, JsonConvert.SerializeObject(AccountInfoDictionary.Values), true); //更新用户交易列表视图 List <DL_TAOLI_TABLE> Deal_records = DBAccessLayer.GetUserDeals(info.alias); if (Deal_records == null) { Deal_records = new List <DL_TAOLI_TABLE>(); } TradeMonitor.Instance.updateTradeList(info.alias, JsonConvert.SerializeObject(Deal_records)); //更新持仓列表视图 TradeMonitor.Instance.updateOrderList(info.alias, null); TradeMonitor.Instance.updateCCList(info.alias, acc.positions); } } } } }
/// <summary> /// 风控检测 /// 仅针对股票买入和期货开仓进行判断 /// 新交易影响持仓参数: /// 股票: /// 可用资金减少 /// 股票成本增加 /// 风控冻结资金量增加 /// 期货: /// 期货冻结资金增加 /// 可用资金减少 /// </summary> /// <param name="alias">用户名</param> /// <param name="orderlist">交易列表</param> /// <param name="result">结果</param> /// <returns>是否通过风控</returns> public static bool RiskDetection(string alias, List <TradeOrderStruct> orderlist, out string result) { result = string.Empty; if (alias == null) { return(false); } //第一步: 计算新交易引入后对于股票,期货持仓参数的预见性影响 alias = alias.Trim(); //风控错误码 int errCode = 0; //默认策略号 String StrategyId = "000"; if (orderlist != null && orderlist.Count > 0) { StrategyId = orderlist[0].belongStrategy; } //获取真实实时账户信息 UserInfo user = DBAccessLayer.GetOneUser(alias); if (user == null) { result = "未查到用户:" + alias; RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = 0, err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } //刷新内存中的资金信息 AccountInfo current_account = accountMonitor.UpdateAccountList(user); StockAccountTable stock_account = accountMonitor.GetStockAccount(alias); if (stock_account == null) { result = "stockAccountDictionary中不存在用户:" + alias; RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = 0, err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } FutureAccountTable future_account = accountMonitor.GetFutureAccount(alias); if (future_account == null) { result = "futureAccountDictionary中不存在用户: " + alias; RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = 0, err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } //计划买入股票交易列表 var Stock_to_buy_var = (from item in orderlist where item.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionBuy && (item.cSecurityType == "S" || item.cSecurityType == "s") select item); List <TradeOrderStruct> Stock_to_buy = new List <TradeOrderStruct>(); if (Stock_to_buy_var.Count() != 0) { Stock_to_buy = Stock_to_buy_var.ToList(); } //计划卖出股票交易列表 var Stock_to_sell_var = (from item in orderlist where item.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionSell && (item.cSecurityType == "S" || item.cSecurityType == "s") select item); List <TradeOrderStruct> Stock_to_sell = new List <TradeOrderStruct>(); if (Stock_to_sell_var.Count() != 0) { Stock_to_sell = Stock_to_sell_var.ToList(); } //计划开仓期货交易列表 var Future_to_open_var = (from item in orderlist where item.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetOpen && (item.cSecurityType == "F" || item.cSecurityType == "f") select item); List <TradeOrderStruct> Future_to_open = new List <TradeOrderStruct>(); if (Future_to_open_var.Count() != 0) { Future_to_open = Future_to_open_var.ToList(); } //计划平仓期货交易列表 var Future_to_close_var = (from item in orderlist where item.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetClose && (item.cSecurityType == "F" || item.cSecurityType == "f") select item); List <TradeOrderStruct> Future_to_close = new List <TradeOrderStruct>(); if (Future_to_close_var.Count() != 0) { Future_to_close = Future_to_close_var.ToList(); } //计算预期购买股票成本 double stock_etimate_add_cost = 0; foreach (TradeOrderStruct order in Stock_to_buy) { stock_etimate_add_cost += order.dOrderPrice * order.nSecurityAmount; } //计算预期期货追加保证金 double future_estimate_add_deposit = 0; //计算预期期货对应股票市值变化值 double future_estimate_market_value = 0; foreach (TradeOrderStruct order in Future_to_open) { future_estimate_add_deposit += (order.nSecurityAmount * order.dOrderPrice * AccountPARA.MarginValue * AccountPARA.Factor(order.cSecurityCode)); if (order.cTradeDirection == TradeOrientationAndFlag.FutureTradeDirectionBuy) { future_estimate_market_value += (order.nSecurityAmount * order.dOrderPrice * AccountPARA.Factor(order.cSecurityCode)); } else if (order.cTradeDirection == TradeOrientationAndFlag.FutureTradeDirectionSell) { future_estimate_market_value -= (order.nSecurityAmount * order.dOrderPrice * AccountPARA.Factor(order.cSecurityCode)); } } //第二步: 计算修改的资金账户参数是否满足风控指标要求 //判断卖出/平仓证券是否小于持仓 #region 黑白名单判断及总股本限制 //获得白名单 List <BWNameTable> BWRecords = DBAccessLayer.GetWBNamwList(); foreach (TradeOrderStruct tos in orderlist) { BWNameTable BW_record = BWRecords.Find(delegate(BWNameTable item) { return(item.Code.Trim() == tos.cSecurityCode.Trim()); }); if (BW_record == null) { errCode = 4; result = accountMonitor.GetErrorCode(errCode, tos.cSecurityCode); RiskInfo info = new RiskInfo() { alias = alias, price = tos.dOrderPrice, amount = Convert.ToInt32(tos.nSecurityAmount), err = result, orientation = tos.cTradeDirection, code = tos.cSecurityCode.Trim(), strid = tos.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } if (tos.cSecurityType.ToUpper() == "S" && tos.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionBuy) { //判断总股本数量和流通股数量限制 double buylimit = Convert.ToDouble(BW_record.PercentageA) * Convert.ToDouble(BW_record.Amount); double buylimit2 = Convert.ToDouble(BW_record.PercentageB) * Convert.ToDouble(BW_record.Value); int entrust_amount = 0; AccountEntrust entrust_record = current_account.entrusts.Find( delegate(AccountEntrust item) { return(item.code == tos.cSecurityCode); } ); if (entrust_record != null) { entrust_amount = Convert.ToInt32(entrust_record.dealAmount); } int position_amount = 0; AccountPosition position_record = current_account.positions.Find( delegate(AccountPosition item) { return(item.code == tos.cSecurityCode); } ); if (position_record != null) { position_amount = Convert.ToInt32(position_record.amount); } //总股本限制 if (tos.nSecurityAmount + entrust_amount + position_amount > buylimit) { errCode = 5; result = accountMonitor.GetErrorCode(errCode, tos.cSecurityCode); RiskInfo info = new RiskInfo() { alias = alias, price = tos.dOrderPrice, amount = Convert.ToInt32(tos.nSecurityAmount), err = result, orientation = tos.cTradeDirection, code = tos.cSecurityCode.Trim(), strid = tos.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } //流通股限制 if (tos.nSecurityAmount + entrust_amount + position_amount > buylimit2) { errCode = 5; result = accountMonitor.GetErrorCode(errCode, tos.cSecurityCode); RiskInfo info = new RiskInfo() { alias = alias, price = tos.dOrderPrice, amount = Convert.ToInt32(tos.nSecurityAmount), err = result, orientation = tos.cTradeDirection, code = tos.cSecurityCode.Trim(), strid = tos.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } } } #endregion #region 判断卖出/平仓证券是否小于持仓 foreach (TradeOrderStruct order in orderlist) { if (order.cSecurityType == "F" || order.cSecurityType == "f") { if (order.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetClose) { int position_amount = 0; //期货平仓交易,需要判断对应开仓数量是否满足 if (order.cTradeDirection == TradeOrientationAndFlag.FutureTradeDirectionBuy) { //买入平仓,需要判断卖出开仓数量 AccountPosition position_record = current_account.positions.Find( delegate(AccountPosition item) { return(item.direction == TradeOrientationAndFlag.FutureTradeDirectionSell && order.cSecurityCode == item.code); } ); if (position_record != null) { position_amount = Convert.ToInt32(position_record.amount); } if (order.nSecurityAmount > position_amount) { //买入平仓数量小于卖出仓位,交易被拒绝。 errCode = 12; result = accountMonitor.GetErrorCode(errCode, order.cSecurityCode + "|" + position_amount + "|" + order.cTradeDirection); RiskInfo info = new RiskInfo() { alias = alias, price = order.dOrderPrice, amount = Convert.ToInt32(order.nSecurityAmount), err = result, orientation = order.cTradeDirection, code = order.cSecurityCode.Trim(), strid = order.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } } else if (order.cTradeDirection == TradeOrientationAndFlag.FutureTradeDirectionSell) { //卖出平仓,需要判断买入开仓的数量 AccountPosition position_record = current_account.positions.Find( delegate(AccountPosition item) { return(item.direction == TradeOrientationAndFlag.FutureTradeDirectionBuy && order.cSecurityCode == item.code); } ); if (position_record != null) { position_amount = Convert.ToInt32(position_record.amount); } if (order.nSecurityAmount > position_amount) { //卖出平仓数量小于买入仓位,交易被拒绝。 errCode = 12; result = accountMonitor.GetErrorCode(errCode, order.cSecurityCode + "|" + position_amount + "|" + order.cTradeDirection); RiskInfo info = new RiskInfo() { alias = alias, price = order.dOrderPrice, amount = Convert.ToInt32(order.nSecurityAmount), err = result, orientation = order.cTradeDirection, code = order.cSecurityCode.Trim(), strid = order.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } } } } else if (order.cSecurityType == "S" || order.cSecurityType == "s") { if (order.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionSell) { //股票卖出交易,需要判断当前持仓数量是否满足 int entrust_amount = 0; AccountEntrust entrust_record = current_account.entrusts.Find( delegate(AccountEntrust item) { return(item.code == order.cSecurityCode && item.direction == TradeOrientationAndFlag.StockTradeDirectionSell); } ); if (entrust_record != null) { entrust_amount = Convert.ToInt32(entrust_record.dealAmount); } int position_amount = 0; AccountPosition position_record = current_account.positions.Find( delegate(AccountPosition item) { return(item.code == order.cSecurityCode); } ); if (position_record != null) { position_amount = Convert.ToInt32(position_record.amount); } //判断当前持仓和委托+下单卖出总和比较 if (order.nSecurityAmount + entrust_amount > position_amount) { errCode = 11; result = accountMonitor.GetErrorCode(errCode, order.cSecurityCode + "|" + (entrust_amount + position_amount).ToString()); RiskInfo info = new RiskInfo() { alias = alias, price = order.dOrderPrice, amount = Convert.ToInt32(order.nSecurityAmount), err = result, orientation = order.cTradeDirection, code = order.cSecurityCode.Trim(), strid = order.belongStrategy }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } } } } #endregion #region 判断买入股票和期货需要资金是否高于当前可用资金 //预期股票剩余资金 double stock_balance = Convert.ToDouble(current_account.account) - stock_etimate_add_cost; if (stock_balance <= 0) { errCode = 1; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } //预期期货可用资金 double future_balance = Convert.ToDouble(current_account.faccount) - future_estimate_add_deposit; if (future_balance <= 0) { errCode = 2; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } #endregion #region 单一股票占总资产不超过5% //总资产 double totalAccount = Convert.ToDouble(current_account.account) + Convert.ToDouble(current_account.fstockvalue) + Convert.ToDouble(current_account.fvalue); foreach (TradeOrderStruct tos in orderlist) { if (tos.cSecurityType.ToUpper() == "S") { if (CheckStockException(tos.cSecurityCode)) { continue; } if (tos.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionBuy) { double entrust_value = 0; AccountEntrust entrust_record = current_account.entrusts.Find( delegate(AccountEntrust item) { return(item.code == tos.cSecurityCode); } ); if (entrust_record != null) { entrust_value = Convert.ToDouble(entrust_record.dealMoney) * Convert.ToDouble(entrust_record.dealAmount); } double position_value = 0; AccountPosition position_record = current_account.positions.Find( delegate(AccountPosition item) { return(item.code == tos.cSecurityCode); } ); if (position_record != null) { position_value = Convert.ToDouble(position_record.price) * Convert.ToDouble(position_record.amount); } if ((tos.nSecurityAmount * tos.dOrderPrice + entrust_value + position_value) / totalAccount > riskPara.PerStockCostPercentage) { errCode = 6; result = accountMonitor.GetErrorCode(errCode, tos.cSecurityCode); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } } } } #endregion #region 股票所占投资总额不超过80% //总市值,totalAccount //当前股票成本 , current_account.cost + 委托中的买入股票成本 double estimate_stock_value = Convert.ToDouble(current_account.value); foreach (AccountEntrust record in current_account.entrusts) { if (record.direction == TradeOrientationAndFlag.StockTradeDirectionBuy) { estimate_stock_value += Convert.ToDouble(record.dealMoney) * Convert.ToDouble(record.dealAmount); } } foreach (RiskFrozenInfo record in current_account.riskFrozenInfo) { if (record.Type.ToUpper() == "S" && record.TradeDirection == TradeOrientationAndFlag.StockTradeDirectionBuy) { estimate_stock_value += Convert.ToDouble(record.FrozenCost); } } estimate_stock_value += stock_etimate_add_cost; if (estimate_stock_value / totalAccount > riskPara.stockRatio) { errCode = 13; result = accountMonitor.GetErrorCode(errCode, (estimate_stock_value / totalAccount * 100).ToString()); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } #endregion #region 单日期货交易次数不超过10手 if (FutureTradeTimes.Keys.Contains(alias)) { if (DateTime.Now.Hour > 16) { //下午四点后,默认计数清零 FutureTradeTimes[alias] = 0; } if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday) { //周末直接清零 FutureTradeTimes[alias] = 0; } } else { FutureTradeTimes.Add(alias, 0); } int future_trade_hand_count = 0; foreach (TradeOrderStruct tos in orderlist) { if (tos.cSecurityType.ToUpper() == "F" && tos.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetOpen) { //只有期货开仓才会计入数量限制,平仓不限 future_trade_hand_count += Convert.ToInt32(tos.nSecurityAmount); } } if (FutureTradeTimes[alias] + future_trade_hand_count > 10) { errCode = 10; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } #endregion #region 期货风险度和敞口比例 //期货风险度 double risk_radio = (Convert.ToDouble(current_account.fbond) + future_estimate_add_deposit) / (Convert.ToDouble(current_account.fvalue)); if (risk_radio >= riskPara.riskLevel) { errCode = 8; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } #endregion #region 监控用户登录判断 if (!userOper.CheckMonitorUser(CONFIG.GlobalMonitor)) { errCode = 14; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); return(false); } #endregion //敞口 foreach (TradeOrderStruct tos in orderlist) { //股票卖出和期货平仓交易不计算敞口 if (tos.cSecurityType.ToUpper() == "S" && tos.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionSell) { continue; } if (tos.cSecurityType.ToUpper() == "F" && tos.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetClose) { continue; } //股票买入和期货开仓需要通过敞口验证 double changkouRatio = 0; if (!((Convert.ToDouble(current_account.value) + stock_etimate_add_cost) == 0)) { changkouRatio = (Convert.ToDouble(current_account.fstockvalue) + future_estimate_market_value + Convert.ToDouble(current_account.value) + stock_etimate_add_cost) / (Convert.ToDouble(current_account.value) + stock_etimate_add_cost); if (Math.Abs(changkouRatio) > riskPara.changkouRatio) { errCode = 9; result = accountMonitor.GetErrorCode(errCode, changkouRatio.ToString()); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); //return false; } } else { errCode = 9; result = accountMonitor.GetErrorCode(errCode, "无穷大"); RiskInfo info = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(info)); //return false; } } //第三部: 实际减少股票资金 foreach (TradeOrderStruct tos in orderlist) { if (tos.cSecurityType.ToUpper() == "S") { if (tos.cTradeDirection == TradeOrientationAndFlag.StockTradeDirectionBuy) { //股票交易买入需要计入风控列表 accountMonitor.UpdateRiskFrozonAccount(user.alias, tos.cSecurityCode, Convert.ToInt32(tos.nSecurityAmount), tos.nSecurityAmount * tos.dOrderPrice, "S", tos.cTradeDirection); } } else if (tos.cSecurityType.ToUpper() == "F") { if (tos.cOffsetFlag == TradeOrientationAndFlag.FutureTradeOffsetOpen) { //期货交易开仓需要计入风控列表 accountMonitor.UpdateRiskFrozonAccount(user.alias, tos.cSecurityCode, Convert.ToInt32(tos.nSecurityAmount), tos.nSecurityAmount * tos.dOrderPrice, "F", tos.cTradeDirection); } } } errCode = 0; result = accountMonitor.GetErrorCode(errCode, string.Empty); RiskInfo infoSuccess = new RiskInfo() { alias = alias, price = 0, amount = Convert.ToInt32(0), err = result, orientation = "0", code = "000", strid = StrategyId }; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.AddRiskRecord), (object)(infoSuccess)); return(true); }